Compare commits

..

396 Commits

Author SHA1 Message Date
Vaxry
8531d1d7a6 Readme: update to mention plugins 2023-03-14 21:56:31 +00:00
stephan-cr
e4b6af41e5 Refactor CMake and Make file (#1766)
* Refactor CMake and Make file

- modernize CMake a bit
- "unscreamify" CMake commands
- replace undocumented CMake option -H by -S in Makefile
- remove unnecessary "cd" in Makefile

* Fix include path to wlroots generated header files
2023-03-14 21:50:30 +00:00
vaxerski
d63e8c8f45 ime: account for text height in popup calcs 2023-03-14 16:46:39 +00:00
vaxerski
7e5a3eb045 ime: fix panels overflowing on corners 2023-03-14 16:12:25 +00:00
vaxerski
f960f72785 input: minor fixes for tiv1 2023-03-14 14:37:00 +00:00
vaxerski
0807b8b95f tiv1: minor fixes for crashes 2023-03-14 13:51:08 +00:00
Vaxry
5dc1a5fec6 input: text-input-v1 support (#1778)
support zwp_text_input_v1

---------

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2023-03-14 12:57:50 +00:00
vaxerski
e749af7b60 dispatchers: remember named workspaces in prev 2023-03-13 15:19:25 +00:00
vaxerski
17deeb07ad master: better cycle 2023-03-13 01:07:05 +00:00
vaxerski
bcd8fe9573 groups: add deco on moveIntoGroup 2023-03-13 00:47:57 +00:00
vaxerski
146d231ec5 config: add key_press_enables_dpms 2023-03-12 13:46:38 +00:00
vaxerski
71ef1bde7e dispatchers: disallow togglesplit on fullscreen 2023-03-11 17:58:34 +00:00
vaxerski
253286669a groups: fix fullscreen behavior with groups 2023-03-10 15:19:09 +00:00
Mihai Fufezan
0ad2d9f0b5 Nix: fix build on aarch64 2023-03-10 11:45:39 +02:00
vaxerski
c9167d9646 blurls: fix address substr length 2023-03-09 14:24:06 +00:00
vaxerski
ca1c1438e3 Compositor: fix crash on exit 2023-03-09 14:19:54 +00:00
vaxerski
878fe20409 [gha] build man pages 2023-03-09 10:55:40 +00:00
Benjamin Asbach
5a5c41301d bugifx: updated urls poiting to old wiki pages (#1738)
Co-authored-by: Benjamin Asbach <asbachb@users.noreply.github.com>
2023-03-09 10:55:17 +00:00
vaxerski
92d2331170 Events: Avoid sending std::nullptr_t in keyboardFocus 2023-03-08 09:46:17 +00:00
vaxerski
a85a6fa6c8 Dwindle: Added default_split_ratio 2023-03-07 14:24:10 +00:00
Stanisław Zagórowski
b11e2eaa3b Fix plugin argument-less hyprctl calls (#1723)
Handle hyprctl command whitespace trimming

might break
2023-03-07 10:42:33 +00:00
vaxerski
0aeb61a95a Opengl: Fix forcefully setting missing time prop to final shader 2023-03-06 19:02:08 +00:00
hillyu
4f647a8e8b fix mfact not applying to addmaster (#1715)
Co-authored-by: Hill <hillyu@live.com>
2023-03-06 09:03:49 +00:00
Jan Beich
7739b776cd config: explicitly use environ(7) after b03c8970e6 (#1708)
src/config/ConfigManager.cpp:40:23: error: use of undeclared identifier 'environ'
    for (char** env = environ; *env; ++env) {
                      ^
2023-03-05 18:39:46 +00:00
opsu
0c8d1ba4a8 Buffer overflow fix (#1707) 2023-03-05 18:16:42 +00:00
hillyu
7ce92f93ad add mfact setting for master layout (#1666)
* add mfact setting for master layout

---------

Co-authored-by: Hill <hillyu@live.com>
2023-03-05 16:29:23 +00:00
vaxerski
b03c8970e6 Allow environment in config 2023-03-05 14:54:32 +00:00
scorpion-26
de5f1b2a83 Optionally expose time to screen shaders (#1700)
* Optionally expose time to screen shaders

Since that collides with damage tracking, it will only be done, when
damage tracking is disabled, meaning this comes at no cost for everyone
not using time.

* Rename m_Timer to m_tGlobalTimer
2023-03-05 14:05:30 +00:00
vaxerski
dc7d783d14 Initialize priority managers before server init 2023-03-05 13:37:21 +00:00
vaxerski
8e5ee31f30 Add env to example cfgs 2023-03-05 13:37:05 +00:00
vaxerski
90c5715bc6 add env dbus opt 2023-03-05 13:15:12 +00:00
vaxerski
d5093f7af0 add env keyword to cfg 2023-03-05 13:12:01 +00:00
vaxerski
4abc608bc0 update dbus env on exec-once dispatches 2023-03-05 12:53:02 +00:00
Mihai Fufezan
7bae0823c8 Nix: move dependency overrides inside wlroots-hyprland call
This fixes overlays failing to build.
Fixes #1704
2023-03-05 14:10:55 +02:00
Mihai Fufezan
5184b542b1 nix: show commit in hyprctl 2023-03-04 18:22:36 +02:00
vaxerski
fea2031bfe systemd: expand sysd import env script 2023-03-04 15:21:27 +00:00
Mihai Fufezan
be22172a35 Nix: simplify CI 2023-03-04 17:03:33 +02:00
vaxerski
b69f40815f opengl: use a passthru shader for final wlr copy 2023-03-04 14:59:27 +00:00
scorpion-26
f678789dfd Fix clang compilation (#1697)
void* + integral type is not allowed on standard C++ and is a GNU
extension
2023-03-04 14:02:40 +00:00
Mihai Fufezan
c386c52cf9 Nix: fix hidpi patch 2023-03-04 15:51:54 +02:00
vaxerski
c444099325 Mirrors: remove accidentally leftover logs 2023-03-04 01:06:16 +00:00
vaxerski
31cd104286 fix warns 2023-03-04 00:53:42 +00:00
vaxerski
1ead6c46f4 Mirrors: minor fixes 2023-03-04 00:48:22 +00:00
vaxerski
fb45f8f2f9 crashReporter: remove inconsistent log from crash reports 2023-03-04 00:14:20 +00:00
Mihai Fufezan
c1217066d1 Nix: fix hyprland-no-hidpi 2023-03-04 00:37:00 +02:00
Froggo
3b41169395 Use ${PREFIX} rather than /usr directly in Makefile, and force the build to attempt compilation even if the user does not have ${PREFIX}/lib write permissions (#1688)
* Force the make process to use ${PREFIX} rather than /usr directly, and make the build attempt to continue even if the user does not have write permissions in ${PREFIX}/lib (for libwlroots)

* Prevent insufficient permissions error with make install

---------

Co-authored-by: Froggo8311 <Froggo8311@localhost>
2023-03-03 22:15:15 +00:00
vaxerski
8bfb2ad2b7 ci: fix arch ci 2023-03-03 21:50:02 +00:00
vaxerski
b602ac0970 [gha] bump flake inputs 2023-03-03 21:33:14 +00:00
vaxerski
a34b747661 update wlroots dep 2023-03-03 21:28:22 +00:00
vaxerski
fe007fd36a xwl: don't try to get unmanaged titles 2023-03-03 19:37:25 +00:00
Stanisław Zagórowski
141365cbc1 Fix plugin config breakage (#1687) 2023-03-03 19:32:44 +00:00
vaxerski
51ce3ddd67 layoutmgr: don't reenable layout on unchanged layout 2023-03-03 14:06:01 +00:00
vaxerski
64f35c0e31 Bezier: Fix incorrect binary search in bezier approx 2023-03-03 13:33:52 +00:00
vaxerski
9c0e2bba54 Renderer: Nuke onWindowResize{start/end} 2023-03-03 13:18:44 +00:00
vaxerski
62e0c9226e Up the bezier bake count 2023-03-03 13:17:11 +00:00
vaxerski
c5aa20f226 fix bezier step approx 2023-03-03 13:08:46 +00:00
vaxerski
66b8629964 Update the debug overlay 2023-03-03 12:15:59 +00:00
vaxerski
9e028d56c0 fix credentials of invalid surfaces 2023-03-03 11:17:43 +00:00
vaxerski
489ef7c51c add toggle group lock 2023-03-02 20:50:37 +00:00
vaxerski
34685a836a Move AnimationManager::tick() to an event loop 2023-03-02 17:30:50 +00:00
vaxerski
dea71875e4 add desc: to getMonitorFromString 2023-03-02 12:04:41 +00:00
vaxerski
76fc12869d nuke cursorSI due to crashes 2023-03-01 22:12:26 +00:00
vaxerski
556c7dd51f reset signal handlers in unrecoverable 2023-03-01 21:55:30 +00:00
vaxerski
52878161e4 add log tail to crash reports 2023-03-01 15:14:35 +00:00
vaxerski
6c250df77e generate coredumps on sigabrt too 2023-03-01 15:08:44 +00:00
vaxerski
7c5c7ced91 Convert reverse iterators to ranges 2023-03-01 14:06:52 +00:00
vaxerski
3cef005fec use XCURSOR_SIZE for internal cursor size 2023-03-01 13:54:48 +00:00
vaxerski
71496a0a3c Fix fatal aborts with X11 OR windows 2023-03-01 13:47:40 +00:00
vaxerski
86acdcf8b6 nuke unmanagedx11 vector 2023-03-01 13:15:51 +00:00
vaxerski
ea717731a4 Simplfy framebuffer erasing in cleanupFadingOut 2023-03-01 10:06:15 +00:00
vaxerski
72f528cb52 [gha] build man pages 2023-03-01 09:33:29 +00:00
vaxerski
0905515c40 use .txt for crash reports 2023-03-01 09:32:31 +00:00
Mihai Fufezan
50a4a74b4e CI/nix: update nix-install-action 2023-03-01 10:05:54 +02:00
Mihai Fufezan
7cbbf9a850 CI/nix: update nix-install-action 2023-03-01 10:03:21 +02:00
vaxerski
0e252d2c77 Don't set surface cursors for overriden 2023-02-28 23:17:27 +00:00
Stanisław Zagórowski
5c93f6947a Unload plugins on compositor cleanup (#1662) 2023-02-28 23:11:49 +00:00
vaxerski
07b98952bc Reset cursor to pointer on focus on interactable deco 2023-02-28 23:06:46 +00:00
vaxerski
cd2399715d Revert small incorrect change to dragging 2023-02-28 22:53:41 +00:00
vaxerski
2187c6cf43 Allow decos to request interactivity 2023-02-28 22:32:42 +00:00
vaxerski
984c2fdc68 Enable manual anims by default 2023-02-28 22:15:18 +00:00
vaxerski
a224d366ca Added mouseMove event 2023-02-28 21:47:00 +00:00
vaxerski
5e48e6b075 Added mouseButton event 2023-02-28 21:45:57 +00:00
vaxerski
72fc309fb1 make window reserved area less stupid 2023-02-28 21:18:13 +00:00
Dashie
7187ea443e Add option to disable/enable mouse window dragging animations (#1658) 2023-02-28 20:50:10 +00:00
vaxerski
91fd854e3b fix warn 2023-02-28 19:37:00 +00:00
vaxerski
4b20d4f1ad Added decoration reserved area 2023-02-28 19:36:36 +00:00
vaxerski
7beb9fd606 Draw HyprError on the last monitor 2023-02-28 19:18:13 +00:00
vaxerski
4d3f2ca96b minor fixes to touch handling 2023-02-28 19:02:30 +00:00
vaxerski
99b7d53817 deny configure requests on drag 2023-02-28 18:52:03 +00:00
vaxerski
7e523e4d5e minor fixes to X11 configure/or handling 2023-02-28 18:50:47 +00:00
vaxerski
89e7d812c8 Include unmapped and hidden windows in hyprctl clients 2023-02-28 12:41:46 +00:00
vaxerski
ac251d7a66 allow focus to grouped windows 2023-02-28 12:34:59 +00:00
vaxerski
49f423aa8f update decos on anim values update 2023-02-27 23:34:41 +00:00
vaxerski
18229043fa Remove useless rax preserve across callq 2023-02-27 19:47:42 +00:00
vaxerski
03d7651916 Plugin Hooks: fix original bytes on %rip accesses 2023-02-27 19:17:58 +00:00
vaxerski
c5d741fb39 Plugin Hooks: fix calls to %rip offsets 2023-02-27 18:34:53 +00:00
vaxerski
3bceabe29b add plugin support to readme 2023-02-27 15:26:44 +00:00
vaxerski
5da96132b9 fix make install 2023-02-27 14:36:59 +00:00
vaxerski
15d108fbc1 fix make install 2023-02-27 14:08:29 +00:00
Vaxry
8b81f41e52 Plugin System (#1590)
---------

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2023-02-27 12:32:38 +00:00
vaxerski
74a10f26a4 remove old unused animation cfgs 2023-02-26 23:14:26 +00:00
Marcus Kellerman
492f36f7df Added center orientation to master layout (#1642)
* Added center orientation to master layout to improve experience on ultra widescreen monitors.

* Added support for orientationcenter layout message for master layout

* Added ability to optionally always center master window when in centered master mode.
2023-02-26 23:12:14 +00:00
vaxerski
2e21ad875b fix cursor image on drag not resize 2023-02-26 23:08:20 +00:00
vaxerski
18ed73f091 Added moveoutofgroup dispatcher 2023-02-26 13:55:35 +00:00
vaxerski
55b412e0f4 Added moveintogroup dispatcher 2023-02-26 13:52:11 +00:00
Ryan Dwyer
3bfaeacf7d movefocus: Set new workspace as active when focusing new monitor (#1640) 2023-02-26 13:44:11 +00:00
Mihai Fufezan
e302724847 use corner cursors on resize (#1638) 2023-02-26 03:56:23 +02:00
vaxerski
edd0a141de don't snap on empty hint 2023-02-25 22:19:51 +00:00
vaxerski
cf566b59ce allow blurls by address 2023-02-25 17:39:26 +00:00
vaxerski
1089e858b4 fix changegroupactive back 2023-02-24 17:24:51 +00:00
vaxerski
60e37d727d fix cyclenext on empty focus 2023-02-23 14:27:43 +00:00
vaxerski
14a2de0d0e add mouse_left _right 2023-02-23 13:55:27 +00:00
vaxerski
2bf7f9e413 fixup constraint snapping on no hint 2023-02-22 23:16:11 +00:00
Ching Pei Yang
513bbb8047 Resize on border icon bug (#1608)
* fix: reset border hover icon on setting empty focus

* cleanup comment

* fix: reset border hover icon on layer surface
2023-02-21 23:57:38 +00:00
vaxerski
f1c9077139 unblock pure wayland compiles 2023-02-21 23:57:08 +00:00
vaxerski
66e3679ba3 Conform to X11 OR surfaces wanting focus 2023-02-21 20:47:02 +00:00
vaxerski
708bb014e9 use sans for fonts instead of noto sans 2023-02-21 19:07:30 +00:00
o69mar
ca3c8cdfae update license on main branch (#1604)
* Update LICENSE
2023-02-21 19:01:40 +00:00
vaxerski
a66ef50469 added a lockgroups dispatcher 2023-02-21 12:13:41 +00:00
vaxerski
431c74f111 remove -g from release compiles 2023-02-20 23:17:31 +00:00
vaxerski
f023126a73 bump ver to 22 2023-02-20 23:05:50 +00:00
Jan Beich
474ada9267 Unbreak CrashReporter on FreeBSD (#1589) 2023-02-20 14:15:15 +00:00
vaxerski
784cdd7638 abort instead of exiting on sigsegv 2023-02-20 11:02:44 +00:00
vaxerski
fc49a055c6 fix warn 2023-02-20 11:01:03 +00:00
vaxerski
be8cf8ea1e Generate symbol info in release for crash reports 2023-02-20 10:57:10 +00:00
vaxerski
0eee57aab9 fixup backtrace curpath 2023-02-20 10:28:16 +00:00
vaxerski
ecd0156265 fix group data in hyprctl 2023-02-20 09:28:42 +00:00
vaxerski
cd6640e890 unset hidden at grouped remove 2023-02-19 23:26:36 +00:00
vaxerski
40622a9e60 properly meld groups together 2023-02-19 22:19:40 +00:00
vaxerski
df2956b411 ignore hidden in allfloat 2023-02-19 22:14:37 +00:00
Vaxry
e5a4c0c986 Group/Tab Rework (#1580) 2023-02-19 21:07:32 +00:00
vaxerski
2363cc2572 bump ver to 21 2023-02-19 20:59:25 +00:00
Vaxry
1b56cc4e99 Added an Event Hook System (#1578)
* added an eventHookSystem

* Add all socket2 events to hooks
2023-02-19 20:54:53 +00:00
vaxerski
6e16627cbc Added execr 2023-02-19 13:59:47 +00:00
vaxerski
67e13fbb64 [gha] build man pages 2023-02-19 13:54:11 +00:00
vaxerski
ad28321a8d update issue guidelines for crash reports 2023-02-19 13:53:38 +00:00
vaxerski
0e5df91e3a adjust crash report paths 2023-02-19 13:51:40 +00:00
vaxerski
38c25bb50d Added a crash reporter 2023-02-19 13:45:56 +00:00
vaxerski
6548439f6c remove constraint recheck log 2023-02-19 12:15:33 +00:00
Ching Pei Yang
c92e0c05e4 Resize on border (#1347) 2023-02-18 22:35:31 +00:00
vaxerski
b944386ca5 reset focus on lock surface destroy 2023-02-18 01:09:01 +00:00
eriedaberrie
be2e4d9dd1 Fix VRR JSON output in hyprctl monitors (#1562) 2023-02-17 10:37:38 +00:00
vaxerski
dbfa6eea7b fixup stutter in rendering with toplevel_export 2023-02-16 22:51:38 +00:00
scorpion-26
f3d1ab55a2 Add vrr to hyprctl monitor (#1560)
Since the (re)addition of vrr in 127e80692f,
it is very useful to know, whether a given monitor has vrr enabled or not,
since not all monitors support it. Now hyprctl reports, whether a
monitor has vrr enabled or not.
2023-02-16 22:20:10 +00:00
vaxerski
ff95721ad9 fix compile for single_pixel_buffer_v1 2023-02-16 13:37:46 +00:00
vaxerski
d710e7347a enable single_pixel_buffer_v1 2023-02-16 12:55:52 +00:00
vaxerski
3fbef25ffc refocus on monitor attach 2023-02-16 12:55:52 +00:00
Mihai Fufezan
ab6a092dbc Nix CI: add GH token (#1557) 2023-02-15 20:45:23 +02:00
wsippel
1992f27a26 ignore VR headsets (#1555)
* ignore VR headsets

don't interact with screens that have the non_desktop property set, fixes #1553

* remove superfluous curly braces
2023-02-15 14:50:51 +00:00
vaxerski
f37866eb7e fix quick start link 2023-02-14 20:28:33 +00:00
vaxerski
87a4cc7654 rethink visible flag in animmgr 2023-02-14 17:44:09 +00:00
vaxerski
fdc847706a ignore damage on hidden windows in animationmanager 2023-02-14 17:14:09 +00:00
vaxerski
61c817319f don't loop border anim on disabled 2023-02-14 17:10:17 +00:00
vaxerski
127e80692f move no_vfr to vfr and add vrr 2023-02-14 17:08:42 +00:00
nub
98c95aa34d focusCurrentOrLast dispatcher (#1545) 2023-02-14 00:46:58 +00:00
vaxerski
6b7e409f05 properly clamp size in dragging floating corners 2023-02-12 22:24:47 +00:00
vaxerski
79ad93d536 clear focus on lockscreen refocus 2023-02-12 19:20:13 +00:00
vaxerski
7d914cd427 force monitor focus on refocus 2023-02-12 10:38:37 +00:00
vaxerski
287f31329e fix json output in hyprctl animations 2023-02-11 20:54:37 +00:00
Philipp Mildenberger
97e0f02621 Fix some issues with a lost focus of the maximized window after using swapwithmaster in fullscreen mode (#1524)
* Fix some issues with a lost focus of the maximized window after using swapwithmaster in fullscreen mode

* Keep current fullscreen mode when `prepareNewFocus` is executed
2023-02-11 13:00:05 +00:00
vaxerski
bda8208aaa render lockscreen in fullscreenworkspace 2023-02-10 22:03:28 +00:00
Philipp Mildenberger
42f4664022 Added support for layoutmsg params and added the param 'newfocus' for 'swapwithmaster' and 'focusmaster' (#1522)
* Added support for layoutmsg params and added the param 'newfocus' for 'swapwithmaster' and 'focusmaster', which lets the user decide what the new focused window should be
2023-02-10 19:13:38 +00:00
vaxerski
d1a7f1dd36 don't alter LS geom on unmap 2023-02-10 12:54:57 +00:00
vaxerski
1dde751da4 fixup LS fs-v1 calcs 2023-02-10 12:53:43 +00:00
David BELEY
7b05133af0 Only use true/false in default config to reduce confusion (#1517) 2023-02-10 00:43:01 +00:00
vaxerski
68f56130ba add misc:mouse_move_focuses_monitor 2023-02-09 15:29:02 +00:00
vaxerski
4ea4efb871 add prev to getWorkspaceIDFromString 2023-02-09 14:15:42 +00:00
Frank Tao
48c86ad863 Update CMakeLists.txt (#1514) 2023-02-09 08:57:26 +00:00
vaxerski
859d6b9b8a fixup ls geom calcs on wp-fs-v1 2023-02-08 22:54:26 +00:00
vaxerski
cb6c47098d use surface size to determine LS size 2023-02-08 22:37:30 +00:00
vaxerski
5eb98c0072 improve VRR state checking with updates to mosthz 2023-02-08 15:18:54 +00:00
vaxerski
863812a097 added activewindowv2 2023-02-06 13:16:59 +00:00
Saltaformajo
4a5c3c4861 explicit config path for autoreload config #1423 (#1494)
* respect explicit config path for autoreload config
2023-02-05 22:53:13 +00:00
eriedaberrie
15544c7544 Update blurriness of layersurfaces after hyprctl keyword blurls (#1493)
* Update blurriness of layersurfaces after hyprctl keyword blurls
2023-02-05 22:46:20 +00:00
Mihai Fufezan
53945cff31 libinput: add tap_button_map (#1495) 2023-02-05 14:17:23 +00:00
vaxerski
760b37f71d properly rid of whitespace chars from cfg lines 2023-02-04 15:22:03 +00:00
vaxerski
a431c1b01c bring back dynamic ls geom updates 2023-02-04 13:12:56 +00:00
Mihai Fufezan
bd2245d642 meson: build in release by default 2023-02-04 01:13:15 +02:00
Max Verevkin
be6325dd4b ext_workspace_unstable: send done after output_enter when wl_output is bound late (#1481) 2023-02-03 21:25:49 +00:00
vaxerski
fcf1bafb09 conform to unmanaged X11 activate requests 2023-02-03 21:21:19 +00:00
vaxerski
6688421240 minor adjustments to xwayland positioning 2023-02-03 21:21:19 +00:00
Max Verevkin
3e6601fa29 ext_workspace_unstable: send output_enter when wl_output is bound late (#1480) 2023-02-03 19:48:08 +00:00
vaxerski
a0bc0e4998 make a null surface focus reset lastfocus 2023-02-03 17:18:22 +00:00
vaxerski
d81f45e54a clear focus on failed unlock attempt 2023-02-03 17:06:07 +00:00
vaxerski
fd3a1cd086 fix crash with libc++ in appid 2023-02-03 16:17:37 +00:00
vaxerski
494103b521 add missing xwayland stub 2023-02-03 14:12:28 +00:00
vaxerski
8e6950e200 place sessionlock surfaces at correct coordinates 2023-02-03 14:00:23 +00:00
vaxerski
9e40e47a2e [gha] bump flake inputs 2023-02-03 12:47:47 +00:00
vaxerski
a46abd8b1a update wlroots dep 2023-02-03 12:43:43 +00:00
vaxerski
129e99a6f6 Implement ext-session-lock-v1 2023-02-03 11:58:55 +00:00
ozwaldorf
32d56fec97 feat: border angle animations (#1469)
Co-authored-by: vaxerski <43317083+vaxerski@users.noreply.github.com>
2023-02-01 21:06:01 +00:00
vaxerski
1a41f729a3 fix legacy system call to create hypr dir 2023-02-01 19:51:22 +00:00
ozwaldorf
445f8c71c5 fix(hyprctl): allow dispatcher to have no args (#1464)
* fix(hyprctl): allow dispatch to have no args

* chore: add .idea/ to gitignore
2023-02-01 10:01:56 +00:00
vaxerski
85c07c2fe0 scale the opaque region in blurring 2023-01-31 12:29:23 +00:00
vaxerski
eaf0fb14c9 reset layout-set render vars on floating 2023-01-31 12:15:40 +00:00
vaxerski
11234529db Simulate mouse movement on unmap of popups and subsurfaces 2023-01-31 00:26:15 +00:00
Jan Beich
f90ff8303b Unbreak build with libc++ (#1457) 2023-01-31 00:03:23 +00:00
vaxerski
d4e2a0fd16 simplify nullcheck in minimize 2023-01-30 14:00:02 +00:00
vaxerski
32381fe6c4 send a 1 on unknown minimize event 2023-01-29 17:02:55 +00:00
vaxerski
5d35c0432b add a minimize ipc event 2023-01-29 16:26:14 +00:00
vaxerski
4c4d3b3aa5 fix urgent hint order in code 2023-01-29 16:20:53 +00:00
vaxerski
b2314aa33a err on invalid transform in monitor cfg 2023-01-29 16:04:50 +00:00
vaxerski
ef12120270 fixup LS scaling impl 2023-01-29 15:58:36 +00:00
vaxerski
3d83a0bc5f enable UV calcs for all surfaces 2023-01-29 13:58:47 +00:00
vaxerski
38011c50ab notify of fractional scale for LS-es 2023-01-29 13:30:51 +00:00
Jan Beich
c3adc9ec56 Get active VT via ioctl instead of sysfs after e90c5c6347 (#1448) 2023-01-29 12:44:38 +00:00
Jan Beich
ff9bcb19fa Allow to disable X11 backend separately from Xwayland after 5a750b485a (#1445) 2023-01-29 12:43:18 +00:00
vaxerski
ce632b7a05 prevent early segfaults on default mouse pos 2023-01-28 18:28:38 +00:00
vaxerski
328e034472 fix clang error 2023-01-28 18:10:57 +00:00
vaxerski
1c1e688564 fix crash in nested non-mouse warps 2023-01-28 17:54:14 +00:00
vaxerski
86f4772bd6 fix clang warn 2023-01-28 17:52:32 +00:00
vaxerski
61c9e50bcd warp cursor on login to center 2023-01-28 12:26:38 +00:00
eriedaberrie
af37a3895f fix: cursor changing on window move and resize (#1371)
* Just use grab cursor for everything
2023-01-27 11:31:56 +00:00
vaxerski
666c805101 fix destroying addon in fractional scale impl 2023-01-27 11:29:56 +00:00
vaxerski
94b7b6b584 added binds:focus_preferred_method 2023-01-26 14:36:22 +00:00
vaxerski
06b17db227 don't set cursor when timeout reached 2023-01-26 10:39:06 +00:00
vaxerski
fc89e70a1f better ls noanim handling 2023-01-25 15:38:21 +00:00
vaxerski
8ae1fd0173 added layer rules 2023-01-25 15:34:13 +00:00
vaxerski
9813ba2f56 Add hyprctl animations 2023-01-25 15:16:28 +00:00
vaxerski
12e293e309 update animated deco values after setprop 2023-01-24 23:52:00 +00:00
vaxerski
da23ec847e fix deprecated-copy warn 2023-01-24 22:46:16 +00:00
vaxerski
84954f376f remove restrictions from setprop for ints 2023-01-24 21:44:54 +00:00
vaxerski
5de659cc7a add fakefullscreen prop to windows in hyprctl 2023-01-24 21:29:27 +00:00
vaxerski
e273717a27 fix typo 2023-01-24 19:31:16 +00:00
vaxerski
a2ae37396f add hyprctl setprop 2023-01-24 19:05:43 +00:00
pranaless
eb9fa8460f fix typo (#1420) 2023-01-24 19:20:50 +02:00
vaxerski
e3d1743722 Revert "use spawn in dbus-env activation"
This reverts commit 63babcba36.

oops.
2023-01-24 16:25:18 +00:00
vaxerski
63babcba36 use spawn in dbus-env activation 2023-01-24 14:05:59 +00:00
vaxerski
1cc7587789 recalculate layout on deco or border change 2023-01-24 14:04:01 +00:00
vaxerski
70b5c1b119 fix clamp in monitor relative 2023-01-23 20:56:43 +00:00
DB
7574b3db64 fix: hyprland crashing wenn moving window -1 from first monitor (#1419)
Co-authored-by: xVermillionx <xVermillionx@notvalid>
2023-01-23 20:56:05 +00:00
vaxerski
cb6e36d804 ignore null ls-es in cleanup 2023-01-23 18:23:44 +00:00
vaxerski
2a5ae435e1 allow preblur for opaque surfaces if alpha not 1 2023-01-23 13:55:11 +00:00
vaxerski
c074f260a1 use proper fade anims for hyprerror 2023-01-23 12:04:48 +00:00
vaxerski
cb98242ea7 remove old comment and fixup lsl var name 2023-01-22 17:03:25 +01:00
vaxerski
147be3e10b use goal size for uv calcs 2023-01-22 16:58:10 +01:00
vaxerski
b963a6624e more verbose logging on invalid var 1 in seterror 2023-01-22 16:51:32 +01:00
vaxerski
ef90a7ad13 fix rounding exceeding max in single-line errors 2023-01-22 16:48:45 +01:00
vaxerski
eb7927d278 fix color typo in hyprerror 2023-01-22 16:45:00 +01:00
vaxerski
8f57db28f7 added hyprctl seterror 2023-01-22 16:38:17 +01:00
vaxerski
7d754b7c22 fix cutting geometry on surfaces spilling out 2023-01-22 16:24:51 +01:00
Cyril Levis
fcbfd19393 feat: add focus to urgent or last window (#1402)
* feat: add focus to urgent or last window

* Rename dispatcher

Co-authored-by: Maxim Baz <git@maximbaz.com>
2023-01-21 11:18:55 +01:00
Mihai Fufezan
e811394603 Nix: update waybar-hyprland, add hyprland-nvidia (#1409)
Also add them to CI
2023-01-21 02:26:29 +02:00
vaxerski
434719611d fix focus history on workspace jumps 2023-01-20 20:57:35 +01:00
vaxerski
5814d9b2a0 make hyprerror follow fadein anim 2023-01-20 20:48:07 +01:00
vaxerski
18330dec4e scale hyprerror 2023-01-20 20:21:50 +01:00
Vaxry
60b880d931 wp-fractional-scaling-v1 impl (#1373)
* Initial fractional scaling impl

* apply UV after geom calcs

* fix scaling -> scale

* meson: add fractional scale proto

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2023-01-20 19:44:30 +01:00
vaxerski
cee7bc6e74 small hyprerror revamp 2023-01-20 19:32:41 +01:00
vaxerski
d345804cd5 fix font color in hyprerror 2023-01-20 19:19:07 +01:00
vaxerski
fb2679d5ef add a focus history vec 2023-01-20 19:15:15 +01:00
vaxerski
6f3548b184 add an urgent event 2023-01-20 19:03:17 +01:00
vaxerski
d5913a23ac reset dragged window on failed begin 2023-01-20 16:30:30 +01:00
vaxerski
3436486575 sanitize scale better 2023-01-20 16:03:52 +01:00
vaxerski
5112056fdb better log wl socket adding and use auto if failed 2023-01-19 16:44:23 +01:00
vaxerski
d8ee624e35 move monitor remove notice up 2023-01-19 16:27:04 +01:00
vaxerski
428063ff23 fix up log types 2023-01-18 16:12:44 +01:00
Mihai Fufezan
32c11bb212 Nix CI: build xdg-desktop-portal-hyprland 2023-01-18 12:54:56 +02:00
Cole Mickens
31ab2349f9 nix: react to another stdenv change (#1399) 2023-01-18 10:37:56 +02:00
scorpion-26
c31c627cf8 Don't ignore previous maximise on defullscreen req (#1393)
When defullscreening a window by the apps' request, we would return
the window to normal mode, even if the window was previously maximized.
Now a defullscreening request honors the previous maximized state.
2023-01-17 13:20:10 +01:00
vaxerski
f14e808847 dump monitor data after setting rules 2023-01-17 11:57:36 +01:00
vaxerski
5c83976977 added misc:hide_cursor_on_touch 2023-01-17 11:47:39 +01:00
vaxerski
2ec7e241cd send cursor updates on touch move 2023-01-17 11:34:57 +01:00
devil-may-c0de
6a56d1e4d0 change placement of isSwitchingToPrevious (#1388)
fixes #1218, but doesn't break functionality of allow_workspace_cycles.
2023-01-16 21:04:10 +01:00
vaxerski
589046ecf7 fix dimaround with transformed displays 2023-01-16 16:12:24 +01:00
ppenguin
040e99fd17 Add tablets calibration matrix for dynamic rotation with 2-in1/tablet PC usage (#1319) 2023-01-15 20:38:58 +01:00
vaxerski
b5b436e01d better error handling around getMonitorFromString 2023-01-14 20:45:28 +01:00
Maxim Baz
668d90c700 Implement urgency hint for workspaces (#1379)
When there are any unfocused windows that request activation, mark the workspace as urgent.
2023-01-14 20:31:11 +01:00
vaxerski
b3012d97ab [gha] bump flake inputs 2023-01-13 21:07:04 +00:00
vaxerski
0b5a751e52 update wlroots dep 2023-01-13 22:06:04 +01:00
Maxim Baz
7729fa9ac9 master layout: remember size & pos of floating windows on fullscreen 1 (#1374) 2023-01-13 21:58:14 +01:00
vaxerski
9c77415cda damage monitor on moveactive 2023-01-13 12:31:24 +01:00
vaxerski
cbd31ba481 damage on border change 2023-01-12 13:33:45 +01:00
vaxerski
8440aa3e9b repaint on dynamic decoration keywords 2023-01-12 12:14:57 +01:00
vaxerski
11afb66010 release mouse buttons on map from LS 2023-01-11 19:15:18 +01:00
vaxerski
c4e422644b move window to top if floating activate 2023-01-11 17:59:35 +01:00
vaxerski
df30f0519a damage monitor on stack rotations 2023-01-11 17:57:54 +01:00
vaxerski
8ba4f34a7c fix cmake systemd header detection 2023-01-11 17:41:03 +01:00
vaxerski
7afb7c85a7 handle fullscreen requests on maximized windows 2023-01-11 13:40:15 +01:00
vaxerski
b24f066c47 escape json strings in hyprctl binds 2023-01-11 12:17:27 +01:00
vaxerski
4ec034ad49 send enter for IME popups 2023-01-10 19:21:59 +01:00
vaxerski
20a1a47e66 replace java envvar 2023-01-09 21:26:19 +01:00
vaxerski
989ee6473f describe layers in hyprctl layers 2023-01-09 21:26:07 +01:00
vaxerski
a572321f61 remove old warn 2023-01-09 20:52:24 +01:00
vaxerski
ff11883482 added make model and serial to hyprctl monitors 2023-01-09 14:35:58 +01:00
Raffaele Mancuso
c0c7c12bb9 Pin dispatcher for a specific window (#1340)
Closes #1339
2023-01-08 18:37:24 +01:00
riChar
e5dcbf73d8 Add "on" and "off" for the bind of switch (#1342) 2023-01-08 16:35:24 +01:00
vaxerski
50e106f2e6 expand region twice in blur damage
we need to update possible blurriness above
2023-01-08 14:46:45 +01:00
Cyril Levis
3173fbdc4a feat: dispatcher, add workspace renaming (#1336)
* feat: dispatcher, add workspace renaming

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

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

see also:
example/ files for example of services

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

* nix: add withSystemd flag

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

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

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

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

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

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

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

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

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

* re-add cleaninstall with deprecation notice

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

65
.clang-format Normal file
View File

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

View File

@@ -12,15 +12,14 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Build wlroots
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots"
su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .."
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Fix permissions for git
run: |
git config --global --add safe.directory /__w/Hyprland/Hyprland
@@ -62,7 +61,14 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
@@ -84,7 +90,14 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Checkout Hyprland
uses: actions/checkout@v3
with:

View File

@@ -5,26 +5,22 @@ jobs:
nix:
name: "Build Hyprland (Nix)"
runs-on: ubuntu-latest
strategy:
matrix:
package:
- default
- hyprland-no-hidpi
steps:
- name: Clone repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install nix
uses: cachix/install-nix-action@v18
uses: cachix/install-nix-action@v20
with:
install_url: https://nixos.org/nix/install
extra_nix_config: |
auto-optimise-store = true
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
with:
name: hyprland
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build Hyprland with default settings
run: nix build .#${{ matrix.package }} --print-build-logs
- name: Build packages
run: nix flake check --print-build-logs --accept-flake-config

View File

@@ -1,26 +0,0 @@
name: "Nix & Meson: update version"
on: [workflow_dispatch]
jobs:
update:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Update flake and meson version
run: |
REGEX="([0-9]+(\.[0-9a-zA-Z]+)+)"
CRT_REV=$(git show-ref --tags --head --abbrev | head -n 1 | head -c 7)
TAG_REV=$(git show-ref --tags --abbrev | tail -n 1 | head -c 7)
CRT_VER=$(sed -nEe "/$REGEX/{p;q;}" meson.build | awk -F\' '{print $2}')
VERSION=$(git show-ref --tags --abbrev | tail -n 1 | tail -c +20)
if [[ $TAG_REV = $CRT_REV ]] || [[ $CRT_VER != $VERSION ]]; then
sed -Ei "s/$REGEX/$VERSION/g" meson.build
sed -Ei "s/$REGEX/$VERSION/g" flake.nix
fi
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "[gha] bump flake and meson version"

View File

@@ -9,14 +9,21 @@ jobs:
- name: Clone repository
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v18
uses: cachix/install-nix-action@v20
with:
install_url: https://nixos.org/nix/install
extra_nix_config: |
auto-optimise-store = true
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
experimental-features = nix-command flakes
- name: Update lockfile
run: nix/update-inputs.sh
- uses: cachix/cachix-action@v12
with:
name: hyprland
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build Waybar-Hyprland
run: nix build .#waybar-hyprland --print-build-logs
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "[gha] bump flake inputs"

2
.gitignore vendored
View File

@@ -12,6 +12,7 @@ _deps
build/
result*
/.vscode/
/.idea/
.envrc
.cache
@@ -19,6 +20,7 @@ result*
*-protocol.c
*-protocol.h
.ccls-cache
*.so
hyprctl/hyprctl

3
.gitmodules vendored
View File

@@ -4,3 +4,6 @@
[submodule "subprojects/hyprland-protocols"]
path = subprojects/hyprland-protocols
url = https://github.com/hyprwm/hyprland-protocols
[submodule "subprojects/udis86"]
path = subprojects/udis86
url = https://github.com/canihavesomecoffee/udis86

View File

@@ -1,6 +1,13 @@
cmake_minimum_required(VERSION 3.4)
project(Hyprland
cmake_minimum_required(VERSION 3.19)
include(CheckIncludeFile)
# Get version
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS)
string(JSON VER GET ${PROPS} version)
project(Hyprland
DESCRIPTION "A Modern C++ Wayland Compositor"
VERSION ${VER}
)
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
@@ -35,49 +42,76 @@ execute_process(
#
#
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
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 )
add_compile_definitions(HYPRLAND_DEBUG)
else()
add_compile_options(-O3)
message(STATUS "Configuring Hyprland in Release with CMake")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
endif()
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
include_directories(
.
"subprojects/wlroots/include/"
"subprojects/wlroots/build/include/"
"subprojects/udis86/")
set(CMAKE_CXX_STANDARD 23)
add_compile_options(-DWLR_USE_UNSTABLE)
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
add_compile_definitions(WLR_USE_UNSTABLE)
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith)
add_link_options(-rdynamic)
set(CMAKE_ENABLE_EXPORTS TRUE)
message(STATUS "Checking deps...")
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
add_executable(Hyprland ${SRCFILES})
IF(LEGACY_RENDERER MATCHES true)
message(STATUS "Using the legacy GLES2 renderer!")
add_definitions( -DLEGACY_RENDERER )
ENDIF(LEGACY_RENDERER MATCHES true)
include(CheckLibraryExists)
check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO)
if(HAVE_LIBEXECINFO)
target_link_libraries(Hyprland PRIVATE execinfo)
endif()
IF(NO_XWAYLAND MATCHES true)
if(LEGACY_RENDERER)
message(STATUS "Using the legacy GLES2 renderer!")
add_compile_definitions(LEGACY_RENDERER)
endif()
if(NO_XWAYLAND)
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
add_definitions( -DNO_XWAYLAND )
ELSE()
add_compile_definitions(NO_XWAYLAND)
else()
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
pkg_check_modules(xcbdep REQUIRED xcb)
target_link_libraries(Hyprland xcb)
ENDIF(NO_XWAYLAND MATCHES true)
endif()
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_DIRTY=\"${GIT_DIRTY}\"")
if(NO_SYSTEMD)
message(STATUS "SYSTEMD support is disabled...")
else()
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...")
pkg_check_modules(LIBSYSTEMD libsystemd)
check_include_file("systemd/sd-daemon.h" SYSTEMDH)
if(LIBSYSTEMD_FOUND AND SYSTEMDH)
add_compile_definitions(USES_SYSTEMD)
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
else()
message(WARNING "Systemd support requested but libsystemd or systemd headers were not found")
endif()
endif()
target_compile_definitions(Hyprland
PRIVATE
"GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\""
"GIT_BRANCH=\"${GIT_BRANCH}\""
"GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\""
"GIT_DIRTY=\"${GIT_DIRTY}\"")
target_link_libraries(Hyprland rt)
@@ -89,15 +123,14 @@ message(STATUS "Setting link libraries")
target_link_libraries(Hyprland PkgConfig::deps)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
target_link_libraries(Hyprland asan)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin -fsanitize=address")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
add_compile_options(-pg -no-pie -fno-builtin -fsanitize=address)
add_link_options(-pg -no-pie -fno-builtin)
endif()
target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
@@ -109,4 +142,7 @@ target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o
${CMAKE_SOURCE_DIR}/fractional-scale-v1-protocol.o
${CMAKE_SOURCE_DIR}/text-input-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a
)

View File

@@ -1,6 +1,6 @@
BSD 3-Clause License
Copyright (c) 2022, vaxerski
Copyright (c) 2022-2023, vaxerski
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -121,20 +121,40 @@ wlr-foreign-toplevel-management-unstable-v1-protocol.c:
wlr-foreign-toplevel-management-unstable-v1-protocol.o: wlr-foreign-toplevel-management-unstable-v1-protocol.h
fractional-scale-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.o: fractional-scale-v1-protocol.h
text-input-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@
text-input-unstable-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@
text-input-unstable-v1-protocol.o: text-input-unstable-v1-protocol.h
legacyrenderer:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j$(shell nproc)
legacyrendererdebug:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j$(shell nproc)
release:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -H./ -B./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j$(shell nproc)
debug:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -H./ -B./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
cmake --build ./build --config Debug --target all -j$(shell nproc)
clear:
@@ -146,24 +166,26 @@ clear:
all:
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 /usr/lib/ && cd ../..
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j$(shell nproc)
make protocols
make release
cd hyprctl && make all && cd ..
make -C hyprctl all
install:
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 /usr/lib/ && cd ../..
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j$(shell nproc) && cd ../..
make protocols
make release
cd hyprctl && make all && cd ..
make -C hyprctl all
mkdir -p /usr/share/wayland-sessions
cp ./example/hyprland.desktop /usr/share/wayland-sessions/
mkdir -p ${PREFIX}/share/wayland-sessions
mkdir -p ${PREFIX}/bin
cp ./build/Hyprland ${PREFIX}/bin
cp ./hyprctl/hyprctl ${PREFIX}/bin
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
@@ -172,34 +194,19 @@ install:
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
cleaninstall:
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 /usr/lib/ && cd ../..
make protocols
make release
cd hyprctl && make all && cd ..
mkdir -p /usr/share/wayland-sessions
mkdir -p ${PREFIX}/bin
cp ./build/Hyprland ${PREFIX}/bin
cp ./hyprctl/hyprctl ${PREFIX}/bin
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
echo -en "make cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning make install instead...\n"
make install
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland
rm -f ${PREFIX}/bin/hyprctl
rm -f /usr/lib/libwlroots.so.12032
rm -f ${PREFIX}/lib/libwlroots.so.12032
rm -rf ${PREFIX}/share/hyprland
rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o text-input-unstable-v1-protocol.o
fixwlr:
sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
@@ -211,10 +218,32 @@ config:
make fixwlr
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release -Dwerror=false -Dexamples=false
cd subprojects/wlroots && ninja -C build/
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false
ninja -C subprojects/wlroots/build/
cd subprojects/wlroots && ninja -C build/ install
ninja -C subprojects/wlroots/build/ install
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j$(shell nproc)
pluginenv:
make protocols
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j$(shell nproc)
make fixwlr
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false
ninja -C subprojects/wlroots/build/
configdebug:
make protocols
make fixwlr
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=debug -Dwerror=false -Dexamples=false -Db_sanitize=address
ninja -C subprojects/wlroots/build/
ninja -C subprojects/wlroots/build/ install
man:
pandoc ./docs/Hyprland.1.rst \

View File

@@ -16,7 +16,7 @@
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, and more.
It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, a powerful plugin system and more.
<br>
<br>
@@ -42,6 +42,7 @@ Although Hyprland is pretty stable, it may have some bugs.
# Features
- Easily expandable and readable codebase
- Plugin support
- Config reloaded instantly upon saving
- Custom bezier curve based animations
- Dual Kawase blur
@@ -130,7 +131,7 @@ Although Hyprland is pretty stable, it may have some bugs.
[Contribute]: https://wiki.hyprland.org/Contributing-and-Debugging/
[Install]: https://wiki.hyprland.org/Getting-Started/Installation/
[Quick Start]: https://wiki.hyprland.org/Getting-Started/Quick-start/
[Quick Start]: https://wiki.hyprland.org/Getting-Started/Master-Tutorial/
[License]: LICENSE
@@ -146,9 +147,9 @@ Although Hyprland is pretty stable, it may have some bugs.
<!----------------------------------{ Images }--------------------------------->
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
[Preview A]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
[Preview B]: https://i.imgur.com/pC6YF1Y.png
[Preview C]: https://i.imgur.com/NbrTnZH.png
[Preview A]: https://i.ibb.co/SX7GbYR/winter-rice.png
[Preview B]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
[Preview C]: https://i.imgur.com/pC6YF1Y.png
<!----------------------------------{ Badges }--------------------------------->

View File

@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "Hyprland" "1" "02 Dec 2022" "" "Hyprland User Manual"
.TH "Hyprland" "1" "09 Mar 2023" "" "Hyprland User Manual"
.hy
.SH NAME
.PP

View File

@@ -3,14 +3,14 @@
First of all, please remember to:
- Check that your issue is not a duplicate
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
- Read the [Configuring Page](https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland)
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland)
<br/>
# Reporting suggestions
Suggestions are welcome.
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://github.com/vaxerski/Hyprland/wiki/IPC). Please do not suggest features that can be implemented as such.
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://wiki.hyprland.org/IPC). Please do not suggest features that can be implemented as such.
<br/>
@@ -25,8 +25,9 @@ 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
- (v0.22.0beta and up) The Hyprland Crash Report
- (v0.21.0beta and below) Coredump / Coredump analysis (with a stacktrace)
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
@@ -44,7 +45,7 @@ cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 2 | tail -n 1)/hyprland.log
basically, directories in /tmp/hypr are your sessions.
## Obtaining the Hyprland coredump
## Obtaining the Hyprland coredump (v0.21.0beta and below)
If you are on systemd, you can simply use
```
coredumpctl
@@ -57,15 +58,25 @@ coredumpctl info [PID]
```
where `[PID]` is the PID you remembered.
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
Go to `~/.hyprland/` and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.
If you do not see it, make sure you have "show hidden files" enabled in your file manager.
Attach that file to your issue.
## Obtaining the debug Hyprland coredump
In very rare cases, the normal coredump would not be enough.
If that's the case, you could try obtaining the debug coredump.
A debug coredump provides more information for debugging and may speed up the process of fixing the bug.
Make sure you're on latest git. Run `git pull --recurse-submodules` to sync everything.
1. [Compile Hyprland with debug mode](http://wiki.hyprland.org/Contributing-and-Debugging/#build-in-debug-mode)
> Note: The config file used will be `hyprlandd.conf` instead of `hyprland.conf`
2. Reproduce the crash in debug mode.
3. `env DEBUGINFOD_URLS="https://debuginfod.archlinux.org/" coredumpctl debug [PID]`(see section above)
4. Wait until the `(gdb)` appears
5. If gdb asks you `press y to continue without paging?` Type `y`
6. `bt -full`
7. copy the output of the command and provide that.
2. `cd ~`
3. For your own convenience, launch Hyprland from a tty with the envvar `ASAN_OPTIONS="log_path=asan.log"`:
- If using a wrapper, add `export ASAN_OPTIONS="log_path=asan.log"` in a separate line before the `exec Hyprland` line.
- If launching straight from the tty, execute `ASAN_OPTIONS="log_path=asan.log" ~/path/to/Hyprland`
4. Reproduce the crash. Hyprland should instantly close.
5. Check out your `~` and find a file called `asan.log.XXXXX` where `XXXXX` will be a number corresponding to the PID of the Hyprland instance that crashed.
6. That is your coredump. Attach it to your issue.

View File

@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "hyprctl" "1" "02 Dec 2022" "" "hyprctl User Manual"
.TH "hyprctl" "1" "09 Mar 2023" "" "hyprctl User Manual"
.hy
.SH NAME
.PP

View File

@@ -0,0 +1,8 @@
# compile with HYPRLAND_HEADERS=<path_to_hl> make all
# make sure that the path above is to the root hl repo directory, NOT src/
# and that you have ran `make protocols` in the hl dir.
all:
g++ -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g -I "/usr/include/pixman-1" -I "/usr/include/libdrm" -I "${HYPRLAND_HEADERS}" -std=c++23
clean:
rm ./examplePlugin.so

View File

@@ -0,0 +1,74 @@
#include "customDecoration.hpp"
#include "../../src/Window.hpp"
#include "../../src/Compositor.hpp"
#include "globals.hpp"
CCustomDecoration::CCustomDecoration(CWindow* pWindow) {
m_pWindow = pWindow;
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
m_vLastWindowSize = pWindow->m_vRealSize.vec();
}
CCustomDecoration::~CCustomDecoration() {
damageEntire();
}
SWindowDecorationExtents CCustomDecoration::getWindowDecorationExtents() {
return m_seExtents;
}
void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
if (!g_pCompositor->windowValidMapped(m_pWindow))
return;
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
static auto* const PCOLOR = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color")->intValue;
static auto* const PROUNDING = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue;
static auto* const PBORDERSIZE = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue;
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ?
0 :
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
// draw the border
wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
fullBox.x += offset.x;
fullBox.y += offset.y;
if (fullBox.width < 1 || fullBox.height < 1)
return; // don't draw invisible shadows
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
}
eDecorationType CCustomDecoration::getDecorationType() {
return DECORATION_CUSTOM;
}
void CCustomDecoration::updateWindow(CWindow* pWindow) {
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
m_vLastWindowSize = pWindow->m_vRealSize.vec();
damageEntire();
}
void CCustomDecoration::damageEntire() {
wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
g_pHyprRenderer->damageBox(&dm);
}

View File

@@ -0,0 +1,29 @@
#pragma once
#define WLR_USE_UNSTABLE
#include "../../src/render/decorations/IHyprWindowDecoration.hpp"
class CCustomDecoration : public IHyprWindowDecoration {
public:
CCustomDecoration(CWindow*);
virtual ~CCustomDecoration();
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(CMonitor*, float a, const Vector2D& offset);
virtual eDecorationType getDecorationType();
virtual void updateWindow(CWindow*);
virtual void damageEntire();
private:
SWindowDecorationExtents m_seExtents;
CWindow* m_pWindow = nullptr;
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
};

View File

@@ -0,0 +1,80 @@
#include "customLayout.hpp"
#include "../../src/Compositor.hpp"
#include "globals.hpp"
void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto SIZE = PMONITOR->vecSize;
// these are used for focus and move calculations, and are *required* to touch for moving focus to work properly.
pWindow->m_vPosition = Vector2D{(SIZE.x / 2.0) * (m_vWindowData.size() % 2), (SIZE.y / 2.0) * (int)(m_vWindowData.size() > 1)};
pWindow->m_vSize = SIZE / 2.0;
// this is the actual pos and size of the window (where it's rendered)
pWindow->m_vRealPosition = pWindow->m_vPosition + Vector2D{10, 10};
pWindow->m_vRealSize = pWindow->m_vSize - Vector2D{20, 20};
const auto PDATA = &m_vWindowData.emplace_back();
PDATA->pWindow = pWindow;
}
void CHyprCustomLayout::onWindowRemovedTiling(CWindow* pWindow) {
std::erase_if(m_vWindowData, [&](const auto& other) { return other.pWindow == pWindow; });
}
bool CHyprCustomLayout::isWindowTiled(CWindow* pWindow) {
return std::find_if(m_vWindowData.begin(), m_vWindowData.end(), [&](const auto& other) { return other.pWindow == pWindow; }) != m_vWindowData.end();
}
void CHyprCustomLayout::recalculateMonitor(const int& eIdleInhibitMode) {
; // empty
}
void CHyprCustomLayout::recalculateWindow(CWindow* pWindow) {
; // empty
}
void CHyprCustomLayout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) {
; // empty
}
void CHyprCustomLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode mode, bool on) {
; // empty
}
std::any CHyprCustomLayout::layoutMessage(SLayoutMessageHeader header, std::string content) {
return "";
}
SWindowRenderLayoutHints CHyprCustomLayout::requestRenderHints(CWindow* pWindow) {
return {};
}
void CHyprCustomLayout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) {
; // empty
}
void CHyprCustomLayout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) {
; // empty
}
std::string CHyprCustomLayout::getLayoutName() {
return "custom";
}
void CHyprCustomLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
; // empty
}
void CHyprCustomLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || w->m_bIsFloating)
continue;
onWindowCreatedTiling(w.get());
}
}
void CHyprCustomLayout::onDisable() {
m_vWindowData.clear();
}

View File

@@ -0,0 +1,32 @@
#pragma once
#define WLR_USE_UNSTABLE
#include "../../src/layout/IHyprLayout.hpp"
struct SWindowData {
CWindow* pWindow = nullptr;
};
class CHyprCustomLayout : 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 alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
virtual void onEnable();
virtual void onDisable();
private:
std::vector<SWindowData> m_vWindowData;
};

View File

@@ -0,0 +1,5 @@
#pragma once
#include <src/plugins/PluginAPI.hpp>
inline HANDLE PHANDLE = nullptr;

View File

@@ -0,0 +1,92 @@
#define WLR_USE_UNSTABLE
#include "globals.hpp"
#include <src/Window.hpp>
#include <src/Compositor.hpp>
#include "customLayout.hpp"
#include "customDecoration.hpp"
#include <unistd.h>
#include <thread>
// Methods
inline std::unique_ptr<CHyprCustomLayout> g_pCustomLayout;
inline CFunctionHook* g_pFocusHook = nullptr;
inline CFunctionHook* g_pMotionHook = nullptr;
inline CFunctionHook* g_pMouseDownHook = nullptr;
typedef void (*origFocusWindow)(void*, CWindow*, wlr_surface*);
typedef void (*origMotion)(wlr_seat*, uint32_t, double, double);
typedef void (*origMouseDownNormal)(void*, wlr_pointer_button_event*);
// Do NOT change this function.
APICALL EXPORT std::string PLUGIN_API_VERSION() {
return HYPRLAND_API_VERSION;
}
static void onActiveWindowChange(void* self, std::any data) {
try {
auto* const PWINDOW = std::any_cast<CWindow*>(data);
HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: " + (PWINDOW ? PWINDOW->m_szTitle : "None"), CColor{0.f, 0.5f, 1.f, 1.f}, 5000);
} catch (std::bad_any_cast& e) { HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: None", CColor{0.f, 0.5f, 1.f, 1.f}, 5000); }
}
static void onNewWindow(void* self, std::any data) {
auto* const PWINDOW = std::any_cast<CWindow*>(data);
HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CCustomDecoration(PWINDOW));
}
void hkFocusWindow(void* thisptr, CWindow* pWindow, wlr_surface* pSurface) {
// HyprlandAPI::addNotification(PHANDLE, getFormat("FocusWindow with %lx %lx", pWindow, pSurface), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
(*(origFocusWindow)g_pFocusHook->m_pOriginal)(thisptr, pWindow, pSurface);
}
void hkNotifyMotion(wlr_seat* wlr_seat, uint32_t time_msec, double sx, double sy) {
// HyprlandAPI::addNotification(PHANDLE, getFormat("NotifyMotion with %lf %lf", sx, sy), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
(*(origMotion)g_pMotionHook->m_pOriginal)(wlr_seat, time_msec, sx, sy);
}
void hkProcessMouseDownNormal(void* thisptr, wlr_pointer_button_event* e) {
// HyprlandAPI::addNotification(PHANDLE, "Mouse down normal!", CColor{0.8f, 0.2f, 0.5f, 1.0f}, 5000);
(*(origMouseDownNormal)g_pMouseDownHook->m_pOriginal)(thisptr, e);
}
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
PHANDLE = handle;
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); });
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); });
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
HyprlandAPI::addLayout(PHANDLE, "custom", g_pCustomLayout.get());
HyprlandAPI::addConfigValue(PHANDLE, "plugin:example:border_color", SConfigValue{.intValue = configStringToInt("rgb(44ee44)")});
HyprlandAPI::addDispatcher(PHANDLE, "example", [](std::string arg) { HyprlandAPI::addNotification(PHANDLE, "Arg passed: " + arg, CColor{0.5f, 0.5f, 0.7f, 1.0f}, 5000); });
// Hook a public member
g_pFocusHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&CCompositor::focusWindow, (void*)&hkFocusWindow);
// Hook a public non-member
g_pMotionHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&wlr_seat_pointer_notify_motion, (void*)&hkNotifyMotion);
// Hook a private member (!WARNING: the signature may differ in clang. This one is for gcc ONLY.)
g_pMouseDownHook = HyprlandAPI::createFunctionHook(
PHANDLE, HyprlandAPI::getFunctionAddressFromSignature(PHANDLE, "_ZN13CInputManager22processMouseDownNormalEP24wlr_pointer_button_event"), (void*)&hkProcessMouseDownNormal);
// Enable our hooks
g_pFocusHook->hook();
g_pMotionHook->hook();
g_pMouseDownHook->hook();
HyprlandAPI::reloadConfig();
return {"ExamplePlugin", "An example plugin", "Vaxry", "1.0"};
}
APICALL EXPORT void PLUGIN_EXIT() {
HyprlandAPI::invokeHyprctlCommand("seterror", "disable");
}

View File

@@ -8,7 +8,7 @@
#
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
monitor=,preferred,auto,auto
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
@@ -19,6 +19,9 @@ monitor=,preferred,auto,1
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# Some default env vars.
env = XCURSOR_SIZE,24
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
kb_layout = us
@@ -30,7 +33,7 @@ input {
follow_mouse = 1
touchpad {
natural_scroll = no
natural_scroll = false
}
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
@@ -52,19 +55,19 @@ decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 10
blur = yes
blur = true
blur_size = 3
blur_passes = 1
blur_new_optimizations = on
blur_new_optimizations = true
drop_shadow = yes
drop_shadow = true
shadow_range = 4
shadow_render_power = 3
col.shadow = rgba(1a1a1aee)
}
animations {
enabled = yes
enabled = true
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
@@ -73,14 +76,15 @@ animations {
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = borderangle, 1, 8, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
dwindle {
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # you probably want this
}
master {
@@ -90,7 +94,7 @@ master {
gestures {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
workspace_swipe = off
workspace_swipe = false
}
# Example per-device config
@@ -111,10 +115,10 @@ $mainMod = SUPER
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, kitty
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, dolphin
bind = $mainMod, V, togglefloating,
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, wofi --show drun
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle

12
example/hyprland.service Normal file
View File

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

13
example/swaybg@.service Normal file
View File

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

48
flake.lock generated
View File

@@ -1,29 +1,17 @@
{
"nodes": {
"hyprland-protocols": {
"flake": false,
"locked": {
"lastModified": 1670703428,
"narHash": "sha256-4KUW5SKR0Y9uaYGcYwy53YJ3B/sgiprCL4fRGO+mpOA=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "d0d6db8cb5bef6d93ca3ad8fb2124964173396da",
"type": "github"
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-protocols",
"type": "github"
}
},
"hyprland-protocols_2": {
"flake": false,
"locked": {
"lastModified": 1670185345,
"narHash": "sha256-hxWGqlPecqEsE6nOHDV29KFBKePbY2Ipeac6lrChMKY=",
"lastModified": 1671839510,
"narHash": "sha256-+PY1qqJfmZzzROgcIY4I7AkCwpnC+qBIYk2eFoA9RWc=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "4623a404c091e64743ba310199bb380ec52f1936",
"rev": "b8f55e02a328c47ed373133c52483bbfa20a1b75",
"type": "github"
},
"original": {
@@ -34,11 +22,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1670064435,
"narHash": "sha256-+ELoY30UN+Pl3Yn7RWRPabykwebsVK/kYE9JsIsUMxQ=",
"lastModified": 1677676435,
"narHash": "sha256-6FxdcmQr5JeZqsQvfinIMr0XcTyTuR7EXX0H3ANShpQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "61a8a98e6d557e6dd7ed0cdb54c3a3e3bbc5e25c",
"rev": "a08d6979dd7c82c4cef0dcc6ac45ab16051c1169",
"type": "github"
},
"original": {
@@ -60,11 +48,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1669925104,
"narHash": "sha256-xMHfW+/G9MieN/5tXHUA5/ztE8dkE093cNFTEUgcwxI=",
"lastModified": 1677789111,
"narHash": "sha256-dWrk+Q3bLdtFe5rkyaAKWCQJCeE/KFNllcu1DvBC38c=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "c8eb24d30e18c165728b8788a10716611c3b633d",
"rev": "5ae17de23f5fd9bb252a698f3771c840280e2c05",
"type": "gitlab"
},
"original": {
@@ -76,17 +64,19 @@
},
"xdph": {
"inputs": {
"hyprland-protocols": "hyprland-protocols_2",
"hyprland-protocols": [
"hyprland-protocols"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1670797151,
"narHash": "sha256-ZFzJHqSXhGCjSeMgqTyJG1KJ2Nlwa+NEN9K4oGhWcjg=",
"lastModified": 1673116118,
"narHash": "sha256-eR0yDSkR2XYMesfdRWJs25kAdXET2mbNNHu5t+KUcKA=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "36ffb6892e14b9c5be6e321b3c47fe286ac256e6",
"rev": "d479c846531fd0e1d2357c9588b8310a2b859ef2",
"type": "github"
},
"original": {

View File

@@ -8,14 +8,15 @@
flake = false;
};
xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland";
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
flake = false;
xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
inputs.hyprland-protocols.follows = "hyprland-protocols";
};
};
@@ -31,28 +32,9 @@
"x86_64-linux"
];
pkgsFor = genSystems (system:
import nixpkgs {
inherit system;
overlays = [
(_: prev: {
libdrm = prev.libdrm.overrideAttrs (old: rec {
version = "2.4.114";
src = prev.fetchurl {
url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz";
sha256 = "sha256-MEnPhDpH0S5e7vvDvjSW14L6CfQjRr8Lfe/j0eWY0CY=";
};
});
wayland-protocols = prev.wayland-protocols.overrideAttrs (old: rec {
version = "1.29";
src = prev.fetchurl {
url = "https://gitlab.freedesktop.org/wayland/${old.pname}/-/releases/${version}/downloads/${old.pname}-${version}.tar.xz";
hash = "sha256-4l6at1rHNnBN3v6S6PmshzC+q29WTbYvetaVu6T/ntg=";
};
});
})
];
});
pkgsFor = nixpkgs.legacyPackages;
props = builtins.fromJSON (builtins.readFile ./props.json);
mkDate = longDate: (lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
@@ -64,25 +46,63 @@
wlroots-hyprland = prev.callPackage ./nix/wlroots.nix {
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101") + "_" + (inputs.wlroots.shortRev or "dirty");
src = inputs.wlroots;
libdisplay-info = prev.libdisplay-info.overrideAttrs (old: {
version = "0.1.1+date=2023-03-02";
src = prev.fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "emersion";
repo = old.pname;
rev = "147d6611a64a6ab04611b923e30efacaca6fc678";
sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4=";
};
});
libliftoff = prev.libliftoff.overrideAttrs (old: {
version = "0.5.0-dev";
src = prev.fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "emersion";
repo = old.pname;
rev = "d98ae243280074b0ba44bff92215ae8d785658c0";
sha256 = "sha256-DjwlS8rXE7srs7A8+tHqXyUsFGtucYSeq6X0T/pVOc8=";
};
NIX_CFLAGS_COMPILE = toString [
"-Wno-error=sign-conversion"
];
});
};
hyprland = prev.callPackage ./nix/default.nix {
stdenv = prev.gcc12Stdenv;
version = "0.18.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
version = props.version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
wlroots = wlroots-hyprland;
inherit (inputs) hyprland-protocols;
commit = self.rev or "";
inherit (inputs.hyprland-protocols.packages.${prev.stdenv.hostPlatform.system}) hyprland-protocols;
inherit udis86;
};
hyprland-debug = hyprland.override {debug = true;};
hyprland-no-hidpi = hyprland.override {hidpiXWayland = false;};
hyprland-nvidia = hyprland.override {nvidiaPatches = true;};
udis86 = prev.callPackage ./nix/udis86.nix {};
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
postPatch = ''
# use hyprctl to switch workspaces
sed -i 's/zext_workspace_handle_v1_activate(workspace_handle_);/const std::string command = "hyprctl dispatch workspace " + name_;\n\tsystem(command.c_str());/g' src/modules/wlr/workspace_manager.cpp
'';
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
});
xdg-desktop-portal-hyprland = inputs.xdph.packages.${prev.system}.default.override {
hyprland-share-picker = inputs.xdph.packages.${prev.system}.hyprland-share-picker.override {inherit hyprland;};
xdg-desktop-portal-hyprland = inputs.xdph.packages.${prev.stdenv.hostPlatform.system}.default.override {
hyprland-share-picker = inputs.xdph.packages.${prev.stdenv.hostPlatform.system}.hyprland-share-picker.override {inherit hyprland;};
};
};
checks = genSystems (system:
(lib.filterAttrs (n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n)) self.packages.${system})
// {inherit (self.packages.${system}) xdg-desktop-portal-hyprland;});
packages = genSystems (system:
(self.overlays.default null pkgsFor.${system})
// {

View File

@@ -27,6 +27,7 @@ commands:
activewindow
layers
devices
binds
dispatch
keyword
version
@@ -38,13 +39,16 @@ commands:
getoption
cursorpos
switchxkblayout
seterror
setprop
plugin
flags:
-j -> output in JSON
--batch -> execute a batch of commands, separated by ';'
)#";
void request(std::string arg, int minArgs = 0) {
void request(std::string arg, int minArgs = 0) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
@@ -59,7 +63,6 @@ void request(std::string arg, int minArgs = 0) {
return;
}
// get the instance signature
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
@@ -71,7 +74,7 @@ void request(std::string arg, int minArgs = 0) {
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
@@ -89,8 +92,8 @@ void request(std::string arg, int minArgs = 0) {
return;
}
std::string reply = "";
char buffer[8192] = {0};
std::string reply = "";
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
@@ -134,7 +137,7 @@ void requestHyprpaper(std::string arg) {
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
@@ -168,7 +171,7 @@ void requestHyprpaper(std::string arg) {
int dispatchRequest(int argc, char** argv) {
if (argc < 4) {
if (argc < 3) {
std::cout << "Usage: hyprctl dispatch <dispatcher> <arg>\n\
Execute a hyprland keybind dispatcher with the given argument";
return 1;
@@ -176,7 +179,7 @@ int dispatchRequest(int argc, char** argv) {
std::string rq = "/dispatch";
for(int i = 2; i < argc; i++) {
for (int i = 2; i < argc; i++) {
if (!strcmp(argv[i], "--"))
continue;
rq += " " + std::string(argv[i]);
@@ -195,7 +198,7 @@ int keywordRequest(int argc, char** argv) {
std::string rq = "/keyword";
for(int i = 2; i < argc; i++)
for (int i = 2; i < argc; i++)
rq += " " + std::string(argv[i]);
request(rq);
@@ -265,7 +268,7 @@ bool isNumber(const std::string& str, bool allowfloat) {
}
int main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c;
int bflag = 0, sflag = 0, index, c;
bool parseArgs = true;
if (argc < 2) {
@@ -274,8 +277,8 @@ int main(int argc, char** argv) {
}
std::string fullRequest = "";
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
for (auto i = 0; i < ARGS.size(); ++i) {
if (ARGS[i] == "--") {
@@ -308,29 +311,59 @@ int main(int argc, char** argv) {
fullRequest.pop_back(); // remove trailing space
fullRequest = fullArgs + "/" + fullRequest;
int exitStatus = 0;
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
else if (fullRequest.contains("/monitors")) request(fullRequest);
else if (fullRequest.contains("/clients")) request(fullRequest);
else if (fullRequest.contains("/workspaces")) request(fullRequest);
else if (fullRequest.contains("/activewindow")) request(fullRequest);
else if (fullRequest.contains("/layers")) request(fullRequest);
else if (fullRequest.contains("/version")) request(fullRequest);
else if (fullRequest.contains("/kill")) request(fullRequest);
else if (fullRequest.contains("/splash")) request(fullRequest);
else if (fullRequest.contains("/devices")) request(fullRequest);
else if (fullRequest.contains("/reload")) request(fullRequest);
else if (fullRequest.contains("/getoption")) request(fullRequest);
else if (fullRequest.contains("/cursorpos")) request(fullRequest);
else if (fullRequest.contains("/switchxkblayout")) request(fullRequest, 2);
else if (fullRequest.contains("/output")) exitStatus = outputRequest(argc, argv);
else if (fullRequest.contains("/setcursor")) exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
if (fullRequest.contains("/--batch"))
batchRequest(fullRequest);
else if (fullRequest.contains("/monitors"))
request(fullRequest);
else if (fullRequest.contains("/clients"))
request(fullRequest);
else if (fullRequest.contains("/workspaces"))
request(fullRequest);
else if (fullRequest.contains("/activewindow"))
request(fullRequest);
else if (fullRequest.contains("/layers"))
request(fullRequest);
else if (fullRequest.contains("/version"))
request(fullRequest);
else if (fullRequest.contains("/kill"))
request(fullRequest);
else if (fullRequest.contains("/splash"))
request(fullRequest);
else if (fullRequest.contains("/devices"))
request(fullRequest);
else if (fullRequest.contains("/reload"))
request(fullRequest);
else if (fullRequest.contains("/getoption"))
request(fullRequest);
else if (fullRequest.contains("/binds"))
request(fullRequest);
else if (fullRequest.contains("/cursorpos"))
request(fullRequest);
else if (fullRequest.contains("/animations"))
request(fullRequest);
else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2);
else if (fullRequest.contains("/seterror"))
request(fullRequest, 1);
else if (fullRequest.contains("/setprop"))
request(fullRequest, 3);
else if (fullRequest.contains("/plugin"))
request(fullRequest, 1);
else if (fullRequest.contains("/output"))
exitStatus = outputRequest(argc, argv);
else if (fullRequest.contains("/setcursor"))
exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch"))
exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword"))
exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper"))
exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help"))
printf("%s", USAGE.c_str());
else {
printf("%s\n", USAGE.c_str());
return 1;

View File

@@ -1,9 +1,11 @@
project('Hyprland', 'cpp', 'c',
version : '0.18.0beta',
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
default_options : [
'warning_level=2',
'default_library=static',
'optimization=3',
'buildtype=release',
'debug=false'
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
])
@@ -41,6 +43,10 @@ wlroots = subproject('wlroots', default_options: ['examples=false'])
have_xwlr = wlroots.get_variable('features').get('xwayland')
xcb_dep = dependency('xcb', required: get_option('xwayland'))
cmake = import('cmake')
udis = cmake.subproject('udis86')
udis86 = udis.dependency('libudis86')
if get_option('xwayland').enabled() and not have_xwlr
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
endif
@@ -50,6 +56,17 @@ if not have_xwayland
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
endif
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
systemd_dep = dependency('libsystemd', required: get_option('systemd'))
if get_option('systemd').enabled()
if systemd_dep.found()
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
else
error('Cannot enable systemd in Hyprland: libsystemd was not found')
endif
endif
if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif

View File

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

View File

@@ -6,16 +6,19 @@
pkg-config,
meson,
ninja,
cairo,
git,
hyprland-protocols,
jq,
libdrm,
libinput,
libxcb,
libxkbcommon,
mesa,
mount,
pango,
pciutils,
systemd,
udis86,
wayland,
wayland-protocols,
wayland-scanner,
@@ -27,7 +30,9 @@
hidpiXWayland ? true,
legacyRenderer ? false,
nvidiaPatches ? false,
withSystemd ? true,
version ? "git",
commit,
}: let
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
Hyprland: cannot have hidpiXWayland when enableXWayland is false.
@@ -49,6 +54,7 @@ in
};
nativeBuildInputs = [
jq
meson
ninja
pkg-config
@@ -62,18 +68,21 @@ in
buildInputs =
[
git
cairo
hyprland-protocols
libdrm
libinput
libxkbcommon
mesa
pango
udis86
wayland
wayland-protocols
wayland-scanner
pciutils
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
]
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland];
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
++ lib.optionals withSystemd [systemd];
mesonBuildType =
if debug
@@ -83,6 +92,7 @@ in
mesonFlags = builtins.concatLists [
(lib.optional (!enableXWayland) "-Dxwayland=disabled")
(lib.optional legacyRenderer "-DLEGACY_RENDERER:STRING=true")
(lib.optional withSystemd "-Dsystemd=enabled")
];
patches = [
@@ -90,13 +100,12 @@ in
./meson-build.patch
];
# Fix hardcoded paths to /usr installation
postPatch = ''
# Fix hardcoded paths to /usr installation
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
# for some reason rmdir doesn't work in a dirty tree
rmdir subprojects/hyprland-protocols || true
ln -s ${hyprland-protocols} subprojects/hyprland-protocols
substituteInPlace meson.build \
--replace "@GIT_COMMIT_HASH@" '${commit}' \
--replace "@GIT_DIRTY@" '${if commit == "" then "dirty" else ""}'
'';
passthru.providedSessions = ["hyprland"];

View File

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

View File

@@ -1,28 +1,45 @@
diff --git a/meson.build b/meson.build
index 22ee4bf..5528613 100644
index f380255..abd7cd3 100644
--- a/meson.build
+++ b/meson.build
@@ -2,16 +2,10 @@ project('Hyprland', 'cpp', 'c',
version : '0.1',
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
@@ -21,9 +21,9 @@ else
endif
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
-GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
+GIT_COMMIT_HASH = '@GIT_COMMIT_HASH@'
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
-GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
+GIT_DIRTY = '@GIT_DIRTY@'
add_project_arguments(
[
@@ -39,23 +39,8 @@ add_project_arguments(
],
language: 'cpp')
-wlroots = subproject('wlroots', default_options: ['examples=false'])
-have_xwlr = wlroots.get_variable('features').get('xwayland')
+wlroots = dependency('wlroots', version: '>=0.16.0')
xcb_dep = dependency('xcb', required: get_option('xwayland'))
-cmake = import('cmake')
-udis = cmake.subproject('udis86')
-udis86 = udis.dependency('libudis86')
-
-if get_option('xwayland').enabled() and not have_xwlr
- error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
-endif
-have_xwayland = xcb_dep.found() and have_xwlr
-
-if not have_xwayland
+if not xcb_dep.found()
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
endif
-add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
-endif
-
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
systemd_dep = dependency('libsystemd', required: get_option('systemd'))
diff --git a/src/meson.build b/src/meson.build
index 5d64188..a676333 100644
index 7b658d3..da8baa5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -7,7 +7,7 @@ executable('Hyprland', src,
@@ -30,7 +47,16 @@ index 5d64188..a676333 100644
dependency('wayland-server'),
dependency('wayland-client'),
- wlroots.get_variable('wlroots'),
+ wlroots,
+ dependency('wlroots'),
dependency('cairo'),
dependency('pango'),
dependency('pangocairo'),
dependency('libdrm'),
dependency('egl'),
@@ -16,7 +16,7 @@ executable('Hyprland', src,
xcb_dep,
backtrace_dep,
systemd_dep,
- udis86,
+ dependency('udis86'),
dependency('pixman-1'),
dependency('gl', 'opengl'),

View File

@@ -8,9 +8,10 @@ inputs: {
with lib; let
cfg = config.programs.hyprland;
defaultHyprlandPackage = inputs.self.packages.${pkgs.system}.default.override {
defaultHyprlandPackage = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
enableXWayland = cfg.xwayland.enable;
hidpiXWayland = cfg.xwayland.hidpi;
nvidiaPatches = cfg.nvidiaPatches;
};
in {
imports = [
@@ -53,6 +54,15 @@ in {
};
};
nvidiaPatches = mkOption {
type = types.bool;
default = false;
example = literalExpression "true";
description = ''
Patch wlroots for better Nvidia support.
'';
};
recommendedEnvironment = mkOption {
type = types.bool;
default = true;
@@ -66,7 +76,7 @@ in {
config = mkIf cfg.enable {
environment = {
systemPackages = lib.optional (cfg.package != null) defaultHyprlandPackage;
systemPackages = lib.optional (cfg.package != null) cfg.package;
sessionVariables = mkIf cfg.recommendedEnvironment {
NIXOS_OZONE_WL = "1";
@@ -79,14 +89,14 @@ in {
xwayland.enable = mkDefault true;
};
security.polkit.enable = true;
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) defaultHyprlandPackage;
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
xdg.portal = {
enable = mkDefault true;
# xdg-desktop-portal-hyprland
extraPortals = lib.mkIf (cfg.package != null) [
(inputs.xdph.packages.${pkgs.system}.xdg-desktop-portal-hyprland.override {
hyprland-share-picker = inputs.xdph.packages.${pkgs.system}.hyprland-share-picker.override {
hyprland = defaultHyprlandPackage;
(inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland.override {
hyprland-share-picker = inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.hyprland-share-picker.override {
hyprland = cfg.package;
};
})
];

32
nix/udis86.nix Normal file
View File

@@ -0,0 +1,32 @@
{
lib,
stdenv,
fetchFromGitHub,
autoreconfHook,
python3,
}:
stdenv.mkDerivation {
pname = "udis86";
version = "unstable-2022-10-13";
src = fetchFromGitHub {
owner = "canihavesomecoffee";
repo = "udis86";
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
};
nativeBuildInputs = [autoreconfHook python3];
configureFlags = ["--enable-shared"];
outputs = ["bin" "out" "dev" "lib"];
meta = with lib; {
homepage = "https://udis86.sourceforge.net";
license = licenses.bsd2;
mainProgram = "udcli";
description = "Easy-to-use, minimalistic x86 disassembler library (libudis86)";
platforms = platforms.all;
};
}

View File

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

164
nix/wlroots-hidpi.patch Normal file
View File

@@ -0,0 +1,164 @@
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
index c69504e8..40d8de8c 100644
--- a/include/xwayland/xwm.h
+++ b/include/xwayland/xwm.h
@@ -88,6 +88,7 @@ enum atom_name {
DND_ACTION_PRIVATE,
NET_CLIENT_LIST,
NET_CLIENT_LIST_STACKING,
+ XWAYLAND_GLOBAL_OUTPUT_SCALE,
ATOM_LAST // keep last
};
@@ -98,6 +99,7 @@ struct wlr_xwm {
struct wl_event_source *event_source;
struct wlr_seat *seat;
uint32_t ping_timeout;
+ uint32_t scale;
xcb_atom_t atoms[ATOM_LAST];
xcb_connection_t *xcb_conn;
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 5a36dc21..83981a87 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -19,6 +19,14 @@
#include <xcb/xfixes.h>
#include "xwayland/xwm.h"
+static int32_t scale(struct wlr_xwm *xwm, uint32_t val) {
+ return val * xwm->scale;
+}
+
+static int32_t unscale(struct wlr_xwm *xwm, uint32_t val) {
+ return (val + xwm->scale/2) / xwm->scale;
+}
+
const char *const atom_map[ATOM_LAST] = {
[WL_SURFACE_ID] = "WL_SURFACE_ID",
[WL_SURFACE_SERIAL] = "WL_SURFACE_SERIAL",
@@ -90,6 +98,7 @@ const char *const atom_map[ATOM_LAST] = {
[DND_ACTION_PRIVATE] = "XdndActionPrivate",
[NET_CLIENT_LIST] = "_NET_CLIENT_LIST",
[NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING",
+ [XWAYLAND_GLOBAL_OUTPUT_SCALE] = "_XWAYLAND_GLOBAL_OUTPUT_SCALE",
};
#define STARTUP_INFO_REMOVE_PREFIX "remove: ID="
@@ -968,8 +977,8 @@ static void xwm_handle_create_notify(struct wlr_xwm *xwm,
return;
}
- xwayland_surface_create(xwm, ev->window, ev->x, ev->y,
- ev->width, ev->height, ev->override_redirect);
+ xwayland_surface_create(xwm, ev->window, unscale(xwm, ev->x), unscale(xwm, ev->y),
+ unscale(xwm, ev->width), unscale(xwm, ev->height), ev->override_redirect);
}
static void xwm_handle_destroy_notify(struct wlr_xwm *xwm,
@@ -1000,10 +1009,10 @@ static void xwm_handle_configure_request(struct wlr_xwm *xwm,
struct wlr_xwayland_surface_configure_event wlr_event = {
.surface = surface,
- .x = mask & XCB_CONFIG_WINDOW_X ? ev->x : surface->x,
- .y = mask & XCB_CONFIG_WINDOW_Y ? ev->y : surface->y,
- .width = mask & XCB_CONFIG_WINDOW_WIDTH ? ev->width : surface->width,
- .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? ev->height : surface->height,
+ .x = mask & XCB_CONFIG_WINDOW_X ? unscale(xwm, ev->x) : surface->x,
+ .y = mask & XCB_CONFIG_WINDOW_Y ? unscale(xwm, ev->y) : surface->y,
+ .width = mask & XCB_CONFIG_WINDOW_WIDTH ? unscale(xwm, ev->width) : surface->width,
+ .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? unscale(xwm, ev->height) : surface->height,
.mask = mask,
};
@@ -1018,14 +1027,14 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm,
}
bool geometry_changed =
- (xsurface->x != ev->x || xsurface->y != ev->y ||
- xsurface->width != ev->width || xsurface->height != ev->height);
+ (xsurface->x != unscale(xwm, ev->x) || xsurface->y != unscale(xwm, ev->y) ||
+ xsurface->width != unscale(xwm, ev->width) || xsurface->height != unscale(xwm, ev->height));
if (geometry_changed) {
- xsurface->x = ev->x;
- xsurface->y = ev->y;
- xsurface->width = ev->width;
- xsurface->height = ev->height;
+ xsurface->x = unscale(xwm, ev->x);
+ xsurface->y = unscale(xwm, ev->y);
+ xsurface->width = unscale(xwm, ev->width);
+ xsurface->height = unscale(xwm, ev->height);
}
if (xsurface->override_redirect != ev->override_redirect) {
@@ -1136,6 +1145,20 @@ static void xwm_handle_property_notify(struct wlr_xwm *xwm,
xcb_property_notify_event_t *ev) {
struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
if (xsurface == NULL) {
+ if (ev->atom == xwm->atoms[XWAYLAND_GLOBAL_OUTPUT_SCALE]) {
+ xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0,
+ ev->window, ev->atom, XCB_ATOM_ANY, 0, 2048);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(xwm->xcb_conn,
+ cookie, NULL);
+ if (reply == NULL) {
+ return;
+ }
+ if (reply->type == XCB_ATOM_CARDINAL) {
+ xwm->scale = *(uint32_t*)xcb_get_property_value(reply);
+ }
+ free(reply);
+ }
+
return;
}
@@ -1763,16 +1786,17 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
int old_w = xsurface->width;
int old_h = xsurface->height;
+ struct wlr_xwm *xwm = xsurface->xwm;
+
xsurface->x = x;
xsurface->y = y;
xsurface->width = width;
xsurface->height = height;
- struct wlr_xwm *xwm = xsurface->xwm;
uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT |
XCB_CONFIG_WINDOW_BORDER_WIDTH;
- uint32_t values[] = {x, y, width, height, 0};
+ uint32_t values[] = {scale(xwm, x), scale(xwm, y), scale(xwm, width), scale(xwm, height), 0};
xcb_configure_window(xwm->xcb_conn, xsurface->window_id, mask, values);
// If the window size did not change, then we cannot rely on
@@ -1780,15 +1804,15 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
// we are supposed to send a synthetic event. See ICCCM part
// 4.1.5. But we ignore override-redirect windows as ICCCM does
// not apply to them.
- if (width == old_w && height == old_h && !xsurface->override_redirect) {
+ if (scale(xwm, width) == scale(xwm, old_w) && scale(xwm, height) == scale(xwm, old_h) && !xsurface->override_redirect) {
xcb_configure_notify_event_t configure_notify = {
.response_type = XCB_CONFIGURE_NOTIFY,
.event = xsurface->window_id,
.window = xsurface->window_id,
- .x = x,
- .y = y,
- .width = width,
- .height = height,
+ .x = scale(xwm, x),
+ .y = scale(xwm, y),
+ .width = scale(xwm, width),
+ .height = scale(xwm, height),
};
xcb_send_event(xwm->xcb_conn, 0, xsurface->window_id,
@@ -2125,6 +2149,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
wl_list_init(&xwm->pending_startup_ids);
xwm->ping_timeout = 10000;
+ xwm->scale = 1;
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
int rc = xcb_connection_has_error(xwm->xcb_conn);

View File

@@ -7,6 +7,8 @@
fetchpatch,
lib,
hwdata,
libliftoff,
libdisplay-info,
hidpiXWayland ? true,
enableXWayland ? true,
nvidiaPatches ? false,
@@ -33,15 +35,19 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
patches =
(old.patches or [])
++ (lib.optionals (enableXWayland && hidpiXWayland) [
(fetchpatch {
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
})
# adapted from https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7
./wlroots-hidpi.patch
(fetchpatch {
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
revert = true;
})
])
++ (lib.optionals nvidiaPatches [
(fetchpatch {
url = "https://aur.archlinux.org/cgit/aur.git/plain/0001-nvidia-format-workaround.patch?h=hyprland-nvidia-screenshare-git";
sha256 = "A9f1p5EW++mGCaNq8w7ZJfeWmvTfUm4iO+1KDcnqYX8=";
})
]);
postPatch =
(old.postPatch or "")
@@ -52,7 +58,11 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
''
else ""
);
buildInputs = old.buildInputs ++ [hwdata];
buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info];
NIX_CFLAGS_COMPILE = toString [
"-Wno-error=maybe-uninitialized"
];
}))
.override {
xwayland = xwayland.overrideAttrs (old: {

3
props.json Normal file
View File

@@ -0,0 +1,3 @@
{
"version": "0.22.0"
}

View File

@@ -21,6 +21,8 @@ wayland_scanner = find_program(
protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
['wlr-foreign-toplevel-management-unstable-v1.xml'],
['wlr-layer-shell-unstable-v1.xml'],
['wlr-output-power-management-unstable-v1.xml'],

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -5,7 +5,8 @@
CWindow::CWindow() {
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_fBorderAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
m_fBorderFadeAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
m_fBorderAngleAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
@@ -16,13 +17,18 @@ CWindow::CWindow() {
CWindow::~CWindow() {
if (g_pCompositor->isWindowActive(this)) {
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastWindow = nullptr;
}
}
wlr_box CWindow::getFullWindowBoundingBox() {
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
}
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
@@ -44,10 +50,8 @@ wlr_box CWindow::getFullWindowBoundingBox() {
}
// Add extents to the real base BB and return
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x,
m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox;
}
@@ -56,11 +60,11 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
auto POS = m_vPosition;
auto SIZE = m_vSize;
auto POS = m_vPosition;
auto SIZE = m_vSize;
if (m_bIsFullscreen) {
POS = PMONITOR->vecPosition;
POS = PMONITOR->vecPosition;
SIZE = PMONITOR->vecSize;
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
@@ -84,6 +88,59 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
}
wlr_box CWindow::getWindowInputBox() {
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
}
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
for (auto& wd : m_dWindowDecorations) {
if (!wd->allowsInput())
continue;
const auto EXTENTS = wd->getWindowDecorationExtents();
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
maxExtents.topLeft.x = EXTENTS.topLeft.x;
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
maxExtents.topLeft.y = EXTENTS.topLeft.y;
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
}
// Add extents to the real base BB and return
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox;
}
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
SWindowDecorationExtents extents;
for (auto& wd : m_dWindowDecorations) {
const auto RESERVED = wd->getWindowDecorationReservedArea();
if (RESERVED.bottomRight == Vector2D{} && RESERVED.topLeft == Vector2D{})
continue;
extents.topLeft = extents.topLeft + RESERVED.topLeft;
extents.bottomRight = extents.bottomRight + RESERVED.bottomRight;
}
return extents;
}
void CWindow::updateWindowDecos() {
for (auto& wd : m_dWindowDecorations)
wd->updateWindow(this);
@@ -104,6 +161,10 @@ void CWindow::updateWindowDecos() {
pid_t CWindow::getPID() {
pid_t PID = -1;
if (!m_bIsX11) {
if (!m_bIsMapped)
return -1;
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
} else {
PID = m_uSurface.xwayland->pid;
@@ -135,25 +196,20 @@ void CWindow::createToplevelHandle() {
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false);
// handle events
hyprListener_toplevelActivate.initCallback(&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) {
hyprListener_toplevelActivate.initCallback(
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pCompositor->focusWindow(this); }, this, "Toplevel");
g_pCompositor->focusWindow(this);
hyprListener_toplevelFullscreen.initCallback(
&m_phForeignToplevel->events.request_fullscreen,
[&](void* owner, void* data) {
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
}, this, "Toplevel");
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
},
this, "Toplevel");
hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) {
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
}, this, "Toplevel");
hyprListener_toplevelClose.initCallback(&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) {
g_pCompositor->closeWindow(this);
}, this, "Toplevel");
hyprListener_toplevelClose.initCallback(
&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) { g_pCompositor->closeWindow(this); }, this, "Toplevel");
m_iLastToplevelMonitorID = m_iMonitorID;
}
@@ -220,7 +276,11 @@ void CWindow::moveToWorkspace(int workspaceID) {
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
EMIT_HOOK_EVENT("moveWindow", (std::vector<void*>{this, PWORKSPACE}));
}
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(g_pXWaylandManager->getWindowSurface(this), PMONITOR->scale);
}
}
@@ -262,13 +322,16 @@ void CWindow::onUnmap() {
m_vRealPosition.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnEnd(unregisterVar);
m_fBorderAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
m_fAlpha.setCallbackOnEnd(unregisterVar);
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
m_fDimPercent.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnBegin(nullptr);
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other == this; });
}
void CWindow::onMap() {
@@ -276,7 +339,8 @@ void CWindow::onMap() {
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
m_vRealPosition.resetAllCallbacks();
m_vRealSize.resetAllCallbacks();
m_fBorderAnimationProgress.resetAllCallbacks();
m_fBorderFadeAnimationProgress.resetAllCallbacks();
m_fBorderAngleAnimationProgress.resetAllCallbacks();
m_fActiveInactiveAlpha.resetAllCallbacks();
m_fAlpha.resetAllCallbacks();
m_cRealShadowColor.resetAllCallbacks();
@@ -284,18 +348,35 @@ void CWindow::onMap() {
m_vRealPosition.registerVar();
m_vRealSize.registerVar();
m_fBorderAnimationProgress.registerVar();
m_fBorderFadeAnimationProgress.registerVar();
m_fBorderAngleAnimationProgress.registerVar();
m_fActiveInactiveAlpha.registerVar();
m_fAlpha.registerVar();
m_cRealShadowColor.registerVar();
m_fDimPercent.registerVar();
m_vRealSize.setCallbackOnEnd([&] (void* ptr) {
g_pHyprOpenGL->onWindowResizeEnd(this);
}, false);
m_vRealSize.setCallbackOnBegin([&] (void* ptr) {
g_pHyprOpenGL->onWindowResizeStart(this);
}, false);
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
m_fBorderAngleAnimationProgress = 1.f;
g_pCompositor->m_vWindowFocusHistory.push_back(this);
}
void CWindow::onBorderAngleAnimEnd(void* ptr) {
const auto PANIMVAR = (CAnimatedVariable*)ptr;
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled)
return;
PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
PANIMVAR->setValueAndWarp(0);
*PANIMVAR = 1.f;
PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
}
void CWindow::setHidden(bool hidden) {
@@ -323,9 +404,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
} else if (r.szRule.find("rounding") == 0) {
try {
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
} catch (std::exception& e) {
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule.find("opacity") == 0) {
try {
CVarList vars(r.szRule, 0, ' ');
@@ -346,47 +425,194 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
}
}
}
} catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} else if (r.szRule == "noanim") {
m_sAdditionalConfigData.forceNoAnims = true;
} else if (r.szRule.find("animation") == 0) {
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
m_sAdditionalConfigData.animationStyle = STYLE;
} else if (r.szRule.find("bordercolor") == 0) {
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule == "noanim") {
m_sAdditionalConfigData.forceNoAnims = true;
} else if (r.szRule.find("animation") == 0) {
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
m_sAdditionalConfigData.animationStyle = STYLE;
} else if (r.szRule.find("bordercolor") == 0) {
try {
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
if (colorPart.contains(' ')) {
// we have a space, 2 values
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1));
} else {
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart);
}
} catch(std::exception& e) {
Debug::log(ERR, "BorderColor rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule == "dimaround") {
m_sAdditionalConfigData.dimAround = true;
}
}
void CWindow::updateDynamicRules() {
m_sSpecialRenderData.activeBorderColor = -1;
m_sSpecialRenderData.activeBorderColor = -1;
m_sSpecialRenderData.inactiveBorderColor = -1;
m_sSpecialRenderData.alpha = 1.f;
m_sSpecialRenderData.alphaInactive = -1.f;
m_sAdditionalConfigData.forceNoBlur = false;
m_sAdditionalConfigData.forceNoBorder = false;
m_sAdditionalConfigData.forceNoShadow = false;
m_sSpecialRenderData.alpha = 1.f;
m_sSpecialRenderData.alphaInactive = -1.f;
m_sAdditionalConfigData.forceNoBlur = false;
m_sAdditionalConfigData.forceNoBorder = false;
m_sAdditionalConfigData.forceNoShadow = false;
if (!m_sAdditionalConfigData.forceOpaqueOverriden)
m_sAdditionalConfigData.forceOpaque = false;
m_sAdditionalConfigData.forceNoAnims = false;
m_sAdditionalConfigData.animationStyle = "";
m_sAdditionalConfigData.rounding = -1;
m_sAdditionalConfigData.forceNoAnims = false;
m_sAdditionalConfigData.animationStyle = std::string("");
m_sAdditionalConfigData.rounding = -1;
m_sAdditionalConfigData.dimAround = false;
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
for (auto& r : WINDOWRULES) {
applyDynamicRule(r);
}
}
// check if the point is "hidden" under a rounded corner of the window
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// otherwise behaviour is undefined
bool CWindow::isInCurvedCorner(double x, double y) {
static auto* const ROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
static auto* const BORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
if (BORDERSIZE >= ROUNDING || ROUNDING == 0)
return false;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
double x0 = m_vRealPosition.vec().x + *ROUNDING;
double y0 = m_vRealPosition.vec().y + *ROUNDING;
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - *ROUNDING;
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - *ROUNDING;
if (x < x0 && y < y0) {
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING;
}
if (x > x1 && y < y0) {
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING;
}
if (x < x0 && y > y1) {
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING;
}
if (x > x1 && y > y1) {
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING;
}
return false;
}
void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
const auto DATA = (SExtensionFindingData*)data;
wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y))
*DATA->found = surface;
}
// checks if the wayland window has a popup at pos
bool CWindow::hasPopupAt(const Vector2D& pos) {
if (m_bIsX11)
return false;
wlr_surface* resultSurf = nullptr;
Vector2D origin = m_vRealPosition.vec();
SExtensionFindingData data = {origin, pos, &resultSurf};
wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data);
return resultSurf;
}
CWindow* CWindow::getGroupHead() {
CWindow* curr = this;
while (!curr->m_sGroupData.head)
curr = curr->m_sGroupData.pNextWindow;
return curr;
}
CWindow* CWindow::getGroupTail() {
CWindow* curr = this;
while (!curr->m_sGroupData.pNextWindow->m_sGroupData.head)
curr = curr->m_sGroupData.pNextWindow;
return curr;
}
CWindow* CWindow::getGroupCurrent() {
CWindow* curr = this;
while (curr->isHidden())
curr = curr->m_sGroupData.pNextWindow;
return curr;
}
void CWindow::setGroupCurrent(CWindow* pWindow) {
CWindow* curr = this->m_sGroupData.pNextWindow;
bool isMember = false;
while (curr != this) {
if (curr == pWindow) {
isMember = true;
break;
}
curr = curr->m_sGroupData.pNextWindow;
}
if (!isMember && pWindow != this)
return;
const auto PCURRENT = getGroupCurrent();
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID);
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv();
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv();
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
if (FULLSCREEN)
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
PCURRENT->setHidden(true);
pWindow->setHidden(false);
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
if (PCURRENT->m_bIsFloating) {
pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS);
pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE);
}
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
if (CURRENTISFOCUS)
g_pCompositor->focusWindow(pWindow);
if (FULLSCREEN)
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
}
void CWindow::insertWindowToGroup(CWindow* pWindow) {
const auto PHEAD = getGroupHead();
const auto PTAIL = getGroupTail();
if (pWindow->m_sGroupData.pNextWindow) {
std::vector<CWindow*> members;
CWindow* curr = pWindow;
do {
const auto PLAST = curr;
members.push_back(curr);
curr = curr->m_sGroupData.pNextWindow;
PLAST->m_sGroupData.pNextWindow = nullptr;
PLAST->m_sGroupData.head = false;
} while (curr != pWindow);
for (auto& w : members) {
insertWindowToGroup(w);
}
return;
}
PTAIL->m_sGroupData.pNextWindow = pWindow;
pWindow->m_sGroupData.pNextWindow = PHEAD;
setGroupCurrent(pWindow);
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -17,7 +17,7 @@ OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
autogenerated = 1 # remove this line to remove the warning
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
monitor=,preferred,auto,auto
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
@@ -28,6 +28,9 @@ monitor=,preferred,auto,1
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# Some default env vars.
env = XCURSOR_SIZE,24
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
kb_layout = us
@@ -82,6 +85,7 @@ animations {
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = borderangle, 1, 8, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}

144
src/debug/CrashReporter.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include "CrashReporter.hpp"
#include <random>
#include <sys/utsname.h>
#include <execinfo.h>
#include <fstream>
#include <signal.h>
#include "../plugins/PluginSystem.hpp"
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
#endif
std::string getRandomMessage() {
const std::vector<std::string> MESSAGES = {"Sorry, didn't mean to...",
"This was an accident, I swear!",
"Calm down, it was a misinput! MISINPUT!",
"Oops",
"Vaxry is going to be upset.",
"Who tried dividing by zero?!",
"Maybe you should try dusting your PC in the meantime?",
"I tried so hard, and got so far...",
"I don't feel so good...",
"*thud*",
"Well this is awkward.",
"\"stable\"",
"I hope you didn't have any unsaved progress."};
std::random_device dev;
std::mt19937 engine(dev());
std::uniform_int_distribution<> distribution(0, MESSAGES.size() - 1);
return MESSAGES[distribution(engine)];
}
void CrashReporter::createAndSaveCrash(int sig) {
// get the backtrace
const int PID = getpid();
std::string finalCrashReport = "";
finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n";
finalCrashReport += getRandomMessage() + "\n\n";
finalCrashReport += getFormat("Hyprland received signal %d (%s)\n\n", sig, strsignal(sig));
if (!g_pPluginSystem->getAllPlugins().empty()) {
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
for (auto& p : g_pPluginSystem->getAllPlugins()) {
finalCrashReport += getFormat("\t%s (%s) %s\n", p->name.c_str(), p->author.c_str(), p->version.c_str());
}
finalCrashReport += "\n\n";
}
finalCrashReport += "System info:\n";
struct utsname unameInfo;
uname(&unameInfo);
finalCrashReport +=
getFormat("\tSystem name: %s\n\tNode name: %s\n\tRelease: %s\n\tVersion: %s\n\n", unameInfo.sysname, unameInfo.nodename, unameInfo.release, unameInfo.version);
#if defined(__DragonFly__) || defined(__FreeBSD__)
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
#else
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
#endif
finalCrashReport += "GPU:\n\t" + GPUINFO;
finalCrashReport += getFormat("\n\nos-release:\n\t%s\n\n\n", replaceInString(execAndGet("cat /etc/os-release"), "\n", "\n\t").c_str());
finalCrashReport += "Backtrace:\n";
void* bt[1024];
size_t btSize;
char** btSymbols;
btSize = backtrace(bt, 1024);
btSymbols = backtrace_symbols(bt, btSize);
#if defined(KERN_PROC_PATHNAME)
int mib[] = {
CTL_KERN,
#if defined(__NetBSD__)
KERN_PROC_ARGS,
-1,
KERN_PROC_PATHNAME,
#else
KERN_PROC,
KERN_PROC_PATHNAME,
-1,
#endif
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
char exe[PATH_MAX] = "";
size_t sz = sizeof(exe);
sysctl(mib, miblen, &exe, &sz, NULL, 0);
const auto FPATH = std::filesystem::canonical(exe);
#elif defined(__OpenBSD__)
// Neither KERN_PROC_PATHNAME nor /proc are supported
const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland");
#else
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
#endif
for (size_t i = 0; i < btSize; ++i) {
finalCrashReport += getFormat("\t#%i | %s\n", i, btSymbols[i]);
#ifdef __clang__
const auto CMD = getFormat("llvm-addr2line -e %s -f 0x%lx", FPATH.c_str(), (uint64_t)bt[i]);
#else
const auto CMD = getFormat("addr2line -e %s -f 0x%lx", FPATH.c_str(), (uint64_t)bt[i]);
#endif
const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t");
finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2);
}
free(btSymbols);
finalCrashReport += "\n\nLog tail:\n";
finalCrashReport += execAndGet(("cat \"" + Debug::logFile + "\" | tail -n 50").c_str());
const auto HOME = getenv("HOME");
if (!HOME)
return;
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) {
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
std::ofstream ofs(std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt", std::ios::trunc);
ofs << finalCrashReport;
ofs.close();
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "../defines.hpp"
namespace CrashReporter {
void createAndSaveCrash(int sig);
};

View File

@@ -11,6 +11,7 @@
#include <unistd.h>
#include <errno.h>
#include <sstream>
#include <string>
std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
@@ -20,10 +21,13 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#({
R"#({
"id": %i,
"name": "%s",
"description": "%s",
"make": "%s",
"model": "%s",
"serial": "%s",
"width": %i,
"height": %i,
"refreshRate": %f,
@@ -37,21 +41,15 @@ R"#({
"scale": %.2f,
"transform": %i,
"focused": %s,
"dpmsStatus": %s
"dpmsStatus": %s,
"vrr": %s
},)#",
m->ID,
escapeJSONStrings(m->szName).c_str(),
escapeJSONStrings(m->output->description ? m->output->description : "").c_str(),
(int)m->vecPixelSize.x, (int)m->vecPixelSize.y,
m->refreshRate,
(int)m->vecPosition.x, (int)m->vecPosition.y,
m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(),
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
m->scale,
(int)m->transform,
(m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
(m->dpmsStatus ? "true" : "false")
);
m->ID, escapeJSONStrings(m->szName).c_str(), escapeJSONStrings(m->output->description ? m->output->description : "").c_str(),
(m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x,
(int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace,
escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
(m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"));
}
// remove trailing comma
@@ -60,8 +58,15 @@ R"#({
result += "]";
} else {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\tdpmsStatus: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, (m->output->description ? m->output->description : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus);
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tmake: %s\n\tmodel: %s\n\tserial: %s\n\tactive workspace: %i (%s)\n\treserved: %i "
"%i %i %i\n\tscale: %.2f\n\ttransform: "
"%i\n\tfocused: %s\n\tdpmsStatus: %i\n\tvrr: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
(m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(),
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale,
(int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus,
(int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED));
}
}
@@ -70,20 +75,22 @@ R"#({
static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
const bool isJson = format == HyprCtl::FORMAT_JSON;
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle")
if (!w->m_sGroupData.pNextWindow)
return isJson ? "" : "0";
SLayoutMessageHeader header;
header.pWindow = w;
const auto groupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
if (groupMembers.empty())
return isJson ? "" : "0";
std::vector<CWindow*> groupMembers;
const auto comma = isJson ? ", " : ",";
const auto fmt = isJson ? "\"0x%x\"" : "%x";
CWindow* curr = w;
do {
groupMembers.push_back(curr);
curr = curr->m_sGroupData.pNextWindow;
} while (curr != w);
const auto comma = isJson ? ", " : ",";
const auto fmt = isJson ? "\"0x%x\"" : "%x";
std::ostringstream result;
bool first = true;
bool first = true;
for (auto& gw : groupMembers) {
if (first)
first = false;
@@ -99,8 +106,10 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
if (format == HyprCtl::FORMAT_JSON) {
return getFormat(
R"#({
R"#({
"address": "0x%x",
"mapped": %s,
"hidden": %s,
"at": [%i, %i],
"size": [%i, %i],
"workspace": {
@@ -116,28 +125,35 @@ R"#({
"pinned": %s,
"fullscreen": %s,
"fullscreenMode": %i,
"fakeFullscreen": %s,
"grouped": [%s],
"swallowing": %s
},)#",
w,
(int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y,
w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
((int)w->m_bIsFloating == 1 ? "true" : "false"),
w->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w)).c_str(),
w->getPID(),
((int)w->m_bIsX11 == 1 ? "true" : "false"),
(w->m_bPinned ? "true" : "false"),
(w->m_bIsFullscreen ? "true" : "false"),
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
getGroupedData(w, format).c_str(),
(w->m_pSwallowed ? getFormat("\"0x%x\"", w->m_pSwallowed).c_str() : "null")
);
w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" :
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)))
.c_str(),
((int)w->m_bIsFloating == 1 ? "true" : "false"), w->m_iMonitorID, escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w)).c_str(), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
(w->m_bIsFullscreen ? "true" : "false"),
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format).c_str(), (w->m_pSwallowed ? getFormat("\"0x%x\"", w->m_pSwallowed).c_str() : "null"));
} else {
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: %i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\tgrouped: %s\n\tswallowing: %x\n\n",
w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w).c_str(), g_pXWaylandManager->getTitle(w).c_str(), w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0), getGroupedData(w, format).c_str(), w->m_pSwallowed);
return getFormat(
"Window %x -> %s:\n\tmapped: %i\n\thidden: %i\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: "
"%i\n\txwayland: %i\n\tpinned: "
"%i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\tfakefullscreen: %i\n\tgrouped: %s\n\tswallowing: %x\n\n",
w, w->m_szTitle.c_str(), (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x,
(int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
(w->m_iWorkspaceID == -1 ? "" :
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() :
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()),
(int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w).c_str(), g_pXWaylandManager->getTitle(w).c_str(), w->getPID(), (int)w->m_bIsX11,
(int)w->m_bPinned, (int)w->m_bIsFullscreen,
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
(int)w->m_bFakeFullscreenState, getGroupedData(w, format).c_str(), w->m_pSwallowed);
}
}
@@ -147,21 +163,17 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
result += "[";
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += getWindowData(w.get(), format);
}
result += getWindowData(w.get(), format);
}
// remove trailing comma
if (result != "[")
result.pop_back();
result.pop_back();
result += "]";
} else {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += getWindowData(w.get(), format);
}
result += getWindowData(w.get(), format);
}
}
return result;
@@ -176,7 +188,7 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat(
R"#({
R"#({
"id": %i,
"name": "%s",
"monitor": "%s",
@@ -185,14 +197,9 @@ R"#({
"lastwindow": "0x%x",
"lastwindowtitle": "%s"
},)#",
w->m_iID,
escapeJSONStrings(w->m_szName).c_str(),
escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID),
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"),
PLASTW,
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : ""
);
w->m_iID, escapeJSONStrings(w->m_szName).c_str(), escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), PLASTW,
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : "");
}
// remove trailing comma
@@ -202,8 +209,9 @@ R"#({
} else {
for (auto& w : g_pCompositor->m_vWorkspaces) {
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n",
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n", w->m_iID,
w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
(int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
}
}
return result;
@@ -216,7 +224,7 @@ std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
return format == HyprCtl::FORMAT_JSON ? "{}" : "Invalid";
auto result = getWindowData(PWINDOW, format);
if (format == HyprCtl::FORMAT_JSON)
result.pop_back();
@@ -231,23 +239,21 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#("%s": {
R"#("%s": {
"levels": {
)#",
escapeJSONStrings(mon->szName).c_str()
);
escapeJSONStrings(mon->szName).c_str());
int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLists) {
for (auto& level : mon->m_aLayerSurfaceLayers) {
result += getFormat(
R"#(
R"#(
"%i": [
)#",
layerLevel
);
layerLevel);
for (auto& layer : level) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"x": %i,
"y": %i,
@@ -255,13 +261,7 @@ R"#( {
"h": %i,
"namespace": "%s"
},)#",
layer.get(),
layer->geometry.x,
layer->geometry.y,
layer->geometry.width,
layer->geometry.height,
escapeJSONStrings(layer->szNamespace).c_str()
);
layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, escapeJSONStrings(layer->szNamespace).c_str());
}
// remove trailing comma
@@ -289,12 +289,14 @@ R"#( {
} 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);
int layerLevel = 0;
static const std::array<std::string, 4> levelNames = {"background", "bottom", "top", "overlay"};
for (auto& level : mon->m_aLayerSurfaceLayers) {
result += getFormat("\tLayer level %i (%s):\n", layerLevel, levelNames[layerLevel].c_str());
for (auto& layer : level) {
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, layer->szNamespace.c_str());
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width,
layer->geometry.height, layer->szNamespace.c_str());
}
layerLevel++;
@@ -315,15 +317,13 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s",
"defaultSpeed": %f
},)#",
&m,
escapeJSONStrings(m.name).c_str(),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f
);
&m, escapeJSONStrings(m.name).c_str(),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f);
}
// remove trailing comma
@@ -334,7 +334,7 @@ R"#( {
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s",
"rules": "%s",
@@ -345,16 +345,9 @@ R"#( {
"active_keymap": "%s",
"main": %s
},)#",
&k,
escapeJSONStrings(k.name).c_str(),
escapeJSONStrings(k.currentRules.rules).c_str(),
escapeJSONStrings(k.currentRules.model).c_str(),
escapeJSONStrings(k.currentRules.layout).c_str(),
escapeJSONStrings(k.currentRules.variant).c_str(),
escapeJSONStrings(k.currentRules.options).c_str(),
escapeJSONStrings(KM).c_str(),
(k.active ? "true" : "false")
);
&k, escapeJSONStrings(k.name).c_str(), escapeJSONStrings(k.currentRules.rules).c_str(), escapeJSONStrings(k.currentRules.model).c_str(),
escapeJSONStrings(k.currentRules.layout).c_str(), escapeJSONStrings(k.currentRules.variant).c_str(), escapeJSONStrings(k.currentRules.options).c_str(),
escapeJSONStrings(KM).c_str(), (k.active ? "true" : "false"));
}
// remove trailing comma
@@ -365,7 +358,7 @@ R"#( {
for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"type": "tabletPad",
"belongsTo": {
@@ -373,33 +366,26 @@ R"#( {
"name": "%s"
}
},)#",
&d,
d.pTabletParent,
escapeJSONStrings(d.pTabletParent ? d.pTabletParent->name : "").c_str()
);
&d, d.pTabletParent, escapeJSONStrings(d.pTabletParent ? d.pTabletParent->name : "").c_str());
}
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
escapeJSONStrings(d.name).c_str()
);
&d, escapeJSONStrings(d.name).c_str());
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"type": "tabletTool",
"belongsTo": "0x%x"
},)#",
&d,
d.wlrTabletTool ? d.wlrTabletTool->data : 0
);
&d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
}
// remove trailing comma
@@ -410,13 +396,11 @@ R"#( {
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.name.c_str()
);
&d, d.name.c_str());
}
// remove trailing comma
@@ -428,13 +412,11 @@ R"#( {
for (auto& d : g_pInputManager->m_lSwitches) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.pWlrDevice ? d.pWlrDevice->name : ""
);
&d, d.pWlrDevice ? d.pWlrDevice->name : "");
}
// remove trailing comma
@@ -448,14 +430,18 @@ R"#( {
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.name.c_str(), (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
result += getFormat(
"\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.name.c_str(),
(wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
}
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k, k.name.c_str(), k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k,
k.name.c_str(), k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(),
k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
}
result += "\n\nTablets:\n";
@@ -488,10 +474,109 @@ R"#( {
return result;
}
std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string ret = "";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
ret += "animations:\n";
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
ret += getFormat("\n\tname: %s\n\t\toverriden: %i\n\t\tbezier: %s\n\t\tenabled: %i\n\t\tspeed: %.2f\n\t\tstyle: %s\n", ac.first.c_str(), (int)ac.second.overriden,
ac.second.internalBezier.c_str(), ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle.c_str());
}
ret += "beziers:\n";
for (auto& bz : g_pAnimationManager->getAllBeziers()) {
ret += getFormat("\n\tname: %s\n", bz.first.c_str());
}
} else {
// json
ret += "[[";
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
ret += getFormat(R"#(
{
"name": "%s",
"overriden": %s,
"bezier": "%s",
"enabled": %s,
"speed": %.2f,
"style": "%s"
},)#",
ac.first.c_str(), ac.second.overriden ? "true" : "false", ac.second.internalBezier.c_str(), ac.second.internalEnabled ? "true" : "false",
ac.second.internalSpeed, ac.second.internalStyle.c_str());
}
ret[ret.length() - 1] = ']';
ret += ",\n[";
for (auto& bz : g_pAnimationManager->getAllBeziers()) {
ret += getFormat(R"#(
{
"name": "%s"
},)#",
bz.first.c_str());
}
ret.pop_back();
ret += "]]";
}
return ret;
}
std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string ret = "";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
ret += "bind";
if (kb.locked)
ret += "l";
if (kb.mouse)
ret += "m";
if (kb.release)
ret += "r";
if (kb.repeat)
ret += "e";
ret += getFormat("\n\tmodmask: %u\n\tsubmap: %s\n\tkey: %s\n\tkeycode: %d\n\tdispatcher: %s\n\targ: %s\n\n", kb.modmask, kb.submap.c_str(), kb.key.c_str(), kb.keycode,
kb.handler.c_str(), kb.arg.c_str());
}
} else {
// json
ret += "[";
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
ret += getFormat(
R"#(
{
"locked": %s,
"mouse": %s,
"release": %s,
"repeat": %s,
"modmask": %u,
"submap": "%s",
"key": "%s",
"keycode": %i,
"dispatcher": "%s",
"arg": "%s"
},)#",
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.modmask,
escapeJSONStrings(kb.submap).c_str(), escapeJSONStrings(kb.key).c_str(), kb.keycode, escapeJSONStrings(kb.handler).c_str(), escapeJSONStrings(kb.arg).c_str());
}
ret.pop_back();
ret += "]";
}
return ret;
}
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nflags: (if any)\n";
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" +
removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nflags: (if any)\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
@@ -500,7 +585,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
result += "debug\n";
#endif
#ifdef HYPRLAND_DEBUG
result += "debug\n";
result += "debug\n";
#endif
#ifdef NO_XWAYLAND
result += "no xwayland\n";
@@ -509,12 +594,13 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
return result;
} else {
std::string result = getFormat(
R"#({
R"#({
"branch": "%s",
"commit": "%s",
"dirty": %s,
"commit_message": "%s",
"flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
"flags": [)#",
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
@@ -523,7 +609,7 @@ R"#({
result += "\"debug\",";
#endif
#ifdef HYPRLAND_DEBUG
result += "\"debug\",";
result += "\"debug\",";
#endif
#ifdef NO_XWAYLAND
result += "\"no xwayland\",";
@@ -563,9 +649,9 @@ std::string dispatchKeyword(std::string in) {
// get rid of the keyword keyword
in = in.substr(in.find_first_of(' ') + 1);
const auto COMMAND = in.substr(0, in.find_first_of(' '));
const auto COMMAND = in.substr(0, in.find_first_of(' '));
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE, true);
@@ -573,17 +659,32 @@ std::string dispatchKeyword(std::string in) {
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setPointerConfigs(); // update mouse cfgs
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setPointerConfigs(); // update mouse cfgs
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
g_pInputManager->setTabletConfigs(); // update tablets
}
if (COMMAND.contains("general:layout"))
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
if (COMMAND.contains("decoration:screen_shader"))
g_pHyprOpenGL->m_bReloadScreenShader = true;
if (COMMAND.contains("blur")) {
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
rd.blurFBDirty = true;
}
}
// decorations will probably need a repaint
if (COMMAND.contains("decoration:") || COMMAND.contains("border")) {
for (auto& m : g_pCompositor->m_vMonitors) {
g_pHyprRenderer->damageMonitor(m.get());
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
}
}
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
if (retval == "")
@@ -592,7 +693,7 @@ std::string dispatchKeyword(std::string in) {
return retval;
}
std::string reloadRequest(std::string request) {
std::string reloadRequest(const std::string& request) {
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
@@ -628,7 +729,8 @@ std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
"x": %i,
"y": %i
}
)#", (int)CURSORPOS.x, (int)CURSORPOS.y);
)#",
(int)CURSORPOS.x, (int)CURSORPOS.y);
}
return "error";
@@ -639,11 +741,11 @@ std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
// split by ;
request = request.substr(9);
request = request.substr(9);
std::string curitem = "";
std::string reply = "";
std::string reply = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(';');
if (idx != std::string::npos) {
@@ -671,7 +773,7 @@ std::string dispatchBatch(std::string request) {
std::string dispatchSetCursor(std::string request) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -718,20 +820,21 @@ std::string dispatchSetCursor(std::string request) {
return "ok";
}
std::string switchXKBLayoutRequest(std::string request) {
CVarList vars(request, 0, ' ');
std::string switchXKBLayoutRequest(const std::string& request) {
CVarList vars(request, 0, ' ');
const auto KB = vars[1];
const auto KB = vars[1];
const auto CMD = vars[2];
// get kb
const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(), [&] (const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); });
const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(),
[&](const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); });
if (PKEYBOARD == g_pInputManager->m_lKeyboards.end())
return "device not found";
const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard);
const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap);
const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard);
const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap);
xkb_layout_index_t activeLayout = 0;
while (activeLayout < LAYOUTS) {
if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE))
@@ -741,32 +844,130 @@ std::string switchXKBLayoutRequest(std::string request) {
}
if (CMD == "next") {
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1);
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
activeLayout > LAYOUTS ? 0 : activeLayout + 1);
} else if (CMD == "prev") {
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
} else {
int requestedLayout = 0;
try {
requestedLayout = std::stoi(CMD);
} catch (std::exception& e) {
return "invalid arg 2";
}
} catch (std::exception& e) { return "invalid arg 2"; }
if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) {
return "layout idx out of range of " + std::to_string(LAYOUTS);
}
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout);
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout);
}
return "ok";
}
std::string dispatchSeterror(std::string request) {
CVarList vars(request, 0, ' ');
std::string errorMessage = "";
if (vars.size() < 3) {
g_pHyprError->destroy();
if (vars.size() == 2 && !vars[1].find("dis"))
return "var 1 not color or disable";
return "ok";
}
const CColor COLOR = configStringToInt(vars[1]);
for (size_t i = 2; i < vars.size(); ++i)
errorMessage += vars[i] + ' ';
if (errorMessage.empty()) {
g_pHyprError->destroy();
} else {
errorMessage.pop_back(); // pop last space
g_pHyprError->queueCreate(errorMessage, COLOR);
}
return "ok";
}
std::string dispatchSetProp(std::string request) {
CVarList vars(request, 0, ' ');
if (vars.size() < 4)
return "not enough args";
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
if (!PWINDOW)
return "window not found";
const auto PROP = vars[2];
const auto VAL = vars[3];
bool lock = false;
if (vars.size() > 4) {
if (vars[4].find("lock") == 0) {
lock = true;
}
}
try {
if (PROP == "animationstyle") {
PWINDOW->m_sAdditionalConfigData.animationStyle = VAL;
} else if (PROP == "rounding") {
PWINDOW->m_sAdditionalConfigData.rounding.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forcenoblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forceopaque") {
PWINDOW->m_sAdditionalConfigData.forceOpaque.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forceopaqueoverriden") {
PWINDOW->m_sAdditionalConfigData.forceOpaqueOverriden.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forceallowsinput") {
PWINDOW->m_sAdditionalConfigData.forceAllowsInput.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forcenoanims") {
PWINDOW->m_sAdditionalConfigData.forceNoAnims.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forcenoborder") {
PWINDOW->m_sAdditionalConfigData.forceNoBorder.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "forcenoshadow") {
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "windowdancecompat") {
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "nomaxsize") {
PWINDOW->m_sAdditionalConfigData.noMaxSize.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "dimaround") {
PWINDOW->m_sAdditionalConfigData.dimAround.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "alphaoverride") {
PWINDOW->m_sSpecialRenderData.alphaOverride.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "alpha") {
PWINDOW->m_sSpecialRenderData.alpha.forceSetIgnoreLocked(std::stof(VAL), lock);
} else if (PROP == "alphainactiveoverride") {
PWINDOW->m_sSpecialRenderData.alphaInactiveOverride.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "alphainactive") {
PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock);
} else if (PROP == "activebordercolor") {
PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else if (PROP == "inactivebordercolor") {
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
} else {
return "prop not found";
}
} catch (std::exception& e) { return "error in parsing prop value: " + std::string(e.what()); }
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return "ok";
}
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -789,10 +990,11 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat
return "no such option";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
return getFormat("option %s\n\tint: %lld\n\tfloat: %f\n\tstr: \"%s\"\n\tdata: %x", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(), PCFGOPT->data.get());
return getFormat("option %s\n\tint: %lld\n\tfloat: %f\n\tstr: \"%s\"\n\tdata: %x", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(),
PCFGOPT->data.get());
else {
return getFormat(
R"#(
R"#(
{
"option": "%s",
"int": %lld,
@@ -800,8 +1002,8 @@ R"#(
"str": "%s",
"data": "0x%x"
}
)#", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(), PCFGOPT->data.get()
);
)#",
curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(), PCFGOPT->data.get());
}
}
@@ -839,7 +1041,7 @@ void createOutputIter(wlr_backend* backend, void* data) {
std::string dispatchOutput(std::string request) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -863,7 +1065,7 @@ std::string dispatchOutput(std::string request) {
const auto NAME = curitem;
if (MODE == "create" || MODE == "add") {
std::pair<std::string, bool> result = { NAME, false };
std::pair<std::string, bool> result = {NAME, false};
wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result);
@@ -885,6 +1087,50 @@ std::string dispatchOutput(std::string request) {
return "ok";
}
std::string dispatchPlugin(std::string request) {
CVarList vars(request, 0, ' ');
if (vars.size() < 2)
return "not enough args";
const auto OPERATION = vars[1];
const auto PATH = vars[2];
if (OPERATION == "load") {
if (vars.size() < 3)
return "not enough args";
const auto PLUGIN = g_pPluginSystem->loadPlugin(PATH);
if (!PLUGIN)
return "error in loading plugin";
} else if (OPERATION == "unload") {
if (vars.size() < 3)
return "not enough args";
const auto PLUGIN = g_pPluginSystem->getPluginByPath(PATH);
if (!PLUGIN)
return "plugin not loaded";
g_pPluginSystem->unloadPlugin(PLUGIN);
} else if (OPERATION == "list") {
const auto PLUGINS = g_pPluginSystem->getAllPlugins();
std::string list = "";
for (auto& p : PLUGINS) {
list += getFormat("\nPlugin %s by %s:\n\tHandle: %lx\n\tVersion: %s\n\tDescription: %s\n", p->name.c_str(), p->author.c_str(), p->m_pHandle, p->version.c_str(),
p->description.c_str());
}
return list;
} else {
return "unknown opt";
}
return "ok";
}
std::string getReply(std::string request) {
auto format = HyprCtl::FORMAT_NORMAL;
@@ -928,6 +1174,16 @@ std::string getReply(std::string request) {
return splashRequest();
else if (request == "cursorpos")
return cursorPosRequest(format);
else if (request == "binds")
return bindsRequest(format);
else if (request == "animations")
return animationsRequest(format);
else if (request.find("plugin") == 0)
return dispatchPlugin(request);
else if (request.find("setprop") == 0)
return dispatchSetProp(request);
else if (request.find("seterror") == 0)
return dispatchSeterror(request);
else if (request.find("switchxkblayout") == 0)
return switchXKBLayoutRequest(request);
else if (request.find("output") == 0)
@@ -946,18 +1202,22 @@ std::string getReply(std::string request) {
return "unknown request";
}
std::string HyprCtl::makeDynamicCall(const std::string& input) {
return getReply(input);
}
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
return 0;
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
socklen_t clientSize = sizeof(clientAddress);
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
char readBuffer[1024];
char readBuffer[1024];
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
std::string request(readBuffer);
@@ -997,7 +1257,10 @@ void HyprCtl::startHyprCtlSocket() {
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
if (bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
return;
}
// 10 max queued.
listen(iSocketFD, 10);

View File

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

View File

@@ -31,6 +31,15 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
if (!m_pMonitor)
m_pMonitor = pMonitor;
// anim data too
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor;
if (PMONITORFORTICKS) {
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
m_dLastAnimationTicks.pop_front();
m_dLastAnimationTicks.push_back(g_pAnimationManager->m_fLastTickTime);
}
}
int CHyprMonitorDebugOverlay::draw(int offset) {
@@ -38,34 +47,68 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
if (!m_pMonitor)
return 0;
int yOffset = offset;
int yOffset = offset;
cairo_text_extents_t cairoExtents;
float maxX = 0;
std::string text = "";
float maxX = 0;
std::string text = "";
// get avg fps
float avgFrametime = 0;
float maxFrametime = 0;
float minFrametime = 9999;
for (auto& ft : m_dLastFrametimes) {
if (ft > maxFrametime)
maxFrametime = ft;
if (ft < minFrametime)
minFrametime = ft;
avgFrametime += ft;
}
float varFrametime = maxFrametime - minFrametime;
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
float avgRenderTime = 0;
float maxRenderTime = 0;
float minRenderTime = 9999;
for (auto& rt : m_dLastRenderTimes) {
if (rt > maxRenderTime)
maxRenderTime = rt;
if (rt < minRenderTime)
minRenderTime = rt;
avgRenderTime += rt;
}
float varRenderTime = maxRenderTime - minRenderTime;
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
float avgRenderTimeNoOverlay = 0;
float maxRenderTimeNoOverlay = 0;
float minRenderTimeNoOverlay = 9999;
for (auto& rt : m_dLastRenderTimesNoOverlay) {
if (rt > maxRenderTimeNoOverlay)
maxRenderTimeNoOverlay = rt;
if (rt < minRenderTimeNoOverlay)
minRenderTimeNoOverlay = rt;
avgRenderTimeNoOverlay += rt;
}
float varRenderTimeNoOverlay = maxRenderTimeNoOverlay - minRenderTimeNoOverlay;
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
float avgAnimMgrTick = 0;
float maxAnimMgrTick = 0;
float minAnimMgrTick = 9999;
for (auto& at : m_dLastAnimationTicks) {
if (at > maxAnimMgrTick)
maxAnimMgrTick = at;
if (at < minAnimMgrTick)
minAnimMgrTick = at;
avgAnimMgrTick += at;
}
float varAnimMgrTick = maxAnimMgrTick - minAnimMgrTick;
avgAnimMgrTick /= m_dLastAnimationTicks.size() == 0 ? 1 : m_dLastAnimationTicks.size();
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
const float idealFPS = m_dLastFrametimes.size();
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
@@ -75,7 +118,8 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
text = m_pMonitor->szName;
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
@@ -88,39 +132,52 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
yOffset += 17;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string(std::to_string((int)FPS) + " FPS");
text = std::string(getFormat("%i FPS", (int)FPS));
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
text = std::string(getFormat("Avg Frametime: %.2fms (var %.2fms)", avgFrametime, varFrametime));
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
text = std::string(getFormat("Avg Rendertime: %.2fms (var %.2fms)", avgRenderTime, varRenderTime));
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
text = std::string(getFormat("Avg Rendertime (No Overlay): %.2fms (var %.2fms)", avgRenderTimeNoOverlay, varRenderTimeNoOverlay));
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string(getFormat("Avg Anim Tick: %.2fms (var %.2fms) (%.2f TPS)", avgAnimMgrTick, varAnimMgrTick, 1.0 / (avgAnimMgrTick / 1000.0)));
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2,
yOffset - offset + 2};
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset;
@@ -143,8 +200,8 @@ void CHyprDebugOverlay::draw() {
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);
m_pCairo = cairo_create(m_pCairoSurface);
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
m_pCairo = cairo_create(m_pCairoSurface);
}
// clear the pixmap
@@ -174,8 +231,8 @@ void CHyprDebugOverlay::draw() {
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);
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
}

View File

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

View File

@@ -0,0 +1,155 @@
#include "HyprNotificationOverlay.hpp"
#include "../Compositor.hpp"
CHyprNotificationOverlay::CHyprNotificationOverlay() {
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
if (m_dNotifications.size() == 0)
return;
g_pHyprRenderer->damageBox(&m_bLastDamage);
});
}
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs) {
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
PNOTIF->text = text;
PNOTIF->color = color;
PNOTIF->started.reset();
PNOTIF->timeMs = timeMs;
}
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
static constexpr auto ANIM_DURATION_MS = 600.0;
static constexpr auto ANIM_LAG_MS = 100.0;
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
float offsetY = 10;
float maxWidth = 0;
const auto SCALE = pMonitor->scale;
const auto FONTSIZE = std::clamp((int)(10.f * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
const auto MONSIZE = pMonitor->vecPixelSize;
cairo_select_font_face(m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(m_pCairo, FONTSIZE);
cairo_text_extents_t cairoExtents;
const auto PBEZIER = g_pAnimationManager->getBezier("default");
for (auto& notif : m_dNotifications) {
// first rect (bg, col)
const float FIRSTRECTANIMP =
(notif->started.getMillis() > (ANIM_DURATION_MS - ANIM_LAG_MS) ?
(notif->started.getMillis() > notif->timeMs - (ANIM_DURATION_MS - ANIM_LAG_MS) ? notif->timeMs - notif->started.getMillis() : (ANIM_DURATION_MS - ANIM_LAG_MS)) :
notif->started.getMillis()) /
(ANIM_DURATION_MS - ANIM_LAG_MS);
const float FIRSTRECTPERC = FIRSTRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(FIRSTRECTANIMP);
// second rect (fg, black)
const float SECONDRECTANIMP = (notif->started.getMillis() > ANIM_DURATION_MS ?
(notif->started.getMillis() > notif->timeMs - ANIM_DURATION_MS ? notif->timeMs - notif->started.getMillis() : ANIM_DURATION_MS) :
notif->started.getMillis()) /
ANIM_DURATION_MS;
const float SECONDRECTPERC = SECONDRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(SECONDRECTANIMP);
// third rect (horiz, col)
const float THIRDRECTPERC = notif->started.getMillis() / notif->timeMs;
// get text size
cairo_text_extents(m_pCairo, notif->text.c_str(), &cairoExtents);
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
const auto NOTIFSIZE = Vector2D{cairoExtents.width + 20, cairoExtents.height + 10};
// draw rects
cairo_rectangle(m_pCairo, MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, offsetY, (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, NOTIFSIZE.y);
cairo_fill(m_pCairo);
cairo_set_source_rgb(m_pCairo, 0.f, 0.f, 0.f);
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC, offsetY, NOTIFSIZE.x * SECONDRECTPERC, NOTIFSIZE.y);
cairo_fill(m_pCairo);
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + 3, offsetY + NOTIFSIZE.y - 4, THIRDRECTPERC * (NOTIFSIZE.x - 6), 2);
cairo_fill(m_pCairo);
// draw text
cairo_set_source_rgb(m_pCairo, 1.f, 1.f, 1.f);
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE, offsetY + FONTSIZE + (FONTSIZE / 10.0));
cairo_show_text(m_pCairo, notif->text.c_str());
// adjust offset and move on
offsetY += NOTIFSIZE.y + 10;
if (maxWidth < NOTIFSIZE.x)
maxWidth = NOTIFSIZE.x;
}
// cleanup notifs
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
}
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
if (m_pLastMonitor != pMonitor || !m_pCairo || !m_pCairoSurface) {
if (m_pCairo && m_pCairoSurface) {
cairo_destroy(m_pCairo);
cairo_surface_destroy(m_pCairoSurface);
}
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_pCairo = cairo_create(m_pCairoSurface);
m_pLastMonitor = pMonitor;
}
// Draw the notifications
if (m_dNotifications.size() == 0)
return;
// Render to the monitor
// clear the pixmap
cairo_save(m_pCairo);
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
cairo_paint(m_pCairo);
cairo_restore(m_pCairo);
cairo_surface_flush(m_pCairoSurface);
wlr_box damage = drawNotifications(pMonitor);
g_pHyprRenderer->damageBox(&damage);
g_pHyprRenderer->damageBox(&m_bLastDamage);
g_pCompositor->scheduleFrameForMonitor(pMonitor);
m_bLastDamage = damage;
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
m_tTexture.allocate();
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "../defines.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/Monitor.hpp"
#include "../render/Texture.hpp"
#include <deque>
#include <cairo/cairo.h>
struct SNotification {
std::string text = "";
CColor color;
CTimer started;
float timeMs = 0;
};
class CHyprNotificationOverlay {
public:
CHyprNotificationOverlay();
void draw(CMonitor* pMonitor);
void addNotification(const std::string& text, const CColor& color, const float timeMs);
private:
wlr_box drawNotifications(CMonitor* pMonitor);
wlr_box m_bLastDamage;
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr;
CMonitor* m_pLastMonitor = nullptr;
CTexture m_tTexture;
};
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,7 @@ namespace Events {
DYNLISTENFUNC(commitSubsurface);
// Popups
DYNLISTENFUNC(newPopup); // LayerSurface
DYNLISTENFUNC(newPopup); // LayerSurface
DYNLISTENFUNC(newPopupXDG);
DYNLISTENFUNC(mapPopupXDG);
@@ -58,9 +58,10 @@ namespace Events {
DYNLISTENFUNC(requestResize);
DYNLISTENFUNC(requestMinimize);
DYNLISTENFUNC(requestMaximize);
DYNLISTENFUNC(setOverrideRedirect);
// Window subsurfaces
// LISTENER(newSubsurfaceWindow);
// LISTENER(newSubsurfaceWindow);
// Input events
LISTENER(mouseMove);
@@ -157,4 +158,7 @@ namespace Events {
LISTENER(holdBegin);
LISTENER(holdEnd);
// Session Lock
LISTENER(newSessionLock);
};

View File

@@ -34,11 +34,11 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
auto PMONITOR = (CMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
if (!WLRLAYERSURFACE->output || !PMONITOR || PMONITOR->pMirrorOf) {
PMONITOR = g_pCompositor->m_vMonitors.front().get();
PMONITOR = g_pCompositor->m_vMonitors.front().get();
WLRLAYERSURFACE->output = PMONITOR->output; // TODO: current mon
}
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLayers[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
@@ -49,13 +49,14 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
layerSurface->layerSurface = WLRLAYERSURFACE;
layerSurface->layer = WLRLAYERSURFACE->current.layer;
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
layerSurface->layer = WLRLAYERSURFACE->current.layer;
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer,
PMONITOR->szName.c_str());
}
void Events::listener_destroyLayerSurface(void* owner, void* data) {
@@ -94,12 +95,13 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
PMONITOR->scheduledRecalc = true;
// and damage
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
}
layersurface->readyToDelete = true;
layersurface->layerSurface = nullptr;
layersurface->layerSurface = nullptr;
}
void Events::listener_mapLayerSurface(void* owner, void* data) {
@@ -108,7 +110,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x mapped", layersurface->layerSurface);
layersurface->layerSurface->mapped = true;
layersurface->mapped = true;
layersurface->mapped = true;
// anim
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
@@ -119,16 +121,21 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
if (!PMONITOR)
return;
for (auto& rule : g_pConfigManager->getMatchingRules(layersurface)) {
if (rule.rule == "noanim")
layersurface->noAnimations = true;
}
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
for (auto it = POLDMON->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLayers[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);
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].emplace_back(std::move(*it));
POLDMON->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
break;
}
}
layersurface->monitorID = PMONITOR->ID;
layersurface->monitorID = PMONITOR->ID;
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
@@ -137,25 +144,31 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
if (layersurface->layerSurface->current.keyboard_interactive &&
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
const auto LOCAL =
g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
}
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
layersurface->alpha.setValue(0);
layersurface->alpha = 255.f;
layersurface->alpha = 1.f;
layersurface->readyToDelete = false;
layersurface->fadingOut = false;
layersurface->fadingOut = false;
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
EMIT_HOOK_EVENT("openLayer", layersurface);
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
}
void Events::listener_unmapLayerSurface(void* owner, void* data) {
@@ -164,6 +177,7 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
EMIT_HOOK_EVENT("closeLayer", layersurface);
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
@@ -201,19 +215,20 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
// refocus if needed
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
Vector2D surfaceCoords;
Vector2D surfaceCoords;
SLayerSurface* pFoundLayerSurface = nullptr;
wlr_surface* foundSurface = nullptr;
wlr_surface* foundSurface = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
// find LS-es to focus
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
&surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
&surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
// if there isn't any, focus the last window
@@ -226,14 +241,13 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
}
}
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
(int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
}
void Events::listener_commitLayerSurface(void* owner, void* data) {
@@ -248,7 +262,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
return;
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
@@ -257,15 +271,15 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
for (auto it = POLDMON->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLayers[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);
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].emplace_back(std::move(*it));
POLDMON->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
break;
}
}
layersurface->monitorID = PMONITOR->ID;
layersurface->monitorID = PMONITOR->ID;
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
@@ -273,10 +287,10 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
if (layersurface->layerSurface->current.committed != 0) {
if (layersurface->layer != layersurface->layerSurface->current.layer) {
for (auto it = PMONITOR->m_aLayerSurfaceLists[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
for (auto it = PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLayers[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);
PMONITOR->m_aLayerSurfaceLayers[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
break;
}
}
@@ -284,18 +298,28 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->layer = layersurface->layerSurface->current.layer;
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
}
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
PMONITOR->scheduledRecalc = true;
} else {
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
// update geom if it changed
if (layersurface->layerSurface->surface->current.scale == 1 && PMONITOR->scale != 1.f && layersurface->layerSurface->surface->current.viewport.has_dst) {
// fractional scaling. Dirty hack.
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, (int)(layersurface->layerSurface->surface->current.viewport.dst_width),
(int)(layersurface->layerSurface->surface->current.viewport.dst_height)};
} else {
// this is because some apps like e.g. rofi-lbonn can't fucking use the protocol correctly.
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width,
(int)layersurface->layerSurface->surface->current.height};
}
}
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
// update geom if it changed
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
}

View File

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

View File

@@ -15,8 +15,6 @@
// //
// --------------------------------------------------------- //
CMonitor* pMostHzMonitor = nullptr;
void Events::listener_change(wl_listener* listener, void* data) {
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create();
@@ -29,14 +27,14 @@ void Events::listener_change(wl_listener* listener, void* data) {
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
// m->vecSize.y = BOX.height;
m->vecPosition.x = BOX.x;
m->vecPosition.y = BOX.y;
CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
@@ -46,6 +44,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
// new monitor added, let's accomodate for that.
const auto OUTPUT = (wlr_output*)data;
// for warping the cursor on launch
static bool firstLaunch = true;
if (!OUTPUT->name) {
Debug::log(ERR, "New monitor has no name?? Ignoring");
return;
@@ -75,22 +76,29 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
PNEWMONITOR->onConnect(false);
if ((!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
pMostHzMonitor = PNEWMONITOR;
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
// ready to process cuz we have a monitor
if (PNEWMONITOR->m_bEnabled) {
g_pCompositor->m_bReadyToProcess = true;
g_pCompositor->m_bUnsafeState = false;
g_pCompositor->m_bUnsafeState = false;
}
g_pConfigManager->m_bWantsMonitorReload = true;
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
if (firstLaunch) {
firstLaunch = false;
const auto POS = PNEWMONITOR->vecPosition + PNEWMONITOR->vecSize / 2.f;
if (g_pCompositor->m_sSeat.mouse)
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y);
}
}
void Events::listener_monitorFrame(void* owner, void* data) {
@@ -104,17 +112,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (!PMONITOR->m_bEnabled)
return;
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("debug:damage_tracking")->intValue;
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
static auto *const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto* const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("debug:damage_tracking")->intValue;
static auto* const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
static auto* const PVFR = &g_pConfigManager->getConfigValuePtr("misc:vfr")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
static int damageBlinkCleanup = 0; // because double-buffered
if (!*PDAMAGEBLINK)
damageBlinkCleanup = 0;
@@ -140,16 +148,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
// checks //
if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
if (PMONITOR->ID == g_pHyprRenderer->m_pMostHzMonitor->ID ||
*PVFR == 1) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
g_pCompositor->sanityCheckWorkspaces();
g_pAnimationManager->tick();
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload();
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
}
// //
@@ -168,12 +176,14 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
}
EMIT_HOOK_EVENT("preRender", PMONITOR);
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
// check the damage
pixman_region32_t damage;
bool hasChanged;
bool hasChanged;
pixman_region32_init(&damage);
if (*PDAMAGETRACKINGMODE == -1) {
@@ -181,13 +191,13 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
g_pHyprOpenGL->preRender(PMONITOR);
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)){
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)) {
Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
return;
}
PMONITOR->renderingActive = true;
// we need to cleanup fading out when rendering the appropriate context
g_pCompositor->cleanupFadingOut(PMONITOR->ID);
@@ -195,31 +205,36 @@ void Events::listener_monitorFrame(void* owner, void* data) {
pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output);
if (*PDAMAGEBLINK || *PNOVFR)
if (*PDAMAGEBLINK || *PVFR == 0)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
PMONITOR->renderingActive = false;
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 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 ||
PMONITOR->isMirror() /* why??? */) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
} else {
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
// if we use blur we need to expand the damage for proper blurring
if (*PBLURENABLED == 1) {
// TODO: can this be optimized?
static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto *const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
// now, prep the damage, get the extended damage region
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
// now, prep the damage, get the extended damage region
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring 2
} else {
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
}
@@ -231,7 +246,6 @@ void Events::listener_monitorFrame(void* owner, void* data) {
PMONITOR->forceFullFrames = 0;
}
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
@@ -240,14 +254,15 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (PMONITOR->isMirror()) {
g_pHyprOpenGL->renderMirrored();
} else {
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
// if correct monitor draw hyprerror
if (PMONITOR == g_pCompositor->m_vMonitors.front().get())
if (PMONITOR == g_pCompositor->m_pLastMonitor) {
g_pHyprNotificationOverlay->draw(PMONITOR);
g_pHyprError->draw();
}
// for drawing the debug overlay
if (PMONITOR == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) {
@@ -258,7 +273,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(255, 0, 255, 100), 0);
g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
@@ -274,14 +289,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pHyprOpenGL->end();
g_pProtocolManager->m_pToplevelExportProtocolManager->onMonitorRender(PMONITOR); // dispatch any toplevel sharing
// calc frame damage
pixman_region32_t frameDamage;
pixman_region32_init(&frameDamage);
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
wlr_region_transform(&frameDamage, &g_pHyprOpenGL->m_rOriginalDamageRegion, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
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);
@@ -297,12 +310,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage);
PMONITOR->renderingActive = false;
if (!wlr_output_commit(PMONITOR->output))
return;
if (*PDAMAGEBLINK || *PNOVFR)
if (*PDAMAGEBLINK || *PVFR == 0 || PMONITOR->pendingFrame)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
PMONITOR->pendingFrame = false;
if (*PDEBUGOVERLAY == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
g_pDebugOverlay->renderData(PMONITOR, µs);
@@ -318,7 +335,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
void Events::listener_monitorDestroy(void* owner, void* data) {
const auto OUTPUT = (wlr_output*)data;
CMonitor* pMonitor = nullptr;
CMonitor* pMonitor = nullptr;
for (auto& m : g_pCompositor->m_vRealMonitors) {
if (m->output == OUTPUT) {
@@ -338,27 +355,13 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
if (!g_pCompositor->m_bUnsafeState) {
Debug::log(LOG, "Removing monitor %s from realMonitors", pMonitor->output->name);
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}
pMostHzMonitor = pMonitorMostHz;
}
std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; });
}
}
void Events::listener_monitorStateRequest(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
const auto E = (wlr_output_event_request_state*)data;
const auto E = (wlr_output_event_request_state*)data;
wlr_output_commit_state(PMONITOR->output, E->state);
}

View File

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

View File

@@ -30,7 +30,7 @@ void addViewCoords(void* pWindow, int* x, int* y) {
}
void setAnimToMove(void* data) {
auto *const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
CAnimatedVariable* animvar = (CAnimatedVariable*)data;
@@ -38,26 +38,28 @@ void setAnimToMove(void* data) {
}
void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
CWindow* PWINDOW = (CWindow*)owner;
static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto *const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
static auto *const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
auto PMONITOR = g_pCompositor->m_pLastMonitor;
const auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
auto PMONITOR = g_pCompositor->m_pLastMonitor;
const auto PWORKSPACE =
PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_bFadingOut = false;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
g_pInputManager->releaseAllMouseButtons();
// Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
@@ -79,18 +81,19 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
if (g_pXWaylandManager->shouldBeFloated(PWINDOW)) {
PWINDOW->m_bIsFloating = true;
PWINDOW->m_bIsFloating = true;
PWINDOW->m_bRequestsFloat = true;
}
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2);
PWINDOW->m_bX11ShouldntFocus =
PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland));
if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true;
if (PWORKSPACE->m_bDefaultPseudo) {
PWINDOW->m_bIsPseudotiled = true;
wlr_box desiredGeometry = {0};
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
}
@@ -99,22 +102,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
pFullscreenWindow = PFULLWINDOW;
pFullscreenWindow = PFULLWINDOW;
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode);
}
// window rules
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
std::string requestedWorkspace = "";
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) || (PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
bool shouldFocus = true;
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
(!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) ||
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
bool requestsMaximize = false;
bool shouldFocus = true;
bool workspaceSpecial = false;
for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) {
try {
const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
const auto MONITORSTR = r.szRule.substr(r.szRule.find(' '));
if (MONITORSTR == "unset") {
PWINDOW->m_iMonitorID = PMONITOR->ID;
@@ -133,9 +139,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
Debug::log(ERR, "Rule monitor, applying to window %x -> mon: %i, workspace: %i", PWINDOW, PWINDOW->m_iMonitorID, PWINDOW->m_iWorkspaceID);
} catch (std::exception& e) {
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what()); }
} else if (r.szRule.find("workspace") == 0) {
// check if it isnt unset
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
@@ -146,7 +150,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
requestedWorkspace = WORKSPACERQ;
}
if (requestedWorkspace == PWORKSPACE->m_szName || requestedWorkspace == "name:" + PWORKSPACE->m_szName)
const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ;
if (JUSTWORKSPACE == PWORKSPACE->m_szName || JUSTWORKSPACE == "name:" + PWORKSPACE->m_szName)
requestedWorkspace = "";
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
@@ -170,6 +176,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
} else if (r.szRule == "pin") {
PWINDOW->m_bPinned = true;
} else if (r.szRule == "maximize") {
requestsMaximize = true;
} else if (r.szRule.find("idleinhibit") == 0) {
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
@@ -198,7 +206,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
// check for silent
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
shouldFocus = false;
shouldFocus = false;
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
@@ -207,14 +215,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
shouldFocus = true;
}
if (requestedWorkspace.find("special" == 0)) {
if (requestedWorkspace.find("special") == 0) {
workspaceSpecial = true;
workspaceSilent = true;
}
if (!workspaceSilent) {
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
PMONITOR = g_pCompositor->m_pLastMonitor;
@@ -228,14 +237,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (!PWORKSPACE) {
std::string workspaceName = "";
int workspaceID = 0;
int workspaceID = 0;
if (requestedWorkspace.find("name:") == 0) {
workspaceName = requestedWorkspace.substr(5);
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
} else if (workspaceSpecial) {
workspaceName = "";
workspaceID = getWorkspaceIDFromString(requestedWorkspace, workspaceName);
workspaceID = getWorkspaceIDFromString(requestedWorkspace, workspaceName);
} else {
try {
workspaceID = std::stoi(requestedWorkspace);
@@ -255,7 +264,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE) {
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
}
}
@@ -267,14 +276,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
for (auto& r : WINDOWRULES) {
if (r.szRule.find("size") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
const auto SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
const auto SIZEX = SIZEXSTR == "max" ?
std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) :
(!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto SIZEY = SIZEYSTR == "max" ?
std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) :
(!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
@@ -282,87 +295,87 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("minsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto SIZE = Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
const auto SIZE =
Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule minsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule minsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("maxsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto SIZE = Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
const auto SIZE =
Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule maxsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("move") == 0) {
try {
auto value = r.szRule.substr(r.szRule.find(" ") + 1);
auto value = r.szRule.substr(r.szRule.find(' ') + 1);
const bool CURSOR = value.find("cursor") == 0;
if (CURSOR)
value = value.substr(value.find_first_of(' ') + 1);
const auto POSXSTR = value.substr(0, value.find(" "));
const auto POSYSTR = value.substr(value.find(" ") + 1);
const auto POSXSTR = value.substr(0, value.find(' '));
const auto POSYSTR = value.substr(value.find(' ') + 1);
int posX = 0;
int posY = 0;
int posX = 0;
int posY = 0;
if (POSXSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSXRAW = POSXSTR.substr(5);
posX = PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stoi(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto POSXRAW = POSXSTR.substr(5);
posX =
PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
} else if (!CURSOR) {
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
} else {
// cursor
if (POSXSTR == "cursor") {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
} else {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x);
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x);
}
}
if (POSYSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSYRAW = POSYSTR.substr(5);
posY = PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stoi(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
const auto POSYRAW = POSYSTR.substr(5);
posY =
PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
} else if (!CURSOR) {
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
} else {
// cursor
if (POSYSTR == "cursor") {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
} else {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y);
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y);
}
}
@@ -371,9 +384,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule == "center") {
PWINDOW->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f - PWINDOW->m_vRealSize.goalv() / 2.f;
}
@@ -388,14 +399,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// Set the pseudo size here too so that it doesnt end up being 0x0
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10, 10);
}
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
PWINDOW->m_bNoFocus = false;
PWINDOW->m_bNoInitialFocus = false;
PWINDOW->m_bNoFocus = false;
PWINDOW->m_bNoInitialFocus = false;
PWINDOW->m_bX11ShouldntFocus = false;
}
@@ -404,7 +415,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
PWINDOW->m_bNoInitialFocus = true;
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2 && !workspaceSilent) {
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(*PDIMSTRENGTH);
@@ -419,32 +431,38 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xdg->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
"XDG Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
"XDG Window Late");
PWINDOW->hyprListener_requestMove.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_move, &Events::listener_requestMove, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
"XDG Window Late");
} else {
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
"XWayland Window Late");
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
"Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
"Xwayland Window Late");
if (PWINDOW->m_iX11Type == 2)
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW,
"XWayland Window Late");
}
// do the animation thing
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
PWINDOW->m_fAlpha = 255.f;
PWINDOW->m_fAlpha = 1.f;
PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove);
PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove);
if (requestsFullscreen && !PWINDOW->m_bNoFullscreenRequest) {
if ((requestsFullscreen || requestsMaximize) && !PWINDOW->m_bNoFullscreenRequest) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
@@ -454,7 +472,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
g_pCompositor->setWindowFullscreen(PWINDOW, true, requestsFullscreen ? FULLSCREEN_FULL : FULLSCREEN_MAXIMIZED);
}
if (pFullscreenWindow && workspaceSilent) {
@@ -499,7 +517,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (ppid) {
// get window by pid
std::vector<CWindow*> found;
CWindow* finalFound = nullptr;
CWindow* finalFound = nullptr;
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden())
continue;
@@ -536,13 +554,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
}
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", getFormat("%x,%s,%s,%s", PWINDOW, workspaceID.c_str(), g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), PWINDOW->m_szTitle.c_str())});
g_pEventManager->postEvent(
SHyprIPCEvent{"openwindow", getFormat("%x,%s,%s,%s", PWINDOW, workspaceID.c_str(), g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), PWINDOW->m_szTitle.c_str())});
EMIT_HOOK_EVENT("openWindow", PWINDOW);
// recalc the values for this window
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PMONITOR->scale);
}
void Events::listener_unmapWindow(void* owner, void* data) {
@@ -551,6 +574,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", getFormat("%x", PWINDOW)});
EMIT_HOOK_EVENT("closeWindow", PWINDOW);
g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW);
@@ -568,7 +592,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
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();
PWINDOW->hyprListener_requestMaximize.removeCallback();
@@ -592,9 +615,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
bool wasLastWindow = false;
if (PWINDOW == g_pCompositor->m_pLastWindow) {
wasLastWindow = true;
wasLastWindow = true;
g_pCompositor->m_pLastWindow = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
}
PWINDOW->m_bMappedX11 = false;
@@ -642,11 +665,11 @@ void Events::listener_unmapWindow(void* owner, void* data) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
// anims
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
@@ -686,12 +709,14 @@ void Events::listener_destroyWindow(void* owner, void* data) {
if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
}
PWINDOW->hyprListener_mapWindow.removeCallback();
PWINDOW->hyprListener_unmapWindow.removeCallback();
PWINDOW->hyprListener_destroyWindow.removeCallback();
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setOverrideRedirect.removeCallback();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
@@ -702,7 +727,7 @@ void Events::listener_destroyWindow(void* owner, void* data) {
}
PWINDOW->m_bReadyToDelete = true;
if (!PWINDOW->m_bFadingOut) {
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
Debug::log(LOG, "Unmapped window %x removed instantly", PWINDOW);
@@ -713,12 +738,15 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
return;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
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{"activewindowv2", getFormat("%x", PWINDOW)});
EMIT_HOOK_EVENT("activeWindow", PWINDOW);
}
PWINDOW->updateDynamicRules();
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
@@ -738,18 +766,47 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
return;
bool requestedFullState = false;
if (!PWINDOW->m_bIsX11) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
if (REQUESTED->fullscreen && PWINDOW->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) {
// Store that we were maximized
PWINDOW->m_bWasMaximized = true;
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_MAXIMIZED);
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
} else
PWINDOW->m_bWasMaximized = false;
} else if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen && !PWINDOW->m_bFakeFullscreenState) {
g_pCompositor->setWindowFullscreen(PWINDOW, REQUESTED->fullscreen, FULLSCREEN_FULL);
if (PWINDOW->m_bWasMaximized && !REQUESTED->fullscreen) {
// Was maximized before the fullscreen request, return now back to maximized instead of normal
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_MAXIMIZED);
}
}
// Disable the maximize flag when we recieve a de-fullscreen request
PWINDOW->m_bWasMaximized &= REQUESTED->fullscreen;
requestedFullState = REQUESTED->fullscreen;
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
if (!PWINDOW->m_uSurface.xwayland->mapped)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
if (!PWINDOW->m_bFakeFullscreenState)
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
requestedFullState = PWINDOW->m_uSurface.xwayland->fullscreen;
}
if (!requestedFullState && PWINDOW->m_bFakeFullscreenState) {
g_pXWaylandManager->setWindowFullscreen(PWINDOW, false); // fixes for apps expecting a de-fullscreen (e.g. ff)
g_pXWaylandManager->setWindowFullscreen(PWINDOW, true);
}
PWINDOW->updateToplevel();
@@ -758,13 +815,13 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
}
void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "Activate request for surface at %x", E->surface);
if (!*PFOCUSONACTIVATE || !wlr_surface_is_xdg_surface(E->surface))
if (!wlr_xdg_surface_try_from_wlr_surface(E->surface))
return;
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
@@ -772,20 +829,56 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", getFormat("%x", PWINDOW)});
EMIT_HOOK_EVENT("urgent", PWINDOW);
PWINDOW->m_bIsUrgent = true;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_pWlrHandle) {
wlr_ext_workspace_handle_v1_set_urgent(PWORKSPACE->m_pWlrHandle, 1);
}
if (!*PFOCUSONACTIVATE)
return;
if (PWINDOW->m_bIsFloating)
g_pCompositor->moveWindowToTop(PWINDOW);
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
void Events::listener_activateX11(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
const auto PWINDOW = (CWindow*)owner;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "X11 Activate request for window %x", PWINDOW);
if (!*PFOCUSONACTIVATE || PWINDOW->m_iX11Type != 1 || PWINDOW == g_pCompositor->m_pLastWindow)
if (PWINDOW->m_iX11Type == 2) {
Debug::log(LOG, "Unmanaged X11 %x requests activate", PWINDOW);
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->getPID() != PWINDOW->getPID())
return;
g_pCompositor->focusWindow(PWINDOW);
return;
}
if (PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", getFormat("%x", PWINDOW)});
EMIT_HOOK_EVENT("urgent", PWINDOW);
if (!*PFOCUSONACTIVATE)
return;
if (PWINDOW->m_bIsFloating)
g_pCompositor->moveWindowToTop(PWINDOW);
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
@@ -793,26 +886,24 @@ void Events::listener_activateX11(void* owner, void* data) {
}
void Events::listener_configureX11(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
CWindow* PWINDOW = (CWindow*)owner;
const auto E = (wlr_xwayland_surface_configure_event*)data;
g_pHyprRenderer->damageWindow(PWINDOW);
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true);
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
return;
}
if (!PWINDOW->m_uSurface.xwayland->mapped || !PWINDOW->m_bMappedX11) {
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
return;
}
g_pHyprRenderer->damageWindow(PWINDOW);
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == PWINDOW) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv(), true);
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
return;
}
if (E->width > 1 && E->height > 1)
PWINDOW->setHidden(false);
else
@@ -821,7 +912,7 @@ void Events::listener_configureX11(void* owner, void* data) {
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y));
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
@@ -859,8 +950,10 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
return;
}
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 ||
abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y,
(int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y));
@@ -876,6 +969,14 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
}
}
void Events::listener_setOverrideRedirect(void* owner, void* data) {
// const auto PWINDOW = (CWindow*)owner;
//if (!PWINDOW->m_bIsMapped && PWINDOW->m_uSurface.xwayland->mapped) {
// Events::listener_mapWindow(PWINDOW, nullptr);
//}
}
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data;
@@ -883,17 +984,19 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
if (XWSURFACE->parent)
Debug::log(LOG, "Window parent data: %s at %x", XWSURFACE->parent->_class, XWSURFACE->parent);
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
const auto PNEWWINDOW = (CWindow*)g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
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");
PNEWWINDOW->hyprListener_setOverrideRedirect.initCallback(&XWSURFACE->events.set_override_redirect, &Events::listener_setOverrideRedirect, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window");
}
void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
@@ -905,7 +1008,7 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
Debug::log(LOG, "New XDG Surface created. (class: %s)", XDGSURFACE->toplevel->app_id);
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
@@ -928,7 +1031,8 @@ void Events::listener_requestMaximize(void* owner, void* data) {
if (!PWINDOW->m_bIsX11) {
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen,
FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
@@ -950,7 +1054,14 @@ void Events::listener_requestMinimize(void* owner, void* data) {
const auto E = (wlr_xwayland_minimize_event*)data;
g_pEventManager->postEvent({"minimize", getFormat("%x,%i", PWINDOW, (int)E->minimize)});
EMIT_HOOK_EVENT("minimize", (std::vector<void*>{PWINDOW, (void*)E->minimize}));
wlr_xwayland_surface_set_minimized(PWINDOW->m_uSurface.xwayland, E->minimize && g_pCompositor->m_pLastWindow != PWINDOW); // fucking DXVK
} else {
const auto E = (wlr_foreign_toplevel_handle_v1_minimized_event*)data;
g_pEventManager->postEvent({"minimize", getFormat("%x,%i", PWINDOW, E ? (int)E->minimized : 1)});
EMIT_HOOK_EVENT("minimize", (std::vector<void*>{PWINDOW, (void*)(E ? (uint64_t)E->minimized : 1)}));
}
}

View File

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

View File

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

View File

@@ -1,17 +1,19 @@
#include "BezierCurve.hpp"
#include <algorithm>
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
m_dPoints.clear();
const auto BEGIN = std::chrono::high_resolution_clock::now();
m_dPoints.emplace_back(Vector2D(0,0));
m_dPoints.emplace_back(Vector2D(0, 0));
for (auto& p : *pVec) {
m_dPoints.push_back(p);
}
m_dPoints.emplace_back(Vector2D(1,1));
m_dPoints.emplace_back(Vector2D(1, 1));
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
@@ -21,7 +23,7 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS));
}
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
@@ -29,9 +31,8 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
getYForPoint(i);
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.",
BAKEDPOINTS, POINTSSIZE, ELAPSEDUS, ELAPSEDCALCAVG);
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.", BAKEDPOINTS, POINTSSIZE, ELAPSEDUS,
ELAPSEDCALCAVG);
}
float CBezierCurve::getYForT(float t) {
@@ -44,29 +45,32 @@ float CBezierCurve::getXForT(float t) {
// Todo: this probably can be done better and faster
float CBezierCurve::getYForPoint(float x) {
// binary search for the range UPDOWN X
float upperT = 1;
float lowerT = 0;
float mid = 0.5;
if (x >= 1.0)
return 1.0;
while(std::abs(upperT - lowerT) > INVBAKEDPOINTS) {
if (m_aPointsBaked[((int)(mid * (float)BAKEDPOINTS))].x > x) {
// binary search for the range UPDOWN X
int upperT = BAKEDPOINTS - 1;
int lowerT = 0;
int mid = upperT / 2;
while (std::abs(upperT - lowerT) > 1) {
if (m_aPointsBaked[mid].x > x) {
upperT = mid;
} else {
lowerT = mid;
}
mid = (upperT + lowerT) / 2.f;
mid = (upperT + lowerT) / 2;
}
// in the name of performance i shall make a hack
const auto LOWERPOINT = &m_aPointsBaked[std::clamp((int)((float)BAKEDPOINTS * lowerT), 0, 199)];
const auto UPPERPOINT = &m_aPointsBaked[std::clamp((int)((float)BAKEDPOINTS * upperT), 0, 199)];
const auto LOWERPOINT = &m_aPointsBaked[std::clamp(lowerT, 0, BAKEDPOINTS - 1)];
const auto UPPERPOINT = &m_aPointsBaked[std::clamp(upperT, 0, BAKEDPOINTS - 1)];
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f;
return LOWERPOINT->y + (UPPERPOINT->y - UPPERPOINT->y) * PERCINDELTA;
return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA;
}

View File

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

View File

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

View File

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

View File

@@ -4,65 +4,121 @@
#include "../Compositor.hpp"
#include <sys/utsname.h>
#include <iomanip>
#include <sstream>
#if defined(__DragonFly__) || defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/sysctl.h>
# if defined(__DragonFly__)
# include <sys/kinfo.h> // struct kinfo_proc
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# include <sys/user.h> // struct kinfo_proc
# endif
# if defined(__NetBSD__)
# undef KERN_PROC
# define KERN_PROC KERN_PROC2
# define KINFO_PROC struct kinfo_proc2
# else
# define KINFO_PROC struct kinfo_proc
# endif
# if defined(__DragonFly__)
# define KP_PPID(kp) kp.kp_ppid
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# define KP_PPID(kp) kp.ki_ppid
# else
# define KP_PPID(kp) kp.p_ppid
# endif
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/sysctl.h>
#if defined(__DragonFly__)
#include <sys/kinfo.h> // struct kinfo_proc
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/user.h> // struct kinfo_proc
#endif
static const float transforms[][9] = {{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},
#if defined(__NetBSD__)
#undef KERN_PROC
#define KERN_PROC KERN_PROC2
#define KINFO_PROC struct kinfo_proc2
#else
#define KINFO_PROC struct kinfo_proc
#endif
#if defined(__DragonFly__)
#define KP_PPID(kp) kp.kp_ppid
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#define KP_PPID(kp) kp.ki_ppid
#else
#define KP_PPID(kp) kp.p_ppid
#endif
#endif
static const float transforms[][9] = {
{
1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
0.0f,
1.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
-1.0f,
0.0f,
0.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
0.0f,
-1.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
-1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
0.0f,
1.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
1.0f,
0.0f,
0.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
{
0.0f,
-1.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
},
};
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
@@ -87,7 +143,7 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
return value;
}
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const std::string& ownerString) {
ASSERT(pSignal);
ASSERT(pListener);
@@ -96,12 +152,12 @@ void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::
Debug::log(LOG, "Registered signal for owner %x: %x -> %x (owner: %s)", pOwner, pSignal, pListener, ownerString.c_str());
}
void handleNoop(struct wl_listener *listener, void *data) {
void handleNoop(struct wl_listener* listener, void* data) {
// Do nothing
}
std::string getFormat(const char *fmt, ...) {
char* outputStr = nullptr;
std::string getFormat(const char* fmt, ...) {
char* outputStr = nullptr;
va_list args;
va_start(args, fmt);
@@ -116,32 +172,31 @@ std::string getFormat(const char *fmt, ...) {
std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss;
for (auto &c : str) {
for (auto& c : str) {
switch (c) {
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u"
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
}
}
return oss.str();
}
void scaleBox(wlr_box* box, float scale) {
box->width = std::round(box->width * scale);
box->width = std::round(box->width * scale);
box->height = std::round(box->height * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
}
std::string removeBeginEndSpacesTabs(std::string str) {
@@ -154,7 +209,7 @@ std::string removeBeginEndSpacesTabs(std::string str) {
}
int countAfter = 0;
while (str.length() != 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
countAfter++;
}
@@ -164,41 +219,12 @@ std::string removeBeginEndSpacesTabs(std::string str) {
}
float getPlusMinusKeywordResult(std::string source, float relative) {
float result = INT_MAX;
if (source.find_first_of("+") == 0) {
try {
if (source.contains("."))
result = relative + std::stof(source.substr(1));
else
result = relative + std::stoi(source.substr(1));
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
} else if (source.find_first_of("-") == 0) {
try {
if (source.contains("."))
result = relative - std::stof(source.substr(1));
else
result = relative - std::stoi(source.substr(1));
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
} else {
try {
if (source.contains("."))
result = stof(source);
else
result = stoi(source);
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
try {
return relative + stof(source);
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
return result;
}
bool isNumber(const std::string& str, bool allowfloat) {
@@ -239,7 +265,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
const auto NAME = in.substr(8);
const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME);
outName = "special:" + NAME;
return WS ? WS->m_iID : g_pCompositor->getNewSpecialID();
@@ -248,7 +274,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
return SPECIAL_WORKSPACE_START;
} else if (in.find("name:") == 0) {
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
if (!WORKSPACE) {
result = g_pCompositor->getNextAvailableNamedWorkspace();
} else {
@@ -262,6 +288,22 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
if (!PWORKSPACE || (g_pCompositor->getWindowsOnWorkspace(id) == 0))
return id;
}
} else if (in.find("prev") == 0) {
if (!g_pCompositor->m_pLastMonitor)
return INT_MAX;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
if (!PWORKSPACE)
return INT_MAX;
const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID);
if (!PLASTWORKSPACE)
return INT_MAX;
outName = PLASTWORKSPACE->m_szName;
return PLASTWORKSPACE->m_iID;
} else {
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
bool onAllMonitors = in[0] == 'e';
@@ -276,8 +318,8 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
// result now has +/- what we should move on mon
int remains = (int)result;
int remains = (int)result;
std::vector<int> validWSes;
for (auto& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
@@ -310,7 +352,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
currentItem = validWSes.size() + currentItem;
}
result = validWSes[currentItem];
result = validWSes[currentItem];
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
} else {
@@ -345,8 +387,8 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
// Execute a shell command and get the output
std::string execAndGet(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::array<char, 128> buffer;
std::string result;
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
Debug::log(ERR, "execAndGet: failed in pipe");
@@ -370,7 +412,11 @@ void logSystemInfo() {
Debug::log(NONE, "\n");
#if defined(__DragonFly__) || defined(__FreeBSD__)
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
#else
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
#endif
Debug::log(LOG, "GPU information:\n%s\n", GPUINFO.c_str());
if (GPUINFO.contains("NVIDIA")) {
@@ -387,8 +433,8 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
memset(mat, 0, sizeof(*mat) * 9);
const float* t = transforms[tr];
float x = 2.0f / w;
float y = 2.0f / h;
float x = 2.0f / w;
float y = 2.0f / h;
// Rotation + reflection
mat[0] = x * t[0];
@@ -411,35 +457,35 @@ int64_t getPPIDof(int64_t pid) {
KERN_PROC,
KERN_PROC_PID,
(int)pid,
# if defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__NetBSD__) || defined(__OpenBSD__)
sizeof(KINFO_PROC),
1,
# endif
#endif
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
u_int miblen = sizeof(mib) / sizeof(mib[0]);
KINFO_PROC kp;
size_t sz = sizeof(KINFO_PROC);
size_t sz = sizeof(KINFO_PROC);
if (sysctl(mib, miblen, &kp, &sz, NULL, 0) != -1)
return KP_PPID(kp);
return 0;
#else
std::string dir = "/proc/" + std::to_string(pid) + "/status";
FILE* infile;
std::string dir = "/proc/" + std::to_string(pid) + "/status";
FILE* infile;
infile = fopen(dir.c_str(), "r");
if (!infile)
return 0;
char* line = nullptr;
size_t len = 0;
ssize_t len2 = 0;
char* line = nullptr;
size_t len = 0;
ssize_t len2 = 0;
std::string pidstr;
while ((len2 = getline(&line, &len, infile)) != -1) {
if (strstr(line, "PPid:")) {
pidstr = std::string(line, len2);
pidstr = std::string(line, len2);
const auto tabpos = pidstr.find_last_of('\t');
if (tabpos != std::string::npos)
pidstr = pidstr.substr(tabpos);
@@ -453,9 +499,7 @@ int64_t getPPIDof(int64_t pid) {
try {
return std::stoll(pidstr);
} catch (std::exception& e) {
return 0;
}
} catch (std::exception& e) { return 0; }
#endif
}
@@ -464,7 +508,7 @@ int64_t configStringToInt(const std::string& VALUE) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
return stol(VALUEWITHOUTHEX, nullptr, 16);
} else if (VALUE.find("rgba(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
} else if (VALUE.find("rgba(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
@@ -476,7 +520,7 @@ int64_t configStringToInt(const std::string& VALUE) {
// now we need to RGBA -> ARGB. The config holds ARGB only.
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
} else if (VALUE.find("rgb(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
} else if (VALUE.find("rgb(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {
@@ -492,5 +536,30 @@ int64_t configStringToInt(const std::string& VALUE) {
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
return 0;
}
return stol(VALUE);
}
return std::stoll(VALUE);
}
double normalizeAngleRad(double ang) {
if (ang > M_PI * 2) {
while (ang > M_PI * 2)
ang -= M_PI * 2;
return ang;
}
if (ang < 0.0) {
while (ang < 0.0)
ang += M_PI * 2;
return ang;
}
return ang;
}
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}

View File

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

View File

@@ -67,15 +67,15 @@ void CMonitor::onConnect(bool noRule) {
if (output->non_desktop) {
Debug::log(LOG, "Not configuring non-desktop output");
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
}
return;
}
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
}
return;
}
if (!m_bRenderingInitPassed) {
output->allocator = nullptr;
output->renderer = nullptr;
output->renderer = nullptr;
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
m_bRenderingInitPassed = true;
}
@@ -91,17 +91,15 @@ void CMonitor::onConnect(bool noRule) {
}
}
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()){
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
}
m_bEnabled = true;
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
// create it in the arr
vecPosition = monitorRule.offset;
vecSize = monitorRule.resolution;
vecSize = monitorRule.resolution;
refreshRate = monitorRule.refreshRate;
wlr_output_enable(output, 1);
@@ -110,7 +108,10 @@ void CMonitor::onConnect(bool noRule) {
if (!noRule)
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x, (int)vecPixelSize.y, output);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x,
(int)vecPixelSize.y, output);
damage = wlr_output_damage_create(output);
@@ -127,12 +128,13 @@ void CMonitor::onConnect(bool noRule) {
m_pThisWrap = nullptr;
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
//
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
EMIT_HOOK_EVENT("monitorAdded", this);
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->setActiveMonitor(this);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
@@ -142,6 +144,18 @@ void CMonitor::onConnect(bool noRule) {
// ensure VRR (will enable if necessary)
g_pConfigManager->ensureVRR(this);
// verify last mon valid
bool found = false;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m.get() == g_pCompositor->m_pLastMonitor) {
found = true;
break;
}
}
if (!found)
g_pCompositor->setActiveMonitor(this);
}
void CMonitor::onDisconnect() {
@@ -160,9 +174,6 @@ void CMonitor::onDisconnect() {
}
}
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->setActiveMonitor(BACKUPMON);
// remove mirror
if (pMirrorOf) {
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
@@ -177,11 +188,24 @@ void CMonitor::onDisconnect() {
g_pConfigManager->m_bWantsMonitorReload = true;
}
m_bEnabled = false;
m_bEnabled = false;
m_bRenderingInitPassed = false;
hyprListener_monitorFrame.removeCallback();
for (size_t i = 0; i < 4; ++i) {
for (auto& ls : m_aLayerSurfaceLayers[i]) {
if (ls->layerSurface && !ls->fadingOut)
wlr_layer_surface_v1_destroy(ls->layerSurface);
}
m_aLayerSurfaceLayers[i].clear();
}
Debug::log(LOG, "Removed monitor %s!", szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
EMIT_HOOK_EVENT("monitorRemoved", this);
if (!BACKUPMON) {
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
@@ -194,7 +218,8 @@ void CMonitor::onDisconnect() {
}
// snap cursor
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f,
BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
// move workspaces
std::deque<CWorkspace*> wspToMove;
@@ -221,9 +246,22 @@ void CMonitor::onDisconnect() {
std::erase_if(g_pCompositor->m_vWorkspaces, [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; });
Debug::log(LOG, "Removed monitor %s!", szName.c_str());
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->setActiveMonitor(BACKUPMON);
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
if (g_pHyprRenderer->m_pMostHzMonitor == this) {
int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz && m.get() != this) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}
g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz;
}
std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; });
}
@@ -247,7 +285,7 @@ int CMonitor::findAvailableDefaultWS() {
if (const auto BOUND = g_pConfigManager->getBoundMonitorStringForWS(std::to_string(i)); !BOUND.empty() && BOUND != szName)
continue;
return i;
}
@@ -257,10 +295,10 @@ int CMonitor::findAvailableDefaultWS() {
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
// Workspace
std::string newDefaultWorkspaceName = "";
int64_t WORKSPACEID = monitorRule.defaultWorkspace == "" ? findAvailableDefaultWS() : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
int64_t WORKSPACEID = monitorRule.defaultWorkspace == "" ? findAvailableDefaultWS() : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.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.c_str());
@@ -335,7 +373,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
}
}
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) ==
g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
}
@@ -368,17 +407,35 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
vecPosition = Vector2D(-1337420, -1337420);
vecPosition = PMIRRORMON->vecPosition;
pMirrorOf = PMIRRORMON;
pMirrorOf->mirrors.push_back(this);
// remove from mvmonitors
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
}
std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; });
g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get());
g_pCompositor->sanityCheckWorkspaces();
}
}
float CMonitor::getDefaultScale() {
if (!m_bEnabled)
return 1;
static constexpr double MMPERINCH = 25.4;
const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2));
const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2));
const auto PPI = DIAGONALPX / DIAGONALIN;
if (PPI > 200 /* High PPI, 2x*/)
return 2;
else if (PPI > 140 /* Medium PPI, 1.5x*/)
return 1.5;
return 1;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,12 +1,17 @@
#include "Vector2D.hpp"
#include <algorithm>
#include <cmath>
Vector2D::Vector2D(double xx, double yy) {
x = xx;
y = yy;
}
Vector2D::Vector2D() { x = 0; y = 0; }
Vector2D::Vector2D() {
x = 0;
y = 0;
}
Vector2D::~Vector2D() {}
double Vector2D::normalize() {
@@ -24,8 +29,11 @@ Vector2D Vector2D::floor() {
}
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
return Vector2D(
std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x),
std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)
);
}
return Vector2D(std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x), std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y));
}
double Vector2D::distance(const Vector2D& other) {
double dx = x - other.x;
double dy = y - other.y;
return std::sqrt(dx * dx + dy * dy);
}

View File

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

View File

@@ -7,11 +7,16 @@
#include "SubsurfaceTree.hpp"
#include "AnimatedVariable.hpp"
struct SLayerRule {
std::string targetNamespace = "";
std::string rule = "";
};
struct SLayerSurface {
SLayerSurface();
wlr_layer_surface_v1* layerSurface;
wl_list link;
wlr_layer_surface_v1* layerSurface;
wl_list link;
DYNLISTENER(destroyLayerSurface);
DYNLISTENER(mapLayerSurface);
@@ -19,45 +24,47 @@ struct SLayerSurface {
DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup);
wlr_box geometry = {0,0,0,0};
Vector2D position;
wlr_box geometry = {0, 0, 0, 0};
Vector2D position;
zwlr_layer_shell_v1_layer layer;
bool mapped = false;
bool mapped = false;
int monitorID = -1;
int monitorID = -1;
std::string szNamespace = "";
std::string szNamespace = "";
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
bool noProcess = false;
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
bool noProcess = false;
bool noAnimations = false;
bool forceBlur = false;
bool forceBlur = false;
// For the list lookup
bool operator==(const SLayerSurface& rhs) {
bool operator==(const SLayerSurface& rhs) const {
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
}
};
class CMonitor;
struct SRenderData {
wlr_output* output;
CMonitor* pMonitor;
timespec* when;
int x, y;
int x, y;
// for iters
void* data = nullptr;
void* data = nullptr;
wlr_surface* surface = nullptr;
int w, h;
void* pMonitor = nullptr;
int w, h;
// for rounding
bool dontRound = true;
// for fade
float fadeAlpha = 255.f;
float fadeAlpha = 1.f;
// for alpha settings
float alpha = 1.f;
@@ -69,7 +76,7 @@ struct SRenderData {
int rounding = -1; // -1 means not set
// for blurring
bool blur = false;
bool blur = false;
bool blockBlurOptimization = false;
// only for windows, not popups
@@ -80,17 +87,17 @@ struct SRenderData {
};
struct SExtensionFindingData {
Vector2D origin;
Vector2D vec;
Vector2D origin;
Vector2D vec;
wlr_surface** found;
};
struct SStringRuleNames {
std::string layout = "";
std::string model = "";
std::string layout = "";
std::string model = "";
std::string variant = "";
std::string options = "";
std::string rules = "";
std::string rules = "";
};
struct SKeyboard {
@@ -101,58 +108,59 @@ struct SKeyboard {
DYNLISTENER(keyboardKeymap);
DYNLISTENER(keyboardDestroy);
bool isVirtual = false;
bool active = false;
bool isVirtual = false;
bool active = false;
bool enabled = true;
xkb_layout_index_t activeLayout = 0;
std::string name = "";
std::string xkbFilePath = "";
std::string name = "";
std::string xkbFilePath = "";
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
// For the list lookup
bool operator==(const SKeyboard& rhs) {
bool operator==(const SKeyboard& rhs) const {
return keyboard == rhs.keyboard;
}
};
struct SMouse {
wlr_input_device* mouse = nullptr;
wlr_input_device* mouse = nullptr;
wlr_pointer_constraint_v1* currentConstraint = nullptr;
bool constraintActive = false;
bool constraintActive = false;
pixman_region32_t confinedTo;
pixman_region32_t confinedTo;
std::string name = "";
std::string name = "";
bool virt = false;
bool virt = false;
bool connected = false; // means connected to the cursor
bool connected = false; // means connected to the cursor
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
bool operator==(const SMouse& b) {
bool operator==(const SMouse& b) const {
return mouse == b.mouse;
}
};
struct SConstraint {
SMouse* pMouse = nullptr;
SMouse* pMouse = nullptr;
wlr_pointer_constraint_v1* constraint = nullptr;
bool hintSet = false;
Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set.
bool hintSet = false;
Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set.
DYNLISTENER(setConstraintRegion);
DYNLISTENER(destroyConstraint);
bool operator==(const SConstraint& b) {
bool operator==(const SConstraint& b) const {
return constraint == b.constraint;
}
};
@@ -160,10 +168,10 @@ struct SConstraint {
class CMonitor;
struct SXDGPopup {
CWindow* parentWindow = nullptr;
SXDGPopup* parentPopup = nullptr;
wlr_xdg_popup* popup = nullptr;
CMonitor* monitor = nullptr;
CWindow* parentWindow = nullptr;
SXDGPopup* parentPopup = nullptr;
wlr_xdg_popup* popup = nullptr;
CMonitor* monitor = nullptr;
DYNLISTENER(newPopupFromPopupXDG);
DYNLISTENER(destroyPopupXDG);
@@ -171,36 +179,36 @@ struct SXDGPopup {
DYNLISTENER(unmapPopupXDG);
DYNLISTENER(commitPopupXDG);
double lx;
double ly;
double lx;
double ly;
SSurfaceTreeNode* pSurfaceTree = nullptr;
// For the list lookup
bool operator==(const SXDGPopup& rhs) {
bool operator==(const SXDGPopup& rhs) const {
return popup == rhs.popup;
}
};
struct SSeat {
wlr_seat* seat = nullptr;
wl_client* exclusiveClient = nullptr;
wlr_seat* seat = nullptr;
wl_client* exclusiveClient = nullptr;
SMouse* mouse = nullptr;
SMouse* mouse = nullptr;
};
struct SDrag {
wlr_drag* drag = nullptr;
wlr_drag* drag = nullptr;
DYNLISTENER(destroy);
// Icon
bool iconMapped = false;
bool iconMapped = false;
wlr_drag_icon* dragIcon = nullptr;
wlr_drag_icon* dragIcon = nullptr;
Vector2D pos;
Vector2D pos;
DYNLISTENER(destroyIcon);
DYNLISTENER(mapIcon);
@@ -215,45 +223,46 @@ struct STablet {
DYNLISTENER(Proximity);
DYNLISTENER(Destroy);
wlr_tablet* wlrTablet = nullptr;
wlr_tablet* wlrTablet = nullptr;
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
wlr_input_device* wlrDevice = nullptr;
wlr_input_device* wlrDevice = nullptr;
std::string name = "";
std::string name = "";
bool operator==(const STablet& b) {
bool operator==(const STablet& b) const {
return wlrDevice == b.wlrDevice;
}
};
struct STabletTool {
wlr_tablet_tool* wlrTabletTool = nullptr;
wlr_tablet_tool* wlrTabletTool = nullptr;
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
wlr_surface* pSurface = nullptr;
wlr_surface* pSurface = nullptr;
double tiltX = 0;
double tiltY = 0;
double tiltX = 0;
double tiltY = 0;
bool active = true;
bool active = true;
std::string name = "";
std::string name = "";
DYNLISTENER(TabletToolDestroy);
DYNLISTENER(TabletToolSetCursor);
bool operator==(const STabletTool& b) {
bool operator==(const STabletTool& b) const {
return wlrTabletTool == b.wlrTabletTool;
}
};
struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
STablet* pTabletParent = nullptr;
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";
std::string name = "";
DYNLISTENER(Attach);
DYNLISTENER(Button);
@@ -261,37 +270,40 @@ struct STabletPad {
DYNLISTENER(Ring);
DYNLISTENER(Destroy);
bool operator==(const STabletPad& b) {
bool operator==(const STabletPad& b) const {
return wlrTabletPadV2 == b.wlrTabletPadV2;
}
};
struct SIdleInhibitor {
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
CWindow* pWindow = nullptr;
CWindow* pWindow = nullptr;
DYNLISTENER(Destroy);
bool operator==(const SIdleInhibitor& b) {
bool operator==(const SIdleInhibitor& b) const {
return pWlrInhibitor == b.pWlrInhibitor;
}
};
struct SSwipeGesture {
CWorkspace* pWorkspaceBegin = nullptr;
CWorkspace* pWorkspaceBegin = nullptr;
double delta = 0;
double delta = 0;
float avgSpeed = 0;
int speedPoints = 0;
float avgSpeed = 0;
int speedPoints = 0;
CMonitor* pMonitor = nullptr;
CMonitor* pMonitor = nullptr;
};
struct STextInputV1;
struct STextInput {
wlr_text_input_v3* pWlrInput = nullptr;
STextInputV1* pV1Input = nullptr;
wlr_surface* pPendingSurface = nullptr;
wlr_surface* pPendingSurface = nullptr;
DYNLISTENER(textInputEnable);
DYNLISTENER(textInputDisable);
@@ -304,7 +316,7 @@ struct STextInput {
struct SIMEKbGrab {
wlr_input_method_keyboard_grab_v2* pWlrKbGrab = nullptr;
wlr_keyboard* pKeyboard = nullptr;
wlr_keyboard* pKeyboard = nullptr;
DYNLISTENER(grabDestroy);
};
@@ -312,10 +324,10 @@ struct SIMEKbGrab {
struct SIMEPopup {
wlr_input_popup_surface_v2* pSurface = nullptr;
int x, y;
int realX, realY;
bool visible;
Vector2D lastSize;
int x, y;
int realX, realY;
bool visible;
Vector2D lastSize;
DYNLISTENER(mapPopup);
DYNLISTENER(unmapPopup);
@@ -324,7 +336,7 @@ struct SIMEPopup {
DYNLISTENER(focusedSurfaceUnmap);
bool operator==(const SIMEPopup& other) {
bool operator==(const SIMEPopup& other) const {
return pSurface == other.pSurface;
}
};
@@ -332,13 +344,13 @@ struct SIMEPopup {
struct STouchDevice {
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";
std::string name = "";
std::string boundOutput = "";
std::string boundOutput = "";
DYNLISTENER(destroy);
bool operator==(const STouchDevice& other) {
bool operator==(const STouchDevice& other) const {
return pWlrDevice == other.pWlrDevice;
}
};
@@ -349,7 +361,7 @@ struct SSwitchDevice {
DYNLISTENER(destroy);
DYNLISTENER(toggle);
bool operator==(const SSwitchDevice& other) {
bool operator==(const SSwitchDevice& other) const {
return pWlrDevice == other.pWlrDevice;
}
};

View File

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

View File

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

View File

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

View File

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

7
src/helpers/X11Stubs.hpp Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
inline bool wlr_backend_is_x11(void*) {
return false;
}
inline void wlr_x11_output_create(void*) {}

View File

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

View File

@@ -1,9 +1,34 @@
#include "HyprError.hpp"
#include "../Compositor.hpp"
CHyprError::CHyprError() {
m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE);
m_fFadeOpacity.registerVar();
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
if (!m_bIsCreated)
return;
g_pHyprRenderer->damageMonitor(g_pCompositor->m_pLastMonitor);
m_bMonitorChanged = true;
});
g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any param) {
if (!m_bIsCreated)
return;
if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(&m_bDamageBox);
});
}
CHyprError::~CHyprError() {
m_fFadeOpacity.unregister();
}
void CHyprError::queueCreate(std::string message, const CColor& color) {
m_szQueued = message;
m_cQueued = color;
m_cQueued = color;
}
void CHyprError::createQueued() {
@@ -12,9 +37,16 @@ void CHyprError::createQueued() {
m_tTexture.destroyTexture();
}
m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
m_fFadeOpacity.setValueAndWarp(0.f);
m_fFadeOpacity = 1.f;
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
const auto FONTSIZE = std::clamp((int)(10.f * (PMONITOR->vecPixelSize.x / 1920.f)), 8, 40);
const auto SCALE = PMONITOR->scale;
const auto FONTSIZE = std::clamp((int)(10.f * ((PMONITOR->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@@ -26,38 +58,52 @@ void CHyprError::createQueued() {
cairo_paint(CAIRO);
cairo_restore(CAIRO);
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
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->vecPixelSize.x, (FONTSIZE + 2 * (FONTSIZE / 10.f)) * LINECOUNT);
const double DEGREES = M_PI / 180.0;
// outline
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
const double PAD = 10 * SCALE;
cairo_fill(CAIRO);
const double X = PAD;
const double Y = PAD;
const double WIDTH = PMONITOR->vecPixelSize.x - PAD * 2;
const double HEIGHT = (FONTSIZE + 2 * (FONTSIZE / 10.0)) * LINECOUNT + 3;
const double RADIUS = PAD > HEIGHT / 2 ? HEIGHT / 2 - 1 : PAD;
m_bDamageBox = {0, 0, (int)PMONITOR->vecPixelSize.x, (int)HEIGHT + (int)PAD * 2};
cairo_new_sub_path(CAIRO);
cairo_arc(CAIRO, X + WIDTH - RADIUS, Y + RADIUS, RADIUS, -90 * DEGREES, 0 * DEGREES);
cairo_arc(CAIRO, X + WIDTH - RADIUS, Y + HEIGHT - RADIUS, RADIUS, 0 * DEGREES, 90 * DEGREES);
cairo_arc(CAIRO, X + RADIUS, Y + HEIGHT - RADIUS, RADIUS, 90 * DEGREES, 180 * DEGREES);
cairo_arc(CAIRO, X + RADIUS, Y + RADIUS, RADIUS, 180 * DEGREES, 270 * DEGREES);
cairo_close_path(CAIRO);
cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a);
cairo_fill_preserve(CAIRO);
cairo_set_source_rgba(CAIRO, 0, 0, 0, 1);
cairo_set_line_width(CAIRO, 2);
cairo_stroke(CAIRO);
// draw the text with a common font
const CColor textColor = m_cQueued.r * m_cQueued.g * m_cQueued.b < 0.5f ? CColor(255, 255, 255, 255) : CColor(0, 0, 0, 255);
const CColor textColor = m_cQueued.r + m_cQueued.g + m_cQueued.b < 0.2f ? CColor(1.0, 1.0, 1.0, 1.0) : CColor(0, 0, 0, 1.0);
cairo_select_font_face(CAIRO, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(CAIRO, FONTSIZE);
cairo_set_source_rgba(CAIRO, textColor.r / 255.f, textColor.g / 255.f, textColor.b / 255.f, textColor.a / 255.f);
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
float yoffset = FONTSIZE;
while(m_szQueued != "") {
while (m_szQueued != "") {
std::string current = m_szQueued.substr(0, m_szQueued.find('\n'));
if (const auto NEWLPOS = m_szQueued.find('\n'); NEWLPOS != std::string::npos)
m_szQueued = m_szQueued.substr(NEWLPOS + 1);
else
m_szQueued = "";
cairo_move_to(CAIRO, 0, yoffset);
cairo_move_to(CAIRO, PAD + 1 + RADIUS, yoffset + PAD + 1);
cairo_show_text(CAIRO, current.c_str());
yoffset += FONTSIZE + (FONTSIZE / 10.f);
}
cairo_surface_flush(CAIROSURFACE);
// copy the data to an OpenGL texture we have
@@ -79,8 +125,8 @@ void CHyprError::createQueued() {
cairo_surface_destroy(CAIROSURFACE);
m_bIsCreated = true;
m_szQueued = "";
m_cQueued = CColor();
m_szQueued = "";
m_cQueued = CColor();
g_pHyprRenderer->damageMonitor(PMONITOR);
}
@@ -93,22 +139,33 @@ void CHyprError::draw() {
}
if (m_bQueuedDestroy) {
m_bQueuedDestroy = false;
m_tTexture.destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
return;
if (!m_fFadeOpacity.isBeingAnimated()) {
if (m_fFadeOpacity.fl() == 0.f) {
m_bQueuedDestroy = false;
m_tTexture.destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
return;
} else {
m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
m_fFadeOpacity = 0.f;
}
}
}
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor;
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon
wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
m_bDamageBox.x = (int)PMONITOR->vecPosition.x;
m_bDamageBox.y = (int)PMONITOR->vecPosition.y;
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(&m_bDamageBox);
m_bMonitorChanged = false;
g_pHyprOpenGL->renderTexture(m_tTexture, &monbox, m_fFadeOpacity.fl(), 0);
}
void CHyprError::destroy() {

View File

@@ -2,22 +2,30 @@
#include "../defines.hpp"
#include "../render/Texture.hpp"
#include "../helpers/AnimatedVariable.hpp"
#include <cairo/cairo.h>
class CHyprError {
public:
void queueCreate(std::string message, const CColor& color);
void draw();
void destroy();
public:
CHyprError();
~CHyprError();
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
CTexture m_tTexture;
void queueCreate(std::string message, const CColor& color);
void draw();
void destroy();
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
CTexture m_tTexture;
CAnimatedVariable m_fFadeOpacity;
wlr_box m_bDamageBox = {0, 0, 0, 0};
bool m_bMonitorChanged = false;
};
inline std::unique_ptr<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time.

View File

@@ -6,7 +6,6 @@
#pragma diag_suppress 1696
#endif
#include <X11/Xlib.h>
#include <getopt.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
@@ -103,13 +102,17 @@ extern "C" {
#include <wlr/backend/headless.h>
#include <wlr/backend/multi.h>
#include <wlr/backend/wayland.h>
#include <wlr/types/wlr_session_lock_v1.h>
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <drm_fourcc.h>
#ifndef NO_XWAYLAND
#if WLR_HAS_X11_BACKEND
#include <wlr/backend/x11.h>
#endif
#ifndef NO_XWAYLAND
#include <wlr/xwayland.h>
#include <X11/Xproto.h>
#endif
}
@@ -129,6 +132,10 @@ extern "C" {
#include <GLES3/gl3ext.h>
#endif
#if !WLR_HAS_X11_BACKEND
#include "helpers/X11Stubs.hpp"
#endif
#ifdef NO_XWAYLAND
#define XWAYLAND false
#include "helpers/XWaylandStubs.hpp"

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -10,7 +10,7 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
} else {
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
@@ -24,6 +24,38 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
if (pWindow->m_sGroupData.pNextWindow) {
if (pWindow->m_sGroupData.pNextWindow == pWindow)
pWindow->m_sGroupData.pNextWindow = nullptr;
else {
// find last window and update
CWindow* curr = pWindow;
const auto CURRWASVISIBLE = curr->getGroupCurrent() == curr;
while (curr->m_sGroupData.pNextWindow != pWindow)
curr = curr->m_sGroupData.pNextWindow;
if (CURRWASVISIBLE)
curr->setGroupCurrent(curr);
curr->m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow;
pWindow->m_sGroupData.pNextWindow = nullptr;
if (pWindow->m_sGroupData.head) {
pWindow->m_sGroupData.head = false;
curr->m_sGroupData.head = true;
}
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
pWindow->setHidden(false);
return;
}
}
if (pWindow->m_bIsFloating) {
onWindowRemovedFloating(pWindow);
} else {
@@ -50,9 +82,10 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 &&
pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
pWindow->setHidden(true);
return;
}
@@ -62,7 +95,17 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
}
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) {
if (pWindow->m_uSurface.xwayland->x != 0 && pWindow->m_uSurface.xwayland->y != 0)
pWindow->m_vRealPosition = Vector2D{pWindow->m_uSurface.xwayland->x, pWindow->m_uSurface.xwayland->y};
else
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 {
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);
@@ -75,10 +118,14 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
if (!pWindow->m_bIsX11) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y,
m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
visible = true;
break;
@@ -102,7 +149,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
}
}
if (pWindow->m_bX11DoesntWantBorders) {
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
@@ -122,11 +169,13 @@ void IHyprLayout::onBeginDragWindow() {
// 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!");
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
if (DRAGGINGWINDOW->m_bIsFullscreen) {
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
@@ -134,56 +183,68 @@ void IHyprLayout::onBeginDragWindow() {
if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)");
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
g_pInputManager->setCursorImageUntilUnset("hand1");
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragMode == MBIND_MOVE) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goalv() / 2.f;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
m_vLastDragXY = m_vBeginDragXY;
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
m_vLastDragXY = m_vBeginDragXY;
// get the grab corner
if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) {
// left
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
m_iGrabbedCorner = 0;
else
m_iGrabbedCorner = 4;
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0) {
m_eGrabbedCorner = CORNER_TOPLEFT;
g_pInputManager->setCursorImageUntilUnset("nw-resize");
} else {
m_eGrabbedCorner = CORNER_BOTTOMLEFT;
g_pInputManager->setCursorImageUntilUnset("sw-resize");
}
} else {
// right
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
m_iGrabbedCorner = 1;
else
m_iGrabbedCorner = 3;
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0) {
m_eGrabbedCorner = CORNER_TOPRIGHT;
g_pInputManager->setCursorImageUntilUnset("ne-resize");
} else {
m_eGrabbedCorner = CORNER_BOTTOMRIGHT;
g_pInputManager->setCursorImageUntilUnset("se-resize");
}
}
if (g_pInputManager->dragMode != MBIND_RESIZE)
g_pInputManager->setCursorImageUntilUnset("grab");
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)) {
if (DRAGGINGWINDOW) {
g_pInputManager->unsetCursorImage();
g_pInputManager->currentlyDraggedWindow = nullptr;
}
return;
}
g_pInputManager->unsetCursorImage();
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
g_pInputManager->currentlyDraggedWindow = nullptr;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
@@ -206,23 +267,30 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
return;
}
const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID);
static auto TIMER = std::chrono::high_resolution_clock::now();
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID);
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
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)
const auto PANIMATEMOUSE = &g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging")->intValue;
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
return;
TIMER = std::chrono::high_resolution_clock::now();
m_vLastDragXY = mousePos;
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragMode == MBIND_MOVE) {
if (*PANIMATE) {
if (*PANIMATEMOUSE) {
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
} else {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
@@ -237,25 +305,23 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
// calc the new size and pos
Vector2D newSize = m_vBeginDragSizeXY;
Vector2D newPos = m_vBeginDragPositionXY;
Vector2D newPos = m_vBeginDragPositionXY;
if (m_iGrabbedCorner == 3) {
newSize = newSize + DELTA;
} else if (m_iGrabbedCorner == 0) {
newSize = newSize - DELTA;
newPos = newPos + DELTA;
} else if (m_iGrabbedCorner == 1) {
newSize = newSize + Vector2D(DELTA.x, -DELTA.y);
newPos = newPos + Vector2D(0, DELTA.y);
} else if (m_iGrabbedCorner == 4) {
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
newPos = newPos + Vector2D(DELTA.x, 0);
if (m_eGrabbedCorner == CORNER_BOTTOMRIGHT) {
newSize = (newSize + DELTA).clamp(Vector2D(20, 20), MAXSIZE);
} else if (m_eGrabbedCorner == CORNER_TOPLEFT) {
newSize = (newSize - DELTA).clamp(Vector2D(20, 20), MAXSIZE);
newPos = newPos - newSize + m_vBeginDragSizeXY;
} else if (m_eGrabbedCorner == CORNER_TOPRIGHT) {
newSize = (newSize + Vector2D(DELTA.x, -DELTA.y)).clamp(Vector2D(20, 20), MAXSIZE);
newPos = newPos + Vector2D(0, (m_vBeginDragSizeXY - newSize).y);
} else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) {
newSize = (newSize + Vector2D(-DELTA.x, DELTA.y)).clamp(Vector2D(20, 20), MAXSIZE);
newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0);
}
newSize = newSize.clamp(Vector2D(20,20), MAXSIZE);
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealSize = newSize;
DRAGGINGWINDOW->m_vRealSize = newSize;
DRAGGINGWINDOW->m_vRealPosition = newPos;
} else {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
@@ -301,15 +367,16 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
const auto TILED = isWindowTiled(pWindow);
// event
g_pEventManager->postEvent(SHyprIPCEvent{ "changefloatingmode", getFormat("%x,%d", pWindow, (int)TILED) });
g_pEventManager->postEvent(SHyprIPCEvent{"changefloatingmode", getFormat("%x,%d", pWindow, (int)TILED)});
EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->moveToWorkspace(PNEWMON->activeWorkspace);
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv();
// if the window is pseudo, update its size
@@ -336,14 +403,16 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
g_pCompositor->moveWindowToTop(pWindow);
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
pWindow->m_sSpecialRenderData.rounding = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
@@ -389,8 +458,10 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// find whether there is a floating window below this one
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) {
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x, w->m_vPosition.y + w->m_vSize.y)) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
!w->m_bNoFocus && w.get() != pWindow) {
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
w->m_vPosition.y + w->m_vSize.y)) {
return w.get();
}
}
@@ -401,12 +472,14 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
return m_pLastTiledWindow;
// if we don't, let's try to find any window that is in the middle
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); PWINDOWCANDIDATE)
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
return PWINDOWCANDIDATE;
// if not, floating window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus)
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
!w->m_bNoFocus && w.get() != pWindow)
return w.get();
}
@@ -417,11 +490,11 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// if it was a tiled window, we first try to find the window that will replace it.
const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus ||
PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
return nullptr;
return PWINDOWCANDIDATE;
}
IHyprLayout::~IHyprLayout() {
}
IHyprLayout::~IHyprLayout() {}

View File

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

View File

@@ -1,5 +1,6 @@
#include "MasterLayout.hpp"
#include "../Compositor.hpp"
#include <ranges>
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) {
for (auto& nd : m_lMasterNodesData) {
@@ -37,17 +38,19 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
}
//create on the fly if it doesn't exist yet
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
PWORKSPACEDATA->workspaceID = ws;
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
if (*orientation == "top") {
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
} else if (*orientation == "right") {
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
} else if (*orientation == "bottom") {
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
} else {
} else if (*orientation == "left") {
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
} else {
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
}
return PWORKSPACEDATA;
}
@@ -69,30 +72,45 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating)
return;
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
static auto* const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
PNODE->workspaceID = pWindow->m_iWorkspaceID;
PNODE->pWindow = pWindow;
PNODE->pWindow = pWindow;
static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
static auto* const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
float lastSplitPercent = 0.5f;
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
static auto* const PMFACT = &g_pConfigManager->getConfigValuePtr("master:mfact")->floatValue;
float lastSplitPercent = *PMFACT;
auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID ?
getNodeFromWindow(g_pCompositor->m_pLastWindow) :
getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && OPENINGON != PNODE && !g_pKeybindManager->m_bGroupsLocked) {
m_lMasterNodesData.remove(*PNODE);
OPENINGON->pWindow->insertWindowToGroup(pWindow);
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
return;
}
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
for (auto& nd : m_lMasterNodesData) {
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
nd.isMaster = false;
nd.isMaster = false;
lastSplitPercent = nd.percMaster;
break;
}
}
PNODE->isMaster = true;
PNODE->isMaster = true;
PNODE->percMaster = lastSplitPercent;
// first, check if it isn't too big.
@@ -104,10 +122,12 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
return;
}
} else {
PNODE->isMaster = false;
PNODE->isMaster = false;
PNODE->percMaster = lastSplitPercent;
// first, check if it isn't too big.
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow);
MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
// we can't continue. make it floating.
pWindow->m_bIsFloating = true;
m_lMasterNodesData.remove(*PNODE);
@@ -134,7 +154,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
return;
pWindow->m_sSpecialRenderData.rounding = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow->m_bIsFullscreen)
@@ -146,7 +166,8 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
// find new one
for (auto& nd : m_lMasterNodesData) {
if (!nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
nd.isMaster = true;
nd.isMaster = true;
nd.percMaster = PNODE->percMaster;
break;
}
}
@@ -157,9 +178,9 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
m_lMasterNodesData.remove(*PNODE);
if (getMastersOnWorkspace(WORKSPACEID) == getNodesOnWorkspace(WORKSPACEID) && MASTERSLEFT > 1) {
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->workspaceID == WORKSPACEID) {
it->isMaster = false;
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
if (nd.workspaceID == WORKSPACEID) {
nd.isMaster = false;
break;
}
}
@@ -169,7 +190,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
}
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
@@ -186,15 +207,15 @@ void CHyprMasterLayout::recalculateMonitor(const int& monid) {
return;
// massive hack from the fullscreen func
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
@@ -220,24 +241,37 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
if (!PMASTERNODE)
return;
eOrientation orientation = PWORKSPACEDATA->orientation;
bool centerMasterWindow = false;
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue;
if (orientation == ORIENTATION_CENTER) {
if (getNodesOnWorkspace(PWORKSPACE->m_iID) > 2 || (*ALWAYSCENTER == 1)) {
centerMasterWindow = true;
} else {
orientation = ORIENTATION_LEFT;
}
}
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
//compute placement of master window(s)
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) {
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2 && !centerMasterWindow) {
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x,
PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
applyNodeDataToWindow(PMASTERNODE);
return;
} else if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
int nodesLeft = MASTERS;
float nextY = 0;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster;
} else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
int nodesLeft = MASTERS;
float nextY = 0;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
if (PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMONITOR->vecSize.x - WIDTH, nextY);
if (orientation == ORIENTATION_RIGHT) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(PMONITOR->vecSize.x - WIDTH - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x, nextY);
} else {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
}
@@ -253,16 +287,17 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
applyNodeDataToWindow(&n);
}
}
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
int nodesLeft = MASTERS;
float nextX = 0;
const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster;
} else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
int nodesLeft = MASTERS;
float nextX = 0;
const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX,PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y);
if (orientation == ORIENTATION_BOTTOM) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(nextX, PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
} else {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
}
@@ -278,22 +313,44 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
applyNodeDataToWindow(&n);
}
}
}
} else if (orientation == ORIENTATION_CENTER) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
int nodesLeft = MASTERS;
float nextY = 0;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
float CENTER_OFFSET = (PMONITOR->vecSize.x - WIDTH) / 2;
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(CENTER_OFFSET, nextY);
float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1)
HEIGHT = heightLeft * 0.9f;
n.size = Vector2D(WIDTH, HEIGHT);
nodesLeft--;
heightLeft -= HEIGHT;
nextY += HEIGHT;
applyNodeDataToWindow(&n);
}
}
}
//compute placement of slave window(s)
int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS;
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
float nextY = 0;
const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x;
if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
float nextY = 0;
const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY);
if (orientation == ORIENTATION_LEFT) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY);
} else {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
}
@@ -308,16 +365,17 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
applyNodeDataToWindow(&nd);
}
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
float nextX = 0;
const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y;
} else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
float nextX = 0;
const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
if (PWORKSPACEDATA->orientation == ORIENTATION_TOP) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y));
if (orientation == ORIENTATION_TOP) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y));
} else {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
}
@@ -332,9 +390,50 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
applyNodeDataToWindow(&nd);
}
} else if (orientation == ORIENTATION_CENTER) {
float heightLeftL = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
float heightLeftR = heightLeftL;
float heightLeft = 0;
float nextYL = 0;
float nextYR = 0;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x) / 2.0;
bool on_left = true;
int slavesLeftL = 1 + (slavesLeft - 1) / 2;
int slavesLeftR = slavesLeft - slavesLeftL;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
if (on_left) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextYL);
heightLeft = heightLeftL;
slavesLeft = slavesLeftL;
} else {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(WIDTH + PMASTERNODE->size.x, nextYR);
heightLeft = heightLeftR;
slavesLeft = slavesLeftR;
}
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
HEIGHT = heightLeft * 0.9f;
nd.size = Vector2D(WIDTH, HEIGHT);
if (on_left) {
heightLeftL -= HEIGHT;
nextYL += HEIGHT;
slavesLeftL--;
} else {
heightLeftR -= HEIGHT;
nextYR += HEIGHT;
slavesLeftR--;
}
applyNodeDataToWindow(&nd);
on_left = !on_left;
}
}
}
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
@@ -357,14 +456,14 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PWINDOW = pNode->pWindow;
@@ -373,49 +472,53 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
return;
}
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 ||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.decorate = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN, DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN, DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
calcPos = calcPos + OFFSETTOPLEFT;
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
const auto RESERVED = PWINDOW->getFullWindowReservedArea();
calcPos = calcPos + RESERVED.topLeft;
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
@@ -459,7 +562,18 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
m_bForceWarps = true;
double delta = pixResize.x / PMONITOR->vecSize.x;
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace);
double delta = 0;
switch (PWORKSPACEDATA->orientation) {
case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break;
case ORIENTATION_RIGHT: delta = -pixResize.x / PMONITOR->vecSize.x; break;
case ORIENTATION_BOTTOM: delta = -pixResize.y / PMONITOR->vecSize.y; break;
case ORIENTATION_TOP: delta = pixResize.y / PMONITOR->vecSize.y; break;
case ORIENTATION_CENTER: delta = pixResize.x / PMONITOR->vecSize.x; break;
default: UNREACHABLE();
}
for (auto& n : m_lMasterNodesData) {
if (n.isMaster && n.workspaceID == PMONITOR->activeWorkspace)
@@ -467,14 +581,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
}
// check the up/down resize
if (pixResize.y != 0) {
const auto RESIZEDELTA = PWORKSPACEDATA->orientation % 2 == 1 ? pixResize.x : pixResize.y;
if (RESIZEDELTA != 0) {
if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) {
// check master size
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ?
(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getMastersOnWorkspace(PNODE->workspaceID) :
(PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
} else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) {
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getNodesOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ?
(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getNodesOnWorkspace(PNODE->workspaceID) :
(PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getNodesOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
}
}
@@ -488,9 +608,9 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
return;
if (on == pWindow->m_bIsFullscreen || g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID))
return; // ignore
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
@@ -500,10 +620,11 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
}
// otherwise, accept it.
pWindow->m_bIsFullscreen = on;
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
EMIT_HOOK_EVENT("fullscreen", pWindow);
if (!pWindow->m_bIsFullscreen) {
// if it got its fullscreen disabled, set back its node if it had one
@@ -512,8 +633,12 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
applyNodeDataToWindow(PNODE);
else {
// get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vPosition;
pWindow->m_vRealSize = pWindow->m_vSize;
pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_sSpecialRenderData.rounding = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
}
} else {
// if it now got fullscreen, make it fullscreen
@@ -522,26 +647,28 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
// save position and size if floating
if (pWindow->m_bIsFloating) {
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
}
// apply new pos and size being monitors' box
if (fullscreenMode == FULLSCREEN_FULL) {
pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize;
pWindow->m_vRealSize = PMONITOR->vecSize;
} else {
// This is a massive hack.
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SMasterNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
@@ -576,7 +703,7 @@ SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow)
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
// windows should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE2 = getNodeFromWindow(pWindow2);
if (!PNODE2 || !PNODE)
@@ -590,7 +717,7 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
}
// massive hack: just swap window pointers, lol
PNODE->pWindow = pWindow2;
PNODE->pWindow = pWindow2;
PNODE2->pWindow = pWindow;
recalculateMonitor(pWindow->m_iMonitorID);
@@ -603,7 +730,7 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
prepareNewFocus(pWindow2, inheritFullscreen);
}
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
void CHyprMasterLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) {
// window should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
@@ -613,7 +740,8 @@ void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f);
float newRatio = exact ? ratio : PMASTER->percMaster + ratio;
PMASTER->percMaster = std::clamp(newRatio, 0.05f, 0.95f);
recalculateMonitor(pWindow->m_iMonitorID);
}
@@ -624,67 +752,20 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
const auto PNODE = getNodeFromWindow(pWindow);
if (next) {
if (PNODE->isMaster) {
// focus the first non master
for (auto n : m_lMasterNodesData) {
if (n.pWindow != pWindow && n.workspaceID == pWindow->m_iWorkspaceID) {
return n.pWindow;
}
}
} else {
// focus next
bool reached = false;
bool found = false;
for (auto n : m_lMasterNodesData) {
if (n.pWindow == pWindow) {
reached = true;
continue;
}
auto nodes = m_lMasterNodesData;
if (!next)
std::reverse(nodes.begin(), nodes.end());
if (n.workspaceID == pWindow->m_iWorkspaceID && reached) {
return n.pWindow;
}
}
if (!found) {
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
const auto NODEIT = std::find(nodes.begin(), nodes.end(), *PNODE);
if (PMASTER)
return PMASTER->pWindow;
}
}
} else {
if (PNODE->isMaster) {
// focus the last non master
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->pWindow != pWindow && it->workspaceID == pWindow->m_iWorkspaceID) {
return it->pWindow;
}
}
} else {
// focus previous
bool reached = false;
bool found = false;
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->pWindow == pWindow) {
reached = true;
continue;
}
const bool ISMASTER = PNODE->isMaster;
if (it->workspaceID == pWindow->m_iWorkspaceID && reached) {
return it->pWindow;
}
}
if (!found) {
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
auto CANDIDATE = std::find_if(NODEIT, nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER == other.isMaster && other.workspaceID == PNODE->workspaceID; });
if (CANDIDATE == nodes.end())
CANDIDATE =
std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; });
if (PMASTER)
return PMASTER->pWindow;
}
}
}
return nullptr;
return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow;
}
bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
@@ -694,7 +775,7 @@ bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
//if the current window is fullscreen, make it normal again if we are about to lose focus
if (pWindow->m_bIsFullscreen) {
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
static auto *const INHERIT = &g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen")->intValue;
static auto* const INHERIT = &g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen")->intValue;
return *INHERIT == 1;
}
@@ -706,7 +787,7 @@ void CHyprMasterLayout::prepareNewFocus(CWindow* pWindow, bool inheritFullscreen
return;
if (inheritFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, true, FULLSCREEN_MAXIMIZED);
g_pCompositor->setWindowFullscreen(pWindow, true, g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_efFullscreenMode);
}
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
@@ -718,7 +799,21 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f);
};
if (message == "swapwithmaster") {
CVarList vars(message, 0, ' ');
if (vars.size() < 1 || vars[0].empty()) {
Debug::log(ERR, "layoutmsg called without params");
return 0;
}
auto command = vars[0];
// swapwithmaster <master | child | auto>
// first message argument can have the following values:
// * master - keep the focus at the new master
// * child - keep the focus at the new child
// * auto (default) - swap the focus (keep the focus of the previously selected window)
if (command == "swapwithmaster") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -732,22 +827,38 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PMASTER)
return 0;
const auto NEWCHILD = PMASTER->pWindow;
if (PMASTER->pWindow != PWINDOW) {
switchWindows(PWINDOW, PMASTER->pWindow);
switchToWindow(PWINDOW);
const auto NEWMASTER = PWINDOW;
const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child";
const bool inheritFullscreen = prepareLoseFocus(NEWMASTER);
switchWindows(NEWMASTER, NEWCHILD);
const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER;
switchToWindow(NEWFOCUS);
prepareNewFocus(NEWFOCUS, inheritFullscreen);
} else {
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchWindows(n.pWindow, PMASTER->pWindow);
switchToWindow(n.pWindow);
const auto NEWMASTER = n.pWindow;
const bool inheritFullscreen = prepareLoseFocus(NEWCHILD);
switchWindows(NEWMASTER, NEWCHILD);
const bool newFocusToMaster = vars.size() >= 2 && vars[1] == "master";
const auto NEWFOCUS = newFocusToMaster ? NEWMASTER : NEWCHILD;
switchToWindow(NEWFOCUS);
prepareNewFocus(NEWFOCUS, inheritFullscreen);
break;
}
}
}
return 0;
} else if (message == "focusmaster") {
}
// focusmaster <master | auto>
// first message argument can have the following values:
// * master - keep the focus at the new master, even if it was focused before
// * auto (default) - swap the focus with the first child, if the current focus was master, otherwise focus master
else if (command == "focusmaster") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -763,7 +874,10 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (PMASTER->pWindow != PWINDOW) {
switchToWindow(PMASTER->pWindow);
prepareNewFocus(PMASTER->pWindow, inheritFullscreen);
} else if (vars.size() >= 2 && vars[1] == "master") {
return 0;
} else {
// if master is focused keep master focused (don't do anything)
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchToWindow(n.pWindow);
@@ -774,7 +888,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
}
return 0;
} else if (message == "cyclenext") {
} else if (command == "cyclenext") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -785,7 +899,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
switchToWindow(PNEXTWINDOW);
prepareNewFocus(PNEXTWINDOW, inheritFullscreen);
} else if (message == "cycleprev") {
} else if (command == "cycleprev") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -793,10 +907,10 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
const auto PPREVWINDOW = getNextWindow(PWINDOW, true);
const auto PPREVWINDOW = getNextWindow(PWINDOW, false);
switchToWindow(PPREVWINDOW);
prepareNewFocus(PPREVWINDOW, inheritFullscreen);
} else if (message == "swapnext") {
} else if (command == "swapnext") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
@@ -812,7 +926,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
}
} else if (message == "swapprev") {
} else if (command == "swapprev") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
@@ -828,14 +942,14 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
}
} else if (message == "addmaster") {
} else if (command == "addmaster") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
if (header.pWindow->m_bIsFloating)
return 0;
const auto PNODE = getNodeFromWindow(header.pWindow);
const auto PNODE = getNodeFromWindow(header.pWindow);
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID);
const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID);
@@ -859,7 +973,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "removemaster") {
} else if (command == "removemaster") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
@@ -879,9 +993,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PNODE || !PNODE->isMaster) {
// first non-master node
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->workspaceID == header.pWindow->m_iWorkspaceID && it->isMaster) {
it->isMaster = false;
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
if (nd.workspaceID == header.pWindow->m_iWorkspaceID && nd.isMaster) {
nd.isMaster = false;
break;
}
}
@@ -890,7 +1004,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
}
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationleft" || message == "orientationright" || message == "orientationtop" || message == "orientationbottom") {
} else if (command == "orientationleft" || command == "orientationright" || command == "orientationtop" || command == "orientationbottom" || command == "orientationcenter") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -900,18 +1014,20 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (message == "orientationleft")
if (command == "orientationleft")
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
else if (message == "orientationright")
else if (command == "orientationright")
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
else if (message == "orientationtop")
else if (command == "orientationtop")
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
else if (message == "orientationbottom")
else if (command == "orientationbottom")
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
else if (command == "orientationcenter")
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationnext") {
} else if (command == "orientationnext") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -921,14 +1037,14 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
if (PWORKSPACEDATA->orientation == ORIENTATION_CENTER) {
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
} else {
PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation + 1);
PWORKSPACEDATA->orientation = (eOrientation)(PWORKSPACEDATA->orientation + 1);
}
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationprev") {
} else if (command == "orientationprev") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
@@ -939,9 +1055,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
} else {
PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation - 1);
PWORKSPACEDATA->orientation = (eOrientation)(PWORKSPACEDATA->orientation - 1);
}
recalculateMonitor(header.pWindow->m_iMonitorID);
@@ -950,6 +1066,17 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
return 0;
}
void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
const auto PNODE = getNodeFromWindow(from);
if (!PNODE)
return;
PNODE->pWindow = to;
applyNodeDataToWindow(PNODE);
}
void CHyprMasterLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())

View File

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

View File

@@ -4,6 +4,9 @@
#include "config/ConfigManager.hpp"
#include "init/initHelpers.hpp"
#include <iostream>
#ifdef USES_SYSTEMD
#include <systemd/sd-daemon.h> // for sd_notify
#endif
int main(int argc, char** argv) {
@@ -16,11 +19,13 @@ int main(int argc, char** argv) {
cmd += std::string(i == 0 ? "" : " ") + argv[i];
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
setenv("XDG_BACKEND", "wayland", 1);
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 0);
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1);
setenv("MOZ_ENABLE_WAYLAND", "1", 1);
setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1);
// parse some args
std::string configPath;
bool ignoreSudo = false;
bool ignoreSudo = false;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid"))
ignoreSudo = true;
@@ -28,20 +33,18 @@ int main(int argc, char** argv) {
configPath = std::string(argv[++i]);
Debug::log(LOG, "Using config location %s.", configPath.c_str());
} else {
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" <<
"--help -h | Show this help message\n" <<
"--config -c | Specify config file to use\n";
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n"
<< "--help -h | Show this help message\n"
<< "--config -c | Specify config file to use\n";
return 1;
}
}
system("mkdir -p /tmp/hypr");
if (!ignoreSudo) {
if (Init::isSudo()) {
std::cout << "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.\n";
return 1;
}
}
} else {
std::cout << "Running with ignored root checks, I surely hope you know what you're doing.\n";
sleep(1);
@@ -49,15 +52,13 @@ int main(int argc, char** argv) {
std::cout << "Welcome to Hyprland!\n";
const auto LOGWLR = getenv("HYPRLAND_LOG_WLR");
if (LOGWLR && std::string(LOGWLR) == "1")
wlr_log_init(WLR_DEBUG, Debug::wlrLog);
// let's init the compositor.
// it initializes basic Wayland stuff in the constructor.
g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor->explicitConfigPath = configPath;
g_pCompositor->initServer();
Debug::log(LOG, "Hyprland init finished.");
// If all's good to go, start.
@@ -66,13 +67,21 @@ int main(int argc, char** argv) {
// If we are here it means we got yote.
Debug::log(LOG, "Hyprland reached the end.");
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
#ifdef USES_SYSTEMD
// tell systemd it destroy bound/related units
if (sd_booted() > 0)
sd_notify(0, "STOPPING=1");
#endif
if (g_pCompositor->m_sWLDisplay)
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
// kill all clients
for (auto& c : g_pCompositor->m_dProcessPIDsOnShutdown)
kill(c, SIGKILL);
wl_display_destroy(g_pCompositor->m_sWLDisplay);
if (g_pCompositor->m_sWLDisplay)
wl_display_destroy(g_pCompositor->m_sWLDisplay);
return EXIT_SUCCESS;
}

View File

@@ -1,9 +1,23 @@
#include "AnimationManager.hpp"
#include "../Compositor.hpp"
int wlTick(void* data) {
float refreshRate = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor->refreshRate : 60.f;
wl_event_source_timer_update(g_pAnimationManager->m_pAnimationTick, 1000 / refreshRate);
g_pAnimationManager->tick();
return 0;
}
CAnimationManager::CAnimationManager() {
std::vector<Vector2D> points = {Vector2D(0, 0.75f), Vector2D(0.15f, 1.f)};
m_mBezierCurves["default"].setup(&points);
m_pAnimationTick = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, &wlTick, nullptr);
wl_event_source_timer_update(m_pAnimationTick, 1);
}
void CAnimationManager::removeAllBeziers() {
@@ -21,17 +35,21 @@ void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1,
void CAnimationManager::tick() {
bool animGlobalDisabled = false;
static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now();
m_fLastTickTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0;
lastTick = std::chrono::high_resolution_clock::now();
static auto *const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
bool animGlobalDisabled = false;
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
if (!*PANIMENABLED)
animGlobalDisabled = true;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
std::vector<CAnimatedVariable*> animationEndedVars;
@@ -50,25 +68,28 @@ void CAnimationManager::tick() {
const float SPENT = av->getPercent();
// window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
CMonitor* PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
CMonitor* PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
wlr_box WLRBOXPREV = {0,0,0,0};
wlr_box WLRBOXPREV = {0, 0, 0, 0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
animationsDisabled = animationsDisabled || PWINDOW->m_sAdditionalConfigData.forceNoAnims;
} else if (PWORKSPACE) {
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry;
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
animationsDisabled = animationsDisabled || PLAYER->noAnimations;
}
const bool VISIBLE = PWINDOW ? g_pCompositor->isWorkspaceVisible(PWINDOW->m_iWorkspaceID) : true;
// beziers are with a switch unforto
// TODO: maybe do something cleaner
@@ -85,7 +106,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -106,7 +127,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -127,7 +148,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -141,7 +162,18 @@ void CAnimationManager::tick() {
}
}
// damage the window with the damage policy
// 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 && PWINDOW->m_iX11Type != 2)
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
// check if we did not finish animating. If so, trigger onAnimationEnd.
if (!av->isBeingAnimated())
animationEndedVars.push_back(av);
// lastly, handle damage, but only if whatever we are animating is visible.
if (!VISIBLE)
continue;
switch (av->m_eDamagePolicy) {
case AVARDAMAGE_ENTIRE: {
g_pHyprRenderer->damageBox(&WLRBOXPREV);
@@ -164,40 +196,46 @@ void CAnimationManager::tick() {
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
}
break;
} case AVARDAMAGE_BORDER: {
}
case AVARDAMAGE_BORDER: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
// damage only the border.
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE;
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE;
// damage for old box
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXPREV.x + WLRBOXPREV.width - ROUNDINGSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXPREV.x, WLRBOXPREV.y + WLRBOXPREV.height - ROUNDINGSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXPREV.x + WLRBOXPREV.width - ROUNDINGSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
WLRBOXPREV.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXPREV.x, WLRBOXPREV.y + WLRBOXPREV.height - ROUNDINGSIZE, WLRBOXPREV.width + 2 * BORDERSIZE,
BORDERSIZE + ROUNDINGSIZE); // bottom
// damage for new box
const wlr_box WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
WLRBOXNEW.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
break;
} case AVARDAMAGE_SHADOW: {
}
case AVARDAMAGE_SHADOW: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
if (PDECO) {
const auto EXTENTS = PDECO->getWindowDecorationExtents();
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x,
PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
if (!*PSHADOWIGNOREWINDOW) {
// easy, damage the entire box
@@ -206,7 +244,8 @@ void CAnimationManager::tick() {
pixman_region32_t rg;
pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height);
pixman_region32_t wb;
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y);
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x,
PWINDOW->m_vRealSize.vec().y);
pixman_region32_subtract(&rg, &rg, &wb);
g_pHyprRenderer->damageRegion(&rg);
pixman_region32_fini(&rg);
@@ -217,21 +256,13 @@ void CAnimationManager::tick() {
break;
}
default: {
Debug::log(ERR, "av has damage policy INVALID???");
break;
}
}
// 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 && PWINDOW->m_iX11Type != 2)
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
// manually schedule a frame
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
// check if we did not finish animating. If so, trigger onAnimationEnd.
if (!av->isBeingAnimated())
animationEndedVars.push_back(av);
if (PMONITOR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
// do it here, because if this alters the animation vars deque we would be in trouble above.
@@ -265,7 +296,7 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
}
bool CAnimationManager::bezierExists(const std::string& bezier) {
for (auto&[bc, bz] : m_mBezierCurves) {
for (auto& [bc, bz] : m_mBezierCurves) {
if (bc == bezier)
return true;
}
@@ -279,33 +310,37 @@ bool CAnimationManager::bezierExists(const std::string& bezier) {
//
void CAnimationManager::animationPopin(CWindow* pWindow, bool close, float minPerc) {
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
if (!close) {
pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}));
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vValue / 2.f);
} else {
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vGoal / 2.f;
}
}
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) {
pWindow->m_vRealSize.warp(false); // size we preserve in slide
pWindow->m_vRealSize.warp(false); // size we preserve in slide
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
Vector2D posOffset;
Vector2D posOffset;
if (force != "") {
if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else if (force == "left") posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
else if (force == "right") posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (force == "bottom")
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else if (force == "left")
posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
else if (force == "right")
posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
else
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (!close)
pWindow->m_vRealPosition.setValue(posOffset);
@@ -318,9 +353,9 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool
const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f;
// check sides it touches
const bool DISPLAYLEFT = STICKS(pWindow->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pWindow->m_vPosition.x + pWindow->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pWindow->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYLEFT = STICKS(pWindow->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pWindow->m_vPosition.x + pWindow->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pWindow->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pWindow->m_vPosition.y + pWindow->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
if (DISPLAYBOTTOM && DISPLAYTOP) {
@@ -351,12 +386,12 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool
void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (!close) {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn");
} else {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut");
}
auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle;
@@ -386,7 +421,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (pWindow->m_sAdditionalConfigData.animationStyle.find("%") != std::string::npos) {
try {
auto percstr = pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
; // oops
}
@@ -404,7 +439,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (ANIMSTYLE.find("%") != 0) {
try {
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
; // oops
}
@@ -425,10 +460,8 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
if (style.find("%") != std::string::npos) {
try {
auto percstr = style.substr(style.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
return "invalid minperc";
}
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) { return "invalid minperc"; }
return "";
}
@@ -444,9 +477,23 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
return "";
return "unknown style";
} else if (config == "borderangle") {
if (style == "loop" || style == "once")
return "";
return "unknown style";
} else {
return "animation has no styles";
}
return "";
}
CBezierCurve* CAnimationManager::getBezier(const std::string& name) {
const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; });
return BEZIER == m_mBezierCurves.end() ? &m_mBezierCurves["default"] : &BEZIER->second;
}
std::unordered_map<std::string, CBezierCurve> CAnimationManager::getAllBeziers() {
return m_mBezierCurves;
}

View File

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

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