mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-28 02:31:54 -07:00
Compare commits
192 Commits
v0.12.1bet
...
v0.15.0bet
Author | SHA1 | Date | |
---|---|---|---|
|
ff5843bd85 | ||
|
3bb5971c2e | ||
|
a1d9404f9f | ||
|
ab82c4806d | ||
|
49ab3890aa | ||
|
85eea70be4 | ||
|
174b593438 | ||
|
0a08830375 | ||
|
a97621b1cb | ||
|
355366714e | ||
|
590fbf808b | ||
|
bbeed21e62 | ||
|
e6c9e3f81d | ||
|
7579e03b64 | ||
|
1ef23a304a | ||
|
3c27d1ab13 | ||
|
59a3c43913 | ||
|
2d73da1a79 | ||
|
45fe185cb9 | ||
|
da40bf823f | ||
|
caeb0636fa | ||
|
bdd9680adf | ||
|
ff4c22ca90 | ||
|
9f9129e536 | ||
|
ab42e4bccf | ||
|
2636abca2d | ||
|
ead0e74471 | ||
|
dcf5e34bfa | ||
|
10c4f4ba35 | ||
|
a1319e5110 | ||
|
5233746ac5 | ||
|
31cb4c49d9 | ||
|
11ee78f88b | ||
|
ec5ffe8839 | ||
|
e3b1d3c3c5 | ||
|
458ba3237b | ||
|
7a775c0584 | ||
|
87afc8c250 | ||
|
cd2b2c4fba | ||
|
c48336aac3 | ||
|
f70b57f360 | ||
|
bf3f519eb7 | ||
|
190229942f | ||
|
e476382d08 | ||
|
c885afcbc6 | ||
|
fad5fc587d | ||
|
73dbacd16d | ||
|
65fb0cf0f6 | ||
|
5101ddeff1 | ||
|
959557ecc3 | ||
|
bccc81d306 | ||
|
718de0d9fa | ||
|
fd6116c0cd | ||
|
00b16888bf | ||
|
abee2da5bd | ||
|
695411f1bd | ||
|
f9d8b3096a | ||
|
e5d143b238 | ||
|
37f2e1ddbe | ||
|
ef3eb37c7f | ||
|
db551b8970 | ||
|
c08218301b | ||
|
75aaf11a9c | ||
|
c4e782ca5d | ||
|
da2c2ddc21 | ||
|
5272588270 | ||
|
215125bd66 | ||
|
30d16373d0 | ||
|
c1feb683ce | ||
|
d3ffccd45f | ||
|
d49af1cc18 | ||
|
8b46d0b5a9 | ||
|
336883dda3 | ||
|
65ec8c7694 | ||
|
79c645f8cd | ||
|
d44cc9f112 | ||
|
1963da2d47 | ||
|
2b99dbb446 | ||
|
d24f31de51 | ||
|
d51c7ca135 | ||
|
8b11a2e1b1 | ||
|
b4bcba935d | ||
|
7f3750bd75 | ||
|
7a9423c782 | ||
|
6f98b3cbd8 | ||
|
2dd1661aec | ||
|
cde624ec6a | ||
|
b82621c4ec | ||
|
5b6c8d5b0f | ||
|
4dca2b945b | ||
|
a8943246a7 | ||
|
e42de0b778 | ||
|
5146165599 | ||
|
73e19aee6f | ||
|
3780361b95 | ||
|
ec6144e5da | ||
|
b6eaeffcf6 | ||
|
c24b45671a | ||
|
85c7aaf155 | ||
|
696253b348 | ||
|
abb6db9c37 | ||
|
18b483b8e1 | ||
|
7c809a3059 | ||
|
4070e1a148 | ||
|
dd61f88ed1 | ||
|
29626989e7 | ||
|
cf32d28082 | ||
|
5131a4acaf | ||
|
a72a39ebd5 | ||
|
151e013241 | ||
|
fa2d81b649 | ||
|
037d4ed422 | ||
|
9f82278d65 | ||
|
8e0f7b9b11 | ||
|
a96acc8fa4 | ||
|
5a146e9d90 | ||
|
da10022d84 | ||
|
e518adf1ac | ||
|
d8dbe26f31 | ||
|
e9f226797e | ||
|
7d4f0a3199 | ||
|
0062281092 | ||
|
81f267dff9 | ||
|
a09c614c2d | ||
|
b49d7007b5 | ||
|
864e227f5d | ||
|
82aa78916d | ||
|
f024d7114f | ||
|
8808d40008 | ||
|
d94fe3d063 | ||
|
f663fa209c | ||
|
9370c7aa8a | ||
|
928158bbfb | ||
|
bacfae3084 | ||
|
0d95a0174c | ||
|
0eb5ecafb9 | ||
|
49a55f136e | ||
|
64be57b780 | ||
|
6e195a6b8c | ||
|
8d3f6c5d84 | ||
|
5c470d2e54 | ||
|
26910a8b63 | ||
|
44a2d755c6 | ||
|
cf5426f2d8 | ||
|
1d631c8a23 | ||
|
789eedd115 | ||
|
4a8274e5f0 | ||
|
4b7d28d2cb | ||
|
5fdd1dd60f | ||
|
e71a4d75de | ||
|
f002bd1603 | ||
|
16f1d1b99b | ||
|
c1bc8d46e9 | ||
|
94ca386a8c | ||
|
2ba7cb2414 | ||
|
5b5f36f494 | ||
|
a74b8033ca | ||
|
41883e0522 | ||
|
3ea89e6171 | ||
|
d6c06318af | ||
|
cb839c9dcc | ||
|
3dd514a452 | ||
|
6afab12b91 | ||
|
7a3b57c99c | ||
|
ba0c5fe0bb | ||
|
f6ecef0959 | ||
|
ff26531e11 | ||
|
fbd2b4799d | ||
|
1664f81cae | ||
|
c425e620af | ||
|
f4add0ac6d | ||
|
3c3f80c2fe | ||
|
eee0cad4d0 | ||
|
0ea96e87c0 | ||
|
5d09bb647b | ||
|
f5697095bc | ||
|
56203b1757 | ||
|
c0a7dffcdc | ||
|
8581e71789 | ||
|
bb90ff0461 | ||
|
1d4d2f4793 | ||
|
7f62cbc48a | ||
|
f2d84a7e3a | ||
|
095185cfe7 | ||
|
f77fac9df9 | ||
|
dacaf72e02 | ||
|
0ad261aa9c | ||
|
7610c20761 | ||
|
4103bca056 | ||
|
21a1b62b6a | ||
|
7f483dfdb0 | ||
|
1cf46fd6a2 |
2
.github/workflows/man-update.yaml
vendored
2
.github/workflows/man-update.yaml
vendored
@@ -5,6 +5,8 @@ on:
|
||||
push:
|
||||
paths:
|
||||
- docs/**
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
main:
|
||||
|
@@ -29,8 +29,6 @@ input {
|
||||
}
|
||||
|
||||
general {
|
||||
main_mod=SUPER
|
||||
|
||||
gaps_in=5
|
||||
gaps_out=20
|
||||
border_size=2
|
||||
@@ -75,6 +73,10 @@ gestures {
|
||||
#windowrule=pseudo,abc
|
||||
#windowrule=monitor 0,xyz
|
||||
|
||||
# some nice mouse binds
|
||||
bindm=SUPER,mouse:272,movewindow
|
||||
bindm=SUPER,mouse:273,resizewindow
|
||||
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,C,killactive,
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1660908602,
|
||||
"narHash": "sha256-SwZ85IPWvC4NxxFhWhRMTJpApSHbY1u4YK2UFWEBWvY=",
|
||||
"lastModified": 1664687381,
|
||||
"narHash": "sha256-9czSuDzS+OGGwq2kC4KXBLXWfYaup+oLB+AA1Md25U4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "495b19d5b3e62b4ec7e846bdfb6ef3d9c3b83492",
|
||||
"rev": "59d2991d4256cdca1c0cda45d876c80a0fe45c31",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1660930713,
|
||||
"narHash": "sha256-bY7q1NqG/sjCUAWPn/Ne9NCigLlPlH5Lk1WCMqv3rTU=",
|
||||
"lastModified": 1664816798,
|
||||
"narHash": "sha256-oLJyFT1Fc4UNNaDSN+EYUAWL4CufCBpuS5AV4Z4XANo=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "7c575922c05e4d5fd9a403c2aa631a54c7531d44",
|
||||
"rev": "50cc1ef4d3791d86854dd83c15fff17e5ea1a5b6",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
37
flake.nix
37
flake.nix
@@ -20,7 +20,31 @@
|
||||
"aarch64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
pkgsFor = nixpkgs.legacyPackages;
|
||||
pkgsFor = genSystems (system:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
(_: prev: {
|
||||
libdrm = prev.libdrm.overrideAttrs (old: rec {
|
||||
version = "2.4.113";
|
||||
src = prev.fetchurl {
|
||||
url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz";
|
||||
sha256 = "sha256-f9frKWf2O+tGBvItUOJ32ZNIDQXvdd2Iqb2OZ3Mj5eE=";
|
||||
};
|
||||
mesonFlags =
|
||||
[
|
||||
"-Dinstall-test-programs=true"
|
||||
"-Domap=enabled"
|
||||
"-Dcairo-tests=disabled"
|
||||
]
|
||||
++ lib.optionals prev.stdenv.hostPlatform.isAarch [
|
||||
"-Dtegra=enabled"
|
||||
"-Detnaviv=enabled"
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
});
|
||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||
(__substring 0 4 longDate)
|
||||
(__substring 4 2 longDate)
|
||||
@@ -28,14 +52,13 @@
|
||||
]);
|
||||
in {
|
||||
overlays.default = _: prev: rec {
|
||||
wlroots-hyprland = prev.wlroots.overrideAttrs (__: {
|
||||
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101");
|
||||
wlroots-hyprland = prev.callPackage ./nix/wlroots.nix {
|
||||
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101") + "_" + (inputs.wlroots.shortRev or "dirty");
|
||||
src = inputs.wlroots;
|
||||
});
|
||||
|
||||
};
|
||||
hyprland = prev.callPackage ./nix/default.nix {
|
||||
stdenv = prev.gcc12Stdenv;
|
||||
version = "0.11.1beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||
version = "0.14.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||
wlroots = wlroots-hyprland;
|
||||
};
|
||||
hyprland-debug = hyprland.override {debug = true;};
|
||||
@@ -66,8 +89,6 @@
|
||||
|
||||
nixosModules.default = import ./nix/module.nix self;
|
||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||
|
||||
overlay = throw "Hyprland: .overlay output is deprecated, please use the .overlays.default output";
|
||||
};
|
||||
|
||||
nixConfig = {
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#include <deque>
|
||||
|
||||
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
||||
|
||||
|
||||
commands:
|
||||
monitors
|
||||
workspaces
|
||||
@@ -36,7 +36,7 @@ commands:
|
||||
reload
|
||||
setcursor
|
||||
getoption
|
||||
|
||||
|
||||
flags:
|
||||
-j -> output in JSON
|
||||
--batch -> execute a batch of commands, separated by ';'
|
||||
@@ -198,7 +198,7 @@ void setcursorRequest(int argc, char** argv) {
|
||||
|
||||
void batchRequest(std::string arg) {
|
||||
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
|
||||
|
||||
|
||||
request(rq);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : '0.11.1beta',
|
||||
version : '0.14.0beta',
|
||||
default_options : [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
|
@@ -24,6 +24,7 @@
|
||||
enableXWayland ? true,
|
||||
hidpiXWayland ? true,
|
||||
legacyRenderer ? false,
|
||||
nvidiaPatches ? false,
|
||||
version ? "git",
|
||||
}: let
|
||||
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
||||
@@ -68,11 +69,7 @@ in
|
||||
wayland
|
||||
wayland-protocols
|
||||
wayland-scanner
|
||||
(
|
||||
if hidpiXWayland
|
||||
then (import ./hidpi_wlroots.nix {inherit wlroots xwayland fetchpatch;})
|
||||
else wlroots.override {inherit enableXWayland;}
|
||||
)
|
||||
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
|
||||
xcbutilwm
|
||||
]
|
||||
++ lib.optional enableXWayland xwayland;
|
||||
|
@@ -1,31 +0,0 @@
|
||||
{
|
||||
wlroots,
|
||||
xwayland,
|
||||
fetchpatch,
|
||||
}:
|
||||
(wlroots.overrideAttrs
|
||||
(old: {
|
||||
patches =
|
||||
(old.patches or [])
|
||||
++ [
|
||||
(fetchpatch {
|
||||
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
|
||||
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
|
||||
})
|
||||
(fetchpatch {
|
||||
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
|
||||
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
|
||||
revert = true;
|
||||
})
|
||||
];
|
||||
}))
|
||||
.override {
|
||||
xwayland = xwayland.overrideAttrs (old: {
|
||||
patches =
|
||||
(old.patches or [])
|
||||
++ [
|
||||
./xwayland-vsync.patch
|
||||
./xwayland-hidpi.patch
|
||||
];
|
||||
});
|
||||
}
|
@@ -67,6 +67,16 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
recommendedEnvironment = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
defaultText = lib.literalExpression "true";
|
||||
example = lib.literalExpression "false";
|
||||
description = ''
|
||||
Whether to set the recommended environment variables.
|
||||
'';
|
||||
};
|
||||
|
||||
imports = [
|
||||
(
|
||||
lib.mkRenamedOptionModule
|
||||
@@ -81,10 +91,17 @@ in {
|
||||
lib.optional (cfg.package != null) cfg.package
|
||||
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
|
||||
|
||||
home.sessionVariables = lib.mkIf cfg.recommendedEnvironment {
|
||||
GDK_BACKEND = "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
||||
NIXOS_OZONE_WL = "1";
|
||||
XCURSOR_SIZE = toString config.home.pointerCursor.size or "24";
|
||||
XDG_SESSION_TYPE = "wayland";
|
||||
};
|
||||
|
||||
xdg.configFile."hypr/hyprland.conf" = {
|
||||
text =
|
||||
(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
|
||||
'')
|
||||
|
@@ -8,6 +8,10 @@ self: {
|
||||
with lib; let
|
||||
cfg = config.programs.hyprland;
|
||||
in {
|
||||
imports = [
|
||||
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
|
||||
];
|
||||
|
||||
options.programs.hyprland = {
|
||||
enable = mkEnableOption ''
|
||||
Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
@@ -27,20 +31,40 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
|
||||
];
|
||||
recommendedEnvironment = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
defaultText = literalExpression "true";
|
||||
example = literalExpression "false";
|
||||
description = ''
|
||||
Whether to set the recommended environment variables.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
security.polkit.enable = true;
|
||||
hardware.opengl.enable = mkDefault true;
|
||||
environment = {
|
||||
systemPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
|
||||
sessionVariables = mkIf cfg.recommendedEnvironment {
|
||||
GDK_BACKEND = "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
||||
NIXOS_OZONE_WL = "1";
|
||||
XCURSOR_SIZE = "24";
|
||||
XDG_SESSION_TYPE = "wayland";
|
||||
};
|
||||
};
|
||||
fonts.enableDefaultFonts = mkDefault true;
|
||||
programs.dconf.enable = mkDefault true;
|
||||
hardware.opengl.enable = mkDefault true;
|
||||
programs = {
|
||||
dconf.enable = mkDefault true;
|
||||
xwayland.enable = mkDefault true;
|
||||
};
|
||||
security.polkit.enable = true;
|
||||
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
programs.xwayland.enable = mkDefault true;
|
||||
xdg.portal.enable = mkDefault true;
|
||||
xdg.portal.extraPortals = [pkgs.xdg-desktop-portal-wlr];
|
||||
xdg.portal = {
|
||||
enable = mkDefault true;
|
||||
extraPortals = [pkgs.xdg-desktop-portal-wlr];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
64
nix/wlroots.nix
Normal file
64
nix/wlroots.nix
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
version,
|
||||
src,
|
||||
#
|
||||
wlroots,
|
||||
xwayland,
|
||||
fetchpatch,
|
||||
lib,
|
||||
hidpiXWayland ? true,
|
||||
enableXWayland ? true,
|
||||
nvidiaPatches ? false,
|
||||
}:
|
||||
assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
||||
wlroots-hyprland: cannot have hidpiXWayland when enableXWayland is false.
|
||||
'');
|
||||
(wlroots.overrideAttrs
|
||||
(old: {
|
||||
inherit version src;
|
||||
pname =
|
||||
old.pname
|
||||
+ "-hyprland"
|
||||
+ (
|
||||
if hidpiXWayland
|
||||
then "-hidpi"
|
||||
else ""
|
||||
)
|
||||
+ (
|
||||
if nvidiaPatches
|
||||
then "-nvidia"
|
||||
else ""
|
||||
);
|
||||
patches =
|
||||
(old.patches or [])
|
||||
++ (lib.optionals (enableXWayland && hidpiXWayland) [
|
||||
(fetchpatch {
|
||||
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
|
||||
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
|
||||
})
|
||||
(fetchpatch {
|
||||
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
|
||||
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
|
||||
revert = true;
|
||||
})
|
||||
]);
|
||||
postPatch =
|
||||
(old.postPatch or "")
|
||||
+ (
|
||||
if nvidiaPatches
|
||||
then ''
|
||||
substituteInPlace render/gles2/renderer.c --replace "glFlush();" "glFinish();"
|
||||
''
|
||||
else ""
|
||||
);
|
||||
}))
|
||||
.override {
|
||||
xwayland = xwayland.overrideAttrs (old: {
|
||||
patches =
|
||||
(old.patches or [])
|
||||
++ (lib.optionals hidpiXWayland [
|
||||
./xwayland-vsync.patch
|
||||
./xwayland-hidpi.patch
|
||||
]);
|
||||
});
|
||||
}
|
@@ -198,6 +198,9 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRCursor->events.touch_down, &Events::listen_touchBegin, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.touch_up, &Events::listen_touchEnd, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.touch_motion, &Events::listen_touchUpdate, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.touch_frame, &Events::listen_touchFrame, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.hold_begin, &Events::listen_holdBegin, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.hold_end, &Events::listen_holdEnd, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
|
||||
addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat");
|
||||
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat");
|
||||
@@ -237,14 +240,14 @@ void CCompositor::cleanup() {
|
||||
|
||||
// accumulate all PIDs for killing, also request closing.
|
||||
for (auto& w : m_vWindows) {
|
||||
m_dProcessPIDsOnShutdown.push_back(w->getPID());
|
||||
if (w->m_bIsMapped || !w->m_bIsX11)
|
||||
m_dProcessPIDsOnShutdown.push_back(w->getPID());
|
||||
|
||||
closeWindow(w.get());
|
||||
}
|
||||
|
||||
// end threads
|
||||
g_pEventManager->m_tThread = std::thread();
|
||||
HyprCtl::tThread = std::thread();
|
||||
|
||||
m_vWorkspaces.clear();
|
||||
m_vWindows.clear();
|
||||
@@ -275,7 +278,7 @@ void CCompositor::startCompositor() {
|
||||
//
|
||||
Debug::log(LOG, "Creating the CHyprError!");
|
||||
g_pHyprError = std::make_unique<CHyprError>();
|
||||
|
||||
|
||||
Debug::log(LOG, "Creating the KeybindManager!");
|
||||
g_pKeybindManager = std::make_unique<CKeybindManager>();
|
||||
|
||||
@@ -453,10 +456,17 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->m_bHidden && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -516,12 +526,43 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned windows on top of floating regardless
|
||||
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 && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus && (*w)->m_bPinned) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
return w->get();
|
||||
|
||||
if (!(*w)->m_bIsX11) {
|
||||
wlr_surface* resultSurf = nullptr;
|
||||
Vector2D origin = (*w)->m_vRealPosition.vec();
|
||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||
wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data);
|
||||
|
||||
if (resultSurf)
|
||||
return w->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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_bX11ShouldntFocus) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bPinned) {
|
||||
// OR windows should add focus to parent
|
||||
if ((*w)->m_bX11ShouldntFocus && (*w)->m_iX11Type != 2)
|
||||
continue;
|
||||
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) {
|
||||
|
||||
if ((*w)->m_iX11Type == 2) {
|
||||
// Override Redirect
|
||||
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
||||
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
||||
}
|
||||
|
||||
return w->get();
|
||||
}
|
||||
|
||||
if (!(*w)->m_bIsX11) {
|
||||
wlr_surface* resultSurf = nullptr;
|
||||
@@ -532,7 +573,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
if (resultSurf)
|
||||
return w->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
@@ -573,10 +614,17 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID))
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -592,7 +640,13 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->m_bHidden && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -607,7 +661,7 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
||||
RASSERT(!pWindow->m_bIsX11, "Cannot call vectorWindowToSurface on an X11 window!");
|
||||
|
||||
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
||||
|
||||
|
||||
double subx, suby;
|
||||
|
||||
// calc for oversized windows... fucking bullshit, again.
|
||||
@@ -675,6 +729,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned)
|
||||
pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace;
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
g_pKeybindManager->changeworkspace("[internal]" + std::to_string(pWindow->m_iWorkspaceID));
|
||||
|
||||
@@ -702,7 +759,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
|
||||
|
||||
// do pointer focus too
|
||||
// do pointer focus too
|
||||
const auto POINTERLOCAL = g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.goalv();
|
||||
wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y);
|
||||
|
||||
@@ -730,7 +787,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
g_pInputManager->m_sIMERelay.onKeyboardFocus(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat);
|
||||
|
||||
@@ -784,7 +841,7 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
||||
|
||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
|
||||
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
|
||||
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
|
||||
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped) || (*it)->alpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
|
||||
@@ -820,7 +877,7 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->activeWorkspace == w)
|
||||
return true;
|
||||
|
||||
|
||||
if (m->specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
}
|
||||
@@ -1057,7 +1114,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectWindow = w.get();
|
||||
@@ -1066,7 +1123,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectWindow = w.get();
|
||||
@@ -1076,7 +1133,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectWindow = w.get();
|
||||
@@ -1086,7 +1143,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectWindow = w.get();
|
||||
@@ -1109,7 +1166,7 @@ void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclud
|
||||
}
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
|
||||
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) {
|
||||
bool gotToWindow = false;
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() != pWindow && !gotToWindow)
|
||||
@@ -1120,19 +1177,19 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden && (!focusableOnly || !w->m_bNoFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden && (!focusableOnly || !w->m_bNoFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow) {
|
||||
CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) {
|
||||
bool gotToWindow = false;
|
||||
for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
|
||||
if (it->get() != pWindow && !gotToWindow)
|
||||
@@ -1143,12 +1200,12 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
|
||||
if ((*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden && (!focusableOnly || !(*it)->m_bNoFocus))
|
||||
return it->get();
|
||||
}
|
||||
|
||||
for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
|
||||
if (it->get() != pWindow && (*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
|
||||
if (it->get() != pWindow && (*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden && (!focusableOnly || !(*it)->m_bNoFocus))
|
||||
return it->get();
|
||||
}
|
||||
|
||||
@@ -1232,7 +1289,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectMonitor = m.get();
|
||||
@@ -1241,7 +1298,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectMonitor = m.get();
|
||||
@@ -1251,7 +1308,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectMonitor = m.get();
|
||||
@@ -1261,7 +1318,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
if (INTERSECTLEN > longestIntersect) {
|
||||
longestIntersect = INTERSECTLEN;
|
||||
longestIntersectMonitor = m.get();
|
||||
@@ -1398,6 +1455,17 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
||||
}
|
||||
}
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pMonitorA->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = PWORKSPACEB->m_iID;
|
||||
}
|
||||
|
||||
if (w->m_iWorkspaceID == pMonitorB->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = PWORKSPACEA->m_iID;
|
||||
}
|
||||
}
|
||||
|
||||
pMonitorA->activeWorkspace = PWORKSPACEB->m_iID;
|
||||
pMonitorB->activeWorkspace = PWORKSPACEA->m_iID;
|
||||
|
||||
@@ -1430,6 +1498,9 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
|
||||
if (isDirection(name)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorInDirection(name[0]);
|
||||
return PMONITOR;
|
||||
@@ -1535,9 +1606,12 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_iID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
|
||||
if (w->m_iID > highestID)
|
||||
highestID = w->m_iID;
|
||||
}
|
||||
@@ -1549,18 +1623,38 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
if (!windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
focusWindow(pWindow);
|
||||
if (pWindow->m_bPinned) {
|
||||
Debug::log(LOG, "Pinned windows cannot be fullscreen'd");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace");
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID) {
|
||||
w->m_bCreatedOverFullscreen = false;
|
||||
if (w.get() != pWindow && !w->m_bFadingOut && !w->m_bPinned)
|
||||
w->m_fAlpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (!ls->fadingOut)
|
||||
ls->alpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
|
||||
|
||||
forceReportSizesToWindowsOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
@@ -1587,7 +1681,7 @@ CWindow* CCompositor::getX11Parent(CWindow* pWindow) {
|
||||
if (w->m_uSurface.xwayland == pWindow->m_uSurface.xwayland->parent)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1662,25 +1756,6 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wl_event_source* hyprCtlTickSource = nullptr;
|
||||
|
||||
int hyprCtlTick(void* data) {
|
||||
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
|
||||
|
||||
wl_event_source_timer_update(hyprCtlTickSource, 16); // tick it 60/s, should be enough.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CCompositor::startHyprCtlTick() {
|
||||
if (hyprCtlTickSource)
|
||||
return;
|
||||
|
||||
hyprCtlTickSource = wl_event_loop_add_timer(m_sWLEventLoop, hyprCtlTick, nullptr);
|
||||
|
||||
wl_event_source_timer_update(hyprCtlTickSource, 16);
|
||||
}
|
||||
|
||||
void CCompositor::warpCursorTo(const Vector2D& pos) {
|
||||
|
||||
// warpCursorTo should only be used for warps that
|
||||
@@ -1692,6 +1767,10 @@ void CCompositor::warpCursorTo(const Vector2D& pos) {
|
||||
return;
|
||||
|
||||
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y);
|
||||
|
||||
const auto PMONITORNEW = getMonitorFromVector(pos);
|
||||
if (PMONITORNEW != m_pLastMonitor)
|
||||
m_pLastMonitor = PMONITORNEW;
|
||||
}
|
||||
|
||||
SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) {
|
||||
@@ -1771,4 +1850,15 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
|
||||
g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.vec(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CCompositor::cursorOnReservedArea() {
|
||||
const auto PMONITOR = getMonitorFromCursor();
|
||||
|
||||
const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight;
|
||||
|
||||
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
return !VECINRECT(CURSORPOS, XY1.x, XY1.y, XY2.x, XY2.y);
|
||||
}
|
||||
|
@@ -86,13 +86,13 @@ public:
|
||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||
|
||||
void startCompositor();
|
||||
void startCompositor();
|
||||
void cleanup();
|
||||
|
||||
wlr_surface* m_pLastFocus = nullptr;
|
||||
CWindow* m_pLastWindow = nullptr;
|
||||
CMonitor* m_pLastMonitor = nullptr;
|
||||
|
||||
|
||||
SSeat m_sSeat;
|
||||
|
||||
bool m_bReadyToProcess = false;
|
||||
@@ -138,8 +138,8 @@ public:
|
||||
void cleanupFadingOut(const int& monid);
|
||||
CWindow* getWindowInDirection(CWindow*, char);
|
||||
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
|
||||
CWindow* getNextWindowOnWorkspace(CWindow*);
|
||||
CWindow* getPrevWindowOnWorkspace(CWindow*);
|
||||
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
||||
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
||||
int getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
CWindow* getConstraintWindow(SMouse*);
|
||||
@@ -164,17 +164,15 @@ public:
|
||||
void closeWindow(CWindow*);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
|
||||
bool cursorOnReservedArea();
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
void startHyprCtlTick();
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void setRandomSplash();
|
||||
void setRandomSplash();
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -193,4 +191,4 @@ inline std::map<std::string, xcb_atom_t> HYPRATOMS = {
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION")};
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION")};
|
||||
|
@@ -48,7 +48,7 @@ wlr_box CWindow::getFullWindowBoundingBox() {
|
||||
m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
|
||||
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
@@ -97,8 +97,7 @@ void CWindow::updateWindowDecos() {
|
||||
pid_t CWindow::getPID() {
|
||||
pid_t PID = -1;
|
||||
if (!m_bIsX11) {
|
||||
const auto CLIENT = wl_resource_get_client(m_uSurface.xdg->resource);
|
||||
wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr);
|
||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
||||
} else {
|
||||
PID = m_uSurface.xwayland->pid;
|
||||
}
|
||||
@@ -120,7 +119,7 @@ void CWindow::createToplevelHandle() {
|
||||
return; // don't create a toplevel
|
||||
|
||||
m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
|
||||
|
||||
|
||||
wlr_foreign_toplevel_handle_v1_set_app_id(m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(this).c_str());
|
||||
wlr_foreign_toplevel_handle_v1_output_enter(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iMonitorID)->output);
|
||||
wlr_foreign_toplevel_handle_v1_set_title(m_phForeignToplevel, m_szTitle.c_str());
|
||||
@@ -212,10 +211,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
if (m_iWorkspaceID != workspaceID) {
|
||||
m_iWorkspaceID = workspaceID;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
if (PWORKSPACE) {
|
||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +226,13 @@ CWindow* CWindow::X11TransientFor() {
|
||||
|
||||
auto PPARENT = g_pCompositor->getWindowFromSurface(m_uSurface.xwayland->parent->surface);
|
||||
|
||||
while (PPARENT->m_uSurface.xwayland->parent) {
|
||||
while (g_pCompositor->windowValidMapped(PPARENT) && PPARENT->m_uSurface.xwayland->parent) {
|
||||
PPARENT = g_pCompositor->getWindowFromSurface(PPARENT->m_uSurface.xwayland->parent->surface);
|
||||
}
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PPARENT))
|
||||
return nullptr;
|
||||
|
||||
return PPARENT;
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,8 @@ struct SWindowSpecialRenderData {
|
||||
// set by the layout
|
||||
bool rounding = true;
|
||||
bool border = true;
|
||||
};
|
||||
bool decorate = true;
|
||||
};
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
std::string animationStyle = "";
|
||||
@@ -119,6 +120,9 @@ public:
|
||||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
|
||||
// For pinned (sticky) windows
|
||||
bool m_bPinned = false;
|
||||
|
||||
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
||||
CWindow* m_pLastCycledWindow = nullptr;
|
||||
|
||||
@@ -142,6 +146,9 @@ public:
|
||||
// animated tint
|
||||
CAnimatedVariable m_fDimPercent;
|
||||
|
||||
// swallowing
|
||||
CWindow* m_pSwallowed = nullptr;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
|
@@ -48,7 +48,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["general:no_cursor_warps"].intValue = 0;
|
||||
|
||||
configValues["general:layout"].strValue = "dwindle";
|
||||
|
||||
|
||||
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
||||
configValues["misc:disable_splash_rendering"].intValue = 0;
|
||||
configValues["misc:no_vfr"].intValue = 1;
|
||||
@@ -57,6 +57,9 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["misc:always_follow_on_dnd"].intValue = 1;
|
||||
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
|
||||
configValues["misc:animate_manual_resizes"].intValue = 0;
|
||||
configValues["misc:disable_autoreload"].intValue = 0;
|
||||
configValues["misc:enable_swallow"].intValue = 0;
|
||||
configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -65,7 +68,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["debug:disable_logs"].intValue = 0;
|
||||
configValues["debug:disable_time"].intValue = 1;
|
||||
|
||||
configValues["decoration:rounding"].intValue = 1;
|
||||
configValues["decoration:rounding"].intValue = 0;
|
||||
configValues["decoration:blur"].intValue = 1;
|
||||
configValues["decoration:blur_size"].intValue = 8;
|
||||
configValues["decoration:blur_passes"].intValue = 1;
|
||||
@@ -80,7 +83,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["decoration:shadow_range"].intValue = 4;
|
||||
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||
configValues["decoration:shadow_offset"].strValue = "0 0";
|
||||
configValues["decoration:shadow_offset"].vecValue = Vector2D();
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
configValues["decoration:dim_inactive"].intValue = 0;
|
||||
@@ -141,7 +144,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["input:touchpad:tap-to-click"].intValue = 1;
|
||||
configValues["input:touchpad:drag_lock"].intValue = 0;
|
||||
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 1;
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 0;
|
||||
configValues["binds:scroll_event_delay"].intValue = 300;
|
||||
configValues["binds:workspace_back_and_forth"].intValue = 0;
|
||||
configValues["binds:allow_workspace_cycles"].intValue = 0;
|
||||
@@ -204,7 +207,7 @@ void CConfigManager::setDefaultAnimationVars() {
|
||||
// workspaces
|
||||
INITANIMCFG("specialWorkspace");
|
||||
}
|
||||
|
||||
|
||||
// init the values
|
||||
animationConfig["global"] = {
|
||||
false,
|
||||
@@ -235,7 +238,7 @@ void CConfigManager::setDefaultAnimationVars() {
|
||||
}
|
||||
|
||||
void CConfigManager::init() {
|
||||
|
||||
|
||||
loadConfigLoadVars();
|
||||
|
||||
const char* const ENVHOME = getenv("HOME");
|
||||
@@ -291,7 +294,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
|
||||
CONFIGENTRY->set = true;
|
||||
|
||||
if (CONFIGENTRY->intValue != -1) {
|
||||
if (CONFIGENTRY->intValue != -INT64_MAX) {
|
||||
try {
|
||||
if (VALUE.find("0x") == 0) {
|
||||
// Values with 0x are hex
|
||||
@@ -308,7 +311,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
} else if (CONFIGENTRY->floatValue != -1) {
|
||||
} else if (CONFIGENTRY->floatValue != -__FLT_MAX__) {
|
||||
try {
|
||||
CONFIGENTRY->floatValue = stof(VALUE);
|
||||
} catch (...) {
|
||||
@@ -322,6 +325,23 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
} else if (CONFIGENTRY->vecValue != Vector2D(-__FLT_MAX__, -__FLT_MAX__)) {
|
||||
try {
|
||||
if (const auto SPACEPOS = VALUE.find(' '); SPACEPOS != std::string::npos) {
|
||||
const auto X = VALUE.substr(0, SPACEPOS);
|
||||
const auto Y = VALUE.substr(SPACEPOS + 1);
|
||||
|
||||
if (isNumber(X, true) && isNumber(Y, true)) {
|
||||
CONFIGENTRY->vecValue = Vector2D(std::stof(X), std::stof(Y));
|
||||
}
|
||||
} else {
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
} catch (...) {
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,35 +405,15 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
// get the monitor config
|
||||
SMonitorRule newrule;
|
||||
|
||||
std::string curitem = "";
|
||||
const auto ARGS = CVarList(args);
|
||||
|
||||
std::string argZ = args;
|
||||
newrule.name = ARGS[0];
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = argZ.find_first_of(',');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = argZ.substr(0, idx);
|
||||
argZ = argZ.substr(idx + 1);
|
||||
} else {
|
||||
curitem = argZ;
|
||||
argZ = "";
|
||||
}
|
||||
};
|
||||
|
||||
nextItem();
|
||||
|
||||
newrule.name = curitem;
|
||||
|
||||
nextItem();
|
||||
|
||||
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved" || curitem == "transform") {
|
||||
if (curitem == "disable" || curitem == "disabled")
|
||||
if (ARGS[1] == "disable" || ARGS[1] == "disabled" || ARGS[1] == "addreserved" || ARGS[1] == "transform") {
|
||||
if (ARGS[1] == "disable" || ARGS[1] == "disabled")
|
||||
newrule.disabled = true;
|
||||
else if (curitem == "transform") {
|
||||
nextItem();
|
||||
|
||||
wl_output_transform transform = (wl_output_transform)std::stoi(curitem);
|
||||
else if (ARGS[1] == "transform") {
|
||||
wl_output_transform transform = (wl_output_transform)std::stoi(ARGS[2]);
|
||||
|
||||
// overwrite if exists
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
@@ -424,22 +424,14 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (curitem == "addreserved") {
|
||||
nextItem();
|
||||
} else if (ARGS[1] == "addreserved") {
|
||||
int top = std::stoi(ARGS[2]);
|
||||
|
||||
int top = std::stoi(curitem);
|
||||
int bottom = std::stoi(ARGS[3]);
|
||||
|
||||
nextItem();
|
||||
int left = std::stoi(ARGS[4]);
|
||||
|
||||
int bottom = std::stoi(curitem);
|
||||
|
||||
nextItem();
|
||||
|
||||
int left = std::stoi(curitem);
|
||||
|
||||
nextItem();
|
||||
|
||||
int right = std::stoi(curitem);
|
||||
int right = std::stoi(ARGS[5]);
|
||||
|
||||
m_mAdditionalReservedAreas[newrule.name] = {top, bottom, left, right};
|
||||
|
||||
@@ -449,7 +441,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
|
||||
|
||||
m_dMonitorRules.push_back(newrule);
|
||||
@@ -457,23 +449,25 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
return;
|
||||
}
|
||||
|
||||
if (curitem.find("pref") == 0) {
|
||||
if (ARGS[1].find("pref") == 0) {
|
||||
newrule.resolution = Vector2D();
|
||||
} else if (ARGS[1].find("highrr") == 0) {
|
||||
newrule.resolution = Vector2D(-1,-1);
|
||||
} else if (ARGS[1].find("highres") == 0) {
|
||||
newrule.resolution = Vector2D(-1,-2);
|
||||
} else {
|
||||
newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
|
||||
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@')));
|
||||
newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x')));
|
||||
newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@')));
|
||||
|
||||
if (curitem.contains("@"))
|
||||
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
|
||||
if (ARGS[1].contains("@"))
|
||||
newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1));
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
if (curitem.find("auto") == 0) {
|
||||
if (ARGS[2].find("auto") == 0) {
|
||||
newrule.offset = Vector2D(-1, -1);
|
||||
} else {
|
||||
newrule.offset.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
|
||||
newrule.offset.y = stoi(curitem.substr(curitem.find_first_of('x') + 1));
|
||||
newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x')));
|
||||
newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1));
|
||||
|
||||
if (newrule.offset.x < 0 || newrule.offset.y < 0) {
|
||||
parseError = "invalid offset. Offset cannot be negative.";
|
||||
@@ -481,22 +475,26 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
}
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
newrule.scale = stof(curitem);
|
||||
newrule.scale = stof(ARGS[3]);
|
||||
|
||||
if (newrule.scale < 0.25f) {
|
||||
parseError = "not a valid scale.";
|
||||
newrule.scale = 1;
|
||||
}
|
||||
|
||||
nextItem();
|
||||
int argno = 4;
|
||||
|
||||
if (curitem != "") {
|
||||
// warning for old cfg
|
||||
Debug::log(ERR, "Error in parsing rule for %s, possibly old config!", newrule.name.c_str());
|
||||
parseError = "Error in setting monitor rule. Are you using the old syntax? Confront the wiki.";
|
||||
return;
|
||||
while (ARGS[argno] != "") {
|
||||
if (ARGS[argno] == "mirror") {
|
||||
newrule.mirrorOf = ARGS[argno + 1];
|
||||
argno++;
|
||||
} else {
|
||||
Debug::log(ERR, "Config error: invalid monitor syntax");
|
||||
parseError = "invalid syntax at \"" + ARGS[argno] + "\"";
|
||||
return;
|
||||
}
|
||||
|
||||
argno++;
|
||||
}
|
||||
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
@@ -506,44 +504,27 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
}
|
||||
|
||||
void CConfigManager::handleBezier(const std::string& command, const std::string& args) {
|
||||
std::string curitem = "";
|
||||
const auto ARGS = CVarList(args);
|
||||
|
||||
std::string argZ = args;
|
||||
std::string bezierName = ARGS[0];
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = argZ.find_first_of(',');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = argZ.substr(0, idx);
|
||||
argZ = argZ.substr(idx + 1);
|
||||
} else {
|
||||
curitem = argZ;
|
||||
argZ = "";
|
||||
}
|
||||
};
|
||||
|
||||
nextItem();
|
||||
|
||||
std::string bezierName = curitem;
|
||||
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
if (ARGS[1] == "")
|
||||
parseError = "too few arguments";
|
||||
float p1x = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
float p1x = std::stof(ARGS[1]);
|
||||
|
||||
if (ARGS[2] == "")
|
||||
parseError = "too few arguments";
|
||||
float p1y = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
float p1y = std::stof(ARGS[2]);
|
||||
|
||||
if (ARGS[3] == "")
|
||||
parseError = "too few arguments";
|
||||
float p2x = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
float p2x = std::stof(ARGS[3]);
|
||||
|
||||
if (ARGS[4] == "")
|
||||
parseError = "too few arguments";
|
||||
float p2y = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem != "")
|
||||
float p2y = std::stof(ARGS[4]);
|
||||
|
||||
if (ARGS[5] != "")
|
||||
parseError = "too many arguments";
|
||||
|
||||
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
|
||||
@@ -561,29 +542,13 @@ void CConfigManager::setAnimForChildren(SAnimationPropertyConfig *const ANIM) {
|
||||
};
|
||||
|
||||
void CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
|
||||
std::string curitem = "";
|
||||
|
||||
std::string argZ = args;
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = argZ.find_first_of(',');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = argZ.substr(0, idx);
|
||||
argZ = argZ.substr(idx + 1);
|
||||
} else {
|
||||
curitem = argZ;
|
||||
argZ = "";
|
||||
}
|
||||
};
|
||||
|
||||
nextItem();
|
||||
const auto ARGS = CVarList(args);
|
||||
|
||||
// Master on/off
|
||||
|
||||
// anim name
|
||||
const auto ANIMNAME = curitem;
|
||||
|
||||
const auto ANIMNAME = ARGS[0];
|
||||
|
||||
const auto PANIM = animationConfig.find(ANIMNAME);
|
||||
|
||||
if (PANIM == animationConfig.end()) {
|
||||
@@ -594,20 +559,16 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
||||
PANIM->second.overriden = true;
|
||||
PANIM->second.pValues = &PANIM->second;
|
||||
|
||||
nextItem();
|
||||
|
||||
// on/off
|
||||
PANIM->second.internalEnabled = curitem == "1";
|
||||
PANIM->second.internalEnabled = ARGS[1] == "1";
|
||||
|
||||
if (curitem != "0" && curitem != "1") {
|
||||
if (ARGS[1] != "0" && ARGS[1] != "1") {
|
||||
parseError = "invalid animation on/off state";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
// speed
|
||||
if (isNumber(curitem, true)) {
|
||||
PANIM->second.internalSpeed = std::stof(curitem);
|
||||
if (isNumber(ARGS[2], true)) {
|
||||
PANIM->second.internalSpeed = std::stof(ARGS[2]);
|
||||
|
||||
if (PANIM->second.internalSpeed <= 0) {
|
||||
parseError = "invalid speed";
|
||||
@@ -618,23 +579,19 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
||||
parseError = "invalid speed";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
// curve
|
||||
PANIM->second.internalBezier = curitem;
|
||||
PANIM->second.internalBezier = ARGS[3];
|
||||
|
||||
if (!g_pAnimationManager->bezierExists(curitem)) {
|
||||
if (!g_pAnimationManager->bezierExists(ARGS[3])) {
|
||||
parseError = "no such bezier";
|
||||
PANIM->second.internalBezier = "default";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
// style
|
||||
PANIM->second.internalStyle = curitem;
|
||||
PANIM->second.internalStyle = ARGS[4];
|
||||
|
||||
if (curitem != "") {
|
||||
const auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, curitem);
|
||||
if (ARGS[4] != "") {
|
||||
const auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]);
|
||||
|
||||
if (ERR != "")
|
||||
parseError = ERR;
|
||||
@@ -652,15 +609,18 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
bool locked = false;
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
const auto ARGS = command.substr(4);
|
||||
bool mouse = false;
|
||||
const auto BINDARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : ARGS) {
|
||||
for (auto& arg : BINDARGS) {
|
||||
if (arg == 'l') {
|
||||
locked = true;
|
||||
} else if (arg == 'r') {
|
||||
release = true;
|
||||
} else if (arg == 'e') {
|
||||
repeat = true;
|
||||
} else if (arg == 'm') {
|
||||
mouse = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
@@ -672,19 +632,35 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
return;
|
||||
}
|
||||
|
||||
auto valueCopy = value;
|
||||
if (mouse && (repeat || release || locked)) {
|
||||
parseError = "flag m is exclusive";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(",")));
|
||||
const auto MODSTR = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
const auto ARGS = CVarList(value, 4);
|
||||
|
||||
const auto KEY = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
if ((ARGS.size() < 3 && !mouse) || (ARGS.size() < 3 && mouse)) {
|
||||
parseError = "bind: too few args";
|
||||
return;
|
||||
} else if ((ARGS.size() > 4 && !mouse) || (ARGS.size() > 3 && mouse)) {
|
||||
parseError = "bind: too many args";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto HANDLER = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
|
||||
const auto MODSTR = ARGS[0];
|
||||
|
||||
const auto COMMAND = valueCopy;
|
||||
const auto KEY = ARGS[1];
|
||||
|
||||
auto HANDLER = ARGS[2];
|
||||
|
||||
const auto COMMAND = mouse ? HANDLER : ARGS[3];
|
||||
|
||||
if (mouse)
|
||||
HANDLER = "mouse";
|
||||
|
||||
// to lower
|
||||
std::transform(HANDLER.begin(), HANDLER.end(), HANDLER.begin(), ::tolower);
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(HANDLER);
|
||||
|
||||
@@ -707,35 +683,24 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
|
||||
auto valueCopy = value;
|
||||
const auto ARGS = CVarList(value);
|
||||
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(",")));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
|
||||
|
||||
const auto KEY = valueCopy;
|
||||
const auto KEY = ARGS[1];
|
||||
|
||||
g_pKeybindManager->removeKeybind(MOD, KEY);
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
||||
const auto RULE = value.substr(0, value.find_first_of(","));
|
||||
const auto VALUE = value.substr(value.find_first_of(",") + 1);
|
||||
|
||||
// check rule and value
|
||||
if (RULE == "" || VALUE == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
// verify we support a rule
|
||||
if (RULE != "float"
|
||||
bool windowRuleValid(const std::string& RULE) {
|
||||
return !(RULE != "float"
|
||||
&& RULE != "tile"
|
||||
&& RULE.find("opacity") != 0
|
||||
&& RULE.find("move") != 0
|
||||
@@ -748,21 +713,100 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
||||
&& RULE != "opaque"
|
||||
&& RULE != "forceinput"
|
||||
&& RULE != "fullscreen"
|
||||
&& RULE != "pin"
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("rounding") != 0
|
||||
&& RULE.find("workspace") != 0) {
|
||||
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
||||
parseError = "Invalid rule found: " + RULE;
|
||||
return;
|
||||
}
|
||||
&& RULE.find("workspace") != 0);
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
||||
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(",")));
|
||||
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(",") + 1));
|
||||
|
||||
// check rule and value
|
||||
if (RULE == "" || VALUE == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
// verify we support a rule
|
||||
if (!windowRuleValid(RULE)) {
|
||||
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
|
||||
parseError = "Invalid rule found: " + RULE;
|
||||
return;
|
||||
}
|
||||
|
||||
m_dWindowRules.push_back({RULE, VALUE});
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
|
||||
const auto RULE = value.substr(0, value.find_first_of(","));
|
||||
const auto VALUE = value.substr(value.find_first_of(",") + 1);
|
||||
|
||||
if (!windowRuleValid(RULE)) {
|
||||
Debug::log(ERR, "Invalid rulev2 found: %s", RULE.c_str());
|
||||
parseError = "Invalid rulev2 found: " + RULE;
|
||||
return;
|
||||
}
|
||||
|
||||
// now we estract shit from the value
|
||||
SWindowRule rule;
|
||||
rule.v2 = true;
|
||||
rule.szRule = RULE;
|
||||
rule.szValue = VALUE;
|
||||
|
||||
const auto TITLEPOS = VALUE.find("title:");
|
||||
const auto CLASSPOS = VALUE.find("class:");
|
||||
const auto X11POS = VALUE.find("xwayland:");
|
||||
const auto FLOATPOS = VALUE.find("floating:");
|
||||
|
||||
if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos) {
|
||||
Debug::log(ERR, "Invalid rulev2 syntax: %s", VALUE.c_str());
|
||||
parseError = "Invalid rulev2 syntax: " + VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
auto extract = [&](size_t pos) -> std::string {
|
||||
std::string result;
|
||||
result = VALUE.substr(pos);
|
||||
|
||||
size_t min = 999999;
|
||||
if (TITLEPOS > pos && TITLEPOS < min) min = TITLEPOS;
|
||||
if (CLASSPOS > pos && CLASSPOS < min) min = CLASSPOS;
|
||||
if (X11POS > pos && X11POS < min) min = X11POS;
|
||||
if (FLOATPOS > pos && FLOATPOS < min) min = FLOATPOS;
|
||||
|
||||
result = result.substr(0, min - pos);
|
||||
|
||||
result = removeBeginEndSpacesTabs(result);
|
||||
|
||||
if (result.back() == ',')
|
||||
result.pop_back();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
if (CLASSPOS != std::string::npos) {
|
||||
rule.szClass = extract(CLASSPOS + 6);
|
||||
}
|
||||
|
||||
if (TITLEPOS != std::string::npos) {
|
||||
rule.szTitle = extract(TITLEPOS + 6);
|
||||
}
|
||||
|
||||
if (X11POS != std::string::npos) {
|
||||
rule.bX11 = extract(X11POS + 9) == "1" ? 1 : 0;
|
||||
}
|
||||
|
||||
if (FLOATPOS != std::string::npos) {
|
||||
rule.bFloating = extract(FLOATPOS + 9) == "1" ? 1 : 0;
|
||||
}
|
||||
|
||||
m_dWindowRules.push_back(rule);
|
||||
}
|
||||
|
||||
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
||||
if (value.find("remove,") == 0) {
|
||||
const auto TOREMOVE = value.substr(7);
|
||||
const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7));
|
||||
m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
|
||||
return;
|
||||
}
|
||||
@@ -771,20 +815,18 @@ void CConfigManager::handleBlurLS(const std::string& command, const std::string&
|
||||
}
|
||||
|
||||
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
|
||||
|
||||
const auto DISPLAY = value.substr(0, value.find_first_of(','));
|
||||
const auto WORKSPACE = value.substr(value.find_first_of(',') + 1);
|
||||
const auto ARGS = CVarList(value);
|
||||
|
||||
for (auto& mr : m_dMonitorRules) {
|
||||
if (mr.name == DISPLAY) {
|
||||
mr.defaultWorkspace = WORKSPACE;
|
||||
if (mr.name == ARGS[0]) {
|
||||
mr.defaultWorkspace = ARGS[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::handleSubmap(const std::string& command, const std::string& submap) {
|
||||
if (submap == "reset")
|
||||
if (submap == "reset")
|
||||
m_szCurrentSubmap = "";
|
||||
else
|
||||
m_szCurrentSubmap = submap;
|
||||
@@ -844,6 +886,19 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::handleBindWS(const std::string& command, const std::string& value) {
|
||||
const auto ARGS = CVarList(value);
|
||||
|
||||
const auto FOUND = std::find_if(boundWorkspaces.begin(), boundWorkspaces.end(), [&](const auto& other) { return other.first == ARGS[0]; });
|
||||
|
||||
if (FOUND != boundWorkspaces.end()) {
|
||||
FOUND->second = ARGS[1];
|
||||
return;
|
||||
}
|
||||
|
||||
boundWorkspaces.push_back({ARGS[0], ARGS[1]});
|
||||
}
|
||||
|
||||
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE, bool dynamic) {
|
||||
if (dynamic) {
|
||||
parseError = "";
|
||||
@@ -866,11 +921,13 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
|
||||
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
|
||||
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
|
||||
else if (COMMAND == "windowrulev2") handleWindowRuleV2(COMMAND, VALUE);
|
||||
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
|
||||
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
|
||||
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
||||
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
|
||||
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
|
||||
else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE);
|
||||
else
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
|
||||
@@ -944,9 +1001,9 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
|
||||
if (LASTSEP == std::string::npos || currentCategory.contains("device"))
|
||||
currentCategory = "";
|
||||
else
|
||||
else
|
||||
currentCategory = currentCategory.substr(0, LASTSEP);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -971,7 +1028,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
Debug::log(LOG, "Reloading the config!");
|
||||
parseError = ""; // reset the error
|
||||
currentCategory = ""; // reset the category
|
||||
|
||||
|
||||
// reset all vars before loading
|
||||
setDefaultVars();
|
||||
m_dMonitorRules.clear();
|
||||
@@ -982,6 +1039,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
configDynamicVars.clear();
|
||||
deviceConfigs.clear();
|
||||
m_dBlurLSNamespaces.clear();
|
||||
boundWorkspaces.clear();
|
||||
setDefaultAnimationVars(); // reset anims
|
||||
|
||||
// paths
|
||||
@@ -999,7 +1057,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
}
|
||||
|
||||
configPaths.push_back(CONFIGPATH);
|
||||
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(CONFIGPATH);
|
||||
|
||||
@@ -1104,14 +1162,14 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
// update layout
|
||||
g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue);
|
||||
|
||||
// mark blur dirty
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
// mark blur dirty
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(m.get());
|
||||
|
||||
// Force the compositor to fully re-render all monitors
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
// Force the compositor to fully re-render all monitors
|
||||
m->forceFullFrames = 2;
|
||||
|
||||
}
|
||||
|
||||
// Reset no monitor reload
|
||||
m_bNoMonitorReload = false;
|
||||
}
|
||||
@@ -1279,22 +1337,53 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
|
||||
for (auto& rule : m_dWindowRules) {
|
||||
// check if we have a matching rule
|
||||
try {
|
||||
if (rule.szValue.find("title:") == 0) {
|
||||
// we have a title rule.
|
||||
std::regex RULECHECK(rule.szValue.substr(6));
|
||||
if (!rule.v2) {
|
||||
try {
|
||||
if (rule.szValue.find("title:") == 0) {
|
||||
// we have a title rule.
|
||||
std::regex RULECHECK(rule.szValue.substr(6));
|
||||
|
||||
if (!std::regex_search(title, RULECHECK))
|
||||
continue;
|
||||
} else {
|
||||
std::regex classCheck(rule.szValue);
|
||||
if (!std::regex_search(title, RULECHECK))
|
||||
continue;
|
||||
} else {
|
||||
std::regex classCheck(rule.szValue);
|
||||
|
||||
if (!std::regex_search(appidclass, classCheck))
|
||||
continue;
|
||||
if (!std::regex_search(appidclass, classCheck))
|
||||
continue;
|
||||
}
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (rule.szClass != "") {
|
||||
std::regex RULECHECK(rule.szClass);
|
||||
|
||||
if (!std::regex_search(appidclass, RULECHECK))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.szTitle != "") {
|
||||
std::regex RULECHECK(rule.szTitle);
|
||||
|
||||
if (!std::regex_search(title, RULECHECK))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.bX11 != -1) {
|
||||
if (pWindow->m_bIsX11 != rule.bX11)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.bFloating != -1) {
|
||||
if (pWindow->m_bIsFloating != rule.bFloating)
|
||||
continue;
|
||||
}
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
||||
continue;
|
||||
}
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// applies. Read the rule and behave accordingly
|
||||
@@ -1334,10 +1423,16 @@ void CConfigManager::performMonitorReload() {
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
auto rule = getMonitorRuleFor(m->szName);
|
||||
|
||||
// ensure mirror
|
||||
m->setMirror(rule.mirrorOf);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(m->ID);
|
||||
}
|
||||
|
||||
if (overAgain)
|
||||
@@ -1397,3 +1492,15 @@ void CConfigManager::addParseError(const std::string& err) {
|
||||
if (parseError == "")
|
||||
parseError = err;
|
||||
}
|
||||
|
||||
CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
|
||||
for (auto&[ws, mon] : boundWorkspaces) {
|
||||
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return g_pCompositor->getMonitorFromString(mon);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -20,9 +20,10 @@
|
||||
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
||||
|
||||
struct SConfigValue {
|
||||
int64_t intValue = -1;
|
||||
float floatValue = -1;
|
||||
int64_t intValue = -INT64_MAX;
|
||||
float floatValue = -__FLT_MAX__;
|
||||
std::string strValue = "";
|
||||
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
|
||||
|
||||
bool set = false; // used for device configs
|
||||
};
|
||||
@@ -36,6 +37,7 @@ struct SMonitorRule {
|
||||
std::string defaultWorkspace = "";
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
@@ -48,6 +50,12 @@ struct SMonitorAdditionalReservedArea {
|
||||
struct SWindowRule {
|
||||
std::string szRule;
|
||||
std::string szValue;
|
||||
|
||||
bool v2 = false;
|
||||
std::string szTitle;
|
||||
std::string szClass;
|
||||
int bX11 = -1; // -1 means "ANY"
|
||||
int bFloating = -1;
|
||||
};
|
||||
|
||||
struct SAnimationPropertyConfig {
|
||||
@@ -62,6 +70,48 @@ struct SAnimationPropertyConfig {
|
||||
SAnimationPropertyConfig* pParentAnimation = nullptr;
|
||||
};
|
||||
|
||||
class CVarList {
|
||||
public:
|
||||
CVarList(const std::string& in, long unsigned int lastArgNo = 0) {
|
||||
std::string curitem = "";
|
||||
std::string argZ = in;
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(',');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = argZ.substr(0, idx);
|
||||
argZ = argZ.substr(idx + 1);
|
||||
} else {
|
||||
curitem = argZ;
|
||||
argZ = STRVAL_EMPTY;
|
||||
}
|
||||
};
|
||||
|
||||
nextItem();
|
||||
|
||||
while (curitem != STRVAL_EMPTY) {
|
||||
m_vArgs.push_back(removeBeginEndSpacesTabs(curitem));
|
||||
nextItem();
|
||||
}
|
||||
};
|
||||
|
||||
~CVarList() = default;
|
||||
|
||||
int size() const {
|
||||
return m_vArgs.size();
|
||||
}
|
||||
|
||||
std::string operator[](const long unsigned int& idx) const {
|
||||
if (idx >= m_vArgs.size())
|
||||
return "";
|
||||
return m_vArgs[idx];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_vArgs;
|
||||
};
|
||||
|
||||
class CConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
@@ -87,6 +137,8 @@ public:
|
||||
|
||||
SMonitorRule getMonitorRuleFor(std::string);
|
||||
|
||||
CMonitor* getBoundMonitorForWS(std::string);
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
@@ -123,6 +175,8 @@ private:
|
||||
|
||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
@@ -151,12 +205,14 @@ private:
|
||||
void handleBind(const std::string&, const std::string&);
|
||||
void handleUnbind(const std::string&, const std::string&);
|
||||
void handleWindowRule(const std::string&, const std::string&);
|
||||
void handleWindowRuleV2(const std::string&, const std::string&);
|
||||
void handleDefaultWorkspace(const std::string&, const std::string&);
|
||||
void handleBezier(const std::string&, const std::string&);
|
||||
void handleAnimation(const std::string&, const std::string&);
|
||||
void handleSource(const std::string&, const std::string&);
|
||||
void handleSubmap(const std::string&, const std::string&);
|
||||
void handleBlurLS(const std::string&, const std::string&);
|
||||
void handleBindWS(const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
@@ -83,6 +83,10 @@ gestures {
|
||||
#windowrule=pseudo,abc
|
||||
#windowrule=monitor 0,xyz
|
||||
|
||||
# some nice mouse binds
|
||||
bindm=SUPER,mouse:272,movewindow
|
||||
bindm=SUPER,mouse:273,resizewindow
|
||||
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,RETURN,exec,alacritty
|
||||
|
@@ -17,7 +17,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat(
|
||||
R"#({
|
||||
@@ -85,7 +85,10 @@ R"#({
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %s
|
||||
"xwayland": %s,
|
||||
"pinned": %s,
|
||||
"fullscreen": %s,
|
||||
"fullscreenMode": %i
|
||||
},)#",
|
||||
w.get(),
|
||||
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
|
||||
@@ -96,7 +99,10 @@ R"#({
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
|
||||
w->getPID(),
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false")
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false"),
|
||||
(w->m_bPinned ? "true" : "false"),
|
||||
(w->m_bIsFullscreen ? "true" : "false"),
|
||||
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -109,9 +115,9 @@ R"#({
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped) {
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
|
||||
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11);
|
||||
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: %i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\n",
|
||||
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,19 +130,25 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
const auto PLASTW = w->getLastFocusedWindow();
|
||||
|
||||
result += getFormat(
|
||||
R"#({
|
||||
"id": %i,
|
||||
"name": "%s",
|
||||
"monitor": "%s",
|
||||
"windows": %i,
|
||||
"hasfullscreen": %s
|
||||
"hasfullscreen": %s,
|
||||
"lastwindow": "0x%x",
|
||||
"lastwindowtitle": "%s"
|
||||
},)#",
|
||||
w->m_iID,
|
||||
escapeJSONStrings(w->m_szName).c_str(),
|
||||
escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
|
||||
g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false")
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"),
|
||||
PLASTW,
|
||||
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : ""
|
||||
);
|
||||
}
|
||||
|
||||
@@ -146,8 +158,9 @@ R"#({
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
|
||||
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
|
||||
const auto PLASTW = w->getLastFocusedWindow();
|
||||
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n",
|
||||
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -205,12 +218,12 @@ R"#("%s": {
|
||||
"levels": {
|
||||
)#",
|
||||
escapeJSONStrings(mon->szName).c_str()
|
||||
);
|
||||
);
|
||||
|
||||
int layerLevel = 0;
|
||||
for (auto& level : mon->m_aLayerSurfaceLists) {
|
||||
result += getFormat(
|
||||
R"#(
|
||||
R"#(
|
||||
"%i": [
|
||||
)#",
|
||||
layerLevel
|
||||
@@ -255,7 +268,7 @@ R"#( {
|
||||
result.pop_back();
|
||||
|
||||
result += "\n}\n";
|
||||
|
||||
|
||||
} else {
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat("Monitor %s:\n", mon->szName.c_str());
|
||||
@@ -287,10 +300,12 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
"name": "%s",
|
||||
"defaultSpeed": %f
|
||||
},)#",
|
||||
&m,
|
||||
escapeJSONStrings(m.mouse->name).c_str()
|
||||
escapeJSONStrings(m.mouse->name).c_str(),
|
||||
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f
|
||||
);
|
||||
}
|
||||
|
||||
@@ -370,6 +385,23 @@ R"#( {
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"touch\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTouchDevices) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
},)#",
|
||||
&d,
|
||||
d.pWlrDevice ? d.pWlrDevice->name : ""
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result[result.size() - 1] == ',')
|
||||
result.pop_back();
|
||||
@@ -381,7 +413,7 @@ R"#( {
|
||||
result += "mice:\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.mouse->name, (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
@@ -404,6 +436,12 @@ R"#( {
|
||||
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||
}
|
||||
|
||||
result += "\n\nTouch:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTouchDevices) {
|
||||
result += getFormat("\tTouch Device at %x:\n\t\t%s\n", &d, d.pWlrDevice ? d.pWlrDevice->name : "");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -503,14 +541,14 @@ std::string dispatchKeyword(std::string in) {
|
||||
|
||||
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
|
||||
|
||||
if (retval == "")
|
||||
if (retval == "")
|
||||
return "ok";
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string reloadRequest(std::string request) {
|
||||
|
||||
|
||||
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
|
||||
|
||||
g_pConfigManager->m_bForceReload = true;
|
||||
@@ -519,6 +557,8 @@ std::string reloadRequest(std::string request) {
|
||||
g_pConfigManager->m_bNoMonitorReload = true;
|
||||
}
|
||||
|
||||
g_pConfigManager->tick();
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@@ -669,7 +709,7 @@ std::string getReply(std::string request) {
|
||||
}
|
||||
|
||||
sepIndex++;
|
||||
|
||||
|
||||
if (c == 'j')
|
||||
format = HyprCtl::FORMAT_JSON;
|
||||
}
|
||||
@@ -712,9 +752,21 @@ std::string getReply(std::string request) {
|
||||
return "unknown request";
|
||||
}
|
||||
|
||||
void HyprCtl::tickHyprCtl() {
|
||||
if (!requestMade)
|
||||
return;
|
||||
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
||||
char readBuffer[1024];
|
||||
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
|
||||
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
|
||||
|
||||
std::string request(readBuffer);
|
||||
|
||||
std::string reply = "";
|
||||
|
||||
@@ -725,88 +777,38 @@ void HyprCtl::tickHyprCtl() {
|
||||
reply = "Err: " + std::string(e.what());
|
||||
}
|
||||
|
||||
request = reply;
|
||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
||||
|
||||
requestMade = false;
|
||||
requestReady = true;
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
||||
g_pConfigManager->ensureDPMS();
|
||||
}
|
||||
}
|
||||
|
||||
std::string getRequestFromThread(std::string rq) {
|
||||
|
||||
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
HyprCtl::request = rq;
|
||||
HyprCtl::requestMade = true;
|
||||
|
||||
while (!HyprCtl::requestReady) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
HyprCtl::requestReady = false;
|
||||
HyprCtl::requestMade = false;
|
||||
|
||||
std::string toReturn = HyprCtl::request;
|
||||
|
||||
HyprCtl::request = "";
|
||||
|
||||
return toReturn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HyprCtl::startHyprCtlSocket() {
|
||||
tThread = std::thread([&]() {
|
||||
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SOCKET < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
if (iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||
|
||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
|
||||
// 10 max queued.
|
||||
listen(SOCKET, 10);
|
||||
bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
// 10 max queued.
|
||||
listen(iSocketFD, 10);
|
||||
|
||||
char readBuffer[1024] = {0};
|
||||
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||
|
||||
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||
|
||||
while(1) {
|
||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
||||
if (ACCEPTEDCONNECTION < 0) {
|
||||
Debug::log(ERR, "Couldn't listen on the Hyprland Socket. (3) IPC will not work.");
|
||||
break;
|
||||
}
|
||||
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
|
||||
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
|
||||
|
||||
std::string request(readBuffer);
|
||||
|
||||
std::string reply = getRequestFromThread(request);
|
||||
|
||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
||||
|
||||
close(ACCEPTEDCONNECTION);
|
||||
}
|
||||
|
||||
close(SOCKET);
|
||||
});
|
||||
|
||||
tThread.detach();
|
||||
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
namespace HyprCtl {
|
||||
void startHyprCtlSocket();
|
||||
void tickHyprCtl();
|
||||
|
||||
// very simple thread-safe request method
|
||||
inline bool requestMade = false;
|
||||
@@ -15,7 +14,9 @@ namespace HyprCtl {
|
||||
|
||||
inline std::ifstream requestStream;
|
||||
|
||||
inline std::thread tThread;
|
||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
||||
|
||||
inline int iSocketFD = -1;
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
|
@@ -58,7 +58,7 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||
if (disableTime && !*disableTime) {
|
||||
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
|
||||
|
||||
|
||||
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
|
||||
|
||||
if (MILLIS > 99)
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#define PIXMAN_DAMAGE_FOREACH(region) int rectsNum = 0; \
|
||||
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
|
||||
for (int i = 0; i < rectsNum; ++i)
|
||||
|
||||
|
||||
|
||||
#define interface class
|
||||
|
||||
@@ -74,4 +74,4 @@
|
||||
#define GIT_DIRTY "?"
|
||||
#endif
|
||||
|
||||
#define SPECIAL_WORKSPACE_ID -99
|
||||
#define SPECIAL_WORKSPACE_ID -99
|
||||
|
@@ -72,7 +72,7 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
|
||||
g_pInputManager->newTouchDevice(DEVICE);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
|
||||
@@ -206,4 +206,16 @@ void Events::listener_touchEnd(wl_listener* listener, void* data) {
|
||||
|
||||
void Events::listener_touchUpdate(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onTouchMove((wlr_touch_motion_event*)data);
|
||||
}
|
||||
|
||||
void Events::listener_touchFrame(wl_listener* listener, void* data) {
|
||||
wlr_seat_touch_notify_frame(g_pCompositor->m_sSeat.seat);
|
||||
}
|
||||
|
||||
void Events::listener_holdBegin(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onPointerHoldBegin((wlr_pointer_hold_begin_event*)data);
|
||||
}
|
||||
|
||||
void Events::listener_holdEnd(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onPointerHoldEnd((wlr_pointer_hold_end_event*)data);
|
||||
}
|
@@ -67,7 +67,7 @@ namespace Events {
|
||||
LISTENER(mouseButton);
|
||||
LISTENER(mouseAxis);
|
||||
LISTENER(mouseFrame);
|
||||
|
||||
|
||||
LISTENER(newInput);
|
||||
|
||||
// Virt Ptr
|
||||
@@ -77,7 +77,7 @@ namespace Events {
|
||||
DYNLISTENFUNC(keyboardKey);
|
||||
DYNLISTENFUNC(keyboardMod);
|
||||
DYNLISTENFUNC(keyboardDestroy);
|
||||
|
||||
|
||||
DYNLISTENFUNC(commitConstraint);
|
||||
LISTENER(newConstraint);
|
||||
DYNLISTENFUNC(setConstraintRegion);
|
||||
@@ -152,4 +152,8 @@ namespace Events {
|
||||
LISTENER(touchBegin);
|
||||
LISTENER(touchEnd);
|
||||
LISTENER(touchUpdate);
|
||||
};
|
||||
LISTENER(touchFrame);
|
||||
|
||||
LISTENER(holdBegin);
|
||||
LISTENER(holdEnd);
|
||||
};
|
||||
|
@@ -133,8 +133,9 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
|
||||
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||
|
||||
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
|
||||
@@ -158,7 +159,7 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
|
||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
@@ -244,7 +245,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
|
||||
if (layersurface->layerSurface->current.committed != 0) {
|
||||
if (layersurface->layer != layersurface->layerSurface->current.layer) {
|
||||
|
||||
|
||||
for (auto it = PMONITOR->m_aLayerSurfaceLists[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
||||
if (it->get() == layersurface) {
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
|
||||
@@ -270,4 +271,4 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
|
||||
|
||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||
}
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ void Events::listener_requestDrag(wl_listener* listener, void* data) {
|
||||
}
|
||||
|
||||
void Events::listener_startDrag(wl_listener* listener, void* data) {
|
||||
|
||||
|
||||
if (g_pInputManager->m_sDrag.drag)
|
||||
return; // don't handle multiple drags
|
||||
|
||||
@@ -124,6 +124,9 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
|
||||
void Events::listener_destroyDrag(void* owner, void* data) {
|
||||
Debug::log(LOG, "Drag destroyed.");
|
||||
|
||||
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
|
||||
g_pHyprRenderer->damageBox(g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4);
|
||||
|
||||
g_pInputManager->m_sDrag.drag = nullptr;
|
||||
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
||||
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
||||
@@ -164,7 +167,7 @@ void Events::listener_commitDragIcon(void* owner, void* data) {
|
||||
|
||||
void Events::listener_InhibitActivate(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "Activated exclusive for %x.", g_pCompositor->m_sSeat.exclusiveClient);
|
||||
|
||||
|
||||
g_pInputManager->refocus();
|
||||
g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client;
|
||||
}
|
||||
@@ -192,7 +195,7 @@ void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
||||
|
||||
wlr_output_enable(EVENT->output, EVENT->mode == 1);
|
||||
|
||||
|
||||
if (!wlr_output_commit(EVENT->output))
|
||||
Debug::log(ERR, "Couldn't set power mode");
|
||||
}
|
||||
@@ -207,4 +210,4 @@ void Events::listener_newTextInput(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "New TextInput added!");
|
||||
|
||||
g_pInputManager->m_sIMERelay.onNewTextInput((wlr_text_input_v3*)data);
|
||||
}
|
||||
}
|
||||
|
@@ -99,7 +99,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||
return; // cannot draw on session inactive (different tty)
|
||||
}
|
||||
|
||||
|
||||
if (!PMONITOR->m_bEnabled)
|
||||
return;
|
||||
|
||||
@@ -190,7 +190,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
@@ -218,44 +218,51 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
if (PMONITOR->forceFullFrames > 10)
|
||||
PMONITOR->forceFullFrames = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: this is getting called with extents being 0,0,0,0 should it be?
|
||||
// potentially can save on resources.
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
if (PMONITOR->isMirror()) {
|
||||
g_pHyprOpenGL->renderMirrored();
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
Debug::log(LOG, "Mirror frame");
|
||||
} else {
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255, 0, 255, 100), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
damageBlinkCleanup++;
|
||||
if (damageBlinkCleanup > 3)
|
||||
damageBlinkCleanup = 0;
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
damageBlinkCleanup++;
|
||||
if (damageBlinkCleanup > 3)
|
||||
damageBlinkCleanup = 0;
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
|
||||
// calc frame damage
|
||||
@@ -272,10 +279,15 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
||||
|
||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||
|
||||
if (!PMONITOR->mirrors.empty())
|
||||
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
|
||||
|
||||
pixman_region32_fini(&frameDamage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
wlr_output_commit(PMONITOR->output);
|
||||
if (!wlr_output_commit(PMONITOR->output))
|
||||
return;
|
||||
|
||||
if (*PDAMAGEBLINK || *PNOVFR)
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
@@ -120,7 +120,7 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
|
||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
||||
|
||||
ASSERT(PPOPUP);
|
||||
|
||||
|
||||
if (PPOPUP->parentWindow)
|
||||
Debug::log(LOG, "New popup created from XDG Window popup %x -> %s", PPOPUP, PPOPUP->parentWindow->m_szTitle.c_str());
|
||||
else
|
||||
@@ -201,4 +201,4 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
|
||||
}
|
||||
|
||||
g_pCompositor->m_vXDGPopups.erase(std::remove_if(g_pCompositor->m_vXDGPopups.begin(), g_pCompositor->m_vXDGPopups.end(), [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; }));
|
||||
}
|
||||
}
|
||||
|
@@ -49,8 +49,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto *const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
|
||||
static auto *const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
PWINDOW->m_bMappedX11 = true;
|
||||
@@ -162,6 +164,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_sAdditionalConfigData.forceOpaque = true;
|
||||
} else if (r.szRule == "forceinput") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
|
||||
} else if (r.szRule == "pin") {
|
||||
PWINDOW->m_bPinned = true;
|
||||
} else if (r.szRule.find("rounding") == 0) {
|
||||
try {
|
||||
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
@@ -188,6 +192,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
// disallow tiled pinned
|
||||
if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating)
|
||||
PWINDOW->m_bPinned = false;
|
||||
|
||||
if (requestedWorkspace != "") {
|
||||
// process requested workspace
|
||||
if (requestedWorkspace.contains(' ')) {
|
||||
@@ -227,8 +235,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
|
||||
|
||||
const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
|
||||
|
||||
const auto SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
|
||||
const auto SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
|
||||
|
||||
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
|
||||
|
||||
@@ -245,8 +255,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
|
||||
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
|
||||
|
||||
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
|
||||
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
|
||||
|
||||
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
|
||||
|
||||
@@ -264,6 +274,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// set the pseudo size to the GOAL of our current size
|
||||
// because the windows are animated on RealSize
|
||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv();
|
||||
|
||||
g_pCompositor->moveWindowToTop(PWINDOW);
|
||||
}
|
||||
else {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
@@ -293,7 +305,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xdg->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "XDG Window Late");
|
||||
@@ -305,7 +317,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
|
||||
|
||||
|
||||
if (PWINDOW->m_iX11Type == 2)
|
||||
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
|
||||
}
|
||||
@@ -320,6 +332,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (workspaceSilent) {
|
||||
// move the window
|
||||
const auto OLDWORKSPACE = PWINDOW->m_iWorkspaceID;
|
||||
|
||||
if (g_pCompositor->m_pLastWindow == PWINDOW) {
|
||||
if (requestedWorkspace != "special")
|
||||
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
|
||||
@@ -328,14 +342,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
} else {
|
||||
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
|
||||
}
|
||||
|
||||
g_pCompositor->forceReportSizesToWindowsOnWorkspace(OLDWORKSPACE);
|
||||
}
|
||||
|
||||
if (requestsFullscreen) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
|
||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
@@ -363,9 +378,49 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
}
|
||||
|
||||
// verify swallowing
|
||||
if (*PSWALLOW) {
|
||||
// check parent
|
||||
int ppid = getPPIDof(PWINDOW->getPID());
|
||||
|
||||
const auto PPPID = getPPIDof(ppid);
|
||||
|
||||
// why? no clue. Blame terminals.
|
||||
if (PPPID > 2) {
|
||||
ppid = PPPID;
|
||||
}
|
||||
|
||||
if (ppid) {
|
||||
// get window by pid
|
||||
CWindow* found = nullptr;
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bHidden)
|
||||
continue;
|
||||
|
||||
if (w->getPID() == ppid) {
|
||||
found = w.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
// check if it's the window we want
|
||||
std::regex rgx(*PSWALLOWREGEX);
|
||||
if (std::regex_match(g_pXWaylandManager->getAppIDClass(found), rgx)) {
|
||||
// swallow
|
||||
PWINDOW->m_pSwallowed = found;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(found);
|
||||
|
||||
found->m_bHidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
|
||||
|
||||
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
||||
|
||||
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", getFormat("%x,%s,%s,%s", PWINDOW, workspaceID.c_str(), g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), PWINDOW->m_szTitle.c_str())});
|
||||
}
|
||||
|
||||
@@ -373,7 +428,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", getFormat("%x", PWINDOW)});
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
@@ -396,13 +451,19 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, false);
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// Allow the renderer to catch the last frame.
|
||||
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
|
||||
|
||||
// swallowing
|
||||
if (PWINDOW->m_pSwallowed && g_pCompositor->windowExists(PWINDOW->m_pSwallowed)) {
|
||||
PWINDOW->m_pSwallowed->m_bHidden = false;
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed);
|
||||
PWINDOW->m_pSwallowed = nullptr;
|
||||
}
|
||||
|
||||
bool wasLastWindow = false;
|
||||
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) {
|
||||
@@ -448,7 +509,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW);
|
||||
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
|
||||
|
||||
|
||||
PWINDOW->m_pSurfaceTree = nullptr;
|
||||
|
||||
PWINDOW->m_bFadingOut = true;
|
||||
@@ -465,7 +526,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
|
||||
|
||||
|
||||
// anims
|
||||
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
|
||||
PWINDOW->m_fAlpha = 0.f;
|
||||
@@ -483,7 +544,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
|
||||
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
|
||||
|
||||
// Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
|
||||
}
|
||||
@@ -557,7 +618,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
PWINDOW->updateToplevel();
|
||||
|
||||
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
}
|
||||
|
||||
@@ -635,7 +696,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
|
||||
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
|
||||
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
|
||||
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y));
|
||||
|
||||
@@ -695,7 +756,10 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
|
||||
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
// ignore
|
||||
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
|
||||
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
}
|
||||
|
||||
@@ -715,4 +779,4 @@ void Events::listener_requestResize(void* owner, void* data) {
|
||||
|
||||
// ignore
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
}
|
||||
}
|
||||
|
@@ -59,5 +59,5 @@ void CAnimatedVariable::unregister() {
|
||||
}
|
||||
|
||||
int CAnimatedVariable::getDurationLeftMs() {
|
||||
return std::clamp((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0, INT_MAX);
|
||||
return std::max((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
|
||||
}
|
||||
|
@@ -125,7 +125,7 @@ public:
|
||||
switch (m_eVarType) {
|
||||
case AVARTYPE_FLOAT:
|
||||
return m_fValue != m_fGoal;
|
||||
case AVARTYPE_VECTOR:
|
||||
case AVARTYPE_VECTOR:
|
||||
return m_vValue != m_vGoal;
|
||||
case AVARTYPE_COLOR:
|
||||
return m_cValue != m_cGoal;
|
||||
@@ -198,4 +198,4 @@ private:
|
||||
friend class CAnimationManager;
|
||||
friend class CWorkspace;
|
||||
friend struct SLayerSurface;
|
||||
};
|
||||
};
|
||||
|
@@ -1,9 +1,7 @@
|
||||
#include "Color.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
CColor::CColor() {
|
||||
|
||||
}
|
||||
CColor::CColor() { }
|
||||
|
||||
CColor::CColor(float r, float g, float b, float a) {
|
||||
this->r = r;
|
||||
|
@@ -23,8 +23,8 @@ public:
|
||||
CColor operator* (const float& v) const {
|
||||
return CColor(r * v, g * v, b * v, a * v);
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const CColor& c2) const {
|
||||
return r == c2.r && g == c2.g && b == c2.b && a == c2.a;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@@ -65,7 +65,7 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
|
||||
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
||||
ASSERT(pSignal);
|
||||
ASSERT(pListener);
|
||||
|
||||
|
||||
wl_signal_add(pSignal, pListener);
|
||||
|
||||
Debug::log(LOG, "Registered signal for owner %x: %x -> %x (owner: %s)", pOwner, pSignal, pListener, ownerString.c_str());
|
||||
@@ -120,14 +120,18 @@ void scaleBox(wlr_box* box, float scale) {
|
||||
}
|
||||
|
||||
std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
while (str[0] == ' ' || str[0] == '\t') {
|
||||
str = str.substr(1);
|
||||
int countBefore = 0;
|
||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
||||
countBefore++;
|
||||
}
|
||||
|
||||
while (str.length() != 0 && (str[str.length() - 1] == ' ' || str[str.length() - 1] == '\t')) {
|
||||
str = str.substr(0, str.length() - 1);
|
||||
int countAfter = 0;
|
||||
while (str.length() != 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
||||
countAfter++;
|
||||
}
|
||||
|
||||
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -170,7 +174,28 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
}
|
||||
|
||||
bool isNumber(const std::string& str, bool allowfloat) {
|
||||
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
||||
|
||||
std::string copy = str;
|
||||
if (*copy.begin() == '-')
|
||||
copy = copy.substr(1);
|
||||
|
||||
if (copy.empty())
|
||||
return false;
|
||||
|
||||
bool point = !allowfloat;
|
||||
for (auto& c : copy) {
|
||||
if (c == '.') {
|
||||
if (point)
|
||||
return false;
|
||||
point = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!std::isdigit(c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isDirection(const std::string& arg) {
|
||||
@@ -192,7 +217,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
outName = WORKSPACENAME;
|
||||
} else {
|
||||
if (in[0] == 'm' || in[0] == 'e') {
|
||||
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||
bool onAllMonitors = in[0] == 'e';
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
@@ -212,15 +237,18 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
while (remains != 0) {
|
||||
if (remains < 0)
|
||||
searchID--;
|
||||
else
|
||||
else
|
||||
searchID++;
|
||||
|
||||
|
||||
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
|
||||
// means we need to wrap around
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
@@ -230,7 +258,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
|
||||
if (remains < 0)
|
||||
searchID = highestID;
|
||||
else
|
||||
else
|
||||
searchID = lowestID;
|
||||
}
|
||||
|
||||
@@ -250,24 +278,32 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
||||
|
||||
} else {
|
||||
if (g_pCompositor->m_pLastMonitor)
|
||||
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
||||
else if (isNumber(in))
|
||||
result = std::clamp(std::stoi(in), 1, INT_MAX);
|
||||
if (in[0] == '+' || in[0] == '-') {
|
||||
if (g_pCompositor->m_pLastMonitor)
|
||||
result = std::max((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1);
|
||||
else {
|
||||
Debug::log(ERR, "Relative workspace on no mon!");
|
||||
result = INT_MAX;
|
||||
}
|
||||
} else if (isNumber(in))
|
||||
result = std::max(std::stoi(in), 1);
|
||||
else {
|
||||
Debug::log(ERR, "Relative workspace on no mon!");
|
||||
result = INT_MAX;
|
||||
// maybe name
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByName(in);
|
||||
if (PWORKSPACE)
|
||||
result = PWORKSPACE->m_iID;
|
||||
}
|
||||
|
||||
outName = std::to_string(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) {
|
||||
const float DX = std::max((double)0, std::max(p1.x - vec.x, vec.x - p2.x));
|
||||
const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y));
|
||||
const float DX = std::max({0.0, p1.x - vec.x, vec.x - p2.x});
|
||||
const float DY = std::max({0.0, p1.y - vec.y, vec.y - p2.y});
|
||||
return DX * DX + DY * DY;
|
||||
}
|
||||
|
||||
@@ -322,3 +358,38 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
|
||||
// Identity
|
||||
mat[8] = 1.0f;
|
||||
}
|
||||
|
||||
int64_t getPPIDof(int64_t pid) {
|
||||
std::string dir = "/proc/" + std::to_string(pid) + "/status";
|
||||
FILE* infile;
|
||||
|
||||
infile = fopen(dir.c_str(), "r");
|
||||
if (!infile)
|
||||
return 0;
|
||||
|
||||
char* line = nullptr;
|
||||
size_t len = 0;
|
||||
ssize_t len2 = 0;
|
||||
|
||||
std::string pidstr;
|
||||
|
||||
while ((len2 = getline(&line, &len, infile)) != -1) {
|
||||
if (strstr(line, "PPid:")) {
|
||||
pidstr = std::string(line, len2);
|
||||
const auto tabpos = pidstr.find_last_of('\t');
|
||||
if (tabpos != std::string::npos)
|
||||
pidstr = pidstr.substr(tabpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
if (line)
|
||||
free(line);
|
||||
|
||||
try {
|
||||
return std::stoll(pidstr);
|
||||
} catch (std::exception& e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
@@ -14,6 +14,7 @@ int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||
void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
int64_t getPPIDof(int64_t pid);
|
||||
|
||||
float getPlusMinusKeywordResult(std::string in, float relative);
|
||||
|
||||
|
@@ -31,7 +31,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
|
||||
if (!wlr_output_test(output))
|
||||
continue;
|
||||
|
||||
|
||||
PREFSTATE = mode;
|
||||
break;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
Debug::log(WARN, "No mode found for disabled output %s", output->name);
|
||||
|
||||
wlr_output_enable(output, 0);
|
||||
|
||||
|
||||
if (!wlr_output_commit(output)) {
|
||||
Debug::log(ERR, "Couldn't commit disabled state on output %s", output->name);
|
||||
}
|
||||
@@ -65,6 +65,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
}
|
||||
|
||||
if (!m_bRenderingInitPassed) {
|
||||
output->allocator = nullptr;
|
||||
output->renderer = nullptr;
|
||||
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||
m_bRenderingInitPassed = true;
|
||||
}
|
||||
@@ -83,15 +85,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()){
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
wlr_output_set_scale(output, monitorRule.scale);
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
|
||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
|
||||
|
||||
wlr_output_enable_adaptive_sync(output, 1);
|
||||
|
||||
// create it in the arr
|
||||
vecPosition = monitorRule.offset;
|
||||
vecSize = monitorRule.resolution;
|
||||
@@ -115,52 +115,16 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!pWLRWorkspaceGroupHandle) {
|
||||
pWLRWorkspaceGroupHandle = wlr_ext_workspace_group_handle_v1_create(g_pCompositor->m_sWLREXTWorkspaceMgr);
|
||||
}
|
||||
|
||||
|
||||
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
|
||||
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
setupDefaultWS(monitorRule);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
scale = monitorRule.scale;
|
||||
|
||||
m_pThisWrap = nullptr;
|
||||
|
||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
//
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
@@ -188,6 +152,20 @@ void CMonitor::onDisconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
// remove mirror
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
pMirrorOf = nullptr;
|
||||
}
|
||||
|
||||
if (!mirrors.empty()) {
|
||||
for (auto& m : mirrors) {
|
||||
m->setMirror("");
|
||||
}
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
@@ -248,3 +226,136 @@ void CMonitor::addDamage(pixman_region32_t* rg) {
|
||||
void CMonitor::addDamage(wlr_box* box) {
|
||||
wlr_output_damage_add_box(damage, box);
|
||||
}
|
||||
|
||||
bool CMonitor::isMirror() {
|
||||
return pMirrorOf != nullptr;
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
}
|
||||
|
||||
void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
const auto PMIRRORMON = g_pCompositor->getMonitorFromString(mirrorOf);
|
||||
|
||||
if (PMIRRORMON == pMirrorOf)
|
||||
return;
|
||||
|
||||
if (PMIRRORMON && PMIRRORMON->isMirror()) {
|
||||
Debug::log(ERR, "Cannot mirror a mirror!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PMIRRORMON == this) {
|
||||
Debug::log(ERR, "Cannot mirror self!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PMIRRORMON) {
|
||||
// disable mirroring
|
||||
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
}
|
||||
|
||||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName);
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
// push to mvmonitors
|
||||
if (!m_pThisWrap) {
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
|
||||
setupDefaultWS(RULE);
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
|
||||
} else {
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m.get() != this) {
|
||||
BACKUPMON = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move all the WS
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : wspToMove) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||
w->startAnim(true, true, true);
|
||||
}
|
||||
|
||||
activeWorkspace = -1;
|
||||
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
|
||||
vecPosition = Vector2D(-1337420, -1337420);
|
||||
|
||||
pMirrorOf = PMIRRORMON;
|
||||
|
||||
pMirrorOf->mirrors.push_back(this);
|
||||
|
||||
// remove from mvmonitors
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
|
||||
}
|
||||
|
||||
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
struct SMonitorRule;
|
||||
|
||||
class CMonitor {
|
||||
public:
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
@@ -35,9 +37,13 @@ public:
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// mirroring
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
// for the special workspace
|
||||
bool specialWorkspaceOpen = false;
|
||||
|
||||
|
||||
// Double-linked list because we need to have constant mem addresses for signals
|
||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
||||
// and I am lazy
|
||||
@@ -57,6 +63,8 @@ public:
|
||||
void onDisconnect();
|
||||
void addDamage(pixman_region32_t* rg);
|
||||
void addDamage(wlr_box* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
@@ -67,4 +75,7 @@ public:
|
||||
bool operator==(const CMonitor& rhs) {
|
||||
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
};
|
||||
|
@@ -101,6 +101,14 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
}
|
||||
|
||||
// remove references to this node
|
||||
for (auto& tn : surfaceTreeNodes) {
|
||||
for (auto& cs : tn.childSubsurfaces) {
|
||||
if (cs.pChild == pNode)
|
||||
cs.pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
surfaceTreeNodes.remove(*pNode);
|
||||
|
||||
Debug::log(LOG, "SurfaceTree Node removed");
|
||||
@@ -154,6 +162,9 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||
void Events::listener_mapSubsurface(void* owner, void* data) {
|
||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
||||
|
||||
if (subsurface->pChild)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
||||
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||
@@ -170,18 +181,16 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {0};
|
||||
wlr_box extents = {lx, ly, 0, 0};
|
||||
if (PNODE->pSurface) {
|
||||
wlr_surface_get_extends(PNODE->pSurface, &extents);
|
||||
|
||||
extents.x += lx;
|
||||
extents.y += ly;
|
||||
extents.width = PNODE->pSurface->current.width;
|
||||
extents.height = PNODE->pSurface->current.height;
|
||||
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
}
|
||||
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
subsurface->pChild = nullptr;
|
||||
//SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
//subsurface->pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +226,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
||||
|
||||
if (subsurface->pChild)
|
||||
listener_destroySubsurfaceNode(subsurface->pChild, nullptr);
|
||||
if (subsurface->pChild) {
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
|
||||
|
||||
|
@@ -193,7 +193,7 @@ struct SDrag {
|
||||
bool iconMapped = false;
|
||||
|
||||
wlr_drag_icon* dragIcon = nullptr;
|
||||
|
||||
|
||||
Vector2D pos;
|
||||
|
||||
DYNLISTENER(destroyIcon);
|
||||
@@ -322,3 +322,13 @@ struct SIMEPopup {
|
||||
return pSurface == other.pSurface;
|
||||
}
|
||||
};
|
||||
|
||||
struct STouchDevice {
|
||||
wlr_input_device* pWlrDevice = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const STouchDevice& other) {
|
||||
return pWlrDevice == other.pWlrDevice;
|
||||
}
|
||||
};
|
||||
|
@@ -12,7 +12,7 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||
m_iMonitorID = monitorID;
|
||||
m_szName = name;
|
||||
m_bIsSpecialWorkspace = special;
|
||||
|
||||
|
||||
if (!special) {
|
||||
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
||||
|
||||
@@ -91,6 +91,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_vRenderOffset.warp();
|
||||
m_fAlpha.warp();
|
||||
}
|
||||
|
||||
// check LS-es
|
||||
if (in) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (!ls->fadingOut)
|
||||
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWorkspace::setActive(bool on) {
|
||||
@@ -119,4 +128,11 @@ void CWorkspace::moveToMonitor(const int& id) {
|
||||
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
||||
|
||||
wlr_ext_workspace_handle_v1_set_name(m_pWlrHandle, m_szName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
CWindow* CWorkspace::getLastFocusedWindow() {
|
||||
if (!g_pCompositor->windowValidMapped(m_pLastFocusedWindow) || m_pLastFocusedWindow->m_iWorkspaceID != m_iID)
|
||||
return nullptr;
|
||||
|
||||
return m_pLastFocusedWindow;
|
||||
}
|
||||
|
@@ -8,6 +8,8 @@ enum eFullscreenMode : uint8_t {
|
||||
FULLSCREEN_MAXIMIZED
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
|
||||
class CWorkspace {
|
||||
public:
|
||||
CWorkspace(int monitorID, std::string name, bool special = false);
|
||||
@@ -36,6 +38,9 @@ public:
|
||||
// "scratchpad"
|
||||
bool m_bIsSpecialWorkspace = false;
|
||||
|
||||
// last window
|
||||
CWindow* m_pLastFocusedWindow = nullptr;
|
||||
|
||||
// user-set
|
||||
bool m_bDefaultFloating = false;
|
||||
bool m_bDefaultPseudo = false;
|
||||
@@ -44,4 +49,6 @@ public:
|
||||
void setActive(bool on);
|
||||
|
||||
void moveToMonitor(const int&);
|
||||
|
||||
CWindow* getLastFocusedWindow();
|
||||
};
|
@@ -56,7 +56,7 @@ void CHyprError::createQueued() {
|
||||
cairo_show_text(CAIRO, current.c_str());
|
||||
yoffset += FONTSIZE + (FONTSIZE / 10.f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
cairo_surface_flush(CAIROSURFACE);
|
||||
|
||||
@@ -66,12 +66,12 @@ void CHyprError::createQueued() {
|
||||
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
|
||||
#ifndef GLES2
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
#endif
|
||||
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
// delete cairo
|
||||
@@ -114,4 +114,4 @@ void CHyprError::draw() {
|
||||
void CHyprError::destroy() {
|
||||
if (m_bIsCreated)
|
||||
m_bQueuedDestroy = true;
|
||||
}
|
||||
}
|
||||
|
@@ -90,6 +90,19 @@ void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
|
||||
this->pWindow->m_bHidden = pMember != this;
|
||||
}
|
||||
|
||||
int SDwindleNodeData::getGroupMemberCount() {
|
||||
SDwindleNodeData* current = this->pNextGroupMember;
|
||||
|
||||
int no = 1;
|
||||
|
||||
while (current != this) {
|
||||
current = current->pNextGroupMember;
|
||||
no++;
|
||||
}
|
||||
|
||||
return no;
|
||||
}
|
||||
|
||||
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
@@ -126,7 +139,7 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
|
||||
|
||||
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool force) {
|
||||
// Don't set nodes, only windows.
|
||||
if (pNode->isNode)
|
||||
if (pNode->isNode)
|
||||
return;
|
||||
|
||||
CMonitor* PMONITOR = nullptr;
|
||||
@@ -153,14 +166,15 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
|
||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
|
||||
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
|
||||
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
|
||||
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
|
||||
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
|
||||
onWindowRemovedTiling(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,29 +183,33 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
|
||||
|
||||
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
||||
|
||||
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && (NODESONWORKSPACE == 1 || (pNode->isGroupMember() && pNode->getGroupMemberCount() == NODESONWORKSPACE))) {
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.border = false;
|
||||
PWINDOW->m_sSpecialRenderData.decorate = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = true;
|
||||
PWINDOW->m_sSpecialRenderData.border = true;
|
||||
PWINDOW->m_sSpecialRenderData.decorate = true;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYTOP ? GAPSOUT : GAPSIN);
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
|
||||
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
|
||||
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
|
||||
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
|
||||
|
||||
calcPos = calcPos + OFFSETTOPLEFT;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
@@ -281,7 +299,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
// 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);
|
||||
@@ -311,6 +329,13 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
@@ -340,9 +365,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If it's not, get the node under our cursor
|
||||
|
||||
m_lDwindleNodesData.push_back(SDwindleNodeData());
|
||||
@@ -355,19 +382,19 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
NEWPARENT->isNode = true; // it is a node
|
||||
|
||||
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
|
||||
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
// if cursor over first child, make it first, etc
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * WIDTHMULTIPLIER;
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
|
||||
const auto PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
|
||||
if (FORCESPLIT == 0) {
|
||||
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|
||||
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
if (*PFORCESPLIT == 0) {
|
||||
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|
||||
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
// we are hovering over the first node, make PNODE first.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
@@ -377,7 +404,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
}
|
||||
} else {
|
||||
if (FORCESPLIT == 1) {
|
||||
if (*PFORCESPLIT == 1) {
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
@@ -385,7 +412,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// and update the previous parent if it exists
|
||||
if (OPENINGON->pParent) {
|
||||
if (OPENINGON->pParent->children[0] == OPENINGON) {
|
||||
@@ -396,9 +423,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// Update the children
|
||||
|
||||
|
||||
if (NEWPARENT->size.x * WIDTHMULTIPLIER > NEWPARENT->size.y) {
|
||||
|
||||
if (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y) {
|
||||
// split left/right
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
@@ -430,6 +457,9 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
// check if it was grouped
|
||||
if (PNODE->isGroupMember()) {
|
||||
// get shit
|
||||
@@ -442,7 +472,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
if (PNODE->groupHead) {
|
||||
PNEXT->groupHead = true;
|
||||
PNEXT->pParent = PNODE->pParent;
|
||||
|
||||
|
||||
if (PNODE->pParent) {
|
||||
if (PNODE->pParent->children[0] == PNODE) {
|
||||
PNODE->pParent->children[0] = PNEXT;
|
||||
@@ -453,21 +483,25 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
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);
|
||||
|
||||
applyNodeDataToWindow(PNEXT);
|
||||
|
||||
if (!PNEXT->isGroupMember()) {
|
||||
// means we dissolved the group
|
||||
recalculateMonitor(PNEXT->pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -485,6 +519,17 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
PSIBLING->size = PPARENT->size;
|
||||
PSIBLING->pParent = PPARENT->pParent;
|
||||
|
||||
if (PSIBLING->isGroupMember()) {
|
||||
// apply to all group members
|
||||
SDwindleNodeData* current = PSIBLING->pNextGroupMember;
|
||||
|
||||
while (current != PSIBLING) {
|
||||
current->position = PPARENT->position;
|
||||
current->size = PPARENT->size;
|
||||
current = current->pNextGroupMember;
|
||||
}
|
||||
}
|
||||
|
||||
if (PPARENT->pParent != nullptr) {
|
||||
if (PPARENT->pParent->children[0] == PPARENT) {
|
||||
PPARENT->pParent->children[0] = PSIBLING;
|
||||
@@ -498,7 +543,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
if (PSIBLING->pParent)
|
||||
PSIBLING->pParent->recalcSizePosRecursive();
|
||||
else
|
||||
else
|
||||
PSIBLING->recalcSizePosRecursive();
|
||||
|
||||
m_lDwindleNodesData.remove(*PPARENT);
|
||||
@@ -576,7 +621,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
if (!PNODE) {
|
||||
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
|
||||
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
||||
PWINDOW->updateWindowDecos();
|
||||
return;
|
||||
}
|
||||
@@ -613,11 +658,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
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->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
@@ -632,11 +677,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
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->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
@@ -650,8 +695,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
||||
|
||||
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->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
@@ -660,10 +705,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
@@ -763,12 +805,13 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
fullscreenRequestForWindow(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FULLSCREEN_FULL, false);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PNODE->isGroupMember()) {
|
||||
Debug::log(ERR, "Cannot enable group on fullscreen window");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE->isGroupMember()) {
|
||||
// dissolve group
|
||||
|
||||
const auto PHEAD = PNODE->getGroupHead();
|
||||
|
||||
SDwindleNodeData* current = PNODE->pNextGroupMember;
|
||||
@@ -776,7 +819,7 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
PNODE->pWindow->m_bIsFloating = PHEAD->pWindow->m_bIsFloating;
|
||||
|
||||
std::deque<CWindow*> toAddWindows;
|
||||
|
||||
|
||||
const auto PWINDOWNODE = PNODE->pWindow;
|
||||
toAddWindows.push_back(PWINDOWNODE);
|
||||
|
||||
@@ -789,8 +832,15 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
PWINDOW->m_bHidden = false;
|
||||
}
|
||||
|
||||
PHEAD->pPreviousGroupMember = nullptr;
|
||||
PHEAD->pNextGroupMember = nullptr;
|
||||
if (PHEAD->pPreviousGroupMember)
|
||||
PHEAD->pPreviousGroupMember->pNextGroupMember = PHEAD->pNextGroupMember;
|
||||
|
||||
if (PHEAD->pNextGroupMember)
|
||||
PHEAD->pNextGroupMember->pPreviousGroupMember = PHEAD->pPreviousGroupMember;
|
||||
|
||||
PHEAD->pPreviousGroupMember = nullptr;
|
||||
PHEAD->pNextGroupMember = nullptr;
|
||||
|
||||
onWindowRemoved(PHEAD->pWindow);
|
||||
|
||||
for (auto& pw : toAddWindows) {
|
||||
@@ -870,6 +920,9 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
|
||||
// focus
|
||||
PNODE->setGroupFocusedNode(PNODE);
|
||||
|
||||
// required for no_gaps_when_only to work
|
||||
applyNodeDataToWindow(PNODE);
|
||||
}
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
@@ -878,7 +931,7 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
|
||||
|
||||
std::deque<CWindow*> result;
|
||||
|
||||
if (!g_pCompositor->windowExists(pWindow))
|
||||
@@ -903,7 +956,7 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWindow* forceTo) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return; // reject
|
||||
|
||||
@@ -921,10 +974,18 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
else
|
||||
pNewNode = PNODE->pPreviousGroupMember;
|
||||
|
||||
if (forceTo) {
|
||||
const auto NODETO = getNodeFromWindow(forceTo);
|
||||
|
||||
if (NODETO)
|
||||
pNewNode = NODETO;
|
||||
}
|
||||
|
||||
PNODE->setGroupFocusedNode(pNewNode);
|
||||
|
||||
pNewNode->position = PNODE->position;
|
||||
pNewNode->size = PNODE->size;
|
||||
pNewNode->workspaceID = PNODE->workspaceID;
|
||||
|
||||
applyNodeDataToWindow(pNewNode);
|
||||
|
||||
@@ -934,7 +995,7 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
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);
|
||||
@@ -954,6 +1015,9 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
|
||||
|
||||
SWindowRenderLayoutHints hints;
|
||||
|
||||
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
|
||||
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
if (!PNODE)
|
||||
return hints; // left for the future, maybe floating funkiness
|
||||
@@ -962,9 +1026,9 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
|
||||
hints.isBorderColor = true;
|
||||
|
||||
if (pWindow == g_pCompositor->m_pLastWindow)
|
||||
hints.borderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
|
||||
hints.borderColor = CColor(*PGROUPCOLACTIVE);
|
||||
else
|
||||
hints.borderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
|
||||
hints.borderColor = CColor(*PGROUPCOLINACTIVE);
|
||||
}
|
||||
|
||||
return hints;
|
||||
@@ -973,58 +1037,101 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
|
||||
void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
// windows should be valid, insallah
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
const auto PNODE2 = getNodeFromWindow(pWindow2);
|
||||
auto PNODE = getNodeFromWindow(pWindow);
|
||||
auto PNODE2 = getNodeFromWindow(pWindow2);
|
||||
|
||||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
if (!PNODE2 || !PNODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Dwindle: Rejecting a swap between workspaces");
|
||||
return;
|
||||
}
|
||||
SDwindleNodeData* ACTIVE1 = nullptr;
|
||||
SDwindleNodeData* ACTIVE2 = nullptr;
|
||||
|
||||
// we will not delete the nodes, just fix the tree
|
||||
if (PNODE2->pParent == PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
|
||||
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
PPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[0] = PNODE;
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
} else {
|
||||
if (PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Groups are confined to a monitor");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE2->pParent) {
|
||||
const auto PPARENT = PNODE2->pParent;
|
||||
if (PNODE->isGroupMember()) {
|
||||
ACTIVE1 = PNODE;
|
||||
PNODE = PNODE->getGroupHead();
|
||||
}
|
||||
|
||||
if (PPARENT->children[0] == PNODE2) {
|
||||
PPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PNODE2->isGroupMember()) {
|
||||
ACTIVE2 = PNODE2;
|
||||
PNODE2 = PNODE2->getGroupHead();
|
||||
}
|
||||
|
||||
const auto PPARENTNODE2 = PNODE2->pParent;
|
||||
PNODE2->pParent = PNODE->pParent;
|
||||
PNODE->pParent = PPARENTNODE2;
|
||||
if (PNODE2->pParent == PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
// these are window nodes, so no children.
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
PPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[0] = PNODE;
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
} else {
|
||||
if (PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
// recalc the workspace
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
}
|
||||
|
||||
if (PNODE2->pParent) {
|
||||
const auto PPARENT = PNODE2->pParent;
|
||||
|
||||
if (PPARENT->children[0] == PNODE2) {
|
||||
PPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto PPARENTNODE2 = PNODE2->pParent;
|
||||
PNODE2->pParent = PNODE->pParent;
|
||||
PNODE->pParent = PPARENTNODE2;
|
||||
|
||||
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
|
||||
} else {
|
||||
// swap the windows and recalc
|
||||
PNODE2->pWindow = pWindow;
|
||||
PNODE->pWindow = pWindow2;
|
||||
}
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
||||
}
|
||||
|
||||
// recalc the workspace
|
||||
getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive();
|
||||
|
||||
if (PNODE2->workspaceID != PNODE->workspaceID) {
|
||||
getMasterNodeOnWorkspace(PNODE2->workspaceID)->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
if (ACTIVE1) {
|
||||
ACTIVE1->position = PNODE->position;
|
||||
ACTIVE1->size = PNODE->size;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
|
||||
}
|
||||
|
||||
if (ACTIVE2) {
|
||||
ACTIVE2->position = PNODE2->position;
|
||||
ACTIVE2->size = PNODE2->size;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
@@ -1032,7 +1139,7 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE || !PNODE->pParent)
|
||||
if (!PNODE || !PNODE->pParent || (PNODE->isGroupMember() && PNODE->getGroupMemberCount() == g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID)))
|
||||
return;
|
||||
|
||||
PNODE->pParent->splitRatio = std::clamp(PNODE->pParent->splitRatio + ratio, 0.1f, 1.9f);
|
||||
@@ -1050,10 +1157,10 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
||||
else if (message == "togglesplit")
|
||||
toggleSplit(header.pWindow);
|
||||
else if (message == "groupinfo") {
|
||||
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
|
||||
auto res = getGroupMembers(header.pWindow ? header.pWindow : g_pCompositor->m_pLastWindow);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,7 @@ struct SDwindleNodeData {
|
||||
bool isGroupMember();
|
||||
SDwindleNodeData* getGroupHead();
|
||||
SDwindleNodeData* getGroupVisible();
|
||||
int getGroupMemberCount();
|
||||
void setGroupFocusedNode(SDwindleNodeData*);
|
||||
CHyprDwindleLayout* layout = nullptr;
|
||||
};
|
||||
@@ -74,7 +75,7 @@ private:
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
||||
void toggleWindowGroup(CWindow*);
|
||||
void switchGroupWindow(CWindow*, bool forward);
|
||||
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
|
||||
void toggleSplit(CWindow*);
|
||||
std::deque<CWindow*> getGroupMembers(CWindow*);
|
||||
|
||||
|
@@ -50,7 +50,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
pWindow->m_bHidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// reject any windows with size <= 5x5
|
||||
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) {
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
|
||||
@@ -64,8 +64,24 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
// check if it's on the correct monitor!
|
||||
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
|
||||
|
||||
// check if it's visible on any monitor (only for XDG)
|
||||
bool visible = pWindow->m_bIsX11;
|
||||
|
||||
if (!pWindow->m_bIsX11) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
|
||||
|
||||
visible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: detect a popup in a more consistent way.
|
||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
|
||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible) {
|
||||
// if it's not, fall back to the center placement
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
|
||||
} else {
|
||||
@@ -121,7 +137,7 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
@@ -135,6 +151,21 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
|
||||
m_vLastDragXY = m_vBeginDragXY;
|
||||
|
||||
// get the grab corner
|
||||
if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) {
|
||||
// left
|
||||
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
|
||||
m_iGrabbedCorner = 0;
|
||||
else
|
||||
m_iGrabbedCorner = 4;
|
||||
} else {
|
||||
// right
|
||||
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
|
||||
m_iGrabbedCorner = 1;
|
||||
else
|
||||
m_iGrabbedCorner = 3;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
// shadow to ignore any bound to MAIN_MOD
|
||||
@@ -176,22 +207,43 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE) {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW);
|
||||
|
||||
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)));
|
||||
// calc the new size and pos
|
||||
|
||||
Vector2D newSize = m_vBeginDragSizeXY;
|
||||
Vector2D newPos = m_vBeginDragPositionXY;
|
||||
|
||||
if (m_iGrabbedCorner == 3) {
|
||||
newSize = newSize + DELTA;
|
||||
} else if (m_iGrabbedCorner == 0) {
|
||||
newSize = newSize - DELTA;
|
||||
newPos = newPos + DELTA;
|
||||
} else if (m_iGrabbedCorner == 1) {
|
||||
newSize = newSize + Vector2D(DELTA.x, -DELTA.y);
|
||||
newPos = newPos + Vector2D(0, DELTA.y);
|
||||
} else if (m_iGrabbedCorner == 4) {
|
||||
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
|
||||
newPos = newPos + Vector2D(DELTA.x, 0);
|
||||
}
|
||||
|
||||
|
||||
newSize = newSize.clamp(Vector2D(20,20), MAXSIZE);
|
||||
|
||||
if (*PANIMATE) {
|
||||
DRAGGINGWINDOW->m_vRealSize = newSize;
|
||||
DRAGGINGWINDOW->m_vRealPosition = newPos;
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(newPos);
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||
@@ -207,7 +259,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
if (PMONITOR) {
|
||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
DRAGGINGWINDOW->moveToWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
|
||||
DRAGGINGWINDOW->updateToplevel();
|
||||
}
|
||||
|
||||
@@ -226,6 +278,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
pWindow->m_bPinned = false;
|
||||
|
||||
const auto TILED = isWindowTiled(pWindow);
|
||||
|
||||
if (!TILED) {
|
||||
@@ -284,4 +338,4 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@ public:
|
||||
*/
|
||||
virtual void onEndDragWindow();
|
||||
/*
|
||||
Called whenever the mouse moves, should the layout want to
|
||||
Called whenever the mouse moves, should the layout want to
|
||||
do anything with it.
|
||||
Useful for dragging.
|
||||
*/
|
||||
@@ -94,19 +94,19 @@ public:
|
||||
|
||||
/*
|
||||
Called when a dispatcher requests a custom message
|
||||
The layout is free to ignore.
|
||||
The layout is free to ignore.
|
||||
std::any is the reply. Can be empty.
|
||||
*/
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
|
||||
|
||||
/*
|
||||
/*
|
||||
Required to be handled, but may return just SWindowRenderLayoutHints()
|
||||
Called when the renderer requests any special draw flags for
|
||||
a specific window, e.g. border color for groups.
|
||||
*/
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*) = 0;
|
||||
|
||||
/*
|
||||
/*
|
||||
Called when the user requests two windows to be swapped places.
|
||||
The layout is free to ignore.
|
||||
*/
|
||||
@@ -128,4 +128,5 @@ private:
|
||||
Vector2D m_vLastDragXY;
|
||||
Vector2D m_vBeginDragPositionXY;
|
||||
Vector2D m_vBeginDragSizeXY;
|
||||
};
|
||||
int m_iGrabbedCorner = 0;
|
||||
};
|
||||
|
@@ -84,6 +84,13 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// recalc
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
@@ -94,6 +101,9 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
if (!PNODE)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
if (PNODE->isMaster) {
|
||||
// find new one
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
@@ -123,7 +133,7 @@ void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
return;
|
||||
|
||||
// massive hack from the fullscreen func
|
||||
@@ -215,9 +225,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
|
||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
|
||||
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
|
||||
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
|
||||
@@ -231,29 +241,31 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
|
||||
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
||||
|
||||
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.border = false;
|
||||
PWINDOW->m_sSpecialRenderData.decorate = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = true;
|
||||
PWINDOW->m_sSpecialRenderData.border = true;
|
||||
PWINDOW->m_sSpecialRenderData.decorate = true;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYTOP ? GAPSOUT : GAPSIN);
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
|
||||
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
|
||||
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
|
||||
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
|
||||
|
||||
calcPos = calcPos + OFFSETTOPLEFT;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
@@ -297,7 +309,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
if (!PNODE) {
|
||||
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
|
||||
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
||||
PWINDOW->updateWindowDecos();
|
||||
return;
|
||||
}
|
||||
@@ -326,10 +338,7 @@ 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)
|
||||
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
@@ -425,16 +434,17 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
return;
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Master: Rejecting a swap between workspaces");
|
||||
return;
|
||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
||||
}
|
||||
|
||||
// massive hack: just swap window pointers, lol
|
||||
const auto PWINDOW1 = PNODE->pWindow;
|
||||
PNODE->pWindow = PNODE2->pWindow;
|
||||
PNODE2->pWindow = PWINDOW1;
|
||||
PNODE->pWindow = pWindow2;
|
||||
PNODE2->pWindow = pWindow;
|
||||
|
||||
recalculateMonitor(PWINDOW1->m_iMonitorID);
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
if (PNODE2->workspaceID != PNODE->workspaceID)
|
||||
recalculateMonitor(pWindow2->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
@@ -602,4 +612,4 @@ void CHyprMasterLayout::onEnable() {
|
||||
|
||||
void CHyprMasterLayout::onDisable() {
|
||||
m_lMasterNodesData.clear();
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,12 @@ int main(int argc, char** argv) {
|
||||
if (!getenv("XDG_RUNTIME_DIR"))
|
||||
throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
|
||||
|
||||
// export HYPRLAND_CMD
|
||||
std::string cmd = "";
|
||||
for (auto i = 0; i < argc; ++i)
|
||||
cmd += std::string(i == 0 ? "" : " ") + argv[i];
|
||||
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
|
||||
|
||||
// parse some args
|
||||
std::string configPath;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
@@ -50,7 +56,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// let's init the compositor.
|
||||
// it initializes basic Wayland stuff in the constructor.
|
||||
g_pCompositor = std::make_unique<CCompositor>();
|
||||
g_pCompositor = std::make_unique<CCompositor>();
|
||||
g_pCompositor->explicitConfigPath = configPath;
|
||||
|
||||
Debug::log(LOG, "Hyprland init finished.");
|
||||
|
@@ -167,7 +167,7 @@ void CAnimationManager::tick() {
|
||||
}
|
||||
case AVARDAMAGE_BORDER: {
|
||||
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
|
||||
|
||||
|
||||
// damage only the border.
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
const auto ROUNDINGSIZE = *PROUNDING + 1;
|
||||
@@ -222,7 +222,7 @@ void CAnimationManager::tick() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// set size and pos if valid, but only if damage policy entire (dont if border for example)
|
||||
if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2)
|
||||
@@ -438,4 +438,4 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@@ -36,19 +36,12 @@ void CEventManager::startThread() {
|
||||
// 10 max queued.
|
||||
listen(SOCKET, 10);
|
||||
|
||||
char readBuf[1024] = {0};
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
|
||||
|
||||
// set the socket nonblock
|
||||
int flags = fcntl(SOCKET, F_GETFL, 0);
|
||||
fcntl(SOCKET, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
while (1) {
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
||||
if (ACCEPTEDCONNECTION > 0) {
|
||||
@@ -61,43 +54,7 @@ void CEventManager::startThread() {
|
||||
Debug::log(LOG, "Socket 2 accepted a new client at FD %d", ACCEPTEDCONNECTION);
|
||||
}
|
||||
|
||||
// pong if all FDs valid
|
||||
for (auto it = m_dAcceptedSocketFDs.begin(); it != m_dAcceptedSocketFDs.end();) {
|
||||
auto sizeRead = recv(*it, &readBuf, 1024, 0);
|
||||
|
||||
if (sizeRead != 0) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// invalid!
|
||||
Debug::log(LOG, "Removed invalid socket (2) FD: %d", *it);
|
||||
it = m_dAcceptedSocketFDs.erase(it);
|
||||
}
|
||||
|
||||
// valid FDs, check the queue
|
||||
// don't do anything if main thread is writing to the eventqueue
|
||||
eventQueueMutex.lock();
|
||||
|
||||
if (m_dQueuedEvents.empty()){ // if queue empty, sleep and ignore
|
||||
eventQueueMutex.unlock();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
// write all queued events
|
||||
for (auto& ev : m_dQueuedEvents) {
|
||||
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
|
||||
for (auto& fd : m_dAcceptedSocketFDs) {
|
||||
write(fd, eventString.c_str(), eventString.length());
|
||||
}
|
||||
}
|
||||
|
||||
m_dQueuedEvents.clear();
|
||||
|
||||
eventQueueMutex.unlock();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
ensureFDsValid();
|
||||
}
|
||||
|
||||
close(SOCKET);
|
||||
@@ -106,6 +63,42 @@ void CEventManager::startThread() {
|
||||
m_tThread.detach();
|
||||
}
|
||||
|
||||
void CEventManager::ensureFDsValid() {
|
||||
static char readBuf[1024] = {0};
|
||||
|
||||
// pong if all FDs valid
|
||||
for (auto it = m_dAcceptedSocketFDs.begin(); it != m_dAcceptedSocketFDs.end();) {
|
||||
auto sizeRead = recv(*it, &readBuf, 1024, 0);
|
||||
|
||||
if (sizeRead != 0) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// invalid!
|
||||
Debug::log(LOG, "Removed invalid socket (2) FD: %d", *it);
|
||||
it = m_dAcceptedSocketFDs.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void CEventManager::flushEvents() {
|
||||
|
||||
ensureFDsValid();
|
||||
|
||||
eventQueueMutex.lock();
|
||||
|
||||
for (auto& ev : m_dQueuedEvents) {
|
||||
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
|
||||
for (auto& fd : m_dAcceptedSocketFDs) {
|
||||
write(fd, eventString.c_str(), eventString.length());
|
||||
}
|
||||
}
|
||||
|
||||
m_dQueuedEvents.clear();
|
||||
|
||||
eventQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
|
||||
|
||||
if ((m_bIgnoreEvents && !force) || g_pCompositor->m_bIsShuttingDown) {
|
||||
@@ -117,5 +110,7 @@ void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
|
||||
eventQueueMutex.lock();
|
||||
m_dQueuedEvents.push_back(ev);
|
||||
eventQueueMutex.unlock();
|
||||
|
||||
flushEvents();
|
||||
}, event).detach();
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void flushEvents();
|
||||
void ensureFDsValid();
|
||||
|
||||
std::mutex eventQueueMutex;
|
||||
std::deque<SHyprIPCEvent> m_dQueuedEvents;
|
||||
|
||||
|
@@ -7,6 +7,7 @@ CKeybindManager::CKeybindManager() {
|
||||
|
||||
m_mDispatchers["exec"] = spawn;
|
||||
m_mDispatchers["killactive"] = killActive;
|
||||
m_mDispatchers["closewindow"] = kill;
|
||||
m_mDispatchers["togglefloating"] = toggleActiveFloating;
|
||||
m_mDispatchers["workspace"] = changeworkspace;
|
||||
m_mDispatchers["fullscreen"] = fullscreenActive;
|
||||
@@ -41,6 +42,8 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||
m_mDispatchers["swapnext"] = swapnext;
|
||||
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
||||
m_mDispatchers["pin"] = pinActive;
|
||||
m_mDispatchers["mouse"] = mouse;
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
}
|
||||
@@ -120,12 +123,39 @@ void CKeybindManager::updateXKBTranslationState() {
|
||||
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
const auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!PKEYMAP) {
|
||||
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )", CColor(255, 50, 50, 255));
|
||||
|
||||
Debug::log(ERR, "[XKBTranslationState] Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||
memset(&rules, 0, sizeof(rules));
|
||||
|
||||
PKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
xkb_context_unref(PCONTEXT);
|
||||
m_pXKBTranslationState = xkb_state_new(PKEYMAP);
|
||||
}
|
||||
|
||||
bool CKeybindManager::ensureMouseBindState() {
|
||||
if (!m_bIsMouseBindActive)
|
||||
return false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
m_bIsMouseBindActive = false;
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_bIsMouseBindActive = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
if (!g_pCompositor->m_bSessionActive) {
|
||||
m_dPressedKeycodes.clear();
|
||||
@@ -158,6 +188,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_uLastCode = KEYCODE;
|
||||
m_uLastMouseCode = 0;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
bool found = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
// clean repeat
|
||||
@@ -184,8 +216,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE));
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym));
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end());
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym), m_dPressedKeysyms.end());
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
|
||||
|
||||
@@ -194,7 +226,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
return !found && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
@@ -211,7 +243,7 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
|
||||
bool found = false;
|
||||
if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
|
||||
if (e->delta < 0) {
|
||||
if (e->delta < 0) {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
|
||||
} else {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
|
||||
@@ -233,6 +265,8 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
m_uLastCode = 0;
|
||||
m_uTimeLastMs = e->time_msec;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
|
||||
|
||||
@@ -244,7 +278,7 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
return !found && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
int repeatKeyHandler(void* data) {
|
||||
@@ -276,7 +310,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
}
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass") || k.shadowed)
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass" && k.handler != "mouse") || k.shadowed)
|
||||
continue;
|
||||
|
||||
if (!key.empty()) {
|
||||
@@ -305,7 +339,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.handler);
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
||||
|
||||
// Should never happen, as we check in the ConfigManager, but oh well
|
||||
if (DISPATCHER == m_mDispatchers.end()) {
|
||||
@@ -316,7 +350,10 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
|
||||
m_iPassPressed = (int)pressed;
|
||||
|
||||
DISPATCHER->second(k.arg);
|
||||
if (k.handler == "mouse")
|
||||
DISPATCHER->second((pressed ? "1" : "0") + k.arg);
|
||||
else
|
||||
DISPATCHER->second(k.arg);
|
||||
|
||||
m_iPassPressed = -1;
|
||||
|
||||
@@ -354,7 +391,7 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int&
|
||||
for (auto& pk : m_dPressedKeysyms) {
|
||||
if ((pk == KBKEY || pk == KBKEYUPPER)) {
|
||||
shadow = true;
|
||||
|
||||
|
||||
if (pk == doesntHave && doesntHave != 0) {
|
||||
shadow = false;
|
||||
break;
|
||||
@@ -475,6 +512,17 @@ void CKeybindManager::killActive(std::string args) {
|
||||
g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow);
|
||||
}
|
||||
|
||||
void CKeybindManager::kill(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "kill: no window found");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->closeWindow(PWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::clearKeybinds() {
|
||||
m_lKeybinds.clear();
|
||||
}
|
||||
@@ -512,7 +560,8 @@ void CKeybindManager::toggleActivePseudo(std::string args) {
|
||||
|
||||
ACTIVEWINDOW->m_bIsPseudotiled = !ACTIVEWINDOW->m_bIsPseudotiled;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(ACTIVEWINDOW);
|
||||
if (!ACTIVEWINDOW->m_bIsFullscreen)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(ACTIVEWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::changeworkspace(std::string args) {
|
||||
@@ -560,15 +609,12 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Workspace_back_and_forth being enabled means that an attempt to switch to
|
||||
// Workspace_back_and_forth being enabled means that an attempt to switch to
|
||||
// the current workspace will instead switch to the previous.
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(
|
||||
g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
static auto *const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
|
||||
if (*PBACKANDFORTH
|
||||
&& PCURRENTWORKSPACE->m_iID == workspaceToChangeTo
|
||||
&& PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1
|
||||
&& !internal) {
|
||||
|
||||
if (*PBACKANDFORTH && PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1 && !internal) {
|
||||
|
||||
workspaceToChangeTo = PCURRENTWORKSPACE->m_iPrevWorkspaceID;
|
||||
isSwitchingToPrevious = true;
|
||||
@@ -578,9 +624,11 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
static auto *const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
if (!*PALLOWWORKSPACECYCLES)
|
||||
PCURRENTWORKSPACE->m_iPrevWorkspaceID = -1;
|
||||
}
|
||||
|
||||
// remove constraints
|
||||
} else if (PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && !internal)
|
||||
return;
|
||||
|
||||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
// if it's not internal, we will unfocus to prevent stuck focus
|
||||
@@ -604,6 +652,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
|
||||
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = workspaceToChangeTo;
|
||||
}
|
||||
}
|
||||
|
||||
// change it
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
@@ -624,7 +679,8 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
}
|
||||
|
||||
// If the monitor is not the one our cursor's at, warp to it.
|
||||
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
|
||||
const bool anotherMonitor = PMONITOR != g_pCompositor->getMonitorFromCursor();
|
||||
if (anotherMonitor) {
|
||||
Vector2D middle = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f;
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
}
|
||||
@@ -639,7 +695,20 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
||||
|
||||
// focus
|
||||
g_pInputManager->refocus();
|
||||
if (const auto PWINDOW = PWORKSPACETOCHANGETO->getLastFocusedWindow(); PWINDOW) {
|
||||
// warp and focus
|
||||
if (anotherMonitor)
|
||||
g_pCompositor->warpCursorTo(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW, g_pXWaylandManager->getWindowSurface(PWINDOW));
|
||||
|
||||
if (g_pCompositor->cursorOnReservedArea()) // fix focus on bars etc
|
||||
g_pInputManager->refocus();
|
||||
} else if (g_pCompositor->getWindowsOnWorkspace(PWORKSPACETOCHANGETO->m_iID) > 0)
|
||||
g_pInputManager->refocus();
|
||||
|
||||
// set the new monitor as the last (no warps would bug otherwise)
|
||||
g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromID(PWORKSPACETOCHANGETO->m_iMonitorID);
|
||||
|
||||
// mark the monitor dirty
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
@@ -648,7 +717,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
}
|
||||
|
||||
// Workspace doesn't exist, create and switch
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
|
||||
|
||||
const auto PMONITOR = BOUNDMON ? BOUNDMON : g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
const auto OLDWORKSPACE = PMONITOR->activeWorkspace;
|
||||
|
||||
@@ -677,6 +748,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
PMONITOR->specialWorkspaceOpen = false;
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = workspaceToChangeTo;
|
||||
}
|
||||
}
|
||||
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
else
|
||||
@@ -689,6 +767,12 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
// mark the monitor dirty
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
// some stuf with the cursor and focus
|
||||
if (g_pCompositor->m_pLastMonitor != PMONITOR)
|
||||
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
|
||||
|
||||
g_pCompositor->m_pLastMonitor = PMONITOR;
|
||||
|
||||
// focus (clears the last)
|
||||
g_pInputManager->refocus();
|
||||
|
||||
@@ -735,8 +819,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
|
||||
auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
|
||||
auto PSAVEDSIZE = PWINDOW->m_vRealSize.goalv();
|
||||
auto PSAVEDPOS = PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
@@ -758,22 +842,18 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
PWINDOW->moveToWorkspace(PWORKSPACE->m_iID);
|
||||
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
|
||||
PWINDOW->m_bIsFullscreen = false;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID)->m_bIsFullscreen = false;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
PWINDOW->m_bIsFullscreen = false;
|
||||
PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10);
|
||||
PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// Hack: So that the layout doesnt find our window at the cursor
|
||||
PWINDOW->m_vPosition = Vector2D(-42069, -42069);
|
||||
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
|
||||
// and restore it
|
||||
@@ -792,10 +872,10 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->specialWorkspaceOpen = false;
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
}
|
||||
|
||||
@@ -834,7 +914,12 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
// may be null until later!
|
||||
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
|
||||
|
||||
const auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
|
||||
auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
|
||||
if (!PWORKSPACE) {
|
||||
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
|
||||
if (BOUNDMON)
|
||||
PMONITORNEW = BOUNDMON;
|
||||
}
|
||||
|
||||
const auto OLDWORKSPACEIDONMONITOR = PMONITORNEW->activeWorkspace;
|
||||
const auto OLDWORKSPACEIDRETURN = PMONITOR->activeWorkspace;
|
||||
@@ -863,6 +948,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
|
||||
g_pEventManager->m_bIgnoreEvents = false;
|
||||
|
||||
// manually post event cuz it got ignored above
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", PWINDOW, PWORKSPACE->m_szName.c_str())});
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
@@ -887,16 +975,27 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
if (PLASTWINDOW->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && PLASTWINDOW->m_bIsFullscreen) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PLASTWINDOW->m_iWorkspaceID);
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
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);
|
||||
g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID); // update last monitor
|
||||
|
||||
if (PWINDOWTOCHANGETO->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) {
|
||||
// event
|
||||
const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID);
|
||||
const auto PNEWWS = g_pCompositor->getWorkspaceByID(PNEWMON->activeWorkspace);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PNEWMON->szName + "," + PNEWWS->m_szName});
|
||||
|
||||
g_pCompositor->m_pLastMonitor = PNEWMON;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -909,13 +1008,13 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
if (PWINDOWTOCHANGETO) {
|
||||
switchToWindow(PWINDOWTOCHANGETO);
|
||||
} else {
|
||||
const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW);
|
||||
const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
|
||||
if (PWINDOWNEXT) {
|
||||
switchToWindow(PWINDOWNEXT);
|
||||
}
|
||||
@@ -1059,7 +1158,7 @@ void CKeybindManager::moveCursorToCorner(std::string arg) {
|
||||
}
|
||||
|
||||
void CKeybindManager::workspaceOpt(std::string args) {
|
||||
|
||||
|
||||
// current workspace
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
|
||||
@@ -1119,18 +1218,7 @@ void CKeybindManager::exitHyprland(std::string argz) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||
CMonitor* PMONITOR = nullptr;
|
||||
|
||||
try {
|
||||
if (!isNumber(args) && !isDirection(args)) {
|
||||
PMONITOR = g_pCompositor->getMonitorFromName(args);
|
||||
} else {
|
||||
PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(LOG, "moveCurrentWorkspaceToMonitor: caught exception in monitor", e.what());
|
||||
return;
|
||||
}
|
||||
CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
@@ -1151,19 +1239,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
std::string workspace = args.substr(0, args.find_first_of(' '));
|
||||
std::string monitor = args.substr(args.find_first_of(' ') + 1);
|
||||
|
||||
CMonitor* PMONITOR = nullptr;
|
||||
|
||||
try {
|
||||
if (!isNumber(monitor) && !isDirection(monitor)) {
|
||||
PMONITOR = g_pCompositor->getMonitorFromName(monitor);
|
||||
} else {
|
||||
PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(LOG, "moveWorkspaceToMonitor: caught exception in monitor", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
|
||||
|
||||
if (!PMONITOR){
|
||||
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
|
||||
@@ -1218,6 +1294,11 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
else
|
||||
g_pInputManager->refocus();
|
||||
} else {
|
||||
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
|
||||
|
||||
@@ -1231,9 +1312,12 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
PSPECIALWORKSPACE->startAnim(true, true);
|
||||
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
else
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::forceRendererReload(std::string args) {
|
||||
@@ -1252,7 +1336,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
@@ -1264,8 +1348,8 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
|
||||
|
||||
@@ -1284,6 +1368,9 @@ void CKeybindManager::moveWindow(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW);
|
||||
@@ -1301,7 +1388,10 @@ void CKeybindManager::resizeWindow(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
|
||||
|
||||
@@ -1320,11 +1410,14 @@ void CKeybindManager::circleNext(std::string arg) {
|
||||
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);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
@@ -1333,9 +1426,9 @@ void CKeybindManager::circleNext(std::string arg) {
|
||||
};
|
||||
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow, true));
|
||||
else
|
||||
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow, true));
|
||||
}
|
||||
|
||||
void CKeybindManager::focusWindow(std::string regexp) {
|
||||
@@ -1346,8 +1439,6 @@ void CKeybindManager::focusWindow(std::string regexp) {
|
||||
|
||||
Debug::log(LOG, "Focusing to window name: %s", PWINDOW->m_szTitle.c_str());
|
||||
|
||||
changeworkspace("[internal]" + std::to_string(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
const auto MIDPOINT = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
|
||||
@@ -1359,6 +1450,7 @@ void CKeybindManager::setSubmap(std::string submap) {
|
||||
if (submap == "reset" || submap == "") {
|
||||
m_szCurrentSelectedSubmap = "";
|
||||
Debug::log(LOG, "Reset active submap to the default one.");
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1366,6 +1458,7 @@ void CKeybindManager::setSubmap(std::string submap) {
|
||||
if (k.submap == submap) {
|
||||
m_szCurrentSelectedSubmap = submap;
|
||||
Debug::log(LOG, "Changed keybind submap to %s", submap.c_str());
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1402,7 +1495,7 @@ void CKeybindManager::pass(std::string regexp) {
|
||||
else
|
||||
wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, g_pXWaylandManager->getWindowSurface(PWINDOW), 1, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wlr_keyboard_modifiers kbmods = {g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0};
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &kbmods);
|
||||
@@ -1425,7 +1518,7 @@ void CKeybindManager::pass(std::string regexp) {
|
||||
} else {
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_PRESSED);
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WLR_BUTTON_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (XWTOXW)
|
||||
@@ -1471,7 +1564,7 @@ void CKeybindManager::dpms(std::string arg) {
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_output_enable(m->output, enable);
|
||||
|
||||
|
||||
if (!wlr_output_commit(m->output)) {
|
||||
Debug::log(ERR, "Couldn't commit output %s", m->szName.c_str());
|
||||
}
|
||||
@@ -1495,16 +1588,16 @@ void CKeybindManager::swapnext(std::string arg) {
|
||||
const auto PLASTCYCLED = g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow->m_pLastCycledWindow) && g_pCompositor->m_pLastWindow->m_pLastCycledWindow->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID ? g_pCompositor->m_pLastWindow->m_pLastCycledWindow : nullptr;
|
||||
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW);
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
|
||||
else
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW);
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
|
||||
|
||||
// sometimes we may come back to ourselves.
|
||||
if (toSwap == PLASTWINDOW) {
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW);
|
||||
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW), true;
|
||||
else
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW);
|
||||
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
|
||||
@@ -1526,3 +1619,56 @@ void CKeybindManager::swapActiveWorkspaces(std::string args) {
|
||||
|
||||
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
|
||||
}
|
||||
|
||||
void CKeybindManager::pinActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || !g_pCompositor->m_pLastWindow->m_bIsFloating || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
g_pCompositor->m_pLastWindow->m_bPinned = !g_pCompositor->m_pLastWindow->m_bPinned;
|
||||
g_pCompositor->m_pLastWindow->m_iWorkspaceID = g_pCompositor->getMonitorFromID(g_pCompositor->m_pLastWindow->m_iMonitorID)->activeWorkspace;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
|
||||
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal());
|
||||
}
|
||||
|
||||
void CKeybindManager::mouse(std::string args) {
|
||||
const auto TRUEARG = args.substr(1);
|
||||
const auto PRESSED = args[0] == '1';
|
||||
|
||||
if (TRUEARG == "movewindow") {
|
||||
if (PRESSED) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
}
|
||||
}
|
||||
} else if (TRUEARG == "resizewindow") {
|
||||
if (PRESSED) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
g_pInputManager->dragMode = MBIND_RESIZE;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ struct SKeybind {
|
||||
std::string submap = "";
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
bool mouse = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
|
||||
bool onAxisEvent(wlr_pointer_axis_event*);
|
||||
bool onMouseEvent(wlr_pointer_button_event*);
|
||||
|
||||
|
||||
void addKeybind(SKeybind);
|
||||
void removeKeybind(uint32_t, const std::string&);
|
||||
uint32_t stringToModMask(std::string);
|
||||
@@ -63,6 +64,8 @@ private:
|
||||
uint32_t m_uLastCode = 0;
|
||||
uint32_t m_uLastMouseCode = 0;
|
||||
|
||||
bool m_bIsMouseBindActive = false;
|
||||
|
||||
int m_iPassPressed = -1; // used for pass
|
||||
|
||||
CTimer m_tScrollTimer;
|
||||
@@ -75,9 +78,11 @@ private:
|
||||
xkb_state* m_pXKBTranslationState = nullptr;
|
||||
|
||||
void updateXKBTranslationState();
|
||||
bool ensureMouseBindState();
|
||||
|
||||
// -------------- Dispatchers -------------- //
|
||||
static void killActive(std::string);
|
||||
static void kill(std::string);
|
||||
static void spawn(std::string);
|
||||
static void toggleActiveFloating(std::string);
|
||||
static void toggleActivePseudo(std::string);
|
||||
@@ -112,6 +117,8 @@ private:
|
||||
static void dpms(std::string);
|
||||
static void swapnext(std::string);
|
||||
static void swapActiveWorkspaces(std::string);
|
||||
static void pinActive(std::string);
|
||||
static void mouse(std::string);
|
||||
|
||||
friend class CCompositor;
|
||||
friend class CInputManager;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
IHyprLayout* CLayoutManager::getCurrentLayout() {
|
||||
switch (m_iCurrentLayoutID) {
|
||||
case DWINDLE:
|
||||
case DWINDLE:
|
||||
return &m_cDwindleLayout;
|
||||
case MASTER:
|
||||
return &m_cMasterLayout;
|
||||
@@ -28,4 +28,4 @@ void CLayoutManager::switchToLayout(std::string layout) {
|
||||
} else {
|
||||
Debug::log(ERR, "Unknown layout %s!", layout.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,10 @@ int slowUpdate = 0;
|
||||
int handleTimer(void* data) {
|
||||
const auto PTM = (CThreadManager*)data;
|
||||
|
||||
g_pConfigManager->tick();
|
||||
static auto *const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
|
||||
|
||||
if (*PDISABLECFGRELOAD != 1)
|
||||
g_pConfigManager->tick();
|
||||
|
||||
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
|
||||
|
||||
@@ -19,8 +22,6 @@ CThreadManager::CThreadManager() {
|
||||
|
||||
HyprCtl::startHyprCtlSocket();
|
||||
|
||||
g_pCompositor->startHyprCtlTick();
|
||||
|
||||
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
|
||||
|
||||
wl_event_source_timer_update(m_esConfigTimer, 1000);
|
||||
|
@@ -32,9 +32,12 @@ wlr_surface* CHyprXWaylandManager::getWindowSurface(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) {
|
||||
if (!pSurface)
|
||||
return;
|
||||
|
||||
if (wlr_surface_is_xdg_surface(pSurface)) {
|
||||
const auto PSURF = wlr_xdg_surface_from_wlr_surface(pSurface);
|
||||
if (PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
|
||||
if (PSURF && PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
|
||||
wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate);
|
||||
}
|
||||
} else if (wlr_surface_is_xwayland_surface(pSurface)) {
|
||||
@@ -43,7 +46,7 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
|
||||
if (activate)
|
||||
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
@@ -59,6 +62,9 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
|
||||
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
|
||||
g_pCompositor->m_pLastWindow = pWindow;
|
||||
|
||||
if (!pWindow->m_bPinned)
|
||||
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) {
|
||||
@@ -160,7 +166,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -190,7 +196,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
return true;
|
||||
} else {
|
||||
const auto PSTATE = &pWindow->m_uSurface.xdg->toplevel->current;
|
||||
|
||||
|
||||
if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) || pWindow->m_uSurface.xdg->toplevel->parent)
|
||||
return true;
|
||||
}
|
||||
@@ -201,7 +207,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
void CHyprXWaylandManager::moveXWaylandWindow(CWindow* pWindow, const Vector2D& pos) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
|
||||
if (pWindow->m_bIsX11) {
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y);
|
||||
}
|
||||
@@ -216,7 +222,7 @@ void CHyprXWaylandManager::checkBorders(CWindow* pWindow) {
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_COMBO"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"]) {
|
||||
|
||||
|
||||
pWindow->m_bX11DoesntWantBorders = true;
|
||||
return;
|
||||
}
|
||||
|
@@ -2,16 +2,18 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
||||
static auto *const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
|
||||
static auto *const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
|
||||
static auto* const PSENSTORAW = &g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw")->intValue;
|
||||
|
||||
const auto DELTA = g_pConfigManager->getInt("input:force_no_accel") == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||
const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||
|
||||
if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1)
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * sensitivity, DELTA.y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
|
||||
if (*PSENSTORAW == 1)
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS, DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS);
|
||||
else
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy);
|
||||
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
|
||||
@@ -27,7 +29,6 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto *const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
@@ -138,17 +139,27 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then, we check if the workspace doesnt have a fullscreen window
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
if (!pFoundWindow) {
|
||||
// what the fuck, somehow happens occasionally??
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
return;
|
||||
}
|
||||
|
||||
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
|
||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||
|
||||
// only check floating because tiled cant be over fullscreen
|
||||
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && (*w)->m_bCreatedOverFullscreen) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
|
||||
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
|
||||
pFoundWindow = (*w).get();
|
||||
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
@@ -164,9 +175,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then windows
|
||||
if (!foundSurface) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
@@ -267,26 +275,36 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
if (pFoundWindow == g_pCompositor->m_pLastWindow && foundSurface != g_pCompositor->m_pLastFocus) {
|
||||
// we changed the subsurface
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
if (pFoundWindow == g_pCompositor->m_pLastWindow) {
|
||||
if (foundSurface != g_pCompositor->m_pLastFocus || m_bLastFocusOnLS) {
|
||||
// ^^^ changed the subsurface ^^^ came back from a LS
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
}
|
||||
|
||||
if (*PFOLLOWONDND && m_sDrag.dragIcon) {
|
||||
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);
|
||||
if (*PFOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow)
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
|
||||
m_bLastFocusOnLS = false;
|
||||
return; // don't enter any new surfaces
|
||||
} else {
|
||||
if ((*PFOLLOWMOUSE != 3 && allowKeyboardRefocus) || refocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
}
|
||||
|
||||
m_bLastFocusOnLS = false;
|
||||
} 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
|
||||
}
|
||||
|
||||
if (pFoundLayerSurface)
|
||||
m_bLastFocusOnLS = true;
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
@@ -354,7 +372,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
@@ -381,22 +399,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_bIsFloating)
|
||||
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
|
||||
|
||||
if ((e->button == BTN_LEFT || e->button == BTN_RIGHT) && wlr_keyboard_get_modifiers(PKEYBOARD) == (uint32_t)g_pConfigManager->getInt("general:main_mod_internal")) {
|
||||
currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
dragButton = e->button;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
if (currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
currentlyDraggedWindow = nullptr;
|
||||
dragButton = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -463,11 +467,11 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
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;
|
||||
@@ -498,7 +502,7 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
|
||||
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);
|
||||
@@ -595,7 +599,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
} 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);
|
||||
@@ -638,7 +642,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
|
||||
m_lMice.emplace_back();
|
||||
@@ -783,12 +787,17 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||
const auto PIMEGRAB = m_sIMERelay.getIMEKeyboardGrab(pKeyboard);
|
||||
|
||||
const auto ALLMODS = accumulateModsFromAllKBs();
|
||||
|
||||
auto MODS = wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers;
|
||||
MODS.depressed = ALLMODS;
|
||||
|
||||
if (PIMEGRAB && PIMEGRAB->pWlrKbGrab && PIMEGRAB->pWlrKbGrab->input_method) {
|
||||
wlr_input_method_keyboard_grab_v2_set_keyboard(PIMEGRAB->pWlrKbGrab, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_input_method_keyboard_grab_v2_send_modifiers(PIMEGRAB->pWlrKbGrab, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
|
||||
wlr_input_method_keyboard_grab_v2_send_modifiers(PIMEGRAB->pWlrKbGrab, &MODS);
|
||||
} else {
|
||||
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);
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &MODS);
|
||||
}
|
||||
|
||||
const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
|
||||
@@ -870,7 +879,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint);
|
||||
}
|
||||
|
||||
@@ -900,11 +909,7 @@ void CInputManager::unconstrainMouse() {
|
||||
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);
|
||||
}
|
||||
g_pXWaylandManager->activateSurface(g_pXWaylandManager->getWindowSurface(CONSTRAINTWINDOW), false);
|
||||
}
|
||||
|
||||
wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
@@ -945,6 +950,9 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
|
||||
uint32_t finalMask = 0;
|
||||
|
||||
for (auto& kb : m_lKeyboards) {
|
||||
if (kb.isVirtual)
|
||||
continue;
|
||||
|
||||
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
|
||||
}
|
||||
|
||||
@@ -961,7 +969,7 @@ std::string CInputManager::getActiveLayoutForKeyboard(SKeyboard* pKeyboard) {
|
||||
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)
|
||||
if (LAYOUTNAME)
|
||||
return std::string(LAYOUTNAME);
|
||||
return "error";
|
||||
}
|
||||
@@ -979,3 +987,22 @@ void CInputManager::disableAllKeyboards(bool virt) {
|
||||
k.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||
const auto PNEWDEV = &m_lTouchDevices.emplace_back();
|
||||
PNEWDEV->pWlrDevice = pDevice;
|
||||
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
|
||||
Debug::log(LOG, "New touch device added at %x", PNEWDEV);
|
||||
|
||||
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
|
||||
destroyTouchDevice((STouchDevice*)data);
|
||||
}, PNEWDEV, "TouchDevice");
|
||||
}
|
||||
|
||||
void CInputManager::destroyTouchDevice(STouchDevice* pDevice) {
|
||||
Debug::log(LOG, "Touch device at %x removed", pDevice);
|
||||
|
||||
m_lTouchDevices.remove(*pDevice);
|
||||
}
|
||||
|
@@ -12,6 +12,12 @@ enum eClickBehaviorMode {
|
||||
CLICKMODE_KILL
|
||||
};
|
||||
|
||||
enum eMouseBindMode {
|
||||
MBIND_INVALID = -1,
|
||||
MBIND_MOVE = 0,
|
||||
MBIND_RESIZE
|
||||
};
|
||||
|
||||
struct STouchData {
|
||||
CWindow* touchFocusWindow = nullptr;
|
||||
Vector2D touchSurfaceOrigin;
|
||||
@@ -23,13 +29,15 @@ public:
|
||||
void onMouseMoved(wlr_pointer_motion_event*);
|
||||
void onMouseWarp(wlr_pointer_motion_absolute_event*);
|
||||
void onMouseButton(wlr_pointer_button_event*);
|
||||
void onMouseWheel(wlr_pointer_axis_event*);
|
||||
void onMouseWheel(wlr_pointer_axis_event*);
|
||||
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
|
||||
void onKeyboardMod(void*, SKeyboard*);
|
||||
|
||||
void newKeyboard(wlr_input_device*);
|
||||
void newVirtualKeyboard(wlr_input_device*);
|
||||
void newMouse(wlr_input_device*, bool virt = false);
|
||||
void newTouchDevice(wlr_input_device*);
|
||||
void destroyTouchDevice(STouchDevice*);
|
||||
void destroyKeyboard(SKeyboard*);
|
||||
void destroyMouse(wlr_input_device*);
|
||||
|
||||
@@ -55,11 +63,14 @@ public:
|
||||
void onTouchUp(wlr_touch_up_event*);
|
||||
void onTouchMove(wlr_touch_motion_event*);
|
||||
|
||||
void onPointerHoldBegin(wlr_pointer_hold_begin_event*);
|
||||
void onPointerHoldEnd(wlr_pointer_hold_end_event*);
|
||||
|
||||
STouchData m_sTouchData;
|
||||
|
||||
// for dragging floating windows
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
int dragButton = -1;
|
||||
eMouseBindMode dragMode = MBIND_INVALID;
|
||||
|
||||
SDrag m_sDrag;
|
||||
|
||||
@@ -75,6 +86,9 @@ public:
|
||||
// idle inhibitors
|
||||
std::list<SIdleInhibitor> m_lIdleInhibitors;
|
||||
|
||||
// Touch devices
|
||||
std::list<STouchDevice> m_lTouchDevices;
|
||||
|
||||
void newTabletTool(wlr_input_device*);
|
||||
void newTabletPad(wlr_input_device*);
|
||||
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||
@@ -105,6 +119,9 @@ private:
|
||||
bool m_bEmptyFocusCursorSet = false;
|
||||
Vector2D m_vLastCursorPosFloored = Vector2D();
|
||||
|
||||
// for some bugs in follow mouse 0
|
||||
bool m_bLastFocusOnLS = false;
|
||||
|
||||
void processMouseDownNormal(wlr_pointer_button_event* e);
|
||||
void processMouseDownKill(wlr_pointer_button_event* e);
|
||||
|
||||
@@ -119,4 +136,4 @@ private:
|
||||
void applyConfigToKeyboard(SKeyboard*);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
||||
|
@@ -2,9 +2,7 @@
|
||||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CInputMethodRelay::CInputMethodRelay() {
|
||||
|
||||
}
|
||||
CInputMethodRelay::CInputMethodRelay() { }
|
||||
|
||||
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
if (m_pWLRIME) {
|
||||
@@ -99,7 +97,7 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
}, this, "IMERelay");
|
||||
|
||||
hyprListener_IMENewPopup.initCallback(&m_pWLRIME->events.new_popup_surface, [&](void* owner, void* data) {
|
||||
|
||||
|
||||
const auto PNEWPOPUP = &m_lIMEPopups.emplace_back();
|
||||
|
||||
PNEWPOPUP->pSurface = (wlr_input_popup_surface_v2*)data;
|
||||
@@ -122,7 +120,7 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
}
|
||||
|
||||
void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
if (!pPopup->pSurface->mapped)
|
||||
if (!pPopup->pSurface->mapped)
|
||||
return;
|
||||
|
||||
// damage last known pos & size
|
||||
@@ -406,7 +404,7 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) {
|
||||
for (auto& ti : m_lTextInputs) {
|
||||
if (ti.pPendingSurface) {
|
||||
|
||||
if (pSurface != ti.pPendingSurface)
|
||||
if (pSurface != ti.pPendingSurface)
|
||||
setPendingSurface(&ti, nullptr);
|
||||
|
||||
} else if (ti.pWlrInput->focused_surface) {
|
||||
@@ -448,4 +446,4 @@ void CInputMethodRelay::setPendingSurface(STextInput* pInput, wlr_surface* pSurf
|
||||
} else {
|
||||
pInput->hyprListener_pendingSurfaceDestroy.removeCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
|
||||
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
|
||||
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
|
||||
|
||||
@@ -11,7 +10,7 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
|
||||
int onMonitor = 0;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && w->m_iID != SPECIAL_WORKSPACE_ID) {
|
||||
onMonitor++;
|
||||
}
|
||||
}
|
||||
@@ -28,10 +27,15 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
|
||||
m_sActiveSwipe.avgSpeed = 0;
|
||||
m_sActiveSwipe.speedPoints = 0;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
ls->alpha = 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
return; // no valid swipe
|
||||
|
||||
@@ -49,6 +53,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
|
||||
|
||||
CWorkspace* pSwitchedTo = nullptr;
|
||||
|
||||
if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
|
||||
// revert
|
||||
if (abs(m_sActiveSwipe.delta) < 2) {
|
||||
@@ -66,6 +72,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
|
||||
}
|
||||
|
||||
pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin;
|
||||
} else if (m_sActiveSwipe.delta < 0) {
|
||||
// switch to left
|
||||
const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
|
||||
@@ -82,6 +90,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the left");
|
||||
|
||||
pSwitchedTo = PWORKSPACEL;
|
||||
} else {
|
||||
// switch to right
|
||||
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
|
||||
@@ -98,6 +108,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the right");
|
||||
|
||||
pSwitchedTo = PWORKSPACER;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
@@ -109,6 +121,11 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr;
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
// apply alpha
|
||||
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
@@ -127,8 +144,10 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
|
||||
|
||||
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
|
||||
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
|
||||
return;
|
||||
}
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true;
|
||||
|
||||
|
@@ -66,7 +66,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER)
|
||||
wlr_tablet_v2_tablet_tool_notify_slider(PTOOL->wlrTabletToolV2, EVENT->slider);
|
||||
|
||||
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL)
|
||||
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL)
|
||||
wlr_tablet_v2_tablet_tool_notify_wheel(PTOOL->wlrTabletToolV2, EVENT->wheel_delta, 0);
|
||||
|
||||
if (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_X)
|
||||
@@ -95,7 +95,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
else {
|
||||
wlr_send_tablet_v2_tablet_tool_up(PTOOL->wlrTabletToolV2);
|
||||
}
|
||||
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Button.initCallback(&wlr_tablet_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
|
||||
@@ -104,7 +104,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||
|
||||
wlr_tablet_v2_tablet_tool_notify_button(PTOOL->wlrTabletToolV2, (zwp_tablet_pad_v2_button_state)EVENT->button, (zwp_tablet_pad_v2_button_state)EVENT->state);
|
||||
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Proximity.initCallback(&wlr_tablet_from_input_device(pDevice)->events.proximity, [](void* owner, void* data) {
|
||||
@@ -120,13 +120,13 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||
PTOOL->pSurface = nullptr;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
PTOOL->active = true;
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->focusTablet(PTAB, EVENT->tool);
|
||||
}
|
||||
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, g_pCompositor->m_pLastMonitor->vecPosition.x + e->x * g_pCompositor->m_pLastMonitor->vecSize.x, g_pCompositor->m_pLastMonitor->vecPosition.y + e->y * g_pCompositor->m_pLastMonitor->vecSize.y);
|
||||
|
||||
refocus();
|
||||
@@ -26,7 +25,6 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::onTouchUp(wlr_touch_up_event* e){
|
||||
|
||||
if (m_sTouchData.touchFocusWindow) {
|
||||
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id);
|
||||
}
|
||||
@@ -42,4 +40,12 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e){
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onPointerHoldBegin(wlr_pointer_hold_begin_event* e) {
|
||||
wlr_pointer_gestures_v1_send_hold_begin(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, e->time_msec, e->fingers);
|
||||
}
|
||||
|
||||
void CInputManager::onPointerHoldEnd(wlr_pointer_hold_end_event* e) {
|
||||
wlr_pointer_gestures_v1_send_hold_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, e->time_msec, e->cancelled);
|
||||
}
|
||||
|
@@ -3,7 +3,8 @@
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h) {
|
||||
bool firstAlloc = false;
|
||||
|
||||
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted %ix%i)", w, h);
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
glGenFramebuffers(1, &m_iFb);
|
||||
@@ -77,4 +78,4 @@ void CFramebuffer::release() {
|
||||
|
||||
CFramebuffer::~CFramebuffer() {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "OpenGL.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include "Shaders.hpp"
|
||||
|
||||
CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), "Couldn't unset current EGL!");
|
||||
@@ -102,6 +103,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
@@ -120,11 +122,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
void CHyprOpenGLImpl::end() {
|
||||
// end the render, copy the data to the WLR framebuffer
|
||||
if (!m_bFakeFrame) {
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
if (!m_RenderData.pMonitor->mirrors.empty())
|
||||
g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
clear(CColor(11, 11, 11, 255));
|
||||
|
||||
m_bEndFrame = true;
|
||||
@@ -268,7 +273,7 @@ void CHyprOpenGLImpl::clear(const CColor& color) {
|
||||
scissor((wlr_box*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
||||
void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
|
||||
|
||||
if (!pBox) {
|
||||
@@ -278,17 +283,19 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
||||
|
||||
wlr_box newBox = *pBox;
|
||||
|
||||
int w, h;
|
||||
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
||||
if (transform) {
|
||||
int w, h;
|
||||
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
||||
|
||||
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
wlr_box_transform(&newBox, &newBox, TR, w, h);
|
||||
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
wlr_box_transform(&newBox, &newBox, TR, w, h);
|
||||
}
|
||||
|
||||
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
||||
void CHyprOpenGLImpl::scissor(const pixman_box32* pBox, bool transform) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
|
||||
|
||||
if (!pBox) {
|
||||
@@ -298,12 +305,12 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
||||
|
||||
wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
|
||||
|
||||
scissor(&newBox);
|
||||
scissor(&newBox, transform);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
|
||||
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h, bool transform) {
|
||||
wlr_box box = {x,y,w,h};
|
||||
scissor(&box);
|
||||
scissor(&box, transform);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
||||
@@ -449,8 +456,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
glUniform1i(shader->applyTint, 0);
|
||||
}
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
const float verts[] = {
|
||||
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
|
||||
@@ -458,6 +463,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
|
||||
};
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
} else {
|
||||
@@ -491,9 +498,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
// get transforms for the full monitor
|
||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
wlr_matrix_project_box(matrix, &MONITORBOX, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
float glMatrix[9];
|
||||
@@ -509,6 +516,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_copy(&damage, originalDamage);
|
||||
wlr_region_transform(&damage, &damage, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
|
||||
|
||||
// helper
|
||||
@@ -550,7 +558,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
if (pixman_region32_not_empty(pDamage)) {
|
||||
PIXMAN_DAMAGE_FOREACH(pDamage) {
|
||||
const auto RECT = RECTSARR[i];
|
||||
scissor(&RECT);
|
||||
scissor(&RECT, false /* this region is already transformed */);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
@@ -573,7 +581,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
// damage region will be scaled, make a temp
|
||||
pixman_region32_t tempDamage;
|
||||
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
|
||||
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_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage);
|
||||
|
||||
@@ -637,7 +645,9 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
|
||||
|
||||
clear(CColor(0,0,0,0));
|
||||
|
||||
m_bEndFrame = true; // fix transformed
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 255, &fakeDamage, 0, false, true, false);
|
||||
m_bEndFrame = false;
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
@@ -654,7 +664,7 @@ void CHyprOpenGLImpl::preWindowPass() {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == m_RenderData.pMonitor->activeWorkspace && !w->m_bHidden && w->m_bIsMapped && !w->m_bIsFloating) {
|
||||
hasWindows = true;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,7 +745,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
// render our great blurred FB
|
||||
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
|
||||
m_bEndFrame = true; // fix transformed
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false);
|
||||
m_bEndFrame = false;
|
||||
|
||||
// render the window, but clear stencil
|
||||
glClearStencil(0);
|
||||
@@ -769,27 +781,29 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
if (*PBORDERSIZE < 1)
|
||||
return;
|
||||
|
||||
int scaledBorderSize = *PBORDERSIZE * m_RenderData.pMonitor->scale;
|
||||
|
||||
if (round < 1) {
|
||||
// zero rounding, just lines
|
||||
wlr_box borderbox = {box->x - *PBORDERSIZE, box->y - *PBORDERSIZE, *PBORDERSIZE, box->height + 2 * *PBORDERSIZE};
|
||||
wlr_box borderbox = {box->x - scaledBorderSize, box->y - scaledBorderSize, scaledBorderSize, box->height + 2 * scaledBorderSize};
|
||||
renderRect(&borderbox, col, 0); // left
|
||||
borderbox = {box->x, box->y - (int)*PBORDERSIZE, box->width + (int)*PBORDERSIZE, (int)*PBORDERSIZE};
|
||||
borderbox = {box->x, box->y - (int)scaledBorderSize, box->width + (int)scaledBorderSize, (int)scaledBorderSize};
|
||||
renderRect(&borderbox, col, 0); // top
|
||||
borderbox = {box->x + box->width, box->y, (int)*PBORDERSIZE, box->height + (int)*PBORDERSIZE};
|
||||
borderbox = {box->x + box->width, box->y, (int)scaledBorderSize, box->height + (int)scaledBorderSize};
|
||||
renderRect(&borderbox, col, 0); // right
|
||||
borderbox = {box->x, box->y + box->height, box->width, (int)*PBORDERSIZE};
|
||||
borderbox = {box->x, box->y + box->height, box->width, (int)scaledBorderSize};
|
||||
renderRect(&borderbox, col, 0); // bottom
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// adjust box
|
||||
box->x -= *PBORDERSIZE;
|
||||
box->y -= *PBORDERSIZE;
|
||||
box->width += 2 * *PBORDERSIZE;
|
||||
box->height += 2 * *PBORDERSIZE;
|
||||
box->x -= scaledBorderSize;
|
||||
box->y -= scaledBorderSize;
|
||||
box->width += 2 * scaledBorderSize;
|
||||
box->height += 2 * scaledBorderSize;
|
||||
|
||||
round += *PBORDERSIZE;
|
||||
round += scaledBorderSize;
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
@@ -816,7 +830,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
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);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
|
||||
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -1081,18 +1095,40 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
|
||||
void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
|
||||
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0, false, false);
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderMirrored() {
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
|
||||
|
||||
if (PFB->m_cTex.m_iTexID <= 0)
|
||||
return;
|
||||
|
||||
renderTexture(PFB->m_cTex, &monbox, 255.f, 0, false, false);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE, double offsetY) {
|
||||
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
|
||||
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
|
||||
cairo_set_font_size(CAIRO, FONTSIZE);
|
||||
|
||||
cairo_set_source_rgba(CAIRO, 1.f, 1.f, 1.f, 0.32f);
|
||||
cairo_set_source_rgba(CAIRO, 1.0, 1.0, 1.0, 0.32);
|
||||
|
||||
cairo_text_extents_t textExtents;
|
||||
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
|
||||
|
||||
cairo_move_to(CAIRO, m_RenderData.pMonitor->vecTransformedSize.x / 2.f - textExtents.width / 2.f, m_RenderData.pMonitor->vecTransformedSize.y - textExtents.height - 1);
|
||||
cairo_move_to(CAIRO, (m_RenderData.pMonitor->vecPixelSize.x - textExtents.width) / 2.0, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height + offsetY);
|
||||
|
||||
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
|
||||
|
||||
cairo_surface_flush(CAIROSURFACE);
|
||||
@@ -1134,13 +1170,37 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
|
||||
PTEX->m_vSize = textureSize;
|
||||
|
||||
// calc the target box
|
||||
const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
|
||||
const double WPRATIO = 1.77;
|
||||
|
||||
Vector2D origin;
|
||||
double scale;
|
||||
|
||||
if (MONRATIO > WPRATIO) {
|
||||
scale = m_RenderData.pMonitor->vecTransformedSize.x / PTEX->m_vSize.x;
|
||||
|
||||
origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - PTEX->m_vSize.y * scale) / 2.0;
|
||||
} else {
|
||||
scale = m_RenderData.pMonitor->vecTransformedSize.y / PTEX->m_vSize.y;
|
||||
|
||||
origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - PTEX->m_vSize.x * scale) / 2.0;
|
||||
}
|
||||
|
||||
wlr_box box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
|
||||
|
||||
// create a new one with cairo
|
||||
const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str());
|
||||
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
||||
// scale it to fit the current monitor
|
||||
cairo_scale(CAIRO, textureSize.x / pMonitor->vecTransformedSize.x, textureSize.y / pMonitor->vecTransformedSize.y);
|
||||
|
||||
// render splash on wallpaper
|
||||
if (!*PNOSPLASH)
|
||||
renderSplash(CAIRO, CAIROSURFACE);
|
||||
renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO);
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
@@ -1156,28 +1216,6 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
cairo_surface_destroy(CAIROSURFACE);
|
||||
cairo_destroy(CAIRO);
|
||||
|
||||
// calc the target box
|
||||
|
||||
const float MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
|
||||
const float WPRATIO = 1.77f;
|
||||
|
||||
Vector2D origin;
|
||||
float scale;
|
||||
|
||||
if (MONRATIO > WPRATIO) {
|
||||
scale = m_RenderData.pMonitor->vecTransformedSize.x / PTEX->m_vSize.x;
|
||||
|
||||
origin.y = -(PTEX->m_vSize.y * scale - m_RenderData.pMonitor->vecTransformedSize.y) / 2.f / scale;
|
||||
} else {
|
||||
scale = m_RenderData.pMonitor->vecTransformedSize.y / PTEX->m_vSize.y;
|
||||
|
||||
origin.x = -(PTEX->m_vSize.x * scale - m_RenderData.pMonitor->vecTransformedSize.x) / 2.f / scale;
|
||||
}
|
||||
|
||||
wlr_box box = {origin.x * scale, origin.y * scale, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
|
||||
|
||||
Debug::log(LOG, "Background created for monitor %s", pMonitor->szName.c_str());
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "Shaders.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
@@ -33,8 +32,10 @@ inline const float fanVertsFull[] = {
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer mirrorFB;
|
||||
CFramebuffer mirrorSwapFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs
|
||||
|
||||
CTexture stencilTex;
|
||||
|
||||
@@ -91,9 +92,9 @@ public:
|
||||
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const wlr_box*);
|
||||
void scissor(const pixman_box32*);
|
||||
void scissor(const int x, const int y, const int w, const int h);
|
||||
void scissor(const wlr_box*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
|
||||
void destroyMonitorResources(CMonitor*);
|
||||
|
||||
@@ -102,6 +103,9 @@ public:
|
||||
void preWindowPass();
|
||||
void preRender(CMonitor*);
|
||||
|
||||
void saveBufferForMirror();
|
||||
void renderMirrored();
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
@@ -135,10 +139,9 @@ private:
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false);
|
||||
|
||||
void renderSplash(cairo_t *const, cairo_surface_t *const);
|
||||
void renderSplash(cairo_t *const, cairo_surface_t *const, double);
|
||||
|
||||
void preBlurForCurrentMonitor();
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
||||
|
@@ -15,8 +15,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
if (RDATA->surface && surface == RDATA->surface)
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
||||
else // here we clamp to 2, these might be some tiny specks
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::clamp(surface->current.width, 2, 1337420), std::clamp(surface->current.height, 2, 1337420)};
|
||||
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
||||
|
||||
if (RDATA->squishOversized) {
|
||||
if (x + windowBox.width > RDATA->w)
|
||||
windowBox.width = RDATA->w - x;
|
||||
@@ -26,7 +26,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
|
||||
if (RDATA->pWindow)
|
||||
g_pHyprRenderer->calculateUVForWindowSurface(RDATA->pWindow, surface, RDATA->squishOversized);
|
||||
|
||||
|
||||
scaleBox(&windowBox, RDATA->output->scale);
|
||||
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
@@ -65,11 +65,14 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
return false;
|
||||
|
||||
if (pWindow->m_bPinned)
|
||||
return true;
|
||||
|
||||
// now check if it has the same workspace
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
|
||||
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()) {
|
||||
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering) {
|
||||
return true;
|
||||
} else {
|
||||
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
|
||||
@@ -99,6 +102,9 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering)
|
||||
return true;
|
||||
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return true;
|
||||
|
||||
@@ -116,11 +122,39 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
|
||||
CWindow* pWorkspaceWindow = nullptr;
|
||||
|
||||
// loop over the tiled windows that are fading out
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsFullscreen || w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// and floating ones too
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsFullscreen || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
||||
|
||||
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen){
|
||||
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering)))
|
||||
continue;
|
||||
|
||||
if (w->m_iMonitorID != pMonitor->ID)
|
||||
@@ -135,9 +169,9 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
|
||||
pWorkspaceWindow = w.get();
|
||||
}
|
||||
|
||||
// then render windows over fullscreen
|
||||
// then render windows over fullscreen.
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || !w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
@@ -159,13 +193,12 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
|
||||
}
|
||||
|
||||
// and the overlay layers
|
||||
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
// on non-full we draw the bar and shit
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (ls->alpha.fl() != 0.f)
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
@@ -186,17 +219,17 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec();
|
||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
|
||||
static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
|
||||
|
||||
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
|
||||
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
|
||||
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.w = std::max(pWindow->m_vRealSize.vec().x, 5.0); // clamp the size to min 5,
|
||||
renderdata.h = std::max(pWindow->m_vRealSize.vec().y, 5.0); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : (PWORKSPACE->m_fAlpha.fl() / 255.f));
|
||||
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
|
||||
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||
@@ -374,7 +407,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
|
||||
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
@@ -459,8 +492,8 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * ((double)pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * ((double)pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y)));
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * (pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * (pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y)));
|
||||
}
|
||||
} else {
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
@@ -703,6 +736,8 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
||||
if (PMONITOR->damage)
|
||||
damageMonitor(PMONITOR);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor);
|
||||
|
||||
Debug::log(LOG, "Monitor %s layers arranged: reserved: %f %f %f %f", PMONITOR->szName.c_str(), PMONITOR->vecReservedTopLeft.x, PMONITOR->vecReservedTopLeft.y, PMONITOR->vecReservedBottomRight.x, PMONITOR->vecReservedBottomRight.y);
|
||||
}
|
||||
|
||||
@@ -770,7 +805,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
||||
return;
|
||||
|
||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
@@ -787,6 +822,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->isMirror())
|
||||
continue; // don't damage mirrors traditionally
|
||||
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
m->addDamage(&damageBox);
|
||||
@@ -810,6 +848,19 @@ void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
|
||||
for (auto& mirror : pMonitor->mirrors) {
|
||||
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
|
||||
|
||||
pixman_region32_t rg;
|
||||
pixman_region32_init(&rg);
|
||||
pixman_region32_copy(&rg, pRegion);
|
||||
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
|
||||
pMonitor->addDamage(&rg);
|
||||
pixman_region32_fini(&rg);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
||||
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
||||
return;
|
||||
@@ -873,7 +924,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecPosition = pMonitorRule->offset;
|
||||
|
||||
// loop over modes and choose an appropriate one.
|
||||
if (pMonitorRule->resolution != Vector2D()) {
|
||||
if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1,-1) && pMonitorRule->resolution != Vector2D(-1,-2)) {
|
||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
||||
wlr_output_mode* mode;
|
||||
bool found = false;
|
||||
@@ -906,6 +957,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
if (!found) {
|
||||
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
|
||||
pMonitor->vecSize = pMonitorRule->resolution;
|
||||
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
||||
|
||||
if (!wlr_output_test(pMonitor->output)) {
|
||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||
@@ -934,8 +986,95 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
} else {
|
||||
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
|
||||
pMonitor->vecSize = pMonitorRule->resolution;
|
||||
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
||||
|
||||
Debug::log(LOG, "Setting custom mode for %s", pMonitor->output->name);
|
||||
if (!wlr_output_test(pMonitor->output)) {
|
||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||
|
||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||
|
||||
if (!PREFERREDMODE) {
|
||||
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Preferred is valid
|
||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
||||
|
||||
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f", pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
||||
|
||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
||||
} else {
|
||||
Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
||||
}
|
||||
}
|
||||
} else if (pMonitorRule->resolution != Vector2D()) {
|
||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
||||
wlr_output_mode* mode;
|
||||
float currentWidth = 0;
|
||||
float currentHeight = 0;
|
||||
float currentRefresh = 0;
|
||||
bool success = false;
|
||||
|
||||
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
|
||||
if(pMonitorRule->resolution == Vector2D(-1,-1)) {
|
||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
||||
if( ( mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= ( currentRefresh - 1000.f ) ) || mode->refresh > ( currentRefresh + 3000.f ) ) {
|
||||
wlr_output_set_mode(pMonitor->output, mode);
|
||||
if (wlr_output_test(pMonitor->output)) {
|
||||
currentWidth = mode->width;
|
||||
currentHeight = mode->height;
|
||||
currentRefresh = mode->refresh;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
||||
if( ( mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= ( currentRefresh - 1000.f ) ) || ( mode->width > currentWidth && mode->height > currentHeight ) ) {
|
||||
wlr_output_set_mode(pMonitor->output, mode);
|
||||
if (wlr_output_test(pMonitor->output)) {
|
||||
currentWidth = mode->width;
|
||||
currentHeight = mode->height;
|
||||
currentRefresh = mode->refresh;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Debug::log(LOG, "Monitor %s: REJECTED mode: %ix%i@%2f! Falling back to preferred.",
|
||||
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
|
||||
mode->width, mode->height, mode->refresh / 1000.f);
|
||||
|
||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||
|
||||
if (!PREFERREDMODE) {
|
||||
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
|
||||
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Preferred is valid
|
||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
||||
|
||||
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
|
||||
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
|
||||
PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
||||
|
||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
||||
} else {
|
||||
|
||||
Debug::log(LOG, "Monitor %s: Applying highest mode %ix%i@%2f.",
|
||||
pMonitor->output->name, (int)currentWidth, (int)currentHeight, (int)currentRefresh / 1000.f,
|
||||
mode->width, mode->height, mode->refresh / 1000.f);
|
||||
|
||||
pMonitor->refreshRate = currentRefresh / 1000.f;
|
||||
pMonitor->vecSize = Vector2D(currentWidth, currentHeight);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||
@@ -977,13 +1116,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
Debug::log(LOG, "Setting preferred mode for %s", pMonitor->output->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
|
||||
pMonitor->transform = pMonitorRule->transform;
|
||||
|
||||
pMonitor->vecPixelSize = pMonitor->vecSize;
|
||||
|
||||
// Adaptive sync (VRR)
|
||||
wlr_output_enable_adaptive_sync(pMonitor->output, 1);
|
||||
|
||||
if (!wlr_output_test(pMonitor->output)) {
|
||||
Debug::log(LOG, "Pending output %s does not accept VRR.", pMonitor->output->name);
|
||||
wlr_output_enable_adaptive_sync(pMonitor->output, 0);
|
||||
}
|
||||
|
||||
// update renderer
|
||||
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
||||
|
||||
@@ -1013,7 +1160,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecPosition = finalPos;
|
||||
}
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
if (!pMonitor->isMirror())
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
|
||||
wlr_output_enable(pMonitor->output, true);
|
||||
|
||||
@@ -1026,6 +1174,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
// frame skip
|
||||
pMonitor->framesToSkip = 1;
|
||||
|
||||
// reload to fix mirrors
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(pixman_region32_t*);
|
||||
void damageMonitor(CMonitor*);
|
||||
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
|
||||
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, CMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
|
@@ -38,7 +38,7 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
|
||||
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
|
||||
@@ -56,38 +56,26 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0))
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
if (!m_pWindow->m_sSpecialRenderData.decorate)
|
||||
return;
|
||||
|
||||
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
|
||||
static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->strValue;
|
||||
static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->vecValue;
|
||||
|
||||
if (*PSHADOWS != 1)
|
||||
return; // disabled
|
||||
|
||||
// get the real offset
|
||||
Vector2D offset;
|
||||
try {
|
||||
if (const auto SPACEPOS = PSHADOWOFFSET->find(' '); SPACEPOS != std::string::npos) {
|
||||
const auto X = PSHADOWOFFSET->substr(0, SPACEPOS);
|
||||
const auto Y = PSHADOWOFFSET->substr(SPACEPOS + 1);
|
||||
|
||||
if (isNumber(X, true) && isNumber(Y, true)) {
|
||||
offset = Vector2D(std::stof(X), std::stof(Y));
|
||||
}
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
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}};
|
||||
m_seExtents = {{*PSHADOWSIZE + 2 - PSHADOWOFFSET->x, *PSHADOWSIZE + 2 - PSHADOWOFFSET->y}, {*PSHADOWSIZE + 2 + PSHADOWOFFSET->x, *PSHADOWSIZE + 2 + PSHADOWOFFSET->y}};
|
||||
|
||||
// draw the shadow
|
||||
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
|
||||
|
||||
|
||||
fullBox.x -= pMonitor->vecPosition.x;
|
||||
fullBox.y -= pMonitor->vecPosition.y;
|
||||
|
||||
@@ -108,7 +96,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
|
||||
|
||||
scaleBox(&windowBox, pMonitor->scale);
|
||||
|
||||
|
||||
if (windowBox.width < 1 || windowBox.height < 1) {
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
@@ -22,13 +22,13 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
|
||||
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||
// we draw 3px above the window's border with 3px
|
||||
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
|
||||
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
|
||||
m_seExtents.topLeft = Vector2D(0, *PBORDERSIZE + 3 + 3);
|
||||
m_seExtents.bottomRight = Vector2D();
|
||||
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
|
||||
@@ -45,7 +45,7 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
// get the group info
|
||||
SLayoutMessageHeader header;
|
||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||
header.pWindow = m_pWindow;
|
||||
|
||||
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
|
||||
|
||||
@@ -70,6 +70,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
if (barsToDraw < 1 || m_pWindow->m_bHidden || !g_pCompositor->windowValidMapped(m_pWindow))
|
||||
return;
|
||||
|
||||
if (!m_pWindow->m_sSpecialRenderData.decorate)
|
||||
return;
|
||||
|
||||
const int PAD = 2; //2px
|
||||
|
||||
const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw;
|
||||
@@ -82,7 +85,12 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
break;
|
||||
|
||||
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
|
||||
scaleBox(&rect, pMonitor->scale);
|
||||
|
||||
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
|
||||
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
|
||||
|
||||
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(*PGROUPCOLACTIVE) : CColor(*PGROUPCOLINACTIVE);
|
||||
color.a *= a;
|
||||
g_pHyprOpenGL->renderRect(&rect, color);
|
||||
|
||||
|
@@ -3,5 +3,5 @@
|
||||
#include "../../Window.hpp"
|
||||
|
||||
IHyprWindowDecoration::~IHyprWindowDecoration() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ void main() {
|
||||
vec4 pixColor = v_color;
|
||||
|
||||
bool done = false;
|
||||
|
||||
|
||||
// check for edges
|
||||
if (pixCoord[0] < topLeft[0]) {
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
@@ -88,4 +88,4 @@ void main() {
|
||||
|
||||
gl_FragColor = pixColor;
|
||||
}
|
||||
)#";
|
||||
)#";
|
||||
|
@@ -59,7 +59,7 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
if (!done) {
|
||||
// distance to all straight bb borders
|
||||
float distanceT = pixCoord[1];
|
||||
float distanceB = fullSize[1] - pixCoord[1];
|
||||
@@ -79,4 +79,4 @@ void main() {
|
||||
}
|
||||
|
||||
gl_FragColor = pixColor;
|
||||
})#";
|
||||
})#";
|
||||
|
@@ -267,7 +267,7 @@ void main() {
|
||||
pixColor[1] = pixColor[1] * tint[1];
|
||||
pixColor[2] = pixColor[2] * tint[2];
|
||||
}
|
||||
|
||||
|
||||
vec2 pixCoord = fullSize * v_texcoord;
|
||||
|
||||
)#" + ROUNDED_SHADER_FUNC("pixColor") +
|
||||
@@ -310,7 +310,7 @@ void main() {
|
||||
vec2 uv = v_texcoord / 2.0;
|
||||
|
||||
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
|
||||
|
||||
|
||||
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
|
||||
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||
|
Submodule subprojects/wlroots updated: 7c575922c0...50cc1ef4d3
Reference in New Issue
Block a user