mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-26 17:51:53 -07:00
Compare commits
179 Commits
v0.9.1beta
...
v0.10.3bet
Author | SHA1 | Date | |
---|---|---|---|
|
61aa4ff70e | ||
|
cc3f0ff9e7 | ||
|
7af193d921 | ||
|
132c96f867 | ||
|
45a0e69286 | ||
|
0ebef9a8ae | ||
|
185f93ae64 | ||
|
1b1a0259a8 | ||
|
223ca6e286 | ||
|
f0ad77251b | ||
|
c2a3896cc9 | ||
|
e749331f30 | ||
|
69d17bf424 | ||
|
946222f4a7 | ||
|
504d07a87d | ||
|
81b27be6bb | ||
|
f9e30e985c | ||
|
6cae44e2c0 | ||
|
43aea417b0 | ||
|
ece3ac97f9 | ||
|
9b62328b22 | ||
|
c1a64a2b9d | ||
|
b078a12eed | ||
|
eca6e53bd7 | ||
|
f2d3aecf00 | ||
|
f3c597bfb7 | ||
|
c5a4c83f78 | ||
|
f4d11d2d43 | ||
|
4c1dba643e | ||
|
5a20573e91 | ||
|
cd9c85a150 | ||
|
bbc6b5d5e0 | ||
|
a59641096c | ||
|
c6de4ee4b7 | ||
|
317b6c430c | ||
|
095487ea5d | ||
|
daeb0d3418 | ||
|
7cde50a018 | ||
|
bec7501365 | ||
|
ea45c6bfe0 | ||
|
6e2467cc24 | ||
|
454d0d3f9f | ||
|
d2011a4ba9 | ||
|
b0b3a5af10 | ||
|
d47bfe6af1 | ||
|
c982312c07 | ||
|
f0fe0c25d6 | ||
|
d906617fb6 | ||
|
ed1b72f37d | ||
|
28867758c4 | ||
|
920727cbba | ||
|
bfe0f844d2 | ||
|
214c2c7b1c | ||
|
9136783e9c | ||
|
662b6003c6 | ||
|
c136078239 | ||
|
38056c0102 | ||
|
db35a1c6d0 | ||
|
66b0622bc5 | ||
|
0e57651e2f | ||
|
e5ab9643be | ||
|
b3c5809986 | ||
|
ae175fdda5 | ||
|
9102471610 | ||
|
f85c765634 | ||
|
37442db20e | ||
|
b178891ab3 | ||
|
073f08301a | ||
|
8fb4669b85 | ||
|
008cc63dc0 | ||
|
aba63a7f96 | ||
|
c9ed5bf77e | ||
|
f4f0495050 | ||
|
c319a2aba9 | ||
|
cd75606f42 | ||
|
c7350117f1 | ||
|
69db6207c0 | ||
|
58ff04fdf3 | ||
|
9b39a0c2e0 | ||
|
f64f94ca56 | ||
|
76877d4b15 | ||
|
96f3b62429 | ||
|
0162da7a7c | ||
|
9eb750c00b | ||
|
03f2e4d42a | ||
|
15fc0892c7 | ||
|
a564be73c5 | ||
|
7e8666754f | ||
|
c043bcdee6 | ||
|
8e5985d70e | ||
|
9255a4d2ff | ||
|
113ac67a16 | ||
|
862722412f | ||
|
a6d4a4d5f3 | ||
|
e2f61e267e | ||
|
ecce027c02 | ||
|
f28b71232a | ||
|
af9d34ab77 | ||
|
2d33d4aebc | ||
|
aa39653ea1 | ||
|
6d788f0fc9 | ||
|
ab6a62f0fd | ||
|
d460519c30 | ||
|
b60b52c5cf | ||
|
5aed6f1bc7 | ||
|
5cec6257e9 | ||
|
6f137938da | ||
|
9fca4b5bc2 | ||
|
87a2ecb90e | ||
|
bf9d358d3b | ||
|
9532ff4287 | ||
|
d64227e7c7 | ||
|
3a8dcf284a | ||
|
1744be7bdd | ||
|
9fcfaaadb6 | ||
|
355ee15039 | ||
|
9564a4cd12 | ||
|
64e80991ca | ||
|
3829b1626e | ||
|
5ce7c71cef | ||
|
793b23dbe6 | ||
|
070db65a24 | ||
|
6aa448534f | ||
|
6357a92e46 | ||
|
68fd97fae9 | ||
|
1b109d9242 | ||
|
69b8568ccf | ||
|
ccd68049f7 | ||
|
206b7f4372 | ||
|
aa7177a9e4 | ||
|
59088decd0 | ||
|
c77b571fa7 | ||
|
49f5ae2ef3 | ||
|
74cbfdcda4 | ||
|
f66365d9da | ||
|
b30bb22bb8 | ||
|
d72f1cc644 | ||
|
78e4f274bc | ||
|
14026d4484 | ||
|
f44af0366f | ||
|
cd37a1533e | ||
|
575434f1a4 | ||
|
97e82fa4fb | ||
|
4ea37fe64d | ||
|
ad42392856 | ||
|
e0ada97a24 | ||
|
9a8a6317ff | ||
|
cb5521ec6e | ||
|
1c4d0e8c18 | ||
|
9f11765707 | ||
|
3947fe9e9f | ||
|
c7c0149c08 | ||
|
d58233d08b | ||
|
07f68bf72a | ||
|
5e97fe8fcd | ||
|
81308a9cc3 | ||
|
5dcbce550f | ||
|
5a96142cf8 | ||
|
9540106959 | ||
|
69558acb2e | ||
|
37068cf4f0 | ||
|
587330d864 | ||
|
9991db159c | ||
|
f488ec166d | ||
|
871c81ac1a | ||
|
36e563c79c | ||
|
69365c7609 | ||
|
c3edb20e04 | ||
|
b9be405d32 | ||
|
8dd88d901d | ||
|
996e5a9e69 | ||
|
fff7534721 | ||
|
cd483a7a37 | ||
|
e13f2480ff | ||
|
f36cd350cc | ||
|
c779a7c03b | ||
|
179e5188a4 | ||
|
d3c96c248c | ||
|
3fabf1c483 |
13
README.md
13
README.md
@@ -17,9 +17,7 @@
|
||||
|
||||
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
||||
|
||||
For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
||||
|
||||
Please note, especially for folks moving from Hypr, that Hyprland and Hypr share a very different feature set and are not 1:1 experiences.
|
||||
It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, and more.
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -70,6 +68,7 @@ Try it out and report bugs / suggestions!
|
||||
- Full damage tracking
|
||||
- Docks support
|
||||
- Drawing tablet support
|
||||
- Native IME + Input panels support
|
||||
- and much more...
|
||||
|
||||
<br>
|
||||
@@ -124,7 +123,7 @@ Try it out and report bugs / suggestions!
|
||||
|
||||
<!----------------------------------------------------------------------------->
|
||||
|
||||
[Configure]: https://github.com/hyprwm/Hyprland/wiki/Configuring-Hyprland
|
||||
[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
[Discord]: https://discord.gg/hQ9XvMUjjr
|
||||
[Stars]: https://starchart.cc/hyprwm/Hyprland
|
||||
[Hypr]: https://github.com/hyprwm/Hypr
|
||||
@@ -133,9 +132,9 @@ Try it out and report bugs / suggestions!
|
||||
[Issues]: https://github.com/hyprwm/Hyprland/issues
|
||||
[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
|
||||
|
||||
[Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
|
||||
[Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
|
||||
[Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
|
||||
[Contribute]: https://wiki.hyprland.org/Contributing-and-Debugging/
|
||||
[Install]: https://wiki.hyprland.org/Getting-Started/Installation/
|
||||
[Quick Start]: https://wiki.hyprland.org/Getting-Started/Quick-start/
|
||||
[License]: LICENSE
|
||||
|
||||
|
||||
|
@@ -8,10 +8,11 @@
|
||||
# For a full list, see the wiki (basic and advanced configuring)
|
||||
#
|
||||
|
||||
monitor=,preferred,0x0,1
|
||||
monitor=,preferred,auto,1
|
||||
workspace=DP-1,1
|
||||
|
||||
input {
|
||||
kb_file=
|
||||
kb_layout=
|
||||
kb_variant=
|
||||
kb_model=
|
||||
@@ -112,4 +113,4 @@ bind=ALT,9,movetoworkspace,9
|
||||
bind=ALT,0,movetoworkspace,10
|
||||
|
||||
bind=SUPER,mouse_down,workspace,e+1
|
||||
bind=SUPER,mouse_up,workspace,e-1
|
||||
bind=SUPER,mouse_up,workspace,e-1
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1659219666,
|
||||
"narHash": "sha256-pzYr5fokQPHv7CmUXioOhhzDy/XyWOIXP4LZvv/T7Mk=",
|
||||
"lastModified": 1660908602,
|
||||
"narHash": "sha256-SwZ85IPWvC4NxxFhWhRMTJpApSHbY1u4YK2UFWEBWvY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7b9be38c7250b22d829ab6effdee90d5e40c6e5c",
|
||||
"rev": "495b19d5b3e62b4ec7e846bdfb6ef3d9c3b83492",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1658770113,
|
||||
"narHash": "sha256-VBq9vw0hvQPKGKLNKLJS8xsUHvrX0o2LUDBVolixenE=",
|
||||
"lastModified": 1660930713,
|
||||
"narHash": "sha256-bY7q1NqG/sjCUAWPn/Ne9NCigLlPlH5Lk1WCMqv3rTU=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "7b5e890e61a27375725068a7d1884b26851b3102",
|
||||
"rev": "7c575922c05e4d5fd9a403c2aa631a54c7531d44",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -17,6 +17,7 @@
|
||||
inherit (nixpkgs) lib;
|
||||
genSystems = lib.genAttrs [
|
||||
# Add more systems if they are supported
|
||||
"aarch64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
pkgsFor = nixpkgs.legacyPackages;
|
||||
@@ -33,7 +34,7 @@
|
||||
});
|
||||
hyprland = prev.callPackage ./nix/default.nix {
|
||||
stdenv = prev.gcc12Stdenv;
|
||||
version = "0.9.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
|
||||
version = "0.10.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
|
||||
wlroots = wlroots-hyprland;
|
||||
};
|
||||
hyprland-debug = hyprland.override {debug = true;};
|
||||
|
@@ -34,6 +34,8 @@ commands:
|
||||
splash
|
||||
hyprpaper
|
||||
reload
|
||||
setcursor
|
||||
getoption
|
||||
|
||||
flags:
|
||||
-j -> output in JSON
|
||||
@@ -183,6 +185,17 @@ void hyprpaperRequest(int argc, char** argv) {
|
||||
requestHyprpaper(rq);
|
||||
}
|
||||
|
||||
void setcursorRequest(int argc, char** argv) {
|
||||
if (argc < 4) {
|
||||
std::cout << "setcursor requires 2 params";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string rq = "setcursor " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||
|
||||
request(rq);
|
||||
}
|
||||
|
||||
void batchRequest(std::string arg) {
|
||||
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
|
||||
|
||||
@@ -252,6 +265,8 @@ int main(int argc, char** argv) {
|
||||
else if (fullRequest.contains("/splash")) request(fullRequest);
|
||||
else if (fullRequest.contains("/devices")) request(fullRequest);
|
||||
else if (fullRequest.contains("/reload")) request(fullRequest);
|
||||
else if (fullRequest.contains("/getoption")) request(fullRequest);
|
||||
else if (fullRequest.contains("/setcursor")) setcursorRequest(argc, argv);
|
||||
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
|
||||
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
|
||||
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
|
||||
|
20
meson.build
20
meson.build
@@ -1,8 +1,22 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : '0.8.1beta',
|
||||
default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
|
||||
version : '0.10.0beta',
|
||||
default_options : [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
'optimization=3',
|
||||
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
|
||||
])
|
||||
|
||||
add_global_arguments('-std=c++23', language: 'cpp')
|
||||
# clang v14.0.6 uses C++2b instead of C++23, so we've gotta account for that
|
||||
# replace the following with a project default option once meson gets support for C++23
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.has_argument('-std=c++23')
|
||||
add_global_arguments('-std=c++23', language: 'cpp')
|
||||
elif cpp_compiler.has_argument('-std=c++2b')
|
||||
add_global_arguments('-std=c++2b', language: 'cpp')
|
||||
else
|
||||
error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.get_version() + ') with required C++ standard (C++23)')
|
||||
endif
|
||||
|
||||
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
||||
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
||||
|
@@ -27,7 +27,16 @@
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland" + lib.optionalString debug "-debug";
|
||||
inherit version;
|
||||
src = ../.;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
filter = name: type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (
|
||||
lib.hasSuffix ".nix" baseName
|
||||
);
|
||||
src = lib.cleanSource ../.;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
@@ -59,7 +68,7 @@ stdenv.mkDerivation {
|
||||
|
||||
mesonFlags = builtins.concatLists [
|
||||
(lib.optional (!enableXWayland) "-DNO_XWAYLAND=true")
|
||||
(lib.optional (legacyRenderer) "-DLEGACY_RENDERER:STRING=true")
|
||||
(lib.optional legacyRenderer "-DLEGACY_RENDERER:STRING=true")
|
||||
];
|
||||
|
||||
patches = [
|
||||
|
@@ -65,9 +65,11 @@ in {
|
||||
|
||||
xdg.configFile."hypr/hyprland.conf" = {
|
||||
text =
|
||||
(lib.optionalString cfg.systemdIntegration "
|
||||
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP; systemctl --user start hyprland-session.target
|
||||
")
|
||||
(lib.optionalString cfg.systemdIntegration ''
|
||||
exec-once=export XDG_SESSION_TYPE=wayland
|
||||
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP
|
||||
exec-once=systemctl --user start hyprland-session.target
|
||||
'')
|
||||
+ cfg.extraConfig;
|
||||
|
||||
onChange = let
|
||||
@@ -75,7 +77,7 @@ in {
|
||||
if cfg.package == null
|
||||
then defaultHyprlandPackage
|
||||
else cfg.package;
|
||||
in "${hyprlandPackage}/bin/hyprctl reload";
|
||||
in "HYPRLAND_INSTANCE_SIGNATURE=$(ls -w 1 /tmp/hypr | tail -1) ${hyprlandPackage}/bin/hyprctl reload config-only";
|
||||
};
|
||||
|
||||
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {
|
||||
|
@@ -153,6 +153,10 @@ CCompositor::CCompositor() {
|
||||
m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRSession = wlr_backend_get_session(m_sWLRBackend);
|
||||
|
||||
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
|
||||
}
|
||||
|
||||
CCompositor::~CCompositor() {
|
||||
@@ -181,6 +185,9 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRCursor->events.pinch_begin, &Events::listen_pinchBegin, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.pinch_update, &Events::listen_pinchUpdate, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.pinch_end, &Events::listen_pinchEnd, m_sWLRCursor, "WLRCursor");
|
||||
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_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");
|
||||
@@ -197,9 +204,13 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
||||
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
|
||||
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
|
||||
addWLSignal(&m_sWLRVKeyboardMgr->events.new_virtual_keyboard, &Events::listen_newVirtualKeyboard, m_sWLRVKeyboardMgr, "VKeyboardMgr");
|
||||
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
|
||||
addWLSignal(&m_sWLRIdleInhibitMgr->events.new_inhibitor, &Events::listen_newIdleInhibitor, m_sWLRIdleInhibitMgr, "WLRIdleInhibitMgr");
|
||||
addWLSignal(&m_sWLROutputPowerMgr->events.set_mode, &Events::listen_powerMgrSetMode, m_sWLROutputPowerMgr, "PowerMgr");
|
||||
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
|
||||
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
|
||||
|
||||
if (m_sWLRSession)
|
||||
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
||||
}
|
||||
@@ -222,6 +233,14 @@ void CCompositor::cleanup() {
|
||||
wl_display_terminate(m_sWLDisplay);
|
||||
|
||||
m_sWLDisplay = nullptr;
|
||||
|
||||
// kill the PID with a sigkill after 2 seconds
|
||||
const auto PID = getpid();
|
||||
|
||||
std::string call = "sleep 2 && kill -9 " + std::to_string(PID);
|
||||
|
||||
execl("/bin/sh", "/bin/sh", "-c", call.c_str(), ">", "/dev/null", nullptr); // this is to prevent that random "freezing"
|
||||
// the PID should not be reused.
|
||||
}
|
||||
|
||||
void CCompositor::startCompositor() {
|
||||
@@ -460,13 +479,13 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2)
|
||||
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus)
|
||||
return (*w).get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && w->m_iX11Type != 2)
|
||||
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && !w->m_bX11ShouldntFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
@@ -474,7 +493,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2) {
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
return w->get();
|
||||
|
||||
@@ -492,7 +511,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2) {
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && !w->m_bX11ShouldntFocus) {
|
||||
wlr_surface* resultSurf = nullptr;
|
||||
Vector2D origin = w->m_vRealPosition.vec();
|
||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||
@@ -504,7 +523,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2)
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && !w->m_bX11ShouldntFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -604,7 +623,19 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
}
|
||||
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
const auto PLASTWINDOW = m_pLastWindow;
|
||||
m_pLastWindow = nullptr;
|
||||
|
||||
if (windowValidMapped(PLASTWINDOW)) {
|
||||
updateWindowAnimatedDecorationValues(PLASTWINDOW);
|
||||
|
||||
if (PLASTWINDOW->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
|
||||
}
|
||||
|
||||
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
||||
|
||||
m_pLastFocus = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -616,6 +647,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
|
||||
return;
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
g_pKeybindManager->changeworkspace("[internal]" + std::to_string(pWindow->m_iWorkspaceID));
|
||||
|
||||
const auto PLASTWINDOW = m_pLastWindow;
|
||||
m_pLastWindow = pWindow;
|
||||
|
||||
@@ -665,6 +699,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
if (!pSurface) {
|
||||
wlr_seat_keyboard_clear_focus(m_sSeat.seat);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused
|
||||
g_pInputManager->m_sIMERelay.onKeyboardFocus(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -676,12 +711,14 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
|
||||
wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
|
||||
|
||||
g_pInputManager->m_sIMERelay.onKeyboardFocus(pSurface);
|
||||
|
||||
wlr_seat_keyboard_focus_change_event event = {
|
||||
.seat = m_sSeat.seat,
|
||||
.old_surface = m_pLastFocus,
|
||||
.new_surface = pSurface,
|
||||
};
|
||||
wlr_signal_emit_safe(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
|
||||
wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
|
||||
|
||||
if (pWindowOwner)
|
||||
Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, pWindowOwner->m_szTitle.c_str());
|
||||
@@ -819,31 +856,6 @@ CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
|
||||
// not needed anymore
|
||||
return;
|
||||
|
||||
const auto ISVISIBLE = isWorkspaceVisible(id);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->m_iWorkspaceID == id) {
|
||||
|
||||
// moveXWaylandWindow only moves XWayland windows
|
||||
// so there is no need to check here
|
||||
// if the window is XWayland or not.
|
||||
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w->m_bIsFullscreen))
|
||||
g_pXWaylandManager->moveXWaylandWindow(w.get(), w->m_vRealPosition.vec());
|
||||
else
|
||||
g_pXWaylandManager->moveXWaylandWindow(w.get(), Vector2D(42069,42069));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
|
||||
return !m_sSeat.exclusiveClient || (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource));
|
||||
}
|
||||
@@ -1281,7 +1293,7 @@ void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& wor
|
||||
|
||||
int CCompositor::getNextAvailableMonitorID() {
|
||||
int64_t topID = -1;
|
||||
for (auto& m : m_vMonitors) {
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if ((int64_t)m->ID > topID)
|
||||
topID = m->ID;
|
||||
}
|
||||
@@ -1338,6 +1350,8 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->m_bHidden) {
|
||||
w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition;
|
||||
}
|
||||
|
||||
w->updateToplevel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1380,14 +1394,19 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
if (!windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
focusWindow(pWindow);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
|
||||
w->m_bCreatedOverFullscreen = false;
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
|
||||
}
|
||||
|
||||
void CCompositor::moveUnmanagedX11ToWindows(CWindow* pWindow) {
|
||||
@@ -1518,3 +1537,80 @@ void CCompositor::warpCursorTo(const Vector2D& pos) {
|
||||
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y);
|
||||
}
|
||||
|
||||
SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLists) {
|
||||
for (auto& ls : lsl) {
|
||||
if (ls->layerSurface == pLS)
|
||||
return ls.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::closeWindow(CWindow* pWindow) {
|
||||
if (pWindow && windowValidMapped(pWindow)) {
|
||||
g_pXWaylandManager->sendCloseWindow(pWindow);
|
||||
|
||||
if (pWindow == m_pLastWindow) {
|
||||
m_pLastFocus = nullptr;
|
||||
m_pLastWindow = nullptr;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused
|
||||
focusWindow(windowFromCursor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SLayerSurface* CCompositor::getLayerSurfaceFromSurface(wlr_surface* pSurface) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLists) {
|
||||
for (auto& ls : lsl) {
|
||||
if (ls->layerSurface && ls->layerSurface->surface == pSurface)
|
||||
return ls.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// returns a delta
|
||||
Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, const Vector2D& relativeTo) {
|
||||
if (!args.contains(' '))
|
||||
return relativeTo;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||
|
||||
if (x == "exact") {
|
||||
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||
|
||||
if (!isNumber(newX) || !isNumber(newY)) {
|
||||
Debug::log(ERR, "parseWindowVectorArgsRelative: exact args not numbers");
|
||||
return relativeTo;
|
||||
}
|
||||
|
||||
const int X = std::stoi(newX);
|
||||
const int Y = std::stoi(newY);
|
||||
|
||||
if (X < 0 || Y < 0) {
|
||||
Debug::log(ERR, "parseWindowVectorArgsRelative: exact args cannot be < 0");
|
||||
return relativeTo;
|
||||
}
|
||||
|
||||
return Vector2D(X, Y);
|
||||
}
|
||||
|
||||
if (!isNumber(x) || !isNumber(y)) {
|
||||
Debug::log(ERR, "parseWindowVectorArgsRelative: args not numbers");
|
||||
return relativeTo;
|
||||
}
|
||||
|
||||
const int X = std::stoi(x);
|
||||
const int Y = std::stoi(y);
|
||||
|
||||
return Vector2D(X + relativeTo.x, Y + relativeTo.y);
|
||||
}
|
@@ -66,6 +66,8 @@ public:
|
||||
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
|
||||
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
|
||||
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
|
||||
wlr_input_method_manager_v2* m_sWLRIMEMgr;
|
||||
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
||||
@@ -95,6 +97,7 @@ public:
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
@@ -125,7 +128,6 @@ public:
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
int getWindowsOnWorkspace(const int&);
|
||||
CWindow* getFirstWindowOnWorkspace(const int&);
|
||||
void fixXWaylandWindowsOnWorkspace(const int&);
|
||||
CWindow* getFullscreenWindowOnWorkspace(const int&);
|
||||
bool doesSeatAcceptInput(wlr_surface*);
|
||||
bool isWindowActive(CWindow*);
|
||||
@@ -153,6 +155,11 @@ public:
|
||||
void addToFadingOutSafe(CWindow*);
|
||||
CWindow* getWindowByRegex(const std::string&);
|
||||
void warpCursorTo(const Vector2D&);
|
||||
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
|
||||
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
|
||||
void closeWindow(CWindow*);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
|
@@ -112,4 +112,97 @@ IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CWindow::createToplevelHandle() {
|
||||
if (m_bIsX11 && (m_bX11DoesntWantBorders || m_iX11Type == 2))
|
||||
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());
|
||||
wlr_foreign_toplevel_handle_v1_set_maximized(m_phForeignToplevel, false);
|
||||
wlr_foreign_toplevel_handle_v1_set_minimized(m_phForeignToplevel, false);
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false);
|
||||
|
||||
// handle events
|
||||
hyprListener_toplevelActivate.initCallback(&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) {
|
||||
|
||||
g_pCompositor->focusWindow(this);
|
||||
|
||||
}, this, "Toplevel");
|
||||
|
||||
hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) {
|
||||
|
||||
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
|
||||
|
||||
}, this, "Toplevel");
|
||||
|
||||
hyprListener_toplevelClose.initCallback(&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) {
|
||||
|
||||
g_pCompositor->closeWindow(this);
|
||||
|
||||
}, this, "Toplevel");
|
||||
|
||||
m_iLastToplevelMonitorID = m_iMonitorID;
|
||||
}
|
||||
|
||||
void CWindow::destroyToplevelHandle() {
|
||||
if (!m_phForeignToplevel)
|
||||
return;
|
||||
|
||||
hyprListener_toplevelActivate.removeCallback();
|
||||
hyprListener_toplevelClose.removeCallback();
|
||||
hyprListener_toplevelFullscreen.removeCallback();
|
||||
|
||||
wlr_foreign_toplevel_handle_v1_destroy(m_phForeignToplevel);
|
||||
m_phForeignToplevel = nullptr;
|
||||
}
|
||||
|
||||
void CWindow::updateToplevel() {
|
||||
updateSurfaceOutputs();
|
||||
|
||||
if (!m_phForeignToplevel)
|
||||
return;
|
||||
|
||||
wlr_foreign_toplevel_handle_v1_set_title(m_phForeignToplevel, m_szTitle.c_str());
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, m_bIsFullscreen);
|
||||
|
||||
if (m_iLastToplevelMonitorID != m_iMonitorID) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iLastToplevelMonitorID); PMONITOR && PMONITOR->m_bEnabled)
|
||||
wlr_foreign_toplevel_handle_v1_output_leave(m_phForeignToplevel, PMONITOR->output);
|
||||
wlr_foreign_toplevel_handle_v1_output_enter(m_phForeignToplevel, g_pCompositor->getMonitorFromID(m_iMonitorID)->output);
|
||||
|
||||
m_iLastToplevelMonitorID = m_iMonitorID;
|
||||
}
|
||||
}
|
||||
|
||||
void sendEnterIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||
const auto OUTPUT = (wlr_output*)data;
|
||||
wlr_surface_send_enter(pSurface, OUTPUT);
|
||||
}
|
||||
|
||||
void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||
const auto OUTPUT = (wlr_output*)data;
|
||||
wlr_surface_send_leave(pSurface, OUTPUT);
|
||||
}
|
||||
|
||||
void CWindow::updateSurfaceOutputs() {
|
||||
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden || !m_bMappedX11)
|
||||
return;
|
||||
|
||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||
|
||||
m_iLastSurfaceMonitorID = m_iMonitorID;
|
||||
|
||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendLeaveIter, PLASTMONITOR->output);
|
||||
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendEnterIter, PNEWMONITOR->output);
|
||||
}
|
@@ -13,6 +13,7 @@ struct SWindowSpecialRenderData {
|
||||
|
||||
// set by the layout
|
||||
bool rounding = true;
|
||||
bool border = true;
|
||||
};
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
@@ -39,6 +40,11 @@ public:
|
||||
DYNLISTENER(requestMinimize);
|
||||
DYNLISTENER(requestMaximize);
|
||||
DYNLISTENER(requestResize);
|
||||
DYNLISTENER(activateX11);
|
||||
DYNLISTENER(configureX11);
|
||||
DYNLISTENER(toplevelClose);
|
||||
DYNLISTENER(toplevelActivate);
|
||||
DYNLISTENER(toplevelFullscreen);
|
||||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
union {
|
||||
@@ -58,6 +64,9 @@ public:
|
||||
Vector2D m_vReportedPosition;
|
||||
Vector2D m_vReportedSize;
|
||||
|
||||
// for restoring floating statuses
|
||||
Vector2D m_vLastFloatingSize;
|
||||
|
||||
// this is used for pseudotiling
|
||||
bool m_bIsPseudotiled = false;
|
||||
Vector2D m_vPseudoSize = Vector2D(0,0);
|
||||
@@ -84,8 +93,7 @@ public:
|
||||
uint64_t m_iX11Type = 0;
|
||||
bool m_bIsModal = false;
|
||||
bool m_bX11DoesntWantBorders = false;
|
||||
DYNLISTENER(activateX11);
|
||||
DYNLISTENER(configureX11);
|
||||
bool m_bX11ShouldntFocus = false;
|
||||
//
|
||||
|
||||
// For nofocus
|
||||
@@ -124,6 +132,10 @@ public:
|
||||
// animated shadow color
|
||||
CAnimatedVariable m_cRealShadowColor;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const CWindow& rhs) {
|
||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
|
||||
@@ -135,5 +147,8 @@ public:
|
||||
void updateWindowDecos();
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
|
||||
void createToplevelHandle();
|
||||
void destroyToplevelHandle();
|
||||
void updateToplevel();
|
||||
void updateSurfaceOutputs();
|
||||
};
|
||||
|
@@ -54,6 +54,9 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["misc:no_vfr"].intValue = 1;
|
||||
configValues["misc:damage_entire_on_snapshot"].intValue = 0;
|
||||
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
|
||||
configValues["misc:always_follow_on_dnd"].intValue = 1;
|
||||
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
|
||||
configValues["misc:animate_manual_resizes"].intValue = 0;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -89,6 +92,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
|
||||
configValues["dwindle:no_gaps_when_only"].intValue = 0;
|
||||
configValues["dwindle:use_active_for_splits"].intValue = 1;
|
||||
|
||||
configValues["master:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["master:new_is_master"].intValue = 1;
|
||||
@@ -116,6 +120,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["animations:workspaces"].intValue = 1;
|
||||
|
||||
configValues["input:sensitivity"].floatValue = 0.f;
|
||||
configValues["input:kb_file"].strValue = STRVAL_EMPTY;
|
||||
configValues["input:kb_layout"].strValue = "us";
|
||||
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
|
||||
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
|
||||
@@ -152,6 +157,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
|
||||
auto& cfgValues = deviceConfigs[dev];
|
||||
|
||||
cfgValues["sensitivity"].floatValue = 0.f;
|
||||
cfgValues["kb_file"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["kb_layout"].strValue = "us";
|
||||
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["kb_options"].strValue = STRVAL_EMPTY;
|
||||
@@ -433,13 +439,8 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
return;
|
||||
}
|
||||
|
||||
// overwrite if exists
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
if (r.name == newrule.name) {
|
||||
r = newrule;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
|
||||
|
||||
m_dMonitorRules.push_back(newrule);
|
||||
|
||||
@@ -454,17 +455,31 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
|
||||
if (curitem.contains("@"))
|
||||
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
|
||||
}
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
newrule.offset.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
|
||||
newrule.offset.y = stoi(curitem.substr(curitem.find_first_of('x') + 1));
|
||||
if (curitem.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));
|
||||
|
||||
if (newrule.offset.x < 0 || newrule.offset.y < 0) {
|
||||
parseError = "invalid offset. Offset cannot be negative.";
|
||||
newrule.offset = Vector2D();
|
||||
}
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
newrule.scale = stof(curitem);
|
||||
|
||||
if (newrule.scale < 0.25f) {
|
||||
parseError = "not a valid scale.";
|
||||
newrule.scale = 1;
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
if (curitem != "") {
|
||||
@@ -474,13 +489,8 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
return;
|
||||
}
|
||||
|
||||
// overwrite if exists
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
if (r.name == newrule.name) {
|
||||
r = newrule;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
|
||||
|
||||
m_dMonitorRules.push_back(newrule);
|
||||
}
|
||||
@@ -507,13 +517,24 @@ void CConfigManager::handleBezier(const std::string& command, const std::string&
|
||||
std::string bezierName = curitem;
|
||||
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
parseError = "too few arguments";
|
||||
float p1x = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
parseError = "too few arguments";
|
||||
float p1y = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
parseError = "too few arguments";
|
||||
float p2x = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem == "")
|
||||
parseError = "too few arguments";
|
||||
float p2y = std::stof(curitem);
|
||||
nextItem();
|
||||
if (curitem != "")
|
||||
parseError = "too many arguments";
|
||||
|
||||
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
|
||||
}
|
||||
@@ -568,14 +589,23 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
||||
// on/off
|
||||
PANIM->second.internalEnabled = curitem == "1";
|
||||
|
||||
if (curitem != "0" && curitem != "1") {
|
||||
parseError = "invalid animation on/off state";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
// speed
|
||||
if (isNumber(curitem, true)) {
|
||||
PANIM->second.internalSpeed = std::stof(curitem);
|
||||
|
||||
if (PANIM->second.internalSpeed <= 0) {
|
||||
parseError = "invalid speed";
|
||||
PANIM->second.internalSpeed = 1.f;
|
||||
}
|
||||
} else {
|
||||
PANIM->second.internalSpeed = 10.f;
|
||||
parseError = "Invalid speed";
|
||||
parseError = "invalid speed";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
@@ -583,11 +613,23 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
||||
// curve
|
||||
PANIM->second.internalBezier = curitem;
|
||||
|
||||
if (!g_pAnimationManager->bezierExists(curitem)) {
|
||||
parseError = "no such bezier";
|
||||
PANIM->second.internalBezier = "default";
|
||||
}
|
||||
|
||||
nextItem();
|
||||
|
||||
// style
|
||||
PANIM->second.internalStyle = curitem;
|
||||
|
||||
if (curitem != "") {
|
||||
const auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, curitem);
|
||||
|
||||
if (ERR != "")
|
||||
parseError = ERR;
|
||||
}
|
||||
|
||||
// now, check for children, recursively
|
||||
setAnimForChildren(&PANIM->second);
|
||||
}
|
||||
@@ -735,28 +777,13 @@ void CConfigManager::handleSubmap(const std::string& command, const std::string&
|
||||
void CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
|
||||
auto value = rawpath;
|
||||
|
||||
if (value.length() < 2) {
|
||||
if (rawpath.length() < 2) {
|
||||
Debug::log(ERR, "source= path garbage");
|
||||
parseError = "source path " + value + " bogus!";
|
||||
parseError = "source path " + rawpath + " bogus!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (value[0] == '.') {
|
||||
auto currentDir = configCurrentPath.substr(0, configCurrentPath.find_last_of('/'));
|
||||
|
||||
if (value[1] == '.') {
|
||||
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
|
||||
value.replace(0, 2, parentDir);
|
||||
} else {
|
||||
value.replace(0, 1, currentDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (value[0] == '~') {
|
||||
value.replace(0, 1, std::string(ENVHOME));
|
||||
}
|
||||
auto value = absolutePath(rawpath, configCurrentPath);
|
||||
|
||||
if (!std::filesystem::exists(value)) {
|
||||
Debug::log(ERR, "source= file doesnt exist");
|
||||
@@ -885,6 +912,7 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
if (line.contains(" {")) {
|
||||
auto cat = line.substr(0, line.find(" {"));
|
||||
transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
|
||||
std::replace(cat.begin(), cat.end(), ' ', '-');
|
||||
if (currentCategory.length() != 0) {
|
||||
currentCategory.push_back(':');
|
||||
currentCategory.append(cat);
|
||||
@@ -1034,14 +1062,15 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
if (parseError != "")
|
||||
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(255, 50, 50, 255));
|
||||
else if (configValues["autogenerated"].intValue == 1)
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Enter -> kitty\nSUPER+T -> Alacritty\nSUPER+M -> exit Hyprland", CColor(255, 255, 70, 255));
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", CColor(255, 255, 70, 255));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
|
||||
// Set the modes for all monitors as we configured them
|
||||
// not on first launch because monitors might not exist yet
|
||||
// and they'll be taken care of in the newMonitor event
|
||||
if (!isFirstLaunch) {
|
||||
// ignore if nomonitorreload is set
|
||||
if (!isFirstLaunch && !m_bNoMonitorReload) {
|
||||
m_bWantsMonitorReload = true;
|
||||
|
||||
// check
|
||||
@@ -1061,6 +1090,9 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
// Force the compositor to fully re-render all monitors
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->forceFullFrames = 2;
|
||||
|
||||
// Reset no monitor reload
|
||||
m_bNoMonitorReload = false;
|
||||
}
|
||||
|
||||
void CConfigManager::tick() {
|
||||
@@ -1109,9 +1141,13 @@ SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
|
||||
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
|
||||
std::lock_guard<std::mutex> lg(configmtx);
|
||||
|
||||
const auto it = deviceConfigs.find(dev);
|
||||
auto devcopy = dev;
|
||||
std::replace(devcopy.begin(), devcopy.end(), ' ', '-');
|
||||
|
||||
const auto it = deviceConfigs.find(devcopy);
|
||||
|
||||
if (it == deviceConfigs.end()) {
|
||||
Debug::log(ERR, "getConfigValueSafeDevice: No device config for %s found???", devcopy.c_str());
|
||||
return SConfigValue();
|
||||
}
|
||||
|
||||
@@ -1124,7 +1160,7 @@ SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, co
|
||||
if (foundIt == std::string::npos)
|
||||
continue;
|
||||
|
||||
if (foundIt == cv.first.length() - val.length()) {
|
||||
if (cv.first == "input:" + val || cv.first == "input:touchpad:" + cv.first) {
|
||||
copy = cv.second;
|
||||
}
|
||||
}
|
||||
@@ -1206,7 +1242,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(std::string name) {
|
||||
|
||||
Debug::log(WARN, "No rules configured. Using the default hardcoded one.");
|
||||
|
||||
return SMonitorRule{.name = "", .resolution = Vector2D(1280, 720), .offset = Vector2D(0, 0), .scale = 1};
|
||||
return SMonitorRule{.name = "", .resolution = Vector2D(0, 0), .offset = Vector2D(-1, -1), .scale = 1}; // 0, 0 is preferred and -1, -1 is auto
|
||||
}
|
||||
|
||||
std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
@@ -1275,7 +1311,7 @@ void CConfigManager::performMonitorReload() {
|
||||
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
auto rule = getMonitorRuleFor(m->szName);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
@@ -1293,8 +1329,20 @@ SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
|
||||
return &configValues[val];
|
||||
}
|
||||
|
||||
SConfigValue* CConfigManager::getConfigValuePtrSafe(std::string val) {
|
||||
const auto IT = configValues.find(val);
|
||||
|
||||
if (IT == configValues.end())
|
||||
return nullptr;
|
||||
|
||||
return &(IT->second);
|
||||
}
|
||||
|
||||
bool CConfigManager::deviceConfigExists(const std::string& dev) {
|
||||
const auto it = deviceConfigs.find(dev);
|
||||
auto copy = dev;
|
||||
std::replace(copy.begin(), copy.end(), ' ', '-');
|
||||
|
||||
const auto it = deviceConfigs.find(copy);
|
||||
|
||||
return it != deviceConfigs.end();
|
||||
}
|
||||
@@ -1314,7 +1362,7 @@ void CConfigManager::ensureDPMS() {
|
||||
auto rule = getMonitorRuleFor(rm->szName);
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled) {
|
||||
rm->m_pThisWrap = &rm;
|
||||
rm->m_pThisWrap = &rm;
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
}
|
||||
}
|
||||
@@ -1323,3 +1371,8 @@ void CConfigManager::ensureDPMS() {
|
||||
SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) {
|
||||
return &animationConfig[name];
|
||||
}
|
||||
|
||||
void CConfigManager::addParseError(const std::string& err) {
|
||||
if (parseError == "")
|
||||
parseError = err;
|
||||
}
|
||||
|
@@ -83,6 +83,7 @@ public:
|
||||
bool shouldBlurLS(const std::string&);
|
||||
|
||||
SConfigValue* getConfigValuePtr(std::string);
|
||||
SConfigValue* getConfigValuePtrSafe(std::string);
|
||||
|
||||
SMonitorRule getMonitorRuleFor(std::string);
|
||||
|
||||
@@ -96,11 +97,17 @@ public:
|
||||
void performMonitorReload();
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
void ensureDPMS();
|
||||
|
||||
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
||||
|
||||
void addParseError(const std::string&);
|
||||
|
||||
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
private:
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
@@ -110,8 +117,6 @@ private:
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
std::string currentCategory = ""; // For storing the category of the current item
|
||||
|
||||
std::string parseError = ""; // For storing a parse error to display later
|
||||
@@ -131,7 +136,6 @@ private:
|
||||
void setDefaultVars();
|
||||
void setDefaultAnimationVars();
|
||||
void setDeviceDefaultVars(const std::string&);
|
||||
void ensureDPMS();
|
||||
|
||||
void setAnimForChildren(SAnimationPropertyConfig *const);
|
||||
|
||||
@@ -155,4 +159,4 @@ private:
|
||||
void handleBlurLS(const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
@@ -17,9 +17,10 @@ OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
|
||||
autogenerated=1 # remove this line to get rid of the warning on top.
|
||||
|
||||
monitor=,preferred,0x0,1
|
||||
monitor=,preferred,auto,1
|
||||
|
||||
input {
|
||||
kb_file=
|
||||
kb_layout=
|
||||
kb_variant=
|
||||
kb_model=
|
||||
@@ -122,4 +123,4 @@ bind=ALT,0,movetoworkspace,10
|
||||
|
||||
bind=SUPER,mouse_down,workspace,e+1
|
||||
bind=SUPER,mouse_up,workspace,e-1
|
||||
)#";
|
||||
)#";
|
||||
|
@@ -35,7 +35,7 @@ R"#({
|
||||
"reserved": [%i, %i, %i, %i],
|
||||
"scale": %.2f,
|
||||
"transform": %i,
|
||||
"active": "%s"
|
||||
"focused": %s
|
||||
},)#",
|
||||
m->ID,
|
||||
escapeJSONStrings(m->szName).c_str(),
|
||||
@@ -46,7 +46,7 @@ R"#({
|
||||
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
|
||||
m->scale,
|
||||
(int)m->transform,
|
||||
(m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no")
|
||||
(m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ R"#({
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tactive: %s\n\n",
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\n",
|
||||
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"));
|
||||
}
|
||||
}
|
||||
@@ -80,29 +80,30 @@ R"#({
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"floating": %i,
|
||||
"floating": %s,
|
||||
"monitor": %i,
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %i
|
||||
"xwayland": %s
|
||||
},)#",
|
||||
w.get(),
|
||||
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
|
||||
(int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y,
|
||||
w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
|
||||
(int)w->m_bIsFloating,
|
||||
((int)w->m_bIsFloating == 1 ? "true" : "false"),
|
||||
w->m_iMonitorID,
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
|
||||
w->getPID(),
|
||||
(int)w->m_bIsX11
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
if (result != "[")
|
||||
result.pop_back();
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
@@ -129,13 +130,13 @@ R"#({
|
||||
"name": "%s",
|
||||
"monitor": "%s",
|
||||
"windows": %i,
|
||||
"hasfullscreen": %i
|
||||
"hasfullscreen": %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
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return "Invalid";
|
||||
return format == HyprCtl::FORMAT_JSON ? "{}" : "Invalid";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
return getFormat(
|
||||
@@ -168,23 +169,23 @@ R"#({
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"floating": %i,
|
||||
"floating": %s,
|
||||
"monitor": %i,
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %i
|
||||
"xwayland": %s
|
||||
})#",
|
||||
PWINDOW,
|
||||
(int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
|
||||
(int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
|
||||
PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(),
|
||||
(int)PWINDOW->m_bIsFloating,
|
||||
((int)PWINDOW->m_bIsFloating == 1 ? "true" : "false"),
|
||||
PWINDOW->m_iMonitorID,
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(),
|
||||
PWINDOW->getPID(),
|
||||
(int)PWINDOW->m_bIsX11
|
||||
((int)PWINDOW->m_bIsX11 == 1 ? "true" : "false")
|
||||
);
|
||||
} else {
|
||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
|
||||
@@ -299,7 +300,7 @@ R"#( {
|
||||
|
||||
result += "\"keyboards\": [\n";
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
|
||||
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
@@ -309,7 +310,8 @@ R"#( {
|
||||
"layout": "%s",
|
||||
"variant": "%s",
|
||||
"options": "%s",
|
||||
"active_keymap": "%s"
|
||||
"active_keymap": "%s",
|
||||
"main": %s
|
||||
},)#",
|
||||
&k,
|
||||
escapeJSONStrings(k.keyboard->name).c_str(),
|
||||
@@ -318,7 +320,8 @@ R"#( {
|
||||
escapeJSONStrings(k.currentRules.layout).c_str(),
|
||||
escapeJSONStrings(k.currentRules.variant).c_str(),
|
||||
escapeJSONStrings(k.currentRules.options).c_str(),
|
||||
escapeJSONStrings(KM).c_str()
|
||||
escapeJSONStrings(KM).c_str(),
|
||||
(k.active ? "true" : "false")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -384,8 +387,8 @@ R"#( {
|
||||
result += "\n\nKeyboards:\n";
|
||||
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
|
||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM);
|
||||
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
|
||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
|
||||
}
|
||||
|
||||
result += "\n\nTablets:\n";
|
||||
@@ -406,23 +409,56 @@ R"#( {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string versionRequest() {
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
|
||||
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nflags: (if any)\n";
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "legacyrenderer\n";
|
||||
result += "legacyrenderer\n";
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
result += "debug\n";
|
||||
result += "debug\n";
|
||||
#endif
|
||||
#ifdef HYPRLAND_DEBUG
|
||||
result += "debug\n";
|
||||
result += "debug\n";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
result += "no xwayland\n";
|
||||
result += "no xwayland\n";
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
} else {
|
||||
std::string result = getFormat(
|
||||
R"#({
|
||||
"branch": "%s",
|
||||
"commit": "%s",
|
||||
"dirty": %s
|
||||
"commit_message": "%s",
|
||||
"flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "\"legacyrenderer\",";
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
result += "\"debug\",";
|
||||
#endif
|
||||
#ifdef HYPRLAND_DEBUG
|
||||
result += "\"debug\",";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
result += "\"no xwayland\",";
|
||||
#endif
|
||||
|
||||
if (result[result.length() - 1] == ',')
|
||||
result.pop_back();
|
||||
|
||||
result += "]\n}";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return ""; // make the compiler happy
|
||||
}
|
||||
|
||||
std::string dispatchRequest(std::string in) {
|
||||
@@ -457,8 +493,10 @@ std::string dispatchKeyword(std::string in) {
|
||||
if (COMMAND == "monitor")
|
||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||
|
||||
if (COMMAND.contains("input"))
|
||||
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setMouseConfigs(); // update mouse cfgs
|
||||
}
|
||||
|
||||
if (COMMAND.contains("general:layout"))
|
||||
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
|
||||
@@ -471,9 +509,16 @@ std::string dispatchKeyword(std::string in) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string reloadRequest() {
|
||||
std::string reloadRequest(std::string request) {
|
||||
|
||||
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
|
||||
|
||||
g_pConfigManager->m_bForceReload = true;
|
||||
|
||||
if (REQMODE == "config-only") {
|
||||
g_pConfigManager->m_bNoMonitorReload = true;
|
||||
}
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@@ -521,6 +566,97 @@ std::string dispatchBatch(std::string request) {
|
||||
return reply;
|
||||
}
|
||||
|
||||
std::string dispatchSetCursor(std::string request) {
|
||||
std::string curitem = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = request.find_first_of(' ');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = request.substr(0, idx);
|
||||
request = request.substr(idx + 1);
|
||||
} else {
|
||||
curitem = request;
|
||||
request = "";
|
||||
}
|
||||
|
||||
curitem = removeBeginEndSpacesTabs(curitem);
|
||||
};
|
||||
|
||||
nextItem();
|
||||
nextItem();
|
||||
|
||||
const auto THEME = curitem;
|
||||
|
||||
nextItem();
|
||||
|
||||
const auto SIZE = curitem;
|
||||
|
||||
if (!isNumber(SIZE)) {
|
||||
return "size not int";
|
||||
}
|
||||
|
||||
const auto SIZEINT = std::stoi(SIZE);
|
||||
|
||||
if (SIZEINT < 1) {
|
||||
return "size must be positive";
|
||||
}
|
||||
|
||||
wlr_xcursor_manager_destroy(g_pCompositor->m_sWLRXCursorMgr);
|
||||
|
||||
g_pCompositor->m_sWLRXCursorMgr = wlr_xcursor_manager_create(THEME.c_str(), SIZEINT);
|
||||
|
||||
setenv("XCURSOR_SIZE", SIZE.c_str(), true);
|
||||
setenv("XCURSOR_THEME", THEME.c_str(), true);
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, m->scale);
|
||||
}
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string curitem = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = request.find_first_of(' ');
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = request.substr(0, idx);
|
||||
request = request.substr(idx + 1);
|
||||
} else {
|
||||
curitem = request;
|
||||
request = "";
|
||||
}
|
||||
|
||||
curitem = removeBeginEndSpacesTabs(curitem);
|
||||
};
|
||||
|
||||
nextItem();
|
||||
nextItem();
|
||||
|
||||
const auto PCFGOPT = g_pConfigManager->getConfigValuePtrSafe(curitem);
|
||||
|
||||
if (!PCFGOPT)
|
||||
return "no such option";
|
||||
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
|
||||
return getFormat("option %s\n\tint: %i\n\tfloat: %f\n\tstr: \"%s\"", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str());
|
||||
else {
|
||||
return getFormat(
|
||||
R"#(
|
||||
{
|
||||
"option": "%s",
|
||||
"int": %i,
|
||||
"float": %f,
|
||||
"str": "%s"
|
||||
}
|
||||
)#", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::string getReply(std::string request) {
|
||||
auto format = HyprCtl::FORMAT_NORMAL;
|
||||
|
||||
@@ -555,9 +691,9 @@ std::string getReply(std::string request) {
|
||||
else if (request == "layers")
|
||||
return layersRequest(format);
|
||||
else if (request == "version")
|
||||
return versionRequest();
|
||||
else if (request == "reload")
|
||||
return reloadRequest();
|
||||
return versionRequest(format);
|
||||
else if (request.find("reload") == 0)
|
||||
return reloadRequest(request);
|
||||
else if (request == "devices")
|
||||
return devicesRequest(format);
|
||||
else if (request == "splash")
|
||||
@@ -566,6 +702,10 @@ std::string getReply(std::string request) {
|
||||
return dispatchRequest(request);
|
||||
else if (request.find("keyword") == 0)
|
||||
return dispatchKeyword(request);
|
||||
else if (request.find("setcursor") == 0)
|
||||
return dispatchSetCursor(request);
|
||||
else if (request.find("getoption") == 0)
|
||||
return dispatchGetOption(request, format);
|
||||
else if (request.find("[[BATCH]]") == 0)
|
||||
return dispatchBatch(request);
|
||||
|
||||
@@ -589,6 +729,10 @@ void HyprCtl::tickHyprCtl() {
|
||||
|
||||
requestMade = false;
|
||||
requestReady = true;
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
||||
g_pConfigManager->ensureDPMS();
|
||||
}
|
||||
}
|
||||
|
||||
std::string getRequestFromThread(std::string rq) {
|
||||
@@ -663,4 +807,4 @@ void HyprCtl::startHyprCtlSocket() {
|
||||
|
||||
close(SOCKET);
|
||||
}).detach();
|
||||
}
|
||||
}
|
||||
|
@@ -72,7 +72,6 @@ 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);
|
||||
Debug::log(WARN, "!!!! Hyprland does not directly support touchscreens, bugs may occur !!!!");
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
@@ -189,4 +188,22 @@ void Events::listener_pinchUpdate(wl_listener* listener, void* data) {
|
||||
void Events::listener_pinchEnd(wl_listener* listener, void* data) {
|
||||
const auto EV = (wlr_pointer_pinch_end_event*)data;
|
||||
wlr_pointer_gestures_v1_send_pinch_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->cancelled);
|
||||
}
|
||||
|
||||
void Events::listener_newVirtualKeyboard(wl_listener* listener, void* data) {
|
||||
const auto WLRKB = (wlr_virtual_keyboard_v1*)data;
|
||||
|
||||
g_pInputManager->newVirtualKeyboard(&WLRKB->keyboard.base);
|
||||
}
|
||||
|
||||
void Events::listener_touchBegin(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onTouchDown((wlr_touch_down_event*)data);
|
||||
}
|
||||
|
||||
void Events::listener_touchEnd(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onTouchUp((wlr_touch_up_event*)data);
|
||||
}
|
||||
|
||||
void Events::listener_touchUpdate(wl_listener* listener, void* data) {
|
||||
g_pInputManager->onTouchMove((wlr_touch_motion_event*)data);
|
||||
}
|
@@ -133,4 +133,20 @@ namespace Events {
|
||||
|
||||
// Power
|
||||
LISTENER(powerMgrSetMode);
|
||||
|
||||
// IME
|
||||
LISTENER(newIME);
|
||||
LISTENER(newTextInput);
|
||||
LISTENER(newVirtualKeyboard);
|
||||
|
||||
// IME Popups
|
||||
DYNLISTENFUNC(mapInputPopup);
|
||||
DYNLISTENFUNC(unmapInputPopup);
|
||||
DYNLISTENFUNC(commitInputPopup);
|
||||
DYNLISTENFUNC(destroyInputPopup);
|
||||
|
||||
// Touch
|
||||
LISTENER(touchBegin);
|
||||
LISTENER(touchEnd);
|
||||
LISTENER(touchUpdate);
|
||||
};
|
@@ -103,6 +103,13 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
|
||||
g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
}
|
||||
|
||||
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
|
||||
if (*PFOLLOWONDND)
|
||||
g_pInputManager->m_pFollowOnDnDBegin = g_pCompositor->m_pLastWindow;
|
||||
else
|
||||
g_pInputManager->m_pFollowOnDnDBegin = nullptr;
|
||||
}
|
||||
|
||||
void Events::listener_destroyDrag(void* owner, void* data) {
|
||||
@@ -113,6 +120,11 @@ void Events::listener_destroyDrag(void* owner, void* data) {
|
||||
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
if (g_pInputManager->m_pFollowOnDnDBegin)
|
||||
g_pCompositor->focusWindow(g_pInputManager->m_pFollowOnDnDBegin);
|
||||
|
||||
g_pInputManager->m_pFollowOnDnDBegin = nullptr;
|
||||
}
|
||||
|
||||
void Events::listener_mapDragIcon(void* owner, void* data) {
|
||||
@@ -174,4 +186,16 @@ void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||
|
||||
if (!wlr_output_commit(EVENT->output))
|
||||
Debug::log(ERR, "Couldn't set power mode");
|
||||
}
|
||||
|
||||
void Events::listener_newIME(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "New IME added!");
|
||||
|
||||
g_pInputManager->m_sIMERelay.onNewIME((wlr_input_method_v2*)data);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@@ -53,33 +53,49 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->getMonitorFromName(std::string(OUTPUT->name))) {
|
||||
Debug::log(WARN, "Monitor with name %s already exists, not adding as new!", OUTPUT->name);
|
||||
return;
|
||||
if (g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Recovering from an unsafe state. May you be lucky.");
|
||||
}
|
||||
|
||||
// add it to real
|
||||
const auto PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
std::shared_ptr<CMonitor>* PNEWMONITORWRAP = nullptr;
|
||||
|
||||
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||
for (auto& rm : g_pCompositor->m_vRealMonitors) {
|
||||
if (rm->szName == OUTPUT->name) {
|
||||
PNEWMONITORWRAP = &rm;
|
||||
Debug::log(LOG, "Recovering a removed monitor.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PNEWMONITORWRAP) {
|
||||
Debug::log(LOG, "Adding completely new monitor.");
|
||||
PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
|
||||
|
||||
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID();
|
||||
}
|
||||
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
|
||||
PNEWMONITOR->output = OUTPUT;
|
||||
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
|
||||
|
||||
PNEWMONITOR->onConnect(false);
|
||||
|
||||
if (!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate)
|
||||
if ((!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
||||
pMostHzMonitor = PNEWMONITOR;
|
||||
|
||||
// ready to process cuz we have a monitor
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
if (PNEWMONITOR->m_bEnabled) {
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
g_pCompositor->m_bUnsafeState = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
CMonitor* const PMONITOR = (CMonitor*)owner;
|
||||
|
||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive) {
|
||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||
return; // cannot draw on session inactive (different tty)
|
||||
}
|
||||
@@ -293,20 +309,23 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
pMonitor->onDisconnect();
|
||||
|
||||
// cleanup
|
||||
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
|
||||
// cleanup if not unsafe
|
||||
|
||||
if (pMostHzMonitor == pMonitor) {
|
||||
int mostHz = 0;
|
||||
CMonitor* pMonitorMostHz = nullptr;
|
||||
if (!g_pCompositor->m_bUnsafeState) {
|
||||
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->refreshRate > mostHz) {
|
||||
pMonitorMostHz = m.get();
|
||||
mostHz = m->refreshRate;
|
||||
if (pMostHzMonitor == pMonitor) {
|
||||
int mostHz = 0;
|
||||
CMonitor* pMonitorMostHz = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->refreshRate > mostHz) {
|
||||
pMonitorMostHz = m.get();
|
||||
mostHz = m->refreshRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pMostHzMonitor = pMonitorMostHz;
|
||||
pMostHzMonitor = pMonitorMostHz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecTransformedSize.x, .height = PMONITOR->vecTransformedSize.y};
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
|
||||
@@ -151,7 +151,10 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
g_pHyprRenderer->damageBox(lx, ly, PPOPUP->popup->current.geometry.width, PPOPUP->popup->current.geometry.width);
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
|
||||
g_pHyprRenderer->damageBox(lx, ly, extents.width + 2, extents.height + 2);
|
||||
|
||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
|
||||
}
|
||||
@@ -167,7 +170,10 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
g_pHyprRenderer->damageBox(lx, ly, PPOPUP->popup->current.geometry.width, PPOPUP->popup->current.geometry.width);
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
|
||||
g_pHyprRenderer->damageBox(lx, ly, extents.width + 2, extents.height + 2);
|
||||
|
||||
PPOPUP->pSurfaceTree = nullptr;
|
||||
}
|
||||
|
@@ -68,9 +68,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
|
||||
|
||||
// Foreign Toplevel
|
||||
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
|
||||
// TODO: handle foreign events (requests)
|
||||
wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||
PWINDOW->createToplevelHandle();
|
||||
|
||||
// checks if the window wants borders and sets the appriopriate flag
|
||||
g_pXWaylandManager->checkBorders(PWINDOW);
|
||||
@@ -87,6 +85,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bRequestsFloat = true;
|
||||
}
|
||||
|
||||
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2);
|
||||
|
||||
if (PWORKSPACE->m_bDefaultFloating)
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
|
||||
@@ -118,13 +118,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
} else {
|
||||
const long int MONITOR = std::stoi(MONITORSTR);
|
||||
if (MONITOR >= (long int)g_pCompositor->m_vMonitors.size() || MONITOR < (long int)0)
|
||||
if (!g_pCompositor->getMonitorFromID(MONITOR))
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
PWINDOW->m_iMonitorID = MONITOR;
|
||||
}
|
||||
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
|
||||
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID));
|
||||
|
||||
Debug::log(ERR, "Rule monitor, applying to window %x -> mon: %i, workspace: %i", PWINDOW, PWINDOW->m_iMonitorID, PWINDOW->m_iWorkspaceID);
|
||||
} catch (std::exception& e) {
|
||||
@@ -327,6 +328,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -381,7 +384,17 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bIsMapped = false;
|
||||
|
||||
// refocus on a new window
|
||||
g_pInputManager->refocus();
|
||||
auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f);
|
||||
|
||||
if (!PWINDOWCANDIDATE)
|
||||
PWINDOWCANDIDATE = g_pCompositor->getFirstWindowOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (!PWINDOWCANDIDATE || PWINDOW == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->m_bHidden || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2)
|
||||
PWINDOWCANDIDATE = nullptr;
|
||||
|
||||
Debug::log(LOG, "On closed window, new focused candidate is %x", PWINDOWCANDIDATE);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
|
||||
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW);
|
||||
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
|
||||
@@ -408,8 +421,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_fAlpha = 0.f;
|
||||
|
||||
// Destroy Foreign Toplevel
|
||||
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
|
||||
PWINDOW->m_phForeignToplevel = nullptr;
|
||||
PWINDOW->destroyToplevelHandle();
|
||||
|
||||
// recheck idle inhibitors
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
@@ -465,8 +477,7 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle});
|
||||
|
||||
if (PWINDOW->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
|
||||
PWINDOW->updateToplevel();
|
||||
|
||||
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
||||
}
|
||||
@@ -474,17 +485,22 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (!PWINDOW->m_bIsMapped || PWINDOW->m_bHidden)
|
||||
return;
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
|
||||
|
||||
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, REQUESTED->fullscreen, FULLSCREEN_FULL);
|
||||
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
|
||||
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
@@ -511,7 +527,7 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
const auto E = (wlr_xwayland_surface_configure_event*)data;
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
if (!PWINDOW->m_bIsFloating) {
|
||||
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) {
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.vec());
|
||||
g_pInputManager->refocus();
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
@@ -40,6 +40,28 @@ static const float transforms[][9] = {{
|
||||
},
|
||||
};
|
||||
|
||||
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
|
||||
auto value = rawpath;
|
||||
|
||||
if (value[0] == '.') {
|
||||
auto currentDir = currentPath.substr(0, currentPath.find_last_of('/'));
|
||||
|
||||
if (value[1] == '.') {
|
||||
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
|
||||
value.replace(0, 2, parentDir);
|
||||
} else {
|
||||
value.replace(0, 1, currentDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (value[0] == '~') {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
value.replace(0, 1, std::string(ENVHOME));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
||||
ASSERT(pSignal);
|
||||
ASSERT(pListener);
|
||||
@@ -53,35 +75,6 @@ void handleNoop(struct wl_listener *listener, void *data) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
|
||||
struct wl_listener cursor;
|
||||
struct wl_listener end;
|
||||
|
||||
/* Add two special markers: one cursor and one end marker. This way, we know
|
||||
* that we've already called listeners on the left of the cursor and that we
|
||||
* don't want to call listeners on the right of the end marker. The 'it'
|
||||
* function can remove any element it wants from the list without troubles.
|
||||
* wl_list_for_each_safe tries to be safe but it fails: it works fine
|
||||
* if the current item is removed, but not if the next one is. */
|
||||
wl_list_insert(&signal->listener_list, &cursor.link);
|
||||
cursor.notify = handleNoop;
|
||||
wl_list_insert(signal->listener_list.prev, &end.link);
|
||||
end.notify = handleNoop;
|
||||
|
||||
while (cursor.link.next != &end.link) {
|
||||
struct wl_list *pos = cursor.link.next;
|
||||
struct wl_listener *l = wl_container_of(pos, l, link);
|
||||
|
||||
wl_list_remove(&cursor.link);
|
||||
wl_list_insert(pos, &cursor.link);
|
||||
|
||||
l->notify(l, data);
|
||||
}
|
||||
|
||||
wl_list_remove(&cursor.link);
|
||||
wl_list_remove(&end.link);
|
||||
}
|
||||
|
||||
std::string getFormat(const char *fmt, ...) {
|
||||
char* outputStr = nullptr;
|
||||
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "../includes.hpp"
|
||||
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
|
||||
void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
|
||||
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
void scaleBox(wlr_box*, float);
|
||||
@@ -17,4 +17,4 @@ std::string execAndGet(const char*);
|
||||
|
||||
float getPlusMinusKeywordResult(std::string in, float relative);
|
||||
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||
|
@@ -3,6 +3,11 @@
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
if (m_bEnabled)
|
||||
return;
|
||||
|
||||
szName = output->name;
|
||||
|
||||
// get monitor rule that matches
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name);
|
||||
|
||||
@@ -11,22 +16,68 @@ void CMonitor::onConnect(bool noRule) {
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (monitorRule.disabled) {
|
||||
|
||||
wlr_output_enable_adaptive_sync(output, 1);
|
||||
wlr_output_set_scale(output, 1);
|
||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
||||
|
||||
if (!PREFSTATE) {
|
||||
wlr_output_mode* mode;
|
||||
|
||||
wl_list_for_each(mode, &output->modes, link) {
|
||||
wlr_output_set_mode(output, PREFSTATE);
|
||||
|
||||
if (!wlr_output_test(output))
|
||||
continue;
|
||||
|
||||
PREFSTATE = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (PREFSTATE)
|
||||
wlr_output_set_mode(output, PREFSTATE);
|
||||
else
|
||||
Debug::log(WARN, "No mode found for disabled output %s", output->name);
|
||||
|
||||
wlr_output_enable(output, 0);
|
||||
wlr_output_commit(output);
|
||||
|
||||
if (!wlr_output_commit(output)) {
|
||||
Debug::log(ERR, "Couldn't commit disabled state on output %s", output->name);
|
||||
}
|
||||
|
||||
Events::listener_change(nullptr, nullptr);
|
||||
|
||||
m_bEnabled = false;
|
||||
|
||||
hyprListener_monitorFrame.removeCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_bRenderingInitPassed) {
|
||||
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||
m_bRenderingInitPassed = true;
|
||||
}
|
||||
|
||||
if (!m_pThisWrap) {
|
||||
|
||||
// find the wrap
|
||||
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);
|
||||
}
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
ID = g_pCompositor->getNextAvailableMonitorID();
|
||||
szName = output->name;
|
||||
|
||||
wlr_output_set_scale(output, monitorRule.scale);
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
|
||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
|
||||
@@ -48,7 +99,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!noRule)
|
||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||
|
||||
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)monitorRule.offset.x, (int)monitorRule.offset.y, (int)monitorRule.resolution.x, (int)monitorRule.resolution.y, output);
|
||||
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x, (int)vecPixelSize.y, output);
|
||||
|
||||
damage = wlr_output_damage_create(output);
|
||||
|
||||
@@ -96,6 +147,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
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);
|
||||
@@ -105,10 +158,19 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
g_pCompositor->m_pLastMonitor = this;
|
||||
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
||||
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(ID);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect() {
|
||||
|
||||
if (!m_bEnabled)
|
||||
return;
|
||||
|
||||
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
@@ -118,16 +180,22 @@ void CMonitor::onDisconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
|
||||
g_pCompositor->cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
hyprListener_monitorFrame.removeCallback();
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
||||
|
||||
hyprListener_monitorMode.removeCallback();
|
||||
hyprListener_monitorDestroy.removeCallback();
|
||||
|
||||
g_pCompositor->m_bUnsafeState = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
|
||||
|
||||
// snap cursor
|
||||
|
@@ -58,6 +58,7 @@ public:
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
||||
// For the list lookup
|
||||
|
||||
|
@@ -94,11 +94,16 @@ struct SKeyboard {
|
||||
|
||||
DYNLISTENER(keyboardMod);
|
||||
DYNLISTENER(keyboardKey);
|
||||
DYNLISTENER(keyboardKeymap);
|
||||
DYNLISTENER(keyboardDestroy);
|
||||
|
||||
bool isVirtual = false;
|
||||
bool active = false;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
|
||||
std::string name = "";
|
||||
std::string xkbFilePath = "";
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
@@ -272,4 +277,44 @@ struct SSwipeGesture {
|
||||
int speedPoints = 0;
|
||||
|
||||
CMonitor* pMonitor = nullptr;
|
||||
};
|
||||
};
|
||||
|
||||
struct STextInput {
|
||||
wlr_text_input_v3* pWlrInput = nullptr;
|
||||
|
||||
wlr_surface* pPendingSurface = nullptr;
|
||||
|
||||
DYNLISTENER(textInputEnable);
|
||||
DYNLISTENER(textInputDisable);
|
||||
DYNLISTENER(textInputCommit);
|
||||
DYNLISTENER(textInputDestroy);
|
||||
|
||||
DYNLISTENER(pendingSurfaceDestroy);
|
||||
};
|
||||
|
||||
struct SIMEKbGrab {
|
||||
wlr_input_method_keyboard_grab_v2* pWlrKbGrab = nullptr;
|
||||
|
||||
wlr_keyboard* pKeyboard = nullptr;
|
||||
|
||||
DYNLISTENER(grabDestroy);
|
||||
};
|
||||
|
||||
struct SIMEPopup {
|
||||
wlr_input_popup_surface_v2* pSurface = nullptr;
|
||||
|
||||
int x, y;
|
||||
int realX, realY;
|
||||
bool visible;
|
||||
|
||||
DYNLISTENER(mapPopup);
|
||||
DYNLISTENER(unmapPopup);
|
||||
DYNLISTENER(destroyPopup);
|
||||
DYNLISTENER(commitPopup);
|
||||
|
||||
DYNLISTENER(focusedSurfaceUnmap);
|
||||
|
||||
bool operator==(const SIMEPopup& other) {
|
||||
return pSurface == other.pSurface;
|
||||
}
|
||||
};
|
||||
|
@@ -14,6 +14,8 @@ void CHyprError::createQueued() {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||
|
||||
const auto FONTSIZE = std::clamp((int)(10.f * (PMONITOR->vecPixelSize.x / 1920.f)), 8, 40);
|
||||
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
@@ -27,7 +29,7 @@ void CHyprError::createQueued() {
|
||||
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
|
||||
|
||||
cairo_set_source_rgba(CAIRO, m_cQueued.r / 255.f, m_cQueued.g / 255.f, m_cQueued.b / 255.f, m_cQueued.a / 255.f);
|
||||
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, 10 * LINECOUNT);
|
||||
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, (FONTSIZE + 2 * (FONTSIZE / 10.f)) * LINECOUNT);
|
||||
|
||||
// outline
|
||||
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
|
||||
@@ -40,10 +42,10 @@ void CHyprError::createQueued() {
|
||||
const CColor textColor = m_cQueued.r * m_cQueued.g * m_cQueued.b < 0.5f ? CColor(255, 255, 255, 255) : CColor(0, 0, 0, 255);
|
||||
|
||||
cairo_select_font_face(CAIRO, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(CAIRO, 8);
|
||||
cairo_set_font_size(CAIRO, FONTSIZE);
|
||||
cairo_set_source_rgba(CAIRO, textColor.r / 255.f, textColor.g / 255.f, textColor.b / 255.f, textColor.a / 255.f);
|
||||
|
||||
float yoffset = 8;
|
||||
float yoffset = FONTSIZE;
|
||||
while(m_szQueued != "") {
|
||||
std::string current = m_szQueued.substr(0, m_szQueued.find('\n'));
|
||||
if (const auto NEWLPOS = m_szQueued.find('\n'); NEWLPOS != std::string::npos)
|
||||
@@ -52,7 +54,7 @@ void CHyprError::createQueued() {
|
||||
m_szQueued = "";
|
||||
cairo_move_to(CAIRO, 0, yoffset);
|
||||
cairo_show_text(CAIRO, current.c_str());
|
||||
yoffset += 9;
|
||||
yoffset += FONTSIZE + (FONTSIZE / 10.f);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#define class _class
|
||||
#define namespace _namespace
|
||||
#define static
|
||||
#define delete delete_
|
||||
|
||||
extern "C" {
|
||||
#include <wlr/backend.h>
|
||||
@@ -94,8 +95,12 @@ extern "C" {
|
||||
#include <wlr/types/wlr_xdg_foreign_v2.h>
|
||||
#include <wlr/types/wlr_pointer_gestures_v1.h>
|
||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||
#include <wlr/types/wlr_input_method_v2.h>
|
||||
#include <wlr/types/wlr_text_input_v3.h>
|
||||
#include <wlr/types/wlr_touch.h>
|
||||
}
|
||||
|
||||
#undef delete
|
||||
#undef class
|
||||
#undef namespace
|
||||
#undef static
|
||||
|
@@ -1,24 +1,7 @@
|
||||
#include "DwindleLayout.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive() {
|
||||
|
||||
// check the group, if we are in one and not active, ignore.
|
||||
if (pGroupParent && pGroupParent->groupMembers[pGroupParent->groupMemberActive] != this) {
|
||||
if (pWindow)
|
||||
pWindow->m_bHidden = true;
|
||||
return;
|
||||
} else {
|
||||
if (pWindow)
|
||||
pWindow->m_bHidden = false;
|
||||
}
|
||||
|
||||
if (pGroupParent) {
|
||||
// means we are in a group and focused. let's just act like the full window in this
|
||||
size = pGroupParent->size;
|
||||
position = pGroupParent->position;
|
||||
}
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force) {
|
||||
if (children[0]) {
|
||||
|
||||
const auto REVERSESPLITRATIO = 2.f - splitRatio;
|
||||
@@ -44,10 +27,10 @@ void SDwindleNodeData::recalcSizePosRecursive() {
|
||||
children[1]->size = Vector2D(size.x, size.y / 2.f * REVERSESPLITRATIO);
|
||||
}
|
||||
|
||||
children[0]->recalcSizePosRecursive();
|
||||
children[1]->recalcSizePosRecursive();
|
||||
children[0]->recalcSizePosRecursive(force);
|
||||
children[1]->recalcSizePosRecursive(force);
|
||||
} else {
|
||||
layout->applyNodeDataToWindow(this);
|
||||
layout->applyNodeDataToWindow(this, force);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +43,51 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pD
|
||||
}
|
||||
}
|
||||
|
||||
bool SDwindleNodeData::isGroupMember() {
|
||||
return pNextGroupMember && pNextGroupMember != this;
|
||||
}
|
||||
|
||||
SDwindleNodeData* SDwindleNodeData::getGroupHead() {
|
||||
SDwindleNodeData* current = this->pNextGroupMember;
|
||||
|
||||
while (current != this) {
|
||||
if (current->groupHead) {
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current->pNextGroupMember;
|
||||
}
|
||||
|
||||
this->groupHead = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
SDwindleNodeData* SDwindleNodeData::getGroupVisible() {
|
||||
SDwindleNodeData* current = this->pNextGroupMember;
|
||||
|
||||
while (current != this) {
|
||||
if (!current->pWindow->m_bHidden) {
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current->pNextGroupMember;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
|
||||
SDwindleNodeData* current = this->pNextGroupMember;
|
||||
|
||||
while (current != this) {
|
||||
current->pWindow->m_bHidden = current != pMember;
|
||||
current = current->pNextGroupMember;
|
||||
}
|
||||
|
||||
this->pWindow->m_bHidden = pMember != this;
|
||||
}
|
||||
|
||||
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
@@ -94,7 +122,7 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool force) {
|
||||
// Don't set nodes, only windows.
|
||||
if (pNode->isNode)
|
||||
return;
|
||||
@@ -129,7 +157,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
|
||||
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
|
||||
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
|
||||
return;
|
||||
}
|
||||
@@ -143,17 +171,19 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
|
||||
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.border = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = true;
|
||||
PWINDOW->m_sSpecialRenderData.border = true;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYTOP ? GAPSOUT : GAPSIN);
|
||||
@@ -203,6 +233,19 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
}
|
||||
|
||||
if (force) {
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
}
|
||||
|
||||
if (pNode->isGroupMember() && pNode->groupHead) {
|
||||
// update visible node
|
||||
const auto PVISNODE = pNode->getGroupVisible();
|
||||
|
||||
PVISNODE->pWindow->m_vRealSize = PWINDOW->m_vRealSize.goalv();
|
||||
PVISNODE->pWindow->m_vRealPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
@@ -215,6 +258,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
static auto *const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
|
||||
|
||||
// Populate the node with our window's data
|
||||
PNODE->workspaceID = pWindow->m_iWorkspaceID;
|
||||
PNODE->pWindow = pWindow;
|
||||
@@ -224,13 +269,22 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
SDwindleNodeData* OPENINGON;
|
||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
|
||||
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && !*PUSEACTIVE) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
|
||||
|
||||
// happens on reserved area
|
||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
} else if (*PUSEACTIVE) {
|
||||
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
||||
} else {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
|
||||
}
|
||||
|
||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
} else
|
||||
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
@@ -241,6 +295,16 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID);
|
||||
}
|
||||
|
||||
// first, check if OPENINGON isn't too big.
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->size.x, OPENINGON->size.y) : PMONITOR->vecSize;
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
@@ -250,6 +314,28 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->isGroupMember()) {
|
||||
const auto PHEAD = OPENINGON->getGroupHead();
|
||||
|
||||
const auto PTAIL = PHEAD->pPreviousGroupMember;
|
||||
|
||||
PHEAD->pPreviousGroupMember = PNODE;
|
||||
PTAIL->pNextGroupMember = PNODE;
|
||||
|
||||
PNODE->pNextGroupMember = PHEAD;
|
||||
PNODE->pPreviousGroupMember = PTAIL;
|
||||
|
||||
PHEAD->setGroupFocusedNode(PNODE);
|
||||
|
||||
PNODE->position = PHEAD->position;
|
||||
PNODE->size = PHEAD->size;
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's not, get the node under our cursor
|
||||
|
||||
@@ -323,35 +409,66 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
OPENINGON->pParent = NEWPARENT;
|
||||
PNODE->pParent = NEWPARENT;
|
||||
|
||||
if (OPENINGON->pGroupParent) {
|
||||
// means we opened on a group
|
||||
NEWPARENT->recalcSizePosRecursive();
|
||||
|
||||
// add the group deco
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
PNODE->pGroupParent = OPENINGON->pGroupParent;
|
||||
PNODE->pGroupParent->groupMembers.push_back(PNODE);
|
||||
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||
|
||||
PNODE->pGroupParent->recalcSizePosRecursive();
|
||||
} else {
|
||||
NEWPARENT->recalcSizePosRecursive();
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
applyNodeDataToWindow(OPENINGON);
|
||||
}
|
||||
applyNodeDataToWindow(PNODE);
|
||||
applyNodeDataToWindow(OPENINGON);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
if (!PNODE) {
|
||||
Debug::log(ERR, "onWindowRemovedTiling node null?");
|
||||
return;
|
||||
}
|
||||
|
||||
// check if it was grouped
|
||||
if (PNODE->isGroupMember()) {
|
||||
// get shit
|
||||
const auto PPREV = PNODE->pPreviousGroupMember;
|
||||
const auto PNEXT = PNODE->pNextGroupMember;
|
||||
|
||||
PPREV->pNextGroupMember = PNEXT;
|
||||
PNEXT->pPreviousGroupMember = PPREV;
|
||||
|
||||
if (PNODE->groupHead) {
|
||||
PNEXT->groupHead = true;
|
||||
PNEXT->pParent = PNODE->pParent;
|
||||
|
||||
if (PNODE->pParent) {
|
||||
if (PNODE->pParent->children[0] == PNODE) {
|
||||
PNODE->pParent->children[0] = PNEXT;
|
||||
} else {
|
||||
PNODE->pParent->children[1] = PNEXT;
|
||||
}
|
||||
}
|
||||
|
||||
PNEXT->position = PNODE->position;
|
||||
PNEXT->size = PNODE->size;
|
||||
|
||||
applyNodeDataToWindow(PNEXT);
|
||||
} else {
|
||||
const auto PHEAD = PNODE->getGroupHead();
|
||||
|
||||
PNEXT->position = PHEAD->position;
|
||||
PNEXT->size = PHEAD->size;
|
||||
|
||||
applyNodeDataToWindow(PNEXT);
|
||||
}
|
||||
|
||||
PNEXT->setGroupFocusedNode(PNEXT);
|
||||
PNEXT->pWindow->m_bHidden = false;
|
||||
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
if (!PPARENT) {
|
||||
Debug::log(LOG, "Removing last node (dwindle)");
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
return;
|
||||
}
|
||||
@@ -370,29 +487,6 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
// check if it was grouped
|
||||
if (PNODE->pGroupParent) {
|
||||
PNODE->pGroupParent->groupMembers.erase(PNODE->pGroupParent->groupMembers.begin() + PNODE->pGroupParent->groupMemberActive);
|
||||
|
||||
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
|
||||
PNODE->pGroupParent->groupMemberActive = 0;
|
||||
|
||||
if (PNODE->pGroupParent->groupMembers.size() <= 1) {
|
||||
PNODE->pGroupParent->isGroup = false;
|
||||
PSIBLING->pGroupParent = nullptr;
|
||||
PNODE->pGroupParent->groupMembers.clear();
|
||||
|
||||
PSIBLING->recalcSizePosRecursive();
|
||||
} else {
|
||||
PNODE->pGroupParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
// if the parent is to be removed, remove the group
|
||||
if (PPARENT == PNODE->pGroupParent) {
|
||||
toggleWindowGroup(PPARENT->groupMembers[PPARENT->groupMemberActive]->pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
PPARENT->valid = false;
|
||||
PNODE->valid = false;
|
||||
|
||||
@@ -407,6 +501,10 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
|
||||
if (!PMONITOR)
|
||||
return; // ???
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
@@ -432,17 +530,21 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
if (!PFULLWINDOW) { // ????
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
} else {
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
@@ -473,6 +575,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
|
||||
// get some data about our window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
@@ -504,11 +608,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -523,11 +627,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -542,14 +646,17 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
|
||||
SIDECONTAINER->recalcSizePosRecursive();
|
||||
TOPCONTAINER->recalcSizePosRecursive();
|
||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
@@ -616,10 +723,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
|
||||
// we need to fix XWayland windows by sending them to NARNIA
|
||||
// because otherwise they'd still be recieving mouse events
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
@@ -632,6 +735,16 @@ void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
|
||||
PNODE->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void addToDequeRecursive(std::deque<SDwindleNodeData*>* pDeque, std::deque<SDwindleNodeData*>* pParents, SDwindleNodeData* node) {
|
||||
if (node->isNode) {
|
||||
pParents->push_back(node);
|
||||
addToDequeRecursive(pDeque, pParents, node->children[0]);
|
||||
addToDequeRecursive(pDeque, pParents, node->children[1]);
|
||||
} else {
|
||||
pDeque->emplace_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
@@ -642,61 +755,115 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
if (!PNODE)
|
||||
return; // reject
|
||||
|
||||
const auto PGROUPPARENT = PNODE->pGroupParent;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
||||
|
||||
if (PGROUPPARENT) {
|
||||
// if there is a parent, release it
|
||||
const auto INACTIVEBORDERCOL = CColor(g_pConfigManager->getInt("general:col.inactive_border"));
|
||||
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||
node->pGroupParent = nullptr;
|
||||
node->pWindow->m_cRealBorderColor.setValueAndWarp(INACTIVEBORDERCOL); // no anim here because they pop in
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
fullscreenRequestForWindow(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FULLSCREEN_FULL, false);
|
||||
|
||||
for (auto& wd : node->pWindow->m_dWindowDecorations) {
|
||||
wd->updateWindow(node->pWindow);
|
||||
}
|
||||
}
|
||||
if (PNODE->isGroupMember()) {
|
||||
// dissolve group
|
||||
|
||||
const auto PHEAD = PNODE->getGroupHead();
|
||||
|
||||
SDwindleNodeData* current = PNODE->pNextGroupMember;
|
||||
|
||||
PNODE->pWindow->m_bIsFloating = PHEAD->pWindow->m_bIsFloating;
|
||||
|
||||
std::deque<CWindow*> toAddWindows;
|
||||
|
||||
PGROUPPARENT->groupMembers.clear();
|
||||
const auto PWINDOWNODE = PNODE->pWindow;
|
||||
toAddWindows.push_back(PWINDOWNODE);
|
||||
|
||||
PGROUPPARENT->isGroup = false;
|
||||
while (current != PNODE) {
|
||||
const auto PWINDOW = current->pWindow;
|
||||
current = current->pNextGroupMember;
|
||||
|
||||
PGROUPPARENT->recalcSizePosRecursive();
|
||||
toAddWindows.push_back(PWINDOW);
|
||||
|
||||
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
g_pCompositor->m_pLastWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("general:col.active_border"));
|
||||
} else {
|
||||
// if there is no parent, let's make one
|
||||
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
if (!PPARENT)
|
||||
return; // reject making group on single window
|
||||
|
||||
|
||||
PPARENT->isGroup = true;
|
||||
|
||||
// recursively get all members
|
||||
std::deque<SDwindleNodeData*> allChildren;
|
||||
PPARENT->getAllChildrenRecursive(&allChildren);
|
||||
|
||||
PPARENT->groupMembers = allChildren;
|
||||
|
||||
const auto GROUPINACTIVEBORDERCOL = CColor(g_pConfigManager->getInt("dwinle:col.group_border"));
|
||||
for (auto& c : PPARENT->groupMembers) {
|
||||
c->pGroupParent = PPARENT;
|
||||
c->pWindow->m_cRealBorderColor = GROUPINACTIVEBORDERCOL;
|
||||
|
||||
c->pWindow->m_dWindowDecorations.push_back(std::make_unique<CHyprGroupBarDecoration>(c->pWindow));
|
||||
|
||||
if (c->pWindow == g_pCompositor->m_pLastWindow)
|
||||
c->pWindow->m_cRealBorderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
|
||||
PWINDOW->m_bHidden = false;
|
||||
}
|
||||
|
||||
PPARENT->groupMemberActive = 0;
|
||||
PHEAD->pPreviousGroupMember = nullptr;
|
||||
PHEAD->pNextGroupMember = nullptr;
|
||||
onWindowRemoved(PHEAD->pWindow);
|
||||
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
for (auto& pw : toAddWindows) {
|
||||
const auto PNODE = getNodeFromWindow(pw);
|
||||
if (PNODE)
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
pw->m_vPosition = Vector2D(-1000000, -1000000);
|
||||
}
|
||||
|
||||
for (auto& pw : toAddWindows) {
|
||||
onWindowCreated(pw);
|
||||
}
|
||||
|
||||
recalculateMonitor(PWORKSPACE->m_iMonitorID);
|
||||
} else {
|
||||
// create group
|
||||
|
||||
if (!PNODE->pParent)
|
||||
return;
|
||||
|
||||
PNODE->groupHead = true;
|
||||
|
||||
std::deque<SDwindleNodeData*> newGroupMembers;
|
||||
std::deque<SDwindleNodeData*> nodesToRemove;
|
||||
|
||||
newGroupMembers.emplace_back(PNODE);
|
||||
|
||||
addToDequeRecursive(&newGroupMembers, &nodesToRemove, PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[1] : PNODE->pParent->children[0]);
|
||||
|
||||
for (auto& n : newGroupMembers) {
|
||||
if (n->isGroupMember())
|
||||
return; // reject nested groups
|
||||
}
|
||||
|
||||
for (auto& nd : nodesToRemove) {
|
||||
m_lDwindleNodesData.remove(*nd);
|
||||
}
|
||||
|
||||
PNODE->position = PNODE->pParent->position;
|
||||
PNODE->size = PNODE->pParent->size;
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
|
||||
if (PNODE->pParent->pParent) {
|
||||
if (PNODE->pParent->pParent->children[0] == PNODE->pParent) {
|
||||
PNODE->pParent->pParent->children[0] = PNODE;
|
||||
} else {
|
||||
PNODE->pParent->pParent->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
|
||||
const auto PPARENT2 = PNODE->pParent->pParent;
|
||||
|
||||
m_lDwindleNodesData.remove(*PNODE->pParent);
|
||||
|
||||
PNODE->pParent = PPARENT2;
|
||||
|
||||
// now remove everyone but head from tree
|
||||
// and set order
|
||||
for (int i = 0; i < (int)newGroupMembers.size(); ++i) {
|
||||
if (i != 0) {
|
||||
newGroupMembers[i]->groupHead = false;
|
||||
newGroupMembers[i]->pParent = PNODE->pParent;
|
||||
}
|
||||
|
||||
const auto PREVMEMBER = i == 0 ? newGroupMembers[newGroupMembers.size() - 1] : newGroupMembers[i - 1];
|
||||
const auto NEXTMEMBER = i == (int)newGroupMembers.size() - 1 ? newGroupMembers[0] : newGroupMembers[i + 1];
|
||||
|
||||
newGroupMembers[i]->pPreviousGroupMember = PREVMEMBER;
|
||||
newGroupMembers[i]->pNextGroupMember = NEXTMEMBER;
|
||||
}
|
||||
|
||||
// focus
|
||||
PNODE->setGroupFocusedNode(PNODE);
|
||||
}
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
@@ -713,13 +880,13 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
if (!PNODE)
|
||||
return result; // reject with empty
|
||||
|
||||
const auto PGROUPPARENT = PNODE->pGroupParent;
|
||||
SDwindleNodeData* current = PNODE->pNextGroupMember;
|
||||
|
||||
if (!PGROUPPARENT)
|
||||
return result; // reject with empty
|
||||
result.push_back(pWindow);
|
||||
|
||||
for (auto& node : PGROUPPARENT->groupMembers) {
|
||||
result.push_back(node->pWindow);
|
||||
while (current != PNODE) {
|
||||
result.push_back(current->pWindow);
|
||||
current = current->pNextGroupMember;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -731,33 +898,41 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
if (!PNODE || !PNODE->isGroupMember())
|
||||
return; // reject
|
||||
|
||||
if (!PNODE->pGroupParent)
|
||||
return; // reject
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
||||
|
||||
SDwindleNodeData* pNewNode;
|
||||
|
||||
if (forward)
|
||||
PNODE->pGroupParent->groupMemberActive++;
|
||||
pNewNode = PNODE->pNextGroupMember;
|
||||
else
|
||||
PNODE->pGroupParent->groupMemberActive--;
|
||||
pNewNode = PNODE->pPreviousGroupMember;
|
||||
|
||||
if (PNODE->pGroupParent->groupMemberActive < 0)
|
||||
PNODE->pGroupParent->groupMemberActive = PNODE->pGroupParent->groupMembers.size() - 1;
|
||||
PNODE->setGroupFocusedNode(pNewNode);
|
||||
|
||||
if ((long unsigned int)PNODE->pGroupParent->groupMemberActive >= PNODE->pGroupParent->groupMembers.size())
|
||||
PNODE->pGroupParent->groupMemberActive = 0;
|
||||
pNewNode->position = PNODE->position;
|
||||
pNewNode->size = PNODE->size;
|
||||
|
||||
PNODE->pGroupParent->recalcSizePosRecursive();
|
||||
applyNodeDataToWindow(pNewNode);
|
||||
|
||||
for (auto& gm : PNODE->pGroupParent->groupMembers) {
|
||||
for (auto& deco : gm->pWindow->m_dWindowDecorations) {
|
||||
deco->updateWindow(gm->pWindow);
|
||||
}
|
||||
pNewNode->pWindow->m_vRealSize.warp();
|
||||
pNewNode->pWindow->m_vRealPosition.warp();
|
||||
|
||||
g_pCompositor->focusWindow(pNewNode->pWindow);
|
||||
|
||||
pNewNode->pWindow->m_bIsFloating = PNODE->pWindow->m_bIsFloating;
|
||||
|
||||
if (PNODE->pWindow->m_bIsFullscreen) {
|
||||
PNODE->pWindow->m_bHidden = false;
|
||||
g_pCompositor->setWindowFullscreen(PNODE->pWindow, false, PWORKSPACE->m_efFullscreenMode);
|
||||
PNODE->pWindow->m_bHidden = true;
|
||||
g_pCompositor->setWindowFullscreen(pNewNode->pWindow, true, PWORKSPACE->m_efFullscreenMode);
|
||||
|
||||
pNewNode->pWindow->m_vRealSize.warp();
|
||||
pNewNode->pWindow->m_vRealPosition.warp();
|
||||
}
|
||||
|
||||
// focus
|
||||
g_pCompositor->focusWindow(PNODE->pGroupParent->groupMembers[PNODE->pGroupParent->groupMemberActive]->pWindow);
|
||||
}
|
||||
|
||||
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow) {
|
||||
@@ -769,7 +944,7 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
|
||||
if (!PNODE)
|
||||
return hints; // left for the future, maybe floating funkiness
|
||||
|
||||
if (PNODE->pGroupParent) {
|
||||
if (PNODE->isGroupMember()) {
|
||||
hints.isBorderColor = true;
|
||||
|
||||
if (pWindow == g_pCompositor->m_pLastWindow)
|
||||
@@ -894,4 +1069,4 @@ void CHyprDwindleLayout::onEnable() {
|
||||
|
||||
void CHyprDwindleLayout::onDisable() {
|
||||
m_lDwindleNodesData.clear();
|
||||
}
|
||||
}
|
||||
|
@@ -18,10 +18,9 @@ struct SDwindleNodeData {
|
||||
|
||||
bool splitTop = false; // for preserve_split
|
||||
|
||||
bool isGroup = false;
|
||||
int groupMemberActive = 0;
|
||||
std::deque<SDwindleNodeData*> groupMembers;
|
||||
SDwindleNodeData* pGroupParent = nullptr;
|
||||
bool groupHead = false;
|
||||
SDwindleNodeData* pNextGroupMember = nullptr;
|
||||
SDwindleNodeData* pPreviousGroupMember = nullptr;
|
||||
|
||||
Vector2D position;
|
||||
Vector2D size;
|
||||
@@ -37,8 +36,12 @@ struct SDwindleNodeData {
|
||||
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent && children[0] == rhs.children[0] && children[1] == rhs.children[1];
|
||||
}
|
||||
|
||||
void recalcSizePosRecursive();
|
||||
void recalcSizePosRecursive(bool force = false);
|
||||
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
|
||||
bool isGroupMember();
|
||||
SDwindleNodeData* getGroupHead();
|
||||
SDwindleNodeData* getGroupVisible();
|
||||
void setGroupFocusedNode(SDwindleNodeData*);
|
||||
CHyprDwindleLayout* layout = nullptr;
|
||||
};
|
||||
|
||||
@@ -65,7 +68,7 @@ private:
|
||||
std::list<SDwindleNodeData> m_lDwindleNodesData;
|
||||
|
||||
int getNodesOnWorkspace(const int&);
|
||||
void applyNodeDataToWindow(SDwindleNodeData*);
|
||||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
@@ -6,6 +6,16 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowCreatedFloating(pWindow);
|
||||
} else {
|
||||
wlr_box desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
||||
} else {
|
||||
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
}
|
||||
|
||||
onWindowCreatedTiling(pWindow);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +46,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
|
||||
|
||||
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11) { // XDG windows should be fine. TODO: check for weird atoms?
|
||||
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
|
||||
pWindow->m_bHidden = true;
|
||||
return;
|
||||
}
|
||||
@@ -77,7 +87,6 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
|
||||
if (pWindow->m_iX11Type != 2) {
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
}
|
||||
@@ -116,12 +125,14 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
|
||||
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goalv() / 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
|
||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
|
||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
|
||||
m_vLastDragXY = m_vBeginDragXY;
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
@@ -156,6 +167,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||
|
||||
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
|
||||
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
|
||||
return;
|
||||
|
||||
@@ -166,16 +179,19 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
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)));
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||
@@ -191,8 +207,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
if (PMONITOR) {
|
||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
||||
|
||||
DRAGGINGWINDOW->updateToplevel();
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
@@ -220,6 +240,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
// if the window is pseudo, update its size
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
||||
|
||||
onWindowCreatedTiling(pWindow);
|
||||
|
||||
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
|
||||
@@ -235,17 +257,17 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
|
||||
const auto POS = pWindow->m_vRealPosition.goalv();
|
||||
const auto SIZ = pWindow->m_vRealSize.goalv();
|
||||
|
||||
pWindow->m_vRealPosition.setValueAndWarp(POS + Vector2D(5, 5));
|
||||
pWindow->m_vRealSize.setValueAndWarp(SIZ - Vector2D(10, 10));
|
||||
|
||||
pWindow->m_vRealPosition = POS;
|
||||
pWindow->m_vRealSize = SIZ;
|
||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.vec() + (pWindow->m_vRealSize.vec() - pWindow->m_vLastFloatingSize) / 2.f;
|
||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
|
||||
pWindow->m_sSpecialRenderData.rounding = true;
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
pWindow->updateToplevel();
|
||||
}
|
||||
|
||||
void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
|
@@ -39,6 +39,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
||||
|
||||
PNODE->workspaceID = pWindow->m_iWorkspaceID;
|
||||
@@ -60,8 +62,26 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
PNODE->isMaster = true;
|
||||
PNODE->percMaster = lastSplitPercent;
|
||||
|
||||
// first, check if it isn't too big.
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
PNODE->isMaster = false;
|
||||
|
||||
// first, check if it isn't too big.
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// recalc
|
||||
@@ -215,17 +235,19 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
|
||||
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.border = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.rounding = true;
|
||||
PWINDOW->m_sSpecialRenderData.border = true;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYTOP ? GAPSOUT : GAPSIN);
|
||||
@@ -250,6 +272,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
}
|
||||
|
||||
if (m_bForceWarps) {
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
@@ -278,6 +305,8 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
|
||||
if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2)
|
||||
return;
|
||||
|
||||
m_bForceWarps = true;
|
||||
|
||||
float delta = pixResize.x / PMONITOR->vecSize.x;
|
||||
|
||||
PMASTER->percMaster += delta;
|
||||
@@ -285,12 +314,17 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
|
||||
std::clamp(PMASTER->percMaster, 0.05f, 0.95f);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
|
||||
m_bForceWarps = false;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
@@ -357,10 +391,6 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
|
||||
// we need to fix XWayland windows by sending them to NARNIA
|
||||
// because otherwise they'd still be recieving mouse events
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
|
@@ -44,6 +44,8 @@ private:
|
||||
|
||||
std::list<SMasterNodeData> m_lMasterNodesData;
|
||||
|
||||
bool m_bForceWarps = false;
|
||||
|
||||
int getNodesOnWorkspace(const int&);
|
||||
void applyNodeDataToWindow(SMasterNodeData*);
|
||||
SMasterNodeData* getNodeFromWindow(CWindow*);
|
||||
|
@@ -147,8 +147,8 @@ void CAnimationManager::tick() {
|
||||
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
||||
|
||||
if (PWINDOW) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
PWINDOW->updateWindowDecos();
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
} else if (PWORKSPACE) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bHidden)
|
||||
@@ -197,7 +197,7 @@ void CAnimationManager::tick() {
|
||||
if (PDECO) {
|
||||
const auto EXTENTS = PDECO->getWindowDecorationExtents();
|
||||
|
||||
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x + EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y + EXTENTS.topLeft.y,
|
||||
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
|
||||
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
|
||||
|
||||
if (!*PSHADOWIGNOREWINDOW) {
|
||||
@@ -257,21 +257,30 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
bool CAnimationManager::bezierExists(const std::string& bezier) {
|
||||
for (auto&[bc, bz] : m_mBezierCurves) {
|
||||
if (bc == bezier)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Anims
|
||||
//
|
||||
//
|
||||
|
||||
void CAnimationManager::animationPopin(CWindow* pWindow, bool close) {
|
||||
void CAnimationManager::animationPopin(CWindow* pWindow, bool close, float minPerc) {
|
||||
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
|
||||
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
|
||||
|
||||
if (!close) {
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f);
|
||||
pWindow->m_vRealSize.setValue(Vector2D(5, 5));
|
||||
pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}));
|
||||
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vValue / 2.f);
|
||||
} else {
|
||||
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f;
|
||||
pWindow->m_vRealSize = Vector2D(5, 5);
|
||||
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
|
||||
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vGoal / 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,14 +370,72 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||
}
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
animationPopin(pWindow, close);
|
||||
|
||||
float minPerc = 0.f;
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find("%") != std::string::npos) {
|
||||
try {
|
||||
auto percstr = pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
} catch (std::exception& e) {
|
||||
; // oops
|
||||
}
|
||||
}
|
||||
|
||||
animationPopin(pWindow, close, minPerc / 100.f);
|
||||
}
|
||||
} else {
|
||||
if (ANIMSTYLE == "slide") {
|
||||
animationSlide(pWindow, "", close);
|
||||
} else {
|
||||
// anim popin, fallback
|
||||
animationPopin(pWindow, close);
|
||||
|
||||
float minPerc = 0.f;
|
||||
if (ANIMSTYLE.find("%") != 0) {
|
||||
try {
|
||||
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
} catch (std::exception& e) {
|
||||
; // oops
|
||||
}
|
||||
}
|
||||
|
||||
animationPopin(pWindow, close, minPerc / 100.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
|
||||
if (config.find("window") == 0) {
|
||||
if (style == "slide") {
|
||||
return "";
|
||||
} else if (style.find("popin") == 0) {
|
||||
// try parsing
|
||||
float minPerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
try {
|
||||
auto percstr = style.substr(style.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
} catch (std::exception& e) {
|
||||
return "invalid minperc";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
minPerc; // fix warning
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
return "unknown style";
|
||||
} else if (config == "workspaces") {
|
||||
if (style == "slide" || style == "slidevert" || style == "fade")
|
||||
return "";
|
||||
|
||||
return "unknown style";
|
||||
} else {
|
||||
return "animation has no styles";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
@@ -18,6 +18,10 @@ public:
|
||||
|
||||
void onWindowPostCreateClose(CWindow*, bool close = false);
|
||||
|
||||
bool bezierExists(const std::string&);
|
||||
|
||||
std::string styleValidInConfigVar(const std::string&, const std::string&);
|
||||
|
||||
std::list<CAnimatedVariable*> m_lAnimatedVariables;
|
||||
|
||||
private:
|
||||
@@ -31,7 +35,7 @@ private:
|
||||
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
|
||||
|
||||
// Anim stuff
|
||||
void animationPopin(CWindow*, bool close = false);
|
||||
void animationPopin(CWindow*, bool close = false, float minPerc = 0.f);
|
||||
void animationSlide(CWindow*, std::string force = "", bool close = false);
|
||||
};
|
||||
|
||||
|
@@ -80,8 +80,8 @@ void CEventManager::startThread() {
|
||||
eventQueueMutex.lock();
|
||||
|
||||
if (m_dQueuedEvents.empty()){ // if queue empty, sleep and ignore
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
eventQueueMutex.unlock();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,8 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["layoutmsg"] = layoutmsg;
|
||||
m_mDispatchers["toggleopaque"] = toggleOpaque;
|
||||
m_mDispatchers["dpms"] = dpms;
|
||||
m_mDispatchers["movewindowpixel"] = moveWindow;
|
||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
}
|
||||
@@ -93,6 +95,9 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||
}
|
||||
|
||||
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
if (pKeyboard->isVirtual)
|
||||
return true;
|
||||
|
||||
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
|
||||
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
|
||||
@@ -257,6 +262,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
// call the dispatcher
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %s, %d)", modmask, key.c_str(), keysym);
|
||||
DISPATCHER->second(k.arg);
|
||||
|
||||
if (k.handler == "submap") {
|
||||
found = true; // don't process keybinds on submap change.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (k.repeat) {
|
||||
@@ -405,14 +415,7 @@ void CKeybindManager::spawn(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::killActive(std::string args) {
|
||||
if (g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) {
|
||||
g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastWindow);
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(g_pCompositor->windowFromCursor());
|
||||
g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow);
|
||||
}
|
||||
|
||||
void CKeybindManager::clearKeybinds() {
|
||||
@@ -466,7 +469,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
}
|
||||
|
||||
// remove constraints
|
||||
g_pCompositor->m_sSeat.mouse->constraintActive = false;
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
// if it exists, we warp to it
|
||||
if (g_pCompositor->getWorkspaceByID(workspaceToChangeTo)) {
|
||||
@@ -487,13 +490,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
else
|
||||
PMONITOR->specialWorkspaceOpen = true;
|
||||
|
||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||
// and that'd be annoying as hell
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(OLDWORKSPACEID);
|
||||
|
||||
// and fix on the new workspace
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
// here and only here begin anim. we don't want to anim visible workspaces on other monitors.
|
||||
// check if anim left or right
|
||||
const auto ANIMTOLEFT = workspaceToChangeTo > OLDWORKSPACEID;
|
||||
@@ -562,10 +558,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
else
|
||||
PMONITOR->specialWorkspaceOpen = true;
|
||||
|
||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||
// and that'd be annoying as hell
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(OLDWORKSPACE);
|
||||
|
||||
// set active and deactivate all other
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACE->m_pWlrHandle);
|
||||
PWORKSPACE->setActive(true);
|
||||
@@ -592,7 +584,15 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args.contains(',')) {
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
|
||||
args = args.substr(0, args.find_last_of(','));
|
||||
} else {
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
}
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
@@ -668,11 +668,27 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
// hacky, but works lol
|
||||
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
const auto ORIGINALARGS = args;
|
||||
|
||||
if (args.contains(',')) {
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
|
||||
args = args.substr(0, args.find_last_of(','));
|
||||
} else {
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
}
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
int workspaceToMoveTo = 0;
|
||||
std::string workspaceName = "";
|
||||
|
||||
@@ -683,14 +699,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
if (workspaceToMoveTo == PMONITOR->activeWorkspace)
|
||||
if (workspaceToMoveTo == PWINDOW->m_iWorkspaceID)
|
||||
return;
|
||||
|
||||
// may be null until later!
|
||||
@@ -706,7 +717,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
|
||||
g_pEventManager->m_bIgnoreEvents = true;
|
||||
|
||||
moveActiveToWorkspace(args);
|
||||
moveActiveToWorkspace(ORIGINALARGS);
|
||||
|
||||
PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
|
||||
|
||||
@@ -738,13 +749,27 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!PLASTWINDOW)
|
||||
return;
|
||||
|
||||
// remove constraints
|
||||
g_pCompositor->m_sSeat.mouse->constraintActive = false;
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
|
||||
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);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
}
|
||||
};
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PLASTWINDOW)) {
|
||||
@@ -801,7 +826,7 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
||||
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PLASTWINDOW))
|
||||
if (!g_pCompositor->windowValidMapped(PLASTWINDOW) || PLASTWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
@@ -1132,120 +1157,90 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeActive(std::string args) {
|
||||
if (!args.contains(' '))
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
|
||||
if (x == "exact") {
|
||||
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
|
||||
if (!isNumber(newX) || !isNumber(newY)) {
|
||||
Debug::log(ERR, "resizeTiledWindow: exact args not numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(newX);
|
||||
const int Y = std::stoi(newY);
|
||||
|
||||
if (X < 10 || Y < 10) {
|
||||
Debug::log(ERR, "resizeTiledWindow: exact args cannot be < 10");
|
||||
return;
|
||||
}
|
||||
|
||||
// calc the delta
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return; // ignore
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
const int DX = X - PWINDOW->m_vRealSize.goalv().x;
|
||||
const int DY = Y - PWINDOW->m_vRealSize.goalv().y;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(DX, DY));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNumber(x) || !isNumber(y)) {
|
||||
Debug::log(ERR, "resizeTiledWindow: args not numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(x);
|
||||
const int Y = std::stoi(y);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(Vector2D(X, Y));
|
||||
if (g_pCompositor->m_pLastWindow->m_vRealSize.goalv().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goalv().y > 1)
|
||||
g_pCompositor->m_pLastWindow->m_bHidden = false;
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActive(std::string args) {
|
||||
if (!args.contains(' '))
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
std::string y = args.substr(args.find_first_of(' ') + 1);
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
|
||||
|
||||
if (x == "exact") {
|
||||
std::string newX = y.substr(0, y.find_first_of(' '));
|
||||
std::string newY = y.substr(y.find_first_of(' ') + 1);
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
|
||||
}
|
||||
|
||||
if (!isNumber(newX) || !isNumber(newY)) {
|
||||
Debug::log(ERR, "moveActive: exact args not numbers");
|
||||
return;
|
||||
}
|
||||
void CKeybindManager::moveWindow(std::string args) {
|
||||
|
||||
const int X = std::stoi(newX);
|
||||
const int Y = std::stoi(newY);
|
||||
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
|
||||
const auto MOVECMD = args.substr(0, args.find_first_of(','));
|
||||
|
||||
if (X < 0 || Y < 0) {
|
||||
Debug::log(ERR, "moveActive: exact args cannot be < 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// calc the delta
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return; // ignore
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
const int DX = X - PWINDOW->m_vRealPosition.goalv().x;
|
||||
const int DY = Y - PWINDOW->m_vRealPosition.goalv().y;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(DX, DY));
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "moveWindow: no window");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNumber(x) || !isNumber(y)) {
|
||||
Debug::log(ERR, "moveActive: args not numbers");
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeWindow(std::string args) {
|
||||
|
||||
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
|
||||
const auto MOVECMD = args.substr(0, args.find_first_of(','));
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "resizeWindow: no window");
|
||||
return;
|
||||
}
|
||||
|
||||
const int X = std::stoi(x);
|
||||
const int Y = std::stoi(y);
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
|
||||
|
||||
if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1)
|
||||
PWINDOW->m_bHidden = false;
|
||||
}
|
||||
|
||||
void CKeybindManager::circleNext(std::string arg) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
|
||||
if (PWINDOWTOCHANGETO == g_pCompositor->m_pLastWindow || !PWINDOWTOCHANGETO)
|
||||
return;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return;
|
||||
if (g_pCompositor->m_pLastWindow->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsFullscreen) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
}
|
||||
};
|
||||
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
else
|
||||
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
|
||||
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
|
||||
|
||||
g_pCompositor->warpCursorTo(MIDPOINT);
|
||||
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
}
|
||||
|
||||
void CKeybindManager::focusWindow(std::string regexp) {
|
||||
@@ -1305,6 +1300,9 @@ void CKeybindManager::pass(std::string regexp) {
|
||||
// pass all mf shit
|
||||
wlr_seat_keyboard_notify_enter(g_pCompositor->m_sSeat.seat, g_pXWaylandManager->getWindowSurface(PWINDOW), KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
|
||||
|
||||
wlr_keyboard_modifiers kbmods = {g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0};
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &kbmods);
|
||||
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED);
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED);
|
||||
|
||||
|
@@ -94,6 +94,8 @@ private:
|
||||
static void forceRendererReload(std::string);
|
||||
static void resizeActive(std::string);
|
||||
static void moveActive(std::string);
|
||||
static void moveWindow(std::string);
|
||||
static void resizeWindow(std::string);
|
||||
static void circleNext(std::string);
|
||||
static void focusWindow(std::string);
|
||||
static void setSubmap(std::string);
|
||||
|
@@ -120,9 +120,9 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
|
||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size, bool force) {
|
||||
|
||||
if ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))
|
||||
if (!force && ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
|
||||
return;
|
||||
|
||||
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec();
|
||||
@@ -155,8 +155,11 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
|
||||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
|
||||
{
|
||||
pWindow->m_bNoInitialFocus = true;
|
||||
return true;
|
||||
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
|
||||
pWindow->m_bX11ShouldntFocus = true;
|
||||
|
||||
pWindow->m_bNoInitialFocus = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pWindow->m_uSurface.xwayland->role) {
|
||||
@@ -230,4 +233,22 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
|
||||
|
||||
if (pWindow->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return Vector2D(99999, 99999);
|
||||
|
||||
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel))
|
||||
return Vector2D(99999, 99999);
|
||||
|
||||
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height)
|
||||
: Vector2D(pWindow->m_uSurface.xdg->toplevel->current.max_width, pWindow->m_uSurface.xdg->toplevel->current.max_height);
|
||||
|
||||
if (MAXSIZE.x < 5)
|
||||
MAXSIZE.x = 99999;
|
||||
if (MAXSIZE.y < 5)
|
||||
MAXSIZE.y = 99999;
|
||||
|
||||
return MAXSIZE;
|
||||
}
|
||||
|
@@ -17,13 +17,14 @@ public:
|
||||
std::string getTitle(CWindow*);
|
||||
std::string getAppIDClass(CWindow*);
|
||||
void sendCloseWindow(CWindow*);
|
||||
void setWindowSize(CWindow*, const Vector2D&);
|
||||
void setWindowSize(CWindow*, const Vector2D&, bool force = false);
|
||||
void setWindowStyleTiled(CWindow*, uint32_t);
|
||||
void setWindowFullscreen(CWindow*, bool);
|
||||
wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&);
|
||||
bool shouldBeFloated(CWindow*);
|
||||
void moveXWaylandWindow(CWindow*, const Vector2D&);
|
||||
void checkBorders(CWindow*);
|
||||
Vector2D getMaxSizeForWindow(CWindow*);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager;
|
@@ -29,7 +29,9 @@ 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 PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
static auto *const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
|
||||
|
||||
if (!g_pCompositor->m_bReadyToProcess)
|
||||
return;
|
||||
@@ -67,7 +69,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
||||
|
||||
if (!CONSTRAINTWINDOW) {
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
unconstrainMouse();
|
||||
} else {
|
||||
// Native Wayland apps know how 2 constrain themselves.
|
||||
// XWayland, we just have to accept them. Might cause issues, but thats XWayland for ya.
|
||||
@@ -123,7 +125,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
ACTIVEWORKSPACE->setActive(true);
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
|
||||
}
|
||||
|
||||
Vector2D surfaceCoords;
|
||||
@@ -180,11 +182,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (!pFoundWindow && refocus)
|
||||
pFoundWindow = g_pCompositor->getFirstWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
// TODO: this causes crashes, sometimes. ???
|
||||
// if (refocus && !pFoundWindow) {
|
||||
// pFoundWindow = g_pCompositor->getFirstWindowOnWorkspace(PMONITOR->activeWorkspace);
|
||||
// }
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
@@ -212,9 +217,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
|
||||
|
||||
if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -233,11 +236,21 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y);
|
||||
}
|
||||
|
||||
bool allowKeyboardRefocus = true;
|
||||
|
||||
if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) {
|
||||
const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
|
||||
if (PLS && PLS->layerSurface->current.keyboard_interactive) {
|
||||
allowKeyboardRefocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
if (*PFOLLOWMOUSE != 1 && !refocus) {
|
||||
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
|
||||
// enter if change floating style
|
||||
if (*PFOLLOWMOUSE != 3)
|
||||
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
} else if (*PFOLLOWMOUSE == 2) {
|
||||
@@ -249,14 +262,22 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
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);
|
||||
return; // don't enter any new surfaces
|
||||
} else {
|
||||
if (*PFOLLOWMOUSE != 3)
|
||||
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
}
|
||||
} else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3)
|
||||
g_pCompositor->focusSurface(foundSurface);
|
||||
} else {
|
||||
if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3 && allowKeyboardRefocus) {
|
||||
g_pCompositor->focusSurface(foundSurface);
|
||||
g_pCompositor->m_pLastWindow = nullptr; // reset last window as we have a full focus on a LS
|
||||
}
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
@@ -315,7 +336,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
m_ecbClickBehavior = CLICKMODE_KILL;
|
||||
|
||||
// remove constraints
|
||||
g_pCompositor->m_sSeat.mouse->constraintActive = false;
|
||||
g_pInputManager->unconstrainMouse();
|
||||
refocus();
|
||||
|
||||
// set cursor
|
||||
@@ -428,10 +449,19 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
|
||||
|
||||
if (m_pActiveKeyboard)
|
||||
m_pActiveKeyboard->active = false;
|
||||
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
|
||||
const auto PKEYBOARD = (SKeyboard*)owner;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
|
||||
|
||||
}, PNEWKEYBOARD, "Keyboard");
|
||||
|
||||
disableAllKeyboards(false);
|
||||
|
||||
m_pActiveKeyboard = PNEWKEYBOARD;
|
||||
|
||||
PNEWKEYBOARD->active = true;
|
||||
|
||||
applyConfigToKeyboard(PNEWKEYBOARD);
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
|
||||
@@ -439,6 +469,41 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
|
||||
}
|
||||
|
||||
void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
|
||||
const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
|
||||
|
||||
PNEWKEYBOARD->keyboard = keyboard;
|
||||
PNEWKEYBOARD->isVirtual = true;
|
||||
|
||||
try {
|
||||
PNEWKEYBOARD->name = std::string(keyboard->name);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Keyboard had no name???"); // logic error
|
||||
}
|
||||
|
||||
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.keymap, [&](void* owner, void* data) {
|
||||
const auto PKEYBOARD = (SKeyboard*)owner;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," +getActiveLayoutForKeyboard(PKEYBOARD)}, true); // force as this should ALWAYS be sent
|
||||
|
||||
}, PNEWKEYBOARD, "Keyboard");
|
||||
|
||||
disableAllKeyboards(true);
|
||||
|
||||
m_pActiveKeyboard = PNEWKEYBOARD;
|
||||
|
||||
PNEWKEYBOARD->active = true;
|
||||
|
||||
applyConfigToKeyboard(PNEWKEYBOARD);
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
|
||||
|
||||
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
|
||||
}
|
||||
|
||||
void CInputManager::setKeyboardLayout() {
|
||||
for (auto& k : m_lKeyboards)
|
||||
applyConfigToKeyboard(&k);
|
||||
@@ -462,6 +527,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
|
||||
const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
|
||||
|
||||
const auto FILEPATH = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_file") : g_pConfigManager->getString("input:kb_file");
|
||||
const auto RULES = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_rules") : g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_model") : g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_layout") : g_pConfigManager->getString("input:kb_layout");
|
||||
@@ -469,7 +535,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "kb_options") : g_pConfigManager->getString("input:kb_options");
|
||||
|
||||
try {
|
||||
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
|
||||
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options && FILEPATH == pKeyboard->xkbFilePath) {
|
||||
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
|
||||
return;
|
||||
}
|
||||
@@ -483,6 +549,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
pKeyboard->repeatDelay = REPEATDELAY;
|
||||
pKeyboard->repeatRate = REPEATRATE;
|
||||
pKeyboard->numlockOn = NUMLOCKON;
|
||||
pKeyboard->xkbFilePath = FILEPATH.c_str();
|
||||
|
||||
xkb_rule_names rules = {
|
||||
.rules = RULES.c_str(),
|
||||
@@ -506,9 +573,25 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
|
||||
Debug::log(LOG, "Attempting to create a keymap for layout %s with variant %s (rules: %s, model: %s, options: %s)", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||
|
||||
auto KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_keymap * KEYMAP = NULL;
|
||||
|
||||
if (!FILEPATH.empty()) {
|
||||
auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath);
|
||||
|
||||
if (!std::filesystem::exists(path)) {
|
||||
Debug::log(ERR, "input:kb_file= file doesnt exist");
|
||||
} else {
|
||||
KEYMAP = xkb_keymap_new_from_file(CONTEXT, fopen(path.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!KEYMAP) {
|
||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
if (!KEYMAP) {
|
||||
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )");
|
||||
|
||||
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||
memset(&rules, 0, sizeof(rules));
|
||||
|
||||
@@ -540,6 +623,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(CONTEXT);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," +getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
|
||||
|
||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
|
||||
}
|
||||
|
||||
@@ -661,7 +746,7 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) {
|
||||
g_pCompositor->m_sSeat.mouse = m_lMice.size() > 0 ? &m_lMice.front() : nullptr;
|
||||
|
||||
if (g_pCompositor->m_sSeat.mouse)
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
unconstrainMouse();
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
@@ -670,14 +755,37 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
|
||||
if (passEvent) {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
|
||||
|
||||
const auto PIMEGRAB = m_sIMERelay.getIMEKeyboardGrab(pKeyboard);
|
||||
|
||||
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_key(PIMEGRAB->pWlrKbGrab, e->time_msec, e->keycode, e->state);
|
||||
} else {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
|
||||
const auto PIMEGRAB = m_sIMERelay.getIMEKeyboardGrab(pKeyboard);
|
||||
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
|
||||
const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
|
||||
|
||||
if (PWLRKB->modifiers.group != pKeyboard->activeLayout) {
|
||||
pKeyboard->activeLayout = PWLRKB->modifiers.group;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + getActiveLayoutForKeyboard(pKeyboard)}, true); // force as this should ALWAYS be sent
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::refocus() {
|
||||
@@ -685,16 +793,16 @@ void CInputManager::refocus() {
|
||||
}
|
||||
|
||||
void CInputManager::updateDragIcon() {
|
||||
if (!g_pInputManager->m_sDrag.dragIcon)
|
||||
if (!m_sDrag.dragIcon)
|
||||
return;
|
||||
|
||||
switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) {
|
||||
switch (m_sDrag.dragIcon->drag->grab_type) {
|
||||
case WLR_DRAG_GRAB_KEYBOARD:
|
||||
break;
|
||||
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
|
||||
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
|
||||
wlr_box box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal();
|
||||
m_sDrag.pos = getMouseCoordsInternal();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -773,6 +881,29 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
Debug::log(LOG, "Constrained mouse to %x", pMouse->currentConstraint);
|
||||
}
|
||||
|
||||
void CInputManager::unconstrainMouse() {
|
||||
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
|
||||
return;
|
||||
|
||||
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
||||
|
||||
if (CONSTRAINTWINDOW) {
|
||||
if (CONSTRAINTWINDOW->m_bIsX11) {
|
||||
wlr_xwayland_surface_activate(CONSTRAINTWINDOW->m_uSurface.xwayland, false);
|
||||
} else {
|
||||
wlr_xdg_toplevel_set_activated(CONSTRAINTWINDOW->m_uSurface.xdg->toplevel, false);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
g_pCompositor->m_sSeat.mouse->constraintActive = false;
|
||||
|
||||
// TODO: its better to somehow detect the workspace...
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
|
||||
g_pCompositor->m_sSeat.mouse->hyprListener_commitConstraint.removeCallback();
|
||||
}
|
||||
|
||||
void Events::listener_commitConstraint(void* owner, void* data) {
|
||||
//g_pInputManager->recheckConstraint((SMouse*)owner);
|
||||
}
|
||||
@@ -807,3 +938,32 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
|
||||
|
||||
return finalMask;
|
||||
}
|
||||
|
||||
std::string CInputManager::getActiveLayoutForKeyboard(SKeyboard* pKeyboard) {
|
||||
const auto WLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
|
||||
const auto KEYMAP = WLRKB->keymap;
|
||||
const auto STATE = WLRKB->xkb_state;
|
||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||
|
||||
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
||||
if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
|
||||
const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i);
|
||||
|
||||
if (LAYOUTNAME)
|
||||
return std::string(LAYOUTNAME);
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
void CInputManager::disableAllKeyboards(bool virt) {
|
||||
|
||||
for (auto& k : m_lKeyboards) {
|
||||
if (k.isVirtual != virt)
|
||||
continue;
|
||||
|
||||
k.active = false;
|
||||
}
|
||||
}
|
||||
|
@@ -5,12 +5,18 @@
|
||||
#include "../../helpers/WLClasses.hpp"
|
||||
#include "../../Window.hpp"
|
||||
#include "../../helpers/Timer.hpp"
|
||||
#include "InputMethodRelay.hpp"
|
||||
|
||||
enum eClickBehaviorMode {
|
||||
CLICKMODE_DEFAULT = 0,
|
||||
CLICKMODE_KILL
|
||||
};
|
||||
|
||||
struct STouchData {
|
||||
CWindow* touchFocusWindow = nullptr;
|
||||
Vector2D touchSurfaceOrigin;
|
||||
};
|
||||
|
||||
class CInputManager {
|
||||
public:
|
||||
|
||||
@@ -22,12 +28,15 @@ public:
|
||||
void onKeyboardMod(void*, SKeyboard*);
|
||||
|
||||
void newKeyboard(wlr_input_device*);
|
||||
void newVirtualKeyboard(wlr_input_device*);
|
||||
void newMouse(wlr_input_device*, bool virt = false);
|
||||
void destroyKeyboard(SKeyboard*);
|
||||
void destroyMouse(wlr_input_device*);
|
||||
|
||||
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
|
||||
void recheckConstraint(SMouse*);
|
||||
void unconstrainMouse();
|
||||
std::string getActiveLayoutForKeyboard(SKeyboard*);
|
||||
|
||||
Vector2D getMouseCoordsInternal();
|
||||
void refocus();
|
||||
@@ -42,6 +51,11 @@ public:
|
||||
eClickBehaviorMode getClickMode();
|
||||
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
|
||||
|
||||
void onTouchDown(wlr_touch_down_event*);
|
||||
void onTouchUp(wlr_touch_up_event*);
|
||||
void onTouchMove(wlr_touch_motion_event*);
|
||||
|
||||
STouchData m_sTouchData;
|
||||
|
||||
// for dragging floating windows
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
@@ -77,9 +91,13 @@ public:
|
||||
|
||||
CTimer m_tmrLastCursorMovement;
|
||||
|
||||
CInputMethodRelay m_sIMERelay;
|
||||
|
||||
// for shared mods
|
||||
uint32_t accumulateModsFromAllKBs();
|
||||
|
||||
CWindow* m_pFollowOnDnDBegin = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
// for click behavior override
|
||||
@@ -89,6 +107,8 @@ private:
|
||||
void processMouseDownNormal(wlr_pointer_button_event* e);
|
||||
void processMouseDownKill(wlr_pointer_button_event* e);
|
||||
|
||||
void disableAllKeyboards(bool virt = false);
|
||||
|
||||
uint32_t m_uiCapabilities = 0;
|
||||
|
||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||
|
447
src/managers/input/InputMethodRelay.cpp
Normal file
447
src/managers/input/InputMethodRelay.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
#include "InputMethodRelay.hpp"
|
||||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CInputMethodRelay::CInputMethodRelay() {
|
||||
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
if (m_pWLRIME) {
|
||||
Debug::log(ERR, "Cannot register 2 IMEs at once!");
|
||||
|
||||
wlr_input_method_v2_send_unavailable(pIME);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_pWLRIME = pIME;
|
||||
|
||||
hyprListener_IMECommit.initCallback(&m_pWLRIME->events.commit, [&](void* owner, void* data) {
|
||||
|
||||
const auto PTI = getFocusedTextInput();
|
||||
const auto PIMR = (CInputMethodRelay*)owner;
|
||||
|
||||
if (!PTI) {
|
||||
Debug::log(LOG, "No focused TextInput on IME Commit");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PIMR->m_pWLRIME->current.preedit.text) {
|
||||
wlr_text_input_v3_send_preedit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.preedit.text, PIMR->m_pWLRIME->current.preedit.cursor_begin, PIMR->m_pWLRIME->current.preedit.cursor_end);
|
||||
}
|
||||
|
||||
if (PIMR->m_pWLRIME->current.commit_text) {
|
||||
wlr_text_input_v3_send_commit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.commit_text);
|
||||
}
|
||||
|
||||
if (PIMR->m_pWLRIME->current.delete_.before_length || PIMR->m_pWLRIME->current.delete_.after_length) {
|
||||
wlr_text_input_v3_send_delete_surrounding_text(PTI->pWlrInput, PIMR->m_pWLRIME->current.delete_.before_length, PIMR->m_pWLRIME->current.delete_.after_length);
|
||||
}
|
||||
|
||||
wlr_text_input_v3_send_done(PTI->pWlrInput);
|
||||
|
||||
}, this, "IMERelay");
|
||||
|
||||
hyprListener_IMEDestroy.initCallback(&m_pWLRIME->events.destroy, [&](void* owner, void* data) {
|
||||
|
||||
m_pWLRIME = nullptr;
|
||||
|
||||
hyprListener_IMEDestroy.removeCallback();
|
||||
hyprListener_IMECommit.removeCallback();
|
||||
hyprListener_IMEGrab.removeCallback();
|
||||
hyprListener_IMENewPopup.removeCallback();
|
||||
|
||||
m_pKeyboardGrab.reset(nullptr);
|
||||
|
||||
const auto PTI = getFocusedTextInput();
|
||||
|
||||
Debug::log(LOG, "IME Destroy");
|
||||
|
||||
if (PTI) {
|
||||
setPendingSurface(PTI, PTI->pWlrInput->focused_surface);
|
||||
|
||||
wlr_text_input_v3_send_leave(PTI->pWlrInput);
|
||||
}
|
||||
|
||||
}, this, "IMERelay");
|
||||
|
||||
hyprListener_IMEGrab.initCallback(&m_pWLRIME->events.grab_keyboard, [&](void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "IME TextInput Keyboard Grab new");
|
||||
|
||||
m_pKeyboardGrab.reset(nullptr);
|
||||
|
||||
m_pKeyboardGrab = std::make_unique<SIMEKbGrab>();
|
||||
|
||||
m_pKeyboardGrab->pKeyboard = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
|
||||
|
||||
const auto PKBGRAB = (wlr_input_method_keyboard_grab_v2*)data;
|
||||
|
||||
m_pKeyboardGrab->pWlrKbGrab = PKBGRAB;
|
||||
|
||||
wlr_input_method_keyboard_grab_v2_set_keyboard(m_pKeyboardGrab->pWlrKbGrab, m_pKeyboardGrab->pKeyboard);
|
||||
|
||||
m_pKeyboardGrab->hyprListener_grabDestroy.initCallback(&PKBGRAB->events.destroy, [&](void* owner, void* data) {
|
||||
|
||||
m_pKeyboardGrab->hyprListener_grabDestroy.removeCallback();
|
||||
|
||||
Debug::log(LOG, "IME TextInput Keyboard Grab destroy");
|
||||
|
||||
if (m_pKeyboardGrab->pKeyboard) {
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &m_pKeyboardGrab->pKeyboard->modifiers);
|
||||
}
|
||||
|
||||
m_pKeyboardGrab.reset(nullptr);
|
||||
|
||||
}, m_pKeyboardGrab.get(), "IME Keyboard Grab");
|
||||
|
||||
}, 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;
|
||||
|
||||
PNEWPOPUP->hyprListener_commitPopup.initCallback(&PNEWPOPUP->pSurface->surface->events.commit, &Events::listener_commitInputPopup, PNEWPOPUP, "IME Popup");
|
||||
PNEWPOPUP->hyprListener_mapPopup.initCallback(&PNEWPOPUP->pSurface->events.map, &Events::listener_mapInputPopup, PNEWPOPUP, "IME Popup");
|
||||
PNEWPOPUP->hyprListener_unmapPopup.initCallback(&PNEWPOPUP->pSurface->events.unmap, &Events::listener_unmapInputPopup, PNEWPOPUP, "IME Popup");
|
||||
PNEWPOPUP->hyprListener_destroyPopup.initCallback(&PNEWPOPUP->pSurface->events.destroy, &Events::listener_destroyInputPopup, PNEWPOPUP, "IME Popup");
|
||||
|
||||
Debug::log(LOG, "New input popup");
|
||||
|
||||
}, this, "IMERelay");
|
||||
|
||||
const auto PTI = getFocusableTextInput();
|
||||
|
||||
if (PTI) {
|
||||
wlr_text_input_v3_send_enter(PTI->pWlrInput, PTI->pPendingSurface);
|
||||
setPendingSurface(PTI, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
if (!pPopup->pSurface->mapped)
|
||||
return;
|
||||
|
||||
const auto PFOCUSEDTI = getFocusedTextInput();
|
||||
|
||||
if (!PFOCUSEDTI || !PFOCUSEDTI->pWlrInput->focused_surface)
|
||||
return;
|
||||
|
||||
bool cursorRect = PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE;
|
||||
const auto PFOCUSEDSURFACE = PFOCUSEDTI->pWlrInput->focused_surface;
|
||||
auto cursorBox = PFOCUSEDTI->pWlrInput->current.cursor_rectangle;
|
||||
|
||||
Vector2D parentPos;
|
||||
Vector2D parentSize;
|
||||
|
||||
if (wlr_surface_is_layer_surface(PFOCUSEDSURFACE)) {
|
||||
const auto PLS = g_pCompositor->getLayerSurfaceFromWlr(wlr_layer_surface_v1_from_wlr_surface(PFOCUSEDSURFACE));
|
||||
|
||||
if (PLS) {
|
||||
parentPos = Vector2D(PLS->geometry.x, PLS->geometry.y) + g_pCompositor->getMonitorFromID(PLS->monitorID)->vecPosition;
|
||||
parentSize = Vector2D(PLS->geometry.width, PLS->geometry.height);
|
||||
}
|
||||
} else {
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(PFOCUSEDSURFACE);
|
||||
|
||||
if (PWINDOW) {
|
||||
parentPos = PWINDOW->m_vRealPosition.goalv();
|
||||
parentSize = PWINDOW->m_vRealSize.goalv();
|
||||
}
|
||||
}
|
||||
|
||||
if (!cursorRect) {
|
||||
cursorBox = {0, 0, (int)parentSize.x, (int)parentSize.y};
|
||||
}
|
||||
|
||||
// todo: anti-overflow
|
||||
|
||||
wlr_box finalBox = cursorBox;
|
||||
|
||||
pPopup->x = finalBox.x;
|
||||
pPopup->y = finalBox.y + finalBox.height;
|
||||
|
||||
pPopup->realX = finalBox.x + parentPos.x;
|
||||
pPopup->realY = finalBox.y + parentPos.y + finalBox.height;
|
||||
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, &finalBox);
|
||||
|
||||
damagePopup(pPopup);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::setIMEPopupFocus(SIMEPopup* pPopup, wlr_surface* pSurface) {
|
||||
updateInputPopup(pPopup);
|
||||
}
|
||||
|
||||
void Events::listener_mapInputPopup(void* owner, void* data) {
|
||||
const auto PPOPUP = (SIMEPopup*)owner;
|
||||
|
||||
Debug::log(LOG, "Mapped an IME Popup");
|
||||
|
||||
g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_unmapInputPopup(void* owner, void* data) {
|
||||
const auto PPOPUP = (SIMEPopup*)owner;
|
||||
|
||||
Debug::log(LOG, "Unmapped an IME Popup");
|
||||
|
||||
g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_destroyInputPopup(void* owner, void* data) {
|
||||
const auto PPOPUP = (SIMEPopup*)owner;
|
||||
|
||||
Debug::log(LOG, "Removed an IME Popup");
|
||||
|
||||
PPOPUP->hyprListener_commitPopup.removeCallback();
|
||||
PPOPUP->hyprListener_destroyPopup.removeCallback();
|
||||
PPOPUP->hyprListener_focusedSurfaceUnmap.removeCallback();
|
||||
PPOPUP->hyprListener_mapPopup.removeCallback();
|
||||
PPOPUP->hyprListener_unmapPopup.removeCallback();
|
||||
|
||||
g_pInputManager->m_sIMERelay.removePopup(PPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_commitInputPopup(void* owner, void* data) {
|
||||
const auto PPOPUP = (SIMEPopup*)owner;
|
||||
|
||||
g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::removePopup(SIMEPopup* pPopup) {
|
||||
m_lIMEPopups.remove(*pPopup);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::damagePopup(SIMEPopup* pPopup) {
|
||||
if (!pPopup->pSurface->mapped)
|
||||
return;
|
||||
|
||||
const auto PFOCUSEDTI = getFocusedTextInput();
|
||||
|
||||
if (!PFOCUSEDTI || !PFOCUSEDTI->pWlrInput->focused_surface)
|
||||
return;
|
||||
|
||||
Vector2D parentPos;
|
||||
|
||||
const auto PFOCUSEDSURFACE = PFOCUSEDTI->pWlrInput->focused_surface;
|
||||
|
||||
if (wlr_surface_is_layer_surface(PFOCUSEDSURFACE)) {
|
||||
const auto PLS = g_pCompositor->getLayerSurfaceFromWlr(wlr_layer_surface_v1_from_wlr_surface(PFOCUSEDSURFACE));
|
||||
|
||||
if (PLS) {
|
||||
parentPos = Vector2D(PLS->geometry.x, PLS->geometry.y) + g_pCompositor->getMonitorFromID(PLS->monitorID)->vecPosition;
|
||||
}
|
||||
} else {
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(PFOCUSEDSURFACE);
|
||||
|
||||
if (PWINDOW) {
|
||||
parentPos = PWINDOW->m_vRealPosition.goalv();
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageSurface(pPopup->pSurface->surface, parentPos.x + pPopup->x, parentPos.y + pPopup->y);
|
||||
}
|
||||
|
||||
SIMEKbGrab* CInputMethodRelay::getIMEKeyboardGrab(SKeyboard* pKeyboard) {
|
||||
|
||||
if (!m_pWLRIME)
|
||||
return nullptr;
|
||||
|
||||
if (!m_pKeyboardGrab.get())
|
||||
return nullptr;
|
||||
|
||||
const auto VIRTKB = wlr_input_device_get_virtual_keyboard(pKeyboard->keyboard);
|
||||
|
||||
if (VIRTKB && (wl_resource_get_client(VIRTKB->resource) == wl_resource_get_client(m_pKeyboardGrab->pWlrKbGrab->resource)))
|
||||
return nullptr;
|
||||
|
||||
if (wlr_keyboard_from_input_device(pKeyboard->keyboard) != m_pKeyboardGrab->pKeyboard)
|
||||
return nullptr;
|
||||
|
||||
return m_pKeyboardGrab.get();
|
||||
}
|
||||
|
||||
STextInput* CInputMethodRelay::getFocusedTextInput() {
|
||||
for (auto& ti : m_lTextInputs) {
|
||||
if (ti.pWlrInput->focused_surface) {
|
||||
return &ti;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
STextInput* CInputMethodRelay::getFocusableTextInput() {
|
||||
for (auto& ti : m_lTextInputs) {
|
||||
if (ti.pPendingSurface) {
|
||||
return &ti;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewTextInput(wlr_text_input_v3* pInput) {
|
||||
createNewTextInput(pInput);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
|
||||
const auto PTEXTINPUT = &m_lTextInputs.emplace_back();
|
||||
|
||||
PTEXTINPUT->pWlrInput = pInput;
|
||||
|
||||
PTEXTINPUT->hyprListener_textInputEnable.initCallback(&pInput->events.enable, [](void* owner, void* data) {
|
||||
|
||||
const auto PINPUT = (STextInput*)owner;
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
|
||||
Debug::log(ERR, "Enabling TextInput on no IME!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Enable TextInput");
|
||||
|
||||
wlr_input_method_v2_send_activate(g_pInputManager->m_sIMERelay.m_pWLRIME);
|
||||
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
|
||||
|
||||
}, PTEXTINPUT, "textInput");
|
||||
|
||||
PTEXTINPUT->hyprListener_textInputCommit.initCallback(&pInput->events.commit, [](void* owner, void* data) {
|
||||
|
||||
const auto PINPUT = (STextInput*)owner;
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
|
||||
Debug::log(ERR, "Committing TextInput on no IME!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PINPUT->pWlrInput->current_enabled) {
|
||||
Debug::log(ERR, "Disabled TextInput commit?");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
|
||||
|
||||
}, PTEXTINPUT, "textInput");
|
||||
|
||||
PTEXTINPUT->hyprListener_textInputDisable.initCallback(&pInput->events.disable, [](void* owner, void* data) {
|
||||
|
||||
const auto PINPUT = (STextInput*)owner;
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
|
||||
Debug::log(ERR, "Disabling TextInput on no IME!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Disable TextInput");
|
||||
|
||||
wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME);
|
||||
|
||||
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
|
||||
|
||||
}, PTEXTINPUT, "textInput");
|
||||
|
||||
PTEXTINPUT->hyprListener_textInputDestroy.initCallback(&pInput->events.destroy, [](void* owner, void* data) {
|
||||
|
||||
const auto PINPUT = (STextInput*)owner;
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
|
||||
Debug::log(ERR, "Disabling TextInput on no IME!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PINPUT->pWlrInput->current_enabled) {
|
||||
wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME);
|
||||
|
||||
g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput);
|
||||
}
|
||||
|
||||
g_pInputManager->m_sIMERelay.setPendingSurface(PINPUT, nullptr);
|
||||
|
||||
PINPUT->hyprListener_textInputCommit.removeCallback();
|
||||
PINPUT->hyprListener_textInputDestroy.removeCallback();
|
||||
PINPUT->hyprListener_textInputDisable.removeCallback();
|
||||
PINPUT->hyprListener_textInputEnable.removeCallback();
|
||||
|
||||
g_pInputManager->m_sIMERelay.removeTextInput(PINPUT->pWlrInput);
|
||||
|
||||
}, PTEXTINPUT, "textInput");
|
||||
}
|
||||
|
||||
void CInputMethodRelay::removeTextInput(wlr_text_input_v3* pInput) {
|
||||
m_lTextInputs.remove_if([&](const auto& other) { return other.pWlrInput == pInput; });
|
||||
}
|
||||
|
||||
void CInputMethodRelay::commitIMEState(wlr_text_input_v3* pInput) {
|
||||
if (!m_pWLRIME)
|
||||
return;
|
||||
|
||||
if (pInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT)
|
||||
wlr_input_method_v2_send_surrounding_text(m_pWLRIME, pInput->current.surrounding.text, pInput->current.surrounding.cursor, pInput->current.surrounding.anchor);
|
||||
|
||||
wlr_input_method_v2_send_text_change_cause(m_pWLRIME, pInput->current.text_change_cause);
|
||||
|
||||
if (pInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE)
|
||||
wlr_input_method_v2_send_content_type(m_pWLRIME, pInput->current.content_type.hint, pInput->current.content_type.purpose);
|
||||
|
||||
for (auto& p : m_lIMEPopups) {
|
||||
updateInputPopup(&p);
|
||||
}
|
||||
|
||||
wlr_input_method_v2_send_done(m_pWLRIME);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) {
|
||||
if (!m_pWLRIME)
|
||||
return;
|
||||
|
||||
for (auto& ti : m_lTextInputs) {
|
||||
if (ti.pPendingSurface) {
|
||||
|
||||
if (pSurface != ti.pPendingSurface)
|
||||
setPendingSurface(&ti, nullptr);
|
||||
|
||||
} else if (ti.pWlrInput->focused_surface) {
|
||||
|
||||
if (pSurface != ti.pWlrInput->focused_surface) {
|
||||
wlr_input_method_v2_send_deactivate(m_pWLRIME);
|
||||
commitIMEState(ti.pWlrInput);
|
||||
|
||||
wlr_text_input_v3_send_leave(ti.pWlrInput);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (pSurface && wl_resource_get_client(ti.pWlrInput->resource) == wl_resource_get_client(pSurface->resource)) {
|
||||
|
||||
if (m_pWLRIME) {
|
||||
wlr_text_input_v3_send_enter(ti.pWlrInput, pSurface);
|
||||
} else {
|
||||
setPendingSurface(&ti, pSurface);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputMethodRelay::setPendingSurface(STextInput* pInput, wlr_surface* pSurface) {
|
||||
pInput->pPendingSurface = pSurface;
|
||||
|
||||
if (pSurface) {
|
||||
pInput->hyprListener_pendingSurfaceDestroy.initCallback(&pSurface->events.destroy, [](void* owner, void* data) {
|
||||
const auto PINPUT = (STextInput*)owner;
|
||||
|
||||
PINPUT->pPendingSurface = nullptr;
|
||||
|
||||
PINPUT->hyprListener_pendingSurfaceDestroy.removeCallback();
|
||||
}, pInput, "TextInput");
|
||||
} else {
|
||||
pInput->hyprListener_pendingSurfaceDestroy.removeCallback();
|
||||
}
|
||||
}
|
48
src/managers/input/InputMethodRelay.hpp
Normal file
48
src/managers/input/InputMethodRelay.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../defines.hpp"
|
||||
#include "../../helpers/WLClasses.hpp"
|
||||
|
||||
class CInputMethodRelay {
|
||||
public:
|
||||
CInputMethodRelay();
|
||||
|
||||
void onNewIME(wlr_input_method_v2*);
|
||||
void onNewTextInput(wlr_text_input_v3*);
|
||||
|
||||
wlr_input_method_v2* m_pWLRIME = nullptr;
|
||||
|
||||
void commitIMEState(wlr_text_input_v3*);
|
||||
void removeTextInput(wlr_text_input_v3*);
|
||||
|
||||
void onKeyboardFocus(wlr_surface*);
|
||||
|
||||
STextInput* getFocusedTextInput();
|
||||
STextInput* getFocusableTextInput();
|
||||
|
||||
void setPendingSurface(STextInput*, wlr_surface*);
|
||||
|
||||
SIMEKbGrab* getIMEKeyboardGrab(SKeyboard*);
|
||||
|
||||
void setIMEPopupFocus(SIMEPopup*, wlr_surface*);
|
||||
void updateInputPopup(SIMEPopup*);
|
||||
void damagePopup(SIMEPopup*);
|
||||
void removePopup(SIMEPopup*);
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<SIMEKbGrab> m_pKeyboardGrab;
|
||||
|
||||
std::list<STextInput> m_lTextInputs;
|
||||
std::list<SIMEPopup> m_lIMEPopups;
|
||||
|
||||
DYNLISTENER(textInputNew);
|
||||
DYNLISTENER(IMECommit);
|
||||
DYNLISTENER(IMEDestroy);
|
||||
DYNLISTENER(IMEGrab);
|
||||
DYNLISTENER(IMENewPopup);
|
||||
|
||||
void createNewTextInput(wlr_text_input_v3*);
|
||||
|
||||
friend class CHyprRenderer;
|
||||
};
|
@@ -79,7 +79,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the left");
|
||||
} else {
|
||||
@@ -95,11 +95,13 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the right");
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
|
||||
PWORKSPACEL->m_bForceRendering = false;
|
||||
PWORKSPACER->m_bForceRendering = false;
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
|
||||
@@ -141,11 +143,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||
|
||||
PWORKSPACE->m_bForceRendering = true;
|
||||
PWORKSPACE->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
if (workspaceIDLeft != workspaceIDRight) {
|
||||
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||
|
||||
PWORKSPACER->m_bForceRendering = false;
|
||||
PWORKSPACER->m_fAlpha.setValueAndWarp(0.f);
|
||||
}
|
||||
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
@@ -161,11 +165,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||
|
||||
PWORKSPACE->m_bForceRendering = true;
|
||||
PWORKSPACE->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
if (workspaceIDLeft != workspaceIDRight) {
|
||||
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||
|
||||
PWORKSPACEL->m_bForceRendering = false;
|
||||
PWORKSPACEL->m_fAlpha.setValueAndWarp(0.f);
|
||||
}
|
||||
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
|
45
src/managers/input/Touch.cpp
Normal file
45
src/managers/input/Touch.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "InputManager.hpp"
|
||||
#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();
|
||||
|
||||
m_sTouchData.touchFocusWindow = nullptr;
|
||||
|
||||
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) {
|
||||
Vector2D local;
|
||||
if (g_pCompositor->m_pLastWindow->m_bIsX11) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv();
|
||||
} else {
|
||||
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), g_pCompositor->m_pLastWindow, local);
|
||||
}
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
|
||||
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, e->time_msec, e->touch_id, local.x, local.y);
|
||||
|
||||
m_sTouchData.touchFocusWindow = g_pCompositor->m_pLastWindow;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onTouchMove(wlr_touch_motion_event* e){
|
||||
if (g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
|
||||
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
}
|
||||
}
|
@@ -23,110 +23,6 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
|
||||
#endif
|
||||
|
||||
// Init shaders
|
||||
|
||||
GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC);
|
||||
m_shQUAD.program = prog;
|
||||
m_shQUAD.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shQUAD.color = glGetUniformLocation(prog, "color");
|
||||
m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shQUAD.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shQUAD.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
|
||||
m_shRGBA.program = prog;
|
||||
m_shRGBA.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shRGBA.tex = glGetUniformLocation(prog, "tex");
|
||||
m_shRGBA.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shRGBA.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shRGBA.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX);
|
||||
m_shRGBX.program = prog;
|
||||
m_shRGBX.tex = glGetUniformLocation(prog, "tex");
|
||||
m_shRGBX.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shRGBX.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shRGBX.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shRGBX.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT);
|
||||
m_shEXT.program = prog;
|
||||
m_shEXT.tex = glGetUniformLocation(prog, "tex");
|
||||
m_shEXT.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shEXT.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_shEXT.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shEXT.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shEXT.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
|
||||
m_shBLUR1.program = prog;
|
||||
m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
|
||||
m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR2);
|
||||
m_shBLUR2.program = prog;
|
||||
m_shBLUR2.tex = glGetUniformLocation(prog, "tex");
|
||||
m_shBLUR2.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_shBLUR2.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
|
||||
m_shSHADOW.program = prog;
|
||||
m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shSHADOW.range = glGetUniformLocation(prog, "range");
|
||||
m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
|
||||
m_shSHADOW.color = glGetUniformLocation(prog, "color");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
|
||||
m_shBORDER1.program = prog;
|
||||
m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_shBORDER1.thick = glGetUniformLocation(prog, "thick");
|
||||
m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_shBORDER1.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
m_shBORDER1.color = glGetUniformLocation(prog, "color");
|
||||
|
||||
Debug::log(LOG, "Shaders initialized successfully.");
|
||||
|
||||
// End shaders
|
||||
|
||||
pixman_region32_init(&m_rOriginalDamageRegion);
|
||||
@@ -180,6 +76,10 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) {
|
||||
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool fake) {
|
||||
m_RenderData.pMonitor = pMonitor;
|
||||
|
||||
if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) {
|
||||
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL));
|
||||
}
|
||||
|
||||
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
@@ -206,6 +106,9 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
|
||||
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
|
||||
initShaders();
|
||||
|
||||
// bind the primary Hypr Framebuffer
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
@@ -236,6 +139,112 @@ void CHyprOpenGLImpl::end() {
|
||||
m_iWLROutputFb = 0;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::initShaders() {
|
||||
GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC);
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX);
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT);
|
||||
m_RenderData.pCurrentMonData->m_shEXT.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shEXT.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR2);
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.thick = glGetUniformLocation(prog, "thick");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.color = glGetUniformLocation(prog, "color");
|
||||
|
||||
m_RenderData.pCurrentMonData->m_bShadersInitialized = true;
|
||||
|
||||
Debug::log(LOG, "Shaders initialized successfully.");
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::clear(const CColor& color) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
|
||||
|
||||
@@ -311,10 +320,10 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(m_shQUAD.program);
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program);
|
||||
|
||||
glUniformMatrix3fv(m_shQUAD.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
|
||||
const auto TOPLEFT = Vector2D(round, round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||
@@ -323,17 +332,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
|
||||
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
// Rounded corners
|
||||
glUniform2f(m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shQUAD.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shQUAD.radius, round);
|
||||
glUniform1i(m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round);
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
|
||||
|
||||
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(m_shQUAD.posAttrib);
|
||||
glEnableVertexAttribArray(m_shQUAD.texAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib);
|
||||
|
||||
if (pixman_region32_not_empty(damage)) {
|
||||
PIXMAN_DAMAGE_FOREACH(damage) {
|
||||
@@ -343,8 +352,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
|
||||
}
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray(m_shQUAD.posAttrib);
|
||||
glDisableVertexAttribArray(m_shQUAD.texAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
@@ -385,13 +394,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
|
||||
switch (tex.m_iType) {
|
||||
case TEXTURE_RGBA:
|
||||
shader = &m_shRGBA;
|
||||
shader = &m_RenderData.pCurrentMonData->m_shRGBA;
|
||||
break;
|
||||
case TEXTURE_RGBX:
|
||||
shader = &m_shRGBX;
|
||||
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
|
||||
break;
|
||||
case TEXTURE_EXTERNAL:
|
||||
shader = &m_shEXT;
|
||||
shader = &m_RenderData.pCurrentMonData->m_shEXT;
|
||||
break;
|
||||
default:
|
||||
RASSERT(false, "tex.m_iTarget unsupported!");
|
||||
@@ -510,10 +519,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
// prep two shaders
|
||||
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform1f(pShader->radius, *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
||||
if (pShader == &m_shBLUR1)
|
||||
glUniform2f(m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1)
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||
else
|
||||
glUniform2f(m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
|
||||
glUniform1i(pShader->tex, 0);
|
||||
|
||||
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -550,17 +559,17 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
pixman_region32_init(&tempDamage);
|
||||
wlr_region_scale(&tempDamage, &damage, 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET
|
||||
|
||||
drawPass(&m_shBLUR1, &tempDamage);
|
||||
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage);
|
||||
|
||||
// and draw
|
||||
for (int i = 1; i < *PBLURPASSES; ++i) {
|
||||
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
|
||||
drawPass(&m_shBLUR1, &tempDamage); // down
|
||||
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down
|
||||
}
|
||||
|
||||
for (int i = *PBLURPASSES - 1; i >= 0; --i) {
|
||||
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
|
||||
drawPass(&m_shBLUR2, &tempDamage); // up
|
||||
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up
|
||||
}
|
||||
|
||||
// finish
|
||||
@@ -741,6 +750,23 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
if (*PBORDERSIZE < 1)
|
||||
return;
|
||||
|
||||
if (round < 1) {
|
||||
// zero rounding, just lines
|
||||
wlr_box borderbox = {box->x - *PBORDERSIZE, box->y - *PBORDERSIZE, *PBORDERSIZE, box->height + 2 * *PBORDERSIZE};
|
||||
renderRect(&borderbox, col, 0); // left
|
||||
borderbox = {box->x, box->y - (int)*PBORDERSIZE, box->width + (int)*PBORDERSIZE, (int)*PBORDERSIZE};
|
||||
renderRect(&borderbox, col, 0); // top
|
||||
borderbox = {box->x + box->width, box->y, (int)*PBORDERSIZE, box->height + (int)*PBORDERSIZE};
|
||||
renderRect(&borderbox, col, 0); // right
|
||||
borderbox = {box->x, box->y + box->height, box->width, (int)*PBORDERSIZE};
|
||||
renderRect(&borderbox, col, 0); // bottom
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// adjust box
|
||||
box->x -= *PBORDERSIZE;
|
||||
box->y -= *PBORDERSIZE;
|
||||
@@ -761,27 +787,27 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(m_shBORDER1.program);
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
|
||||
|
||||
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
|
||||
const auto TOPLEFT = Vector2D(round, round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||
|
||||
glUniform2f(m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shBORDER1.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shBORDER1.radius, round);
|
||||
glUniform1f(m_shBORDER1.thick, *PBORDERSIZE);
|
||||
glUniform1i(m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, *PBORDERSIZE);
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
|
||||
|
||||
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(m_shBORDER1.posAttrib);
|
||||
glEnableVertexAttribArray(m_shBORDER1.texAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
|
||||
|
||||
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||
@@ -791,8 +817,8 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
}
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray(m_shBORDER1.posAttrib);
|
||||
glDisableVertexAttribArray(m_shBORDER1.texAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
@@ -1004,28 +1030,28 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(m_shSHADOW.program);
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program);
|
||||
|
||||
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
|
||||
|
||||
const auto TOPLEFT = Vector2D(range + round, range + round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
|
||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||
|
||||
// Rounded corners
|
||||
glUniform2f(m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shSHADOW.radius, range + round);
|
||||
glUniform1f(m_shSHADOW.range, range);
|
||||
glUniform1f(m_shSHADOW.shadowPower, SHADOWPOWER);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER);
|
||||
|
||||
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(m_shSHADOW.posAttrib);
|
||||
glEnableVertexAttribArray(m_shSHADOW.texAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
|
||||
|
||||
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||
@@ -1035,8 +1061,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
}
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray(m_shSHADOW.posAttrib);
|
||||
glDisableVertexAttribArray(m_shSHADOW.texAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
@@ -1081,10 +1107,10 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
// get the adequate tex
|
||||
std::string texPath = "/usr/share/hyprland/wall_";
|
||||
Vector2D textureSize;
|
||||
if (pMonitor->vecTransformedSize.x > 7000) {
|
||||
if (pMonitor->vecTransformedSize.x > 3850) {
|
||||
textureSize = Vector2D(7680, 4320);
|
||||
texPath += "8K.png";
|
||||
} else if (pMonitor->vecTransformedSize.x > 3000) {
|
||||
} else if (pMonitor->vecTransformedSize.x > 1930) {
|
||||
textureSize = Vector2D(3840, 2160);
|
||||
texPath += "4K.png";
|
||||
} else {
|
||||
@@ -1105,8 +1131,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
#ifndef GLES2
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
@@ -42,6 +42,18 @@ struct SMonitorRenderData {
|
||||
bool blurFBDirty = true;
|
||||
|
||||
wlr_box backgroundTexBox;
|
||||
|
||||
// Shaders
|
||||
bool m_bShadersInitialized = false;
|
||||
CShader m_shQUAD;
|
||||
CShader m_shRGBA;
|
||||
CShader m_shRGBX;
|
||||
CShader m_shEXT;
|
||||
CShader m_shBLUR1;
|
||||
CShader m_shBLUR2;
|
||||
CShader m_shSHADOW;
|
||||
CShader m_shBORDER1;
|
||||
//
|
||||
};
|
||||
|
||||
struct SCurrentRenderData {
|
||||
@@ -114,20 +126,10 @@ private:
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
|
||||
// Shaders
|
||||
CShader m_shQUAD;
|
||||
CShader m_shRGBA;
|
||||
CShader m_shRGBX;
|
||||
CShader m_shEXT;
|
||||
CShader m_shBLUR1;
|
||||
CShader m_shBLUR2;
|
||||
CShader m_shSHADOW;
|
||||
CShader m_shBORDER1;
|
||||
//
|
||||
|
||||
GLuint createProgram(const std::string&, const std::string&);
|
||||
GLuint compileShader(const GLuint&, std::string);
|
||||
void createBGTextureForMonitor(CMonitor*);
|
||||
void initShaders();
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||
|
@@ -32,10 +32,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
scaleBox(&windowBox, RDATA->output->scale);
|
||||
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
static auto *const PBORDERTHICK = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
|
||||
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
|
||||
rounding += *PBORDERTHICK;
|
||||
rounding *= RDATA->output->scale;
|
||||
|
||||
if (RDATA->surface && surface == RDATA->surface) {
|
||||
if (wlr_surface_is_xwayland_surface(surface) && !wlr_xwayland_surface_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 255.f) {
|
||||
@@ -80,16 +79,22 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
|
||||
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
|
||||
return false;
|
||||
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()) {
|
||||
return true;
|
||||
} else {
|
||||
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pWindow->m_iWorkspaceID == pMonitor->activeWorkspace)
|
||||
return true;
|
||||
|
||||
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
return true;
|
||||
// if not, check if it maybe is active on a different monitor.
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) ||
|
||||
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || // vvvv might be in animation progress vvvvv
|
||||
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
|
||||
|
||||
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
@@ -127,6 +132,9 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
|
||||
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen){
|
||||
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
continue;
|
||||
|
||||
if (w->m_iMonitorID != pMonitor->ID)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->m_bIsFullscreen)
|
||||
@@ -256,10 +264,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
||||
|
||||
if (renderdata.decorate) {
|
||||
if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) {
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
|
||||
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
|
||||
rounding *= pMonitor->scale;
|
||||
|
||||
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f;
|
||||
@@ -306,6 +315,18 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
|
||||
wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {
|
||||
SRenderData renderdata = {pMonitor->output, time, pPopup->realX, pPopup->realY};
|
||||
|
||||
renderdata.blur = false;
|
||||
renderdata.surface = pPopup->pSurface->surface;
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = pPopup->pSurface->surface->current.width;
|
||||
renderdata.h = pPopup->pSurface->surface->current.height;
|
||||
|
||||
wlr_surface_for_each_surface(pPopup->pSurface->surface, renderSurface, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(ID);
|
||||
|
||||
@@ -405,6 +426,12 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
|
||||
// Render IME popups
|
||||
for (auto& imep : g_pInputManager->m_sIMERelay.m_lIMEPopups) {
|
||||
renderIMEPopup(&imep, PMONITOR, time);
|
||||
}
|
||||
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
@@ -654,6 +681,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
||||
if (!pSurface)
|
||||
return; // wut?
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
pixman_region32_t damageBox;
|
||||
pixman_region32_init(&damageBox);
|
||||
wlr_surface_get_effective_damage(pSurface, &damageBox);
|
||||
@@ -694,6 +724,9 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
||||
@@ -708,6 +741,9 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
wlr_output_damage_add_box(pMonitor->damage, &damageBox);
|
||||
|
||||
@@ -718,6 +754,9 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
@@ -778,7 +817,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
if (pMonitor->m_bEnabled)
|
||||
pMonitor->onDisconnect();
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pMonitor->m_bEnabled) {
|
||||
@@ -787,7 +826,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
}
|
||||
|
||||
// Check if the rule isn't already applied
|
||||
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
|
||||
if (!force
|
||||
&& DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1)
|
||||
&& DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1)
|
||||
&& DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1)
|
||||
&& pMonitor->scale == pMonitorRule->scale
|
||||
&& ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || pMonitorRule->offset == Vector2D(-1, -1))
|
||||
&& pMonitor->transform == pMonitorRule->transform) {
|
||||
|
||||
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -859,6 +905,8 @@ 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;
|
||||
|
||||
Debug::log(LOG, "Setting custom mode for %s", pMonitor->output->name);
|
||||
}
|
||||
} else {
|
||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||
@@ -896,6 +944,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
|
||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
||||
|
||||
Debug::log(LOG, "Setting preferred mode for %s", pMonitor->output->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,9 +968,23 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
|
||||
pMonitor->vecTransformedSize = Vector2D(x,y);
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitorRule->offset.x, (int)pMonitorRule->offset.y);
|
||||
if (pMonitorRule->offset == Vector2D(-1, -1)) {
|
||||
// let's find manually a sensible position for it, to the right.
|
||||
Vector2D finalPos;
|
||||
|
||||
//wlr_output_damage_add_whole(pMonitor->damage);
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->ID == pMonitor->ID)
|
||||
continue;
|
||||
|
||||
if (m->vecPosition.x + std::ceil(m->vecSize.x) > finalPos.x) {
|
||||
finalPos.x = m->vecPosition.x + std::ceil(m->vecSize.x);
|
||||
}
|
||||
}
|
||||
|
||||
pMonitor->vecPosition = finalPos;
|
||||
}
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
|
||||
wlr_output_enable(pMonitor->output, true);
|
||||
|
||||
|
@@ -51,6 +51,7 @@ private:
|
||||
void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode);
|
||||
void renderLayer(SLayerSurface*, CMonitor*, timespec*);
|
||||
void renderDragIcon(CMonitor*, timespec*);
|
||||
void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*);
|
||||
|
||||
bool m_bHasARenderedCursor = true;
|
||||
|
||||
|
@@ -10,4 +10,11 @@ GLint CShader::getUniformLocation(const std::string& unif) {
|
||||
}
|
||||
|
||||
return itpos->second;
|
||||
}
|
||||
|
||||
CShader::~CShader() {
|
||||
// destroy shader
|
||||
if (program != 0) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
@@ -5,7 +5,9 @@
|
||||
|
||||
class CShader {
|
||||
public:
|
||||
GLuint program;
|
||||
~CShader();
|
||||
|
||||
GLuint program = 0;
|
||||
GLint proj;
|
||||
GLint color;
|
||||
GLint tex;
|
||||
|
@@ -80,6 +80,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
return; // cannot parse
|
||||
}
|
||||
|
||||
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ? 0 : (m_pWindow->m_sAdditionalConfigData.rounding == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding);
|
||||
|
||||
// update the extents
|
||||
m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}};
|
||||
|
||||
@@ -92,12 +94,14 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor((wlr_box *)nullptr);
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
@@ -106,18 +110,20 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
scaleBox(&windowBox, pMonitor->scale);
|
||||
|
||||
if (windowBox.width < 1 || windowBox.height < 1) {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
return; // prevent assert failed
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
return; // prevent assert failed
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->renderRect(&windowBox, CColor(0,0,0,0), *PROUNDING);
|
||||
|
||||
g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 0), ROUNDING * pMonitor->scale);
|
||||
|
||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
}
|
||||
|
||||
scaleBox(&fullBox, pMonitor->scale);
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
// cleanup
|
||||
|
@@ -112,7 +112,7 @@ static void workspace_handle_remove(struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&workspace->events.remove_request, NULL);
|
||||
wl_signal_emit_mutable(&workspace->events.remove_request, NULL);
|
||||
}
|
||||
|
||||
static void workspace_handle_deactivate(struct wl_client *client,
|
||||
@@ -312,7 +312,7 @@ void wlr_ext_workspace_handle_v1_destroy(
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&workspace->events.destroy, workspace);
|
||||
wl_signal_emit_mutable(&workspace->events.destroy, workspace);
|
||||
|
||||
workspace_manager_update_idle_source(workspace->group->manager);
|
||||
|
||||
@@ -338,7 +338,7 @@ static void workspace_group_handle_handle_create_workspace(struct wl_client *cli
|
||||
struct wlr_ext_workspace_group_handle_v1_create_workspace_event event;
|
||||
event.workspace_group = group;
|
||||
event.name = arg;
|
||||
wlr_signal_emit_safe(&group->events.create_workspace_request, &event);
|
||||
wl_signal_emit_mutable(&group->events.create_workspace_request, &event);
|
||||
}
|
||||
|
||||
static void workspace_group_handle_handle_destroy(struct wl_client *client,
|
||||
@@ -513,7 +513,7 @@ void wlr_ext_workspace_group_handle_v1_destroy(
|
||||
wlr_ext_workspace_handle_v1_destroy(workspace);
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&group->events.destroy, group);
|
||||
wl_signal_emit_mutable(&group->events.destroy, group);
|
||||
workspace_manager_update_idle_source(group->manager);
|
||||
|
||||
struct wlr_ext_workspace_group_handle_v1_output *output, *tmp2;
|
||||
@@ -556,7 +556,7 @@ static void workspace_manager_commit(struct wl_client *client,
|
||||
}
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&manager->events.commit, manager);
|
||||
wl_signal_emit_mutable(&manager->events.commit, manager);
|
||||
}
|
||||
|
||||
static void workspace_manager_stop(struct wl_client *client,
|
||||
@@ -602,7 +602,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_workspace_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, display_destroy);
|
||||
|
||||
wlr_signal_emit_safe(&manager->events.destroy, manager);
|
||||
wl_signal_emit_mutable(&manager->events.destroy, manager);
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
|
||||
|
Submodule subprojects/wlroots updated: 7b5e890e61...7c575922c0
Reference in New Issue
Block a user