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");
@@ -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);
@@ -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>

View File

@@ -2,6 +2,9 @@
#include "helpers/Splashes.hpp"
#include <random>
#include "debug/HyprCtl.hpp"
#ifdef USES_SYSTEMD
#include <systemd/sd-daemon.h> // for sd_notify
#endif
int handleCritSignal(int signo, void* data) {
Debug::log(LOG, "Hyprland received signal %d", signo);
@@ -22,8 +25,15 @@ CCompositor::CCompositor() {
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
if (!std::filesystem::exists("/tmp/hypr")) {
std::filesystem::create_directory("/tmp/hypr");
std::filesystem::permissions("/tmp/hypr", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
std::filesystem::create_directory(INSTANCEPATH);
std::filesystem::permissions(INSTANCEPATH, std::filesystem::perms::group_all, std::filesystem::perm_options::replace);
std::filesystem::permissions(INSTANCEPATH, std::filesystem::perms::owner_all, std::filesystem::perm_options::add);
Debug::init(m_szInstanceSignature);
@@ -39,7 +49,7 @@ CCompositor::CCompositor() {
Debug::log(NONE, "\n\n"); // pad
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://github.com/hyprwm/Hyprland/wiki/Crashing-and-bugs\n\n");
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://wiki.hyprland.org/Crashes-and-Bugs/\n\n");
setRandomSplash();
@@ -53,7 +63,7 @@ CCompositor::CCompositor() {
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession);
if (!m_sWLRBackend) {
Debug::log(CRIT, "m_sWLRBackend was NULL!");
@@ -76,11 +86,10 @@ CCompositor::CCompositor() {
wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay);
if (wlr_renderer_get_dmabuf_texture_formats(m_sWLRRenderer)) {
if (wlr_renderer_get_drm_fd(m_sWLRRenderer) >= 0) {
if (wlr_renderer_get_drm_fd(m_sWLRRenderer) >= 0)
wlr_drm_create(m_sWLDisplay, m_sWLRRenderer);
}
m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create(m_sWLDisplay, m_sWLRRenderer);
m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create_with_renderer(m_sWLDisplay, 4, m_sWLRRenderer);
}
m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer);
@@ -132,7 +141,7 @@ CCompositor::CCompositor() {
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay);
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
m_sWLRServerDecoMgr = wlr_server_decoration_manager_create(m_sWLDisplay);
m_sWLRXDGDecoMgr = wlr_xdg_decoration_manager_v1_create(m_sWLDisplay);
@@ -173,8 +182,6 @@ CCompositor::CCompositor() {
m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay);
m_sWLRSession = wlr_backend_get_session(m_sWLRBackend);
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
@@ -247,7 +254,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
if(m_sWRLDRMLeaseMgr)
if (m_sWRLDRMLeaseMgr)
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
if (m_sWLRSession)
@@ -329,6 +336,9 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "Creating the XWaylandManager!");
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
Debug::log(LOG, "Creating the ProtocolManager!");
g_pProtocolManager = std::make_unique<CProtocolManager>();
Debug::log(LOG, "Creating the EventManager!");
g_pEventManager = std::make_unique<CEventManager>();
g_pEventManager->startThread();
@@ -345,22 +355,28 @@ void CCompositor::startCompositor() {
initAllSignals();
m_szWLDisplaySocket = wl_display_add_socket_auto(m_sWLDisplay);
// get socket, avoid using 0
for (int candidate = 1; candidate <= 32; candidate++) {
if (wl_display_add_socket(m_sWLDisplay, ("wayland-" + std::to_string(candidate)).c_str()) >= 0) {
m_szWLDisplaySocket = "wayland-" + std::to_string(candidate);
break;
}
}
if (!m_szWLDisplaySocket) {
if (m_szWLDisplaySocket.empty()) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
wlr_backend_destroy(m_sWLRBackend);
throw std::runtime_error("m_szWLDisplaySocket was null! (wl_display_add_socket_auto failed)");
}
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1);
signal(SIGPIPE, SIG_IGN);
if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */ && fork() == 0)
execl("/bin/sh", "/bin/sh", "-c", "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE", nullptr);
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket);
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket.c_str());
if (!wlr_backend_start(m_sWLRBackend)) {
Debug::log(CRIT, "Backend did not start!");
@@ -371,6 +387,15 @@ void CCompositor::startCompositor() {
wlr_xcursor_manager_set_cursor_image(m_sWLRXCursorMgr, "left_ptr", m_sWLRCursor);
#ifdef USES_SYSTEMD
if (sd_booted() > 0)
// tell systemd that we are ready so it can start other bond, following, related units
sd_notify(0, "READY=1");
else
Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!");
#endif
// This blocks until we are done.
Debug::log(LOG, "Hyprland is ready, running the event loop!");
wl_display_run(m_sWLDisplay);
@@ -430,9 +455,9 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
}
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
if (windowExists(pWindow) && !pWindow->m_bFadingOut){
if (windowExists(pWindow) && !pWindow->m_bFadingOut) {
if (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) {
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
std::erase_if(m_dUnmanagedX11Windows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
}
// if X11, also check its children
@@ -443,16 +468,16 @@ void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
continue;
if (w->m_pX11Parent == pWindow)
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); });
}
for (auto& w : m_dUnmanagedX11Windows) {
if (w->m_pX11Parent == pWindow)
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
std::erase_if(m_dUnmanagedX11Windows, [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); });
}
}
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
}
}
@@ -468,16 +493,16 @@ bool CCompositor::windowExists(CWindow* pWindow) {
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
if (PMONITOR->specialWorkspaceID) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden())
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == PMONITOR->specialWorkspaceID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden())
return (*w).get();
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden())
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden())
return w.get();
}
}
@@ -492,7 +517,8 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned)
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() &&
!(*w)->m_bPinned)
return w->get();
}
@@ -508,10 +534,10 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
if (PMONITOR->specialWorkspaceID) {
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden())
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden())
return w.get();
}
}
@@ -538,16 +564,18 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
if (PMONITOR->specialWorkspaceID) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus)
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == PMONITOR->specialWorkspaceID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) &&
!(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus)
return (*w).get();
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() && !w->m_bX11ShouldntFocus)
if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
!w->m_bX11ShouldntFocus)
return w.get();
}
}
@@ -592,7 +620,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
if (!(*w)->m_bIsX11) {
wlr_surface* resultSurf = nullptr;
Vector2D origin =(*w)->m_vRealPosition.vec();
Vector2D origin = (*w)->m_vRealPosition.vec();
SExtensionFindingData data = {origin, pos, &resultSurf};
wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data);
@@ -616,7 +644,8 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus)
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() &&
!w->m_bX11ShouldntFocus)
return w.get();
}
@@ -626,16 +655,17 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) {
if (PMONITOR->specialWorkspaceID) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && !(*w)->isHidden())
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == PMONITOR->specialWorkspaceID && (*w)->m_bIsMapped &&
wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && !(*w)->isHidden())
return (*w).get();
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped)
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped)
return w.get();
}
}
@@ -650,7 +680,8 @@ CWindow* CCompositor::windowFromCursor() {
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bPinned)
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) &&
!(*w)->m_bPinned)
return w->get();
}
@@ -672,7 +703,8 @@ CWindow* CCompositor::windowFloatingFromCursor() {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned)
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) &&
!(*w)->isHidden() && !(*w)->m_bPinned)
return w->get();
}
@@ -815,7 +847,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == g_pXWaylandManager->getWindowSurface(pWindowOwner)))
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface ||
(pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == g_pXWaylandManager->getWindowSurface(pWindowOwner)))
return; // Don't focus when already focused on this.
// Unfocus last surface if should
@@ -829,7 +862,6 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
return;
}
const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat);
if (!KEYBOARD)
@@ -883,14 +915,30 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
return nullptr;
}
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords,
SLayerSurface** ppLayerSurfaceFound) {
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped) || (*it)->alpha.fl() == 0.f)
continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
if (!SURFACEAT && VECINRECT(pos, (*it)->geometry.x, (*it)->geometry.y, (*it)->geometry.x + (*it)->geometry.width, (*it)->geometry.y + (*it)->geometry.height)) {
SURFACEAT = (*it)->layerSurface->surface;
}
if ((*it)->layerSurface->current.keyboard_interactive && (*it)->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
if (!SURFACEAT)
SURFACEAT = (*it)->layerSurface->surface;
*ppLayerSurfaceFound = it->get();
return SURFACEAT;
}
if (SURFACEAT) {
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
continue;
*ppLayerSurfaceFound = it->get();
return SURFACEAT;
}
@@ -901,6 +949,9 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
for (auto& w : m_vWindows) {
if (!w->m_bIsMapped || w->m_bFadingOut || !w->m_bMappedX11)
continue;
if (g_pXWaylandManager->getWindowSurface(w.get()) == pSurface)
return w.get();
}
@@ -908,6 +959,33 @@ CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
return nullptr;
}
CWindow* CCompositor::getWindowFromHandle(uint32_t handle) {
for (auto& w : m_vWindows) {
if ((uint32_t)(((uint64_t)w.get()) & 0xFFFFFFFF) == handle) {
return w.get();
}
}
return nullptr;
}
CWindow* CCompositor::getWindowFromZWLRHandle(wl_resource* handle) {
for (auto& w : m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || !w->m_phForeignToplevel)
continue;
wl_resource* current;
wl_list_for_each(current, &w->m_phForeignToplevel->resources, link) {
if (current == handle) {
return w.get();
}
}
}
return nullptr;
}
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == ID && w->m_bIsFullscreen)
@@ -922,7 +1000,7 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
if (m->activeWorkspace == w)
return true;
if (m->specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
if (m->specialWorkspaceID && isWorkspaceSpecial(w))
return true;
}
@@ -939,30 +1017,23 @@ CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
}
void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_vWorkspaces.begin(); it != m_vWorkspaces.end(); ++it) {
auto it = m_vWorkspaces.begin();
while (it != m_vWorkspaces.end()) {
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID);
if ((*it)->m_bIsSpecialWorkspace && WINDOWSONWORKSPACE == 0) {
getMonitorFromID((*it)->m_iMonitorID)->specialWorkspaceID = 0;
it = m_vWorkspaces.erase(it);
continue;
}
if ((WINDOWSONWORKSPACE == 0 && !isWorkspaceVisible((*it)->m_iID))) {
it = m_vWorkspaces.erase(it);
if (it == m_vWorkspaces.end())
break;
continue;
}
if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) {
for (auto& m : m_vMonitors) {
m->specialWorkspaceOpen = false;
}
it = m_vWorkspaces.erase(it);
if (it == m_vWorkspaces.end())
break;
continue;
}
++it;
}
}
@@ -1016,6 +1087,8 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
moveToTop(pWindow);
pWindow->m_bCreatedOverFullscreen = true;
if (!pWindow->m_bIsX11)
return;
@@ -1050,8 +1123,9 @@ void CCompositor::cleanupFadingOut(const int& monid) {
g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
w->m_bFadingOut = false;
removeWindowFromVectorSafe(w);
m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
std::erase(m_vWindowsFadingOut, w);
Debug::log(LOG, "Cleanup: destroyed a window");
@@ -1082,7 +1156,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
}
if (!exists) {
m_vSurfacesFadingOut.erase(std::remove(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), ls));
std::erase(m_vSurfacesFadingOut, ls);
Debug::log(LOG, "Fading out a non-existent LS??");
@@ -1103,12 +1177,12 @@ void CCompositor::cleanupFadingOut(const int& monid) {
for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLists) {
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) {
lsl.erase(std::remove_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }));
std::erase_if(lsl, [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; });
}
}
}
m_vSurfacesFadingOut.erase(std::remove(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), ls));
std::erase(m_vSurfacesFadingOut, ls);
Debug::log(LOG, "Cleanup: destroyed a layersurface");
@@ -1150,6 +1224,10 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
continue;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
continue;
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
@@ -1283,9 +1361,7 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
try {
std::string name = "";
return getWorkspaceByID(getWorkspaceIDFromString(str, name));
} catch (std::exception& e) {
Debug::log(ERR, "Error in getWorkspaceByString, invalid id");
}
} catch (std::exception& e) { Debug::log(ERR, "Error in getWorkspaceByString, invalid id"); }
return nullptr;
}
@@ -1401,42 +1477,47 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() {
void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
// optimization
static int64_t* ACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.active_border")->intValue;
static int64_t* INACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->intValue;
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 PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue;
static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get();
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
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 PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
static auto* const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto* const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue;
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
auto setBorderColor = [&](CGradientValueData grad) -> void {
if (grad == pWindow->m_cRealBorderColor)
return;
pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor;
pWindow->m_cRealBorderColor = grad;
pWindow->m_fBorderAnimationProgress.setValueAndWarp(0.f);
pWindow->m_fBorderAnimationProgress = 1.f;
};
// border
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
if (RENDERDATA.isBorderColor)
pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
if (RENDERDATA.isBorderGradient)
setBorderColor(*RENDERDATA.borderGradient);
else
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ?
(pWindow->m_sSpecialRenderData.activeBorderColor >= 0 ? pWindow->m_sSpecialRenderData.activeBorderColor : *ACTIVECOL) :
(pWindow->m_sSpecialRenderData.inactiveBorderColor >= 0 ? pWindow->m_sSpecialRenderData.inactiveBorderColor : *INACTIVECOL));
setBorderColor(pWindow == m_pLastWindow ?
(pWindow->m_sSpecialRenderData.activeBorderColor >= 0 ? CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor)) : *ACTIVECOL) :
(pWindow->m_sSpecialRenderData.inactiveBorderColor >= 0 ? CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor)) : *INACTIVECOL));
// opacity
if (pWindow->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
else {
if (pWindow == m_pLastWindow)
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
else
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
}
} else {
if (pWindow == m_pLastWindow)
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
pWindow->m_fActiveInactiveAlpha =
pWindow->m_sSpecialRenderData.alphaOverride ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
else
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ?
(pWindow->m_sSpecialRenderData.alphaInactiveOverride ? pWindow->m_sSpecialRenderData.alphaInactive :
pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA) :
*PINACTIVEALPHA;
}
// dim
@@ -1547,7 +1628,8 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
return nullptr;
}
int offsetLeft = std::stoi(OFFSET) % m_vMonitors.size(); // no need to cycle more
int offsetLeft = std::stoi(OFFSET);
offsetLeft = offsetLeft < 0 ? -((-offsetLeft) % m_vMonitors.size()) : offsetLeft % m_vMonitors.size();
int currentPlace = 0;
for (int i = 0; i < (int)m_vMonitors.size(); i++) {
@@ -1602,8 +1684,6 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
}
}
}
Debug::log(ERR, "Error in getMonitorFromString: no such monitor");
}
return nullptr;
@@ -1634,7 +1714,10 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
if (nextWorkspaceOnMonitorID == -1) {
nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { const auto B = g_pConfigManager->getBoundMonitorForWS(std::to_string(nextWorkspaceOnMonitorID)); return B && B != POLDMON; }())
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool {
const auto B = g_pConfigManager->getBoundMonitorForWS(std::to_string(nextWorkspaceOnMonitorID));
return B && B != POLDMON;
}())
nextWorkspaceOnMonitorID++;
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
@@ -1680,7 +1763,8 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
pWorkspace->startAnim(true, true, true);
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2,
pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
}
// finalize
@@ -1697,7 +1781,7 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int highestID = -99999;
for (auto& w : m_vWorkspaces) {
if (w->m_iID == SPECIAL_WORKSPACE_ID)
if (w->m_bIsSpecialWorkspace)
continue;
if (w->m_iID < lowestID)
@@ -1740,13 +1824,13 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID) {
w->m_bCreatedOverFullscreen = false;
if (w.get() != pWindow && !w->m_bFadingOut && !w->m_bPinned)
w->m_fAlpha = pWindow->m_bIsFullscreen ? 0.f : 255.f;
w->m_fAlpha = pWindow->m_bIsFullscreen ? 0.f : 1.f;
}
}
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut)
ls->alpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
ls->alpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 1.f;
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
@@ -1797,6 +1881,9 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) {
if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive)
return;
if (!pMonitor->m_bEnabled)
return;
wlr_output_schedule_frame(pMonitor->output);
}
@@ -1845,8 +1932,7 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
continue;
break;
}
default:
break;
default: break;
}
return w.get();
@@ -1860,7 +1946,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos) {
// warpCursorTo should only be used for warps that
// should be disabled with no_cursor_warps
static auto *const PNOWARPS = &g_pConfigManager->getConfigValuePtr("general:no_cursor_warps")->intValue;
static auto* const PNOWARPS = &g_pConfigManager->getConfigValuePtr("general:no_cursor_warps")->intValue;
if (*PNOWARPS)
return;
@@ -1869,7 +1955,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos) {
const auto PMONITORNEW = getMonitorFromVector(pos);
if (PMONITORNEW != m_pLastMonitor)
m_pLastMonitor = PMONITORNEW;
setActiveMonitor(PMONITORNEW);
}
SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) {
@@ -1971,10 +2057,12 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con
monID = PMONITOR->ID;
}
const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(monID, NAME, id == SPECIAL_WORKSPACE_ID)).get();
const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2;
const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(monID, NAME, SPECIAL)).get();
// We are required to set the name here immediately
if (id != SPECIAL_WORKSPACE_ID)
if (!SPECIAL)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, NAME.c_str());
PWORKSPACE->m_iID = id;
@@ -1982,3 +2070,33 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con
return PWORKSPACE;
}
void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
if (m_pLastMonitor == pMonitor)
return;
if (!pMonitor) {
m_pLastMonitor = nullptr;
return;
}
const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace);
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + PWORKSPACE->m_szName});
m_pLastMonitor = pMonitor;
}
bool CCompositor::isWorkspaceSpecial(const int& id) {
return id >= SPECIAL_WORKSPACE_START && id <= -2;
}
int CCompositor::getNewSpecialID() {
int highest = -100;
for (auto& ws : m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) {
highest = ws->m_iID;
}
}
return highest + 1;
}

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,7 +25,7 @@
#include "hyprerror/HyprError.hpp"
class CCompositor {
public:
public:
CCompositor();
~CCompositor();
@@ -74,8 +75,7 @@ public:
wlr_backend* m_sWLRHeadlessBackend;
// ------------------------------------------------- //
const char* m_szWLDisplaySocket;
std::string m_szWLDisplaySocket = "";
std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
@@ -126,6 +126,8 @@ public:
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&);
@@ -169,22 +171,23 @@ public:
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;
private:
private:
void initAllSignals();
void setRandomSplash();
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"),
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"),

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);
@@ -22,7 +22,12 @@ CWindow::~CWindow() {
}
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;
}
@@ -59,6 +62,13 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
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;
SIZE.y += PMONITOR->vecReservedTopLeft.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) {
g_pCompositor->focusWindow(this);
}, this, "Toplevel");
hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) {
hyprListener_toplevelActivate.initCallback(
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pCompositor->focusWindow(this); }, 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");
}, 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,27 +312,33 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
} else if (r.szRule == "noshadow") {
m_sAdditionalConfigData.forceNoShadow = true;
} else if (r.szRule == "opaque") {
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));
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 {
m_sSpecialRenderData.alpha = std::stof(alphaPart);
if (vars[i] == "override") {
if (i == 2) {
m_sSpecialRenderData.alphaOverride = true;
} else {
m_sSpecialRenderData.alphaInactiveOverride = true;
}
} catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
} 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) {
@@ -338,9 +355,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
} 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;
}
}
@@ -352,10 +369,12 @@ void CWindow::updateDynamicRules() {
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.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,7 +16,9 @@ enum eIdleInhibitMode {
};
struct SWindowSpecialRenderData {
bool alphaOverride = false;
float alpha = 1.f;
bool alphaInactiveOverride = false;
float alphaInactive = -1.f; // -1 means unset
int64_t activeBorderColor = -1; // -1 means unset
@@ -32,11 +35,14 @@ struct SWindowAdditionalConfigData {
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 {
@@ -53,7 +59,7 @@ struct SWindowRule {
};
class CWindow {
public:
public:
CWindow();
~CWindow();
@@ -82,8 +88,8 @@ public:
} 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;
@@ -95,10 +101,11 @@ public:
// for restoring floating statuses
Vector2D m_vLastFloatingSize;
Vector2D m_vLastFloatingPosition;
// this is used for pseudotiling
bool m_bIsPseudotiled = false;
Vector2D m_vPseudoSize = Vector2D(0,0);
Vector2D m_vPseudoSize = Vector2D(0, 0);
uint64_t m_iTags = 0;
bool m_bIsFloating = false;
@@ -129,13 +136,16 @@ public:
bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
// initial fullscreen
// 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;
@@ -147,6 +157,9 @@ public:
// For pinned (sticky) windows
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;
@@ -182,7 +195,8 @@ public:
// 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
@@ -205,8 +219,7 @@ public:
void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules();
private:
private:
// For hidden windows and stuff
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;
}
};

View File

@@ -11,6 +11,11 @@
#include <iostream>
CConfigManager::CConfigManager() {
configValues["general:col.active_border"].data = std::make_shared<CGradientValueData>(0xffffffff);
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
configValues["dwindle:col.group_border"].data = std::make_shared<CGradientValueData>(0x66777700);
configValues["dwindle:col.group_border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
setDefaultVars();
setDefaultAnimationVars();
@@ -32,15 +37,13 @@ void CConfigManager::setDefaultVars() {
configValues["general:max_fps"].intValue = 60;
configValues["general:sensitivity"].floatValue = 1.0f;
configValues["general:apply_sens_to_raw"].intValue = 0;
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
configValues["general:border_size"].intValue = 1;
configValues["general:no_border_on_floating"].intValue = 0;
configValues["general:gaps_in"].intValue = 5;
configValues["general:gaps_out"].intValue = 20;
configValues["general:col.active_border"].intValue = 0xffffffff;
configValues["general:col.inactive_border"].intValue = 0xff444444;
((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff);
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
configValues["general:cursor_inactive_timeout"].intValue = 0;
configValues["general:no_cursor_warps"].intValue = 0;
@@ -49,7 +52,6 @@ void CConfigManager::setDefaultVars() {
configValues["misc:disable_hyprland_logo"].intValue = 0;
configValues["misc:disable_splash_rendering"].intValue = 0;
configValues["misc:no_vfr"].intValue = 1;
configValues["misc:damage_entire_on_snapshot"].intValue = 0;
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
configValues["misc:always_follow_on_dnd"].intValue = 1;
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
@@ -73,7 +75,8 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:blur_size"].intValue = 8;
configValues["decoration:blur_passes"].intValue = 1;
configValues["decoration:blur_ignore_opacity"].intValue = 0;
configValues["decoration:blur_new_optimizations"].intValue = 0;
configValues["decoration:blur_new_optimizations"].intValue = 1;
configValues["decoration:blur_xray"].intValue = 0;
configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1;
@@ -89,10 +92,13 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
configValues["decoration:dim_inactive"].intValue = 0;
configValues["decoration:dim_strength"].floatValue = 0.5f;
configValues["decoration:dim_special"].floatValue = 0.2f;
configValues["decoration:dim_around"].floatValue = 0.4f;
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
((CGradientValueData*)configValues["dwindle:col.group_border"].data.get())->reset(0x66777700);
((CGradientValueData*)configValues["dwindle:col.group_border_active"].data.get())->reset(0x66ffff00);
configValues["dwindle:pseudotile"].intValue = 0;
configValues["dwindle:col.group_border"].intValue = 0x66777700;
configValues["dwindle:col.group_border_active"].intValue = 0x66ffff00;
configValues["dwindle:force_split"].intValue = 0;
configValues["dwindle:preserve_split"].intValue = 0;
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
@@ -104,9 +110,10 @@ void CConfigManager::setDefaultVars() {
configValues["master:new_is_master"].intValue = 1;
configValues["master:new_on_top"].intValue = 0;
configValues["master:no_gaps_when_only"].intValue = 0;
configValues["master:orientation"].strValue = "left";
configValues["master:inherit_fullscreen"].intValue = 1;
configValues["animations:enabled"].intValue = 1;
configValues["animations:use_resize_transitions"].intValue = 0;
configValues["animations:speed"].floatValue = 7.f;
configValues["animations:curve"].strValue = "default";
configValues["animations:windows_style"].strValue = STRVAL_EMPTY;
@@ -142,11 +149,13 @@ void CConfigManager::setDefaultVars() {
configValues["input:float_switch_override_focus"].intValue = 1;
configValues["input:left_handed"].intValue = 0;
configValues["input:scroll_method"].strValue = STRVAL_EMPTY;
configValues["input:scroll_button"].intValue = 0;
configValues["input:touchpad:natural_scroll"].intValue = 0;
configValues["input:touchpad:disable_while_typing"].intValue = 1;
configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
configValues["input:touchpad:middle_button_emulation"].intValue = 0;
configValues["input:touchpad:tap-to-click"].intValue = 1;
configValues["input:touchpad:tap-and-drag"].intValue = 1;
configValues["input:touchpad:drag_lock"].intValue = 0;
configValues["input:touchpad:scroll_factor"].floatValue = 1.f;
configValues["input:touchdevice:transform"].intValue = 0;
@@ -165,6 +174,7 @@ void CConfigManager::setDefaultVars() {
configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
configValues["gestures:workspace_swipe_create_new"].intValue = 1;
configValues["gestures:workspace_swipe_forever"].intValue = 0;
configValues["gestures:workspace_swipe_numbered"].intValue = 0;
configValues["input:follow_mouse"].intValue = 1;
@@ -190,11 +200,13 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
cfgValues["clickfinger_behavior"].intValue = 0;
cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1;
cfgValues["tap-and-drag"].intValue = 1;
cfgValues["drag_lock"].intValue = 0;
cfgValues["left_handed"].intValue = 0;
cfgValues["scroll_method"].strValue = STRVAL_EMPTY;
cfgValues["touch_transform"].intValue = 0;
cfgValues["touch_output"].strValue = STRVAL_EMPTY;
cfgValues["scroll_button"].intValue = 0;
cfgValues["transform"].intValue = 0;
cfgValues["output"].strValue = STRVAL_EMPTY;
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
}
@@ -225,15 +237,7 @@ void CConfigManager::setDefaultAnimationVars() {
}
// init the values
animationConfig["global"] = {
false,
"default",
"",
8.f,
1,
&animationConfig["general"],
nullptr
};
animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr};
CREATEANIMCFG("windows", "global");
CREATEANIMCFG("fade", "global");
@@ -299,6 +303,11 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
auto it = deviceConfigs.find(DEVICE);
if (it->second.find(CONFIGVAR) == it->second.end()) {
if (it->second.contains("touch_output") || it->second.contains("touch_transform")) {
parseError = "touch_output and touch_transform have been changed to output and transform respectively";
return;
}
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
return;
}
@@ -348,6 +357,71 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY->data.get() != nullptr) {
switch (CONFIGENTRY->data->getDataType()) {
case CVD_TYPE_GRADIENT: {
CVarList varlist(VALUE, 0, ' ');
CGradientValueData* data = (CGradientValueData*)CONFIGENTRY->data.get();
data->m_vColors.clear();
for (auto& var : varlist) {
if (var.find("deg") != std::string::npos) {
// last arg
try {
data->m_fAngle = std::stoi(var.substr(0, var.find("deg"))) * (PI / 180.0); // radians
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
break;
}
if (data->m_vColors.size() >= 10) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">. Max colors in a gradient is 10.";
break;
}
try {
data->m_vColors.push_back(CColor(configStringToInt(var)));
} catch (std::exception& e) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">. " + e.what();
}
}
if (data->m_vColors.size() == 0) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">. No colors provided.";
data->m_vColors.push_back(0); // transparent
}
break;
}
default: {
UNREACHABLE();
}
}
}
if (COMMAND == "decoration:screen_shader") {
const auto PATH = absolutePath(VALUE, configCurrentPath);
configPaths.push_back(PATH);
struct stat fileStat;
int err = stat(PATH.c_str(), &fileStat);
if (err != 0) {
Debug::log(WARN, "Error at ticking config at %s, error %i: %s", PATH.c_str(), err, strerror(err));
return;
}
configModifyTimes[PATH] = fileStat.st_mtime;
}
}
@@ -397,8 +471,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
return;
}
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
std::erase_if(m_dMonitorRules, [&](const auto& other) { return other.name == newrule.name; });
m_dMonitorRules.push_back(newrule);
@@ -408,9 +481,9 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
if (ARGS[1].find("pref") == 0) {
newrule.resolution = Vector2D();
} else if (ARGS[1].find("highrr") == 0) {
newrule.resolution = Vector2D(-1,-1);
newrule.resolution = Vector2D(-1, -1);
} else if (ARGS[1].find("highres") == 0) {
newrule.resolution = Vector2D(-1,-2);
newrule.resolution = Vector2D(-1, -2);
} else {
newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x')));
newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@')));
@@ -431,12 +504,16 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
}
}
if (ARGS[3].find("auto") == 0) {
newrule.scale = -1;
} else {
newrule.scale = stof(ARGS[3]);
if (newrule.scale < 0.25f) {
parseError = "not a valid scale.";
newrule.scale = 1;
}
}
int argno = 4;
@@ -456,8 +533,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
argno++;
}
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
std::erase_if(m_dMonitorRules, [&](const auto& other) { return other.name == newrule.name; });
m_dMonitorRules.push_back(newrule);
}
@@ -489,7 +565,7 @@ void CConfigManager::handleBezier(const std::string& command, const std::string&
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
}
void CConfigManager::setAnimForChildren(SAnimationPropertyConfig *const ANIM) {
void CConfigManager::setAnimForChildren(SAnimationPropertyConfig* const ANIM) {
for (auto& [name, anim] : animationConfig) {
if (anim.pParentAnimation == ANIM && !anim.overriden) {
// if a child isnt overriden, set the values of the parent
@@ -659,36 +735,16 @@ void CConfigManager::handleUnbind(const std::string& command, const std::string&
}
bool windowRuleValid(const std::string& RULE) {
return !(RULE != "float"
&& RULE != "tile"
&& RULE.find("opacity") != 0
&& RULE.find("move") != 0
&& RULE.find("size") != 0
&& RULE.find("minsize") != 0
&& RULE.find("maxsize") != 0
&& RULE.find("pseudo") != 0
&& RULE.find("monitor") != 0
&& RULE.find("idleinhibit") != 0
&& RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "noshadow"
&& RULE != "noborder"
&& RULE != "center"
&& RULE != "opaque"
&& RULE != "forceinput"
&& RULE != "fullscreen"
&& RULE != "pin"
&& RULE != "noanim"
&& RULE != "windowdance"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0
&& RULE.find("bordercolor") != 0);
return !(RULE != "float" && RULE != "tile" && RULE.find("opacity") != 0 && RULE.find("move") != 0 && RULE.find("size") != 0 && RULE.find("minsize") != 0 &&
RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" &&
RULE != "noshadow" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" &&
RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 &&
RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0);
}
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(",")));
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(",") + 1));
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(',')));
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(',') + 1));
// check rule and value
if (RULE == "" || VALUE == "") {
@@ -696,9 +752,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
}
if (RULE == "unset") {
std::erase_if(m_dWindowRules, [&] (const SWindowRule& other) {
return other.szValue == VALUE;
});
std::erase_if(m_dWindowRules, [&](const SWindowRule& other) { return other.szValue == VALUE; });
return;
}
@@ -713,8 +767,8 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
}
void CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
const auto RULE = value.substr(0, value.find_first_of(","));
const auto VALUE = value.substr(value.find_first_of(",") + 1);
const auto RULE = value.substr(0, value.find_first_of(','));
const auto VALUE = value.substr(value.find_first_of(',') + 1);
if (!windowRuleValid(RULE) && RULE != "unset") {
Debug::log(ERR, "Invalid rulev2 found: %s", RULE.c_str());
@@ -735,9 +789,8 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
const auto FULLSCREENPOS = VALUE.find("fullscreen:");
const auto PINNEDPOS = VALUE.find("pinned:");
if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos &&
X11POS == std::string::npos && FLOATPOS == std::string::npos &&
FULLSCREENPOS == std::string::npos && PINNEDPOS == std::string::npos) {
if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos &&
PINNEDPOS == std::string::npos) {
Debug::log(ERR, "Invalid rulev2 syntax: %s", VALUE.c_str());
parseError = "Invalid rulev2 syntax: " + VALUE;
return;
@@ -748,12 +801,18 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
result = VALUE.substr(pos);
size_t min = 999999;
if (TITLEPOS > pos && TITLEPOS < min) min = TITLEPOS;
if (CLASSPOS > pos && CLASSPOS < min) min = CLASSPOS;
if (X11POS > pos && X11POS < min) min = X11POS;
if (FLOATPOS > pos && FLOATPOS < min) min = FLOATPOS;
if (FULLSCREENPOS > pos && FULLSCREENPOS < min) min = FULLSCREENPOS;
if (PINNEDPOS > pos && PINNEDPOS < min) min = PINNEDPOS;
if (TITLEPOS > pos && TITLEPOS < min)
min = TITLEPOS;
if (CLASSPOS > pos && CLASSPOS < min)
min = CLASSPOS;
if (X11POS > pos && X11POS < min)
min = X11POS;
if (FLOATPOS > pos && FLOATPOS < min)
min = FLOATPOS;
if (FULLSCREENPOS > pos && FULLSCREENPOS < min)
min = FULLSCREENPOS;
if (PINNEDPOS > pos && PINNEDPOS < min)
min = PINNEDPOS;
result = result.substr(0, min - pos);
@@ -830,7 +889,7 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
if (value.find("remove,") == 0) {
const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7));
m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
std::erase_if(m_dBlurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; });
return;
}
@@ -928,6 +987,8 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
currentCategory = "";
}
int needsLayoutRecalc = COMMAND == "monitor"; // 0 - no, 1 - yes, 2 - maybe
if (COMMAND == "exec") {
if (isFirstLaunch) {
firstExecRequests.push_back(VALUE);
@@ -938,29 +999,46 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
if (isFirstLaunch) {
firstExecRequests.push_back(VALUE);
}
}
else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE);
else if (COMMAND.find("bind") == 0) handleBind(COMMAND, VALUE);
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
else if (COMMAND == "windowrulev2") handleWindowRuleV2(COMMAND, VALUE);
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE);
else
} else if (COMMAND == "monitor")
handleMonitor(COMMAND, VALUE);
else if (COMMAND.find("bind") == 0)
handleBind(COMMAND, VALUE);
else if (COMMAND == "unbind")
handleUnbind(COMMAND, VALUE);
else if (COMMAND == "workspace")
handleDefaultWorkspace(COMMAND, VALUE);
else if (COMMAND == "windowrule")
handleWindowRule(COMMAND, VALUE);
else if (COMMAND == "windowrulev2")
handleWindowRuleV2(COMMAND, VALUE);
else if (COMMAND == "bezier")
handleBezier(COMMAND, VALUE);
else if (COMMAND == "animation")
handleAnimation(COMMAND, VALUE);
else if (COMMAND == "source")
handleSource(COMMAND, VALUE);
else if (COMMAND == "submap")
handleSubmap(COMMAND, VALUE);
else if (COMMAND == "blurls")
handleBlurLS(COMMAND, VALUE);
else if (COMMAND == "wsbind")
handleBindWS(COMMAND, VALUE);
else {
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
needsLayoutRecalc = 2;
}
if (dynamic) {
std::string retval = parseError;
parseError = "";
// invalidate layouts jic
// invalidate layouts if they changed
if (needsLayoutRecalc) {
if (needsLayoutRecalc == 1 || COMMAND.contains("gaps_") || COMMAND.find("dwindle:") == 0 || COMMAND.find("master:") == 0) {
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
}
}
// Update window border colors
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
@@ -977,7 +1055,7 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals
while (dollarPlace != std::string::npos) {
const auto STRAFTERDOLLAR = line.substr(dollarPlace + 1);
for (auto&[var, value] : configDynamicVars) {
for (auto& [var, value] : configDynamicVars) {
if (STRAFTERDOLLAR.find(var) == 0) {
line.replace(dollarPlace, var.length() + 1, value);
break;
@@ -1023,8 +1101,7 @@ void CConfigManager::parseLine(std::string& line) {
if (currentCategory.length() != 0) {
currentCategory.push_back(':');
currentCategory.append(cat);
}
else {
} else {
currentCategory = cat;
}
@@ -1098,17 +1175,17 @@ void CConfigManager::loadConfigLoadVars() {
ifs.open(CONFIGPATH);
if (!ifs.good()) {
if(g_pCompositor->explicitConfigPath == "") {
if (g_pCompositor->explicitConfigPath == "") {
Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
try {
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
} catch(...) { /* Probably doesn't exist */}
} catch (...) { /* Probably doesn't exist */
}
try {
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
std::filesystem::create_directories(CONFIGPARENTPATH);
}
catch (...) {
} catch (...) {
parseError = "Broken config file! (Could not create directory)";
return;
}
@@ -1162,16 +1239,18 @@ void CConfigManager::loadConfigLoadVars() {
g_pInputManager->setKeyboardLayout();
g_pInputManager->setPointerConfigs();
g_pInputManager->setTouchDeviceConfigs();
g_pInputManager->setTabletConfigs();
}
// Calculate the internal vars
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
if (!isFirstLaunch)
g_pHyprOpenGL->m_bReloadScreenShader = true;
// parseError will be displayed next frame
if (parseError != "")
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(255, 50, 50, 255));
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
else if (configValues["autogenerated"].intValue == 1)
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", CColor(255, 255, 70, 255));
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
else
g_pHyprError->destroy();
@@ -1180,9 +1259,8 @@ void CConfigManager::loadConfigLoadVars() {
// and they'll be taken care of in the newMonitor event
// ignore if nomonitorreload is set
if (!isFirstLaunch && !m_bNoMonitorReload) {
m_bWantsMonitorReload = true;
// check
performMonitorReload();
ensureDPMS();
ensureVRR();
}
@@ -1251,13 +1329,10 @@ SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
auto devcopy = dev;
std::replace(devcopy.begin(), devcopy.end(), ' ', '-');
const auto it = deviceConfigs.find(devcopy);
const auto it = deviceConfigs.find(dev);
if (it == deviceConfigs.end()) {
Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", devcopy.c_str());
Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", dev.c_str());
return SConfigValue();
}
@@ -1270,7 +1345,7 @@ SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, co
if (foundIt == std::string::npos)
continue;
if (cv.first == "input:" + val || cv.first == "input:touchpad:" + cv.first) {
if (cv.first == "input:" + val || cv.first == "input:touchpad:" + cv.first || cv.first == "input:touchdevice:" + val) {
copy = cv.second;
}
}
@@ -1288,7 +1363,7 @@ float CConfigManager::getFloat(const std::string& v) {
}
std::string CConfigManager::getString(const std::string& v) {
const auto VAL = getConfigValueSafe(v).strValue;
auto VAL = getConfigValueSafe(v).strValue;
if (VAL == STRVAL_EMPTY)
return "";
@@ -1305,7 +1380,7 @@ float CConfigManager::getDeviceFloat(const std::string& dev, const std::string&
}
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v) {
const auto VAL = getConfigValueSafeDevice(dev, v).strValue;
auto VAL = getConfigValueSafeDevice(dev, v).strValue;
if (VAL == STRVAL_EMPTY)
return "";
@@ -1313,23 +1388,25 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s
return VAL;
}
void CConfigManager::setInt(std::string v, int val) {
void CConfigManager::setInt(const std::string& v, int val) {
configValues[v].intValue = val;
}
void CConfigManager::setFloat(std::string v, float val) {
void CConfigManager::setFloat(const std::string& v, float val) {
configValues[v].floatValue = val;
}
void CConfigManager::setString(std::string v, std::string val) {
void CConfigManager::setString(const std::string& v, const std::string& val) {
configValues[v].strValue = val;
}
SMonitorRule CConfigManager::getMonitorRuleFor(std::string name, std::string displayName) {
SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const std::string& displayName) {
SMonitorRule* found = nullptr;
for (auto& r : m_dMonitorRules) {
if (r.name == name || (r.name.find("desc:") == 0 && (r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) {
if (r.name == name ||
(r.name.find("desc:") == 0 &&
(r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) {
found = &r;
break;
}
@@ -1352,7 +1429,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(std::string name, std::string dis
Debug::log(WARN, "No rules configured. Using the default hardcoded one.");
return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-1, -1), .scale = 1}; // 0, 0 is preferred and -1, -1 is auto
return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-1, -1), .scale = -1}; // 0, 0 is preferred and -1, -1 is auto
}
std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
@@ -1465,6 +1542,7 @@ void CConfigManager::dispatchExecOnce() {
g_pInputManager->setKeyboardLayout();
g_pInputManager->setPointerConfigs();
g_pInputManager->setTouchDeviceConfigs();
g_pInputManager->setTabletConfigs();
// set ws names again
for (auto& ws : g_pCompositor->m_vWorkspaces) {
@@ -1479,28 +1557,31 @@ void CConfigManager::performMonitorReload() {
for (auto& m : g_pCompositor->m_vRealMonitors) {
auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
// ensure mirror
m->setMirror(rule.mirrorOf);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
overAgain = true;
break;
}
// ensure mirror
m->setMirror(rule.mirrorOf);
g_pHyprRenderer->arrangeLayersForMonitor(m->ID);
}
if (overAgain)
performMonitorReload();
if (!g_pCompositor->m_vMonitors.empty()) // reset unsafe state if we have monitors
g_pCompositor->m_bUnsafeState = false;
m_bWantsMonitorReload = false;
}
SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
SConfigValue* CConfigManager::getConfigValuePtr(const std::string& val) {
return &configValues[val];
}
SConfigValue* CConfigManager::getConfigValuePtrSafe(std::string val) {
SConfigValue* CConfigManager::getConfigValuePtrSafe(const std::string& val) {
const auto IT = configValues.find(val);
if (IT == configValues.end())
@@ -1540,7 +1621,7 @@ void CConfigManager::ensureDPMS() {
}
void CConfigManager::ensureVRR(CMonitor* pMonitor) {
static auto *const PNOVRR = &getConfigValuePtr("misc:no_vfr")->intValue;
static auto* const PNOVRR = &getConfigValuePtr("misc:no_vfr")->intValue;
auto ensureVRRForDisplay = [&](CMonitor* m) -> void {
if (!*PNOVRR && !m->vrrActive) {
@@ -1589,10 +1670,12 @@ SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::
void CConfigManager::addParseError(const std::string& err) {
if (parseError == "")
parseError = err;
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
}
CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
for (auto&[ws, mon] : boundWorkspaces) {
CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
for (auto& [ws, mon] : boundWorkspaces) {
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
if (WSNAME == wsname) {
@@ -1603,6 +1686,22 @@ CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
return nullptr;
}
void CConfigManager::addExecRule(SExecRequestedRule rule) {
std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) {
for (auto& [ws, mon] : boundWorkspaces) {
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
if (WSNAME == wsname) {
return mon;
}
}
return "";
}
void CConfigManager::addExecRule(const SExecRequestedRule& rule) {
execRequestedRules.push_back(rule);
}
ICustomConfigValueData::~ICustomConfigValueData() {
; // empty
}

View File

@@ -13,6 +13,7 @@
#include "../Window.hpp"
#include "defaultConfig.hpp"
#include "ConfigDataValues.hpp"
#define STRVAL_EMPTY "[[EMPTY]]"
@@ -24,14 +25,15 @@ struct SConfigValue {
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
};
struct SMonitorRule {
std::string name = "";
Vector2D resolution = Vector2D(1280,720);
Vector2D offset = Vector2D(0,0);
Vector2D resolution = Vector2D(1280, 720);
Vector2D offset = Vector2D(0, 0);
float scale = 1;
float refreshRate = 60;
std::string defaultWorkspace = "";
@@ -66,7 +68,7 @@ struct SExecRequestedRule {
};
class CVarList {
public:
public:
CVarList(const std::string& in, long unsigned int lastArgNo = 0, const char separator = ',') {
std::string curitem = "";
std::string argZ = in;
@@ -93,7 +95,7 @@ public:
~CVarList() = default;
int size() const {
size_t size() const {
return m_vArgs.size();
}
@@ -104,17 +106,25 @@ 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();
@@ -123,9 +133,9 @@ public:
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);
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&);
@@ -133,12 +143,13 @@ public:
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*);
@@ -160,11 +171,11 @@ public:
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
void addExecRule(SExecRequestedRule);
void addExecRule(const SExecRequestedRule&);
std::string configCurrentPath;
private:
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
@@ -197,7 +208,7 @@ private:
void setDefaultAnimationVars();
void setDeviceDefaultVars(const std::string&);
void setAnimForChildren(SAnimationPropertyConfig *const);
void setAnimForChildren(SAnimationPropertyConfig* const);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();

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, (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->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);
}
}
@@ -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";
@@ -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\",";
@@ -544,11 +596,21 @@ std::string dispatchKeyword(std::string in) {
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
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());
if (retval == "")
@@ -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";
@@ -683,6 +746,52 @@ 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 = "";
@@ -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());
}
}
@@ -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)
@@ -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

@@ -18,7 +18,8 @@ namespace HyprCtl {
inline int iSocketFD = -1;
enum eHyprCtlOutputFormat {
enum eHyprCtlOutputFormat
{
FORMAT_NORMAL = 0,
FORMAT_JSON
};

View File

@@ -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;
@@ -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,14 +8,14 @@
#include <unordered_map>
class CHyprMonitorDebugOverlay {
public:
public:
int draw(int offset);
void renderData(CMonitor* pMonitor, float µs);
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
void frameData(CMonitor* pMonitor);
private:
private:
std::deque<float> m_dLastFrametimes;
std::deque<float> m_dLastRenderTimes;
std::deque<float> m_dLastRenderTimesNoOverlay;
@@ -25,15 +25,13 @@ private:
};
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;

View File

@@ -5,7 +5,7 @@
#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");
}
@@ -35,23 +35,12 @@ 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

View File

@@ -4,7 +4,8 @@
#define LOGMESSAGESIZE 1024
enum LogLevel {
enum LogLevel
{
NONE = -1,
LOG = 0,
WARN,
@@ -14,7 +15,7 @@ enum LogLevel {
};
namespace Debug {
void init(std::string IS);
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);

View File

@@ -18,19 +18,23 @@
#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; \
#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
@@ -41,12 +45,15 @@
#define GREEN(c) ((double)(((c) >> 8) & 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()); \
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 */ \
}
@@ -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) {
@@ -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);
}
}

View File

@@ -96,6 +96,7 @@ namespace Events {
// Monitor part 2 the sequel
DYNLISTENFUNC(monitorFrame);
DYNLISTENFUNC(monitorDestroy);
DYNLISTENFUNC(monitorStateRequest);
// XWayland
LISTENER(readyXWayland);

View File

@@ -55,7 +55,8 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
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,7 +95,8 @@ 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);
}
@@ -137,21 +139,24 @@ 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;
@@ -209,11 +214,12 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
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?
}
@@ -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

@@ -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);
@@ -112,10 +113,11 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
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,8 +128,11 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
void Events::listener_destroyDrag(void* owner, void* data) {
Debug::log(LOG, "Drag destroyed.");
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
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_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;
@@ -135,7 +140,7 @@ void Events::listener_destroyDrag(void* owner, void* data) {
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();
@@ -80,14 +78,17 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
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_pConfigManager->m_bWantsMonitorReload = true;
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
}
void Events::listener_monitorFrame(void* owner, void* data) {
@@ -105,11 +106,11 @@ void Events::listener_monitorFrame(void* owner, void* data) {
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 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
@@ -137,7 +138,8 @@ 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();
@@ -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,18 +201,19 @@ 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;
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);
@@ -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,7 +239,7 @@ 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->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);
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);
@@ -316,8 +319,8 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
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,7 +16,7 @@
// --------------------------------------------- //
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
SXDGPopup *const PPOPUP = (SXDGPopup*)pPopup;
SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup;
auto curPopup = PPOPUP;
@@ -69,7 +69,8 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
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) {
@@ -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,34 +29,29 @@ 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;
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);
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->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false;
@@ -113,14 +108,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
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 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;
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);
@@ -206,7 +213,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
shouldFocus = true;
}
if (requestedWorkspace == "special") {
if (requestedWorkspace.find("special") == 0) {
workspaceSpecial = true;
workspaceSilent = true;
}
@@ -216,6 +223,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
PMONITOR = g_pCompositor->m_pLastMonitor;
}
}
@@ -233,7 +242,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
} else if (workspaceSpecial) {
workspaceName = "";
workspaceID = SPECIAL_WORKSPACE_ID;
workspaceID = getWorkspaceIDFromString(requestedWorkspace, workspaceName);
} else {
try {
workspaceID = std::stoi(requestedWorkspace);
@@ -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,50 +293,46 @@ 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;
@@ -331,36 +340,40 @@ void Events::listener_mapWindow(void* owner, void* data) {
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);
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);
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,7 +397,7 @@ 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;
@@ -397,6 +408,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
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) {
@@ -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();
@@ -693,6 +720,11 @@ 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) {
@@ -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;
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();
@@ -746,7 +790,7 @@ 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;
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);
@@ -766,7 +810,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
void Events::listener_activateX11(void* owner, void* data) {
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);
@@ -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,7 +915,8 @@ 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;
@@ -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

@@ -38,9 +38,7 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPro
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

@@ -24,7 +24,7 @@ struct SAnimationPropertyConfig;
class CHyprRenderer;
class CAnimatedVariable {
public:
public:
CAnimatedVariable(); // dummy var
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
@@ -65,28 +65,34 @@ public:
return m_cGoal;
}
void operator=(const Vector2D& v) {
CAnimatedVariable& operator=(const Vector2D& v) {
m_vGoal = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
onAnimationBegin();
return *this;
}
void operator=(const float& v) {
CAnimatedVariable& operator=(const float& v) {
m_fGoal = v;
animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue;
onAnimationBegin();
return *this;
}
void operator=(const CColor& v) {
CAnimatedVariable& operator=(const CColor& v) {
m_cGoal = v;
animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue;
onAnimationBegin();
return *this;
}
// Sets the actual stored value, without affecting the goal, but resets the timer
@@ -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,6 +188,9 @@ 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. */
@@ -205,17 +209,24 @@ public:
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);
private:
Vector2D m_vValue = Vector2D(0, 0);
float m_fValue = 0;
CColor m_cValue;
Vector2D m_vGoal = Vector2D(0,0);
Vector2D m_vGoal = Vector2D(0, 0);
float m_fGoal = 0;
CColor m_cGoal;
Vector2D m_vBegun = Vector2D(0,0);
Vector2D m_vBegun = Vector2D(0, 0);
float m_fBegun = 0;
CColor m_cBegun;

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());
@@ -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) {
@@ -49,7 +48,7 @@ float CBezierCurve::getYForPoint(float x) {
float lowerT = 0;
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 {

View File

@@ -10,7 +10,7 @@ constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
// 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);
@@ -19,7 +19,7 @@ public:
float getXForT(float t);
float getYForPoint(float x);
private:
private:
// this INCLUDES the 0,0 and 1,1 points.
std::deque<Vector2D> m_dPoints;

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();
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 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,29 +5,28 @@
#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] = {{
@@ -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,11 +95,11 @@ 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, ...) {
std::string getFormat(const char* fmt, ...) {
char* outputStr = nullptr;
va_list args;
@@ -116,7 +115,7 @@ 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;
@@ -127,8 +126,7 @@ std::string escapeJSONStrings(const std::string& str) {
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);
oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
@@ -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));
return relative + stof(source);
} 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;
}
}
return result;
}
bool isNumber(const std::string& str, bool allowfloat) {
@@ -234,7 +203,18 @@ 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);
@@ -244,6 +224,13 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
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';
@@ -259,51 +246,41 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
// result now has +/- what we should move on mon
int remains = (int)result;
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
int searchID = currentID;
while (remains != 0) {
if (remains < 0)
searchID--;
else
searchID++;
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
// means we need to wrap around
int lowestID = 99999;
int highestID = -99999;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iID == SPECIAL_WORKSPACE_ID)
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 (w->m_iID < lowestID)
lowestID = w->m_iID;
if (w->m_iID > highestID)
highestID = w->m_iID;
validWSes.push_back(ws->m_iID);
}
if (remains < 0)
searchID = highestID;
else
searchID = lowestID;
}
std::sort(validWSes.begin(), validWSes.end());
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;
// get the offset
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
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] == '-') {
@@ -403,10 +380,10 @@ 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]);
KINFO_PROC kp;
@@ -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,8 +3,8 @@
#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);
std::string removeBeginEndSpacesTabs(std::string);

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);
@@ -85,16 +91,12 @@ 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;
@@ -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);
@@ -126,18 +131,30 @@ void CMonitor::onConnect(bool noRule) {
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
//
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = this;
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; }));
@@ -176,10 +192,17 @@ void CMonitor::onDisconnect() {
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,12 +275,26 @@ 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) {
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
@@ -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,11 +10,11 @@
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;
@@ -24,8 +24,8 @@ public:
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;
@@ -46,8 +46,8 @@ public:
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
@@ -56,13 +56,12 @@ public:
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();
@@ -70,6 +69,7 @@ public:
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;
@@ -81,6 +81,7 @@ public:
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
}
private:
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
@@ -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;
@@ -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,7 +217,8 @@ 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) {
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) {

View File

@@ -6,7 +6,7 @@
struct SSubsurface;
class CWindow;
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
typedef void (*applyGlobalOffsetFn)(void*, int*, int*);
struct SSurfaceTreeNode {
wlr_surface* pSurface = nullptr;
@@ -21,7 +21,7 @@ struct SSurfaceTreeNode {
std::list<SSubsurface> childSubsurfaces;
applyGlobalOffsetFn offsetfn;
void *globalOffsetData;
void* globalOffsetData;
CWindow* pWindowOwner = nullptr;
bool operator==(const SSurfaceTreeNode& rhs) {

View File

@@ -3,12 +3,12 @@
#include "../defines.hpp"
class CTimer {
public:
public:
void reset();
float getSeconds();
int getMillis();
private:
private:
std::chrono::system_clock::time_point m_tpLastReset;
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

@@ -14,16 +14,16 @@ class Vector2D {
// returns the scale
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

@@ -19,7 +19,7 @@ struct SLayerSurface {
DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup);
wlr_box geometry = {0,0,0,0};
wlr_box geometry = {0, 0, 0, 0};
Vector2D position;
zwlr_layer_shell_v1_layer layer;
@@ -57,7 +57,7 @@ struct SRenderData {
bool dontRound = true;
// for fade
float fadeAlpha = 255.f;
float fadeAlpha = 1.f;
// for alpha settings
float alpha = 1.f;
@@ -70,6 +70,7 @@ struct SRenderData {
// for blurring
bool blur = false;
bool blockBlurOptimization = false;
// only for windows, not popups
bool squishOversized = true;
@@ -102,6 +103,7 @@ struct SKeyboard {
bool isVirtual = false;
bool active = false;
bool enabled = true;
xkb_layout_index_t activeLayout = 0;
@@ -145,6 +147,9 @@ struct SConstraint {
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);
@@ -248,6 +253,7 @@ struct STabletTool {
struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";

View File

@@ -4,7 +4,7 @@
#include <functional>
class CHyprWLListener {
public:
public:
CHyprWLListener(wl_signal*, std::function<void(void*, void*)>, void* owner);
CHyprWLListener();
~CHyprWLListener();
@@ -27,7 +27,7 @@ public:
void emit(void*);
private:
private:
SWrapper m_swWrapper;
void* m_pOwner = nullptr;

View File

@@ -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,7 +12,7 @@ enum eFullscreenMode : uint8_t {
class CWindow;
class CWorkspace {
public:
public:
CWorkspace(int monitorID, std::string name, bool special = false);
~CWorkspace();

View File

@@ -28,7 +28,8 @@ typedef struct {
} xcb_size_hints_t;
typedef unsigned int xcb_window_t;
typedef enum xcb_stack_mode_t {
typedef enum xcb_stack_mode_t
{
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,
@@ -37,59 +38,59 @@ typedef enum xcb_stack_mode_t {
} 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;
struct wlr_xwm* xwm;
uint32_t surface_id;
struct wl_list link;
struct wl_list stack_link;
struct wl_list unpaired_link;
struct wlr_surface *surface;
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;
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 wlr_xwayland_surface* parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
xcb_atom_t *window_type;
xcb_atom_t* window_type;
size_t window_type_len;
xcb_atom_t *protocols;
xcb_atom_t* protocols;
size_t protocols_len;
uint32_t decorations;
xcb_icccm_wm_hints_t *hints;
xcb_size_hints_t *size_hints;
xcb_icccm_wm_hints_t* hints;
xcb_size_hints_t* size_hints;
bool pinging;
struct wl_event_source *ping_timer;
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;
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;
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

@@ -28,7 +28,7 @@ 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
@@ -39,14 +39,14 @@ void CHyprError::createQueued() {
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
@@ -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,12 +6,12 @@
#include <cairo/cairo.h>
class CHyprError {
public:
public:
void queueCreate(std::string message, const CColor& color);
void draw();
void destroy();
private:
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;

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

@@ -6,8 +6,8 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force) {
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;
@@ -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;
}
@@ -181,14 +181,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
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);
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);
@@ -205,11 +207,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
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;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
@@ -238,9 +238,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
}
}
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;
@@ -282,7 +282,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
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;
@@ -293,7 +293,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
SDwindleNodeData* OPENINGON;
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,6 +338,16 @@ 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;
@@ -393,8 +405,12 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
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,7 +440,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
// Update the children
if (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y) {
// split left/right
OPENINGON->position = NEWPARENT->position;
@@ -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);
@@ -563,8 +582,8 @@ 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;
@@ -705,7 +724,7 @@ 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);
@@ -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,8 +759,10 @@ 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
@@ -800,13 +821,15 @@ 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;
}
@@ -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) {
@@ -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);
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;
@@ -1132,9 +1161,12 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
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,6 +4,7 @@
#include <list>
#include <deque>
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include <array>
class CHyprDwindleLayout;
enum eFullscreenMode : uint8_t;
@@ -14,7 +15,7 @@ struct SDwindleNodeData {
CWindow* pWindow = nullptr;
std::array<SDwindleNodeData*, 2> children = { nullptr, nullptr };
std::array<SDwindleNodeData*, 2> children = {nullptr, nullptr};
bool splitTop = false; // for preserve_split
@@ -33,7 +34,8 @@ struct SDwindleNodeData {
// 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);
@@ -47,7 +49,7 @@ struct SDwindleNodeData {
};
class CHyprDwindleLayout : public IHyprLayout {
public:
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
@@ -58,14 +60,13 @@ public:
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float);
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void onEnable();
virtual void onDisable();
private:
private:
std::list<SDwindleNodeData> m_lDwindleNodesData;
int getNodesOnWorkspace(const int&);

View File

@@ -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 {
@@ -49,7 +52,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
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,16 +138,13 @@ 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) {
@@ -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,10 +208,13 @@ 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 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);
@@ -249,7 +259,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
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;
@@ -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,6 +307,9 @@ 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);
pWindow->m_iMonitorID = PNEWMON->ID;
@@ -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,10 +2,11 @@
#include "../defines.hpp"
#include "../Window.hpp"
#include <any>
struct SWindowRenderLayoutHints {
bool isBorderColor = false;
CColor borderColor;
bool isBorderGradient = false;
CGradientValueData* borderGradient;
};
struct SLayoutMessageHeader {
@@ -15,7 +16,8 @@ struct SLayoutMessageHeader {
enum eFullscreenMode : uint8_t;
interface IHyprLayout {
public:
public:
virtual ~IHyprLayout() = 0;
virtual void onEnable() = 0;
virtual void onDisable() = 0;
@@ -113,10 +115,10 @@ public:
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
@@ -133,7 +135,7 @@ public:
*/
virtual void onWindowFocusChange(CWindow*);
private:
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;

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,7 +69,7 @@ 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);
@@ -56,7 +78,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
PNODE->workspaceID = pWindow->m_iWorkspaceID;
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;
@@ -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);
@@ -121,16 +148,19 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
for (auto& nd : m_lMasterNodesData) {
if (!nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
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;
}
@@ -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) {
@@ -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,46 +224,88 @@ 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 {
} 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) {
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;
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;
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * PMONITOR->vecSize.x, nextY);
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(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, HEIGHT);
nd.size = Vector2D(WIDTH, HEIGHT);
slavesLeft--;
heightLeft -= HEIGHT;
@@ -239,14 +313,40 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
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;
}
@@ -277,7 +377,7 @@ 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_vPosition = pNode->position;
@@ -285,7 +385,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
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);
@@ -302,17 +404,15 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
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;
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;
@@ -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,7 +507,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
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);
@@ -486,6 +602,8 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* 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);
@@ -498,9 +616,14 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
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);
}
@@ -552,14 +676,14 @@ 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;
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
@@ -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;
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;
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);
}
@@ -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,11 +1,22 @@
#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;
@@ -24,8 +35,17 @@ struct SMasterNodeData {
}
};
struct SMasterWorkspaceData {
int workspaceID = -1;
eOrientation orientation = ORIENTATION_LEFT;
bool operator==(const SMasterWorkspaceData& rhs) {
return workspaceID == rhs.workspaceID;
}
};
class CHyprMasterLayout : public IHyprLayout {
public:
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
@@ -36,15 +56,15 @@ public:
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float);
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void onEnable();
virtual void onDisable();
private:
private:
std::list<SMasterNodeData> m_lMasterNodesData;
std::vector<SMasterWorkspaceData> m_lMasterWorkspacesData;
bool m_bForceWarps = false;
@@ -52,9 +72,13 @@ private:
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;
}
}
@@ -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

@@ -23,13 +23,13 @@ void CAnimationManager::tick() {
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");
@@ -56,7 +56,7 @@ void CAnimationManager::tick() {
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);
@@ -164,32 +164,36 @@ 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;
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.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.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);
@@ -197,7 +201,8 @@ void CAnimationManager::tick() {
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};
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;
}
@@ -302,10 +308,14 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool
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);
@@ -426,9 +436,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
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";
}
} 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,8 +8,7 @@
#include "../Window.hpp"
class CAnimationManager {
public:
public:
CAnimationManager();
void tick();
@@ -19,12 +18,13 @@ public:
void onWindowPostCreateClose(CWindow*, bool close = false);
bool bezierExists(const std::string&);
CBezierCurve* getBezier(const std::string&);
std::string styleValidInConfigVar(const std::string&, const std::string&);
std::list<CAnimatedVariable*> m_lAnimatedVariables;
private:
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);

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);
@@ -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) {
std::thread(
[&](const SHyprIPCEvent ev) {
eventQueueMutex.lock();
m_dQueuedEvents.push_back(ev);
eventQueueMutex.unlock();
flushEvents();
}, event).detach();
},
event)
.detach();
}

View File

@@ -12,7 +12,7 @@ struct SHyprIPCEvent {
};
class CEventManager {
public:
public:
CEventManager();
void postEvent(const SHyprIPCEvent event, bool force = false);
@@ -23,8 +23,7 @@ public:
std::thread m_tThread;
private:
private:
void flushEvents();
std::mutex eventQueueMutex;

View File

@@ -11,6 +11,7 @@ CKeybindManager::CKeybindManager() {
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;
@@ -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())
@@ -116,21 +116,20 @@ void CKeybindManager::updateXKBTranslationState() {
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);
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);
@@ -234,7 +233,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
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();
@@ -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()) {
@@ -436,7 +436,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
unsigned int ttynum = 0;
try {
ttynum = std::stoll(TTYSTR);
} catch (std::exception &e) {
} catch (std::exception& e) {
; // oops?
}
@@ -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;
@@ -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;
}
@@ -680,7 +680,7 @@ 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;
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);
@@ -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,6 +956,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
// hacky, but works lol
// TODO: this sucks
CWindow* PWINDOW = nullptr;
@@ -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,7 +1051,6 @@ 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;
@@ -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);
}
}
};
@@ -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,8 +1162,13 @@ void CKeybindManager::alterSplitRatio(std::string args) {
}
if (splitratio == 0) {
if (args.find("exact") == 0) {
exact = true;
splitratio = getPlusMinusKeywordResult(args.substr(5), 0);
} else {
splitratio = getPlusMinusKeywordResult(args, 0);
}
}
if (splitratio == INT_MAX) {
Debug::log(ERR, "Splitratio invalid in alterSplitRatio!");
@@ -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
@@ -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);
}
}
}
@@ -1304,7 +1317,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
if (!PMONITOR){
if (!PMONITOR) {
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
return;
}
@@ -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);
@@ -1551,7 +1605,7 @@ 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;
}
@@ -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);
@@ -1626,6 +1679,7 @@ void CKeybindManager::toggleOpaque(std::string unused) {
return;
PWINDOW->m_sAdditionalConfigData.forceOpaque = !PWINDOW->m_sAdditionalConfigData.forceOpaque;
PWINDOW->m_sAdditionalConfigData.forceOpaqueOverriden = true;
g_pHyprRenderer->damageWindow(PWINDOW);
}
@@ -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);
@@ -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

@@ -33,7 +33,7 @@ enum eFocusWindowMode {
};
class CKeybindManager {
public:
public:
CKeybindManager();
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
@@ -51,8 +51,9 @@ public:
wl_event_source* m_pActiveKeybindEventSource = nullptr;
private:
std::list<SKeybind> m_lKeybinds;
private:
std::deque<xkb_keysym_t> m_dPressedKeysyms;
std::deque<int> m_dPressedKeycodes;
@@ -90,6 +91,7 @@ private:
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);

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();
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

@@ -7,7 +7,7 @@ int slowUpdate = 0;
int handleTimer(void* 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,7 +5,7 @@
#include "../Compositor.hpp"
class CThreadManager {
public:
public:
CThreadManager();
~CThreadManager();

View File

@@ -22,9 +22,7 @@ CHyprXWaylandManager::CHyprXWaylandManager() {
#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,12 +53,11 @@ 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) {
@@ -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,7 +138,8 @@ 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();
@@ -173,13 +166,18 @@ 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"] ||
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"])
{
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;
@@ -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,7 +4,7 @@
#include "../Window.hpp"
class CHyprXWaylandManager {
public:
public:
CHyprXWaylandManager();
~CHyprXWaylandManager();

View File

@@ -17,8 +17,9 @@ 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;
g_pInputManager->m_lIdleInhibitors.remove(*PINH);
@@ -26,8 +27,8 @@ void CInputManager::newIdleInhibitor(wlr_idle_inhibitor_v1* pInhibitor) {
Debug::log(LOG, "Destroyed an idleinhibitor");
g_pInputManager->recheckIdleInhibitorStatus();
}, PINHIBIT, "IdleInhibitor");
},
PINHIBIT, "IdleInhibitor");
PINHIBIT->pWindow = g_pCompositor->getWindowFromSurface(pInhibitor->surface);

View File

@@ -2,16 +2,18 @@
#include "../../Compositor.hpp"
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
static auto *const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
static auto *const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
static auto* const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
static auto* const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
static auto* const PSENSTORAW = &g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw")->intValue;
const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
if (*PSENSTORAW == 1)
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS, DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS);
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS,
DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS);
else
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy);
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y,
e->unaccel_dx, e->unaccel_dy);
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS);
@@ -29,11 +31,11 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
}
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
static auto *const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
static auto *const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
static auto *const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue;
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue;
m_pFoundSurfaceToFocus = nullptr;
m_pFoundLSToFocus = nullptr;
@@ -73,38 +75,40 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// XWayland windows sometimes issue constraints weirdly.
// TODO: We probably should search their parent. wlr_xwayland_surface->parent
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint);
if (!CONSTRAINTWINDOW) {
if (!CONSTRAINTWINDOW || !PCONSTRAINT) {
unconstrainMouse();
} else {
// Native Wayland apps know how 2 constrain themselves.
// XWayland, we just have to accept them. Might cause issues, but thats XWayland for ya.
const auto CONSTRAINTPOS = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->x, CONSTRAINTWINDOW->m_uSurface.xwayland->y) : CONSTRAINTWINDOW->m_vRealPosition.vec();
const auto CONSTRAINTSIZE = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->width, CONSTRAINTWINDOW->m_uSurface.xwayland->height) : CONSTRAINTWINDOW->m_vRealSize.vec();
const auto CONSTRAINTPOS =
CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->x, CONSTRAINTWINDOW->m_uSurface.xwayland->y) : CONSTRAINTWINDOW->m_vRealPosition.vec();
const auto CONSTRAINTSIZE = CONSTRAINTWINDOW->m_bIsX11 ? Vector2D(CONSTRAINTWINDOW->m_uSurface.xwayland->width, CONSTRAINTWINDOW->m_uSurface.xwayland->height) :
CONSTRAINTWINDOW->m_vRealSize.vec();
if (!VECINRECT(mouseCoords, CONSTRAINTPOS.x, CONSTRAINTPOS.y, CONSTRAINTPOS.x + CONSTRAINTSIZE.x - 1.0, CONSTRAINTPOS.y + CONSTRAINTSIZE.y - 1.0)) {
if (g_pCompositor->m_sSeat.mouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) {
// we just snap the cursor to where it should be.
Vector2D hint = {PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y};
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, CONSTRAINTPOS.x + hint.x, CONSTRAINTPOS.y + hint.y);
return; // don't process anything else, the cursor is locked. The surface should not receive any further events.
// these are usually FPS games. They will use the relative motion.
} else {
// we restrict the cursor to the confined region
if (!pixman_region32_contains_point(&PCONSTRAINT->constraint->region, mouseCoords.x - CONSTRAINTPOS.x, mouseCoords.y - CONSTRAINTPOS.y, nullptr)) {
if (g_pCompositor->m_sSeat.mouse->constraintActive) {
Vector2D newConstrainedCoords = mouseCoords;
if (mouseCoords.x < CONSTRAINTPOS.x)
newConstrainedCoords.x = CONSTRAINTPOS.x;
else if (mouseCoords.x >= CONSTRAINTPOS.x + CONSTRAINTSIZE.x)
newConstrainedCoords.x = CONSTRAINTPOS.x + CONSTRAINTSIZE.x - 1.0;
if (mouseCoords.y < CONSTRAINTPOS.y)
newConstrainedCoords.y = CONSTRAINTPOS.y;
else if (mouseCoords.y >= CONSTRAINTPOS.y + CONSTRAINTSIZE.y)
newConstrainedCoords.y = CONSTRAINTPOS.y + CONSTRAINTSIZE.y - 1.0;
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, newConstrainedCoords.x, newConstrainedCoords.y);
mouseCoords = newConstrainedCoords;
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, mouseCoords.x, mouseCoords.y);
mouseCoords = getMouseCoordsInternal();
}
} else {
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
g_pCompositor->m_sSeat.mouse->constraintActive = true;
}
}
}
if (CONSTRAINTWINDOW->m_bIsX11) {
foundSurface = g_pXWaylandManager->getWindowSurface(CONSTRAINTWINDOW);
@@ -123,15 +127,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal());
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor) {
g_pCompositor->m_pLastMonitor = PMONITOR;
g_pCompositor->setActiveMonitor(PMONITOR);
// set active workspace and deactivate all other in wlr
const auto ACTIVEWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
g_pCompositor->deactivateAllWLRWorkspaces(ACTIVEWORKSPACE->m_pWlrHandle);
ACTIVEWORKSPACE->setActive(true);
// event
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
}
// overlay is above fullscreen
@@ -155,7 +156,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden()) {
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) ||
(g_pCompositor->isWorkspaceSpecial((*w)->m_iWorkspaceID) && PMONITOR->specialWorkspaceID)) &&
wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden()) {
pFoundWindow = (*w).get();
break;
}
@@ -174,10 +177,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (!foundSurface) {
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
if (PMONITOR->specialWorkspaceOpen) {
if (PMONITOR->specialWorkspaceID) {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow && pFoundWindow->m_iWorkspaceID != SPECIAL_WORKSPACE_ID) {
if (pFoundWindow && !g_pCompositor->isWorkspaceSpecial(pFoundWindow->m_iWorkspaceID)) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
}
} else {
@@ -268,7 +271,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (pFoundWindow) {
if (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && ((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow &&
((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) {
// enter if change floating style
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
@@ -318,14 +322,9 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
m_tmrLastCursorMovement.reset();
switch (m_ecbClickBehavior) {
case CLICKMODE_DEFAULT:
processMouseDownNormal(e);
break;
case CLICKMODE_KILL:
processMouseDownKill(e);
break;
default:
break;
case CLICKMODE_DEFAULT: processMouseDownNormal(e); break;
case CLICKMODE_KILL: processMouseDownKill(e); break;
default: break;
}
}
@@ -375,23 +374,16 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
// set cursor
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
break;
default:
break;
default: break;
}
}
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!PKEYBOARD) { // ???
Debug::log(ERR, "No active keyboard in processMouseDownNormal??");
return;
}
// notify the keybind manager
static auto *const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
const auto PASS = g_pKeybindManager->onMouseEvent(e);
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
if (!PASS && !*PPASSMOUSE)
return;
@@ -409,8 +401,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
break;
case WLR_BUTTON_RELEASED:
break;
case WLR_BUTTON_RELEASED: break;
}
// notify app if we didnt handle it
@@ -422,7 +413,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
switch (e->state) {
case WLR_BUTTON_PRESSED: {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(getMouseCoordsInternal());
if (!PWINDOW) {
Debug::log(ERR, "Cannot kill invalid window!");
@@ -433,10 +424,8 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
kill(PWINDOW->getPID(), SIGKILL);
break;
}
case WLR_BUTTON_RELEASED:
break;
default:
break;
case WLR_BUTTON_RELEASED: break;
default: break;
}
// reset click behavior mode
@@ -444,7 +433,7 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
}
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
static auto *const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue;
static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue;
auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR);
@@ -453,8 +442,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
if (passEvent) {
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta,
std::round(factor * e->delta_discrete), e->source);
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source);
}
}
@@ -468,7 +456,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->keyboard = keyboard;
try {
PNEWKEYBOARD->name = std::string(keyboard->name);
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
@@ -477,12 +465,14 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(
&wlr_keyboard_from_input_device(keyboard)->events.keymap,
[&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
}, PNEWKEYBOARD, "Keyboard");
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
},
PNEWKEYBOARD, "Keyboard");
disableAllKeyboards(false);
@@ -504,7 +494,7 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->isVirtual = true;
try {
PNEWKEYBOARD->name = std::string(keyboard->name);
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
@@ -512,12 +502,14 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(
&wlr_keyboard_from_input_device(keyboard)->events.keymap,
[&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
}, PNEWKEYBOARD, "Keyboard");
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
},
PNEWKEYBOARD, "Keyboard");
disableAllKeyboards(true);
@@ -541,7 +533,6 @@ void CInputManager::setKeyboardLayout() {
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
auto devname = pKeyboard->name;
transform(devname.begin(), devname.end(), devname.begin(), ::tolower);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
@@ -564,8 +555,14 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto VARIANT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_variant") : g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_options") : g_pConfigManager->getString("input:kb_options");
const auto ENABLED = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "enabled") : true;
pKeyboard->enabled = ENABLED;
try {
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options && FILEPATH == pKeyboard->xkbFilePath) {
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" &&
RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout &&
VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options && FILEPATH == pKeyboard->xkbFilePath) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
@@ -581,12 +578,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
pKeyboard->numlockOn = NUMLOCKON;
pKeyboard->xkbFilePath = FILEPATH.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()};
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
pKeyboard->currentRules.rules = RULES;
pKeyboard->currentRules.model = MODEL;
@@ -601,9 +593,10 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
return;
}
Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model,
rules.options);
xkb_keymap * KEYMAP = NULL;
xkb_keymap* KEYMAP = NULL;
if (!FILEPATH.empty()) {
auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath);
@@ -620,9 +613,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
}
if (!KEYMAP) {
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )");
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
", layout: " + LAYOUT + " )");
Debug::log(ERR, "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, "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));
pKeyboard->currentRules.rules = "";
@@ -653,7 +648,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," +getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
}
@@ -665,15 +660,17 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
PMOUSE->mouse = mouse;
PMOUSE->virt = virt;
try {
PMOUSE->name = std::string(mouse->name);
} catch(std::exception& e) {
PMOUSE->name = getNameForNewDevice(mouse->name);
} catch (std::exception& e) {
Debug::log(ERR, "Mouse had no name???"); // logic error
}
if (wlr_input_device_is_libinput(mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
Debug::log(LOG, "New mouse has libinput sens %.2f (%.2f) with accel profile %i (%i)", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), libinput_device_config_accel_get_profile(LIBINPUTDEV), libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
Debug::log(LOG, "New mouse has libinput sens %.2f (%.2f) with accel profile %i (%i)", libinput_device_config_accel_get_speed(LIBINPUTDEV),
libinput_device_config_accel_get_default_speed(LIBINPUTDEV), libinput_device_config_accel_get_profile(LIBINPUTDEV),
libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
}
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
@@ -696,7 +693,6 @@ void CInputManager::setPointerConfigs() {
const auto PPOINTER = &m;
auto devname = PPOINTER->name;
transform(devname.begin(), devname.end(), devname.begin(), ::tolower);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
@@ -714,7 +710,8 @@ void CInputManager::setPointerConfigs() {
if (wlr_input_device_is_libinput(m.mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) == 0) // toggle software buttons or clickfinger
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) ==
0) // toggle software buttons or clickfinger
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
else
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
@@ -732,7 +729,7 @@ void CInputManager::setPointerConfigs() {
}
const auto SCROLLMETHOD = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "scroll_method") : g_pConfigManager->getString("input:scroll_method");
if (SCROLLMETHOD == "" || SCROLLMETHOD == STRVAL_EMPTY) {
if (SCROLLMETHOD == "") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, libinput_device_config_scroll_get_default_method(LIBINPUTDEV));
} else if (SCROLLMETHOD == "no_scroll") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
@@ -746,6 +743,11 @@ void CInputManager::setPointerConfigs() {
Debug::log(WARN, "Scroll method unknown");
}
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "tap-and-drag") : g_pConfigManager->getInt("input:touchpad:tap-and-drag")) == 0)
libinput_device_config_tap_set_drag_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_DISABLED);
else
libinput_device_config_tap_set_drag_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_ENABLED);
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0)
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
else
@@ -758,23 +760,28 @@ void CInputManager::setPointerConfigs() {
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
double w = 0, h = 0;
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
libinput_device_config_scroll_set_natural_scroll_enabled(
LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
else
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll")));
libinput_device_config_scroll_set_natural_scroll_enabled(
LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll")));
}
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
const auto DWT = static_cast<enum libinput_config_dwt_state>((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
const auto DWT = static_cast<enum libinput_config_dwt_state>(
(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
}
const auto LIBINPUTSENS = std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(devname, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
const auto LIBINPUTSENS =
std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(devname, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
const auto ACCELPROFILE = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "accel_profile") : g_pConfigManager->getString("input:accel_profile");
if (ACCELPROFILE == "" || ACCELPROFILE == STRVAL_EMPTY) {
if (ACCELPROFILE == "") {
libinput_device_config_accel_set_profile(LIBINPUTDEV, libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
} else if (ACCELPROFILE == "adaptive") {
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
@@ -784,6 +791,10 @@ void CInputManager::setPointerConfigs() {
Debug::log(WARN, "Unknown acceleration profile, falling back to default");
}
const auto SCROLLBUTTON = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "scroll_button") : g_pConfigManager->getInt("input:scroll_button");
libinput_device_config_scroll_set_button(LIBINPUTDEV, SCROLLBUTTON == 0 ? libinput_device_config_scroll_get_default_button(LIBINPUTDEV) : SCROLLBUTTON);
Debug::log(LOG, "Applied config to mouse %s, sens %.2f", m.name.c_str(), LIBINPUTSENS);
}
}
@@ -803,8 +814,7 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
} else {
m_pActiveKeyboard = nullptr;
}
}
} else
m_lKeyboards.remove(*pKeyboard);
}
@@ -822,7 +832,6 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) {
unconstrainMouse();
}
void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) {
auto keyboard = wlr_keyboard_from_input_device(pKeyboard);
@@ -832,8 +841,7 @@ void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) {
uint32_t leds = 0;
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
if (xkb_state_led_index_is_active(keyboard->xkb_state,
keyboard->led_indexes[i])) {
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) {
leds |= (1 << i);
}
}
@@ -846,8 +854,10 @@ void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) {
}
}
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
if (!pKeyboard->enabled)
return;
bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard);
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
@@ -869,6 +879,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
}
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
if (!pKeyboard->enabled)
return;
const auto PIMEGRAB = m_sIMERelay.getIMEKeyboardGrab(pKeyboard);
const auto ALLMODS = accumulateModsFromAllKBs();
@@ -896,7 +909,9 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
}
bool CInputManager::shouldIgnoreVirtualKeyboard(SKeyboard* pKeyboard) {
return !pKeyboard || (m_sIMERelay.m_pKeyboardGrab && wl_resource_get_client(m_sIMERelay.m_pKeyboardGrab->pWlrKbGrab->resource) == wl_resource_get_client(wlr_input_device_get_virtual_keyboard(pKeyboard->keyboard)->resource));
return !pKeyboard ||
(m_sIMERelay.m_pKeyboardGrab &&
wl_resource_get_client(m_sIMERelay.m_pKeyboardGrab->pWlrKbGrab->resource) == wl_resource_get_client(wlr_input_device_get_virtual_keyboard(pKeyboard->keyboard)->resource));
}
void CInputManager::refocus() {
@@ -908,16 +923,14 @@ void CInputManager::updateDragIcon() {
return;
switch (m_sDrag.dragIcon->drag->grab_type) {
case WLR_DRAG_GRAB_KEYBOARD:
break;
case WLR_DRAG_GRAB_KEYBOARD: break;
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
wlr_box box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
g_pHyprRenderer->damageBox(&box);
m_sDrag.pos = getMouseCoordsInternal();
break;
}
default:
break;
default: break;
}
}
@@ -936,7 +949,8 @@ void CInputManager::recheckConstraint(SMouse* pMouse) {
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
const auto PWINDOWNAME = PWINDOW ? PWINDOW->m_szTitle : "";
Debug::log(LOG, "Constraint rechecked: %i, %i to %i, %i for %x (window name: %s)", PREGION->extents.x1, PREGION->extents.y1, PREGION->extents.x2, PREGION->extents.y2, pMouse->currentConstraint->surface, PWINDOWNAME.c_str());
Debug::log(LOG, "Constraint rechecked: %i, %i to %i, %i for %x (window name: %s)", PREGION->extents.x1, PREGION->extents.y1, PREGION->extents.x2, PREGION->extents.y2,
pMouse->currentConstraint->surface, PWINDOWNAME.c_str());
}
void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* constraint) {
@@ -956,17 +970,23 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
if (PWINDOW) {
if (PWINDOW->m_bIsX11) {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PWINDOW->m_vRealPosition.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x,
PWINDOW->m_uSurface.xwayland->y + PWINDOW->m_vRealPosition.vec().y);
wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
} else {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x,
constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
}
}
const auto PCONSTRAINT = constraintFromWlr(constraint);
if (PCONSTRAINT) { // should never be null but who knows
PCONSTRAINT->positionHint = Vector2D(constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
PCONSTRAINT->hintSet = true;
}
}
}
@@ -1012,27 +1032,41 @@ void CInputManager::unconstrainMouse() {
}
void Events::listener_commitConstraint(void* owner, void* data) {
//g_pInputManager->recheckConstraint((SMouse*)owner);
}
const auto PMOUSE = (SMouse*)owner;
void CInputManager::updateCapabilities(wlr_input_device* pDev) {
// TODO: this is dumb
switch (pDev->type) {
case WLR_INPUT_DEVICE_KEYBOARD:
m_uiCapabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
break;
case WLR_INPUT_DEVICE_POINTER:
m_uiCapabilities |= WL_SEAT_CAPABILITY_POINTER;
break;
case WLR_INPUT_DEVICE_TOUCH:
m_uiCapabilities |= WL_SEAT_CAPABILITY_TOUCH;
break;
default:
break;
if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
const auto PCONSTRAINT = g_pInputManager->constraintFromWlr(PMOUSE->currentConstraint);
if (PCONSTRAINT) { // should never be null but who knows
PCONSTRAINT->positionHint = Vector2D(PMOUSE->currentConstraint->current.cursor_hint.x, PMOUSE->currentConstraint->current.cursor_hint.y);
PCONSTRAINT->hintSet = true;
}
}
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
if (pixman_region32_not_empty(&PMOUSE->currentConstraint->current.region)) {
pixman_region32_intersect(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region, &PMOUSE->currentConstraint->current.region);
} else {
pixman_region32_copy(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region);
}
g_pInputManager->recheckConstraint(PMOUSE);
}
}
void CInputManager::updateCapabilities() {
uint32_t caps = 0;
if (!m_lKeyboards.empty())
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
if (!m_lMice.empty())
caps |= WL_SEAT_CAPABILITY_POINTER;
if (!m_lTouchDevices.empty())
caps |= WL_SEAT_CAPABILITY_TOUCH;
if (!m_lTabletTools.empty())
caps |= WL_SEAT_CAPABILITY_POINTER;
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, caps);
m_uiCapabilities = caps;
}
uint32_t CInputManager::accumulateModsFromAllKBs() {
@@ -1043,6 +1077,9 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
if (kb.isVirtual && shouldIgnoreVirtualKeyboard(&kb))
continue;
if (!kb.enabled)
continue;
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
}
@@ -1083,8 +1120,8 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
PNEWDEV->pWlrDevice = pDevice;
try {
PNEWDEV->name = std::string(pDevice->name);
} catch(std::exception& e) {
PNEWDEV->name = getNameForNewDevice(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Touch Device had no name???"); // logic error
}
@@ -1093,62 +1130,41 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
Debug::log(LOG, "New touch device added at %x", PNEWDEV);
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
destroyTouchDevice((STouchDevice*)data);
}, PNEWDEV, "TouchDevice");
PNEWDEV->hyprListener_destroy.initCallback(
&pDevice->events.destroy, [&](void* owner, void* data) { destroyTouchDevice((STouchDevice*)data); }, PNEWDEV, "TouchDevice");
}
void CInputManager::setTouchDeviceConfigs() {
// The third row is always 0 0 1 and is not expected by `libinput_device_config_calibration_set_matrix`
static const float MATRICES[8][6] = {
{ // normal
1, 0, 0,
0, 1, 0
},
{ // rotation 90°
0, -1, 1,
1, 0, 0
},
{ // rotation 180°
-1, 0, 1,
0, -1, 1
},
{ // rotation 270°
0, 1, 0,
-1, 0, 1
},
{ // flipped
-1, 0, 1,
0, 1, 0
},
{ // flipped + rotation 90°
0, 1, 0,
1, 0, 0
},
{ // flipped + rotation 180°
1, 0, 0,
0, -1, 1
},
{ // flipped + rotation 270°
0, -1, 1,
-1, 0, 1
}
};
static const float MATRICES[8][6] = {{// normal
1, 0, 0, 0, 1, 0},
{// rotation 90°
0, -1, 1, 1, 0, 0},
{// rotation 180°
-1, 0, 1, 0, -1, 1},
{// rotation 270°
0, 1, 0, -1, 0, 1},
{// flipped
-1, 0, 1, 0, 1, 0},
{// flipped + rotation 90°
0, 1, 0, 1, 0, 0},
{// flipped + rotation 180°
1, 0, 0, 0, -1, 1},
{// flipped + rotation 270°
0, -1, 1, -1, 0, 1}};
for (auto& m : m_lTouchDevices) {
const auto PTOUCHDEV = &m;
auto devname = PTOUCHDEV->name;
transform(devname.begin(), devname.end(), devname.begin(), ::tolower);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PTOUCHDEV->name);
if (wlr_input_device_is_libinput(m.pWlrDevice)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.pWlrDevice);
const int ROTATION = std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "touch_transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7);
const int ROTATION =
std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7);
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "touch_output") : g_pConfigManager->getString("input:touchdevice:output");
const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output") : g_pConfigManager->getString("input:touchdevice:output");
if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY)
PTOUCHDEV->boundOutput = OUTPUT;
else
@@ -1157,6 +1173,22 @@ void CInputManager::setTouchDeviceConfigs() {
}
}
void CInputManager::setTabletConfigs() {
for (auto& t : m_lTablets) {
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(t.name);
if (HASCONFIG) {
const auto OUTPUT = g_pConfigManager->getDeviceString(t.name, "output");
const auto PMONITOR = g_pCompositor->getMonitorFromString(OUTPUT);
if (PMONITOR) {
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output);
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr);
}
}
}
}
void CInputManager::destroyTouchDevice(STouchDevice* pDevice) {
Debug::log(LOG, "Touch device at %x removed", pDevice);
@@ -1169,20 +1201,22 @@ void CInputManager::newSwitch(wlr_input_device* pDevice) {
Debug::log(LOG, "New switch with name \"%s\" added", pDevice->name);
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
destroySwitch((SSwitchDevice*)owner);
}, PNEWDEV, "SwitchDevice");
PNEWDEV->hyprListener_destroy.initCallback(
&pDevice->events.destroy, [&](void* owner, void* data) { destroySwitch((SSwitchDevice*)owner); }, PNEWDEV, "SwitchDevice");
const auto PSWITCH = wlr_switch_from_input_device(pDevice);
PNEWDEV->hyprListener_toggle.initCallback(&PSWITCH->events.toggle, [&](void* owner, void* data) {
PNEWDEV->hyprListener_toggle.initCallback(
&PSWITCH->events.toggle,
[&](void* owner, void* data) {
const auto PDEVICE = (SSwitchDevice*)owner;
const auto NAME = std::string(PDEVICE->pWlrDevice->name);
Debug::log(LOG, "Switch %s fired, triggering binds.", NAME.c_str());
g_pKeybindManager->onSwitchEvent(NAME);
}, PNEWDEV, "SwitchDevice");
},
PNEWDEV, "SwitchDevice");
}
void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
@@ -1202,3 +1236,50 @@ void CInputManager::unsetCursorImage() {
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide)
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
}
std::string CInputManager::deviceNameToInternalString(std::string in) {
std::replace(in.begin(), in.end(), ' ', '-');
std::transform(in.begin(), in.end(), in.begin(), ::tolower);
return in;
}
std::string CInputManager::getNameForNewDevice(std::string internalName) {
auto proposedNewName = deviceNameToInternalString(internalName);
int dupeno = 0;
while (std::find_if(m_lKeyboards.begin(), m_lKeyboards.end(),
[&](const SKeyboard& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lKeyboards.end())
dupeno++;
while (std::find_if(m_lMice.begin(), m_lMice.end(), [&](const SMouse& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) !=
m_lMice.end())
dupeno++;
while (std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(),
[&](const STouchDevice& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTouchDevices.end())
dupeno++;
while (std::find_if(m_lTabletPads.begin(), m_lTabletPads.end(),
[&](const STabletPad& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTabletPads.end())
dupeno++;
while (std::find_if(m_lTablets.begin(), m_lTablets.end(),
[&](const STablet& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTablets.end())
dupeno++;
while (std::find_if(m_lTabletTools.begin(), m_lTabletTools.end(),
[&](const STabletTool& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTabletTools.end())
dupeno++;
return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno)));
}
SConstraint* CInputManager::constraintFromWlr(wlr_pointer_constraint_v1* constraint) {
for (auto& c : m_lConstraints) {
if (c.constraint == constraint)
return &c;
}
return nullptr;
}

View File

@@ -7,12 +7,14 @@
#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_RESIZE
@@ -25,9 +27,10 @@ struct STouchData {
Vector2D touchSurfaceOrigin;
};
class CInputManager {
public:
class CKeybindManager;
class CInputManager {
public:
void onMouseMoved(wlr_pointer_motion_event*);
void onMouseWarp(wlr_pointer_motion_absolute_event*);
void onMouseButton(wlr_pointer_button_event*);
@@ -48,6 +51,7 @@ public:
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
void unconstrainMouse();
SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);
std::string getActiveLayoutForKeyboard(SKeyboard*);
Vector2D getMouseCoordsInternal();
@@ -56,9 +60,10 @@ public:
void setKeyboardLayout();
void setPointerConfigs();
void setTouchDeviceConfigs();
void setTabletConfigs();
void updateDragIcon();
void updateCapabilities(wlr_input_device*);
void updateCapabilities();
void setClickMode(eClickBehaviorMode);
eClickBehaviorMode getClickMode();
@@ -129,8 +134,10 @@ public:
void setCursorImageUntilUnset(std::string);
void unsetCursorImage();
private:
std::string deviceNameToInternalString(std::string);
std::string getNameForNewDevice(std::string);
private:
bool m_bCursorImageOverriden = false;
// for click behavior override
@@ -161,6 +168,8 @@ private:
// swipe
void beginWorkspaceSwipe();
friend class CKeybindManager;
};
inline std::unique_ptr<CInputManager> g_pInputManager;

View File

@@ -2,7 +2,7 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
CInputMethodRelay::CInputMethodRelay() { }
CInputMethodRelay::CInputMethodRelay() {}
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
if (m_pWLRIME) {
@@ -15,8 +15,9 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
m_pWLRIME = pIME;
hyprListener_IMECommit.initCallback(&m_pWLRIME->events.commit, [&](void* owner, void* data) {
hyprListener_IMECommit.initCallback(
&m_pWLRIME->events.commit,
[&](void* owner, void* data) {
const auto PTI = getFocusedTextInput();
const auto PIMR = (CInputMethodRelay*)owner;
@@ -26,7 +27,8 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
}
if (PIMR->m_pWLRIME->current.preedit.text) {
wlr_text_input_v3_send_preedit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.preedit.text, PIMR->m_pWLRIME->current.preedit.cursor_begin, PIMR->m_pWLRIME->current.preedit.cursor_end);
wlr_text_input_v3_send_preedit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.preedit.text, PIMR->m_pWLRIME->current.preedit.cursor_begin,
PIMR->m_pWLRIME->current.preedit.cursor_end);
}
if (PIMR->m_pWLRIME->current.commit_text) {
@@ -38,11 +40,12 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
}
wlr_text_input_v3_send_done(PTI->pWlrInput);
},
this, "IMERelay");
}, this, "IMERelay");
hyprListener_IMEDestroy.initCallback(&m_pWLRIME->events.destroy, [&](void* owner, void* data) {
hyprListener_IMEDestroy.initCallback(
&m_pWLRIME->events.destroy,
[&](void* owner, void* data) {
m_pWLRIME = nullptr;
hyprListener_IMEDestroy.removeCallback();
@@ -61,11 +64,12 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
wlr_text_input_v3_send_leave(PTI->pWlrInput);
}
},
this, "IMERelay");
}, this, "IMERelay");
hyprListener_IMEGrab.initCallback(&m_pWLRIME->events.grab_keyboard, [&](void* owner, void* data) {
hyprListener_IMEGrab.initCallback(
&m_pWLRIME->events.grab_keyboard,
[&](void* owner, void* data) {
Debug::log(LOG, "IME TextInput Keyboard Grab new");
m_pKeyboardGrab.reset(nullptr);
@@ -80,8 +84,9 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
wlr_input_method_keyboard_grab_v2_set_keyboard(m_pKeyboardGrab->pWlrKbGrab, m_pKeyboardGrab->pKeyboard);
m_pKeyboardGrab->hyprListener_grabDestroy.initCallback(&PKBGRAB->events.destroy, [&](void* owner, void* data) {
m_pKeyboardGrab->hyprListener_grabDestroy.initCallback(
&PKBGRAB->events.destroy,
[&](void* owner, void* data) {
m_pKeyboardGrab->hyprListener_grabDestroy.removeCallback();
Debug::log(LOG, "IME TextInput Keyboard Grab destroy");
@@ -91,13 +96,14 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
}
m_pKeyboardGrab.reset(nullptr);
},
m_pKeyboardGrab.get(), "IME Keyboard Grab");
},
this, "IMERelay");
}, m_pKeyboardGrab.get(), "IME Keyboard Grab");
}, this, "IMERelay");
hyprListener_IMENewPopup.initCallback(&m_pWLRIME->events.new_popup_surface, [&](void* owner, void* data) {
hyprListener_IMENewPopup.initCallback(
&m_pWLRIME->events.new_popup_surface,
[&](void* owner, void* data) {
const auto PNEWPOPUP = &m_lIMEPopups.emplace_back();
PNEWPOPUP->pSurface = (wlr_input_popup_surface_v2*)data;
@@ -108,8 +114,8 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
PNEWPOPUP->hyprListener_destroyPopup.initCallback(&PNEWPOPUP->pSurface->events.destroy, &Events::listener_destroyInputPopup, PNEWPOPUP, "IME Popup");
Debug::log(LOG, "New input popup");
}, this, "IMERelay");
},
this, "IMERelay");
const auto PTI = getFocusableTextInput();
@@ -296,8 +302,9 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
PTEXTINPUT->pWlrInput = pInput;
PTEXTINPUT->hyprListener_textInputEnable.initCallback(&pInput->events.enable, [](void* owner, void* data) {
PTEXTINPUT->hyprListener_textInputEnable.initCallback(
&pInput->events.enable,
[](void* owner, void* data) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
@@ -309,11 +316,12 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
wlr_input_method_v2_send_activate(g_pInputManager->m_sIMERelay.m_pWLRIME);
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
},
PTEXTINPUT, "textInput");
}, PTEXTINPUT, "textInput");
PTEXTINPUT->hyprListener_textInputCommit.initCallback(&pInput->events.commit, [](void* owner, void* data) {
PTEXTINPUT->hyprListener_textInputCommit.initCallback(
&pInput->events.commit,
[](void* owner, void* data) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
@@ -327,11 +335,12 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
}
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
},
PTEXTINPUT, "textInput");
}, PTEXTINPUT, "textInput");
PTEXTINPUT->hyprListener_textInputDisable.initCallback(&pInput->events.disable, [](void* owner, void* data) {
PTEXTINPUT->hyprListener_textInputDisable.initCallback(
&pInput->events.disable,
[](void* owner, void* data) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
@@ -344,11 +353,12 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME);
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
},
PTEXTINPUT, "textInput");
}, PTEXTINPUT, "textInput");
PTEXTINPUT->hyprListener_textInputDestroy.initCallback(&pInput->events.destroy, [](void* owner, void* data) {
PTEXTINPUT->hyprListener_textInputDestroy.initCallback(
&pInput->events.destroy,
[](void* owner, void* data) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
@@ -370,8 +380,8 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
PINPUT->hyprListener_textInputEnable.removeCallback();
g_pInputManager->m_sIMERelay.removeTextInput(PINPUT->pWlrInput);
}, PTEXTINPUT, "textInput");
},
PTEXTINPUT, "textInput");
}
void CInputMethodRelay::removeTextInput(wlr_text_input_v3* pInput) {
@@ -417,7 +427,6 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) {
} else {
continue;
}
}
if (pSurface && wl_resource_get_client(ti.pWlrInput->resource) == wl_resource_get_client(pSurface->resource)) {
@@ -427,7 +436,6 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) {
} else {
setPendingSurface(&ti, pSurface);
}
}
}
}
@@ -436,13 +444,16 @@ void CInputMethodRelay::setPendingSurface(STextInput* pInput, wlr_surface* pSurf
pInput->pPendingSurface = pSurface;
if (pSurface) {
pInput->hyprListener_pendingSurfaceDestroy.initCallback(&pSurface->events.destroy, [](void* owner, void* data) {
pInput->hyprListener_pendingSurfaceDestroy.initCallback(
&pSurface->events.destroy,
[](void* owner, void* data) {
const auto PINPUT = (STextInput*)owner;
PINPUT->pPendingSurface = nullptr;
PINPUT->hyprListener_pendingSurfaceDestroy.removeCallback();
}, pInput, "TextInput");
},
pInput, "TextInput");
} else {
pInput->hyprListener_pendingSurfaceDestroy.removeCallback();
}

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