Compare commits

..

295 Commits

Author SHA1 Message Date
vaxerski
d3c1d3435c fix typo in XDG popup callbacks 2022-07-26 22:45:59 +02:00
vaxerski
57f5de68ae remove commit event cuz i forgot 2022-07-26 22:01:55 +02:00
vaxerski
eb30d9bdc8 fix typo in LS destroy event 2022-07-26 21:59:07 +02:00
vaxerski
98ef43496b listener fixes 2022-07-26 21:41:29 +02:00
vaxerski
1455442b9a fix swipe not cancelling constraints 2022-07-26 18:38:30 +02:00
vaxerski
71c1ff8ee3 log xwayland in hyprctl 2022-07-26 18:25:08 +02:00
vaxerski
b18a2738e3 schedule recalcs in LS 2022-07-26 18:22:34 +02:00
vaxerski
99ebbb36b2 README stuff 2022-07-26 17:34:53 +02:00
vaxerski
6f2368f809 Add a pass dispatcher 2022-07-26 17:30:30 +02:00
vaxerski
7dc014e967 r and e exclusivity in bind 2022-07-26 17:04:26 +02:00
vaxerski
66eac124e2 add binding to mouse buttons 2022-07-26 14:50:21 +02:00
vaxerski
d04f36c57d set moz env 2022-07-26 10:05:29 +02:00
vaxerski
7babcf7e6a arrange after switch 2022-07-25 23:53:43 +02:00
vaxerski
b0d91cbf3a simplify formats 2022-07-25 22:40:34 +02:00
vaxerski
db899e00e7 adjust ls fading out logic 2022-07-25 22:00:46 +02:00
vaxerski
6e16dfa5e5 use defines for unreachable 2022-07-25 21:34:57 +02:00
vaxerski
c998e946aa Wrap adding to fading out
needed to avoid memory safety issues, because sometimes there would be duplicates.
2022-07-25 21:08:54 +02:00
vaxerski
cde39e0b6e ls fixes 2022-07-25 20:47:56 +02:00
vaxerski
b1d3a1deea force unmap on direct destroy 2022-07-25 18:38:40 +02:00
vaxerski
e2594c79cc fix fading out layers without unmap 2022-07-25 18:35:53 +02:00
vaxerski
a0be6e19d8 fix shadowing with doesntHave 2022-07-25 16:12:06 +02:00
vaxerski
14176f01ca fix swiping with one workspace on monitor 2022-07-25 15:42:27 +02:00
Vaxry
574d950145 updated previews in readme 2022-07-25 15:05:23 +02:00
vaxerski
bb539f0a8d added keybind repeat flag 2022-07-25 14:42:49 +02:00
vaxerski
067e2d39f6 shadow with respect of keysym on press 2022-07-25 14:24:02 +02:00
vaxerski
e388a86c9d move floating windows manually on moveworkspacetomonitor 2022-07-25 14:22:32 +02:00
vaxerski
3e6abaf680 fix some swipe issues 2022-07-25 14:06:49 +02:00
vaxerski
6dc8c4b310 Shadowing Keybinds fixes 2022-07-24 14:35:58 +02:00
vaxerski
1ddd7ee713 remove forced envvars 2022-07-24 13:29:46 +02:00
vaxerski
92d1d21a3d added default touchpad settings to example configs 2022-07-24 12:23:31 +02:00
vaxerski
8dcc3032a8 fix keybinds shadowing multibinds 2022-07-24 12:16:26 +02:00
vaxerski
1626707b7f make layerSurfaces into RAII 2022-07-23 15:48:08 +02:00
Mihai Fufezan
72700bf9dc layersurfaces: set default geometry 2022-07-22 20:28:43 +03:00
vaxerski
616ec22735 wrapped wl_listener fixes 2022-07-22 13:34:19 +02:00
vaxerski
d9b0edb786 remove newPopup handler for LS 2022-07-22 13:12:26 +02:00
vaxerski
3f169a937a fix wlr workspace names before init 2022-07-22 12:37:44 +02:00
vaxerski
fa1273f258 minor changes to swipes 2022-07-22 00:13:56 +02:00
vaxerski
8f66ddcad0 minor changes to swipes 2022-07-22 00:10:26 +02:00
vaxerski
4db1062af6 minor changes to swipes 2022-07-22 00:08:25 +02:00
vaxerski
0013ef9ef0 reload input after exec once 2022-07-21 20:30:48 +02:00
vaxerski
19cd04c85f shadow keybinds on drag events 2022-07-21 19:44:34 +02:00
Vaxry
a011c28227 Merge pull request #265 from xDarksome/main
Scroll workspaces with Super+MouseWheel
2022-07-21 19:40:15 +02:00
Darksome
d5ccca4fdb Consider scroll as a 'pressed' key 2022-07-21 20:31:38 +03:00
vaxerski
f512bf6b5a remove server from hyprctl as it's unused 2022-07-21 19:27:55 +02:00
Darksome
ce508f1cdc Fix merge 2022-07-21 19:48:34 +03:00
Darksome
eb8a1939e6 Merge upstream 2022-07-21 19:18:03 +03:00
Vaxry
7f660fed0d Merge pull request #404 from System-x64/new-hyprland.png
Updated assets/hyprland.png
2022-07-21 14:46:56 +02:00
vaxerski
75ce01b1a7 Make the thread manager into a wl event loop timer 2022-07-21 12:33:22 +02:00
Dikshant Namdeo
b9f8d900b3 updated-hyprland.png 2022-07-21 12:31:24 +05:30
vaxerski
189cbe9f09 added shadowing keybinds 2022-07-20 23:17:26 +02:00
vaxerski
fa2bd3b1a8 added keybinds on key up 2022-07-20 22:45:06 +02:00
vaxerski
fc33cae70c change bind flag parsing 2022-07-20 22:33:43 +02:00
vaxerski
641aaff998 minor code adjustments 2022-07-20 18:39:08 +02:00
vaxerski
9463e3eb0a fix transformed snapshots a bit 2022-07-20 16:28:05 +02:00
vaxerski
e6b151b6c3 fix memory read after free in damageSurface 2022-07-20 12:06:14 +02:00
vaxerski
d52446135b add sensitivity per device & reload mice on config 2022-07-19 19:26:53 +02:00
vaxerski
1ba600ca23 added workspace swipe fingers 2022-07-19 18:35:24 +02:00
vaxerski
0026414f9b fix workspace swipes mistake 2022-07-19 18:30:53 +02:00
vaxerski
ce8d655fad fix oopsie in log 2022-07-19 16:39:15 +02:00
vaxerski
d4690a5c5e minor change to unmanaged X11 geom requests 2022-07-19 16:38:27 +02:00
vaxerski
755245e752 adjust workspace on geom change x11 2022-07-19 16:21:35 +02:00
vaxerski
ec2afb563e fix oopsie include 2022-07-19 14:28:37 +02:00
vaxerski
59e34e311e fix oopsie include 2022-07-19 14:27:52 +02:00
vaxerski
c6c3d66373 fix hyprctl with relative negative 2022-07-19 14:24:03 +02:00
vaxerski
21217bcb2b notify enter on subsurfaces with follow mouse not 1 2022-07-19 14:05:12 +02:00
vaxerski
f905ae33c8 guard pSurface in unmapsubsurface 2022-07-19 13:54:42 +02:00
vaxerski
0281caa8e0 fix ASan error 2022-07-19 13:36:54 +02:00
Vaxry
f35d513bf5 Merge pull request #391 from dgerblick/focuswindow-options
focuswindow options + other hyprctl bugs I found when testing
2022-07-18 23:19:12 +02:00
vaxerski
10a83853ac added ls noprocess 2022-07-18 21:16:01 +02:00
vaxerski
53b8263eb1 remove fixXwaylandwindowsonworkspace, not needed anymore 2022-07-18 21:15:46 +02:00
vaxerski
8bcfda2230 update moveactivetoworkspace logic 2022-07-18 20:53:29 +02:00
Daniel Gerblick
f2c0e6ef02 fixed issue causing hyprctl to output ill-formed json when strings include characters needing escaping 2022-07-18 14:47:28 -04:00
vaxerski
b669948737 fix logo center 2022-07-18 15:41:02 +02:00
vaxerski
a4b1d51c63 add new wallpapers 2022-07-18 15:31:59 +02:00
vaxerski
e7b8cda360 update logo 2022-07-18 15:23:26 +02:00
vaxerski
c466bd1219 fix webkit 2022-07-18 14:21:21 +02:00
vaxerski
ad19a15cef readme center 2022-07-18 14:20:43 +02:00
vaxerski
954a387cf9 fix center 2022-07-18 14:19:21 +02:00
vaxerski
a51f44d566 readme fix 2022-07-18 14:16:49 +02:00
vaxerski
423c9f9d56 new logo 2022-07-18 14:15:33 +02:00
vaxerski
900e6947e9 reject windows with tiny sizes, overwrite size 2022-07-18 13:14:31 +02:00
vaxerski
90d07d7b52 fix shadows on unmanaged and noborder 2022-07-18 12:39:57 +02:00
vaxerski
60cc33a53c added time logging 2022-07-18 11:46:42 +02:00
Daniel Gerblick
dc1f34c5fa added PID and address-based options for focuswindow, as well as updated hyprctl clients to be consistent with logs and hyprctl activewindow 2022-07-17 19:00:12 -04:00
vaxerski
afeb040684 fix selection events 2022-07-17 18:56:01 +02:00
vaxerski
f5bd30569f fix borders on scaled 2022-07-16 23:29:42 +02:00
vaxerski
6f1b9d6af9 add master:new_on_top 2022-07-16 23:24:42 +02:00
vaxerski
1848086abd reload layout on hyprctl layout 2022-07-16 22:44:29 +02:00
vaxerski
cb2989cec5 fix fade corner artifacts 2022-07-16 21:10:16 +02:00
vaxerski
16afa2c422 fix border rendering on certain windows
oversized subsurfaces had a tendency to be above borders, now they wont be
2022-07-16 20:57:59 +02:00
vaxerski
edcecae7a0 dont cycle on fullscreen 2022-07-16 19:55:40 +02:00
vaxerski
aac546b771 added center windowrule 2022-07-16 16:27:17 +02:00
vaxerski
ef24329495 pass through pinch events 2022-07-16 16:12:31 +02:00
vaxerski
5c836e6460 added master layout 2022-07-16 15:57:31 +02:00
Darksome
68cfc1a496 Merge branch 'main' of github.com:xDarksome/Hyprland 2022-07-16 15:35:47 +03:00
Darksome
08319dd1f5 Fix handleKeybinds debug log 2022-07-16 15:34:13 +03:00
xDarksome
4f9be67298 Merge branch 'hyprwm:main' into main 2022-07-16 15:30:32 +03:00
Darksome
ce9efb7ae3 Impl changeworkspace(e+{n}) 2022-07-16 15:28:17 +03:00
vaxerski
48e5bd96bc Added shadow colors animations and inactive col 2022-07-16 12:44:45 +02:00
Darksome
2ae088d631 Use correct wlroots commit 2022-07-16 12:47:37 +03:00
Darksome
fdbc54d97b Restore events/Devices.cpp formatting 2022-07-16 12:44:12 +03:00
Darksome
e56ff0fcb0 Merge remote-tracking branch 'upstream/main' into mouse-wheel-cfg 2022-07-16 12:40:02 +03:00
Darksome
43b7da0bb1 Rollback flake.lock 2022-07-16 12:30:07 +03:00
vaxerski
b2650928ea obey xdg reqs better 2022-07-16 00:11:21 +02:00
Vaxry
069e3b2114 Merge pull request #376 from dgerblick/hyprctl-json-segfault-fix
Fixed SEGFAULT when running hyprctl with only the -j option
2022-07-15 23:21:46 +02:00
Daniel Gerblick
db693ec7e5 Fixed SEGFAULT when running hyprctl with only the -j option 2022-07-15 15:39:39 -04:00
xDarksome
16fecac2d1 [gha] bump flake inputs 2022-07-15 18:55:08 +00:00
Darksome
1eceae811f Try mouse wheel configuration 2022-07-15 21:54:05 +03:00
vaxerski
fbcc6936f4 fix dashes in hyprctl 2022-07-15 20:07:52 +02:00
vaxerski
90ebeaa881 fixed fullscreen opacity on fullscreen 1 2022-07-15 19:33:09 +02:00
vaxerski
1441856811 fix blur on oversized, default to enabled 2022-07-15 19:21:13 +02:00
vaxerski
19c646ab47 Minor changes to the renderer's overflow behavior
Won't squish base layers anymore
2022-07-15 19:07:06 +02:00
Darksome
5388b54442 Merge upstream 2022-07-15 19:42:03 +03:00
vaxerski
6306d4dae3 add remove, to blurls 2022-07-15 13:29:56 +02:00
Vaxry
5af26a451a Merge pull request #373 from fufexan/configpath
Add config flag
2022-07-15 12:03:50 +02:00
vaxerski
ba48e7ceea fixed up hyprctl flags 2022-07-15 11:58:09 +02:00
vaxerski
c0377457df don't poison wlr in make install 2022-07-15 11:39:11 +02:00
Mihai Fufezan
202fb4d8d4 add clangd cache in gitignore 2022-07-15 00:10:00 +03:00
Mihai Fufezan
d8fee02063 add simple help message 2022-07-15 00:09:31 +03:00
Mihai Fufezan
01fc3d6068 add config flag
you can now specify a config with -c <path>
2022-07-14 23:55:24 +03:00
vaxerski
634970a284 update deco values on fullscreen 2022-07-14 22:49:49 +02:00
vaxerski
642af5395e dont focus anything on constrained 2022-07-14 21:33:36 +02:00
Vaxry
316589406f Merge pull request #372 from bazuin-32/main
Fix error when running `hyprctl dispatch exec` with an arg that contains a `/`
2022-07-14 19:33:21 +02:00
bazuin-32
0085319c18 Fix error when running hyprctl dispatch exec with an arg that contains
a `/`
2022-07-14 11:23:18 -06:00
vaxerski
0488f17976 fix opacity inactive methodology 2022-07-14 18:46:42 +02:00
vaxerski
8b52858bb5 fix opacity active 2022-07-14 18:45:16 +02:00
Vaxry
b0dd370421 Merge pull request #342 from viperML/main
ci: add release workflow
2022-07-14 12:54:49 +02:00
vaxerski
65e75c0b44 fix backwards hyprctl compat 2022-07-14 11:43:15 +02:00
Vaxry
7c999fb9f5 Merge pull request #242 from calebowens/caleb-feature-add-width-multiplier
Added a multiplier for the width to height ratio
2022-07-14 11:38:49 +02:00
Kainoa Kanter
21da348826 hyprwm in readme links 2022-07-13 11:23:43 -07:00
vaxerski
c2215e4efb fix focus on fullscreen and over 2022-07-13 18:33:36 +02:00
vaxerski
49dbb586e3 fixed session-less envs 2022-07-13 18:31:09 +02:00
Vaxry
6708f3b133 Fixed TTY switching (#364) 2022-07-13 18:18:23 +02:00
vaxerski
ef7ee2fd0f added active keymap prop 2022-07-13 16:02:14 +02:00
vaxerski
e93b45615c better doc in help 2022-07-13 15:50:46 +02:00
vaxerski
0a16513946 fix warning 2022-07-13 15:48:47 +02:00
vaxerski
99e9503732 flag pos 2022-07-13 15:47:35 +02:00
Vaxry
be69098cb8 Merge pull request #360 from bazuin-32/main
Add hyprctl output in json when `-j` flag is used
2022-07-13 15:44:59 +02:00
Fernando Ayats
d7d5b1a4eb ci: fix repo source 2022-07-13 10:39:57 +02:00
Fernando Ayats
868fc6e0f3 Revert "FIXME: temp disable workflows"
This reverts commit 532ffe1681.
2022-07-13 10:36:47 +02:00
Fernando Ayats
9580ef4bc2 ci: upload source 2022-07-13 10:35:23 +02:00
Fernando Ayats
532ffe1681 FIXME: temp disable workflows 2022-07-13 10:26:11 +02:00
Fernando Ayats
0cfc97972f ci: upload source 2022-07-13 10:25:21 +02:00
bazuin-32
ab859ec9fc Fix issues with batch requests 2022-07-12 16:34:28 -06:00
bazuin-32
ac9ff795cd Fix calls to substr with invalid pos 2022-07-12 15:38:50 -06:00
vaxerski
4bea3467e0 update hyprctl help 2022-07-12 23:21:00 +02:00
vaxerski
bca93f4d3c code styling 2022-07-12 23:17:55 +02:00
vaxerski
bf762f566f Fix VRAM memory leak when releasing snapshots 2022-07-12 23:11:34 +02:00
bazuin-32
2402f2e364 Use enum for specifying hyprctl output format and change the way flags
are passed for json output
2022-07-12 14:59:36 -06:00
bazuin-32
036f431206 Add hyprctl output in json when -j flag is used 2022-07-12 11:57:33 -06:00
Mihai Fufezan
f9985a36b3 nix & meson: 0.6.2 -> 0.7.0 2022-07-12 20:12:59 +03:00
vaxerski
ad03360665 fix device sections shadowing parse errors 2022-07-12 16:07:51 +02:00
vaxerski
3914672dd5 mention more config options in cfgs 2022-07-12 15:41:42 +02:00
vaxerski
78c6371743 default vfr to off 2022-07-12 15:41:28 +02:00
Vaxry
f789a14527 updated issue guidelines 2022-07-12 15:35:23 +02:00
vaxerski
b1e3430405 only set xwayland size/pos on reasonable deltas 2022-07-12 14:14:12 +02:00
vaxerski
a4f82491b7 active opacity is now animated 2022-07-12 13:40:55 +02:00
Mathias Zhang
da83ef7b96 add config drag_lock for touchpad (#353)
* add config drag_lock for touchpad

* fix err

* Update ConfigManager.cpp
2022-07-12 13:11:54 +02:00
vaxerski
2d856ac4b0 Added yes/no values to int parsing 2022-07-12 10:28:42 +02:00
vaxerski
29e2bb27f6 added misc:no_vfr 2022-07-12 10:02:12 +02:00
vaxerski
2f3b2db83d fixed tiled popups going behind windows 2022-07-12 09:49:56 +02:00
vaxerski
bf8bd87d11 added active monitor to hyprctl monitors 2022-07-12 00:16:28 +02:00
vaxerski
c0c75db621 roll VFR for everyone 2022-07-11 23:56:24 +02:00
vaxerski
f461ea3105 squish oversized subsurfaces while animating 2022-07-11 23:38:10 +02:00
vaxerski
668dc9bd9c [gha] bump flake inputs 2022-07-11 21:11:07 +00:00
vaxerski
b55b6c95f2 update wlroots dep 2022-07-11 23:09:35 +02:00
vaxerski
676e4c36c5 fix focus on layers when constrained 2022-07-11 22:51:20 +02:00
vaxerski
ad66c158ba don't refocus on virt ptrs 2022-07-11 20:23:16 +02:00
vaxerski
ab44aabbd7 update decos on setgeometry x11 2022-07-11 19:07:59 +02:00
vaxerski
4c4c36096b fix config reload on fullscreen mode maximized 2022-07-11 15:40:41 +02:00
vaxerski
c923b0e538 respect size in setgeo unmanaged x11 2022-07-11 15:31:31 +02:00
vaxerski
2936368e80 minor event fixes 2022-07-11 14:13:15 +02:00
vaxerski
5eaf93697a clear kb focus on focusSurface null 2022-07-11 12:29:50 +02:00
vaxerski
11c88e2503 apply surface width to ls geo on commit 2022-07-10 20:36:32 +02:00
vaxerski
4b334594dc Added splashes 2022-07-10 15:41:26 +02:00
vaxerski
06c0be5ea6 clear with 17 2022-07-10 11:45:50 +02:00
vaxerski
6f7377f381 accumulate mods from all kbs for keybind processing 2022-07-09 23:24:08 +02:00
vaxerski
c44cafda97 added cyclenext param previous 2022-07-09 18:39:41 +02:00
vaxerski
ddc4cbbd7e allow focus to modal 2022-07-08 23:37:55 +02:00
vaxerski
e6872bddf4 fix minor issues with floating windows and fullscreen 2022-07-08 21:52:52 +02:00
Mihai Fufezan
a7a3c0fc1d nix: add devShell 2022-07-08 18:34:23 +03:00
Fernando Ayats
c8c5e0b90a nix: fix wallpaper location (#334) 2022-07-08 17:46:42 +03:00
vaxerski
8482063157 fixed layersurface focus quirks 2022-07-08 13:19:57 +02:00
vaxerski
92e17f2925 added rules to hyprctl devices and fixed rules 2022-07-08 12:27:05 +02:00
vaxerski
491b99c61e handle unmanaged X11 setGeometry 2022-07-08 11:24:07 +02:00
vaxerski
75a580feda Disallow focus to modal and override_redirect X11 windows 2022-07-08 10:36:21 +02:00
vaxerski
91249675de fix corner artifacts 2022-07-08 09:43:55 +02:00
vaxerski
46306e59eb added keycode support to unbind 2022-07-08 09:32:09 +02:00
vaxerski
cd0a01f4de Added binding by keycodes 2022-07-08 09:27:17 +02:00
vaxerski
75c2a378e3 unfocus keyboard on refocus null 2022-07-07 21:47:59 +02:00
vaxerski
96f19d706a fix possible swipe crash 2022-07-07 20:53:22 +02:00
vaxerski
3278db67a2 added general:disable_hyprland_logo 2022-07-07 20:16:40 +02:00
vaxerski
aa3bc65342 fix special status when workspace is changed 2022-07-07 19:16:16 +02:00
vaxerski
a7b595d968 allow windowrule special again 2022-07-07 19:01:42 +02:00
vaxerski
05736bc1e3 I am an idiot, fixed special ws deletion 2022-07-07 19:00:34 +02:00
vaxerski
3bf172a37e fix hyprerror on scaled outputs 2022-07-07 18:45:01 +02:00
vaxerski
22c4ecf496 fixed swiping with one ws 2022-07-07 13:57:26 +02:00
Vaxry
3f43f94dc4 Merge pull request #318 from hyprwm/swipes
Added swipe workspace gestures
2022-07-07 13:49:43 +02:00
vaxerski
4b796d30c1 Added swipe workspace gestures 2022-07-07 13:49:04 +02:00
vaxerski
5762e3b9e2 fix stretched ls 2022-07-07 12:40:32 +02:00
vaxerski
1cf2f378d4 added ls blurring 2022-07-06 22:12:03 +02:00
vaxerski
6a16f11d63 add namespace to hyprctl layers 2022-07-06 21:57:35 +02:00
vaxerski
a545992891 fixed hyprctl layers crash 2022-07-06 21:57:15 +02:00
Mihai Fufezan
f5936f97d6 nix: use gcc12Stdenv 2022-07-06 18:41:20 +03:00
vaxerski
141f9810bb fix meson C++23 2022-07-06 17:02:12 +02:00
vaxerski
1599dc47d1 set proper C++23 std to meson as well 2022-07-06 16:55:49 +02:00
vaxerski
42d18143e5 use std::unreachable in avars 2022-07-06 16:54:45 +02:00
vaxerski
f9756d10d4 changed C++ std to C++23, use std::string::contains 2022-07-06 16:50:11 +02:00
vaxerski
0d7a8cca79 use C++ throw methods instead of printf and exit 2022-07-06 16:17:58 +02:00
vaxerski
9655d0c138 added support for wlr_idle_inhibitor_v1 2022-07-06 15:42:37 +02:00
vaxerski
5a22335b8d refocus after group toggles 2022-07-06 15:08:21 +02:00
vaxerski
0277f4c6bd support relative paths in source= 2022-07-06 15:05:23 +02:00
vaxerski
8d05dddb98 fix focus on maximized windows with special open 2022-07-06 14:58:46 +02:00
vaxerski
0d54451c67 fix incorrect mouse pos in fullscreen xdg 2022-07-06 11:12:27 +02:00
vaxerski
cda0c4577e find floating special windows in vector methods 2022-07-06 11:07:23 +02:00
vaxerski
239aa2cec4 fix internal workspace changes being clamped 2022-07-06 11:02:21 +02:00
vaxerski
ae096219e8 do updates on every mon update if VFR is enabled 2022-07-05 21:45:32 +02:00
vaxerski
7ff427c229 remove wlroots so in make uninstall 2022-07-05 19:46:05 +02:00
vaxerski
55aeb91e6a use provided wlroots, don't find system 2022-07-05 19:36:28 +02:00
vaxerski
6f5b8425cb fix invalidating the deque in CHyprGroupBarDeco 2022-07-05 17:31:47 +02:00
vaxerski
dd422abb33 schedule frames at the end of avar loop 2022-07-05 16:05:06 +02:00
vaxerski
cc8b8f595f disallow workspace special windowrule 2022-07-04 19:58:51 +02:00
vaxerski
9742ac7596 attempt to fix a specialworkspace crash 2022-07-04 19:41:55 +02:00
vaxerski
beef23cee5 fix vfr frame scheduling 2022-07-04 17:55:33 +02:00
vaxerski
7e38de37a7 fix crash 2022-07-04 17:48:04 +02:00
vaxerski
e0bfec6ef2 added experimental:vfr 2022-07-04 17:47:31 +02:00
vaxerski
c40ef59a35 support monitor names in moving workspaces 2022-07-04 16:51:42 +02:00
vaxerski
c71b76a9e0 fix chromium part 1 2022-07-04 15:58:12 +02:00
vaxerski
853a33888b fix issue with special workspace rules 2022-07-04 12:03:09 +02:00
vaxerski
fc3957d538 optimize workspace in applyNodeData 2022-07-04 00:04:56 +02:00
vaxerski
3df126c675 oops 2022-07-03 23:17:12 +02:00
vaxerski
69e179816b oops last fix didnt fix 2022-07-03 23:16:42 +02:00
vaxerski
a229701f28 fix crash with null pmonitor in special nodes on dwindle 2022-07-03 23:14:51 +02:00
vaxerski
01228fbc9c fix some bugs 2022-07-03 22:54:47 +02:00
vaxerski
f7c4865bac warp size and pos before rule fullscreen 2022-07-03 21:38:39 +02:00
Mihai Fufezan
0a01ec9926 Fix non-focused windows on WS change
Fixes #298
2022-07-03 15:51:32 +03:00
xDarksome
e0f0ed9af4 Don't use pkgs.hyprland package in the nix module (#299)
Users who use the overlay: see wiki for fixing your config if it broke.
2022-07-03 15:28:10 +03:00
vaxerski
e81de82706 added Vector2D::clamp 2022-07-02 22:17:17 +02:00
vaxerski
9d6999345e don't process new focus when cursor constrained 2022-07-02 20:06:10 +02:00
Darksome
cb8a6f881b Disallow scrolling into empty workspaces 2022-07-02 19:55:35 +03:00
xDarksome
185c4d6ea1 Merge branch 'hyprwm:main' into main 2022-07-02 19:43:52 +03:00
vaxerski
b7b3344188 hyprctl: added support for hyprpaper 2022-07-02 18:27:44 +02:00
Mihai Fufezan
80962de2a2 PR Template: add headers 2022-07-02 16:37:19 +03:00
Mihai Fufezan
9ee14eb445 meson: build with -O3 (#291) 2022-07-02 02:48:21 +03:00
vaxerski
e77f451e27 minor oopsie 2022-07-01 22:49:12 +02:00
vaxerski
6f4f164071 don't focus layers without keyboard_interactive 2022-07-01 20:14:33 +02:00
Vaxry
3d294b1aaa Merge pull request #292 from Dakes/focus-window-title
Changed dispatcher: focusWindowByClass -> focusWindow. Now supports titles & classes
2022-07-01 18:20:10 +02:00
vaxerski
7d7e82d446 only do mouseMoveUnified on pix change 2022-07-01 17:59:11 +02:00
Dakes
2225dca576 Add focusWindow dispatcher. Takes titles & classes
Removed focusWindowByClass function, replaced with focusWindow.
Either takes a class matching regex, or a title matching one,
beginning with "title:"
Kept the focuswindowbyclass dispatcher identifier to stay backwards
compatible with existing configs.
2022-07-01 16:24:37 +02:00
vaxerski
868e0f48d0 added debug:disable_logs 2022-07-01 15:57:56 +02:00
vaxerski
1750a7cdbb oops 2022-07-01 11:54:52 +02:00
vaxerski
6f2a36c123 limit events on socket2 to 1024 chars 2022-07-01 10:37:17 +02:00
vaxerski
29ca7f9018 bring back O3 2022-07-01 10:37:07 +02:00
vaxerski
91d68513de fix possible segfault by realloc 2022-06-30 23:55:28 +02:00
vaxerski
3970b43ea2 fix disabling monitor while hyprland is running 2022-06-30 23:50:57 +02:00
vaxerski
92890d492a fallback on unset device config var 2022-06-30 21:38:06 +02:00
vaxerski
d010ca2049 added per-device config options 2022-06-30 21:26:00 +02:00
vaxerski
4510764f34 finally fix scaled snapshots 2022-06-30 20:02:04 +02:00
vaxerski
96a23eca81 calculate damage properly for layers on commit
since the damageSurface func now works, we can remove this old remnant
2022-06-30 18:46:00 +02:00
Vaxry
ac8a23c3ae Merge pull request #281 from hyprwm/modernize-pointers
Modernize pointers (optimization)
2022-06-30 18:20:00 +02:00
vaxerski
990d3f232b fix another crash 2022-06-30 16:11:26 +02:00
vaxerski
97b515edb7 fix crash 2022-06-30 16:00:44 +02:00
vaxerski
328b3fa4bc mordernize pointers 2022-06-30 15:44:26 +02:00
vaxerski
d1564299d2 fix minor bug with new anim optimization 2022-06-30 13:11:10 +02:00
vaxerski
cfc1f6c211 optimize animationmanager 2022-06-30 12:54:58 +02:00
vaxerski
a7ebf0ddc3 added CPU uniform location lookup optimization 2022-06-30 12:39:10 +02:00
vaxerski
4101006b5e remove asserts in CAnimatedVariable 2022-06-30 12:22:24 +02:00
vaxerski
b0cd90a43c refactor a bunch of layout code 2022-06-30 12:09:05 +02:00
vaxerski
ae3ff6736e hyprctl monitors changes 2022-06-29 23:33:51 +02:00
vaxerski
7d20d5c8c3 fix make clear wlroots 2022-06-29 23:06:45 +02:00
vaxerski
6ce2678970 fix snapshot scaling issue 2022-06-29 22:26:34 +02:00
vaxerski
d28151d255 added foreign support 2022-06-29 22:23:51 +02:00
Mihai Fufezan
be390dacfd Merge pull request #274 from fufexan/nix-stuff
nix: add debug package and waybar with -Dexperimental flag
2022-06-29 20:57:18 +03:00
Mihai Fufezan
dc83110c05 nix & meson: 0.6.0 -> 0.6.2 2022-06-29 20:50:33 +03:00
Mihai Fufezan
cbf3595e96 nix: add debug package and waybar with -Dexperimental flag 2022-06-29 20:50:27 +03:00
vaxerski
2659afee3c force workspace events 2022-06-29 18:19:06 +02:00
vaxerski
9391357063 fix focus on maximize 2022-06-29 14:44:24 +02:00
vaxerski
6ec16fdcda damage drag and drop 2022-06-29 14:15:08 +02:00
vaxerski
208864cba9 include build/include in CMakeLists 2022-06-29 13:49:53 +02:00
vaxerski
bbc3b5e19b added make fixwlr 2022-06-29 13:30:28 +02:00
vaxerski
697ce96d62 temp fix for snapshot size on scaled 2022-06-29 13:08:28 +02:00
vaxerski
31a1b3b192 allow init logs to be saved 2022-06-29 12:58:49 +02:00
vaxerski
8820f7f210 optimization + revert one oopsie 2022-06-29 12:54:53 +02:00
vaxerski
73663a8ba5 fix incorrect snapshot calc for scaled outputs 2022-06-29 12:36:50 +02:00
vaxerski
13acfb1c30 fix disabling in animationmanager 2022-06-29 12:06:09 +02:00
vaxerski
37abe0aedc added debug:damage_blink 2022-06-29 11:44:00 +02:00
vaxerski
5636d2031e simplify damageWindow 2022-06-29 11:21:42 +02:00
vaxerski
9388bb5d55 fix shadows on scaled 2022-06-29 11:13:30 +02:00
xDarksome
fc4b10d13c Remove empty line 2022-06-26 19:28:30 +03:00
xDarksome
504f76112a Merge branch 'hyprwm:main' into main 2022-06-26 19:20:20 +03:00
xDarksome
be460ea954 Merge branch 'hyprwm:main' into main 2022-06-24 18:58:11 +03:00
Darksome
776ca3baf2 Change workspace wheel scrolling direction 2022-06-24 18:57:14 +03:00
Darksome
8f62f6d4b0 Add workspace switching with mouse wheel 2022-06-20 22:47:28 +03:00
Caleb Owens
7d80327e7d fixed vertical swapping issue 2022-06-20 17:11:59 +01:00
Caleb Owens
3d46c73981 Added a multiplier for the width to height ratio 2022-06-20 14:37:27 +01:00
90 changed files with 4602 additions and 1563 deletions

View File

@@ -1,9 +1,9 @@
Describe your PR, what does it fix/add?
#### Describe your PR, what does it fix/add?
Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
#### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
Is it ready for merging, or does it need work?
#### Is it ready for merging, or does it need work?

38
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Release artifacts
on:
release:
types: [published]
workflow_dispatch:
jobs:
source-tarball:
runs-on: ubuntu-latest
steps:
- name: Checkout Hyprland
id: checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Create tarball with submodules
id: tar
run: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
- id: whatrelease
name: Get latest release
uses: pozetroninc/github-action-get-latest-release@master
with:
owner: hyprwm
repo: Hyprland
excludes: prerelease, draft
- name: Upload to release
id: upload
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: source.tar.gz
asset_name: source-${{ steps.whatrelease.outputs.release }}.tar.gz
tag: ${{ steps.whatrelease.outputs.release }}
overwrite: true

2
.gitignore vendored
View File

@@ -12,6 +12,8 @@ _deps
build/
result
/.vscode/
.envrc
.cache
*.o
*-protocol.c

View File

@@ -36,12 +36,13 @@ execute_process(
#
include_directories(. PRIVATE "subprojects/wlroots/include/")
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
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 wlroots libinput xcb)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -61,7 +62,7 @@ IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake!")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
# add_compile_options(-O3) # may crash for some
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake!")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
@@ -79,7 +80,7 @@ include(CPack)
target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland
wlroots
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us
pixman-1
OpenGL
GLESv2

View File

@@ -99,7 +99,7 @@ clear:
rm -rf build
rm -f *.o *-protocol.h *-protocol.c
rm -f ./hyprctl/hyprctl
rm -rf ./wlroots/build
rm -rf ./subprojects/wlroots/build
all:
make config
@@ -107,11 +107,13 @@ all:
cd ./hyprctl && make all && cd ..
install:
[ ! -d /usr/include/wlr ] || mv /usr/include/wlr /usr/include/wlrBackup
[ ! -f /usr/lib/libwlroots.so ] || mv /usr/lib/libwlroots.so /usr/lib/libwlroots.so.backup
[ ! -f /usr/lib/pkgconfig/wlroots.pc ] || mv /usr/lib/pkgconfig/wlroots.pc /usr/lib/pkgconfig/wlroots.pc.backup
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../..
make protocols
make release
cd hyprctl && make all && cd ..
make all
mkdir -p ${PREFIX}/share/wayland-sessions
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
mkdir -p ${PREFIX}/bin
@@ -122,28 +124,26 @@ install:
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
rm -rf /usr/include/wlr
rm -f /usr/lib/libwlroots.so
rm -f /usr/lib/pkgconfig/wlroots.pc
[ ! -d /usr/include/wlrBackup ] || mv /usr/include/wlrBackup /usr/include/wlr
[ ! -f /usr/lib/libwlroots.so.backup ] || mv -f /usr/lib/libwlroots.so.backup /usr/lib/libwlroots.so
[ ! -f /usr/lib/pkgconfig/wlroots.pc.backup ] || mv -f /usr/lib/pkgconfig/wlroots.pc.backup /usr/lib/pkgconfig/wlroots.pc
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland
rm -f ${PREFIX}/bin/hyprctl
rm -f /usr/lib/libwlroots.so.11032
rm -rf ${PREFIX}/share/hyprland
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
config:
make protocols
fixwlr:
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
rm -rf ./subprojects/wlroots/build
config:
make protocols
make fixwlr
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
cd subprojects/wlroots && ninja -C build/

View File

@@ -1,6 +1,6 @@
<div align = center>
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="1000" height="500" alt="banner">
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
<br>
@@ -57,6 +57,7 @@ Try it out and report bugs / suggestions!
- Drop shadows
- Fully dynamic workspaces
- Closely follows `wlroots-git`
- Global keybinds passed to your apps of choice
- Bundled wlroots
- Window/layer fade in/out
- Tiling/pseudotiling/floating/fullscreen windows
@@ -69,6 +70,7 @@ Try it out and report bugs / suggestions!
- Full damage tracking
- Docks support
- Drawing tablet support
- and much more...
<br>
<br>
@@ -122,18 +124,18 @@ Try it out and report bugs / suggestions!
<!----------------------------------------------------------------------------->
[Configure]: https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland
[Configure]: https://github.com/hyprwm/Hyprland/wiki/Configuring-Hyprland
[Discord]: https://discord.gg/hQ9XvMUjjr
[Stars]: https://starchart.cc/vaxerski/Hyprland
[Hypr]: https://github.com/vaxerski/Hypr
[Stars]: https://starchart.cc/hyprwm/Hyprland
[Hypr]: https://github.com/hyprwm/Hypr
[Pull Requests]: https://github.com/vaxerski/Hyprland/pulls
[Issues]: https://github.com/vaxerski/Hyprland/issues
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
[Pull Requests]: https://github.com/hyprwm/Hyprland/pulls
[Issues]: https://github.com/hyprwm/Hyprland/issues
[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
[Contribute]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
[Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
[Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
[Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
[License]: LICENSE
@@ -149,19 +151,19 @@ Try it out and report bugs / suggestions!
<!----------------------------------{ Images }--------------------------------->
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
[Preview A]: https://i.imgur.com/NbrTnZH.png
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
[Preview C]: https://i.imgur.com/BpXxM8H.png
[Preview A]: https://i.imgur.com/sCafdKQ.png
[Preview B]: https://i.imgur.com/NbrTnZH.png
[Preview C]: https://i.imgur.com/ZA4Fa8R.png
<!----------------------------------{ Badges }--------------------------------->
[Badge Workflow]: https://github.com/vaxerski/Hyprland/actions/workflows/ci.yaml/badge.svg
[Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg
[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
[Badge Issues]: https://img.shields.io/github/issues/vaxerski/Hyprland
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/vaxerski/Hyprland
[Badge Language]: https://img.shields.io/github/languages/top/vaxerski/Hyprland
[Badge License]: https://img.shields.io/github/license/vaxerski/Hyprland
[Badge Lines]: https://img.shields.io/tokei/lines/github/vaxerski/Hyprland
[Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
[Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
[Badge License]: https://img.shields.io/github/license/hyprwm/Hyprland
[Badge Lines]: https://img.shields.io/tokei/lines/github/hyprwm/Hyprland
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 798 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 KiB

After

Width:  |  Height:  |  Size: 146 KiB

View File

@@ -26,6 +26,7 @@ If your bug is one that doesn't crash Hyprland, but feels like invalid behavior,
If your bug crashes Hyprland, append additionally:
- The Hyprland log
- Coredump / Coredump analysis (with a stacktrace)
- Your config
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.

View File

@@ -3,6 +3,11 @@
#
# Refer to the wiki for more information.
#
# Please note not all available settings / options are set here.
# For a full list, see the wiki (basic and advanced configuring)
#
monitor=,1280x720@60,0x0,1
workspace=DP-1,1
@@ -14,6 +19,10 @@ input {
kb_rules=
follow_mouse=1
touchpad {
natural_scroll=no
}
}
general {
@@ -97,3 +106,6 @@ bind=ALT,7,movetoworkspace,7
bind=ALT,8,movetoworkspace,8
bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1656239181,
"narHash": "sha256-wW1xRFBn376yGloXZ4QzBE4hjipMawpV18Lshd9QSPw=",
"lastModified": 1657447684,
"narHash": "sha256-FCP9AuU1q6PE3vOeM5SFf58f/UKPBAsoSGDUGamNBbo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5",
"rev": "5f43d8b088d3771274bcfb69d3c7435b1121ac88",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1655824477,
"narHash": "sha256-1kskHOLsnisR3kqIL5IHrQbQG/4xoXxeEf1ExMV6/RU=",
"lastModified": 1656865312,
"narHash": "sha256-xtQ0zwJZwN8sciruveM10CzKz6TWxBY8SyXa8E4jly4=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "5c4384a1330faedf975c8b8644881d50390f3613",
"rev": "5dc1d4671dd2ca3c1f0f09587c463fdbb542f0a4",
"type": "gitlab"
},
"original": {

View File

@@ -32,9 +32,14 @@
src = inputs.wlroots;
});
hyprland = prev.callPackage ./nix/default.nix {
version = "0.6.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
stdenv = prev.gcc12Stdenv;
version = "0.7.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
});
};
packages = genSystems (system:
@@ -43,6 +48,16 @@
default = self.packages.${system}.hyprland;
});
devShells = genSystems (system: {
default = pkgsFor.${system}.mkShell.override {stdenv = pkgsFor.${system}.gcc12Stdenv;} {
name = "hyprland-shell";
inputsFrom = [
self.packages.${system}.wlroots-hyprland
self.packages.${system}.hyprland
];
};
});
formatter = genSystems (system: pkgsFor.${system}.alejandra);
nixosModules.default = import ./nix/module.nix self;

View File

@@ -1,4 +1,4 @@
all:
g++ -std=c++20 ./main.cpp -o ./hyprctl
g++ -std=c++23 ./main.cpp -o ./hyprctl
clean:
rm ./hyprctl
rm ./hyprctl

View File

@@ -9,14 +9,18 @@
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <ranges>
#include <algorithm>
#include <iostream>
#include <string>
#include <fstream>
#include <string>
#include <deque>
const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
commands:
monitors
workspaces
clients
@@ -27,7 +31,13 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
keyword
version
kill
reload)#";
splash
hyprpaper
reload
flags:
j -> output in JSON
)#";
void request(std::string arg) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -75,7 +85,58 @@ void request(std::string arg) {
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET,buffer, 8192);
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
return;
}
close(SERVERSOCKET);
std::cout << std::string(buffer);
}
void requestHyprpaper(std::string arg) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
if (SERVERSOCKET < 0) {
std::cout << "Couldn't open a socket (1)";
return;
}
// get the instance signature
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!instanceSig) {
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
return;
}
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
strcpy(serverAddress.sun_path, socketPath.c_str());
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
std::cout << "Couldn't connect to " << socketPath << ". (3)";
return;
}
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
if (sizeWritten < 0) {
std::cout << "Couldn't write (4)";
return;
}
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
@@ -94,7 +155,7 @@ void dispatchRequest(int argc, char** argv) {
return;
}
std::string rq = "dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
std::string rq = "/dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
request(rq);
}
@@ -110,12 +171,36 @@ void keywordRequest(int argc, char** argv) {
request(rq);
}
void batchRequest(int argc, char** argv) {
std::string rq = "[[BATCH]]" + std::string(argv[2]);
void hyprpaperRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "hyprpaper requires 2 params";
return;
}
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
requestHyprpaper(rq);
}
void batchRequest(std::string arg) {
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
request(rq);
}
std::deque<std::string> splitArgs(int argc, char** argv) {
std::deque<std::string> result;
for (auto i = 1 /* skip the executable */; i < argc; ++i)
result.push_back(std::string(argv[i]));
return result;
}
bool isNumber(const std::string& str, bool allowfloat) {
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
}
int main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c;
@@ -124,19 +209,52 @@ int main(int argc, char** argv) {
return 1;
}
if (!strcmp(argv[1], "monitors")) request("monitors");
else if (!strcmp(argv[1], "clients")) request("clients");
else if (!strcmp(argv[1], "workspaces")) request("workspaces");
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
else if (!strcmp(argv[1], "layers")) request("layers");
else if (!strcmp(argv[1], "version")) request("version");
else if (!strcmp(argv[1], "kill")) request("kill");
else if (!strcmp(argv[1], "devices")) request("devices");
else if (!strcmp(argv[1], "reload")) request("reload");
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
std::string fullRequest = "";
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
for (auto i = 0; i < ARGS.size(); ++i) {
if (ARGS[i][0] == '-' && !isNumber(ARGS[i], true) /* For stuff like -2 */) {
// parse
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
fullArgs += "j";
} else if (ARGS[i] == "--batch") {
fullRequest = "--batch ";
} else {
printf("%s\n", USAGE.c_str());
return 1;
}
continue;
}
fullRequest += ARGS[i] + " ";
}
if (fullRequest.empty()) {
printf("%s\n", USAGE.c_str());
return 1;
}
fullRequest.pop_back(); // remove trailing space
fullRequest = fullArgs + "/" + fullRequest;
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("/dispatch")) dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) 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,6 +1,17 @@
project('Hyprland', 'cpp', 'c',
version : '0.6.0beta',
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
version : '0.7.0beta',
default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
add_global_arguments('-std=c++23', language: 'cpp')
add_project_arguments(
[
'-Wno-unused-parameter',
'-Wno-unused-value',
'-Wno-missing-field-initializers',
'-Wno-narrowing',
],
language: 'cpp')
wlroots = subproject('wlroots', default_options: ['examples=false'])
have_xwlr = wlroots.get_variable('features').get('xwayland')

View File

@@ -20,9 +20,10 @@
xwayland,
enableXWayland ? true,
version ? "git",
debug ? false,
}:
stdenv.mkDerivation {
pname = "hyprland";
pname = "hyprland" + lib.optionalString debug "-debug";
inherit version;
src = ../.;
@@ -48,7 +49,10 @@ stdenv.mkDerivation {
]
++ lib.optional enableXWayland xwayland;
mesonBuildType = "release";
mesonBuildType =
if debug
then "debug"
else "release";
mesonFlags = lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
@@ -57,6 +61,11 @@ stdenv.mkDerivation {
./meson-build.patch
];
# Fix hardcoded paths to /usr installation
postPatch = ''
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
'';
passthru.providedSessions = ["hyprland"];
meta = with lib; {

View File

@@ -19,7 +19,7 @@ in {
package = mkOption {
type = types.package;
default = pkgs.hyprland or self.packages.${pkgs.system}.default;
default = self.packages.${pkgs.system}.default;
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
description = ''

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,9 @@ public:
// ------------------ WLR BASICS ------------------ //
wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
@@ -60,22 +62,27 @@ public:
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
// ------------------------------------------------- //
const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
std::list<SMonitor> m_lMonitors;
std::list<CWindow> m_lWindows;
std::list<SXDGPopup> m_lXDGPopups;
std::list<CWorkspace> m_lWorkspaces;
std::list<SSubsurface> m_lSubsurfaces;
std::list<CWindow*> m_lWindowsFadingOut;
std::list<SLayerSurface*> m_lSurfacesFadingOut;
std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor();
void cleanupExit();
void cleanup();
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
@@ -84,6 +91,7 @@ public:
SSeat m_sSeat;
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
// ------------------------------------------------- //
@@ -97,9 +105,9 @@ public:
bool windowExists(CWindow*);
bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor();
@@ -111,6 +119,7 @@ public:
CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
void fixXWaylandWindowsOnWorkspace(const int&);
@@ -118,24 +127,34 @@ public:
bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*);
void moveWindowToTop(CWindow*);
void cleanupFadingOut();
void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*);
CWindow* getPrevWindowOnWorkspace(CWindow*);
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
SMonitor* getMonitorInDirection(const char&);
void updateAllWindowsBorders();
void updateWindowBorderColor(CWindow*);
void updateAllWindowsAnimatedDecorationValues();
void updateWindowAnimatedDecorationValues(CWindow*);
void moveWindowToWorkspace(CWindow*, const std::string&);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
void scheduleFrameForMonitor(SMonitor*);
void addToFadingOutSafe(SLayerSurface*);
void addToFadingOutSafe(CWindow*);
CWindow* getWindowByRegex(const std::string&);
std::string explicitConfigPath;
private:
void initAllSignals();
void setRandomSplash();
};

View File

@@ -7,6 +7,8 @@ CWindow::CWindow() {
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_cRealShadowColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_SHADOW);
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
}
@@ -77,6 +79,18 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
void CWindow::updateWindowDecos() {
for (auto& wd : m_dWindowDecorations)
wd->updateWindow(this);
for (auto& wd : m_vDecosToRemove) {
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
if (it->get() == wd) {
it = m_dWindowDecorations.erase(it);
if (it == m_dWindowDecorations.end())
break;
}
}
}
m_vDecosToRemove.clear();
}
pid_t CWindow::getPID() {
@@ -90,3 +104,12 @@ pid_t CWindow::getPID() {
return PID;
}
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
for (auto& wd : m_dWindowDecorations) {
if (wd->getDecorationType() == type)
return wd.get();
}
return nullptr;
}

View File

@@ -28,8 +28,13 @@ public:
DYNLISTENER(unmapWindow);
DYNLISTENER(destroyWindow);
DYNLISTENER(setTitleWindow);
DYNLISTENER(setGeometryX11U);
DYNLISTENER(fullscreenWindow);
DYNLISTENER(newPopupXDG);
DYNLISTENER(requestMove);
DYNLISTENER(requestMinimize);
DYNLISTENER(requestMaximize);
DYNLISTENER(requestResize);
// DYNLISTENER(newSubsurfaceWindow);
union {
@@ -67,6 +72,7 @@ public:
// XWayland stuff
bool m_bIsX11 = false;
bool m_bMappedX11 = false;
CWindow* m_pX11Parent = nullptr;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false;
@@ -98,11 +104,18 @@ public:
// Window decorations
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
// Special render data, rules, etc
SWindowSpecialRenderData m_sSpecialRenderData;
SWindowAdditionalConfigData m_sAdditionalConfigData;
// for alpha
CAnimatedVariable m_fActiveInactiveAlpha;
// animated shadow color
CAnimatedVariable m_cRealShadowColor;
// 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;
@@ -113,5 +126,6 @@ public:
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos();
pid_t getPID();
IHyprWindowDecoration* getDecorationByType(eDecorationType);
};

View File

@@ -12,9 +12,19 @@
CConfigManager::CConfigManager() {
setDefaultVars();
static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
std::string CONFIGPATH;
if (g_pCompositor->explicitConfigPath == "") {
static const char* const ENVHOME = getenv("HOME");
CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
} else {
CONFIGPATH = g_pCompositor->explicitConfigPath;
}
configPaths.emplace_back(CONFIGPATH);
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
Debug::disableTime = &configValues["debug:disable_time"].intValue;
}
void CConfigManager::setDefaultVars() {
@@ -35,9 +45,18 @@ void CConfigManager::setDefaultVars() {
configValues["general:col.inactive_border"].intValue = 0xff444444;
configValues["general:cursor_inactive_timeout"].intValue = 0;
configValues["general:layout"].strValue = "dwindle";
configValues["misc:disable_hyprland_logo"].intValue = 0;
configValues["misc:disable_splash_rendering"].intValue = 0;
configValues["misc:no_vfr"].intValue = 1;
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
configValues["debug:overlay"].intValue = 0;
configValues["debug:damage_blink"].intValue = 0;
configValues["debug:disable_logs"].intValue = 0;
configValues["debug:disable_time"].intValue = 1;
configValues["decoration:rounding"].intValue = 1;
configValues["decoration:blur"].intValue = 1;
@@ -48,13 +67,14 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1;
configValues["decoration:multisample_edges"].intValue = 1;
configValues["decoration:no_blur_on_oversized"].intValue = 1;
configValues["decoration:no_blur_on_oversized"].intValue = 0;
configValues["decoration:drop_shadow"].intValue = 1;
configValues["decoration:shadow_range"].intValue = 4;
configValues["decoration:shadow_render_power"].intValue = 3;
configValues["decoration:shadow_ignore_window"].intValue = 1;
configValues["decoration:shadow_offset"].strValue = "0 0";
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
configValues["dwindle:pseudotile"].intValue = 0;
configValues["dwindle:col.group_border"].intValue = 0x66777700;
@@ -62,6 +82,11 @@ void CConfigManager::setDefaultVars() {
configValues["dwindle:force_split"].intValue = 0;
configValues["dwindle:preserve_split"].intValue = 0;
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
configValues["master:special_scale_factor"].floatValue = 0.8f;
configValues["master:new_is_master"].intValue = 1;
configValues["master:new_on_top"].intValue = 0;
configValues["animations:enabled"].intValue = 1;
configValues["animations:speed"].floatValue = 7.f;
@@ -83,6 +108,7 @@ void CConfigManager::setDefaultVars() {
configValues["animations:workspaces_speed"].floatValue = 0.f;
configValues["animations:workspaces"].intValue = 1;
configValues["input:sensitivity"].floatValue = 0.f;
configValues["input:kb_layout"].strValue = "us";
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
@@ -98,12 +124,42 @@ void CConfigManager::setDefaultVars() {
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:drag_lock"].intValue = 0;
configValues["binds:pass_mouse_when_bound"].intValue = 1;
configValues["gestures:workspace_swipe"].intValue = 0;
configValues["gestures:workspace_swipe_fingers"].intValue = 3;
configValues["gestures:workspace_swipe_distance"].intValue = 300;
configValues["gestures:workspace_swipe_invert"].intValue = 1;
configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30;
configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
configValues["input:follow_mouse"].intValue = 1;
configValues["autogenerated"].intValue = 0;
}
void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
auto& cfgValues = deviceConfigs[dev];
cfgValues["sensitivity"].floatValue = 0.f;
cfgValues["kb_layout"].strValue = "us";
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
cfgValues["kb_options"].strValue = STRVAL_EMPTY;
cfgValues["kb_rules"].strValue = STRVAL_EMPTY;
cfgValues["kb_model"].strValue = STRVAL_EMPTY;
cfgValues["repeat_rate"].intValue = 25;
cfgValues["repeat_delay"].intValue = 600;
cfgValues["natural_scroll"].intValue = 0;
cfgValues["numlock_by_default"].intValue = 0;
cfgValues["disable_while_typing"].intValue = 1;
cfgValues["clickfinger_behavior"].intValue = 0;
cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1;
cfgValues["drag_lock"].intValue = 0;
}
void CConfigManager::init() {
loadConfigLoadVars();
@@ -125,41 +181,69 @@ void CConfigManager::init() {
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
if (configValues.find(COMMAND) == configValues.end()) {
if (COMMAND[0] == '$') {
// register a dynamic var
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
configDynamicVars[COMMAND.substr(1)] = VALUE;
} else {
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
}
if (COMMAND.find("device:") != 0 /* devices parsed later */) {
if (COMMAND[0] == '$') {
// register a dynamic var
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
configDynamicVars[COMMAND.substr(1)] = VALUE;
} else {
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
}
return;
return;
}
}
SConfigValue* CONFIGENTRY = nullptr;
auto& CONFIGENTRY = configValues.at(COMMAND);
if (CONFIGENTRY.intValue != -1) {
if (COMMAND.find("device:") == 0) {
const auto DEVICE = COMMAND.substr(7).substr(0, COMMAND.find_last_of(':') - 7);
const auto CONFIGVAR = COMMAND.substr(COMMAND.find_last_of(':') + 1);
if (!deviceConfigExists(DEVICE))
setDeviceDefaultVars(DEVICE);
auto it = deviceConfigs.find(DEVICE);
if (it->second.find(CONFIGVAR) == it->second.end()) {
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
return;
}
CONFIGENTRY = &it->second.at(CONFIGVAR);
} else {
CONFIGENTRY = &configValues.at(COMMAND);
}
CONFIGENTRY->set = true;
if (CONFIGENTRY->intValue != -1) {
try {
if (VALUE.find("0x") == 0) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY.intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
} else
CONFIGENTRY.intValue = stol(VALUE);
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
} else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
CONFIGENTRY->intValue = 1;
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
CONFIGENTRY->intValue = 0;
}
else
CONFIGENTRY->intValue = stol(VALUE);
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY.floatValue != -1) {
} else if (CONFIGENTRY->floatValue != -1) {
try {
CONFIGENTRY.floatValue = stof(VALUE);
CONFIGENTRY->floatValue = stof(VALUE);
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY.strValue != "") {
} else if (CONFIGENTRY->strValue != "") {
try {
CONFIGENTRY.strValue = VALUE;
CONFIGENTRY->strValue = VALUE;
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
@@ -307,7 +391,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@')));
if (curitem.find_first_of('@') != std::string::npos)
if (curitem.contains("@"))
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
nextItem();
@@ -424,9 +508,33 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
configSetValueSafe("animations:" + ANIMNAME + "_style", curitem);
}
void CConfigManager::handleBind(const std::string& command, const std::string& value, bool locked) {
void CConfigManager::handleBind(const std::string& command, const std::string& value) {
// example:
// bind=SUPER,G,exec,dmenu_run <args>
// bind[fl]=SUPER,G,exec,dmenu_run <args>
// flags
bool locked = false;
bool release = false;
bool repeat = false;
const auto ARGS = command.substr(4);
for (auto& arg : ARGS) {
if (arg == 'l') {
locked = true;
} else if (arg == 'r') {
release = true;
} else if (arg == 'e') {
repeat = true;
} else {
parseError = "bind: invalid flag";
return;
}
}
if (release && repeat) {
parseError = "flags r and e are mutually exclusive";
return;
}
auto valueCopy = value;
@@ -456,8 +564,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
return;
}
if (KEY != "")
g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
if (KEY != "") {
if (isNumber(KEY) && std::stoi(KEY) > 9)
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
else
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
}
}
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
@@ -490,6 +603,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
&& RULE.find("monitor") != 0
&& RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "center"
&& RULE != "fullscreen"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
@@ -503,6 +617,16 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
}
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
if (value.find("remove,") == 0) {
const auto TOREMOVE = value.substr(7);
m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
return;
}
m_dBlurLSNamespaces.emplace_back(value);
}
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
const auto DISPLAY = value.substr(0, value.find_first_of(','));
@@ -528,6 +652,23 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
auto value = rawpath;
if (value.length() < 2) {
Debug::log(ERR, "source= path garbage");
parseError = "source path " + value + " bogus!";
return;
}
if (value[0] == '.') {
auto currentDir = configCurrentPath.substr(0, configCurrentPath.find_last_of('/'));
if (value[1] == '.') {
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
value.replace(0, 2, parentDir);
} else {
value.replace(0, 1, currentDir);
}
}
if (value[0] == '~') {
value.replace(0, 1, std::string(ENVHOME));
}
@@ -595,8 +736,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
}
}
else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE);
else if (COMMAND == "bind") handleBind(COMMAND, VALUE);
else if (COMMAND == "bindl") handleBind(COMMAND, VALUE, true);
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);
@@ -604,6 +744,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
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
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
@@ -612,11 +753,11 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
parseError = "";
// invalidate layouts jic
for (auto& m : g_pCompositor->m_lMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update window border colors
g_pCompositor->updateAllWindowsBorders();
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return retval;
}
@@ -656,7 +797,7 @@ void CConfigManager::parseLine(std::string& line) {
line = line.substr(1);
}
if (line.find(" {") != std::string::npos) {
if (line.contains(" {")) {
auto cat = line.substr(0, line.find(" {"));
transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
if (currentCategory.length() != 0) {
@@ -670,7 +811,7 @@ void CConfigManager::parseLine(std::string& line) {
return;
}
if (line.find("}") != std::string::npos && currentCategory != "") {
if (line.contains("}") && currentCategory != "") {
currentCategory = "";
return;
}
@@ -705,32 +846,43 @@ void CConfigManager::loadConfigLoadVars() {
g_pAnimationManager->removeAllBeziers();
m_mAdditionalReservedAreas.clear();
configDynamicVars.clear();
deviceConfigs.clear();
m_dBlurLSNamespaces.clear();
// paths
configPaths.clear();
std::string CONFIGPATH;
static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
const std::string CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
if (g_pCompositor->explicitConfigPath == "") {
CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
} else {
CONFIGPATH = g_pCompositor->explicitConfigPath;
}
configPaths.push_back(CONFIGPATH);
std::ifstream ifs;
ifs.open(CONFIGPATH);
if (!ifs.good()) {
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 */}
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 */}
try {
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
std::filesystem::create_directories(CONFIGPARENTPATH);
}
catch (...) {
parseError = "Broken config file! (Could not create directory)";
return;
try {
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
std::filesystem::create_directories(CONFIGPARENTPATH);
}
catch (...) {
parseError = "Broken config file! (Could not create directory)";
return;
}
}
std::ofstream ofs;
@@ -773,12 +925,14 @@ void CConfigManager::loadConfigLoadVars() {
ifs.close();
}
for (auto& m : g_pCompositor->m_lMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update the keyboard layout to the cfg'd one if this is not the first launch
if (!isFirstLaunch)
if (!isFirstLaunch) {
g_pInputManager->setKeyboardLayout();
g_pInputManager->setMouseConfigs();
}
// Calculate the internal vars
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
@@ -806,11 +960,14 @@ void CConfigManager::loadConfigLoadVars() {
}
// Update window border colors
g_pCompositor->updateAllWindowsBorders();
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
// update layout
g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue);
// Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_lMonitors)
m.forceFullFrames = 2;
for (auto& m : g_pCompositor->m_vMonitors)
m->forceFullFrames = 2;
}
void CConfigManager::tick() {
@@ -848,7 +1005,7 @@ void CConfigManager::tick() {
}
std::mutex configmtx;
SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
SConfigValue copy = configValues[val];
@@ -856,15 +1013,38 @@ SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
return copy;
}
int CConfigManager::getInt(std::string v) {
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
const auto it = deviceConfigs.find(dev);
if (it == deviceConfigs.end()) {
return SConfigValue();
}
SConfigValue copy = it->second[val];
// fallback if not set explicitly
if (!copy.set) {
for (auto& cv : configValues) {
if (cv.first.find(val) == cv.first.length() - val.length()) {
copy = cv.second;
}
}
}
return copy;
}
int CConfigManager::getInt(const std::string& v) {
return getConfigValueSafe(v).intValue;
}
float CConfigManager::getFloat(std::string v) {
float CConfigManager::getFloat(const std::string& v) {
return getConfigValueSafe(v).floatValue;
}
std::string CConfigManager::getString(std::string v) {
std::string CConfigManager::getString(const std::string& v) {
const auto VAL = getConfigValueSafe(v).strValue;
if (VAL == STRVAL_EMPTY)
@@ -873,6 +1053,23 @@ std::string CConfigManager::getString(std::string v) {
return VAL;
}
int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v) {
return getConfigValueSafeDevice(dev, v).intValue;
}
float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v) {
return getConfigValueSafeDevice(dev, v).floatValue;
}
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v) {
const auto VAL = getConfigValueSafeDevice(dev, v).strValue;
if (VAL == STRVAL_EMPTY)
return "";
return VAL;
}
void CConfigManager::setInt(std::string v, int val) {
configValues[v].intValue = val;
}
@@ -966,17 +1163,51 @@ void CConfigManager::dispatchExecOnce() {
}
firstExecRequests.clear(); // free some kb of memory :P
// set input, fixes some certain issues
g_pInputManager->setKeyboardLayout();
g_pInputManager->setMouseConfigs();
// set ws names again
for (auto& ws : g_pCompositor->m_vWorkspaces) {
wlr_ext_workspace_handle_v1_set_name(ws->m_pWlrHandle, ws->m_szName.c_str());
}
}
void CConfigManager::performMonitorReload() {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule);
bool overAgain = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto rule = getMonitorRuleFor(m->szName);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
overAgain = true;
break;
}
}
if (overAgain)
performMonitorReload();
m_bWantsMonitorReload = false;
}
SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
return &configValues[val];
}
bool CConfigManager::deviceConfigExists(const std::string& dev) {
const auto it = deviceConfigs.find(dev);
return it != deviceConfigs.end();
}
bool CConfigManager::shouldBlurLS(const std::string& ns) {
for (auto& bls : m_dBlurLSNamespaces) {
if (bls == ns) {
return true;
}
}
return false;
}

View File

@@ -20,6 +20,8 @@ struct SConfigValue {
int64_t intValue = -1;
float floatValue = -1;
std::string strValue = "";
bool set = false; // used for device configs
};
struct SMonitorRule {
@@ -52,13 +54,19 @@ public:
void tick();
void init();
int getInt(std::string);
float getFloat(std::string);
std::string getString(std::string);
int getInt(const std::string&);
float getFloat(const std::string&);
std::string getString(const std::string&);
void setFloat(std::string, float);
void setInt(std::string, int);
void setString(std::string, std::string);
int getDeviceInt(const std::string&, const std::string&);
float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&);
bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(std::string);
SMonitorRule getMonitorRuleFor(std::string);
@@ -81,6 +89,7 @@ private:
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues;
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
std::string configCurrentPath;
@@ -94,21 +103,25 @@ private:
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWindowRule> m_dWindowRules;
std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false;
std::deque<std::string> firstExecRequests;
// internal methods
void setDefaultVars();
void setDeviceDefaultVars(const std::string&);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();
SConfigValue getConfigValueSafe(std::string);
SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
void parseLine(std::string&);
void configSetValueSafe(const std::string&, const std::string&);
void handleDeviceConfig(const std::string&, const std::string&);
void handleRawExec(const std::string&, const std::string&);
void handleMonitor(const std::string&, const std::string&);
void handleBind(const std::string&, const std::string&, bool locked = false);
void handleBind(const std::string&, const std::string&);
void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&);
void handleDefaultWorkspace(const std::string&, const std::string&);
@@ -116,6 +129,7 @@ private:
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
void handleBlurLS(const std::string&, const std::string&);
};
inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -9,6 +9,12 @@ PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
########################################################################################
#
# Please note not all available settings / options are set here.
# For a full list, see the wiki (basic and advanced configuring)
#
autogenerated=1 # remove this line to get rid of the warning on top.
monitor=,1920x1080@60,0x0,1
@@ -21,6 +27,10 @@ input {
kb_rules=
follow_mouse=1
touchpad {
natural_scroll=no
}
}
general {
@@ -105,4 +115,7 @@ bind=ALT,7,movetoworkspace,7
bind=ALT,8,movetoworkspace,8
bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1
)#";

View File

@@ -13,95 +13,394 @@
#include <string>
std::string monitorsRequest() {
std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
for (auto& m : g_pCompositor->m_lMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\n",
m.szName.c_str(), m.ID, (int)m.vecSize.x, (int)m.vecSize.y, m.refreshRate, (int)m.vecPosition.x, (int)m.vecPosition.y, 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);
if (format == HyprCtl::FORMAT_JSON) {
result += "[";
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#({
"id": %i,
"name": "%s",
"width": %i,
"height": %i,
"refreshRate": %f,
"x": %i,
"y": %i,
"activeWorkspace": {
"id": %i,
"name": "%s"
},
"reserved": [%i, %i, %i, %i],
"scale": %.2f,
"transform": %i,
"active": "%s"
},)#",
m->ID,
escapeJSONStrings(m->szName).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 ? "yes" : "no")
);
}
// remove trailing comma
result.pop_back();
result += "]";
} else {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tactive: %s\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->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"));
}
}
return result;
}
std::string clientsRequest() {
std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_bIsMapped) {
result += 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\n",
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().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());
if (format == HyprCtl::FORMAT_JSON) {
result += "[";
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += getFormat(
R"#({
"address": "0x%x",
"at": [%i, %i],
"size": [%i, %i],
"workspace": {
"id": %i,
"name": "%s"
},
"floating": %i,
"monitor": %i,
"class": "%s",
"title": "%s",
"pid": %i,
"xwayland": %i
},)#",
w.get(),
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
(int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().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,
w->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
w->getPID(),
(int)w->m_bIsX11
);
}
}
// remove trailing comma
result.pop_back();
result += "]";
} else {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += 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\n",
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().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.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11);
}
}
}
return result;
}
std::string workspacesRequest() {
std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
for (auto& w : g_pCompositor->m_lWorkspaces) {
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\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);
if (format == HyprCtl::FORMAT_JSON) {
result += "[";
for (auto& w : g_pCompositor->m_vWorkspaces) {
result += getFormat(
R"#({
"id": %i,
"name": "%s",
"monitor": "%s",
"windows": %i,
"hasfullscreen": %i
},)#",
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
);
}
// remove trailing comma
result.pop_back();
result += "]";
} else {
for (auto& w : g_pCompositor->m_vWorkspaces) {
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\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);
}
}
return result;
}
std::string activeWindowRequest() {
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid";
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\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID());
if (format == HyprCtl::FORMAT_JSON) {
return getFormat(
R"#({
"address": "0x%x",
"at": [%i, %i],
"size": [%i, %i],
"workspace": {
"id": %i,
"name": "%s"
},
"floating": %i,
"monitor": %i,
"class": "%s",
"title": "%s",
"pid": %i,
"xwayland": %i
})#",
PWINDOW,
(int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
(int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(),
(int)PWINDOW->m_bIsFloating,
PWINDOW->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(),
PWINDOW->getPID(),
(int)PWINDOW->m_bIsX11
);
} 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\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID(), (int)PWINDOW->m_bIsX11);
}
}
std::string layersRequest() {
std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
for (auto& mon : g_pCompositor->m_lMonitors) {
result += getFormat("Monitor %s:\n");
int layerLevel = 0;
for (auto& level : mon.m_aLayerSurfaceLists) {
result += getFormat("\tLayer level %i:\n", layerLevel);
if (format == HyprCtl::FORMAT_JSON) {
result += "{\n";
for (auto& layer : level) {
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height);
for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#("%s": {
"levels": {
)#",
escapeJSONStrings(mon->szName).c_str()
);
int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLists) {
result += getFormat(
R"#(
"%i": [
)#",
layerLevel
);
for (auto& layer : level) {
result += getFormat(
R"#( {
"address": "0x%x",
"x": %i,
"y": %i,
"w": %i,
"h": %i,
"namespace": "%s"
},)#",
layer.get(),
layer->geometry.x,
layer->geometry.y,
layer->geometry.width,
layer->geometry.height,
escapeJSONStrings(layer->szNamespace).c_str()
);
}
// remove trailing comma
result.pop_back();
if (level.size() > 0)
result += "\n ";
result += "],";
layerLevel++;
}
layerLevel++;
// remove trailing comma
result.pop_back();
result += "\n }\n},";
}
// remove trailing comma
result.pop_back();
result += "\n}\n";
} else {
for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s:\n", mon->szName.c_str());
int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLists) {
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());
}
layerLevel++;
}
result += "\n\n";
}
result += "\n\n";
}
return result;
}
std::string devicesRequest() {
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
result += "mice:\n";
if (format == HyprCtl::FORMAT_JSON) {
result += "{\n";
result += "\"mice\": [\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
}
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&m,
escapeJSONStrings(m.mouse->name).c_str()
);
}
result += "\n\nKeyboards:\n";
// remove trailing comma
result.pop_back();
result += "\n],\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
}
result += "\"keyboards\": [\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s",
"rules": "%s",
"model": "%s",
"layout": "%s",
"variant": "%s",
"options": "%s",
"active_keymap": "%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()
);
}
result += "\n\nTablets:\n";
// remove trailing comma
result.pop_back();
result += "\n],\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 += "\"tablets\": [\n";
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
}
for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat(
R"#( {
"address": "0x%x",
"type": "tabletPad",
"belongsTo": {
"address": "0x%x",
"name": "%s"
}
},)#",
&d,
d.pTabletParent,
escapeJSONStrings(d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "").c_str()
);
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
escapeJSONStrings(d.wlrDevice ? d.wlrDevice->name : "").c_str()
);
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat(
R"#( {
"address": "0x%x",
"type": "tabletTool",
"belongsTo": "0x%x"
},)#",
&d,
d.wlrTabletTool ? d.wlrTabletTool->data : 0
);
}
// remove trailing comma
if (result[result.size() - 1] == ',')
result.pop_back();
result += "\n]\n";
result += "}\n";
} else {
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
}
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
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", &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);
}
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 : "" : "");
}
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
}
}
return result;
@@ -158,9 +457,12 @@ std::string dispatchKeyword(std::string in) {
if (COMMAND == "monitor")
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
if (COMMAND.find("input") != std::string::npos)
if (COMMAND.contains("input"))
g_pInputManager->setKeyboardLayout(); // update kb layout
if (COMMAND.contains("general:layout"))
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
if (retval == "")
@@ -181,6 +483,10 @@ std::string killRequest() {
return "ok";
}
std::string splashRequest() {
return g_pCompositor->m_szCurrentSplash;
}
std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
@@ -216,24 +522,46 @@ std::string dispatchBatch(std::string request) {
}
std::string getReply(std::string request) {
auto format = HyprCtl::FORMAT_NORMAL;
// process flags for non-batch requests
if (!request.contains("[[BATCH]]") && request.contains("/")) {
long unsigned int sepIndex = 0;
for (const auto& c : request) {
if (c == '/') { // stop at separator
break;
}
sepIndex++;
if (c == 'j')
format = HyprCtl::FORMAT_JSON;
}
if (sepIndex < request.size())
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
}
if (request == "monitors")
return monitorsRequest();
return monitorsRequest(format);
else if (request == "workspaces")
return workspacesRequest();
return workspacesRequest(format);
else if (request == "clients")
return clientsRequest();
return clientsRequest(format);
else if (request == "kill")
return killRequest();
else if (request == "activewindow")
return activeWindowRequest();
return activeWindowRequest(format);
else if (request == "layers")
return layersRequest();
return layersRequest(format);
else if (request == "version")
return versionRequest();
else if (request == "reload")
return reloadRequest();
else if (request == "devices")
return devicesRequest();
return devicesRequest(format);
else if (request == "splash")
return splashRequest();
else if (request.find("dispatch") == 0)
return dispatchRequest(request);
else if (request.find("keyword") == 0)
@@ -264,6 +592,16 @@ void HyprCtl::tickHyprCtl() {
}
std::string getRequestFromThread(std::string rq) {
// we need to do something to wake hyprland up if VFR is enabled
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
// TODO: is this safe...?
// this might be a race condition
// tested with 2 instances of `watch -n 0.1 hyprctl splash` and seems to not crash so I'll take that as a yes
if (!*PNOVFR)
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_vMonitors.front().get());
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}

View File

@@ -14,4 +14,9 @@ namespace HyprCtl {
inline std::string request = "";
inline std::ifstream requestStream;
enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0,
FORMAT_JSON
};
};

View File

@@ -120,7 +120,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_lMonitors.front().vecPosition.x, (int)g_pCompositor->m_lMonitors.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;
@@ -140,7 +140,7 @@ void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
void CHyprDebugOverlay::draw() {
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
@@ -155,8 +155,8 @@ void CHyprDebugOverlay::draw() {
// draw the things
int offsetY = 0;
for (auto& m : g_pCompositor->m_lMonitors) {
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
for (auto& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
offsetY += 5; // for padding between mons
}

View File

@@ -14,6 +14,9 @@ void Debug::init(std::string IS) {
void Debug::log(LogLevel level, const char* fmt, ...) {
if (disableLogs && *disableLogs)
return;
// log to a file
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
@@ -38,37 +41,37 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
break;
}
char buf[LOGMESSAGESIZE] = "";
char* outputStr;
int logLen;
// print date and time to the ofs
if (disableTime && !*disableTime) {
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
if (MILLIS > 99)
ofs << MILLIS;
else if (MILLIS > 9)
ofs << "0" << MILLIS;
else
ofs << "00" << MILLIS;
ofs << "] ";
}
char* outputStr = nullptr;
va_list args;
va_start(args, fmt);
logLen = vsnprintf(buf, sizeof buf, fmt, args);
vasprintf(&outputStr, fmt, args);
va_end(args);
if ((long unsigned int)logLen < sizeof buf) {
outputStr = strdup(buf);
} else {
outputStr = (char*)malloc(logLen + 1);
std::string output = std::string(outputStr);
free(outputStr);
if (!outputStr) {
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
return;
}
va_start(args, fmt);
vsnprintf(outputStr, logLen + 1U, fmt, args);
va_end(args);
}
ofs << outputStr << "\n";
ofs << output << "\n";
ofs.close();
// log it to the stdout too.
std::cout << outputStr << "\n";
// free the log
free(outputStr);
std::cout << output << "\n";
}

View File

@@ -17,4 +17,6 @@ namespace Debug {
void log(LogLevel level, const char* fmt, ...);
inline std::string logFile;
inline int64_t* disableLogs = nullptr;
inline int64_t* disableTime = nullptr;
};

View File

@@ -16,8 +16,6 @@
#define ISDEBUG false
#endif
#define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); }
#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;
@@ -56,6 +54,12 @@
#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; }
#else
#define UNREACHABLE() std::unreachable();
#endif
// git stuff
#ifndef GIT_COMMIT_HASH
#define GIT_COMMIT_HASH "?"

View File

@@ -49,9 +49,7 @@ void Events::listener_mouseButton(wl_listener* listener, void* data) {
}
void Events::listener_mouseAxis(wl_listener* listener, void* data) {
const auto E = (wlr_pointer_axis_event*)data;
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, E->time_msec, E->orientation, E->delta, E->delta_discrete, E->source);
g_pInputManager->onMouseWheel((wlr_pointer_axis_event*)data);
}
void Events::listener_requestMouse(wl_listener* listener, void* data) {
@@ -151,11 +149,44 @@ void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
const auto POINTER = EV->new_pointer;
const auto DEVICE = &POINTER->pointer.base;
g_pInputManager->newMouse(DEVICE);
g_pInputManager->newMouse(DEVICE, true);
}
void Events::listener_destroyMouse(void* owner, void* data) {
const auto PMOUSE = (SMouse*)owner;
g_pInputManager->destroyMouse(PMOUSE->mouse);
}
void Events::listener_swipeBegin(wl_listener* listener, void* data) {
const auto EVENT = (wlr_pointer_swipe_begin_event*)data;
g_pInputManager->onSwipeBegin(EVENT);
}
void Events::listener_swipeUpdate(wl_listener* listener, void* data) {
const auto EVENT = (wlr_pointer_swipe_update_event*)data;
g_pInputManager->onSwipeUpdate(EVENT);
}
void Events::listener_swipeEnd(wl_listener* listener, void* data) {
const auto EVENT = (wlr_pointer_swipe_end_event*)data;
g_pInputManager->onSwipeEnd(EVENT);
}
void Events::listener_pinchBegin(wl_listener* listener, void* data) {
const auto EV = (wlr_pointer_pinch_begin_event*)data;
wlr_pointer_gestures_v1_send_pinch_begin(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->fingers);
}
void Events::listener_pinchUpdate(wl_listener* listener, void* data) {
const auto EV = (wlr_pointer_pinch_update_event*)data;
wlr_pointer_gestures_v1_send_pinch_update(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->dx, EV->dy, EV->scale, EV->rotation);
}
void Events::listener_pinchEnd(wl_listener* listener, void* data) {
const auto EV = (wlr_pointer_pinch_end_event*)data;
wlr_pointer_gestures_v1_send_pinch_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->cancelled);
}

View File

@@ -49,6 +49,11 @@ namespace Events {
DYNLISTENFUNC(fullscreenWindow);
DYNLISTENFUNC(activateX11);
DYNLISTENFUNC(configureX11);
DYNLISTENFUNC(unmanagedSetGeometry);
DYNLISTENFUNC(requestMove);
DYNLISTENFUNC(requestResize);
DYNLISTENFUNC(requestMinimize);
DYNLISTENFUNC(requestMaximize);
// Window subsurfaces
// LISTENER(newSubsurfaceWindow);
@@ -112,4 +117,17 @@ namespace Events {
// Renderer destroy
LISTENER(RendererDestroy);
LISTENER(newIdleInhibitor);
// session
LISTENER(sessionActive);
// Touchpad shit
LISTENER(swipeBegin);
LISTENER(swipeEnd);
LISTENER(swipeUpdate);
LISTENER(pinchBegin);
LISTENER(pinchUpdate);
LISTENER(pinchEnd);
};

View File

@@ -32,15 +32,16 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
}
const auto PMONITOR = (SMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].push_back(new SLayerSurface());
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
if (!WLRLAYERSURFACE->output) {
WLRLAYERSURFACE->output = g_pCompositor->m_lMonitors.front().output; // TODO: current mon
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon
}
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
@@ -50,6 +51,8 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
}
@@ -63,12 +66,20 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID))
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
if (!layersurface->fadingOut && PMONITOR) {
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
layersurface->alpha.setValueAndWarp(0.f);
layersurface->fadingOut = true;
if (!layersurface->fadingOut) {
if (layersurface->mapped) {
Debug::log(LOG, "Forcing an unmap of a LS that did a straight destroy!");
listener_unmapLayerSurface(layersurface, nullptr);
} else {
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
layersurface->alpha.setValueAndWarp(0.f);
layersurface->fadingOut = true;
g_pCompositor->addToFadingOutSafe(layersurface);
}
}
layersurface->noProcess = true;
layersurface->hyprListener_commitLayerSurface.removeCallback();
layersurface->hyprListener_destroyLayerSurface.removeCallback();
layersurface->hyprListener_mapLayerSurface.removeCallback();
@@ -78,7 +89,7 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
// rearrange to fix the reserved areas
if (PMONITOR) {
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
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};
@@ -95,8 +106,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x mapped", layersurface->layerSurface);
layersurface->layerSurface->mapped = true;
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
layersurface->mapped = true;
// fix if it changed its mon
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
@@ -106,18 +116,29 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
POLDMON->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].push_back(layersurface);
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
if (it->get() == layersurface) {
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
break;
}
}
layersurface->monitorID = PMONITOR->ID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
if (layersurface->layerSurface->current.keyboard_interactive)
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
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);
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};
@@ -136,6 +157,14 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
g_pCompositor->addToFadingOutSafe(layersurface);
layersurface->mapped = false;
layersurface->fadingOut = true;
layersurface->alpha.setValueAndWarp(0.f);
return;
}
@@ -143,21 +172,26 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
layersurface->alpha = 0.f;
layersurface->mapped = false;
layersurface->fadingOut = true;
g_pCompositor->m_lSurfacesFadingOut.push_back(layersurface);
g_pCompositor->addToFadingOutSafe(layersurface);
if (layersurface->layerSurface->mapped)
layersurface->layerSurface->mapped = false;
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus)
g_pCompositor->m_pLastFocus = nullptr;
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
if (!PMONITOR)
return;
// refocus if needed
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
g_pCompositor->m_pLastFocus = nullptr;
g_pInputManager->refocus();
}
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);
@@ -179,33 +213,49 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
if (!PMONITOR)
return;
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, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
// fix if it changed its mon
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
POLDMON->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].push_back(layersurface);
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
if (it->get() == layersurface) {
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
break;
}
}
layersurface->monitorID = PMONITOR->ID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
if (layersurface->layerSurface->current.committed != 0) {
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
if (layersurface->layer != layersurface->layerSurface->current.layer) {
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].push_back(layersurface);
for (auto it = PMONITOR->m_aLayerSurfaceLists[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
if (it->get() == layersurface) {
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].erase(it);
break;
}
}
layersurface->layer = layersurface->layerSurface->current.layer;
}
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
PMONITOR->scheduledRecalc = true;
}
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
// TODO: optimize this. This does NOT need to be here but it prevents some issues with full DT.
g_pHyprRenderer->damageMonitor(PMONITOR);
// update geom if it changed
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

@@ -157,4 +157,10 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
Debug::log(LOG, "!!Renderer destroyed!!");
}
void Events::listener_sessionActive(wl_listener* listener, void* data) {
Debug::log(LOG, "Session got activated!");
g_pCompositor->m_bSessionActive = true;
}

View File

@@ -21,24 +21,24 @@ void Events::listener_change(wl_listener* listener, void* data) {
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create();
for (auto& m : g_pCompositor->m_lMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m.output);
for (auto& m : g_pCompositor->m_vMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
// TODO: clients off of disabled
wlr_box BOX;
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m.output, &BOX);
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
//m.vecSize.x = BOX.width;
// m.vecSize.y = BOX.height;
m.vecPosition.x = BOX.x;
m.vecPosition.y = BOX.y;
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
m->vecPosition.x = BOX.x;
m->vecPosition.y = BOX.y;
CONFIGHEAD->state.enabled = m.output->enabled;
CONFIGHEAD->state.mode = m.output->current_mode;
CONFIGHEAD->state.x = m.vecPosition.x;
CONFIGHEAD->state.y = m.vecPosition.y;
CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
wlr_output_set_custom_mode(m.output, m.vecPixelSize.x, m.vecPixelSize.y, (int)(round(m.refreshRate * 1000)));
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
@@ -72,10 +72,11 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
return;
}
SMonitor newMonitor;
newMonitor.output = OUTPUT;
newMonitor.ID = g_pCompositor->getNextAvailableMonitorID();
newMonitor.szName = OUTPUT->name;
const auto PNEWMONITOR = g_pCompositor->m_vMonitors.emplace_back(std::make_unique<SMonitor>()).get();
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->ID = g_pCompositor->getNextAvailableMonitorID();
PNEWMONITOR->szName = OUTPUT->name;
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
@@ -86,12 +87,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
wlr_output_enable_adaptive_sync(OUTPUT, 1);
// create it in the arr
newMonitor.vecPosition = monitorRule.offset;
newMonitor.vecSize = monitorRule.resolution;
newMonitor.refreshRate = monitorRule.refreshRate;
g_pCompositor->m_lMonitors.push_back(newMonitor);
const auto PNEWMONITOR = &g_pCompositor->m_lMonitors.back();
PNEWMONITOR->vecPosition = monitorRule.offset;
PNEWMONITOR->vecSize = monitorRule.resolution;
PNEWMONITOR->refreshRate = monitorRule.refreshRate;
PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR);
PNEWMONITOR->hyprListener_monitorDestroy.initCallback(&OUTPUT->events.destroy, &Events::listener_monitorDestroy, PNEWMONITOR);
@@ -115,13 +113,13 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// Workspace
std::string newDefaultWorkspaceName = "";
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_lWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
WORKSPACEID = g_pCompositor->m_lWorkspaces.size() + 1;
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
}
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
@@ -135,7 +133,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
PNEWWORKSPACE->startAnim(true,true,true);
} else {
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID, newDefaultWorkspaceName);
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PNEWMONITOR->ID, newDefaultWorkspaceName)).get();
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
@@ -150,15 +148,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
PNEWWORKSPACE->setActive(true);
//
if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate)
pMostHzMonitor = PNEWMONITOR;
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", PNEWMONITOR->szName});
// ready to process cuz we have a monitor
g_pCompositor->m_bReadyToProcess = true;
@@ -167,40 +165,32 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
void Events::listener_monitorFrame(void* owner, void* data) {
SMonitor* const PMONITOR = (SMonitor*)owner;
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive) {
Debug::log(WARN, "Attempted to render frame on inactive session!");
return; // cannot draw on session inactive (different tty)
}
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
if (*PDEBUGOVERLAY == 1) {
startRender = std::chrono::high_resolution_clock::now();
g_pDebugOverlay->frameData(PMONITOR);
}
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
// This is for stuff that should be run every frame
if (PMONITOR->ID == pMostHzMonitor->ID) {
g_pCompositor->sanityCheckWorkspaces();
g_pAnimationManager->tick();
g_pCompositor->cleanupFadingOut();
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload();
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
}
if (PMONITOR->framesToSkip > 0) {
PMONITOR->framesToSkip -= 1;
if (!PMONITOR->noFrameSchedule)
wlr_output_schedule_frame(PMONITOR->output);
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
else {
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
}
@@ -208,6 +198,27 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
// 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
g_pCompositor->sanityCheckWorkspaces();
g_pAnimationManager->tick();
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload();
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
}
// //
if (PMONITOR->scheduledRecalc) {
PMONITOR->scheduledRecalc = false;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
}
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -226,15 +237,21 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0) {
// we need to cleanup fading out when rendering the appropriate context
g_pCompositor->cleanupFadingOut(PMONITOR->ID);
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
if (*PDAMAGEBLINK || *PNOVFR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
return;
}
// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
@@ -264,7 +281,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// potentially can save on resources.
g_pHyprOpenGL->begin(PMONITOR, &damage);
g_pHyprOpenGL->clear(CColor(100, 11, 11, 255));
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
@@ -280,6 +297,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
endRenderOverlay = std::chrono::high_resolution_clock::now();
}
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
wlr_box monrect = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
if (damageBlinkCleanup > 3)
damageBlinkCleanup = 0;
}
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
wlr_output_render_software_cursors(PMONITOR->output, NULL);
@@ -298,13 +325,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
if (*PDAMAGEBLINK)
pixman_region32_union(&frameDamage, &frameDamage, &damage);
wlr_output_set_damage(PMONITOR->output, &frameDamage);
pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage);
wlr_output_commit(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output);
if (*PDAMAGEBLINK || *PNOVFR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
if (*PDEBUGOVERLAY == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
@@ -323,9 +354,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
SMonitor* pMonitor = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.szName == OUTPUT->name) {
pMonitor = &m;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == OUTPUT->name) {
pMonitor = m.get();
break;
}
}
@@ -334,12 +365,11 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
return;
// Cleanup everything. Move windows back, snap cursor, shit.
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
const auto BACKUPMON = g_pCompositor->m_vMonitors.front().get();
if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanupExit();
exit(1);
g_pCompositor->cleanup();
return;
}
@@ -350,9 +380,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
// move workspaces
std::deque<CWorkspace*> wspToMove;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(&w);
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(w.get());
}
}
@@ -363,27 +393,22 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
pMonitor->activeWorkspace = -1;
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++it) {
if (it->m_iMonitorID == pMonitor->ID) {
it = g_pCompositor->m_lWorkspaces.erase(it);
}
}
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 == pMonitor->ID; }));
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", pMonitor->szName});
g_pCompositor->m_lMonitors.remove(*pMonitor);
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr<SMonitor>& el) { return el.get() == pMonitor; }));
// update the pMostHzMonitor
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.refreshRate > mostHz) {
pMonitorMostHz = &m;
mostHz = m.refreshRate;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}

View File

@@ -51,7 +51,7 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
pHyprPopup->popup = popup;
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->surface->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
@@ -76,8 +76,7 @@ void Events::listener_newPopup(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
@@ -93,12 +92,14 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
ASSERT(PWINDOW);
if (!PWINDOW->m_bIsMapped)
return;
Debug::log(LOG, "New layer popup created from XDG window %x -> %s", PWINDOW, PWINDOW->m_szTitle.c_str());
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
@@ -122,8 +123,7 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP;
@@ -170,5 +170,5 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
PPOPUP->pSurfaceTree = nullptr;
}
g_pCompositor->m_lXDGPopups.remove(*PPOPUP);
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; }));
}

View File

@@ -32,6 +32,9 @@ void addViewCoords(void* pWindow, int* x, int* y) {
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;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
@@ -43,6 +46,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_fAlpha = 255.f;
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
// Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
@@ -57,7 +65,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(PWINDOW);
if (!PWINDOWSURFACE) {
g_pCompositor->m_lWindows.remove(*PWINDOW);
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
return;
}
@@ -97,7 +105,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_iMonitorID = PMONITOR->ID;
} else {
const long int MONITOR = std::stoi(MONITORSTR);
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
if (MONITOR >= (long int)g_pCompositor->m_vMonitors.size() || MONITOR < (long int)0)
PWINDOW->m_iMonitorID = 0;
else
PWINDOW->m_iMonitorID = MONITOR;
@@ -142,7 +150,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
try {
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
if (alphaPart.find_first_of(' ') != std::string::npos) {
if (alphaPart.contains(' ')) {
// we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
@@ -160,13 +168,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (requestedWorkspace != "") {
// process requested workspace
if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
if (requestedWorkspace.contains(' ')) {
// check for silent
if (requestedWorkspace.find("silent") != std::string::npos) {
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
if (requestedWorkspace == "special") {
workspaceSilent = true;
}
}
if (!workspaceSilent) {
@@ -189,8 +201,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto SIZEX = SIZEXSTR.find('%') == std::string::npos ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto SIZEY = SIZEYSTR.find('%') == std::string::npos ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
@@ -205,8 +217,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto POSX = POSXSTR.find('%') == std::string::npos ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto POSY = POSYSTR.find('%') == std::string::npos ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
@@ -214,6 +226,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
} 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;
}
}
@@ -228,8 +242,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
}
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
} else
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
@@ -238,11 +255,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, 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_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_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");
} else {
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");
if (PWINDOW->m_iX11Type == 2)
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
}
// do the animation thing
@@ -251,7 +275,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (workspaceSilent) {
// move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) {
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
if (requestedWorkspace != "special")
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
else
g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
@@ -265,9 +292,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
}
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
}
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
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);
@@ -279,17 +312,22 @@ void Events::listener_unmapWindow(void* owner, void* data) {
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
if (!PWINDOW->m_bIsX11) {
Debug::log(LOG, "Unregistered late callbacks XDG: %x %x %x %x", &PWINDOW->hyprListener_commitWindow.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link, &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_newPopupXDG.m_sListener.link);
Debug::log(LOG, "Unregistered late callbacks XDG");
PWINDOW->hyprListener_commitWindow.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
PWINDOW->hyprListener_newPopupXDG.removeCallback();
PWINDOW->hyprListener_requestMaximize.removeCallback();
PWINDOW->hyprListener_requestMinimize.removeCallback();
PWINDOW->hyprListener_requestMove.removeCallback();
PWINDOW->hyprListener_requestResize.removeCallback();
} else {
Debug::log(LOG, "Unregistered late callbacks XWL: %x %x %x %x", &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_activateX11.m_sListener.link, &PWINDOW->hyprListener_configureX11.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link);
Debug::log(LOG, "Unregistered late callbacks XWL");
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
PWINDOW->hyprListener_activateX11.removeCallback();
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_setGeometryX11U.removeCallback();
}
if (PWINDOW->m_bIsFullscreen) {
@@ -330,12 +368,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->m_bFadingOut = true;
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
g_pCompositor->addToFadingOutSafe(PWINDOW);
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
@@ -345,14 +385,19 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// Destroy Foreign Toplevel
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
PWINDOW->m_phForeignToplevel = nullptr;
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
}
void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
return;
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
// Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
}
@@ -393,7 +438,7 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle});
if (PWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
@@ -409,6 +454,8 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
}
@@ -458,6 +505,8 @@ void Events::listener_configureX11(void* owner, void* data) {
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
g_pCompositor->moveWindowToTop(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true;
@@ -467,6 +516,32 @@ void Events::listener_configureX11(void* owner, void* data) {
g_pHyprRenderer->damageWindow(PWINDOW);
}
void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden)
return;
const auto POS = PWINDOW->m_vRealPosition.goalv();
const auto SIZ = PWINDOW->m_vRealSize.goalv();
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));
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
g_pCompositor->moveWindowToTop(PWINDOW);
PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW);
}
}
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data;
@@ -474,13 +549,14 @@ 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);
g_pCompositor->m_lWindows.emplace_back();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XWSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_unmapWindow.initCallback(&XWSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window");
@@ -495,8 +571,7 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; // TODO: handle?
g_pCompositor->m_lWindows.emplace_back();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
@@ -508,3 +583,28 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
const auto WLRDECO = (wlr_xdg_toplevel_decoration_v1*)data;
wlr_xdg_toplevel_decoration_v1_set_mode(WLRDECO, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
// ignore
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
}
void Events::listener_requestMinimize(void* owner, void* data) {
// ignore
}
void Events::listener_requestMove(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
// ignore
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
}
void Events::listener_requestResize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
// ignore
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
}

View File

@@ -13,7 +13,8 @@ enum ANIMATEDVARTYPE {
enum AVARDAMAGEPOLICY {
AVARDAMAGE_INVALID = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
class CAnimationManager;
@@ -33,56 +34,47 @@ public:
// gets the current vector value (real time)
const Vector2D& vec() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access vec() of AVARTYPE %i!", m_eVarType);
return m_vValue;
}
// gets the current float value (real time)
const float& fl() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access fl() of AVARTYPE %i!", m_eVarType);
return m_fValue;
}
// gets the current color value (real time)
const CColor& col() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access col() of AVARTYPE %i!", m_eVarType);
return m_cValue;
}
// gets the goal vector value
const Vector2D& goalv() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access goalv() of AVARTYPE %i!", m_eVarType);
return m_vGoal;
}
// gets the goal float value
const float& goalf() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access goalf() of AVARTYPE %i!", m_eVarType);
return m_fGoal;
}
// gets the goal color value
const CColor& goalc() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access goalc() of AVARTYPE %i!", m_eVarType);
return m_cGoal;
}
void operator=(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access =v of AVARTYPE %i!", m_eVarType);
m_vGoal = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
}
void operator=(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access =f of AVARTYPE %i!", m_eVarType);
m_fGoal = v;
animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue;
}
void operator=(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access =c of AVARTYPE %i!", m_eVarType);
m_cGoal = v;
animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue;
@@ -90,7 +82,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValue(v) of AVARTYPE %i!", m_eVarType);
m_vValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@@ -98,7 +89,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValue(f) of AVARTYPE %i!", m_eVarType);
m_fValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@@ -106,7 +96,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValue(c) of AVARTYPE %i!", m_eVarType);
m_cValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
@@ -114,21 +103,18 @@ public:
// Sets the actual value and goal
void setValueAndWarp(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValueAndWarp(v) of AVARTYPE %i!", m_eVarType);
m_vGoal = v;
warp();
}
// Sets the actual value and goal
void setValueAndWarp(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValueAndWarp(f) of AVARTYPE %i!", m_eVarType);
m_fGoal = v;
warp();
}
// Sets the actual value and goal
void setValueAndWarp(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValueAndWarp(c) of AVARTYPE %i!", m_eVarType);
m_cGoal = v;
warp();
}
@@ -143,10 +129,12 @@ public:
case AVARTYPE_COLOR:
return m_cValue != m_cGoal;
default:
return false;
UNREACHABLE();
}
return false; // unreachable
UNREACHABLE();
return false; // just so that the warning is suppressed
}
void warp() {
@@ -164,7 +152,7 @@ public:
break;
}
default:
break;
UNREACHABLE();
}
}

View File

@@ -3,6 +3,7 @@
#include <algorithm>
#include "../Compositor.hpp"
#include <sys/utsname.h>
#include <iomanip>
static const float transforms[][9] = {{
1.0f, 0.0f, 0.0f,
@@ -82,40 +83,45 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
}
std::string getFormat(const char *fmt, ...) {
char buf[LOGMESSAGESIZE] = "";
char* outputStr;
int logLen;
char* outputStr = nullptr;
va_list args;
va_start(args, fmt);
logLen = vsnprintf(buf, sizeof buf, fmt, args);
vasprintf(&outputStr, fmt, args);
va_end(args);
if ((long unsigned int)logLen < sizeof buf) {
outputStr = strdup(buf);
} else {
outputStr = (char*)malloc(logLen + 1);
if (!outputStr) {
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
return "";
}
va_start(args, fmt);
vsnprintf(outputStr, logLen + 1U, fmt, args);
va_end(args);
}
std::string output = std::string(outputStr);
free(outputStr);
return output;
}
std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss;
for (auto &c : str) {
switch (c) {
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u"
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
}
}
return oss.str();
}
void scaleBox(wlr_box* box, float scale) {
box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale);
box->height = std::round((box->y + box->height) * scale) - std::round(box->y * scale);
box->width = std::round(box->width * scale);
box->height = std::round(box->height * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
}
@@ -137,7 +143,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
if (source.find_first_of("+") == 0) {
try {
if (source.find('.') != std::string::npos)
if (source.contains("."))
result = relative + std::stof(source.substr(1));
else
result = relative + std::stoi(source.substr(1));
@@ -147,7 +153,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
}
} else if (source.find_first_of("-") == 0) {
try {
if (source.find('.') != std::string::npos)
if (source.contains("."))
result = relative - std::stof(source.substr(1));
else
result = relative - std::stoi(source.substr(1));
@@ -157,7 +163,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
}
} else {
try {
if (source.find('.') != std::string::npos)
if (source.contains("."))
result = stof(source);
else
result = stoi(source);
@@ -193,7 +199,9 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
}
outName = WORKSPACENAME;
} else {
if (in[0] == 'm') {
if (in[0] == 'm' || in[0] == 'e') {
bool onAllMonitors = in[0] == 'e';
if (!g_pCompositor->m_pLastMonitor) {
Debug::log(ERR, "Relative monitor workspace on monitor null!");
result = INT_MAX;
@@ -219,12 +227,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iID < lowestID)
lowestID = w->m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
if (w->m_iID > highestID)
highestID = w->m_iID;
}
if (remains < 0)
@@ -234,7 +242,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
}
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
if (onAllMonitors || PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
currentID = PWORKSPACE->m_iID;
if (remains < 0)

View File

@@ -5,6 +5,7 @@
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
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);
bool isNumber(const std::string&, bool allowfloat = false);

View File

@@ -3,8 +3,9 @@
#include "../defines.hpp"
#include <deque>
#include "WLClasses.hpp"
#include <list>
#include <vector>
#include <array>
#include <memory>
struct SMonitor {
Vector2D vecPosition = Vector2D(0,0);
@@ -30,6 +31,7 @@ struct SMonitor {
int framesToSkip = 0;
int forceFullFrames = 0;
bool noFrameSchedule = false;
bool scheduledRecalc = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
// for the special workspace
@@ -38,7 +40,7 @@ struct SMonitor {
// Double-linked list because we need to have constant mem addresses for signals
// We have to store pointers and use raw new/delete because they might be moved between them
// and I am lazy
std::array<std::list<SLayerSurface*>, 4> m_aLayerSurfaceLists;
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLists;
DYNLISTENER(monitorFrame);
DYNLISTENER(monitorDestroy);

56
src/helpers/Splashes.hpp Normal file
View File

@@ -0,0 +1,56 @@
#pragma once
#include <array>
#include <string>
inline const std::vector<std::string> SPLASHES = {
"Woo, animations!",
"It's like Hypr, but better.",
"Release 1.0 when?",
"It's not awesome, it's Hyprland!",
"\"I commit too often, people can't catch up lmao\" - Vaxry",
"This text is random.",
"\"There are reasons to not use rust.\" - Boga",
"Read the wiki.",
"\"Hello everyone this is YOUR daily dose of read the wiki\" - Vaxry",
"h",
"\"why no work, bro I haven't hacked your pc to get live feeds yet\" - Vaxry",
"Compile, wait for 20 minutes, notice a new commit, compile again.",
"To rice, or not to rice, that is the question.",
"Now available on Fedora!",
// music reference / quote section
"J'remue le ciel, le jour, la nuit.",
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
"Wir sind schon sehr lang zusammen...",
"I see a red door and I want it painted black.",
"Take on me, take me on...",
"You spin me right round baby right round",
"Stayin' alive, stayin' alive",
"Say no way, say no way ya, no way!",
"Ground control to Major Tom...",
"Alors on danse",
"And all that I can see, is just a yellow lemon tree.",
"Got a one-way ticket to the blues",
"Is this the real life, is this just fantasy",
"What's in your head, in your head?",
"We're all living in America, America, America.",
"I'm still standing, better than I ever did",
"Here comes the sun, bringing you love and shining on everyone",
"Two trailer park girls go round the outside",
"With the lights out, it's less dangerous",
"Here we go back, this is the moment, tonight is the night",
"Now you're just somebody that I used to know...",
"Black bird, black moon, black sky",
"Some legends are told, some turn to dust or to gold",
"Your brain gets smart, but your head gets dumb.",
"Save your mercy for someone who needs it more",
"You're gonna hear my voice when I shout it out loud",
"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",
//
"Join the discord server!",
"Thanks ThatOneCalculator!",
"The AUR packages always work, except for the times they don't.",
"Funny animation compositor woo"
};

View File

@@ -21,9 +21,7 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
}
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
PNODE->pSurface = pSurface;
PNODE->pWindowOwner = pWindow;
@@ -128,8 +126,7 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
const auto PSUBSURFACE = (wlr_subsurface*)data;
pNode->childSubsurfaces.push_back(SSubsurface());
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.back();
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
@@ -171,12 +168,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
addSurfaceGlobalOffset(PNODE, &lx, &ly);
wlr_box extents = {0};
wlr_surface_get_extends(PNODE->pSurface, &extents);
if (PNODE->pSurface) {
wlr_surface_get_extends(PNODE->pSurface, &extents);
extents.x += lx;
extents.y += ly;
extents.x += lx;
extents.y += ly;
g_pHyprRenderer->damageBox(&extents);
g_pHyprRenderer->damageBox(&extents);
}
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
subsurface->pChild = nullptr;

View File

@@ -1,4 +1,5 @@
#include "Vector2D.hpp"
#include <algorithm>
Vector2D::Vector2D(double xx, double yy) {
x = xx;
@@ -20,4 +21,11 @@ double Vector2D::normalize() {
Vector2D Vector2D::floor() {
return Vector2D((int)x, (int)y);
}
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)
);
}

View File

@@ -35,5 +35,7 @@ class Vector2D {
return a.x != x || a.y != y;
}
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
Vector2D floor();
};

View File

@@ -19,15 +19,22 @@ struct SLayerSurface {
DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup);
wlr_box geometry;
wlr_box geometry = {0,0,0,0};
Vector2D position;
zwlr_layer_shell_v1_layer layer;
bool mapped = false;
int monitorID = -1;
std::string szNamespace = "";
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
bool noProcess = false;
bool forceBlur = false;
// For the list lookup
bool operator==(const SLayerSurface& rhs) {
@@ -60,6 +67,26 @@ struct SRenderData {
// for custom round values
int rounding = -1; // -1 means not set
// for blurring
bool blur = false;
// only for windows, not popups
bool squishOversized = true;
};
struct SExtensionFindingData {
Vector2D origin;
Vector2D vec;
wlr_surface** found;
};
struct SStringRuleNames {
std::string layout = "";
std::string model = "";
std::string variant = "";
std::string options = "";
std::string rules = "";
};
struct SKeyboard {
@@ -71,7 +98,12 @@ struct SKeyboard {
bool active = false;
xkb_rule_names currentRules = {0};
std::string name = "";
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
// For the list lookup
bool operator==(const SKeyboard& rhs) {
@@ -87,6 +119,10 @@ struct SMouse {
pixman_region32_t confinedTo;
std::string name = "";
bool virt = false;
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
@@ -168,6 +204,8 @@ struct STablet {
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
wlr_input_device* wlrDevice = nullptr;
std::string name = "";
bool operator==(const STablet& b) {
return wlrDevice == b.wlrDevice;
}
@@ -186,6 +224,8 @@ struct STabletTool {
bool active = true;
std::string name = "";
DYNLISTENER(TabletToolDestroy);
DYNLISTENER(TabletToolSetCursor);
@@ -198,6 +238,8 @@ struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
std::string name = "";
DYNLISTENER(Attach);
DYNLISTENER(Button);
DYNLISTENER(Strip);
@@ -208,3 +250,25 @@ struct STabletPad {
return wlrTabletPadV2 == b.wlrTabletPadV2;
}
};
struct SIdleInhibitor {
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
CWindow* pWindow = nullptr;
DYNLISTENER(Destroy);
bool operator==(const SIdleInhibitor& b) {
return pWlrInhibitor == b.pWlrInhibitor;
}
};
struct SSwipeGesture {
CWorkspace* pWorkspaceBegin = nullptr;
double delta = 0;
float avgSpeed = 0;
int speedPoints = 0;
SMonitor* pMonitor = nullptr;
};

View File

@@ -4,9 +4,9 @@
#include "../debug/Log.hpp"
void handleWrapped(wl_listener* listener, void* data) {
CHyprWLListener* pListener = wl_container_of(listener, pListener, m_sListener);
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
pListener->emit(data);
pWrap->m_pSelf->emit(data);
}
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
@@ -14,7 +14,9 @@ CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, v
}
CHyprWLListener::CHyprWLListener() {
; //
m_swWrapper.m_pSelf = this;
m_swWrapper.m_sListener.notify = &handleWrapped;
wl_list_init(&m_swWrapper.m_sListener.link);
}
CHyprWLListener::~CHyprWLListener() {
@@ -22,31 +24,28 @@ CHyprWLListener::~CHyprWLListener() {
}
void CHyprWLListener::removeCallback() {
if (m_bIsConnected) {
Debug::log(LOG, "Callback %x -> %x, %s removed.", m_pCallback, m_pOwner, m_szAuthor.c_str());
wl_list_remove(&m_sListener.link);
if (isConnected()) {
Debug::log(LOG, "Callback %x -> %x, %s removed.", &m_pCallback, &m_pOwner, m_szAuthor.c_str());
wl_list_remove(&m_swWrapper.m_sListener.link);
wl_list_init(&m_swWrapper.m_sListener.link);
}
m_bIsConnected = false;
}
bool CHyprWLListener::isConnected() {
return m_bIsConnected;
return !wl_list_empty(&m_swWrapper.m_sListener.link);
}
void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner, std::string author) {
if (m_bIsConnected)
removeCallback();
if (isConnected()) {
Debug::log(ERR, "Tried to connect a listener twice?!");
return;
}
m_pOwner = pOwner;
m_pCallback = callback;
m_szAuthor = author;
m_sListener.notify = &handleWrapped;
m_bIsConnected = true;
addWLSignal(pSignal, &m_sListener, pOwner, m_szAuthor);
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
}
void CHyprWLListener::emit(void* data) {

View File

@@ -9,18 +9,26 @@ public:
CHyprWLListener();
~CHyprWLListener();
CHyprWLListener(const CHyprWLListener&) = delete;
CHyprWLListener(CHyprWLListener&&) = delete;
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
void removeCallback();
bool isConnected();
wl_listener m_sListener;
struct SWrapper {
wl_listener m_sListener;
CHyprWLListener* m_pSelf;
};
void emit(void*);
private:
bool m_bIsConnected = false;
SWrapper m_swWrapper;
void* m_pOwner = nullptr;

View File

@@ -31,7 +31,7 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(255.f);
g_pEventManager->postEvent({"createworkspace", m_szName});
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
}
CWorkspace::~CWorkspace() {
@@ -45,7 +45,7 @@ CWorkspace::~CWorkspace() {
m_pWlrHandle = nullptr;
}
g_pEventManager->postEvent({"destroyworkspace", m_szName});
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
}
void CWorkspace::startAnim(bool in, bool left, bool instant) {

View File

@@ -28,6 +28,7 @@ public:
// for animations
CAnimatedVariable m_vRenderOffset;
CAnimatedVariable m_fAlpha;
bool m_bForceRendering = false;
// "scratchpad"
bool m_bIsSpecialWorkspace = false;

View File

@@ -12,9 +12,9 @@ void CHyprError::createQueued() {
m_tTexture.destroyTexture();
}
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
const auto CAIRO = cairo_create(CAIROSURFACE);
@@ -27,12 +27,12 @@ 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_rectangle(CAIRO, 0, 0, PMONITOR->vecSize.x, 10 * LINECOUNT);
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, 10 * LINECOUNT);
// outline
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecSize.x - 1, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecSize.y - 1, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // bottom
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
cairo_fill(CAIRO);
@@ -70,7 +70,7 @@ void CHyprError::createQueued() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
// delete cairo
cairo_destroy(CAIRO);
@@ -95,16 +95,16 @@ void CHyprError::draw() {
m_tTexture.destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
g_pHyprRenderer->damageMonitor(&g_pCompositor->m_lMonitors.front());
g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
return;
}
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
}

View File

@@ -74,6 +74,7 @@ extern "C" {
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <wlr/util/region.h>
@@ -88,6 +89,10 @@ extern "C" {
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
#include <wlr/types/wlr_pointer_gestures_v1.h>
}
#undef class
@@ -114,3 +119,6 @@ extern "C" {
#include "helpers/Vector2D.hpp"
#include "ext-workspace-unstable-v1-protocol.h"
#include <algorithm>
#include <utility>

View File

@@ -23,19 +23,21 @@ void SDwindleNodeData::recalcSizePosRecursive() {
const auto REVERSESPLITRATIO = 2.f - splitRatio;
if (g_pConfigManager->getInt("dwindle:preserve_split") == 0)
splitTop = size.y > size.x;
if (g_pConfigManager->getInt("dwindle:preserve_split") == 0) {
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
splitTop = size.y * WIDTHMULTIPLIER > size.x;
}
const auto SPLITSIDE = !splitTop;
if (SPLITSIDE) {
// split sidey
// split left/right
children[0]->position = position;
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y);
children[1]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y);
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
} else {
// split toppy bottomy
// split top/bottom
children[0]->position = position;
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio);
@@ -93,17 +95,28 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
}
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
if (!PMONITOR){
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
return;
}
// Don't set nodes, only windows.
if (pNode->isNode)
return;
SMonitor* PMONITOR = nullptr;
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
PMONITOR = m.get();
break;
}
}
} else {
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
}
if (!PMONITOR) {
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
return;
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
@@ -160,9 +173,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
}
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bIsSpecialWorkspace) {
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
// if special, we adjust the coords a bit
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
@@ -180,7 +191,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
PWINDOW->updateWindowDecos();
}
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating)
return;
@@ -206,7 +217,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
} else
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
@@ -237,16 +248,19 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
// if cursor over first child, make it first, etc
const auto SIDEBYSIDE = NEWPARENT->size.x / NEWPARENT->size.y > 1.f;
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * WIDTHMULTIPLIER;
NEWPARENT->splitTop = !SIDEBYSIDE;
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
if (FORCESPLIT == 0) {
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, 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;
@@ -275,14 +289,16 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
}
// Update the children
if (NEWPARENT->size.x > NEWPARENT->size.y) {
// split sidey
if (NEWPARENT->size.x * WIDTHMULTIPLIER > NEWPARENT->size.y) {
// split left/right
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
} else {
// split toppy bottomy
// split top/bottom
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
@@ -311,7 +327,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
}
}
void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
@@ -378,6 +394,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
if (!PWORKSPACE)
return;
g_pHyprRenderer->damageMonitor(PMONITOR);
if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
@@ -388,9 +406,26 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
}
}
// Ignore any recalc events if we have a fullscreen window.
if (PWORKSPACE->m_bHasFullscreenWindow)
// Ignore any recalc events if we have a fullscreen window, but process if fullscreen mode 2
if (PWORKSPACE->m_bHasFullscreenWindow) {
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
return;
// massive hack from the fullscreen func
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
return;
}
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
@@ -401,150 +436,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
}
}
void CHyprDwindleLayout::changeWindowFloatingMode(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
// restore its' floating mode
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
return;
}
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->m_iWorkspaceID = PNEWMON->activeWorkspace;
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
// if the window is pseudo, update its size
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
onWindowCreated(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else {
onWindowRemoved(pWindow);
g_pCompositor->moveWindowToTop(pWindow);
}
}
void CHyprDwindleLayout::onBeginDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
m_vBeginDragSizeXY = Vector2D();
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
Debug::log(ERR, "Dragging attempted on an invalid window!");
return;
}
if (DRAGGINGWINDOW->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
return;
}
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragButton == BTN_LEFT) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
m_vLastDragXY = m_vBeginDragXY;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void CHyprDwindleLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
changeWindowFloatingMode(DRAGGINGWINDOW);
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
// Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
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);
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
return;
m_vLastDragXY = mousePos;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragButton == BTN_LEFT) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
if (DRAGGINGWINDOW->m_bIsFloating) {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
}
}
// get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
// and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
if (PMONITOR) {
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
bool CHyprDwindleLayout::isWindowTiled(CWindow* pWindow) {
return getNodeFromWindow(pWindow) != nullptr;
}
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
@@ -635,55 +528,6 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
TOPCONTAINER->recalcSizePosRecursive();
}
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR){
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
return;
}
if (desiredGeometry.width <= 0 || desiredGeometry.height <= 0) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.vec().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.vec().y) / 2.f);
} else {
// we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way.
if (!g_pCompositor->isPointOnAnyMonitor(middlePoint) || (desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
} else {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
}
}
}
if (pWindow->m_bX11DoesntWantBorders) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow);
}
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
@@ -704,6 +548,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
if (!pWindow->m_bIsFullscreen) {
// if it got its fullscreen disabled, set back its node if it had one
const auto PNODE = getNodeFromWindow(pWindow);
@@ -739,11 +585,15 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
}
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->moveWindowToTop(pWindow);
@@ -751,6 +601,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
// we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
recalculateMonitor(PMONITOR->ID);
}
void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
@@ -826,6 +678,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
PPARENT->recalcSizePosRecursive();
}
g_pInputManager->refocus();
}
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
@@ -1011,18 +865,15 @@ std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle";
}
void CHyprDwindleLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
void CHyprDwindleLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
continue;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
if (!PWINDOW->m_bIsFloating) {
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
return;
onWindowCreatedTiling(w.get());
}
}
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
g_pHyprRenderer->damageWindow(PWINDOW);
void CHyprDwindleLayout::onDisable() {
m_lDwindleNodesData.clear();
}

View File

@@ -42,17 +42,12 @@ struct SDwindleNodeData {
class CHyprDwindleLayout : public IHyprLayout {
public:
virtual void onWindowCreated(CWindow*);
virtual void onWindowRemoved(CWindow*);
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void changeWindowFloatingMode(CWindow*);
virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void onEndDragWindow();
virtual void onMouseMove(const Vector2D&);
virtual void onWindowCreatedFloating(CWindow*);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
@@ -60,15 +55,13 @@ public:
virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
private:
virtual void onEnable();
virtual void onDisable();
private:
std::list<SDwindleNodeData> m_lDwindleNodesData;
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SDwindleNodeData*);
SDwindleNodeData* getNodeFromWindow(CWindow*);

257
src/layout/IHyprLayout.cpp Normal file
View File

@@ -0,0 +1,257 @@
#include "IHyprLayout.hpp"
#include "../defines.hpp"
#include "../Compositor.hpp"
void IHyprLayout::onWindowCreated(CWindow* pWindow) {
if (pWindow->m_bIsFloating) {
onWindowCreatedFloating(pWindow);
} else {
onWindowCreatedTiling(pWindow);
}
}
void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
if (pWindow->m_bIsFloating) {
onWindowRemovedFloating(pWindow);
} else {
onWindowRemovedTiling(pWindow);
}
}
void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
return; // no-op
}
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
if (!PMONITOR) {
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
return;
}
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
// reject any windows with size <= 5x5
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) {
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);
} else {
// we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way.
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
} else {
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
}
}
}
if (pWindow->m_bX11DoesntWantBorders) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
if (pWindow->m_iX11Type != 2) {
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow);
}
}
void IHyprLayout::onBeginDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
m_vBeginDragSizeXY = Vector2D();
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
Debug::log(ERR, "Dragging attempted on an invalid window!");
return;
}
if (DRAGGINGWINDOW->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
return;
}
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragButton == BTN_LEFT) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
m_vLastDragXY = m_vBeginDragXY;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
// shadow to ignore any bound to MAIN_MOD
g_pKeybindManager->shadowKeybinds();
}
void IHyprLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
changeWindowFloatingMode(DRAGGINGWINDOW);
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
// Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
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);
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
return;
m_vLastDragXY = mousePos;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragButton == BTN_LEFT) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
if (DRAGGINGWINDOW->m_bIsFloating) {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
DRAGGINGWINDOW->updateWindowDecos();
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
}
}
// get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
// and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
if (PMONITOR) {
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
}
void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
// restore its' floating mode
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
return;
}
const auto TILED = isWindowTiled(pWindow);
if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->m_iWorkspaceID = PNEWMON->activeWorkspace;
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
// if the window is pseudo, update its size
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else {
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
onWindowRemovedTiling(pWindow);
g_pCompositor->moveWindowToTop(pWindow);
const auto POS = pWindow->m_vRealPosition.goalv();
const auto SIZ = pWindow->m_vRealSize.goalv();
pWindow->m_vRealPosition.setValueAndWarp(POS + Vector2D(5, 5));
pWindow->m_vRealSize.setValueAndWarp(SIZ - Vector2D(10, 10));
pWindow->m_vRealPosition = POS;
pWindow->m_vRealSize = SIZ;
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
}
}
void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
if (!PWINDOW->m_bIsFloating) {
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
return;
}
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
g_pHyprRenderer->damageWindow(PWINDOW);
}

View File

@@ -16,17 +16,29 @@ enum eFullscreenMode : uint8_t;
interface IHyprLayout {
public:
virtual void onEnable() = 0;
virtual void onDisable() = 0;
/*
Called when a window is created (mapped)
The layout HAS TO set the goal pos and size (anim mgr will use it)
If !animationinprogress, then the anim mgr will not apply an anim.
*/
virtual void onWindowCreated(CWindow*) = 0;
virtual void onWindowCreated(CWindow*);
virtual void onWindowCreatedTiling(CWindow*) = 0;
virtual void onWindowCreatedFloating(CWindow*);
/*
Return tiled status
*/
virtual bool isWindowTiled(CWindow*) = 0;
/*
Called when a window is removed (unmapped)
*/
virtual void onWindowRemoved(CWindow*) = 0;
virtual void onWindowRemoved(CWindow*);
virtual void onWindowRemovedTiling(CWindow*) = 0;
virtual void onWindowRemovedFloating(CWindow*);
/*
Called when the monitor requires a layout recalculation
this usually means reserved area changes
@@ -42,13 +54,13 @@ public:
/*
Called when a window is requested to be floated
*/
virtual void changeWindowFloatingMode(CWindow*) = 0;
virtual void changeWindowFloatingMode(CWindow*);
/*
Called when a window is clicked on, beginning a drag
this might be a resize, move, whatever the layout defines it
as.
*/
virtual void onBeginDragWindow() = 0;
virtual void onBeginDragWindow();
/*
Called when a user requests a resize of the current window by a vec
Vector2D holds pixel values
@@ -60,24 +72,18 @@ public:
Vector2D holds pixel values
Optional pWindow for a specific window
*/
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
/*
Called when a window is ended being dragged
(mouse up)
*/
virtual void onEndDragWindow() = 0;
virtual void onEndDragWindow();
/*
Called whenever the mouse moves, should the layout want to
do anything with it.
Useful for dragging.
*/
virtual void onMouseMove(const Vector2D&) = 0;
/*
Called when a window is created, but is requesting to be floated.
Warning: this also includes stuff like popups, incorrect handling
of which can result in a crash!
*/
virtual void onWindowCreatedFloating(CWindow*) = 0;
virtual void onMouseMove(const Vector2D&);
/*
Called when a window / the user requests to toggle the fullscreen state of a window
@@ -116,4 +122,10 @@ public:
Called when something wants the current layout's name
*/
virtual std::string getLayoutName() = 0;
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
};

423
src/layout/MasterLayout.cpp Normal file
View File

@@ -0,0 +1,423 @@
#include "MasterLayout.hpp"
#include "../Compositor.hpp"
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) {
for (auto& nd : m_lMasterNodesData) {
if (nd.pWindow == pWindow)
return &nd;
}
return nullptr;
}
int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
int no = 0;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == ws)
no++;
}
return no;
}
std::string CHyprMasterLayout::getLayoutName() {
return "Master";
}
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) {
for (auto& n : m_lMasterNodesData) {
if (n.isMaster && n.workspaceID == ws)
return &n;
}
return nullptr;
}
void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating)
return;
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
PNODE->workspaceID = pWindow->m_iWorkspaceID;
PNODE->pWindow = pWindow;
static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
float lastSplitPercent = 0.5f;
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
for (auto& nd : m_lMasterNodesData) {
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
nd.isMaster = false;
lastSplitPercent = nd.percMaster;
break;
}
}
PNODE->isMaster = true;
PNODE->percMaster = lastSplitPercent;
} else {
PNODE->isMaster = false;
}
// recalc
recalculateMonitor(pWindow->m_iMonitorID);
}
void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return;
if (PNODE->isMaster) {
// find new one
for (auto& nd : m_lMasterNodesData) {
if (!nd.isMaster) {
nd.isMaster = true;
break;
}
}
}
m_lMasterNodesData.remove(*PNODE);
recalculateMonitor(pWindow->m_iMonitorID);
}
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
return;
g_pHyprRenderer->damageMonitor(PMONITOR);
if (PMONITOR->specialWorkspaceOpen) {
calculateWorkspace(SPECIAL_WORKSPACE_ID);
}
if (PWORKSPACE->m_bHasFullscreenWindow) {
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
return;
// massive hack from the fullscreen func
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
return;
}
// calc the WS
calculateWorkspace(PWORKSPACE->m_iID);
}
void CHyprMasterLayout::calculateWorkspace(const int& ws) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(ws);
if (!PWORKSPACE)
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
if (!PMASTERNODE)
return;
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);
applyNodeDataToWindow(PMASTERNODE);
return;
} else {
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
PMASTERNODE->size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
}
const auto SLAVESIZE = 1.f / (getNodesOnWorkspace(PWORKSPACE->m_iID) - 1) * (PMASTERNODE->size.y);
int slavesDone = 0;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID)
continue;
if (nd == *PMASTERNODE) {
applyNodeDataToWindow(PMASTERNODE);
continue;
}
nd.position = Vector2D(PMASTERNODE->size.x + PMASTERNODE->position.x, slavesDone * SLAVESIZE + PMASTERNODE->position.y);
nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, SLAVESIZE);
slavesDone++;
applyNodeDataToWindow(&nd);
}
}
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
SMonitor* PMONITOR = nullptr;
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
PMONITOR = m.get();
break;
}
}
} else {
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
}
if (!PMONITOR) {
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
return;
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
const auto PWINDOW = pNode->pWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
return;
}
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
// TODO: special
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
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;
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
}
PWINDOW->updateWindowDecos();
}
bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) {
return getNodeFromWindow(pWindow) != nullptr;
}
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) {
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
PWINDOW->updateWindowDecos();
return;
}
// get master
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2)
return;
float delta = pixResize.x / PMONITOR->vecSize.x;
PMASTER->percMaster += delta;
std::clamp(PMASTER->percMaster, 0.05f, 0.95f);
recalculateMonitor(PMONITOR->ID);
}
void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (on == pWindow->m_bIsFullscreen)
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
// if the window wants to be fullscreen but there already is one,
// ignore the request.
return;
}
// otherwise, accept it.
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
if (!pWindow->m_bIsFullscreen) {
// if it got its fullscreen disabled, set back its node if it had one
const auto PNODE = getNodeFromWindow(pWindow);
if (PNODE)
applyNodeDataToWindow(PNODE);
else {
// get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vPosition;
pWindow->m_vRealSize = pWindow->m_vSize;
}
} else {
// if it now got fullscreen, make it fullscreen
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
// save position and size if floating
if (pWindow->m_bIsFloating) {
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
pWindow->m_vSize = pWindow->m_vRealSize.vec();
}
// apply new pos and size being monitors' box
if (fullscreenMode == FULLSCREEN_FULL) {
pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize;
} else {
// This is a massive hack.
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SMasterNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
}
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->moveWindowToTop(pWindow);
// we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
recalculateMonitor(PMONITOR->ID);
}
void CHyprMasterLayout::recalculateWindow(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return;
recalculateMonitor(pWindow->m_iMonitorID);
}
SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow) {
// window should be valid, insallah
SWindowRenderLayoutHints hints;
return hints; // master doesnt have any hints
}
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
// windows should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE2 = getNodeFromWindow(pWindow2);
if (!PNODE2 || !PNODE)
return;
if (PNODE->workspaceID != PNODE2->workspaceID) {
Debug::log(ERR, "Master: Rejecting a swap between workspaces");
return;
}
// massive hack: just swap window pointers, lol
const auto PWINDOW1 = PNODE->pWindow;
PNODE->pWindow = PNODE2->pWindow;
PNODE2->pWindow = PWINDOW1;
recalculateMonitor(PWINDOW1->m_iMonitorID);
}
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
// window should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return;
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f);
recalculateMonitor(pWindow->m_iMonitorID);
}
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
return "";
}
void CHyprMasterLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
continue;
onWindowCreatedTiling(w.get());
}
}
void CHyprMasterLayout::onDisable() {
m_lMasterNodesData.clear();
}

View File

@@ -0,0 +1,54 @@
#pragma once
#include "IHyprLayout.hpp"
#include <list>
#include <deque>
enum eFullscreenMode : uint8_t;
struct SMasterNodeData {
bool isMaster = false;
float percMaster = 0.5f;
CWindow* pWindow = nullptr;
Vector2D position;
Vector2D size;
int workspaceID = -1;
bool operator==(const SMasterNodeData& rhs) {
return pWindow == rhs.pWindow;
}
};
class CHyprMasterLayout : public IHyprLayout {
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
virtual void onEnable();
virtual void onDisable();
private:
std::list<SMasterNodeData> m_lMasterNodesData;
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SMasterNodeData*);
SMasterNodeData* getNodeFromWindow(CWindow*);
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
void calculateWorkspace(const int&);
friend struct SMasterNodeData;
};

View File

@@ -12,12 +12,22 @@ bool ignoreSudo = false;
int main(int argc, char** argv) {
if (!getenv("XDG_RUNTIME_DIR"))
RIP("XDG_RUNTIME_DIR not set!");
throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
// parse some args
std::string configPath;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid"))
ignoreSudo = true;
else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) {
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";
return 1;
}
}
system("mkdir -p /tmp/hypr");
@@ -37,6 +47,7 @@ int main(int argc, char** argv) {
// let's init the compositor.
// it initializes basic Wayland stuff in the constructor.
g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor->explicitConfigPath = configPath;
Debug::log(LOG, "Hyprland init finished.");
@@ -46,7 +57,7 @@ int main(int argc, char** argv) {
// If we are here it means we got yote.
Debug::log(LOG, "Hyprland reached the end.");
g_pCompositor->cleanupExit();
g_pCompositor->cleanup();
return EXIT_SUCCESS;
}

View File

@@ -31,111 +31,113 @@ void CAnimationManager::tick() {
static auto *const PANIMSPEED = &g_pConfigManager->getConfigValuePtr("animations:speed")->floatValue;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const BEZIERSTR = &g_pConfigManager->getConfigValuePtr("animations:curve")->strValue;
static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
auto DEFAULTBEZIER = m_mBezierCurves.find(*BEZIERSTR);
if (DEFAULTBEZIER == m_mBezierCurves.end())
DEFAULTBEZIER = m_mBezierCurves.find("default");
for (auto& av : m_lAnimatedVariables) {
// get speed
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
// window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
// first of all, check if we need to update it at all
if (!av->isBeingAnimated())
continue;
wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
} else if (PWORKSPACE) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry;
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
av->warp();
continue;
}
// beziers are with a switch unforto
// TODO: maybe do something cleaner
// get speed
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
// get the spent % (0 - 1)
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - av->animationBegin).count();
const float SPENT = std::clamp((DURATIONPASSED / 100.f) / SPEED, 0.f, 1.f);
// window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
SMonitor* PMONITOR = nullptr;
wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
} else if (PWORKSPACE) {
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry;
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
}
// beziers are with a switch unforto
// TODO: maybe do something cleaner
switch (av->m_eVarType) {
case AVARTYPE_FLOAT: {
if (!deltazero(av->m_fValue, av->m_fGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
else
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
else
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
break;
}
case AVARTYPE_VECTOR: {
if (!deltazero(av->m_vValue, av->m_vGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
break;
}
case AVARTYPE_COLOR: {
if (!deltazero(av->m_cValue, av->m_cGoal)) {
// for disabled anims just warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
// for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
break;
}
if (SPENT >= 1.f) {
av->warp();
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
break;
}
default: {
@@ -152,14 +154,14 @@ void CAnimationManager::tick() {
g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->updateWindowDecos();
} else if (PWORKSPACE) {
for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_bHidden)
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_bHidden)
continue;
if (w.m_iWorkspaceID != PWORKSPACE->m_iID)
if (w->m_iWorkspaceID != PWORKSPACE->m_iID)
continue;
w.updateWindowDecos();
w->updateWindowDecos();
}
}
break;
@@ -185,6 +187,35 @@ void CAnimationManager::tick() {
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: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
if (PDECO) {
const auto EXTENTS = PDECO->getWindowDecorationExtents();
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x + EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y + EXTENTS.topLeft.y,
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
if (!*PSHADOWIGNOREWINDOW) {
// easy, damage the entire box
g_pHyprRenderer->damageBox(&dmg);
} else {
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_subtract(&rg, &rg, &wb);
g_pHyprRenderer->damageRegion(&rg);
pixman_region32_fini(&rg);
pixman_region32_fini(&wb);
}
}
break;
}
default: {
@@ -195,8 +226,11 @@ void CAnimationManager::tick() {
// set size and pos if valid, but only if damage policy entire (dont if border for example)
if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE)
if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2)
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
// manually schedule a frame
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
}
@@ -310,7 +344,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
// the window has config'd special anim
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) {
// has a direction
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
} else {

View File

@@ -87,7 +87,7 @@ void CEventManager::startThread() {
// write all queued events
for (auto& ev : m_dQueuedEvents) {
std::string eventString = ev.event + ">>" + ev.data + "\n";
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
for (auto& fd : m_dAcceptedSocketFDs) {
write(fd, eventString.c_str(), eventString.length());
}
@@ -104,9 +104,9 @@ void CEventManager::startThread() {
}).detach();
}
void CEventManager::postEvent(const SHyprIPCEvent event) {
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
if (m_bIgnoreEvents) {
if (m_bIgnoreEvents && !force) {
Debug::log(WARN, "Suppressed (ignoreevents true) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
return;
}

View File

@@ -15,7 +15,7 @@ class CEventManager {
public:
CEventManager();
void postEvent(const SHyprIPCEvent event);
void postEvent(const SHyprIPCEvent event, bool force = false);
void startThread();

View File

@@ -30,66 +30,209 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["submap"] = setSubmap;
m_mDispatchers["pass"] = pass;
}
void CKeybindManager::addKeybind(SKeybind kb) {
m_lKeybinds.push_back(kb);
m_pActiveKeybind = nullptr;
}
void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) {
if (it->modmask == mod && it->key == key) {
if (isNumber(key) && std::stoi(key) > 9) {
const auto KEYNUM = std::stoi(key);
if (it->modmask == mod && it->keycode == KEYNUM) {
it = m_lKeybinds.erase(it);
if (it == m_lKeybinds.end())
break;
}
}
else if (it->modmask == mod && it->key == key) {
it = m_lKeybinds.erase(it);
if (it == m_lKeybinds.end())
break;
}
}
m_pActiveKeybind = nullptr;
}
uint32_t CKeybindManager::stringToModMask(std::string mods) {
uint32_t modMask = 0;
if (mods.find("SHIFT") != std::string::npos)
if (mods.contains("SHIFT"))
modMask |= WLR_MODIFIER_SHIFT;
if (mods.find("CAPS") != std::string::npos)
if (mods.contains("CAPS"))
modMask |= WLR_MODIFIER_CAPS;
if (mods.find("CTRL") != std::string::npos || mods.find("CONTROL") != std::string::npos)
if (mods.contains("CTRL") || mods.contains("CONTROL"))
modMask |= WLR_MODIFIER_CTRL;
if (mods.find("ALT") != std::string::npos)
if (mods.contains("ALT"))
modMask |= WLR_MODIFIER_ALT;
if (mods.find("MOD2") != std::string::npos)
if (mods.contains("MOD2"))
modMask |= WLR_MODIFIER_MOD2;
if (mods.find("MOD3") != std::string::npos)
if (mods.contains("MOD3"))
modMask |= WLR_MODIFIER_MOD3;
if (mods.find("SUPER") != std::string::npos || mods.find("WIN") != std::string::npos || mods.find("LOGO") != std::string::npos || mods.find("MOD4") != std::string::npos)
if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4"))
modMask |= WLR_MODIFIER_LOGO;
if (mods.find("MOD5") != std::string::npos)
if (mods.contains("MOD5"))
modMask |= WLR_MODIFIER_MOD5;
return modMask;
}
bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key) {
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
m_uTimeLastMs = e->time_msec;
m_uLastCode = KEYCODE;
bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
// clean repeat
if (m_pActiveKeybindEventSource) {
wl_event_source_remove(m_pActiveKeybindEventSource);
m_pActiveKeybindEventSource = nullptr;
m_pActiveKeybind = nullptr;
}
m_dPressedKeycodes.push_back(KEYCODE);
m_dPressedKeysyms.push_back(keysym);
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found;
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found;
if (found)
shadowKeybinds(keysym, KEYCODE);
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// clean repeat
if (m_pActiveKeybindEventSource) {
wl_event_source_remove(m_pActiveKeybindEventSource);
m_pActiveKeybindEventSource = nullptr;
m_pActiveKeybind = nullptr;
}
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE));
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym));
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found;
shadowKeybinds();
}
return !found;
}
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
bool found = false;
if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
if (e->delta < 0) {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
} else {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
}
if (found)
shadowKeybinds();
}
return !found;
}
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
bool found = false;
if (handleInternalKeybinds(key))
if (e->state == WLR_BUTTON_PRESSED) {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
if (found)
shadowKeybinds();
} else {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0);
shadowKeybinds();
}
return !found;
}
int repeatKeyHandler(void* data) {
SKeybind** ppActiveKeybind = (SKeybind**)data;
if (!*ppActiveKeybind)
return 0;
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler);
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
DISPATCHER->second((*ppActiveKeybind)->arg);
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pInputManager->m_pActiveKeyboard->repeatRate);
return 0;
}
bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode, bool pressed, uint32_t time) {
bool found = false;
if (handleInternalKeybinds(keysym))
return true;
if (g_pCompositor->m_sSeat.exclusiveClient)
Debug::log(LOG, "Keybind handling only locked (inhibitor)");
if (pressed && m_kHeldBack) {
// release the held back event
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, time, m_kHeldBack, WL_KEYBOARD_KEY_STATE_PRESSED);
m_kHeldBack = 0;
}
for (auto& k : m_lKeybinds) {
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap)
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release) || k.shadowed)
continue;
// oMg such performance hit!!11!
// this little maneouver is gonna cost us 4µs
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
// small TODO: fix 0-9 keys and other modified ones with shift
if (key != KBKEY && key != KBKEYUPPER)
continue;
if (!key.empty()) {
if (key != k.key)
continue;
} else if (k.keycode != -1) {
if (keycode != k.keycode)
continue;
} else {
if (keysym == 0)
continue; // this is a keycode check run
// oMg such performance hit!!11!
// this little maneouver is gonna cost us 4µs
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
// small TODO: fix 0-9 keys and other modified ones with shift
if (keysym != KBKEY && keysym != KBKEYUPPER)
continue;
}
if (pressed && k.release) {
// suppress down event
m_kHeldBack = keysym;
return true;
}
const auto DISPATCHER = m_mDispatchers.find(k.handler);
@@ -98,16 +241,61 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
} else {
// call the dispatcher
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %s, %d)", modmask, key, keysym);
DISPATCHER->second(k.arg);
}
if (k.repeat) {
m_pActiveKeybind = &k;
m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind);
const auto PACTIVEKEEB = g_pInputManager->m_pActiveKeyboard;
wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay);
}
found = true;
}
return found;
}
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int& doesntHaveCode) {
// shadow disables keybinds after one has been triggered
for (auto& k : m_lKeybinds) {
bool shadow = false;
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
for (auto& pk : m_dPressedKeysyms) {
if ((pk == KBKEY || pk == KBKEYUPPER)) {
shadow = true;
if (pk == doesntHave && doesntHave != 0) {
shadow = false;
break;
}
}
}
for (auto& pk : m_dPressedKeycodes) {
if (pk == k.keycode) {
shadow = true;
if (pk == doesntHaveCode && doesntHaveCode != 0 && doesntHaveCode != -1) {
shadow = false;
break;
}
}
}
k.shadowed = shadow;
}
}
bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// Handles the CTRL+ALT+FX TTY keybinds
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
@@ -117,11 +305,11 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
if (PSESSION) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY);
g_pCompositor->m_bSessionActive = false;
for (auto& m : g_pCompositor->m_lMonitors) {
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore
m.noFrameSchedule = true;
m.framesToSkip = 2;
for (auto& m : g_pCompositor->m_vMonitors) {
m->noFrameSchedule = true;
m->framesToSkip = 1;
}
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
@@ -207,7 +395,7 @@ void CKeybindManager::killActive(std::string args) {
g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastWindow);
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastWindow = nullptr;
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", ",")); // post an activewindow event to empty, as we are currently unfocused
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused
}
g_pCompositor->focusWindow(g_pCompositor->windowFromCursor());
@@ -221,15 +409,15 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow;
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
// remove drag status
g_pInputManager->currentlyDraggedWindow = nullptr;
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
}
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(ACTIVEWINDOW);
}
}
@@ -249,7 +437,14 @@ void CKeybindManager::changeworkspace(std::string args) {
int workspaceToChangeTo = 0;
std::string workspaceName = "";
workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
if (args.find("[internal]") == 0) {
workspaceToChangeTo = std::stoi(args.substr(10));
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
if (PWORKSPACE)
workspaceName = PWORKSPACE->m_szName;
} else {
workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
}
if (workspaceToChangeTo == INT_MAX) {
Debug::log(ERR, "Error in changeworkspace, invalid value");
@@ -273,8 +468,6 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// change it
PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
@@ -297,7 +490,7 @@ void CKeybindManager::changeworkspace(std::string args) {
// start anim on new workspace
PWORKSPACETOCHANGETO->startAnim(true, ANIMTOLEFT);
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACETOCHANGETO->m_szName});
}
// If the monitor is not the one our cursor's at, warp to it.
@@ -336,8 +529,7 @@ void CKeybindManager::changeworkspace(std::string args) {
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
@@ -371,7 +563,7 @@ void CKeybindManager::changeworkspace(std::string args) {
g_pInputManager->refocus();
// Event
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACE->m_szName));
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACE->m_szName});
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
}
@@ -402,6 +594,9 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
return;
}
auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
g_pKeybindManager->changeworkspace(args);
@@ -429,32 +624,33 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
PWORKSPACE->m_bHasFullscreenWindow = false;
}
if (PWINDOW->m_bIsFullscreen) {
PWINDOW->m_bIsFullscreen = false;
PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10);
PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20);
}
// Hack: So that the layout doesnt find our window at the cursor
PWINDOW->m_vPosition = Vector2D(-42069, -42069);
// Save the real position and size because the layout might set its own
const auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
const auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// and restore it
PWINDOW->m_vRealPosition.setValue(PSAVEDPOS);
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
// and restore it
if (PWINDOW->m_bIsFloating) {
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
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(std::to_string(OLDWORKSPACE->m_iID));
changeworkspace("[internal]" + std::to_string(OLDWORKSPACE->m_iID));
OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
for (auto& m : g_pCompositor->m_lMonitors)
m.specialWorkspaceOpen = false;
for (auto& m : g_pCompositor->m_vMonitors)
m->specialWorkspaceOpen = false;
}
g_pInputManager->refocus();
@@ -500,8 +696,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
changeworkspace(std::to_string(OLDWORKSPACEIDONMONITOR));
changeworkspace(std::to_string(OLDWORKSPACEIDRETURN));
changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDONMONITOR));
changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDRETURN));
// revert animations
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
@@ -659,8 +855,8 @@ void CKeybindManager::focusMonitor(std::string arg) {
Debug::log(ERR, "Error in focusMonitor: invalid num");
}
if (monID > -1 && monID < (int)g_pCompositor->m_lMonitors.size()) {
changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) {
changeworkspace("[internal]" + std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
} else {
Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
}
@@ -678,9 +874,9 @@ void CKeybindManager::focusMonitor(std::string arg) {
return;
}
} else {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.szName == arg) {
changeworkspace(std::to_string(m.activeWorkspace));
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == arg) {
changeworkspace("[internal]" + std::to_string(m->activeWorkspace));
return;
}
}
@@ -740,11 +936,11 @@ void CKeybindManager::workspaceOpt(std::string args) {
PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo;
// apply
for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_iWorkspaceID != PWORKSPACE->m_iID)
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
continue;
w.m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
w->m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
}
} else if (args == "allfloat") {
PWORKSPACE->m_bDefaultFloating = !PWORKSPACE->m_bDefaultFloating;
@@ -752,8 +948,8 @@ void CKeybindManager::workspaceOpt(std::string args) {
// we make a copy because changeWindowFloatingMode might invalidate the iterator
std::deque<CWindow*> ptrs;
for (auto& w : g_pCompositor->m_lWindows)
ptrs.push_back(&w);
for (auto& w : g_pCompositor->m_vWindows)
ptrs.push_back(w.get());
for (auto& w : ptrs) {
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
@@ -785,20 +981,20 @@ void CKeybindManager::workspaceOpt(std::string args) {
}
void CKeybindManager::exitHyprland(std::string argz) {
g_pCompositor->cleanupExit();
exit(0);
g_pCompositor->cleanup();
}
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
if (!isNumber(args) && !isDirection(args)) {
Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!");
return;
}
SMonitor* PMONITOR = nullptr;
const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
if (!PMONITOR) {
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
try {
if (!isNumber(args) && !isDirection(args)) {
PMONITOR = g_pCompositor->getMonitorFromName(args);
} else {
PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
}
} catch (std::exception& e) {
Debug::log(LOG, "moveCurrentWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
@@ -812,18 +1008,25 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
}
void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
if (args.find_first_of(' ') == std::string::npos)
if (!args.contains(' '))
return;
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
if (!isNumber(monitor) && !isDirection(monitor)) {
Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
SMonitor* PMONITOR = nullptr;
try {
if (!isNumber(monitor) && !isDirection(monitor)) {
PMONITOR = g_pCompositor->getMonitorFromName(monitor);
} else {
PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
}
} catch (std::exception& e) {
Debug::log(LOG, "moveWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
if (!PMONITOR){
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
@@ -857,8 +1060,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
bool open = false;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
open = true;
break;
}
@@ -870,20 +1073,25 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
Debug::log(LOG, "Toggling special workspace to open");
if (open) {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen != !open) {
m.specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen != !open) {
m->specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
}
} else {
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
if (!PSPECIALWORKSPACE) {
// ??? happens sometimes...?
PSPECIALWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(g_pCompositor->m_pLastMonitor->ID, "special", true)).get();
}
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
}
@@ -892,14 +1100,22 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
}
void CKeybindManager::forceRendererReload(std::string args) {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule, true);
bool overAgain = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
overAgain = true;
break;
}
}
if (overAgain)
forceRendererReload(args);
}
void CKeybindManager::resizeActive(std::string args) {
if (args.find_first_of(' ') == std::string::npos)
if (!args.contains(' '))
return;
std::string x = args.substr(0, args.find_first_of(' '));
@@ -948,7 +1164,7 @@ void CKeybindManager::resizeActive(std::string args) {
}
void CKeybindManager::moveActive(std::string args) {
if (args.find_first_of(' ') == std::string::npos)
if (!args.contains(' '))
return;
std::string x = args.substr(0, args.find_first_of(' '));
@@ -996,41 +1212,40 @@ void CKeybindManager::moveActive(std::string args) {
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
}
void CKeybindManager::circleNext(std::string) {
void CKeybindManager::circleNext(std::string arg) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow)
return;
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
else
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
}
void CKeybindManager::focusWindowByClass(std::string clazz) {
std::regex classCheck(clazz);
void CKeybindManager::focusWindow(std::string regexp) {
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
for (auto& w : g_pCompositor->m_lWindows) {
if (!w.m_bIsMapped || w.m_bHidden)
continue;
if (!PWINDOW)
return;
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
Debug::log(LOG, "Focusing to window name: %s", PWINDOW->m_szTitle.c_str());
if (!std::regex_search(windowClass, classCheck))
continue;
changeworkspace("[internal]" + std::to_string(PWINDOW->m_iWorkspaceID));
Debug::log(LOG, "Focusing to window name: %s", w.m_szTitle.c_str());
g_pCompositor->focusWindow(PWINDOW);
changeworkspace(std::to_string(w.m_iWorkspaceID));
const auto MIDPOINT = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->focusWindow(&w);
const auto MIDPOINT = w.m_vRealPosition.goalv() + w.m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
break;
}
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
}
void CKeybindManager::setSubmap(std::string submap) {
@@ -1050,3 +1265,31 @@ void CKeybindManager::setSubmap(std::string submap) {
Debug::log(ERR, "Cannot set submap %s, submap doesn't exist (wasn't registered!)", submap.c_str());
}
void CKeybindManager::pass(std::string regexp) {
// find the first window passing the regex
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
if (!PWINDOW) {
Debug::log(ERR, "pass: window not found");
return;
}
const auto PLASTSRF = g_pCompositor->m_pLastFocus;
const auto KEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!KEYBOARD){
Debug::log(ERR, "No kb in pass?");
return;
}
// pass all mf shit
wlr_seat_keyboard_notify_enter(g_pCompositor->m_sSeat.seat, g_pXWaylandManager->getWindowSurface(PWINDOW), KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED);
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED);
wlr_seat_keyboard_notify_enter(g_pCompositor->m_sSeat.seat, PLASTSRF, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
}

View File

@@ -7,31 +7,61 @@
#include <functional>
struct SKeybind {
std::string key = 0;
std::string key = "";
int keycode = -1;
uint32_t modmask = 0;
std::string handler = "";
std::string arg = "";
bool locked = false;
std::string submap = "";
bool release = false;
bool repeat = false;
// DO NOT INITIALIZE
bool shadowed = false;
};
enum eFocusWindowMode {
MODE_CLASS_REGEX = 0,
MODE_TITLE_REGEX,
MODE_ADDRESS,
MODE_PID
};
class CKeybindManager {
public:
CKeybindManager();
bool handleKeybinds(const uint32_t&, const xkb_keysym_t&);
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*);
void addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&);
uint32_t stringToModMask(std::string);
void clearKeybinds();
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0);
std::unordered_map<std::string, std::function<void(std::string)>> m_mDispatchers;
wl_event_source* m_pActiveKeybindEventSource = nullptr;
private:
std::list<SKeybind> m_lKeybinds;
std::deque<xkb_keysym_t> m_dPressedKeysyms;
std::deque<int> m_dPressedKeycodes;
inline static std::string m_szCurrentSelectedSubmap = "";
xkb_keysym_t m_kHeldBack = 0;
SKeybind* m_pActiveKeybind = nullptr;
uint32_t m_uTimeLastMs = 0;
uint32_t m_uLastCode = 0;
bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t);
bool handleInternalKeybinds(xkb_keysym_t);
bool handleVT(xkb_keysym_t);
@@ -61,10 +91,11 @@ private:
static void resizeActive(std::string);
static void moveActive(std::string);
static void circleNext(std::string);
static void focusWindowByClass(std::string);
static void focusWindow(std::string);
static void setSubmap(std::string);
static void pass(std::string);
friend class CCompositor;
};
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;

View File

@@ -4,8 +4,28 @@ IHyprLayout* CLayoutManager::getCurrentLayout() {
switch (m_iCurrentLayoutID) {
case DWINDLE:
return &m_cDwindleLayout;
case MASTER:
return &m_cMasterLayout;
}
// fallback
return &m_cDwindleLayout;
}
void CLayoutManager::switchToLayout(std::string layout) {
if (layout == "dwindle") {
if (m_iCurrentLayoutID != DWINDLE) {
getCurrentLayout()->onDisable();
m_iCurrentLayoutID = DWINDLE;
getCurrentLayout()->onEnable();
}
} else if (layout == "master") {
if (m_iCurrentLayoutID != MASTER) {
getCurrentLayout()->onDisable();
m_iCurrentLayoutID = MASTER;
getCurrentLayout()->onEnable();
}
} else {
Debug::log(ERR, "Unknown layout %s!", layout.c_str());
}
}

View File

@@ -1,20 +1,25 @@
#pragma once
#include "../layout/DwindleLayout.hpp"
#include "../layout/MasterLayout.hpp"
class CLayoutManager {
public:
IHyprLayout* getCurrentLayout();
void switchToLayout(std::string);
private:
enum HYPRLAYOUTS {
DWINDLE = 0,
MASTER
};
HYPRLAYOUTS m_iCurrentLayoutID = DWINDLE;
CHyprDwindleLayout m_cDwindleLayout;
CHyprMasterLayout m_cMasterLayout;
};
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;

View File

@@ -1,34 +1,29 @@
#include "ThreadManager.hpp"
#include "../debug/HyprCtl.hpp"
CThreadManager::CThreadManager() {
m_tMainThread = new std::thread([&]() {
// Call the handle method.
this->handle();
});
m_tMainThread->detach(); // detach and continue.
}
CThreadManager::~CThreadManager() {
//
}
#include "../Compositor.hpp"
int slowUpdate = 0;
void CThreadManager::handle() {
int handleTimer(void* data) {
const auto PTM = (CThreadManager*)data;
g_pConfigManager->tick();
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
return 0;
}
CThreadManager::CThreadManager() {
g_pConfigManager->init();
HyprCtl::startHyprCtlSocket();
while (3.1415f) {
slowUpdate++;
if (slowUpdate >= g_pConfigManager->getInt("general:max_fps")){
g_pConfigManager->tick();
slowUpdate = 0;
}
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
std::this_thread::sleep_for(std::chrono::microseconds(1000000 / g_pConfigManager->getInt("general:max_fps")));
}
wl_event_source_timer_update(m_esConfigTimer, 1000);
}
CThreadManager::~CThreadManager() {
//
}

View File

@@ -9,11 +9,9 @@ public:
CThreadManager();
~CThreadManager();
private:
wl_event_source* m_esConfigTimer;
void handle();
std::thread* m_tMainThread;
private:
};
inline std::unique_ptr<CThreadManager> g_pThreadManager;

View File

@@ -36,7 +36,9 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(pSurface)->toplevel, activate);
else if (wlr_surface_is_xwayland_surface(pSurface)) {
wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate);
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
if (activate)
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
}
}
@@ -153,7 +155,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
if (pWindow->m_uSurface.xwayland->role) {
try {
std::string winrole = std::string(pWindow->m_uSurface.xwayland->role);
if (winrole.find("pop-up") != std::string::npos || winrole.find("task_dialog") != std::string::npos) {
if (winrole.contains("pop-up") || winrole.contains("task_dialog")) {
return true;
}
} catch (std::exception& e) {
@@ -221,6 +223,4 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
}

View File

@@ -0,0 +1,54 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
void Events::listener_newIdleInhibitor(wl_listener* listener, void* data) {
const auto WLRIDLEINHIBITOR = (wlr_idle_inhibitor_v1*)data;
if (!WLRIDLEINHIBITOR)
return;
g_pInputManager->newIdleInhibitor(WLRIDLEINHIBITOR);
}
void CInputManager::newIdleInhibitor(wlr_idle_inhibitor_v1* pInhibitor) {
const auto PINHIBIT = &m_lIdleInhibitors.emplace_back();
Debug::log(LOG, "New idle inhibitor registered");
PINHIBIT->pWlrInhibitor = pInhibitor;
PINHIBIT->hyprListener_Destroy.initCallback(&pInhibitor->events.destroy, [](void* owner, void* data){
const auto PINH = (SIdleInhibitor*)owner;
g_pInputManager->m_lIdleInhibitors.remove(*PINH);
Debug::log(LOG, "Destroyed an idleinhibitor");
g_pInputManager->recheckIdleInhibitorStatus();
}, PINHIBIT, "IdleInhibitor");
PINHIBIT->pWindow = g_pCompositor->getWindowFromSurface(pInhibitor->surface);
if (PINHIBIT->pWindow)
Debug::log(LOG, "IdleInhibitor got window %x (%s)", PINHIBIT->pWindow, PINHIBIT->pWindow->m_szTitle.c_str());
recheckIdleInhibitorStatus();
}
void CInputManager::recheckIdleInhibitorStatus() {
for (auto& ii : m_lIdleInhibitors) {
if (!ii.pWindow) {
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
return;
} else if (g_pHyprRenderer->shouldRenderWindow(ii.pWindow)) {
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
return;
}
}
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, true);
return;
}

View File

@@ -28,6 +28,8 @@ 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;
if (!g_pCompositor->m_bReadyToProcess)
return;
@@ -36,7 +38,17 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
return;
}
if (g_pCompositor->m_sSeat.mouse->virt)
return; // don't refocus on virt
Vector2D mouseCoords = getMouseCoordsInternal();
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
return;
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
bool didConstraintOnCursor = false;
@@ -79,6 +91,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else {
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
g_pCompositor->m_sSeat.mouse->constraintActive = true;
didConstraintOnCursor = true;
}
}
}
@@ -104,16 +117,17 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
ACTIVEWORKSPACE->setActive(true);
// event
g_pEventManager->postEvent(SHyprIPCEvent("activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName));
g_pEventManager->postEvent(SHyprIPCEvent{"activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
}
Vector2D surfaceCoords;
Vector2D surfacePos = Vector2D(-1337, -1337);
CWindow* pFoundWindow = nullptr;
SLayerSurface* pFoundLayerSurface = nullptr;
// overlay is above fullscreen
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
// then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
@@ -123,13 +137,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
surfacePos = pFoundWindow->m_vRealPosition.vec();
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.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_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
pFoundWindow = &(*w);
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_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
pFoundWindow = (*w).get();
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
surfacePos = Vector2D(-1337, -1337);
} else {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
@@ -141,11 +156,27 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
// then windows
if (!foundSurface) {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
if (PMONITOR->specialWorkspaceOpen) {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow && pFoundWindow->m_iWorkspaceID != SPECIAL_WORKSPACE_ID) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
}
} else {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
}
} else
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow) {
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@@ -158,10 +189,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then surfaces below
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords);
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
if (m_ecbClickBehavior == CLICKMODE_KILL)
@@ -171,6 +202,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
g_pCompositor->focusSurface(nullptr);
g_pCompositor->m_pLastWindow = nullptr;
}
return;
}
@@ -188,7 +225,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
if (pFoundWindow) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
if (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
// enter if change floating style
@@ -197,12 +233,18 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else if (*PFOLLOWMOUSE == 2) {
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
}
if (pFoundWindow == g_pCompositor->m_pLastWindow && foundSurface != g_pCompositor->m_pLastFocus) {
// we changed the subsurface
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
}
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
return; // don't enter any new surfaces
} else {
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
}
} else
} else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive)
g_pCompositor->focusSurface(foundSurface);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
@@ -281,6 +323,13 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
return;
}
// notify the keybind manager
static auto *const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
const auto PASS = g_pKeybindManager->onMouseEvent(e);
if (!PASS && !*PPASSMOUSE)
return;
switch (e->state) {
case WLR_BUTTON_PRESSED:
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
@@ -339,6 +388,16 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
m_ecbClickBehavior = CLICKMODE_DEFAULT;
}
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
bool passEvent = g_pKeybindManager->onAxisEvent(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, e->delta, e->delta_discrete, e->source);
}
}
Vector2D CInputManager::getMouseCoordsInternal() {
return Vector2D(g_pCompositor->m_sWLRCursor->x, g_pCompositor->m_sWLRCursor->y);
}
@@ -348,13 +407,14 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->keyboard = keyboard;
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
try {
PNEWKEYBOARD->name = std::string(keyboard->name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "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");
if (m_pActiveKeyboard)
@@ -363,7 +423,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
}
@@ -374,17 +434,26 @@ void CInputManager::setKeyboardLayout() {
}
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(pKeyboard->name);
ASSERT(pKeyboard);
const auto RULES = g_pConfigManager->getString("input:kb_rules");
const auto MODEL = g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
if (!wlr_keyboard_from_input_device(pKeyboard->keyboard))
return;
const auto REPEATRATE = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_rate") : g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_delay") : g_pConfigManager->getInt("input:repeat_delay");
const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
const auto RULES = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_rules") : g_pConfigManager->getString("input:kb_rules");
const auto MODEL = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_model") : g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_layout") : g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_variant") : g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_options") : g_pConfigManager->getString("input:kb_options");
try {
if (RULES != "" && RULES == std::string(pKeyboard->currentRules.rules) && MODEL == std::string(pKeyboard->currentRules.model) && LAYOUT == std::string(pKeyboard->currentRules.layout) && VARIANT == std::string(pKeyboard->currentRules.variant) && OPTIONS == std::string(pKeyboard->currentRules.options)) {
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) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
@@ -393,6 +462,12 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
// we can ignore those and just apply
}
wlr_keyboard_set_repeat_info(wlr_keyboard_from_input_device(pKeyboard->keyboard), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
pKeyboard->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE;
pKeyboard->numlockOn = NUMLOCKON;
xkb_rule_names rules = {
.rules = RULES.c_str(),
.model = MODEL.c_str(),
@@ -400,7 +475,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
.variant = VARIANT.c_str(),
.options = OPTIONS.c_str()};
pKeyboard->currentRules = rules;
pKeyboard->currentRules.rules = RULES;
pKeyboard->currentRules.model = MODEL;
pKeyboard->currentRules.variant = VARIANT;
pKeyboard->currentRules.options = OPTIONS;
pKeyboard->currentRules.layout = LAYOUT;
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
@@ -417,16 +496,20 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
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;
pKeyboard->currentRules.rules = "";
pKeyboard->currentRules.model = "";
pKeyboard->currentRules.variant = "";
pKeyboard->currentRules.options = "";
pKeyboard->currentRules.layout = "";
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP);
wlr_keyboard_modifiers wlrMods = {0};
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
if (NUMLOCKON == 1) {
// lock numlock
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
@@ -435,7 +518,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
}
if (wlrMods.locked != 0) {
wlr_keyboard_notify_modifiers(pKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0);
}
xkb_keymap_unref(KEYMAP);
@@ -444,46 +527,26 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
}
void CInputManager::newMouse(wlr_input_device* mouse) {
void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
m_lMice.emplace_back();
const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse;
PMOUSE->virt = virt;
try {
PMOUSE->name = std::string(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);
if (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);
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
if (g_pConfigManager->getInt("input:touchpad:middle_button_emulation") == 1)
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
else
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
}
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
if (g_pConfigManager->getInt("input:touchpad:tap-to-click") == 1)
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
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, g_pConfigManager->getInt("input:touchpad:natural_scroll"));
else
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:natural_scroll"));
}
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
const auto DWT = static_cast<enum libinput_config_dwt_state>(g_pConfigManager->getInt("input:touchpad:disable_while_typing") != 0);
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
}
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));
}
setMouseConfigs();
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
@@ -495,6 +558,60 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
}
void CInputManager::setMouseConfigs() {
for (auto& m : m_lMice) {
const auto PMOUSE = &m;
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PMOUSE->name);
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(PMOUSE->name, "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);
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
else
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
}
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "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
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED);
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
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(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
else
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "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(PMOUSE->name, "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(PMOUSE->name, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
Debug::log(LOG, "Applied config to mouse %s, sens %.2f", m.name.c_str(), LIBINPUTSENS);
}
}
}
void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
pKeyboard->hyprListener_keyboardDestroy.removeCallback();
pKeyboard->hyprListener_keyboardMod.removeCallback();
@@ -529,32 +646,19 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) {
}
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t* keysyms;
int syms = xkb_state_key_get_syms(pKeyboard->keyboard->keyboard->xkb_state, KEYCODE, &keysyms);
const auto MODS = wlr_keyboard_get_modifiers(pKeyboard->keyboard->keyboard);
bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard);
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
for (int i = 0; i < syms; ++i)
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// hee hee
}
if (!found) {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
if (passEvent) {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
}
}
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &pKeyboard->keyboard->keyboard->modifiers);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
}
void CInputManager::refocus() {
@@ -568,9 +672,12 @@ void CInputManager::updateDragIcon() {
switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) {
case WLR_DRAG_GRAB_KEYBOARD:
break;
case WLR_DRAG_GRAB_KEYBOARD_POINTER:
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
wlr_box box = {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(&box);
g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal();
break;
}
default:
break;
}
@@ -669,4 +776,15 @@ void CInputManager::updateCapabilities(wlr_input_device* pDev) {
}
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
}
}
uint32_t CInputManager::accumulateModsFromAllKBs() {
uint32_t finalMask = 0;
for (auto& kb : m_lKeyboards) {
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
}
return finalMask;
}

View File

@@ -17,11 +17,12 @@ public:
void onMouseMoved(wlr_pointer_motion_event*);
void onMouseWarp(wlr_pointer_motion_absolute_event*);
void onMouseButton(wlr_pointer_button_event*);
void onMouseWheel(wlr_pointer_axis_event*);
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
void onKeyboardMod(void*, SKeyboard*);
void newKeyboard(wlr_input_device*);
void newMouse(wlr_input_device*);
void newMouse(wlr_input_device*, bool virt = false);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
@@ -32,6 +33,7 @@ public:
void refocus();
void setKeyboardLayout();
void setMouseConfigs();
void updateDragIcon();
void updateCapabilities(wlr_input_device*);
@@ -56,18 +58,33 @@ public:
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
// idle inhibitors
std::list<SIdleInhibitor> m_lIdleInhibitors;
void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
void recheckIdleInhibitorStatus();
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
void onSwipeEnd(wlr_pointer_swipe_end_event*);
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
SSwipeGesture m_sActiveSwipe;
SKeyboard* m_pActiveKeyboard = nullptr;
CTimer m_tmrLastCursorMovement;
// for shared mods
uint32_t accumulateModsFromAllKBs();
private:
// for click behavior override
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
Vector2D m_vLastCursorPosFloored = Vector2D();
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);

View File

@@ -0,0 +1,180 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
if (e->fingers != *PSWIPEFINGERS|| *PSWIPE == 0)
return;
int onMonitor = 0;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
onMonitor++;
}
}
if (onMonitor < 2)
return; // disallow swiping when there's 1 workspace on a monitor
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
Debug::log(LOG, "Starting a swipe from %s", PWORKSPACE->m_szName.c_str());
m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE;
m_sActiveSwipe.delta = 0;
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
m_sActiveSwipe.avgSpeed = 0;
m_sActiveSwipe.speedPoints = 0;
}
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
if (!m_sActiveSwipe.pWorkspaceBegin)
return; // no valid swipe
static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
// commit
std::string wsname = "";
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
// revert
if (abs(m_sActiveSwipe.delta) < 2) {
PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
} else {
if (m_sActiveSwipe.delta < 0) {
// to left
PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
} else {
// to right
PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0});
}
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
}
} else if (m_sActiveSwipe.delta < 0) {
// switch to left
const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDLeft));
PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET);
PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
Debug::log(LOG, "Ended swipe to the left");
} else {
// switch to right
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET);
PWORKSPACER->m_fAlpha.setValueAndWarp(255.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
Debug::log(LOG, "Ended swipe to the right");
}
PWORKSPACEL->m_bForceRendering = false;
PWORKSPACER->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin = nullptr;
g_pInputManager->refocus();
}
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
if (!m_sActiveSwipe.pWorkspaceBegin)
return;
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue;
m_sActiveSwipe.delta += *PSWIPEINVR ? -e->dx : e->dx;
m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1);
m_sActiveSwipe.speedPoints++;
std::string wsname = "";
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
return;
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true;
m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST);
if (m_sActiveSwipe.delta < 0) {
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){
m_sActiveSwipe.delta = 0;
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
PWORKSPACE->m_bForceRendering = true;
if (workspaceIDLeft != workspaceIDRight) {
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
PWORKSPACER->m_bForceRendering = false;
}
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
} else {
if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID){
m_sActiveSwipe.delta = 0;
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight);
PWORKSPACE->m_bForceRendering = true;
if (workspaceIDLeft != workspaceIDRight) {
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
PWORKSPACEL->m_bForceRendering = false;
}
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight);
}
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
}

View File

@@ -4,7 +4,13 @@
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PNEWTABLET = &m_lTablets.emplace_back();
PNEWTABLET->wlrTablet = pDevice->tablet;
try {
PNEWTABLET->name = std::string(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Tablet had no name???"); // logic error
}
PNEWTABLET->wlrTablet = wlr_tablet_from_input_device(pDevice);
PNEWTABLET->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWTABLET->wlrTablet->data = PNEWTABLET;
@@ -21,7 +27,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
Debug::log(LOG, "Removed a tablet");
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Axis.initCallback(&pDevice->tablet->events.axis, [](void* owner, void* data) {
PNEWTABLET->hyprListener_Axis.initCallback(&wlr_tablet_from_input_device(pDevice)->events.axis, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_axis_event*)data;
const auto PTAB = (STablet*)owner;
@@ -74,7 +80,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Tip.initCallback(&pDevice->tablet->events.tip, [](void* owner, void* data) {
PNEWTABLET->hyprListener_Tip.initCallback(&wlr_tablet_from_input_device(pDevice)->events.tip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_tip_event*)data;
const auto PTAB = (STablet*)owner;
@@ -92,7 +98,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Button.initCallback(&pDevice->tablet->events.button, [](void* owner, void* data) {
PNEWTABLET->hyprListener_Button.initCallback(&wlr_tablet_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_button_event*)data;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
@@ -101,7 +107,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
PNEWTABLET->hyprListener_Proximity.initCallback(&pDevice->tablet->events.proximity, [](void* owner, void* data) {
PNEWTABLET->hyprListener_Proximity.initCallback(&wlr_tablet_from_input_device(pDevice)->events.proximity, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_proximity_event*)data;
const auto PTAB = (STablet*)owner;
@@ -151,9 +157,15 @@ STabletTool* CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) {
void CInputManager::newTabletPad(wlr_input_device* pDevice) {
const auto PNEWPAD = &m_lTabletPads.emplace_back();
try {
PNEWPAD->name = std::string(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Pad had no name???"); // logic error
}
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {
PNEWPAD->hyprListener_Button.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_button_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -163,7 +175,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Strip.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
PNEWPAD->hyprListener_Strip.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_strip_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -172,7 +184,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Ring.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
PNEWPAD->hyprListener_Ring.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_ring_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -181,7 +193,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
PNEWPAD->hyprListener_Attach.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
PNEWPAD->hyprListener_Attach.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto TABLET = (wlr_tablet_tool*)data;
const auto PPAD = (STabletPad*)owner;

View File

@@ -2,15 +2,14 @@
#include "OpenGL.hpp"
bool CFramebuffer::alloc(int w, int h) {
bool firstAlloc = false;
if (m_iFb == (uint32_t)-1)
{
bool firstAlloc = false;
if (m_iFb == (uint32_t)-1) {
firstAlloc = true;
glGenFramebuffers(1, &m_iFb);
}
if (m_cTex.m_iTexID == 0)
{
if (m_cTex.m_iTexID == 0) {
firstAlloc = true;
glGenTextures(1, &m_cTex.m_iTexID);
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
@@ -20,13 +19,11 @@ bool CFramebuffer::alloc(int w, int h) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
if (firstAlloc || m_Size != Vector2D(w, h))
{
if (firstAlloc || m_Size != Vector2D(w, h)) {
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
@@ -37,7 +34,6 @@ bool CFramebuffer::alloc(int w, int h) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0);
}
@@ -78,3 +74,7 @@ void CFramebuffer::release() {
m_cTex.m_iTexID = 0;
m_iFb = -1;
}
CFramebuffer::~CFramebuffer() {
release();
}

View File

@@ -6,6 +6,8 @@
class CFramebuffer {
public:
~CFramebuffer();
bool alloc(int w, int h);
void bind();
void release();

View File

@@ -146,28 +146,30 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
m_iWLROutputFb = m_iCurrentOutputFb;
// ensure a framebuffer for the monitor exists
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_mMonitorRenderResources[pMonitor].primaryFB.m_Size != pMonitor->vecPixelSize) {
m_mMonitorRenderResources[pMonitor].stencilTex.allocate();
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
m_RenderData.pCurrentMonData->stencilTex.allocate();
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor);
}
// bind the primary Hypr Framebuffer
m_mMonitorRenderResources[pMonitor].primaryFB.bind();
m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pDamage = pDamage;
@@ -186,7 +188,7 @@ void CHyprOpenGLImpl::end() {
m_bEndFrame = true;
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0);
m_bEndFrame = false;
}
@@ -283,11 +285,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glUniform2f(m_shQUAD.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shQUAD.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shQUAD.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shQUAD.getUniformLocation("radius"), round);
glUniform1i(m_shQUAD.getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -309,21 +311,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round) {
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTexture(CTexture(tex), pBox, alpha, round);
renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV);
}
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowCustomUV);
scissor((wlr_box*)nullptr);
}
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@@ -378,22 +380,22 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
glUniform2f(shader->getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(shader->getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(shader->getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(shader->getUniformLocation("radius"), round);
glUniform1i(shader->getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
const float verts[] = {
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
};
const float verts[] = {
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
};
if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
} else {
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -447,10 +449,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB;
const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
const auto PMIRRORSWAPFB = &m_RenderData.pCurrentMonData->mirrorSwapFB;
CFramebuffer* currentRenderToFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB;
CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB;
// declare the draw func
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
@@ -469,11 +471,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
glUniform1f(pShader->getUniformLocation("radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_shBLUR1)
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
glUniform2f(m_shBLUR1.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
else
glUniform2f(glGetUniformLocation(m_shBLUR2.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform2f(m_shBLUR2.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -503,7 +505,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// draw the things.
// first draw is prim -> mirr
PMIRRORFB->bind();
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID);
// damage region will be scaled, make a temp
pixman_region32_t tempDamage;
@@ -565,7 +567,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
}
if (!pixman_region32_not_empty(&inverseOpaque)) {
renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
renderTexture(tex, pBox, a, round, false, true); // reject blurring a fully opaque window
return;
}
@@ -575,7 +577,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_fini(&inverseOpaque);
// bind primary
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
m_RenderData.pCurrentMonData->primaryFB.bind();
// make a stencil for rounded corners to work with blur
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
@@ -588,7 +590,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
renderTexture(tex, pBox, a, round, true); // discard opaque
renderTexture(tex, pBox, a, round, true, true); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, -1);
@@ -599,7 +601,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false);
// render the window, but clear stencil
glClearStencil(0);
@@ -653,18 +655,18 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glUseProgram(m_shBORDER1.program);
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
glUniform4f(glGetUniformLocation(m_shBORDER1.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
glUniform4f(m_shBORDER1.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
const auto FULLSIZE = Vector2D(box->width, box->height);
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "radius"), round);
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "thick"), *PBORDERSIZE);
glUniform1i(glGetUniformLocation(m_shBORDER1.program, "primitiveMultisample"), *PMULTISAMPLE);
glUniform2f(m_shBORDER1.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shBORDER1.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shBORDER1.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shBORDER1.getUniformLocation("radius"), round);
glUniform1f(m_shBORDER1.getUniformLocation("thick"), *PBORDERSIZE);
glUniform1i(m_shBORDER1.getUniformLocation("primitiveMultisample"), *PMULTISAMPLE);
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -696,12 +698,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage;
pixman_region32_init(&fakeDamage);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
begin(PMONITOR, &fakeDamage, true);
pixman_region32_fini(&fakeDamage);
clear(CColor(0,0,0,0)); // JIC
timespec now;
@@ -715,7 +715,9 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0);
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders);
m_bEndFrame = true;
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
g_pConfigManager->setInt("decoration:blur", BLURVAL);
@@ -731,8 +733,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
clear(CColor(0, 0, 0, 0)); // JIC
wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &fullMonBox, 255.f, 0);
wlr_box fullMonBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &fullMonBox, 255.f, 0);
m_bEndFrame = false;
// restore original fb
#ifndef GLES2
@@ -740,9 +744,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
#else
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
#endif
end();
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output);
}
@@ -756,12 +761,10 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage;
pixman_region32_init(&fakeDamage);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
begin(PMONITOR, &fakeDamage, true);
pixman_region32_fini(&fakeDamage);
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
@@ -775,9 +778,13 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
m_bEndFrame = true;
// draw the layer
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
m_bEndFrame = false;
// TODO: WARN:
// revise if any stencil-requiring rendering is done to the layers.
@@ -790,6 +797,8 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
end();
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output);
}
@@ -811,15 +820,18 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
wlr_box windowBox;
// some mafs to figure out the correct box
Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
// the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale)));
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
// TODO: this is wrong on scaled.
windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0);
@@ -842,10 +854,10 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
wlr_box windowBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PLAYER->alpha.fl(), &fakeDamage, 0);
@@ -855,13 +867,13 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) {
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!");
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
const auto col = CColor(*PSHADOWCOL);
const auto col = m_pCurrentWindow->m_cRealShadowColor.col();
float matrix[9];
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
@@ -878,19 +890,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glUseProgram(m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
glUniform4f(m_shSHADOW.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
glUniform2f(m_shSHADOW.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shSHADOW.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shSHADOW.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shSHADOW.getUniformLocation("radius"), range + round);
glUniform1f(m_shSHADOW.getUniformLocation("range"), range);
glUniform1f(m_shSHADOW.getUniformLocation("shadowPower"), SHADOWPOWER);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -912,9 +924,28 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
cairo_set_font_size(CAIRO, FONTSIZE);
cairo_set_source_rgba(CAIRO, 1.f, 1.f, 1.f, 0.32f);
cairo_text_extents_t textExtents;
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
cairo_move_to(CAIRO, m_RenderData.pMonitor->vecPixelSize.x / 2.f - textExtents.width / 2.f, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height - 1);
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
cairo_surface_flush(CAIROSURFACE);
}
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
static auto *const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
// release the last tex if exists
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
PTEX->destroyTexture();
@@ -923,6 +954,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
Debug::log(LOG, "Allocated texture for BGTex");
// TODO: use relative paths to the installation
// or configure the paths at build time
// check if wallpapers exist
if (!std::filesystem::exists("/usr/share/hyprland/wall_8K.png"))
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
@@ -946,6 +980,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
const auto CAIRO = cairo_create(CAIROSURFACE);
if (!*PNOSPLASH)
renderSplash(CAIRO, CAIROSURFACE);
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
@@ -966,9 +1003,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
void CHyprOpenGLImpl::clearWithTex() {
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
static auto *const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
if (!*PRENDERTEX) {
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
}
}
void CHyprOpenGLImpl::destroyMonitorResources(SMonitor* pMonitor) {

View File

@@ -6,6 +6,8 @@
#include <list>
#include <unordered_map>
#include <cairo/cairo.h>
#include "Shaders.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
@@ -29,17 +31,6 @@ inline const float fanVertsFull[] = {
-1.0f, 1.0f
};
struct SCurrentRenderData {
SMonitor* pMonitor = nullptr;
float projection[9];
pixman_region32_t* pDamage = nullptr;
bool renderingPrimarySurface = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
struct SMonitorRenderData {
CFramebuffer primaryFB;
CFramebuffer mirrorFB;
@@ -48,6 +39,18 @@ struct SMonitorRenderData {
CTexture stencilTex;
};
struct SCurrentRenderData {
SMonitor* pMonitor = nullptr;
float projection[9];
SMonitorRenderData* pCurrentMonData = nullptr;
pixman_region32_t* pDamage = nullptr;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
class CHyprOpenGLImpl {
public:
@@ -58,8 +61,8 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowCustomUV = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round);
@@ -102,7 +105,7 @@ private:
bool m_bEndFrame = false;
// Shaders
SQuad m_shQUAD;
CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shRGBX;
CShader m_shEXT;
@@ -119,7 +122,9 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false);
void renderSplash(cairo_t *const, cairo_surface_t *const);
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;

View File

@@ -12,31 +12,53 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY);
wlr_box windowBox;
if (RDATA->surface && surface == RDATA->surface) {
if (RDATA->surface && surface == RDATA->surface)
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
} else { // here we clamp to 2, these might be some tiny specks
else // here we clamp to 2, these might be some tiny specks
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::clamp(surface->current.width, 2, 1337420), std::clamp(surface->current.height, 2, 1337420)};
// squish all oversized but dont in some cases, jesus christ this is a mess
// TODO: this shouldn't be done this way. Custom UV here as well.
// this is fucking horrible
// Issue: will cause oversized apps with reserved area to overflow from the window box. (see chromium on ozone wayland)
const auto PRESQUISHSIZE = Vector2D(windowBox.width, windowBox.height);
if (RDATA->squishOversized) {
if (x + windowBox.width > RDATA->w)
windowBox.width = RDATA->w - x;
if (y + windowBox.height > RDATA->h)
windowBox.height = RDATA->h - y;
}
scaleBox(&windowBox, RDATA->output->scale);
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false;
if (RDATA->surface && surface == RDATA->surface) {
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
if (RDATA->decorate) {
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
}
if (RDATA->blur)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
}
else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
else {
if (RDATA->surface && wlr_surface_is_xdg_surface(RDATA->surface)) {
wlr_box geo;
wlr_xdg_surface_get_geometry(wlr_xdg_surface_from_wlr_surface(RDATA->surface), &geo);
// TODO: continuation of the above madness.
if (geo.x != 0 || geo.y != 0) {
windowBox.width = PRESQUISHSIZE.x;
windowBox.height = PRESQUISHSIZE.y;
}
windowBox.x -= geo.x;
windowBox.y -= geo.y;
}
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false);
}
wlr_surface_send_frame_done(surface, RDATA->when);
@@ -54,8 +76,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
return true;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return true;
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
@@ -74,11 +96,11 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true;
for (auto& m : g_pCompositor->m_lMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
for (auto& m : g_pCompositor->m_vMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
return true;
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (m->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
}
@@ -88,59 +110,59 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
CWindow* pWorkspaceWindow = nullptr;
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID != pWorkspace->m_iID || !w.m_bIsFullscreen)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen)
continue;
// found it!
renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
pWorkspaceWindow = &w;
pWorkspaceWindow = w.get();
}
// then render windows over fullscreen
for (auto& w : g_pCompositor->m_lWindows) {
if (w.m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w.m_bCreatedOverFullscreen || !w.m_bIsMapped)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue;
renderWindow(&w, pMonitor, time, true);
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
// and then special windows
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, pMonitor))
if (!shouldRenderWindow(w.get(), pMonitor))
continue;
// render the bad boy
renderWindow(&w, pMonitor, time, true);
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
// and the overlay layers
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
// on non-full we draw the bar and shit
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
renderLayer(ls, pMonitor, time);
renderLayer(ls.get(), pMonitor, time);
}
}
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
renderLayer(ls, pMonitor, time);
renderLayer(ls.get(), pMonitor, time);
}
renderDragIcon(pMonitor, time);
// if correct monitor draw hyprerror
if (pMonitor == &g_pCompositor->m_lMonitors.front())
if (pMonitor == g_pCompositor->m_vMonitors.front().get())
g_pHyprError->draw();
}
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) {
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode) {
if (pWindow->m_bHidden)
return;
@@ -160,9 +182,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
renderdata.blur = true; // if it shouldn't, it will be ignored later
// apply window special data
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
@@ -173,37 +196,71 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first, if not fullscreen full
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
if (!pWindow->m_bIsX11) {
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
// To everyone who makes apps with improperly aligned surfaces,
// For example chromium, or GTK devs who allow shadows on windows,
// a sincere FUCK YOU.
if (!pWindow->m_bIsX11) {
wlr_box geom;
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
wlr_box geom;
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
// first, check for poorly sized windows.
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
// No special UV mods needed
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
// No special UV mods needed
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
}
// then, if the surface is too big, modify the pos UV
if (geom.width > renderdata.w + 1 || geom.height > renderdata.h + 1) {
const auto OFF = Vector2D(renderdata.w / (double)geom.width, renderdata.h / (double)geom.height);
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D(-1, -1))
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * ((double)renderdata.w / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * ((double)renderdata.h / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y))
);
}
} else {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
}
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
if (renderdata.decorate) {
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f;
wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
scaleBox(&windowBox, pMonitor->scale);
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
}
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
}
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
if (!pWindow->m_bIsX11) {
renderdata.dontRound = false; // restore dontround
renderdata.pMonitor = pMonitor;
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
if (!pWindow->m_bIsX11) {
renderdata.dontRound = false; // restore dontround
renderdata.pMonitor = pMonitor;
renderdata.squishOversized = false; // don't squish popups
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
}
}
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
@@ -217,6 +274,11 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, SMonitor* pMonitor, times
SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y};
renderdata.fadeAlpha = pLayer->alpha.fl();
renderdata.blur = pLayer->forceBlur;
renderdata.surface = pLayer->layerSurface->surface;
renderdata.decorate = false;
renderdata.w = pLayer->layerSurface->surface->current.width;
renderdata.h = pLayer->layerSurface->surface->current.height;
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
}
@@ -228,10 +290,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// Render layer surfaces below windows for monitor
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls, PMONITOR, time);
renderLayer(ls.get(), PMONITOR, time);
}
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls, PMONITOR, time);
renderLayer(ls.get(), PMONITOR, time);
}
// if there is a fullscreen window, render it and then do not render anymore.
@@ -243,63 +305,81 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
return;
}
// Non-floating
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
// Non-floating main
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w.m_bIsFloating)
if (w->m_bIsFloating)
continue; // floating are in the second pass
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_MAIN);
}
// Non-floating popup
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w->m_bIsFloating)
continue; // floating are in the second pass
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_POPUP);
}
// floating on top
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (!w.m_bIsFloating)
if (!w->m_bIsFloating)
continue;
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
}
// and then special
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
if (!shouldRenderWindow(w.get(), PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
}
// Render surfaces above windows for monitor
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
renderLayer(ls, PMONITOR, time);
renderLayer(ls.get(), PMONITOR, time);
}
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
renderLayer(ls, PMONITOR, time);
renderLayer(ls.get(), PMONITOR, time);
}
renderDragIcon(PMONITOR, time);
@@ -424,11 +504,11 @@ void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclu
}
}
void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayerSurface*>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::vector<std::unique_ptr<SLayerSurface>>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
for (auto& ls : layerSurfaces) {
if (ls->fadingOut || ls->readyToDelete)
if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
continue;
const auto PLAYER = ls->layerSurface;
@@ -497,7 +577,7 @@ void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayer
box.y -= PSTATE->margin.bottom;
}
if (box.width <= 0 || box.height <= 0) {
Debug::log(ERR, "LayerSurface %x has a negative/zero w/h???", ls);
Debug::log(ERR, "LayerSurface %x has a negative/zero w/h???", ls.get());
continue;
}
// Apply
@@ -551,6 +631,11 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
// schedule frame events
if (!wl_list_empty(&pSurface->current.frame_callback_list)) {
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
}
if (!pixman_region32_not_empty(&damageBox)) {
pixman_region32_fini(&damageBox);
return;
@@ -558,57 +643,35 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_translate(&damageBox, x, y);
for (auto& m : g_pCompositor->m_lMonitors) {
for (auto& m : g_pCompositor->m_vMonitors) {
double lx = 0, ly = 0;
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m.output, &lx, &ly);
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
pixman_region32_translate(&damageBox, lx, ly);
wlr_region_scale(&damageBox, &damageBox, m.scale);
wlr_output_damage_add(m.damage, &damageBox);
wlr_region_scale(&damageBox, &damageBox, m->scale);
wlr_output_damage_add(m->damage, &damageBox);
pixman_region32_translate(&damageBox, -lx, -ly);
}
pixman_region32_fini(&damageBox);
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1);
pixman_region32_fini(&damageBox);
}
void CHyprRenderer::damageWindow(CWindow* pWindow) {
if (!pWindow->m_bIsFloating) {
// damage by size & pos
// TODO TEMP: revise when added shadows/etc
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
fixedDamageBox.y -= m.vecPosition.y;
scaleBox(&fixedDamageBox, m.scale);
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
} else {
// damage by real size & pos + border size * 2 (JIC)
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box fixedDamageBox = damageBox;
fixedDamageBox.x -= m.vecPosition.x;
fixedDamageBox.y -= m.vecPosition.y;
scaleBox(&fixedDamageBox, m.scale);
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
scaleBox(&fixedDamageBox, m->scale);
wlr_output_damage_add_box(m->damage, &fixedDamageBox);
}
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Window (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
}
void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
@@ -622,10 +685,10 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
}
void CHyprRenderer::damageBox(wlr_box* pBox) {
for (auto& m : g_pCompositor->m_lMonitors) {
wlr_box damageBox = {pBox->x - m.vecPosition.x, pBox->y - m.vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m.scale);
wlr_output_damage_add_box(m.damage, &damageBox);
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m->scale);
wlr_output_damage_add_box(m->damage, &damageBox);
}
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
@@ -639,6 +702,13 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in
damageBox(&box);
}
void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
PIXMAN_DAMAGE_FOREACH(rg) {
const auto RECT = RECTSARR[i];
damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1);
}
}
void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
return;
@@ -649,6 +719,9 @@ void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
wlr_box box = {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(&box);
}
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
@@ -662,14 +735,23 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string&
return DAMAGE_TRACKING_INVALID;
}
void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
bool CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
// if it's disabled, disable and ignore
if (pMonitorRule->disabled) {
wlr_output_enable(pMonitor->output, 0);
wlr_output_commit(pMonitor->output);
Events::listener_monitorDestroy(nullptr, pMonitor->output);
return false;
}
// Check if the rule isn't already applied
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
return;
return true;
}
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
@@ -719,7 +801,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return;
return true;
}
// Preferred is valid
@@ -750,7 +832,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
if (!wlr_output_commit(pMonitor->output)) {
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
return;
return true;
}
int x, y;
@@ -772,6 +854,8 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip
pMonitor->framesToSkip = 1;
return true;
}
void CHyprRenderer::ensureCursorRenderingMode() {
@@ -787,8 +871,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Hiding the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
m_bHasARenderedCursor = true;
@@ -797,8 +881,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Showing the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
}
} else {
m_bHasARenderedCursor = true;
@@ -807,4 +891,4 @@ void CHyprRenderer::ensureCursorRenderingMode() {
bool CHyprRenderer::shouldRenderCursor() {
return m_bHasARenderedCursor;
}
}

View File

@@ -17,6 +17,12 @@ enum DAMAGETRACKINGMODES {
DAMAGE_TRACKING_FULL
};
enum eRenderPassMode {
RENDER_PASS_ALL = 0,
RENDER_PASS_MAIN,
RENDER_PASS_POPUP
};
class CHyprRenderer {
public:
@@ -27,8 +33,9 @@ public:
void damageWindow(CWindow*);
void damageBox(wlr_box*);
void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageRegion(pixman_region32_t*);
void damageMonitor(SMonitor*);
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*);
void ensureCursorRenderingMode();
@@ -39,9 +46,9 @@ public:
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
private:
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
void arrangeLayerArray(SMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
void renderWindow(CWindow*, SMonitor*, timespec*, bool, eRenderPassMode);
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
void renderDragIcon(SMonitor*, timespec*);

View File

@@ -0,0 +1,13 @@
#include "Shader.hpp"
GLint CShader::getUniformLocation(const std::string& unif) {
const auto itpos = m_muUniforms.find(unif);
if (itpos == m_muUniforms.end()) {
const auto unifLoc = glGetUniformLocation(program, unif.c_str());
m_muUniforms[unif] = unifLoc;
return unifLoc;
}
return itpos->second;
}

View File

@@ -1,22 +1,21 @@
#pragma once
#include "../defines.hpp"
struct SQuad {
GLuint program;
GLint proj;
GLint color;
GLint posAttrib;
GLint texAttrib;
};
#include <unordered_map>
class CShader {
public:
GLuint program;
GLint proj;
GLint color;
GLint tex;
GLint alpha;
GLint posAttrib;
GLint texAttrib;
GLint discardOpaque;
GLint getUniformLocation(const std::string&);
private:
std::unordered_map<std::string, GLint> m_muUniforms;
};

View File

@@ -53,6 +53,9 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
if (!g_pCompositor->windowValidMapped(m_pWindow))
return;
if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0))
return; // don't draw invisible shadows
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
@@ -99,6 +102,8 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
scaleBox(&windowBox, pMonitor->scale);
if (windowBox.width < 1 || windowBox.height < 1) {
glDisable(GL_STENCIL_TEST);
@@ -110,7 +115,8 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
glStencilFunc(GL_NOTEQUAL, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
if (*PSHADOWIGNOREWINDOW) {

View File

@@ -40,12 +40,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
// ????
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
if (it->get() == this) {
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
m_pWindow->m_vDecosToRemove.push_back(this);
return;
}
// get the group info
@@ -58,12 +54,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (m_dwGroupMembers.size() == 0) {
// remove
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
if (it->get() == this) {
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
m_pWindow->m_vDecosToRemove.push_back(this);
return;
}
}

View File

@@ -16,7 +16,7 @@ struct SWindowDecorationExtents {
class CWindow;
struct SMonitor;
class IHyprWindowDecoration {
interface IHyprWindowDecoration {
public:
virtual ~IHyprWindowDecoration() = 0;

View File

@@ -34,8 +34,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
@@ -66,8 +65,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
}
@@ -102,8 +100,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
@@ -134,8 +131,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
distances = distances / 4.0;
gl_FragColor = )#" + colorVarName + R"#( * distances;
return;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
}
@@ -176,11 +172,13 @@ void main() {
return;
}
vec4 pixColor = v_color;
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = v_color;
gl_FragColor = pixColor;
})#";
inline const std::string TEXVERTSRC = R"#(