Compare commits

...

106 Commits

Author SHA1 Message Date
vaxerski
61aa4ff70e [gha] bump flake inputs 2022-08-20 18:07:29 +00:00
vaxerski
cc3f0ff9e7 update wlroots dep 2022-08-20 20:06:24 +02:00
vaxerski
7af193d921 reload on input and device hyprctl 2022-08-20 18:57:30 +02:00
vaxerski
132c96f867 multiple fixes for device configs 2022-08-20 18:47:48 +02:00
vaxerski
45a0e69286 Find a candidate better on window close 2022-08-20 18:12:59 +02:00
vaxerski
0ebef9a8ae no focus to OR Xwayland 2022-08-20 18:00:50 +02:00
vaxerski
185f93ae64 fix dwindle active for splits 2022-08-20 17:59:15 +02:00
vaxerski
1b1a0259a8 fix crash 2022-08-19 23:22:59 +02:00
Vaxry
223ca6e286 Merge pull request #548 from FlafyDev/main
add input:kb_file option to use a .xkb file.
2022-08-19 22:39:50 +02:00
FlafyDev
f0ad77251b move absolutePath to MiscFunctions 2022-08-19 23:18:09 +03:00
vaxerski
c2a3896cc9 added dwindle:use_active_for_splits 2022-08-19 22:03:41 +02:00
Vaxry
e749331f30 update wiki links in readme 2022-08-19 21:50:57 +02:00
FlafyDev
69d17bf424 add input:kb_file 2022-08-19 21:01:51 +03:00
vaxerski
946222f4a7 fix typo in swipe alpha control 2022-08-19 17:42:10 +02:00
vaxerski
504d07a87d fix swipe on workspace style fade 2022-08-19 17:36:01 +02:00
vaxerski
81b27be6bb reset lastwindow on full LS focus 2022-08-19 17:29:16 +02:00
vaxerski
f9e30e985c fix refocus on no window 2022-08-19 17:25:07 +02:00
vaxerski
6cae44e2c0 fix custom rounding in shadow deco 2022-08-19 14:52:18 +02:00
vaxerski
43aea417b0 Fix occasional hangups on exit 2022-08-18 22:36:58 +02:00
Vaxry
ece3ac97f9 Merge pull request #543 from Roger-Roger-debug/main
More fullscreen animation fixes
2022-08-18 19:51:37 +02:00
vaxerski
9b62328b22 minor changes to the activelayout event 2022-08-18 17:50:32 +02:00
vaxerski
c1a64a2b9d added main param to keyboards 2022-08-18 17:34:01 +02:00
vaxerski
b078a12eed Added an activelayout event 2022-08-18 17:17:33 +02:00
Roger Roger
eca6e53bd7 Animate workspaces with fullscreen windows 2022-08-18 12:42:21 +02:00
Roger Roger
f2d3aecf00 Don't draw fullscreen windows on other monitors 2022-08-18 12:41:10 +02:00
vaxerski
f3c597bfb7 fix crash 2022-08-18 07:28:07 +02:00
vaxerski
c5a4c83f78 better integrate touch with subsurfaces 2022-08-17 23:23:36 +02:00
vaxerski
f4d11d2d43 fix lastFocus on activateWindow 2022-08-17 22:59:40 +02:00
Vaxry
4c1dba643e Merge pull request #535 from Roger-Roger-debug/main
Fix workspace animation showing on other monitors
2022-08-17 12:35:03 +02:00
Roger Roger
5a20573e91 Fix workspace animation showing on other monitors 2022-08-17 12:12:16 +02:00
vaxerski
cd9c85a150 never animate moving floating windows 2022-08-16 22:40:16 +02:00
vaxerski
bbc6b5d5e0 added misc:animate_manual_resizes 2022-08-16 21:56:54 +02:00
vaxerski
a59641096c ignore dwindle reload on full window null 2022-08-16 21:32:12 +02:00
vaxerski
c6de4ee4b7 more checks in fullscreen event 2022-08-16 21:30:53 +02:00
vaxerski
317b6c430c damage monitor on workspace swipe end 2022-08-16 16:34:36 +02:00
vaxerski
095487ea5d disallow configure from fullscreen 2022-08-16 16:31:44 +02:00
vaxerski
daeb0d3418 force sending size on setWindowFullscreen 2022-08-16 16:30:10 +02:00
vaxerski
7cde50a018 scale hyprerror with the monitor res 2022-08-16 16:25:53 +02:00
vaxerski
bec7501365 fix borders on no_gaps_when_only 2022-08-16 16:19:52 +02:00
vaxerski
ea45c6bfe0 fix memory issue with hyprctl devices 2022-08-16 16:15:43 +02:00
vaxerski
6e2467cc24 fix active keymap in hyprctl devices 2022-08-16 16:10:20 +02:00
vaxerski
454d0d3f9f fix autogen config warning 2022-08-16 15:59:18 +02:00
vaxerski
d2011a4ba9 added support for window selection in moving to workspace 2022-08-15 16:12:53 +02:00
vaxerski
b0b3a5af10 added resizewindowpixel and movewindowpixel 2022-08-15 15:59:07 +02:00
vaxerski
d47bfe6af1 remove unused fixXWaylandWindowsOnWorkspace 2022-08-15 00:34:39 +02:00
Mihai Fufezan
c982312c07 Nix HM module: reload config-only 2022-08-15 00:47:56 +03:00
vaxerski
f0fe0c25d6 added config-only to hyprctl reload 2022-08-14 23:26:18 +02:00
vaxerski
d906617fb6 clean up fullscreen logic in fullscreenWindow event 2022-08-14 23:03:50 +02:00
Mihai Fufezan
ed1b72f37d Nix HM module: add XDG_SESSION_TYPE, fix reload 2022-08-14 23:45:55 +03:00
vaxerski
28867758c4 better fix the last fix 2022-08-14 16:39:56 +02:00
vaxerski
920727cbba fix crash with fullscreen requests 2022-08-14 16:34:40 +02:00
vaxerski
bfe0f844d2 fix wallpaper pixelation in some cases 2022-08-13 22:33:51 +02:00
vaxerski
214c2c7b1c fix groups not updating size on head change 2022-08-13 10:08:35 +02:00
vaxerski
9136783e9c default hardcoded rule to preferred auto 2022-08-12 22:26:35 +02:00
Vaxry
662b6003c6 Merge pull request #515 from SignalWalker/main
fix: support clang in meson build
2022-08-12 22:15:32 +02:00
Fernando Ayats
c136078239 nix: use cleanSource (#518) 2022-08-12 23:12:24 +03:00
Ash Walker
38056c0102 fix: support clang in meson build 2022-08-12 11:21:19 -04:00
vaxerski
db35a1c6d0 ensure egl is current in begin 2022-08-12 17:10:07 +02:00
vaxerski
66b0622bc5 fixed popup unmap damage 2022-08-12 17:04:26 +02:00
vaxerski
0e57651e2f fix segfault with cyclenext null 2022-08-11 22:56:16 +02:00
vaxerski
e5ab9643be enable layers_hog_keyboard_focus by default 2022-08-11 21:52:38 +02:00
vaxerski
b3c5809986 fix flags syntax in json 2022-08-11 21:29:31 +02:00
vaxerski
ae175fdda5 handle json for hyprctl version 2022-08-11 21:28:37 +02:00
vaxerski
9102471610 added hyprctl getoption 2022-08-11 21:16:38 +02:00
vaxerski
f85c765634 change activemon to focusedmon for consistency 2022-08-11 20:55:39 +02:00
vaxerski
37442db20e destroy program in shader destructor 2022-08-11 20:33:35 +02:00
vaxerski
b178891ab3 compile shaders for every context separately 2022-08-11 20:29:21 +02:00
vaxerski
073f08301a fix formatting in focused monitor hyprctl 2022-08-11 20:22:41 +02:00
vaxerski
8fb4669b85 fix cyclenext on fullscreen 2022-08-11 20:21:55 +02:00
vaxerski
008cc63dc0 fix error for popin 2022-08-11 20:17:23 +02:00
vaxerski
aba63a7f96 disallow nested groups creation 2022-08-11 19:56:29 +02:00
vaxerski
c9ed5bf77e fix cyclenext with fullscreen windows 2022-08-11 19:45:37 +02:00
vaxerski
f4f0495050 disable focus to menu x11 types 2022-08-11 19:36:15 +02:00
vaxerski
c319a2aba9 Completely rewrote Dwindle group code 2022-08-11 19:29:39 +02:00
vaxerski
cd75606f42 change active to focused in hyprctl monitors 2022-08-10 23:49:20 +02:00
vaxerski
c7350117f1 reinit render on disconnected displays 2022-08-10 23:19:15 +02:00
vaxerski
69db6207c0 don't damage in unsafe state 2022-08-10 23:14:53 +02:00
vaxerski
58ff04fdf3 added experimental monitor saving 2022-08-10 21:54:09 +02:00
vaxerski
9b39a0c2e0 Added hyprctl setcursor 2022-08-10 21:22:11 +02:00
vaxerski
f64f94ca56 scale rounding in shadows 2022-08-10 18:29:37 +02:00
vaxerski
76877d4b15 minor changes to monitor logging 2022-08-10 18:27:57 +02:00
vaxerski
96f3b62429 multiply by scale in rounding 2022-08-10 18:22:01 +02:00
vaxerski
0162da7a7c adjust curve size for scaled 2022-08-10 18:10:38 +02:00
vaxerski
9eb750c00b added misc:layers_hog_keyboard_focus 2022-08-10 17:46:01 +02:00
vaxerski
03f2e4d42a fix compile 2022-08-10 13:45:20 +02:00
vaxerski
15fc0892c7 further fixes to monitor disabling on launch 2022-08-10 13:44:04 +02:00
vaxerski
a564be73c5 set correct full params in disabled at launch 2022-08-10 13:31:58 +02:00
vaxerski
7e8666754f allow focus to override redirect 2022-08-10 12:49:45 +02:00
vaxerski
c043bcdee6 fixes to toplevel updates 2022-08-10 08:51:59 +02:00
vaxerski
8e5985d70e clean up unconstraining logic 2022-08-09 20:36:21 +02:00
vaxerski
9255a4d2ff ignore further keybinds on submap change 2022-08-09 19:54:06 +02:00
vaxerski
113ac67a16 focus monitor on monitor rule 2022-08-09 18:51:26 +02:00
vaxerski
862722412f handle fullscreen in dwindle groups better 2022-08-09 18:37:50 +02:00
vaxerski
a6d4a4d5f3 warn about incorrect bezier args 2022-08-09 18:15:37 +02:00
vaxerski
e2f61e267e add parse errors for invalid kb layouts 2022-08-09 18:13:13 +02:00
Mihai Fufezan
ecce027c02 flake: add aarch64-linux as supported platform 2022-08-09 13:17:47 +03:00
Mihai Fufezan
f28b71232a unhide window on requested size change 2022-08-09 11:57:09 +03:00
Yavor Kolev
af9d34ab77 Fix my idiotic mistake (#502)
When resolving conflicts i accepted the old changes 👨🏻🔫
2022-08-09 02:22:55 +03:00
Mihai Fufezan
2d33d4aebc nix & meson: update version to 0.10.0 2022-08-09 01:35:05 +03:00
Vaxry
aa39653ea1 Merge pull request #500 from yavko/fix-active-window-json-bools
Fix the fix
2022-08-08 22:58:34 +02:00
Yavor Kolev
6d788f0fc9 Merge branch 'main' into fix-active-window-json-bools 2022-08-08 13:51:08 -07:00
vaxerski
ab6a62f0fd Revert "Merge pull request #499 from yavko/fix-active-window-json-bools"
This reverts commit 5aed6f1bc7, reversing
changes made to 6f137938da.
2022-08-08 22:49:02 +02:00
Yavor Kolev
d460519c30 Fix the fix 2022-08-08 13:48:33 -07:00
vaxerski
b60b52c5cf fix movefocusto with null last 2022-08-08 22:46:11 +02:00
Vaxry
5aed6f1bc7 Merge pull request #499 from yavko/fix-active-window-json-bools
makes active windoe consistient with client json
2022-08-08 22:42:09 +02:00
Yavor Kolev
5cec6257e9 The fix 2022-08-08 13:39:02 -07:00
46 changed files with 1352 additions and 670 deletions

View File

@@ -123,7 +123,7 @@ Try it out and report bugs / suggestions!
<!----------------------------------------------------------------------------->
[Configure]: https://github.com/hyprwm/Hyprland/wiki/Configuring-Hyprland
[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
[Discord]: https://discord.gg/hQ9XvMUjjr
[Stars]: https://starchart.cc/hyprwm/Hyprland
[Hypr]: https://github.com/hyprwm/Hypr
@@ -132,9 +132,9 @@ Try it out and report bugs / suggestions!
[Issues]: https://github.com/hyprwm/Hyprland/issues
[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
[Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
[Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
[Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
[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/
[License]: LICENSE

View File

@@ -12,6 +12,7 @@ monitor=,preferred,auto,1
workspace=DP-1,1
input {
kb_file=
kb_layout=
kb_variant=
kb_model=
@@ -112,4 +113,4 @@ bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1
bind=SUPER,mouse_up,workspace,e-1

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1659522808,
"narHash": "sha256-HBcM19nGhI3IWwPNVlYb0MZ8VW6iKp4JbAVkeIHVykc=",
"lastModified": 1660908602,
"narHash": "sha256-SwZ85IPWvC4NxxFhWhRMTJpApSHbY1u4YK2UFWEBWvY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "168d1c578909dc143ba52dbed661c36e76b12b36",
"rev": "495b19d5b3e62b4ec7e846bdfb6ef3d9c3b83492",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1659738224,
"narHash": "sha256-bV3TLiCgptpKoUKLiH/5RMtiIsfn0hawdaCEHQFB6WY=",
"lastModified": 1660930713,
"narHash": "sha256-bY7q1NqG/sjCUAWPn/Ne9NCigLlPlH5Lk1WCMqv3rTU=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "3baf2a6bcfc4cb86c364f5724aaec80f28715a01",
"rev": "7c575922c05e4d5fd9a403c2aa631a54c7531d44",
"type": "gitlab"
},
"original": {

View File

@@ -17,6 +17,7 @@
inherit (nixpkgs) lib;
genSystems = lib.genAttrs [
# Add more systems if they are supported
"aarch64-linux"
"x86_64-linux"
];
pkgsFor = nixpkgs.legacyPackages;
@@ -33,7 +34,7 @@
});
hyprland = prev.callPackage ./nix/default.nix {
stdenv = prev.gcc12Stdenv;
version = "0.9.1beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
version = "0.10.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};

View File

@@ -34,6 +34,8 @@ commands:
splash
hyprpaper
reload
setcursor
getoption
flags:
-j -> output in JSON
@@ -183,6 +185,17 @@ void hyprpaperRequest(int argc, char** argv) {
requestHyprpaper(rq);
}
void setcursorRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "setcursor requires 2 params";
return;
}
std::string rq = "setcursor " + std::string(argv[2]) + " " + std::string(argv[3]);
request(rq);
}
void batchRequest(std::string arg) {
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
@@ -252,6 +265,8 @@ int main(int argc, char** argv) {
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("/setcursor")) setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);

View File

@@ -1,8 +1,22 @@
project('Hyprland', 'cpp', 'c',
version : '0.8.1beta',
default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
version : '0.10.0beta',
default_options : [
'warning_level=2',
'default_library=static',
'optimization=3',
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
])
add_global_arguments('-std=c++23', language: 'cpp')
# clang v14.0.6 uses C++2b instead of C++23, so we've gotta account for that
# replace the following with a project default option once meson gets support for C++23
cpp_compiler = meson.get_compiler('cpp')
if cpp_compiler.has_argument('-std=c++23')
add_global_arguments('-std=c++23', language: 'cpp')
elif cpp_compiler.has_argument('-std=c++2b')
add_global_arguments('-std=c++2b', language: 'cpp')
else
error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.get_version() + ') with required C++ standard (C++23)')
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()

View File

@@ -27,7 +27,16 @@
stdenv.mkDerivation {
pname = "hyprland" + lib.optionalString debug "-debug";
inherit version;
src = ../.;
src = lib.cleanSourceWith {
filter = name: type: let
baseName = baseNameOf (toString name);
in
! (
lib.hasSuffix ".nix" baseName
);
src = lib.cleanSource ../.;
};
nativeBuildInputs = [
meson
@@ -59,7 +68,7 @@ stdenv.mkDerivation {
mesonFlags = builtins.concatLists [
(lib.optional (!enableXWayland) "-DNO_XWAYLAND=true")
(lib.optional (legacyRenderer) "-DLEGACY_RENDERER:STRING=true")
(lib.optional legacyRenderer "-DLEGACY_RENDERER:STRING=true")
];
patches = [

View File

@@ -65,9 +65,11 @@ in {
xdg.configFile."hypr/hyprland.conf" = {
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
")
(lib.optionalString cfg.systemdIntegration ''
exec-once=export XDG_SESSION_TYPE=wayland
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP
exec-once=systemctl --user start hyprland-session.target
'')
+ cfg.extraConfig;
onChange = let
@@ -75,7 +77,7 @@ in {
if cfg.package == null
then defaultHyprlandPackage
else cfg.package;
in "${hyprlandPackage}/bin/hyprctl reload";
in "HYPRLAND_INSTANCE_SIGNATURE=$(ls -w 1 /tmp/hypr | tail -1) ${hyprlandPackage}/bin/hyprctl reload config-only";
};
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {

View File

@@ -233,6 +233,14 @@ void CCompositor::cleanup() {
wl_display_terminate(m_sWLDisplay);
m_sWLDisplay = nullptr;
// kill the PID with a sigkill after 2 seconds
const auto PID = getpid();
std::string call = "sleep 2 && kill -9 " + std::to_string(PID);
execl("/bin/sh", "/bin/sh", "-c", call.c_str(), ">", "/dev/null", nullptr); // this is to prevent that random "freezing"
// the PID should not be reused.
}
void CCompositor::startCompositor() {
@@ -471,13 +479,13 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
if (PMONITOR->specialWorkspaceOpen) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2)
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus)
return (*w).get();
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && w->m_iX11Type != 2)
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && !w->m_bX11ShouldntFocus)
return w.get();
}
}
@@ -485,7 +493,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2) {
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus) {
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
return w->get();
@@ -503,7 +511,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// for windows, we need to check their extensions too, first.
for (auto& w : m_vWindows) {
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2) {
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && !w->m_bX11ShouldntFocus) {
wlr_surface* resultSurf = nullptr;
Vector2D origin = w->m_vRealPosition.vec();
SExtensionFindingData data = {origin, pos, &resultSurf};
@@ -515,7 +523,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
}
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2)
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && !w->m_bX11ShouldntFocus)
return w.get();
}
@@ -710,7 +718,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
.old_surface = m_pLastFocus,
.new_surface = pSurface,
};
wlr_signal_emit_safe(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
if (pWindowOwner)
Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, pWindowOwner->m_szTitle.c_str());
@@ -848,31 +856,6 @@ CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
return nullptr;
}
void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
// not needed anymore
return;
const auto ISVISIBLE = isWorkspaceVisible(id);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
if (!PWORKSPACE)
return;
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == id) {
// moveXWaylandWindow only moves XWayland windows
// so there is no need to check here
// if the window is XWayland or not.
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w->m_bIsFullscreen))
g_pXWaylandManager->moveXWaylandWindow(w.get(), w->m_vRealPosition.vec());
else
g_pXWaylandManager->moveXWaylandWindow(w.get(), Vector2D(42069,42069));
}
}
}
bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
return !m_sSeat.exclusiveClient || (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource));
}
@@ -1411,14 +1394,19 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
if (!windowValidMapped(pWindow))
return;
focusWindow(pWindow);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
// make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
w->m_bCreatedOverFullscreen = false;
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
}
void CCompositor::moveUnmanagedX11ToWindows(CWindow* pWindow) {
@@ -1573,4 +1561,56 @@ void CCompositor::closeWindow(CWindow* pWindow) {
focusWindow(windowFromCursor());
}
}
}
SLayerSurface* CCompositor::getLayerSurfaceFromSurface(wlr_surface* pSurface) {
for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLists) {
for (auto& ls : lsl) {
if (ls->layerSurface && ls->layerSurface->surface == pSurface)
return ls.get();
}
}
}
return nullptr;
}
// returns a delta
Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, const Vector2D& relativeTo) {
if (!args.contains(' '))
return relativeTo;
std::string x = args.substr(0, args.find_first_of(' '));
std::string y = args.substr(args.find_first_of(' ') + 1);
if (x == "exact") {
std::string newX = y.substr(0, y.find_first_of(' '));
std::string newY = y.substr(y.find_first_of(' ') + 1);
if (!isNumber(newX) || !isNumber(newY)) {
Debug::log(ERR, "parseWindowVectorArgsRelative: exact args not numbers");
return relativeTo;
}
const int X = std::stoi(newX);
const int Y = std::stoi(newY);
if (X < 0 || Y < 0) {
Debug::log(ERR, "parseWindowVectorArgsRelative: exact args cannot be < 0");
return relativeTo;
}
return Vector2D(X, Y);
}
if (!isNumber(x) || !isNumber(y)) {
Debug::log(ERR, "parseWindowVectorArgsRelative: args not numbers");
return relativeTo;
}
const int X = std::stoi(x);
const int Y = std::stoi(y);
return Vector2D(X + relativeTo.x, Y + relativeTo.y);
}

View File

@@ -97,6 +97,7 @@ public:
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
// ------------------------------------------------- //
@@ -127,7 +128,6 @@ public:
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
void fixXWaylandWindowsOnWorkspace(const int&);
CWindow* getFullscreenWindowOnWorkspace(const int&);
bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*);
@@ -156,7 +156,10 @@ public:
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&);
std::string explicitConfigPath;

View File

@@ -173,7 +173,8 @@ void CWindow::updateToplevel() {
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, m_bIsFullscreen);
if (m_iLastToplevelMonitorID != m_iMonitorID) {
wlr_foreign_toplevel_handle_v1_output_leave(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iLastToplevelMonitorID)->output);
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iLastToplevelMonitorID); PMONITOR && PMONITOR->m_bEnabled)
wlr_foreign_toplevel_handle_v1_output_leave(m_phForeignToplevel, PMONITOR->output);
wlr_foreign_toplevel_handle_v1_output_enter(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iMonitorID)->output);
m_iLastToplevelMonitorID = m_iMonitorID;
@@ -191,7 +192,7 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
}
void CWindow::updateSurfaceOutputs() {
if (m_iLastSurfaceMonitorID == m_iMonitorID)
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden || !m_bMappedX11)
return;
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
@@ -200,7 +201,7 @@ void CWindow::updateSurfaceOutputs() {
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
if (PLASTMONITOR)
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendLeaveIter, PLASTMONITOR->output);
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendEnterIter, PNEWMONITOR->output);

View File

@@ -13,6 +13,7 @@ struct SWindowSpecialRenderData {
// set by the layout
bool rounding = true;
bool border = true;
};
struct SWindowAdditionalConfigData {
@@ -92,6 +93,7 @@ public:
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false;
bool m_bX11ShouldntFocus = false;
//
// For nofocus

View File

@@ -55,6 +55,8 @@ void CConfigManager::setDefaultVars() {
configValues["misc:damage_entire_on_snapshot"].intValue = 0;
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
configValues["misc:always_follow_on_dnd"].intValue = 1;
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
configValues["misc:animate_manual_resizes"].intValue = 0;
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
@@ -90,6 +92,7 @@ void CConfigManager::setDefaultVars() {
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
configValues["dwindle:no_gaps_when_only"].intValue = 0;
configValues["dwindle:use_active_for_splits"].intValue = 1;
configValues["master:special_scale_factor"].floatValue = 0.8f;
configValues["master:new_is_master"].intValue = 1;
@@ -117,6 +120,7 @@ void CConfigManager::setDefaultVars() {
configValues["animations:workspaces"].intValue = 1;
configValues["input:sensitivity"].floatValue = 0.f;
configValues["input:kb_file"].strValue = STRVAL_EMPTY;
configValues["input:kb_layout"].strValue = "us";
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
@@ -153,6 +157,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
auto& cfgValues = deviceConfigs[dev];
cfgValues["sensitivity"].floatValue = 0.f;
cfgValues["kb_file"].strValue = STRVAL_EMPTY;
cfgValues["kb_layout"].strValue = "us";
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
cfgValues["kb_options"].strValue = STRVAL_EMPTY;
@@ -512,13 +517,24 @@ void CConfigManager::handleBezier(const std::string& command, const std::string&
std::string bezierName = curitem;
nextItem();
if (curitem == "")
parseError = "too few arguments";
float p1x = std::stof(curitem);
nextItem();
if (curitem == "")
parseError = "too few arguments";
float p1y = std::stof(curitem);
nextItem();
if (curitem == "")
parseError = "too few arguments";
float p2x = std::stof(curitem);
nextItem();
if (curitem == "")
parseError = "too few arguments";
float p2y = std::stof(curitem);
nextItem();
if (curitem != "")
parseError = "too many arguments";
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
}
@@ -761,28 +777,13 @@ void CConfigManager::handleSubmap(const std::string& command, const std::string&
void CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
static const char* const ENVHOME = getenv("HOME");
auto value = rawpath;
if (value.length() < 2) {
if (rawpath.length() < 2) {
Debug::log(ERR, "source= path garbage");
parseError = "source path " + value + " bogus!";
parseError = "source path " + rawpath + " bogus!";
return;
}
if (value[0] == '.') {
auto currentDir = configCurrentPath.substr(0, configCurrentPath.find_last_of('/'));
if (value[1] == '.') {
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
value.replace(0, 2, parentDir);
} else {
value.replace(0, 1, currentDir);
}
}
if (value[0] == '~') {
value.replace(0, 1, std::string(ENVHOME));
}
auto value = absolutePath(rawpath, configCurrentPath);
if (!std::filesystem::exists(value)) {
Debug::log(ERR, "source= file doesnt exist");
@@ -911,6 +912,7 @@ void CConfigManager::parseLine(std::string& line) {
if (line.contains(" {")) {
auto cat = line.substr(0, line.find(" {"));
transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
std::replace(cat.begin(), cat.end(), ' ', '-');
if (currentCategory.length() != 0) {
currentCategory.push_back(':');
currentCategory.append(cat);
@@ -1060,14 +1062,15 @@ void CConfigManager::loadConfigLoadVars() {
if (parseError != "")
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(255, 50, 50, 255));
else if (configValues["autogenerated"].intValue == 1)
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Enter -> kitty\nSUPER+T -> Alacritty\nSUPER+M -> exit Hyprland", CColor(255, 255, 70, 255));
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", CColor(255, 255, 70, 255));
else
g_pHyprError->destroy();
// Set the modes for all monitors as we configured them
// not on first launch because monitors might not exist yet
// and they'll be taken care of in the newMonitor event
if (!isFirstLaunch) {
// ignore if nomonitorreload is set
if (!isFirstLaunch && !m_bNoMonitorReload) {
m_bWantsMonitorReload = true;
// check
@@ -1087,6 +1090,9 @@ void CConfigManager::loadConfigLoadVars() {
// Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_vMonitors)
m->forceFullFrames = 2;
// Reset no monitor reload
m_bNoMonitorReload = false;
}
void CConfigManager::tick() {
@@ -1135,9 +1141,13 @@ SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx);
const auto it = deviceConfigs.find(dev);
auto devcopy = dev;
std::replace(devcopy.begin(), devcopy.end(), ' ', '-');
const auto it = deviceConfigs.find(devcopy);
if (it == deviceConfigs.end()) {
Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", devcopy.c_str());
return SConfigValue();
}
@@ -1150,7 +1160,7 @@ SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, co
if (foundIt == std::string::npos)
continue;
if (foundIt == cv.first.length() - val.length()) {
if (cv.first == "input:" + val || cv.first == "input:touchpad:" + cv.first) {
copy = cv.second;
}
}
@@ -1232,7 +1242,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(std::string name) {
Debug::log(WARN, "No rules configured. Using the default hardcoded one.");
return SMonitorRule{.name = "", .resolution = Vector2D(1280, 720), .offset = Vector2D(0, 0), .scale = 1};
return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-1, -1), .scale = 1}; // 0, 0 is preferred and -1, -1 is auto
}
std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
@@ -1319,8 +1329,20 @@ SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
return &configValues[val];
}
SConfigValue* CConfigManager::getConfigValuePtrSafe(std::string val) {
const auto IT = configValues.find(val);
if (IT == configValues.end())
return nullptr;
return &(IT->second);
}
bool CConfigManager::deviceConfigExists(const std::string& dev) {
const auto it = deviceConfigs.find(dev);
auto copy = dev;
std::replace(copy.begin(), copy.end(), ' ', '-');
const auto it = deviceConfigs.find(copy);
return it != deviceConfigs.end();
}
@@ -1349,3 +1371,8 @@ void CConfigManager::ensureDPMS() {
SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) {
return &animationConfig[name];
}
void CConfigManager::addParseError(const std::string& err) {
if (parseError == "")
parseError = err;
}

View File

@@ -83,6 +83,7 @@ public:
bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(std::string);
SConfigValue* getConfigValuePtrSafe(std::string);
SMonitorRule getMonitorRuleFor(std::string);
@@ -96,12 +97,17 @@ public:
void performMonitorReload();
bool m_bWantsMonitorReload = false;
bool m_bForceReload = false;
bool m_bNoMonitorReload = false;
void ensureDPMS();
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
void addParseError(const std::string&);
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
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
@@ -111,8 +117,6 @@ private:
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::string configCurrentPath;
std::string currentCategory = ""; // For storing the category of the current item
std::string parseError = ""; // For storing a parse error to display later
@@ -155,4 +159,4 @@ private:
void handleBlurLS(const std::string&, const std::string&);
};
inline std::unique_ptr<CConfigManager> g_pConfigManager;
inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -20,6 +20,7 @@ autogenerated=1 # remove this line to get rid of the warning on top.
monitor=,preferred,auto,1
input {
kb_file=
kb_layout=
kb_variant=
kb_model=
@@ -122,4 +123,4 @@ bind=ALT,0,movetoworkspace,10
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1
)#";
)#";

View File

@@ -35,7 +35,7 @@ R"#({
"reserved": [%i, %i, %i, %i],
"scale": %.2f,
"transform": %i,
"active": %s
"focused": %s
},)#",
m->ID,
escapeJSONStrings(m->szName).c_str(),
@@ -56,7 +56,7 @@ 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\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tactive: %s\n\n",
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"));
}
}
@@ -169,23 +169,23 @@ R"#({
"id": %i,
"name": "%s"
},
"floating": %i,
"floating": %s,
"monitor": %i,
"class": "%s",
"title": "%s",
"pid": %i,
"xwayland": %i
"xwayland": %s
})#",
PWINDOW,
(int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
(int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(),
(int)PWINDOW->m_bIsFloating,
((int)PWINDOW->m_bIsFloating == 1 ? "true" : "false"),
PWINDOW->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(),
PWINDOW->getPID(),
(int)PWINDOW->m_bIsX11
((int)PWINDOW->m_bIsX11 == 1 ? "true" : "false")
);
} else {
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
@@ -300,7 +300,7 @@ R"#( {
result += "\"keyboards\": [\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat(
R"#( {
"address": "0x%x",
@@ -310,7 +310,8 @@ R"#( {
"layout": "%s",
"variant": "%s",
"options": "%s",
"active_keymap": "%s"
"active_keymap": "%s",
"main": %s
},)#",
&k,
escapeJSONStrings(k.keyboard->name).c_str(),
@@ -319,7 +320,8 @@ R"#( {
escapeJSONStrings(k.currentRules.layout).c_str(),
escapeJSONStrings(k.currentRules.variant).c_str(),
escapeJSONStrings(k.currentRules.options).c_str(),
escapeJSONStrings(KM).c_str()
escapeJSONStrings(KM).c_str(),
(k.active ? "true" : "false")
);
}
@@ -385,8 +387,8 @@ R"#( {
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM);
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
}
result += "\n\nTablets:\n";
@@ -407,23 +409,56 @@ R"#( {
return result;
}
std::string versionRequest() {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
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";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
result += "legacyrenderer\n";
#endif
#ifndef NDEBUG
result += "debug\n";
result += "debug\n";
#endif
#ifdef HYPRLAND_DEBUG
result += "debug\n";
result += "debug\n";
#endif
#ifdef NO_XWAYLAND
result += "no xwayland\n";
result += "no xwayland\n";
#endif
return result;
return result;
} else {
std::string result = getFormat(
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());
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
#endif
#ifndef NDEBUG
result += "\"debug\",";
#endif
#ifdef HYPRLAND_DEBUG
result += "\"debug\",";
#endif
#ifdef NO_XWAYLAND
result += "\"no xwayland\",";
#endif
if (result[result.length() - 1] == ',')
result.pop_back();
result += "]\n}";
return result;
}
return ""; // make the compiler happy
}
std::string dispatchRequest(std::string in) {
@@ -458,8 +493,10 @@ std::string dispatchKeyword(std::string in) {
if (COMMAND == "monitor")
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
if (COMMAND.contains("input"))
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setMouseConfigs(); // update mouse cfgs
}
if (COMMAND.contains("general:layout"))
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
@@ -472,9 +509,16 @@ std::string dispatchKeyword(std::string in) {
return retval;
}
std::string reloadRequest() {
std::string reloadRequest(std::string request) {
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
g_pConfigManager->m_bForceReload = true;
if (REQMODE == "config-only") {
g_pConfigManager->m_bNoMonitorReload = true;
}
return "ok";
}
@@ -522,6 +566,97 @@ std::string dispatchBatch(std::string request) {
return reply;
}
std::string dispatchSetCursor(std::string request) {
std::string curitem = "";
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
curitem = request.substr(0, idx);
request = request.substr(idx + 1);
} else {
curitem = request;
request = "";
}
curitem = removeBeginEndSpacesTabs(curitem);
};
nextItem();
nextItem();
const auto THEME = curitem;
nextItem();
const auto SIZE = curitem;
if (!isNumber(SIZE)) {
return "size not int";
}
const auto SIZEINT = std::stoi(SIZE);
if (SIZEINT < 1) {
return "size must be positive";
}
wlr_xcursor_manager_destroy(g_pCompositor->m_sWLRXCursorMgr);
g_pCompositor->m_sWLRXCursorMgr = wlr_xcursor_manager_create(THEME.c_str(), SIZEINT);
setenv("XCURSOR_SIZE", SIZE.c_str(), true);
setenv("XCURSOR_THEME", THEME.c_str(), true);
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, m->scale);
}
return "ok";
}
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
std::string curitem = "";
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
curitem = request.substr(0, idx);
request = request.substr(idx + 1);
} else {
curitem = request;
request = "";
}
curitem = removeBeginEndSpacesTabs(curitem);
};
nextItem();
nextItem();
const auto PCFGOPT = g_pConfigManager->getConfigValuePtrSafe(curitem);
if (!PCFGOPT)
return "no such option";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
return getFormat("option %s\n\tint: %i\n\tfloat: %f\n\tstr: \"%s\"", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str());
else {
return getFormat(
R"#(
{
"option": "%s",
"int": %i,
"float": %f,
"str": "%s"
}
)#", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str()
);
}
}
std::string getReply(std::string request) {
auto format = HyprCtl::FORMAT_NORMAL;
@@ -556,9 +691,9 @@ std::string getReply(std::string request) {
else if (request == "layers")
return layersRequest(format);
else if (request == "version")
return versionRequest();
else if (request == "reload")
return reloadRequest();
return versionRequest(format);
else if (request.find("reload") == 0)
return reloadRequest(request);
else if (request == "devices")
return devicesRequest(format);
else if (request == "splash")
@@ -567,6 +702,10 @@ std::string getReply(std::string request) {
return dispatchRequest(request);
else if (request.find("keyword") == 0)
return dispatchKeyword(request);
else if (request.find("setcursor") == 0)
return dispatchSetCursor(request);
else if (request.find("getoption") == 0)
return dispatchGetOption(request, format);
else if (request.find("[[BATCH]]") == 0)
return dispatchBatch(request);

View File

@@ -53,35 +53,49 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
return;
}
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
return;
if (g_pCompositor->m_bUnsafeState) {
Debug::log(WARN, "Recovering from an unsafe state. May you be lucky.");
}
// add it to real
const auto PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
std::shared_ptr<CMonitor>* PNEWMONITORWRAP = nullptr;
for (auto& rm : g_pCompositor->m_vRealMonitors) {
if (rm->szName == OUTPUT->name) {
PNEWMONITORWRAP = &rm;
Debug::log(LOG, "Recovering a removed monitor.");
break;
}
}
if (!PNEWMONITORWRAP) {
Debug::log(LOG, "Adding completely new monitor.");
PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID();
}
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
PNEWMONITOR->ID = g_pCompositor->getNextAvailableMonitorID();
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
PNEWMONITOR->onConnect(false);
if (!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate)
if ((!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
pMostHzMonitor = PNEWMONITOR;
// ready to process cuz we have a monitor
g_pCompositor->m_bReadyToProcess = true;
if (PNEWMONITOR->m_bEnabled) {
g_pCompositor->m_bReadyToProcess = true;
g_pCompositor->m_bUnsafeState = false;
}
}
void Events::listener_monitorFrame(void* owner, void* data) {
CMonitor* const PMONITOR = (CMonitor*)owner;
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive) {
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
Debug::log(WARN, "Attempted to render frame on inactive session!");
return; // cannot draw on session inactive (different tty)
}
@@ -295,20 +309,23 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
pMonitor->onDisconnect();
// cleanup
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; }));
// cleanup if not unsafe
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr;
if (!g_pCompositor->m_bUnsafeState) {
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
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;
pMostHzMonitor = pMonitorMostHz;
}
}
}

View File

@@ -151,7 +151,10 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
g_pHyprRenderer->damageBox(lx, ly, PPOPUP->popup->current.geometry.width, PPOPUP->popup->current.geometry.width);
wlr_box extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
g_pHyprRenderer->damageBox(lx, ly, extents.width + 2, extents.height + 2);
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
}
@@ -167,7 +170,10 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
g_pHyprRenderer->damageBox(lx, ly, PPOPUP->popup->current.geometry.width, PPOPUP->popup->current.geometry.width);
wlr_box extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
g_pHyprRenderer->damageBox(lx, ly, extents.width + 2, extents.height + 2);
PPOPUP->pSurfaceTree = nullptr;
}

View File

@@ -85,6 +85,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bRequestsFloat = true;
}
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2);
if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true;
@@ -123,6 +125,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID));
Debug::log(ERR, "Rule monitor, applying to window %x -> mon: %i, workspace: %i", PWINDOW, PWINDOW->m_iMonitorID, PWINDOW->m_iWorkspaceID);
} catch (std::exception& e) {
@@ -381,11 +384,17 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->m_bIsMapped = false;
// refocus on a new window
g_pInputManager->refocus();
auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f);
if (!g_pCompositor->m_pLastWindow) {
g_pCompositor->focusWindow(g_pCompositor->getFirstWindowOnWorkspace(PWORKSPACE->m_iID));
}
if (!PWINDOWCANDIDATE)
PWINDOWCANDIDATE = g_pCompositor->getFirstWindowOnWorkspace(PWINDOW->m_iWorkspaceID);
if (!PWINDOWCANDIDATE || PWINDOW == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->m_bHidden || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2)
PWINDOWCANDIDATE = nullptr;
Debug::log(LOG, "On closed window, new focused candidate is %x", PWINDOWCANDIDATE);
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW);
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
@@ -476,15 +485,18 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
void Events::listener_fullscreenWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!PWINDOW->m_bIsMapped || PWINDOW->m_bHidden)
return;
if (!PWINDOW->m_bIsX11) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
g_pCompositor->setWindowFullscreen(PWINDOW, REQUESTED->fullscreen, FULLSCREEN_FULL);
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_FULL);
}
PWINDOW->updateToplevel();
@@ -515,7 +527,7 @@ void Events::listener_configureX11(void* owner, void* data) {
const auto E = (wlr_xwayland_surface_configure_event*)data;
g_pHyprRenderer->damageWindow(PWINDOW);
if (!PWINDOW->m_bIsFloating) {
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.vec());
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);

View File

@@ -40,6 +40,28 @@ static const float transforms[][9] = {{
},
};
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
auto value = rawpath;
if (value[0] == '.') {
auto currentDir = currentPath.substr(0, currentPath.find_last_of('/'));
if (value[1] == '.') {
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
value.replace(0, 2, parentDir);
} else {
value.replace(0, 1, currentDir);
}
}
if (value[0] == '~') {
static const char* const ENVHOME = getenv("HOME");
value.replace(0, 1, std::string(ENVHOME));
}
return value;
}
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
ASSERT(pSignal);
ASSERT(pListener);
@@ -53,35 +75,6 @@ void handleNoop(struct wl_listener *listener, void *data) {
// Do nothing
}
void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
struct wl_listener cursor;
struct wl_listener end;
/* Add two special markers: one cursor and one end marker. This way, we know
* that we've already called listeners on the left of the cursor and that we
* don't want to call listeners on the right of the end marker. The 'it'
* function can remove any element it wants from the list without troubles.
* wl_list_for_each_safe tries to be safe but it fails: it works fine
* if the current item is removed, but not if the next one is. */
wl_list_insert(&signal->listener_list, &cursor.link);
cursor.notify = handleNoop;
wl_list_insert(signal->listener_list.prev, &end.link);
end.notify = handleNoop;
while (cursor.link.next != &end.link) {
struct wl_list *pos = cursor.link.next;
struct wl_listener *l = wl_container_of(pos, l, link);
wl_list_remove(&cursor.link);
wl_list_insert(pos, &cursor.link);
l->notify(l, data);
}
wl_list_remove(&cursor.link);
wl_list_remove(&end.link);
}
std::string getFormat(const char *fmt, ...) {
char* outputStr = nullptr;

View File

@@ -2,8 +2,8 @@
#include "../includes.hpp"
std::string absolutePath(const std::string&, const std::string&);
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
std::string escapeJSONStrings(const std::string& str);
void scaleBox(wlr_box*, float);
@@ -17,4 +17,4 @@ std::string execAndGet(const char*);
float getPlusMinusKeywordResult(std::string in, float relative);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);

View File

@@ -6,6 +6,8 @@ void CMonitor::onConnect(bool noRule) {
if (m_bEnabled)
return;
szName = output->name;
// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name);
@@ -14,13 +16,51 @@ void CMonitor::onConnect(bool noRule) {
// if it's disabled, disable and ignore
if (monitorRule.disabled) {
wlr_output_enable_adaptive_sync(output, 1);
wlr_output_set_scale(output, 1);
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
auto PREFSTATE = wlr_output_preferred_mode(output);
if (!PREFSTATE) {
wlr_output_mode* mode;
wl_list_for_each(mode, &output->modes, link) {
wlr_output_set_mode(output, PREFSTATE);
if (!wlr_output_test(output))
continue;
PREFSTATE = mode;
break;
}
}
if (PREFSTATE)
wlr_output_set_mode(output, PREFSTATE);
else
Debug::log(WARN, "No mode found for disabled output %s", output->name);
wlr_output_enable(output, 0);
wlr_output_commit(output);
if (!wlr_output_commit(output)) {
Debug::log(ERR, "Couldn't commit disabled state on output %s", output->name);
}
Events::listener_change(nullptr, nullptr);
m_bEnabled = false;
hyprListener_monitorFrame.removeCallback();
return;
}
if (!m_bRenderingInitPassed) {
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
m_bRenderingInitPassed = true;
}
if (!m_pThisWrap) {
// find the wrap
@@ -38,8 +78,6 @@ void CMonitor::onConnect(bool noRule) {
m_bEnabled = true;
szName = output->name;
wlr_output_set_scale(output, monitorRule.scale);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
@@ -61,7 +99,7 @@ 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)monitorRule.offset.x, (int)monitorRule.offset.y, (int)monitorRule.resolution.x, (int)monitorRule.resolution.y, output);
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);
@@ -120,6 +158,11 @@ void CMonitor::onConnect(bool noRule) {
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = this;
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
g_pHyprRenderer->arrangeLayersForMonitor(ID);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
}
@@ -137,16 +180,22 @@ void CMonitor::onDisconnect() {
}
}
if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanup();
return;
}
m_bEnabled = false;
m_bRenderingInitPassed = false;
hyprListener_monitorFrame.removeCallback();
if (!BACKUPMON) {
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
hyprListener_monitorMode.removeCallback();
hyprListener_monitorDestroy.removeCallback();
g_pCompositor->m_bUnsafeState = true;
return;
}
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
// snap cursor
@@ -175,10 +224,6 @@ void CMonitor::onDisconnect() {
wlr_output_commit(output);
for (auto& lsl : m_aLayerSurfaceLists) {
lsl.clear();
}
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; }));
Debug::log(LOG, "Removed monitor %s!", szName.c_str());

View File

@@ -58,6 +58,7 @@ public:
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
bool m_bEnabled = false;
bool m_bRenderingInitPassed = false;
// For the list lookup

View File

@@ -94,12 +94,16 @@ struct SKeyboard {
DYNLISTENER(keyboardMod);
DYNLISTENER(keyboardKey);
DYNLISTENER(keyboardKeymap);
DYNLISTENER(keyboardDestroy);
bool isVirtual = false;
bool active = false;
xkb_layout_index_t activeLayout = 0;
std::string name = "";
std::string xkbFilePath = "";
SStringRuleNames currentRules;
int repeatRate = 0;
@@ -313,4 +317,4 @@ struct SIMEPopup {
bool operator==(const SIMEPopup& other) {
return pSurface == other.pSurface;
}
};
};

View File

@@ -14,6 +14,8 @@ void CHyprError::createQueued() {
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 CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
const auto CAIRO = cairo_create(CAIROSURFACE);
@@ -27,7 +29,7 @@ void CHyprError::createQueued() {
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
cairo_set_source_rgba(CAIRO, m_cQueued.r / 255.f, m_cQueued.g / 255.f, m_cQueued.b / 255.f, m_cQueued.a / 255.f);
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, 10 * LINECOUNT);
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, (FONTSIZE + 2 * (FONTSIZE / 10.f)) * LINECOUNT);
// outline
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
@@ -40,10 +42,10 @@ void CHyprError::createQueued() {
const CColor textColor = m_cQueued.r * m_cQueued.g * m_cQueued.b < 0.5f ? CColor(255, 255, 255, 255) : CColor(0, 0, 0, 255);
cairo_select_font_face(CAIRO, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(CAIRO, 8);
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);
float yoffset = 8;
float yoffset = FONTSIZE;
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)
@@ -52,7 +54,7 @@ void CHyprError::createQueued() {
m_szQueued = "";
cairo_move_to(CAIRO, 0, yoffset);
cairo_show_text(CAIRO, current.c_str());
yoffset += 9;
yoffset += FONTSIZE + (FONTSIZE / 10.f);
}

View File

@@ -2,23 +2,6 @@
#include "../Compositor.hpp"
void SDwindleNodeData::recalcSizePosRecursive(bool force) {
// check the group, if we are in one and not active, ignore.
if (pGroupParent && pGroupParent->groupMembers[pGroupParent->groupMemberActive] != this) {
if (pWindow)
pWindow->m_bHidden = true;
return;
} else {
if (pWindow)
pWindow->m_bHidden = false;
}
if (pGroupParent) {
// means we are in a group and focused. let's just act like the full window in this
size = pGroupParent->size;
position = pGroupParent->position;
}
if (children[0]) {
const auto REVERSESPLITRATIO = 2.f - splitRatio;
@@ -60,6 +43,51 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pD
}
}
bool SDwindleNodeData::isGroupMember() {
return pNextGroupMember && pNextGroupMember != this;
}
SDwindleNodeData* SDwindleNodeData::getGroupHead() {
SDwindleNodeData* current = this->pNextGroupMember;
while (current != this) {
if (current->groupHead) {
return current;
}
current = current->pNextGroupMember;
}
this->groupHead = true;
return this;
}
SDwindleNodeData* SDwindleNodeData::getGroupVisible() {
SDwindleNodeData* current = this->pNextGroupMember;
while (current != this) {
if (!current->pWindow->m_bHidden) {
return current;
}
current = current->pNextGroupMember;
}
return this;
}
void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
SDwindleNodeData* current = this->pNextGroupMember;
while (current != this) {
current->pWindow->m_bHidden = current != pMember;
current = current->pNextGroupMember;
}
this->pWindow->m_bHidden = pMember != this;
}
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
int no = 0;
for (auto& n : m_lDwindleNodesData) {
@@ -129,7 +157,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
const auto PWINDOW = pNode->pWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
return;
}
@@ -149,11 +177,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
@@ -208,6 +238,14 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
PWINDOW->m_vRealSize.warp();
}
if (pNode->isGroupMember() && pNode->groupHead) {
// update visible node
const auto PVISNODE = pNode->getGroupVisible();
PVISNODE->pWindow->m_vRealSize = PWINDOW->m_vRealSize.goalv();
PVISNODE->pWindow->m_vRealPosition = PWINDOW->m_vRealPosition.goalv();
}
PWINDOW->updateWindowDecos();
}
@@ -220,6 +258,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
static auto *const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
// Populate the node with our window's data
PNODE->workspaceID = pWindow->m_iWorkspaceID;
PNODE->pWindow = pWindow;
@@ -229,13 +269,22 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
SDwindleNodeData* OPENINGON;
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && !*PUSEACTIVE) {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
// happens on reserved area
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
} else if (*PUSEACTIVE) {
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
} else {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
}
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
} else
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
@@ -265,6 +314,28 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
return;
}
// if it's a group, add the window
if (OPENINGON->isGroupMember()) {
const auto PHEAD = OPENINGON->getGroupHead();
const auto PTAIL = PHEAD->pPreviousGroupMember;
PHEAD->pPreviousGroupMember = PNODE;
PTAIL->pNextGroupMember = PNODE;
PNODE->pNextGroupMember = PHEAD;
PNODE->pPreviousGroupMember = PTAIL;
PHEAD->setGroupFocusedNode(PNODE);
PNODE->position = PHEAD->position;
PNODE->size = PHEAD->size;
applyNodeDataToWindow(PNODE);
return;
}
// If it's not, get the node under our cursor
@@ -338,35 +409,66 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
OPENINGON->pParent = NEWPARENT;
PNODE->pParent = NEWPARENT;
if (OPENINGON->pGroupParent) {
// means we opened on a group
NEWPARENT->recalcSizePosRecursive();
// add the group deco
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
PNODE->pGroupParent = OPENINGON->pGroupParent;
PNODE->pGroupParent->groupMembers.push_back(PNODE);
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
PNODE->pGroupParent->recalcSizePosRecursive();
} else {
NEWPARENT->recalcSizePosRecursive();
applyNodeDataToWindow(PNODE);
applyNodeDataToWindow(OPENINGON);
}
applyNodeDataToWindow(PNODE);
applyNodeDataToWindow(OPENINGON);
}
void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
if (!PNODE) {
Debug::log(ERR, "onWindowRemovedTiling node null?");
return;
}
// check if it was grouped
if (PNODE->isGroupMember()) {
// get shit
const auto PPREV = PNODE->pPreviousGroupMember;
const auto PNEXT = PNODE->pNextGroupMember;
PPREV->pNextGroupMember = PNEXT;
PNEXT->pPreviousGroupMember = PPREV;
if (PNODE->groupHead) {
PNEXT->groupHead = true;
PNEXT->pParent = PNODE->pParent;
if (PNODE->pParent) {
if (PNODE->pParent->children[0] == PNODE) {
PNODE->pParent->children[0] = PNEXT;
} else {
PNODE->pParent->children[1] = PNEXT;
}
}
PNEXT->position = PNODE->position;
PNEXT->size = PNODE->size;
applyNodeDataToWindow(PNEXT);
} else {
const auto PHEAD = PNODE->getGroupHead();
PNEXT->position = PHEAD->position;
PNEXT->size = PHEAD->size;
applyNodeDataToWindow(PNEXT);
}
PNEXT->setGroupFocusedNode(PNEXT);
PNEXT->pWindow->m_bHidden = false;
m_lDwindleNodesData.remove(*PNODE);
return;
}
const auto PPARENT = PNODE->pParent;
if (!PPARENT) {
Debug::log(LOG, "Removing last node (dwindle)");
m_lDwindleNodesData.remove(*PNODE);
return;
}
@@ -385,29 +487,6 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
}
}
// check if it was grouped
if (PNODE->pGroupParent) {
PNODE->pGroupParent->groupMembers.erase(PNODE->pGroupParent->groupMembers.begin() + PNODE->pGroupParent->groupMemberActive);
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
PNODE->pGroupParent->groupMemberActive = 0;
if (PNODE->pGroupParent->groupMembers.size() <= 1) {
PNODE->pGroupParent->isGroup = false;
PSIBLING->pGroupParent = nullptr;
PNODE->pGroupParent->groupMembers.clear();
PSIBLING->recalcSizePosRecursive();
} else {
PNODE->pGroupParent->recalcSizePosRecursive();
}
// if the parent is to be removed, remove the group
if (PPARENT == PNODE->pGroupParent) {
toggleWindowGroup(PPARENT->groupMembers[PPARENT->groupMemberActive]->pWindow);
}
}
PPARENT->valid = false;
PNODE->valid = false;
@@ -422,6 +501,10 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
if (!PMONITOR)
return; // ???
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
@@ -447,17 +530,21 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
// massive hack from the fullscreen func
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
if (!PFULLWINDOW) { // ????
PWORKSPACE->m_bHasFullscreenWindow = false;
} else {
SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
applyNodeDataToWindow(&fakeNode);
return;
return;
}
}
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
@@ -488,6 +575,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
return;
}
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
// get some data about our window
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
@@ -519,11 +608,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive(true);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive(true);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
return;
@@ -538,11 +627,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive(true);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->recalcSizePosRecursive(true);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
return;
@@ -557,14 +646,17 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
SIDECONTAINER->recalcSizePosRecursive(true);
TOPCONTAINER->recalcSizePosRecursive(true);
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
}
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return;
if (on == pWindow->m_bIsFullscreen)
return; // ignore
@@ -631,10 +723,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
g_pCompositor->moveWindowToTop(pWindow);
// we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
recalculateMonitor(PMONITOR->ID);
}
@@ -647,6 +735,16 @@ void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
PNODE->recalcSizePosRecursive();
}
void addToDequeRecursive(std::deque<SDwindleNodeData*>* pDeque, std::deque<SDwindleNodeData*>* pParents, SDwindleNodeData* node) {
if (node->isNode) {
pParents->push_back(node);
addToDequeRecursive(pDeque, pParents, node->children[0]);
addToDequeRecursive(pDeque, pParents, node->children[1]);
} else {
pDeque->emplace_back(node);
}
}
void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
@@ -657,61 +755,115 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
if (!PNODE)
return; // reject
const auto PGROUPPARENT = PNODE->pGroupParent;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
if (PGROUPPARENT) {
// if there is a parent, release it
const auto INACTIVEBORDERCOL = CColor(g_pConfigManager->getInt("general:col.inactive_border"));
for (auto& node : PGROUPPARENT->groupMembers) {
node->pGroupParent = nullptr;
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
if (PWORKSPACE->m_bHasFullscreenWindow)
fullscreenRequestForWindow(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FULLSCREEN_FULL, false);
for (auto& wd : node->pWindow->m_dWindowDecorations) {
wd->updateWindow(node->pWindow);
}
}
if (PNODE->isGroupMember()) {
// dissolve group
const auto PHEAD = PNODE->getGroupHead();
SDwindleNodeData* current = PNODE->pNextGroupMember;
PNODE->pWindow->m_bIsFloating = PHEAD->pWindow->m_bIsFloating;
std::deque<CWindow*> toAddWindows;
PGROUPPARENT->groupMembers.clear();
const auto PWINDOWNODE = PNODE->pWindow;
toAddWindows.push_back(PWINDOWNODE);
PGROUPPARENT->isGroup = false;
while (current != PNODE) {
const auto PWINDOW = current->pWindow;
current = current->pNextGroupMember;
PGROUPPARENT->recalcSizePosRecursive();
toAddWindows.push_back(PWINDOW);
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
g_pCompositor->m_pLastWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("general:col.active_border"));
} else {
// if there is no parent, let's make one
const auto PPARENT = PNODE->pParent;
if (!PPARENT)
return; // reject making group on single window
PPARENT->isGroup = true;
// recursively get all members
std::deque<SDwindleNodeData*> allChildren;
PPARENT->getAllChildrenRecursive(&allChildren);
PPARENT->groupMembers = allChildren;
const auto GROUPINACTIVEBORDERCOL = CColor(g_pConfigManager->getInt("dwinle:col.group_border"));
for (auto& c : PPARENT->groupMembers) {
c->pGroupParent = PPARENT;
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
c->pWindow->m_dWindowDecorations.push_back(std::make_unique<CHyprGroupBarDecoration>(c->pWindow));
if (c->pWindow == g_pCompositor->m_pLastWindow)
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
PWINDOW->m_bHidden = false;
}
PPARENT->groupMemberActive = 0;
PHEAD->pPreviousGroupMember = nullptr;
PHEAD->pNextGroupMember = nullptr;
onWindowRemoved(PHEAD->pWindow);
PPARENT->recalcSizePosRecursive();
for (auto& pw : toAddWindows) {
const auto PNODE = getNodeFromWindow(pw);
if (PNODE)
m_lDwindleNodesData.remove(*PNODE);
pw->m_vPosition = Vector2D(-1000000, -1000000);
}
for (auto& pw : toAddWindows) {
onWindowCreated(pw);
}
recalculateMonitor(PWORKSPACE->m_iMonitorID);
} else {
// create group
if (!PNODE->pParent)
return;
PNODE->groupHead = true;
std::deque<SDwindleNodeData*> newGroupMembers;
std::deque<SDwindleNodeData*> nodesToRemove;
newGroupMembers.emplace_back(PNODE);
addToDequeRecursive(&newGroupMembers, &nodesToRemove, PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[1] : PNODE->pParent->children[0]);
for (auto& n : newGroupMembers) {
if (n->isGroupMember())
return; // reject nested groups
}
for (auto& nd : nodesToRemove) {
m_lDwindleNodesData.remove(*nd);
}
PNODE->position = PNODE->pParent->position;
PNODE->size = PNODE->pParent->size;
applyNodeDataToWindow(PNODE);
if (PNODE->pParent->pParent) {
if (PNODE->pParent->pParent->children[0] == PNODE->pParent) {
PNODE->pParent->pParent->children[0] = PNODE;
} else {
PNODE->pParent->pParent->children[1] = PNODE;
}
}
const auto PPARENT2 = PNODE->pParent->pParent;
m_lDwindleNodesData.remove(*PNODE->pParent);
PNODE->pParent = PPARENT2;
// now remove everyone but head from tree
// and set order
for (int i = 0; i < (int)newGroupMembers.size(); ++i) {
if (i != 0) {
newGroupMembers[i]->groupHead = false;
newGroupMembers[i]->pParent = PNODE->pParent;
}
const auto PREVMEMBER = i == 0 ? newGroupMembers[newGroupMembers.size() - 1] : newGroupMembers[i - 1];
const auto NEXTMEMBER = i == (int)newGroupMembers.size() - 1 ? newGroupMembers[0] : newGroupMembers[i + 1];
newGroupMembers[i]->pPreviousGroupMember = PREVMEMBER;
newGroupMembers[i]->pNextGroupMember = NEXTMEMBER;
}
// focus
PNODE->setGroupFocusedNode(PNODE);
}
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
g_pInputManager->refocus();
}
@@ -728,13 +880,13 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
if (!PNODE)
return result; // reject with empty
const auto PGROUPPARENT = PNODE->pGroupParent;
SDwindleNodeData* current = PNODE->pNextGroupMember;
if (!PGROUPPARENT)
return result; // reject with empty
result.push_back(pWindow);
for (auto& node : PGROUPPARENT->groupMembers) {
result.push_back(node->pWindow);
while (current != PNODE) {
result.push_back(current->pWindow);
current = current->pNextGroupMember;
}
return result;
@@ -746,33 +898,41 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
if (!PNODE || !PNODE->isGroupMember())
return; // reject
if (!PNODE->pGroupParent)
return; // reject
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
SDwindleNodeData* pNewNode;
if (forward)
PNODE->pGroupParent->groupMemberActive++;
pNewNode = PNODE->pNextGroupMember;
else
PNODE->pGroupParent->groupMemberActive--;
pNewNode = PNODE->pPreviousGroupMember;
if (PNODE->pGroupParent->groupMemberActive < 0)
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
PNODE->setGroupFocusedNode(pNewNode);
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
PNODE->pGroupParent->groupMemberActive = 0;
pNewNode->position = PNODE->position;
pNewNode->size = PNODE->size;
PNODE->pGroupParent->recalcSizePosRecursive();
applyNodeDataToWindow(pNewNode);
for (auto& gm : PNODE->pGroupParent->groupMembers) {
for (auto& deco : gm->pWindow->m_dWindowDecorations) {
deco->updateWindow(gm->pWindow);
}
pNewNode->pWindow->m_vRealSize.warp();
pNewNode->pWindow->m_vRealPosition.warp();
g_pCompositor->focusWindow(pNewNode->pWindow);
pNewNode->pWindow->m_bIsFloating = PNODE->pWindow->m_bIsFloating;
if (PNODE->pWindow->m_bIsFullscreen) {
PNODE->pWindow->m_bHidden = false;
g_pCompositor->setWindowFullscreen(PNODE->pWindow, false, PWORKSPACE->m_efFullscreenMode);
PNODE->pWindow->m_bHidden = true;
g_pCompositor->setWindowFullscreen(pNewNode->pWindow, true, PWORKSPACE->m_efFullscreenMode);
pNewNode->pWindow->m_vRealSize.warp();
pNewNode->pWindow->m_vRealPosition.warp();
}
// focus
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
}
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow) {
@@ -784,7 +944,7 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
if (!PNODE)
return hints; // left for the future, maybe floating funkiness
if (PNODE->pGroupParent) {
if (PNODE->isGroupMember()) {
hints.isBorderColor = true;
if (pWindow == g_pCompositor->m_pLastWindow)
@@ -909,4 +1069,4 @@ void CHyprDwindleLayout::onEnable() {
void CHyprDwindleLayout::onDisable() {
m_lDwindleNodesData.clear();
}
}

View File

@@ -18,10 +18,9 @@ struct SDwindleNodeData {
bool splitTop = false; // for preserve_split
bool isGroup = false;
int groupMemberActive = 0;
std::deque<SDwindleNodeData*> groupMembers;
SDwindleNodeData* pGroupParent = nullptr;
bool groupHead = false;
SDwindleNodeData* pNextGroupMember = nullptr;
SDwindleNodeData* pPreviousGroupMember = nullptr;
Vector2D position;
Vector2D size;
@@ -39,6 +38,10 @@ struct SDwindleNodeData {
void recalcSizePosRecursive(bool force = false);
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
bool isGroupMember();
SDwindleNodeData* getGroupHead();
SDwindleNodeData* getGroupVisible();
void setGroupFocusedNode(SDwindleNodeData*);
CHyprDwindleLayout* layout = nullptr;
};

View File

@@ -87,7 +87,6 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
if (pWindow->m_iX11Type != 2) {
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow);
}
@@ -168,6 +167,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
return;
@@ -184,9 +185,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)MAXSIZE.x), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)MAXSIZE.y)));
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealSize = Vector2D(std::clamp(m_vBeginDragSizeXY.x + DELTA.x, (double)20, (double)MAXSIZE.x), std::clamp(m_vBeginDragSizeXY.y + DELTA.y, (double)20, (double)MAXSIZE.y));
} else {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)MAXSIZE.x), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)MAXSIZE.y)));
}
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
@@ -260,6 +265,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
pWindow->m_sSpecialRenderData.rounding = true;
}
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
pWindow->updateToplevel();
}

View File

@@ -241,11 +241,13 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
@@ -320,6 +322,9 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return;
if (on == pWindow->m_bIsFullscreen)
return; // ignore
@@ -386,10 +391,6 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
g_pCompositor->moveWindowToTop(pWindow);
// we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
recalculateMonitor(PMONITOR->ID);
}

View File

@@ -372,7 +372,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
// anim popin, fallback
float minPerc = 0.f;
if (pWindow->m_sAdditionalConfigData.animationStyle.find("%") != 0) {
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));
@@ -411,7 +411,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
} else if (style.find("popin") == 0) {
// try parsing
float minPerc = 0.f;
if (style.find("%") != 0) {
if (style.find("%") != std::string::npos) {
try {
auto percstr = style.substr(style.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));

View File

@@ -37,6 +37,8 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["layoutmsg"] = layoutmsg;
m_mDispatchers["toggleopaque"] = toggleOpaque;
m_mDispatchers["dpms"] = dpms;
m_mDispatchers["movewindowpixel"] = moveWindow;
m_mDispatchers["resizewindowpixel"] = resizeWindow;
m_tScrollTimer.reset();
}
@@ -260,6 +262,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
// call the dispatcher
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %s, %d)", modmask, key.c_str(), keysym);
DISPATCHER->second(k.arg);
if (k.handler == "submap") {
found = true; // don't process keybinds on submap change.
break;
}
}
if (k.repeat) {
@@ -462,7 +469,7 @@ void CKeybindManager::changeworkspace(std::string args) {
}
// remove constraints
g_pCompositor->m_sSeat.mouse->constraintActive = false;
g_pInputManager->unconstrainMouse();
// if it exists, we warp to it
if (g_pCompositor->getWorkspaceByID(workspaceToChangeTo)) {
@@ -483,13 +490,6 @@ void CKeybindManager::changeworkspace(std::string args) {
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell
g_pCompositor->fixXWaylandWindowsOnWorkspace(OLDWORKSPACEID);
// and fix on the new workspace
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
// here and only here begin anim. we don't want to anim visible workspaces on other monitors.
// check if anim left or right
const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACEID;
@@ -558,10 +558,6 @@ void CKeybindManager::changeworkspace(std::string args) {
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell
g_pCompositor->fixXWaylandWindowsOnWorkspace(OLDWORKSPACE);
// set active and deactivate all other
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACE->m_pWlrHandle);
PWORKSPACE->setActive(true);
@@ -588,7 +584,15 @@ void CKeybindManager::fullscreenActive(std::string args) {
}
void CKeybindManager::moveActiveToWorkspace(std::string args) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
CWindow* PWINDOW = nullptr;
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_pLastWindow;
}
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
@@ -671,6 +675,20 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
// hacky, but works lol
CWindow* PWINDOW = nullptr;
const auto ORIGINALARGS = args;
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_pLastWindow;
}
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
int workspaceToMoveTo = 0;
std::string workspaceName = "";
@@ -681,14 +699,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
return;
}
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
if (workspaceToMoveTo == PMONITOR->activeWorkspace)
if (workspaceToMoveTo == PWINDOW->m_iWorkspaceID)
return;
// may be null until later!
@@ -704,7 +717,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
g_pEventManager->m_bIgnoreEvents = true;
moveActiveToWorkspace(args);
moveActiveToWorkspace(ORIGINALARGS);
PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
@@ -736,8 +749,11 @@ void CKeybindManager::moveFocusTo(std::string args) {
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
if (!PLASTWINDOW)
return;
// remove constraints
g_pCompositor->m_sSeat.mouse->constraintActive = false;
g_pInputManager->unconstrainMouse();
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
@@ -1141,120 +1157,90 @@ void CKeybindManager::forceRendererReload(std::string args) {
}
void CKeybindManager::resizeActive(std::string args) {
if (!args.contains(' '))
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
std::string x = args.substr(0, args.find_first_of(' '));
std::string y = args.substr(args.find_first_of(' ') + 1);
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
if (x == "exact") {
std::string newX = y.substr(0, y.find_first_of(' '));
std::string newY = y.substr(y.find_first_of(' ') + 1);
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
if (!isNumber(newX) || !isNumber(newY)) {
Debug::log(ERR, "resizeTiledWindow: exact args not numbers");
return;
}
const int X = std::stoi(newX);
const int Y = std::stoi(newY);
if (X < 10 || Y < 10) {
Debug::log(ERR, "resizeTiledWindow: exact args cannot be < 10");
return;
}
// calc the delta
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return; // ignore
const auto PWINDOW = g_pCompositor->m_pLastWindow;
const int DX = X - PWINDOW->m_vRealSize.goalv().x;
const int DY = Y - PWINDOW->m_vRealSize.goalv().y;
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(DX, DY));
return;
}
if (!isNumber(x) || !isNumber(y)) {
Debug::log(ERR, "resizeTiledWindow: args not numbers");
return;
}
const int X = std::stoi(x);
const int Y = std::stoi(y);
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
if (g_pCompositor->m_pLastWindow->m_vRealSize.goalv().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goalv().y > 1)
g_pCompositor->m_pLastWindow->m_bHidden = false;
}
void CKeybindManager::moveActive(std::string args) {
if (!args.contains(' '))
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
std::string x = args.substr(0, args.find_first_of(' '));
std::string y = args.substr(args.find_first_of(' ') + 1);
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
if (x == "exact") {
std::string newX = y.substr(0, y.find_first_of(' '));
std::string newY = y.substr(y.find_first_of(' ') + 1);
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
}
if (!isNumber(newX) || !isNumber(newY)) {
Debug::log(ERR, "moveActive: exact args not numbers");
return;
}
void CKeybindManager::moveWindow(std::string args) {
const int X = std::stoi(newX);
const int Y = std::stoi(newY);
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
if (X < 0 || Y < 0) {
Debug::log(ERR, "moveActive: exact args cannot be < 0");
return;
}
// calc the delta
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return; // ignore
const auto PWINDOW = g_pCompositor->m_pLastWindow;
const int DX = X - PWINDOW->m_vRealPosition.goalv().x;
const int DY = Y - PWINDOW->m_vRealPosition.goalv().y;
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(DX, DY));
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "moveWindow: no window");
return;
}
if (!isNumber(x) || !isNumber(y)) {
Debug::log(ERR, "moveActive: args not numbers");
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW);
}
void CKeybindManager::resizeWindow(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "resizeWindow: no window");
return;
}
const int X = std::stoi(x);
const int Y = std::stoi(y);
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1)
PWINDOW->m_bHidden = false;
}
void CKeybindManager::circleNext(std::string arg) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (PWINDOWTOCHANGETO == g_pCompositor->m_pLastWindow || !PWINDOWTOCHANGETO)
return;
if (PWORKSPACE->m_bHasFullscreenWindow)
return;
if (g_pCompositor->m_pLastWindow->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
} else {
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
};
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
else
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(MIDPOINT);
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
}
void CKeybindManager::focusWindow(std::string regexp) {

View File

@@ -94,6 +94,8 @@ private:
static void forceRendererReload(std::string);
static void resizeActive(std::string);
static void moveActive(std::string);
static void moveWindow(std::string);
static void resizeWindow(std::string);
static void circleNext(std::string);
static void focusWindow(std::string);
static void setSubmap(std::string);

View File

@@ -120,9 +120,9 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
}
}
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size, bool force) {
if ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))
if (!force && ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
return;
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec();
@@ -155,8 +155,11 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
{
pWindow->m_bNoInitialFocus = true;
return true;
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
pWindow->m_bX11ShouldntFocus = true;
pWindow->m_bNoInitialFocus = true;
return true;
}
if (pWindow->m_uSurface.xwayland->role) {

View File

@@ -17,7 +17,7 @@ public:
std::string getTitle(CWindow*);
std::string getAppIDClass(CWindow*);
void sendCloseWindow(CWindow*);
void setWindowSize(CWindow*, const Vector2D&);
void setWindowSize(CWindow*, const Vector2D&, bool force = false);
void setWindowStyleTiled(CWindow*, uint32_t);
void setWindowFullscreen(CWindow*, bool);
wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&);

View File

@@ -31,6 +31,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
static auto *const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
static auto *const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
if (!g_pCompositor->m_bReadyToProcess)
return;
@@ -68,7 +69,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
if (!CONSTRAINTWINDOW) {
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
unconstrainMouse();
} else {
// Native Wayland apps know how 2 constrain themselves.
// XWayland, we just have to accept them. Might cause issues, but thats XWayland for ya.
@@ -124,7 +125,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
ACTIVEWORKSPACE->setActive(true);
// event
g_pEventManager->postEvent(SHyprIPCEvent{"activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
}
Vector2D surfaceCoords;
@@ -181,9 +182,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
}
} else
} else {
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
// TODO: this causes crashes, sometimes. ???
// if (refocus && !pFoundWindow) {
// pFoundWindow = g_pCompositor->getFirstWindowOnWorkspace(PMONITOR->activeWorkspace);
// }
}
if (pFoundWindow) {
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@@ -229,11 +236,21 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y);
}
bool allowKeyboardRefocus = true;
if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) {
const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
if (PLS && PLS->layerSurface->current.keyboard_interactive) {
allowKeyboardRefocus = false;
}
}
if (pFoundWindow) {
if (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
// enter if change floating style
if (*PFOLLOWMOUSE != 3)
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
} else if (*PFOLLOWMOUSE == 2) {
@@ -252,11 +269,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
return; // don't enter any new surfaces
} else {
if (*PFOLLOWMOUSE != 3)
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
}
} else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3)
g_pCompositor->focusSurface(foundSurface);
} else {
if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3 && allowKeyboardRefocus) {
g_pCompositor->focusSurface(foundSurface);
g_pCompositor->m_pLastWindow = nullptr; // reset last window as we have a full focus on a LS
}
}
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
@@ -315,7 +336,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
m_ecbClickBehavior = CLICKMODE_KILL;
// remove constraints
g_pCompositor->m_sSeat.mouse->constraintActive = false;
g_pInputManager->unconstrainMouse();
refocus();
// set cursor
@@ -428,10 +449,19 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
if (m_pActiveKeyboard)
m_pActiveKeyboard->active = false;
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
}, PNEWKEYBOARD, "Keyboard");
disableAllKeyboards(false);
m_pActiveKeyboard = PNEWKEYBOARD;
PNEWKEYBOARD->active = true;
applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
@@ -454,11 +484,19 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
}, PNEWKEYBOARD, "Keyboard");
disableAllKeyboards(true);
if (m_pActiveKeyboard)
m_pActiveKeyboard->active = false;
m_pActiveKeyboard = PNEWKEYBOARD;
PNEWKEYBOARD->active = true;
applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
@@ -489,6 +527,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
const auto FILEPATH = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_file") : g_pConfigManager->getString("input:kb_file");
const auto RULES = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_rules") : g_pConfigManager->getString("input:kb_rules");
const auto MODEL = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_model") : g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_layout") : g_pConfigManager->getString("input:kb_layout");
@@ -496,7 +535,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_options") : g_pConfigManager->getString("input:kb_options");
try {
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options && FILEPATH == pKeyboard->xkbFilePath) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
@@ -510,6 +549,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
pKeyboard->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE;
pKeyboard->numlockOn = NUMLOCKON;
pKeyboard->xkbFilePath = FILEPATH.c_str();
xkb_rule_names rules = {
.rules = RULES.c_str(),
@@ -533,9 +573,25 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_keymap * KEYMAP = NULL;
if (!FILEPATH.empty()) {
auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath);
if (!std::filesystem::exists(path)) {
Debug::log(ERR, "input:kb_file= file doesnt exist");
} else {
KEYMAP = xkb_keymap_new_from_file(CONTEXT, fopen(path.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
}
if (!KEYMAP) {
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
if (!KEYMAP) {
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )");
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
@@ -567,6 +623,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," +getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
}
@@ -688,7 +746,7 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) {
g_pCompositor->m_sSeat.mouse = m_lMice.size() > 0 ? &m_lMice.front() : nullptr;
if (g_pCompositor->m_sSeat.mouse)
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
unconstrainMouse();
}
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
@@ -720,6 +778,14 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
}
const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
if (PWLRKB->modifiers.group != pKeyboard->activeLayout) {
pKeyboard->activeLayout = PWLRKB->modifiers.group;
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
}
}
void CInputManager::refocus() {
@@ -815,6 +881,29 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
Debug::log(LOG, "Constrained mouse to %x", pMouse->currentConstraint);
}
void CInputManager::unconstrainMouse() {
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
return;
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
if (CONSTRAINTWINDOW) {
if (CONSTRAINTWINDOW->m_bIsX11) {
wlr_xwayland_surface_activate(CONSTRAINTWINDOW->m_uSurface.xwayland, false);
} else {
wlr_xdg_toplevel_set_activated(CONSTRAINTWINDOW->m_uSurface.xdg->toplevel, false);
}
}
wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
g_pCompositor->m_sSeat.mouse->constraintActive = false;
// TODO: its better to somehow detect the workspace...
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
g_pCompositor->m_sSeat.mouse->hyprListener_commitConstraint.removeCallback();
}
void Events::listener_commitConstraint(void* owner, void* data) {
//g_pInputManager->recheckConstraint((SMouse*)owner);
}
@@ -849,3 +938,32 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
return finalMask;
}
std::string CInputManager::getActiveLayoutForKeyboard(SKeyboard* pKeyboard) {
const auto WLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
const auto KEYMAP = WLRKB->keymap;
const auto STATE = WLRKB->xkb_state;
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i);
if (LAYOUTNAME)
return std::string(LAYOUTNAME);
return "error";
}
}
return "none";
}
void CInputManager::disableAllKeyboards(bool virt) {
for (auto& k : m_lKeyboards) {
if (k.isVirtual != virt)
continue;
k.active = false;
}
}

View File

@@ -14,6 +14,7 @@ enum eClickBehaviorMode {
struct STouchData {
CWindow* touchFocusWindow = nullptr;
Vector2D touchSurfaceOrigin;
};
class CInputManager {
@@ -34,6 +35,8 @@ public:
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
void unconstrainMouse();
std::string getActiveLayoutForKeyboard(SKeyboard*);
Vector2D getMouseCoordsInternal();
void refocus();
@@ -104,6 +107,8 @@ private:
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
void disableAllKeyboards(bool virt = false);
uint32_t m_uiCapabilities = 0;
void mouseMoveUnified(uint32_t, bool refocus = false);

View File

@@ -79,7 +79,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
g_pInputManager->unconstrainMouse();
Debug::log(LOG, "Ended swipe to the left");
} else {
@@ -95,11 +95,13 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
g_pInputManager->unconstrainMouse();
Debug::log(LOG, "Ended swipe to the right");
}
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
PWORKSPACEL->m_bForceRendering = false;
PWORKSPACER->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
@@ -141,11 +143,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
PWORKSPACE->m_bForceRendering = true;
PWORKSPACE->m_fAlpha.setValueAndWarp(255.f);
if (workspaceIDLeft != workspaceIDRight) {
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
PWORKSPACER->m_bForceRendering = false;
PWORKSPACER->m_fAlpha.setValueAndWarp(0.f);
}
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
@@ -161,11 +165,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight);
PWORKSPACE->m_bForceRendering = true;
PWORKSPACE->m_fAlpha.setValueAndWarp(255.f);
if (workspaceIDLeft != workspaceIDRight) {
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
PWORKSPACEL->m_bForceRendering = false;
PWORKSPACEL->m_fAlpha.setValueAndWarp(0.f);
}
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));

View File

@@ -10,9 +10,16 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
m_sTouchData.touchFocusWindow = nullptr;
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) {
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, e->time_msec, e->touch_id,
e->x * g_pCompositor->m_pLastMonitor->vecSize.x + g_pCompositor->m_pLastMonitor->vecPosition.x - g_pCompositor->m_pLastWindow->m_vRealPosition.vec().x,
e->y * g_pCompositor->m_pLastMonitor->vecSize.y + g_pCompositor->m_pLastMonitor->vecPosition.y - g_pCompositor->m_pLastWindow->m_vRealPosition.vec().y);
Vector2D local;
if (g_pCompositor->m_pLastWindow->m_bIsX11) {
local = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv();
} else {
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), g_pCompositor->m_pLastWindow, local);
}
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, e->time_msec, e->touch_id, local.x, local.y);
m_sTouchData.touchFocusWindow = g_pCompositor->m_pLastWindow;
}
@@ -29,10 +36,10 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e){
if (g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id,
e->x * PMONITOR->vecSize.x + PMONITOR->vecPosition.x - m_sTouchData.touchFocusWindow->m_vRealPosition.vec().x,
e->y * PMONITOR->vecSize.y + PMONITOR->vecPosition.y - m_sTouchData.touchFocusWindow->m_vRealPosition.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
}
}

View File

@@ -23,110 +23,6 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
#endif
// Init shaders
GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC);
m_shQUAD.program = prog;
m_shQUAD.proj = glGetUniformLocation(prog, "proj");
m_shQUAD.color = glGetUniformLocation(prog, "color");
m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
m_shQUAD.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
m_shQUAD.radius = glGetUniformLocation(prog, "radius");
m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_shRGBA.program = prog;
m_shRGBA.proj = glGetUniformLocation(prog, "proj");
m_shRGBA.tex = glGetUniformLocation(prog, "tex");
m_shRGBA.alpha = glGetUniformLocation(prog, "alpha");
m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
m_shRGBA.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
m_shRGBA.radius = glGetUniformLocation(prog, "radius");
m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX);
m_shRGBX.program = prog;
m_shRGBX.tex = glGetUniformLocation(prog, "tex");
m_shRGBX.proj = glGetUniformLocation(prog, "proj");
m_shRGBX.alpha = glGetUniformLocation(prog, "alpha");
m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos");
m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
m_shRGBX.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
m_shRGBX.radius = glGetUniformLocation(prog, "radius");
m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT);
m_shEXT.program = prog;
m_shEXT.tex = glGetUniformLocation(prog, "tex");
m_shEXT.proj = glGetUniformLocation(prog, "proj");
m_shEXT.alpha = glGetUniformLocation(prog, "alpha");
m_shEXT.posAttrib = glGetAttribLocation(prog, "pos");
m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
m_shEXT.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
m_shEXT.radius = glGetUniformLocation(prog, "radius");
m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
m_shBLUR1.program = prog;
m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(TEXVERTSRC, FRAGBLUR2);
m_shBLUR2.program = prog;
m_shBLUR2.tex = glGetUniformLocation(prog, "tex");
m_shBLUR2.alpha = glGetUniformLocation(prog, "alpha");
m_shBLUR2.proj = glGetUniformLocation(prog, "proj");
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
m_shSHADOW.program = prog;
m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
m_shSHADOW.range = glGetUniformLocation(prog, "range");
m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
m_shSHADOW.color = glGetUniformLocation(prog, "color");
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
m_shBORDER1.program = prog;
m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
m_shBORDER1.thick = glGetUniformLocation(prog, "thick");
m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
m_shBORDER1.topLeft = glGetUniformLocation(prog, "topLeft");
m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
m_shBORDER1.color = glGetUniformLocation(prog, "color");
Debug::log(LOG, "Shaders initialized successfully.");
// End shaders
pixman_region32_init(&m_rOriginalDamageRegion);
@@ -180,6 +76,10 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) {
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool fake) {
m_RenderData.pMonitor = pMonitor;
if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) {
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL));
}
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
@@ -206,6 +106,9 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
createBGTextureForMonitor(pMonitor);
}
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
initShaders();
// bind the primary Hypr Framebuffer
m_RenderData.pCurrentMonData->primaryFB.bind();
@@ -236,6 +139,112 @@ void CHyprOpenGLImpl::end() {
m_iWLROutputFb = 0;
}
void CHyprOpenGLImpl::initShaders() {
GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC);
m_RenderData.pCurrentMonData->m_shQUAD.program = prog;
m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color");
m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shQUAD.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBA.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX);
m_RenderData.pCurrentMonData->m_shRGBX.program = prog;
m_RenderData.pCurrentMonData->m_shRGBX.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shRGBX.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shRGBX.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBX.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT);
m_RenderData.pCurrentMonData->m_shEXT.program = prog;
m_RenderData.pCurrentMonData->m_shEXT.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shEXT.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shEXT.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_shEXT.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shEXT.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
m_RenderData.pCurrentMonData->m_shBLUR1.program = prog;
m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(TEXVERTSRC, FRAGBLUR2);
m_RenderData.pCurrentMonData->m_shBLUR2.program = prog;
m_RenderData.pCurrentMonData->m_shBLUR2.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shBLUR2.alpha = glGetUniformLocation(prog, "alpha");
m_RenderData.pCurrentMonData->m_shBLUR2.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
m_RenderData.pCurrentMonData->m_shSHADOW.program = prog;
m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
m_RenderData.pCurrentMonData->m_shBORDER1.program = prog;
m_RenderData.pCurrentMonData->m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBORDER1.thick = glGetUniformLocation(prog, "thick");
m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBORDER1.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
m_RenderData.pCurrentMonData->m_shBORDER1.color = glGetUniformLocation(prog, "color");
m_RenderData.pCurrentMonData->m_bShadersInitialized = true;
Debug::log(LOG, "Shaders initialized successfully.");
}
void CHyprOpenGLImpl::clear(const CColor& color) {
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
@@ -311,10 +320,10 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shQUAD.program);
glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program);
glUniformMatrix3fv(m_shQUAD.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
@@ -323,17 +332,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shQUAD.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shQUAD.radius, round);
glUniform1i(m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round);
glUniform1i(m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shQUAD.posAttrib);
glEnableVertexAttribArray(m_shQUAD.texAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib);
if (pixman_region32_not_empty(damage)) {
PIXMAN_DAMAGE_FOREACH(damage) {
@@ -343,8 +352,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
}
}
glDisableVertexAttribArray(m_shQUAD.posAttrib);
glDisableVertexAttribArray(m_shQUAD.texAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
@@ -385,13 +394,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
switch (tex.m_iType) {
case TEXTURE_RGBA:
shader = &m_shRGBA;
shader = &m_RenderData.pCurrentMonData->m_shRGBA;
break;
case TEXTURE_RGBX:
shader = &m_shRGBX;
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
break;
case TEXTURE_EXTERNAL:
shader = &m_shEXT;
shader = &m_RenderData.pCurrentMonData->m_shEXT;
break;
default:
RASSERT(false, "tex.m_iTarget unsupported!");
@@ -510,10 +519,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
glUniform1f(pShader->radius, *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_shBLUR1)
glUniform2f(m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1)
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
else
glUniform2f(m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -550,17 +559,17 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
pixman_region32_init(&tempDamage);
wlr_region_scale(&tempDamage, &damage, 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET
drawPass(&m_shBLUR1, &tempDamage);
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage);
// and draw
for (int i = 1; i < *PBLURPASSES; ++i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
drawPass(&m_shBLUR1, &tempDamage); // down
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down
}
for (int i = *PBLURPASSES - 1; i >= 0; --i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
drawPass(&m_shBLUR2, &tempDamage); // up
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up
}
// finish
@@ -778,27 +787,27 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shBORDER1.program);
glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
const auto FULLSIZE = Vector2D(box->width, box->height);
glUniform2f(m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shBORDER1.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shBORDER1.radius, round);
glUniform1f(m_shBORDER1.thick, *PBORDERSIZE);
glUniform1i(m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, *PBORDERSIZE);
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_shBORDER1.texAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
@@ -808,8 +817,8 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
}
}
glDisableVertexAttribArray(m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_shBORDER1.texAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
@@ -1021,28 +1030,28 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_shSHADOW.program);
glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners
glUniform2f(m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_shSHADOW.radius, range + round);
glUniform1f(m_shSHADOW.range, range);
glUniform1f(m_shSHADOW.shadowPower, SHADOWPOWER);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shSHADOW.posAttrib);
glEnableVertexAttribArray(m_shSHADOW.texAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
@@ -1052,8 +1061,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
}
}
glDisableVertexAttribArray(m_shSHADOW.posAttrib);
glDisableVertexAttribArray(m_shSHADOW.texAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
@@ -1098,10 +1107,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
// get the adequate tex
std::string texPath = "/usr/share/hyprland/wall_";
Vector2D textureSize;
if (pMonitor->vecTransformedSize.x > 7000) {
if (pMonitor->vecTransformedSize.x > 3850) {
textureSize = Vector2D(7680, 4320);
texPath += "8K.png";
} else if (pMonitor->vecTransformedSize.x > 3000) {
} else if (pMonitor->vecTransformedSize.x > 1930) {
textureSize = Vector2D(3840, 2160);
texPath += "4K.png";
} else {
@@ -1122,8 +1131,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);

View File

@@ -42,6 +42,18 @@ struct SMonitorRenderData {
bool blurFBDirty = true;
wlr_box backgroundTexBox;
// Shaders
bool m_bShadersInitialized = false;
CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shRGBX;
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shSHADOW;
CShader m_shBORDER1;
//
};
struct SCurrentRenderData {
@@ -114,20 +126,10 @@ private:
bool m_bFakeFrame = false;
bool m_bEndFrame = false;
// Shaders
CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shRGBX;
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shSHADOW;
CShader m_shBORDER1;
//
GLuint createProgram(const std::string&, const std::string&);
GLuint compileShader(const GLuint&, std::string);
void createBGTextureForMonitor(CMonitor*);
void initShaders();
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);

View File

@@ -34,6 +34,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
rounding *= RDATA->output->scale;
if (RDATA->surface && surface == RDATA->surface) {
if (wlr_surface_is_xwayland_surface(surface) && !wlr_xwayland_surface_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 255.f) {
@@ -78,16 +79,22 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
return false;
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()) {
return true;
} else {
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
return false;
}
}
if (pWindow->m_iWorkspaceID == pMonitor->activeWorkspace)
return true;
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return true;
// if not, check if it maybe is active on a different monitor.
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) ||
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || // vvvv might be in animation progress vvvvv
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
@@ -125,6 +132,9 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen){
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
continue;
if (w->m_iMonitorID != pMonitor->ID)
continue;
}
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->m_bIsFullscreen)
@@ -254,10 +264,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
if (renderdata.decorate) {
if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) {
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
rounding *= pMonitor->scale;
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f;
@@ -670,6 +681,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
if (!pSurface)
return; // wut?
if (g_pCompositor->m_bUnsafeState)
return;
pixman_region32_t damageBox;
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
@@ -710,6 +724,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
}
void CHyprRenderer::damageWindow(CWindow* pWindow) {
if (g_pCompositor->m_bUnsafeState)
return;
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
@@ -724,6 +741,9 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
}
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
if (g_pCompositor->m_bUnsafeState)
return;
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
wlr_output_damage_add_box(pMonitor->damage, &damageBox);
@@ -734,6 +754,9 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
}
void CHyprRenderer::damageBox(wlr_box* pBox) {
if (g_pCompositor->m_bUnsafeState)
return;
for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m->scale);

View File

@@ -10,4 +10,11 @@ GLint CShader::getUniformLocation(const std::string& unif) {
}
return itpos->second;
}
CShader::~CShader() {
// destroy shader
if (program != 0) {
glDeleteProgram(program);
}
}

View File

@@ -5,7 +5,9 @@
class CShader {
public:
GLuint program;
~CShader();
GLuint program = 0;
GLint proj;
GLint color;
GLint tex;

View File

@@ -80,6 +80,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
return; // cannot parse
}
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ? 0 : (m_pWindow->m_sAdditionalConfigData.rounding == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding);
// update the extents
m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}};
@@ -113,15 +115,15 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
glDisable(GL_STENCIL_TEST);
return; // prevent assert failed
}
g_pHyprOpenGL->renderRect(&windowBox, CColor(0,0,0,0), *PROUNDING);
g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 0), ROUNDING * pMonitor->scale);
glStencilFunc(GL_NOTEQUAL, 1, -1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE * pMonitor->scale, a);
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
if (*PSHADOWIGNOREWINDOW) {
// cleanup

View File

@@ -112,7 +112,7 @@ static void workspace_handle_remove(struct wl_client *client,
return;
}
wlr_signal_emit_safe(&workspace->events.remove_request, NULL);
wl_signal_emit_mutable(&workspace->events.remove_request, NULL);
}
static void workspace_handle_deactivate(struct wl_client *client,
@@ -312,7 +312,7 @@ void wlr_ext_workspace_handle_v1_destroy(
return;
}
wlr_signal_emit_safe(&workspace->events.destroy, workspace);
wl_signal_emit_mutable(&workspace->events.destroy, workspace);
workspace_manager_update_idle_source(workspace->group->manager);
@@ -338,7 +338,7 @@ static void workspace_group_handle_handle_create_workspace(struct wl_client *cli
struct wlr_ext_workspace_group_handle_v1_create_workspace_event event;
event.workspace_group = group;
event.name = arg;
wlr_signal_emit_safe(&group->events.create_workspace_request, &event);
wl_signal_emit_mutable(&group->events.create_workspace_request, &event);
}
static void workspace_group_handle_handle_destroy(struct wl_client *client,
@@ -513,7 +513,7 @@ void wlr_ext_workspace_group_handle_v1_destroy(
wlr_ext_workspace_handle_v1_destroy(workspace);
}
wlr_signal_emit_safe(&group->events.destroy, group);
wl_signal_emit_mutable(&group->events.destroy, group);
workspace_manager_update_idle_source(group->manager);
struct wlr_ext_workspace_group_handle_v1_output *output, *tmp2;
@@ -556,7 +556,7 @@ static void workspace_manager_commit(struct wl_client *client,
}
}
wlr_signal_emit_safe(&manager->events.commit, manager);
wl_signal_emit_mutable(&manager->events.commit, manager);
}
static void workspace_manager_stop(struct wl_client *client,
@@ -602,7 +602,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_ext_workspace_manager_v1 *manager =
wl_container_of(listener, manager, display_destroy);
wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_signal_emit_mutable(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->global);