mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-18 05:23:47 -07:00
Compare commits
224 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b08b72358a | ||
|
aac75ddcbf | ||
|
5cd5631fb2 | ||
|
b8a7b09092 | ||
|
81f4a4f471 | ||
|
2623364dbd | ||
|
3b03597784 | ||
|
ce9c5fd722 | ||
|
f2999e84b9 | ||
|
2fed1badbf | ||
|
7c1dacea09 | ||
|
08310b4af9 | ||
|
16fd9084ea | ||
|
0ba28a46fd | ||
|
8370a7fcc4 | ||
|
629e61c7a5 | ||
|
2e323a5671 | ||
|
8c9e2e1ff1 | ||
|
5c8a20be77 | ||
|
d2eb4fee76 | ||
|
4537860079 | ||
|
7f47655f60 | ||
|
2c7b2ad6ca | ||
|
ddb8c89776 | ||
|
cacdb424a9 | ||
|
b156a9654f | ||
|
3229862dd4 | ||
|
06563d7034 | ||
|
459afcc47f | ||
|
06f5910365 | ||
|
b159634ef9 | ||
|
db2367bf33 | ||
|
f8def68e7e | ||
|
9f7382bca4 | ||
|
d3a644d81c | ||
|
70dae78c1b | ||
|
5e577acf51 | ||
|
21f64b6660 | ||
|
7a7e3ee6d9 | ||
|
9c9f56743e | ||
|
64e7d5345d | ||
|
29d017f54b | ||
|
26579fa962 | ||
|
0c61a1530f | ||
|
da7ea2b33d | ||
|
382af06406 | ||
|
515a363ecd | ||
|
fe54dcb4eb | ||
|
42f46aeac5 | ||
|
4cc0e6de90 | ||
|
d9f7f039e1 | ||
|
b99ac063ea | ||
|
b33d82734f | ||
|
f49af187bc | ||
|
e632bf176b | ||
|
41358c6fb5 | ||
|
bbedb065e1 | ||
|
bc34713b29 | ||
|
0c974b7236 | ||
|
8407a9af0a | ||
|
c4f288582b | ||
|
981c71e60a | ||
|
86e487e003 | ||
|
34d845da13 | ||
|
07d7962c7f | ||
|
18f9fb5e0f | ||
|
6f91997f06 | ||
|
283a8e77aa | ||
|
50755d26d4 | ||
|
05047f60f4 | ||
|
738ec900f4 | ||
|
86ca283352 | ||
|
6c28388420 | ||
|
e96fcb31f0 | ||
|
64fc19cc81 | ||
|
1012e2735a | ||
|
990ad854bd | ||
|
d83296c7a9 | ||
|
62c75883d1 | ||
|
7ed66abe57 | ||
|
4294456cdc | ||
|
a82559f185 | ||
|
01f85a09a9 | ||
|
69fae18e63 | ||
|
c241da5ea5 | ||
|
0283c498d6 | ||
|
fc59cef1ee | ||
|
2f875aec79 | ||
|
cfa4086b0b | ||
|
cbe9bf0e69 | ||
|
83ad6b9af8 | ||
|
cabdf38ce4 | ||
|
2295bbdd80 | ||
|
74ca81cc79 | ||
|
5ac625d7bd | ||
|
1d902a4621 | ||
|
302ec1372c | ||
|
d768226de9 | ||
|
c55c28ec7f | ||
|
c4dec4f796 | ||
|
0f1911a8d4 | ||
|
e43f7fc98d | ||
|
fbabb105c3 | ||
|
f0e4f6622e | ||
|
9a88c19f1a | ||
|
7762ac0173 | ||
|
e8c6d0f51e | ||
|
807b52b019 | ||
|
0e31eaa157 | ||
|
24ed9b061f | ||
|
528cfc2889 | ||
|
91fbee24da | ||
|
6beb79f27b | ||
|
64ce06a353 | ||
|
e1edfde539 | ||
|
10fd75c833 | ||
|
7932e42507 | ||
|
003993337a | ||
|
bca3068db2 | ||
|
cf37922d42 | ||
|
d123835ef5 | ||
|
7f753cab9a | ||
|
4afeedbd56 | ||
|
10db5a4fdb | ||
|
1a4e6e6a4b | ||
|
e4e6ddb075 | ||
|
4ef684f615 | ||
|
2629cfeeab | ||
|
d83e5b8409 | ||
|
df98db5092 | ||
|
d87010f300 | ||
|
c5a7202cd9 | ||
|
70e4162dcc | ||
|
147e962370 | ||
|
d7db7040d4 | ||
|
67be8d89b5 | ||
|
18956144d5 | ||
|
871ab24c6e | ||
|
ce0f248d20 | ||
|
dd0bf87c01 | ||
|
6ba8310c13 | ||
|
ca3791fed8 | ||
|
9cf72a30fc | ||
|
e76bd43f53 | ||
|
baf81cdc5d | ||
|
9f72d508ae | ||
|
1844e8adad | ||
|
b540d28849 | ||
|
fd73a7f795 | ||
|
51a930f802 | ||
|
a7cfbdb854 | ||
|
1e3571eb5b | ||
|
5484411232 | ||
|
f1ad270ff8 | ||
|
b3a86952cf | ||
|
409ff027f8 | ||
|
438d063ec6 | ||
|
078ba6daa8 | ||
|
74b49de883 | ||
|
8afc2f45c7 | ||
|
5f4659afef | ||
|
0887e2ee6e | ||
|
62e3953f5b | ||
|
9c9b74179c | ||
|
a2bb95fc60 | ||
|
12227d7b6a | ||
|
a4c120d608 | ||
|
53285a75ad | ||
|
f877d68f4f | ||
|
5bfd5a9240 | ||
|
eb1f832fce | ||
|
799add8659 | ||
|
90cb5fb672 | ||
|
d1ec314a03 | ||
|
7bcc01efb7 | ||
|
206ac000b9 | ||
|
1eb6cfd45c | ||
|
088b4a68e6 | ||
|
086f724951 | ||
|
ad244190e0 | ||
|
9f8c5cb63c | ||
|
5627b70981 | ||
|
79b8576df9 | ||
|
ba714b3b71 | ||
|
d7935356da | ||
|
9ef7225532 | ||
|
642030f959 | ||
|
78826c6d18 | ||
|
b5b9af508a | ||
|
d68f8ea668 | ||
|
5b84b0fb44 | ||
|
621eac32d3 | ||
|
824813fc6a | ||
|
7c207243e4 | ||
|
b748b0734f | ||
|
896a78aaa0 | ||
|
cc01550aff | ||
|
413a36a914 | ||
|
86ef85efae | ||
|
a483376591 | ||
|
f2725a374a | ||
|
7fde80f38e | ||
|
cc4ccfdbfd | ||
|
2f87e4c2f3 | ||
|
e7c2ea9724 | ||
|
826dc61e5c | ||
|
a31dceb2c6 | ||
|
1ba7a09bf6 | ||
|
afe8d8dfec | ||
|
7e5ba5e824 | ||
|
83cd5e2ebd | ||
|
7f0738bcb3 | ||
|
583b8842e7 | ||
|
a8541d5f64 | ||
|
4ad03af544 | ||
|
0859944c9a | ||
|
c0be1e2fd8 | ||
|
7b73a332ea | ||
|
a5d63a0324 | ||
|
8435d6fc12 | ||
|
d1d4683c91 | ||
|
bf04c83e3d | ||
|
0432804b18 | ||
|
da093a8aec |
55
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
55
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Bug Report
|
||||
description: Something is not working right
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a new issue, take a moment to search through the current open ones.
|
||||
|
||||
---
|
||||
|
||||
- type: input
|
||||
id: ver
|
||||
attributes:
|
||||
label: Hyprland Version
|
||||
description: "Paste here the output of `hyprctl version`."
|
||||
placeholder: Hyprland, built from branch main at commit...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Bug or Regression?
|
||||
description: Is this a bug or a regression?
|
||||
options:
|
||||
- Bug
|
||||
- Regression
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Description
|
||||
description: "What went wrong?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: How to reproduce
|
||||
description: "How can someone else reproduce the issue?"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Crash reports, logs, images, videos
|
||||
description: |
|
||||
Anything that can help. Please always ATTACH and not paste them.
|
||||
Logs can be found in /tmp/hypr
|
||||
Crash reports are stored in ~/.hyprland or $XDG_CACHE_HOME/hyprland
|
||||
|
12
.github/ISSUE_TEMPLATE/bug_report.md
vendored
12
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Found a bug? Report it here!
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please consult the issue guidelines at
|
||||
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
|
||||
BEFORE submitting.
|
18
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
18
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Feature Request
|
||||
description: I'd like to request additional functionality
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a new issue, take a moment to search through the current open ones.
|
||||
|
||||
---
|
||||
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Description
|
||||
description: "Describe your idea"
|
||||
validations:
|
||||
required: true
|
||||
|
12
.github/ISSUE_TEMPLATE/feature_request.md
vendored
12
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a feature/change/idea
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please consult the issue guidelines at
|
||||
https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md
|
||||
BEFORE submitting.
|
@@ -1,13 +1,17 @@
|
||||
name: "Nix: update lockfile"
|
||||
name: "Nix update"
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: "inputs"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install nix
|
||||
uses: cachix/install-nix-action@v20
|
||||
with:
|
||||
@@ -16,14 +20,21 @@ jobs:
|
||||
auto-optimise-store = true
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
experimental-features = nix-command flakes
|
||||
|
||||
- name: Update lockfile
|
||||
run: nix/update-inputs.sh
|
||||
|
||||
- uses: cachix/cachix-action@v12
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- name: Build packages
|
||||
run: nix flake check --print-build-logs --accept-flake-config
|
||||
|
||||
- name: Build Waybar-Hyprland
|
||||
run: nix build .#waybar-hyprland --print-build-logs
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "[gha] bump flake inputs"
|
||||
commit_message: "Nix: bump inputs"
|
35
.github/workflows/nix-update-wlroots.yaml
vendored
Normal file
35
.github/workflows/nix-update-wlroots.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: "Nix update"
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: "wlroots"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install nix
|
||||
uses: cachix/install-nix-action@v20
|
||||
with:
|
||||
install_url: https://nixos.org/nix/install
|
||||
extra_nix_config: |
|
||||
auto-optimise-store = true
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
experimental-features = nix-command flakes
|
||||
|
||||
- name: Update lockfile
|
||||
run: nix/update-wlroots.sh
|
||||
|
||||
- uses: cachix/cachix-action@v12
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- name: Build packages
|
||||
run: nix flake check --print-build-logs --accept-flake-config
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "Nix: bump wlroots"
|
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
run: |
|
||||
sed -i "1s/^/#define GIT_COMMIT_HASH $(git rev-parse HEAD)\n#define GIT_TAG \"$(git describe --tags)\"\n/" ./src/defines.hpp
|
||||
sed -i "1s/^/#define GIT_COMMIT_HASH \"$(git rev-parse HEAD)\"\n#define GIT_TAG \"$(git describe --tags)\"\n/" ./src/defines.hpp
|
||||
mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||
|
||||
- id: whatrelease
|
||||
|
@@ -96,9 +96,14 @@ add_executable(Hyprland ${SRCFILES})
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Setting debug flags")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
if (WITH_ASAN)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
add_compile_options(-pg -no-pie -fno-builtin -fsanitize=address)
|
||||
target_link_libraries(Hyprland asan)
|
||||
add_compile_options(-fsanitize=address)
|
||||
endif()
|
||||
|
||||
add_compile_options(-pg -no-pie -fno-builtin)
|
||||
add_link_options(-pg -no-pie -fno-builtin)
|
||||
endif()
|
||||
|
||||
@@ -194,5 +199,6 @@ protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.
|
||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
|
||||
protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
||||
protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
|
||||
protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||
|
5
Makefile
5
Makefile
@@ -47,6 +47,9 @@ install:
|
||||
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_anime_2K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_anime_4K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_anime_8K.png ${PREFIX}/share/hyprland
|
||||
|
||||
mkdir -p ${PREFIX}/share/man/man1
|
||||
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
|
||||
@@ -58,6 +61,7 @@ install:
|
||||
|
||||
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
|
||||
cd subprojects/wlroots/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../../..
|
||||
cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
@@ -107,6 +111,7 @@ pluginenv:
|
||||
|
||||
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
|
||||
cd subprojects/wlroots/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../../..
|
||||
cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
|
@@ -147,9 +147,9 @@ Although Hyprland is pretty stable, it may have some bugs.
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.ibb.co/SX7GbYR/winter-rice.png
|
||||
[Preview B]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
[Preview C]: https://i.imgur.com/pC6YF1Y.png
|
||||
[Preview A]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png
|
||||
[Preview B]: https://i.ibb.co/SX7GbYR/winter-rice.png
|
||||
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
|
||||
|
||||
<!----------------------------------{ Badges }--------------------------------->
|
||||
|
BIN
assets/wall_anime_2K.png
Normal file
BIN
assets/wall_anime_2K.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 502 KiB |
BIN
assets/wall_anime_4K.png
Normal file
BIN
assets/wall_anime_4K.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/wall_anime_8K.png
Normal file
BIN
assets/wall_anime_8K.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
@@ -1,6 +1,6 @@
|
||||
.\" Automatically generated by Pandoc 2.9.2.1
|
||||
.\"
|
||||
.TH "Hyprland" "1" "03 Apr 2023" "" "Hyprland User Manual"
|
||||
.TH "Hyprland" "1" "" "" "Hyprland User Manual"
|
||||
.hy
|
||||
.SH NAME
|
||||
.PP
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
First of all, please remember to:
|
||||
- Check that your issue is not a duplicate
|
||||
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
|
||||
- Read the [FAQ](https://wiki.hyprland.org/FAQ/)
|
||||
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland)
|
||||
|
||||
<br/>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
.\" Automatically generated by Pandoc 2.9.2.1
|
||||
.\"
|
||||
.TH "hyprctl" "1" "03 Apr 2023" "" "hyprctl User Manual"
|
||||
.TH "hyprctl" "1" "" "" "hyprctl User Manual"
|
||||
.hy
|
||||
.SH NAME
|
||||
.PP
|
||||
|
@@ -3,6 +3,6 @@
|
||||
# and that you have ran `make protocols` in the hl dir.
|
||||
|
||||
all:
|
||||
g++ -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g -I "/usr/include/pixman-1" -I "/usr/include/libdrm" -I "${HYPRLAND_HEADERS}" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/include" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/include" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/build/include" -std=c++23
|
||||
$(CXX) -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g `pkg-config --cflags pixman-1 libdrm hyprland` -std=c++2b
|
||||
clean:
|
||||
rm ./examplePlugin.so
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include "customDecoration.hpp"
|
||||
#include "../../src/Window.hpp"
|
||||
#include "../../src/Compositor.hpp"
|
||||
#include <hyprland/src/Window.hpp>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "globals.hpp"
|
||||
|
||||
CCustomDecoration::CCustomDecoration(CWindow* pWindow) {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#define WLR_USE_UNSTABLE
|
||||
|
||||
#include "../../src/render/decorations/IHyprWindowDecoration.hpp"
|
||||
#include <hyprland/src/render/decorations/IHyprWindowDecoration.hpp>
|
||||
|
||||
class CCustomDecoration : public IHyprWindowDecoration {
|
||||
public:
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#include "customLayout.hpp"
|
||||
#include "../../src/Compositor.hpp"
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "globals.hpp"
|
||||
|
||||
void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#define WLR_USE_UNSTABLE
|
||||
|
||||
#include "../../src/layout/IHyprLayout.hpp"
|
||||
#include <hyprland/src/layout/IHyprLayout.hpp>
|
||||
|
||||
struct SWindowData {
|
||||
CWindow* pWindow = nullptr;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <src/plugins/PluginAPI.hpp>
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
|
||||
inline HANDLE PHANDLE = nullptr;
|
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "globals.hpp"
|
||||
|
||||
#include <src/Window.hpp>
|
||||
#include <src/Compositor.hpp>
|
||||
#include <hyprland/src/Window.hpp>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "customLayout.hpp"
|
||||
#include "customDecoration.hpp"
|
||||
|
||||
@@ -77,8 +77,12 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||
static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "processMouseDownNormal");
|
||||
g_pMouseDownHook = HyprlandAPI::createFunctionHook(PHANDLE, METHODS[0].address, (void*)&hkProcessMouseDownNormal);
|
||||
|
||||
static auto* const PBORDERCOLOR = HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color");
|
||||
|
||||
// fancy notifications
|
||||
HyprlandAPI::addNotificationV2(PHANDLE, {{"text", "Example hint"}, {"time", (uint64_t)10000}, {"color", CColor(0.2, 0.2, 0.9, 1.0)}, {"icon", ICON_HINT}});
|
||||
HyprlandAPI::addNotificationV2(
|
||||
PHANDLE,
|
||||
{{"text", "Example hint, color " + std::to_string(PBORDERCOLOR->intValue)}, {"time", (uint64_t)10000}, {"color", CColor{PBORDERCOLOR->intValue}}, {"icon", ICON_HINT}});
|
||||
|
||||
// Enable our hooks
|
||||
g_pFocusHook->hook();
|
||||
|
@@ -98,7 +98,7 @@ gestures {
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
|
||||
device:epic-mouse-v1 {
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
24
flake.lock
generated
24
flake.lock
generated
@@ -7,11 +7,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1681065697,
|
||||
"narHash": "sha256-QPzwwlGKX95tl6ZEshboZbEwwAXww6lNLdVYd6T9Mrc=",
|
||||
"lastModified": 1684265364,
|
||||
"narHash": "sha256-AxNnWbthsuNx73HDQr0eBxrcE3+yfl/WsaXZqUFmkpQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "4d29e48433270a2af06b8bc711ca1fe5109746cd",
|
||||
"rev": "8c279b9fb0f2b031427dc5ef4eab53f2ed835530",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -22,11 +22,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1683014792,
|
||||
"narHash": "sha256-6Va9iVtmmsw4raBc3QKvQT2KT/NGRWlvUlJj46zN8B8=",
|
||||
"lastModified": 1688500189,
|
||||
"narHash": "sha256-djYYiY4lzJOlXOnTHytH6BUugrxHDZjuGxTSrU4gt4M=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1a411f23ba299db155a5b45d5e145b85a7aafc42",
|
||||
"rev": "78419edadf0fabbe5618643bd850b2f2198ed060",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -48,11 +48,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1682436395,
|
||||
"narHash": "sha256-GGEjkQO9m7YLYIXIXM76HWdhjg4Ye+oafOtyaFAYKI4=",
|
||||
"lastModified": 1689611045,
|
||||
"narHash": "sha256-3RTOlQabkNetQ4O4UzSf57JPco9VGVHhSU1ls5uKBeE=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "6830bfc17fd94709e2cdd4da0af989f102a26e59",
|
||||
"rev": "7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
@@ -72,11 +72,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1682439384,
|
||||
"narHash": "sha256-zHDa8LCZs05TZHQSIZ3ucwyMPglBGHcqTBzfkLjYXTM=",
|
||||
"lastModified": 1685385764,
|
||||
"narHash": "sha256-r+XMyOoRXq+hlfjayb+fyi9kq2JK48TrwuNIAXqlj7U=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "c0e233955568fbea4e859336f6d3d14d51294d7c",
|
||||
"rev": "4d9ff0c17716936e0b5ca577a39e263633901ed1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -52,6 +52,7 @@
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
wlroots-hyprland
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
]);
|
||||
};
|
||||
|
||||
|
@@ -96,5 +96,5 @@ import('pkgconfig').generate(
|
||||
url: 'https://github.com/hyprwm/Hyprland',
|
||||
description: 'Hyprland header files',
|
||||
install_dir: pkg_install_dir,
|
||||
subdirs: ['', 'hyprland/protocols'],
|
||||
subdirs: ['', 'hyprland/protocols', 'hyprland/wlroots'],
|
||||
)
|
||||
|
@@ -2,8 +2,10 @@
|
||||
lib,
|
||||
stdenv,
|
||||
pkg-config,
|
||||
makeWrapper,
|
||||
meson,
|
||||
ninja,
|
||||
binutils,
|
||||
cairo,
|
||||
git,
|
||||
hyprland-protocols,
|
||||
@@ -29,6 +31,7 @@
|
||||
legacyRenderer ? false,
|
||||
nvidiaPatches ? false,
|
||||
withSystemd ? true,
|
||||
wrapRuntimeDeps ? true,
|
||||
version ? "git",
|
||||
commit,
|
||||
}: let
|
||||
@@ -56,6 +59,7 @@ in
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
makeWrapper
|
||||
];
|
||||
|
||||
outputs = [
|
||||
@@ -99,6 +103,8 @@ in
|
||||
patches = [
|
||||
# make meson use the provided wlroots instead of the git submodule
|
||||
./meson-build.patch
|
||||
# fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR
|
||||
./portals.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
@@ -113,6 +119,14 @@ in
|
||||
}'
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots
|
||||
${lib.optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${lib.makeBinPath [ binutils pciutils ]}
|
||||
''}
|
||||
'';
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
|
||||
meta = with lib; {
|
||||
|
@@ -55,7 +55,7 @@ in {
|
||||
type = with lib.types; listOf (either package path);
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
List of hyprlad plugins to use. Can either be packages or
|
||||
List of Hyprland plugins to use. Can either be packages or
|
||||
absolute plugin paths.
|
||||
'';
|
||||
};
|
||||
@@ -65,7 +65,7 @@ in {
|
||||
default = pkgs.stdenv.isLinux;
|
||||
description = lib.mdDoc ''
|
||||
Whether to enable {file}`hyprland-session.target` on
|
||||
hyprland startup. This links to {file}`graphical-session.target`.
|
||||
Hyprland startup. This links to {file}`graphical-session.target`.
|
||||
Some important environment variables will be imported to systemd
|
||||
and dbus user environment before reaching the target, including
|
||||
- {env}`DISPLAY`
|
||||
@@ -119,7 +119,7 @@ in {
|
||||
warnings =
|
||||
if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null then
|
||||
[ ''You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins.
|
||||
Your hyprland config will be linked by home manager.
|
||||
Your Hyprland config will be linked by home manager.
|
||||
Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning.'' ]
|
||||
else [];
|
||||
|
||||
@@ -159,7 +159,7 @@ in {
|
||||
|
||||
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {
|
||||
Unit = {
|
||||
Description = "hyprland compositor session";
|
||||
Description = "Hyprland compositor session";
|
||||
Documentation = ["man:systemd.special(7)"];
|
||||
BindsTo = ["graphical-session.target"];
|
||||
Wants = ["graphical-session-pre.target"];
|
||||
|
@@ -25,6 +25,7 @@ in {
|
||||
inherit (final) udis86 hyprland-protocols;
|
||||
};
|
||||
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
hyprland-debug = final.hyprland.override {debug = true;};
|
||||
hyprland-hidpi = final.hyprland.override {hidpiXWayland = true;};
|
||||
hyprland-nvidia = final.hyprland.override {nvidiaPatches = true;};
|
||||
@@ -55,6 +56,10 @@ in {
|
||||
# use hyprctl to switch workspaces
|
||||
sed -i 's/zext_workspace_handle_v1_activate(workspace_handle_);/const std::string command = "hyprctl dispatch workspace " + name_;\n\tsystem(command.c_str());/g' src/modules/wlr/workspace_manager.cpp
|
||||
'';
|
||||
postFixup = ''
|
||||
wrapProgram $out/bin/waybar \
|
||||
--suffix PATH : ${lib.makeBinPath [ prev.hyprland ]}
|
||||
'';
|
||||
mesonFlags = old.mesonFlags ++ ["-Dexperimental=true"];
|
||||
});
|
||||
})
|
||||
|
26
nix/portals.patch
Normal file
26
nix/portals.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
|
||||
index a9d95f39..069a03ca 100644
|
||||
--- a/src/Compositor.cpp
|
||||
+++ b/src/Compositor.cpp
|
||||
@@ -2340,14 +2340,18 @@ void CCompositor::performUserChecks() {
|
||||
|
||||
static auto* const PSUPPRESSPORTAL = &g_pConfigManager->getConfigValuePtr("misc:suppress_portal_warnings")->intValue;
|
||||
|
||||
- if (!*PSUPPRESSPORTAL) {
|
||||
- if (std::ranges::any_of(BAD_PORTALS, [&](const std::string& portal) { return std::filesystem::exists("/usr/share/xdg-desktop-portal/portals/" + portal + ".portal"); })) {
|
||||
+ static auto* const PORTALDIRENV = getenv("XDG_DESKTOP_PORTAL_DIR");
|
||||
+
|
||||
+ static auto const PORTALDIR = PORTALDIRENV != NULL ? std::string(PORTALDIRENV) : "";
|
||||
+
|
||||
+ if (!*PSUPPRESSPORTAL && PORTALDIR != "") {
|
||||
+ if (std::ranges::any_of(BAD_PORTALS, [&](const std::string& portal) { return std::filesystem::exists(PORTALDIR + "/" + portal + ".portal"); })) {
|
||||
// bad portal detected
|
||||
g_pHyprNotificationOverlay->addNotification("You have one or more incompatible xdg-desktop-portal impls installed. Please remove incompatible ones to avoid issues.",
|
||||
CColor(0), 15000, ICON_ERROR);
|
||||
}
|
||||
|
||||
- if (std::filesystem::exists("/usr/share/xdg-desktop-portal/portals/hyprland.portal") && std::filesystem::exists("/usr/share/xdg-desktop-portal/portals/wlr.portal")) {
|
||||
+ if (std::filesystem::exists(PORTALDIR + "/hyprland.portal") && std::filesystem::exists(PORTALDIR + "/wlr.portal")) {
|
||||
g_pHyprNotificationOverlay->addNotification("You have xdg-desktop-portal-hyprland and -wlr installed simultaneously. Please uninstall one to avoid issues.", CColor(0),
|
||||
15000, ICON_ERROR);
|
||||
}
|
@@ -1,21 +1,25 @@
|
||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq nixpkgs#ripgrep -c bash
|
||||
#!/usr/bin/env -S nix shell nixpkgs#jq -c bash
|
||||
|
||||
set -ex
|
||||
# Update inputs when the Mesa version is outdated. We don't want
|
||||
# incompatibilities between the user's system and Hyprland.
|
||||
|
||||
# get wlroots revision from submodule
|
||||
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2)}')
|
||||
# and from lockfile
|
||||
CRT_REV=$(jq <flake.lock '.nodes.wlroots.locked.rev' -r)
|
||||
# get the current Nixpkgs revision
|
||||
REV=$(jq <flake.lock '.nodes.nixpkgs.locked.rev' -r)
|
||||
# check versions for current and remote nixpkgs' mesa
|
||||
CRT_VER=$(nix eval --raw github:nixos/nixpkgs/"$REV"#mesa.version)
|
||||
NEW_VER=$(nix eval --raw github:nixos/nixpkgs/nixos-unstable#mesa.version)
|
||||
|
||||
if [ "$CRT_VER" != "$NEW_VER" ]; then
|
||||
echo "Updating Mesa $CRT_VER -> $NEW_VER and flake inputs"
|
||||
|
||||
# keep wlroots rev, as we don't want to update it
|
||||
WLR_REV=$(nix flake metadata --json | jq -r '.locks.nodes.wlroots.locked.rev')
|
||||
|
||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
# update inputs to latest versions
|
||||
nix flake update
|
||||
|
||||
# update wlroots to submodule revision
|
||||
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
||||
|
||||
# remove "dirty" mark from lockfile
|
||||
jq <flake.lock 'del(.nodes.wlroots.original.rev)' | sponge flake.lock
|
||||
# hold back wlroots (nix/update-wlroots.nix handles updating that)
|
||||
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$WLR_REV?host=gitlab.freedesktop.org"
|
||||
else
|
||||
echo "wlroots is up to date!"
|
||||
echo "nixpkgs is up to date!"
|
||||
fi
|
||||
|
17
nix/update-wlroots.sh
Executable file
17
nix/update-wlroots.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#jq nixpkgs#ripgrep -c bash
|
||||
|
||||
# get wlroots revision from submodule
|
||||
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2)}')
|
||||
# and from lockfile
|
||||
CRT_REV=$(jq <flake.lock '.nodes.wlroots.locked.rev' -r)
|
||||
|
||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
echo "Updating wlroots..."
|
||||
# update wlroots to submodule revision
|
||||
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
||||
|
||||
# fix revision in wlroots.wrap
|
||||
sed -Ei "s/[a-z0-9]{40}/$SUB_REV/g" subprojects/wlroots.wrap
|
||||
else
|
||||
echo "wlroots is up to date!"
|
||||
fi
|
28
nix/wlroots-nvidia.patch
Normal file
28
nix/wlroots-nvidia.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
diff --git a/types/output/render.c b/types/output/render.c
|
||||
index 2e38919a..97f78608 100644
|
||||
--- a/types/output/render.c
|
||||
+++ b/types/output/render.c
|
||||
@@ -240,22 +240,7 @@ bool output_pick_format(struct wlr_output *output,
|
||||
}
|
||||
|
||||
uint32_t wlr_output_preferred_read_format(struct wlr_output *output) {
|
||||
- struct wlr_renderer *renderer = output->renderer;
|
||||
- assert(renderer != NULL);
|
||||
-
|
||||
- if (!renderer->impl->preferred_read_format || !renderer->impl->read_pixels) {
|
||||
- return DRM_FORMAT_INVALID;
|
||||
- }
|
||||
-
|
||||
- if (!wlr_output_attach_render(output, NULL)) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- uint32_t fmt = renderer->impl->preferred_read_format(renderer);
|
||||
-
|
||||
- output_clear_back_buffer(output);
|
||||
-
|
||||
- return fmt;
|
||||
+ return DRM_FORMAT_XRGB8888;
|
||||
}
|
||||
|
||||
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
@@ -44,10 +44,7 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
||||
})
|
||||
])
|
||||
++ (lib.optionals nvidiaPatches [
|
||||
(fetchpatch {
|
||||
url = "https://aur.archlinux.org/cgit/aur.git/plain/0001-nvidia-format-workaround.patch?h=hyprland-nvidia-screenshare-git";
|
||||
sha256 = "A9f1p5EW++mGCaNq8w7ZJfeWmvTfUm4iO+1KDcnqYX8=";
|
||||
})
|
||||
./wlroots-nvidia.patch
|
||||
]);
|
||||
postPatch =
|
||||
(old.postPatch or "")
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.25.0"
|
||||
"version": "0.27.2"
|
||||
}
|
@@ -22,6 +22,7 @@ protocols = [
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "Compositor.hpp"
|
||||
#include "helpers/Splashes.hpp"
|
||||
#include <random>
|
||||
#include <unordered_set>
|
||||
#include "debug/HyprCtl.hpp"
|
||||
#include "debug/CrashReporter.hpp"
|
||||
#ifdef USES_SYSTEMD
|
||||
@@ -153,10 +154,11 @@ void CCompositor::initServer() {
|
||||
|
||||
wlr_export_dmabuf_manager_v1_create(m_sWLDisplay);
|
||||
wlr_data_control_manager_v1_create(m_sWLDisplay);
|
||||
wlr_gamma_control_manager_v1_create(m_sWLDisplay);
|
||||
wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
|
||||
wlr_viewporter_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRGammaCtrlMgr = wlr_gamma_control_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLROutputLayout = wlr_output_layout_create();
|
||||
|
||||
m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create(m_sWLDisplay);
|
||||
@@ -186,6 +188,7 @@ void CCompositor::initServer() {
|
||||
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
||||
|
||||
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
|
||||
m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
|
||||
|
||||
@@ -193,7 +196,6 @@ void CCompositor::initServer() {
|
||||
m_sWLRXDGDecoMgr = wlr_xdg_decoration_manager_v1_create(m_sWLDisplay);
|
||||
wlr_server_decoration_manager_set_default_mode(m_sWLRServerDecoMgr, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
||||
|
||||
wlr_xdg_output_manager_v1_create(m_sWLDisplay, m_sWLROutputLayout);
|
||||
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay);
|
||||
@@ -294,6 +296,7 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
|
||||
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
|
||||
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
|
||||
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
||||
@@ -308,6 +311,11 @@ void CCompositor::cleanup() {
|
||||
|
||||
m_bIsShuttingDown = true;
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (sd_booted() > 0)
|
||||
sd_notify(0, "STOPPING=1");
|
||||
#endif
|
||||
|
||||
// unload all remaining plugins while the compositor is
|
||||
// still in a normal working state.
|
||||
g_pPluginSystem->unloadAllPlugins();
|
||||
@@ -456,7 +464,7 @@ void CCompositor::startCompositor() {
|
||||
throw std::runtime_error("The backend could not start!");
|
||||
}
|
||||
|
||||
wlr_xcursor_manager_set_cursor_image(m_sWLRXCursorMgr, "left_ptr", m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(m_sWLRCursor, m_sWLRXCursorMgr, "left_ptr");
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (sd_booted() > 0)
|
||||
@@ -487,7 +495,14 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->output->description && std::string(m->output->description).find(desc) == 0)
|
||||
return m.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -864,10 +879,6 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
|
||||
|
||||
// do pointer focus too
|
||||
const auto POINTERLOCAL = g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.goalv();
|
||||
wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y);
|
||||
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
// Handle urgency hint on the workspace
|
||||
@@ -990,7 +1001,7 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords,
|
||||
SLayerSurface** ppLayerSurfaceFound) {
|
||||
for (auto& ls : *layerSurfaces | std::views::reverse) {
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.fl() == 0.f)
|
||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
||||
@@ -1068,7 +1079,7 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
|
||||
if (m->activeWorkspace == w)
|
||||
return true;
|
||||
|
||||
if (m->specialWorkspaceID && isWorkspaceSpecial(w))
|
||||
if (m->specialWorkspaceID == w)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1490,6 +1501,15 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWorkspace* CCompositor::getWorkspaceByWorkspaceHandle(const wlr_ext_workspace_handle_v1* handle) {
|
||||
for (auto& ws : m_vWorkspaces) {
|
||||
if (ws->m_pWlrHandle == handle)
|
||||
return ws.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
|
||||
@@ -1605,12 +1625,15 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
||||
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data.get();
|
||||
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border")->data.get();
|
||||
static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked_active")->data.get();
|
||||
static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked")->data.get();
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
||||
static auto* const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
|
||||
static auto* const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue;
|
||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto* const PDIMENABLED = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue;
|
||||
|
||||
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
||||
if (grad == pWindow->m_cRealBorderColor)
|
||||
@@ -1627,13 +1650,14 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
if (RENDERDATA.isBorderGradient)
|
||||
setBorderColor(*RENDERDATA.borderGradient);
|
||||
else {
|
||||
const bool GROUPLOCKED = pWindow->m_sGroupData.pNextWindow ? pWindow->getGroupHead()->m_sGroupData.locked : false;
|
||||
if (pWindow == m_pLastWindow) {
|
||||
const auto* const ACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? ACTIVECOL : GROUPACTIVECOL;
|
||||
const auto* const ACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? ACTIVECOL : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ?
|
||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) :
|
||||
*ACTIVECOLOR);
|
||||
} else {
|
||||
const auto* const INACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? INACTIVECOL : GROUPINACTIVECOL;
|
||||
const auto* const INACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? INACTIVECOL : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ?
|
||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) :
|
||||
*INACTIVECOLOR);
|
||||
@@ -1660,7 +1684,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// dim
|
||||
if (pWindow == m_pLastWindow) {
|
||||
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) {
|
||||
pWindow->m_fDimPercent = 0;
|
||||
} else {
|
||||
pWindow->m_fDimPercent = *PDIMSTRENGTH;
|
||||
@@ -1681,14 +1705,23 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
d->updateWindow(pWindow);
|
||||
}
|
||||
|
||||
int CCompositor::getNextAvailableMonitorID() {
|
||||
int64_t topID = -1;
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if ((int64_t)m->ID > topID)
|
||||
topID = m->ID;
|
||||
int CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
||||
if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
|
||||
return m_mMonitorIDMap[name];
|
||||
|
||||
// otherwise, find minimum available ID that is not in the map
|
||||
std::unordered_set<uint64_t> usedIDs;
|
||||
for (auto const& monitor : m_vRealMonitors) {
|
||||
usedIDs.insert(monitor->ID);
|
||||
}
|
||||
|
||||
return topID + 1;
|
||||
uint64_t nextID = 0;
|
||||
while (usedIDs.count(nextID) > 0) {
|
||||
nextID++;
|
||||
}
|
||||
m_mMonitorIDMap[name] = nextID;
|
||||
return nextID;
|
||||
}
|
||||
|
||||
void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) {
|
||||
@@ -1755,7 +1788,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACEB);
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACEA);
|
||||
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
||||
@@ -1863,7 +1896,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
|
||||
const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
|
||||
const bool SWITCHINGISACTIVE = POLDMON->activeWorkspace == pWorkspace->m_iID;
|
||||
const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace->m_iID : false;
|
||||
|
||||
// fix old mon
|
||||
int nextWorkspaceOnMonitorID = -1;
|
||||
@@ -1910,6 +1943,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
|
||||
// additionally, move floating and fs windows manually
|
||||
if (w->m_bIsMapped && !w->isHidden()) {
|
||||
if (POLDMON) {
|
||||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition;
|
||||
|
||||
@@ -1917,6 +1951,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
w->m_vRealPosition = pMonitor->vecPosition;
|
||||
w->m_vRealSize = pMonitor->vecSize;
|
||||
}
|
||||
} else {
|
||||
w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goalv().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goalv().y % (int)pMonitor->vecSize.y};
|
||||
}
|
||||
}
|
||||
|
||||
w->updateToplevel();
|
||||
@@ -1935,24 +1972,26 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
pWorkspace->startAnim(true, true, true);
|
||||
|
||||
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
// finalize
|
||||
if (POLDMON) {
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
updateFullscreenFadeOnWorkspace(getWorkspaceByID(POLDMON->activeWorkspace));
|
||||
}
|
||||
|
||||
updateFullscreenFadeOnWorkspace(pWorkspace);
|
||||
updateFullscreenFadeOnWorkspace(getWorkspaceByID(POLDMON->activeWorkspace));
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName});
|
||||
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<void*>{pWorkspace, pMonitor}));
|
||||
}
|
||||
|
||||
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) {
|
||||
int64_t lowestID = INT64_MAX;
|
||||
int64_t highestID = INT64_MIN;
|
||||
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_bIsSpecialWorkspace)
|
||||
@@ -1975,7 +2014,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(CWorkspace* pWorkspace) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||
|
||||
if (w->m_bFadingOut || w->m_bPinned)
|
||||
if (w->m_bFadingOut || w->m_bPinned || w->m_bIsFullscreen)
|
||||
continue;
|
||||
|
||||
if (!FULLSCREEN)
|
||||
@@ -2016,7 +2055,7 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
for (auto& w : m_vWindows) {
|
||||
@@ -2217,11 +2256,6 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2313,7 +2347,7 @@ bool CCompositor::isWorkspaceSpecial(const int& id) {
|
||||
}
|
||||
|
||||
int CCompositor::getNewSpecialID() {
|
||||
int highest = -100;
|
||||
int highest = SPECIAL_WORKSPACE_START;
|
||||
for (auto& ws : m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) {
|
||||
highest = ws->m_iID;
|
||||
@@ -2346,6 +2380,9 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks
|
||||
if (!pWindow || !pWorkspace)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned && pWorkspace->m_bIsSpecialWorkspace)
|
||||
return;
|
||||
|
||||
const bool FULLSCREEN = pWindow->m_bIsFullscreen;
|
||||
const auto FULLSCREENMODE = getWorkspaceByID(pWindow->m_iWorkspaceID)->m_efFullscreenMode;
|
||||
|
||||
@@ -2372,6 +2409,39 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks
|
||||
pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition;
|
||||
}
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow) {
|
||||
CWindow* next = pWindow->m_sGroupData.pNextWindow;
|
||||
while (next != pWindow) {
|
||||
next->moveToWorkspace(pWorkspace->m_iID);
|
||||
next->updateToplevel();
|
||||
next = next->m_sGroupData.pNextWindow;
|
||||
}
|
||||
}
|
||||
|
||||
if (FULLSCREEN)
|
||||
setWindowFullscreen(pWindow, true, FULLSCREENMODE);
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getForceFocus() {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!w->m_bStayFocused)
|
||||
continue;
|
||||
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::notifyIdleActivity() {
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat);
|
||||
}
|
||||
|
||||
void CCompositor::setIdleActivityInhibit(bool enabled) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled);
|
||||
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ class CCompositor {
|
||||
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
||||
wlr_output_layout* m_sWLROutputLayout;
|
||||
wlr_idle* m_sWLRIdle;
|
||||
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
|
||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||
wlr_xdg_shell* m_sWLRXDGShell;
|
||||
wlr_cursor* m_sWLRCursor;
|
||||
@@ -84,6 +85,7 @@ class CCompositor {
|
||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
||||
wlr_backend* m_sWLRHeadlessBackend;
|
||||
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
|
||||
wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
std::string m_szWLDisplaySocket = "";
|
||||
@@ -99,6 +101,8 @@ class CCompositor {
|
||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||
|
||||
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||
|
||||
void initServer();
|
||||
void startCompositor();
|
||||
void cleanup();
|
||||
@@ -121,6 +125,7 @@ class CCompositor {
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
CMonitor* getMonitorFromVector(const Vector2D&);
|
||||
void removeWindowFromVectorSafe(CWindow*);
|
||||
@@ -144,6 +149,7 @@ class CCompositor {
|
||||
CWorkspace* getWorkspaceByID(const int&);
|
||||
CWorkspace* getWorkspaceByName(const std::string&);
|
||||
CWorkspace* getWorkspaceByString(const std::string&);
|
||||
CWorkspace* getWorkspaceByWorkspaceHandle(const wlr_ext_workspace_handle_v1*);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
int getWindowsOnWorkspace(const int&);
|
||||
@@ -165,11 +171,11 @@ class CCompositor {
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||
int getNextAvailableMonitorID();
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
||||
void updateFullscreenFadeOnWorkspace(CWorkspace*);
|
||||
CWindow* getX11Parent(CWindow*);
|
||||
@@ -191,6 +197,9 @@ class CCompositor {
|
||||
int getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace);
|
||||
CWindow* getForceFocus();
|
||||
void notifyIdleActivity();
|
||||
void setIdleActivityInhibit(bool inhibit);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
|
@@ -20,4 +20,6 @@ enum eRenderStage
|
||||
RENDER_LAST_MOMENT, /* Last moment to render with the gl context */
|
||||
RENDER_POST, /* After rendering is finished, gl context not available anymore */
|
||||
RENDER_POST_MIRROR, /* After rendering a mirror */
|
||||
RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */
|
||||
RENDER_POST_WINDOW, /* After rendering a window (any pass) */
|
||||
};
|
125
src/Window.cpp
125
src/Window.cpp
@@ -49,6 +49,37 @@ wlr_box CWindow::getFullWindowBoundingBox() {
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
}
|
||||
|
||||
if (m_pWLSurface.exists() && !m_bIsX11) {
|
||||
wlr_box surfaceExtents = {0, 0, 0, 0};
|
||||
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
||||
wlr_xdg_surface_for_each_popup_surface(
|
||||
m_uSurface.xdg,
|
||||
[](wlr_surface* surf, int sx, int sy, void* data) {
|
||||
wlr_box* pSurfaceExtents = (wlr_box*)data;
|
||||
if (sx < pSurfaceExtents->x)
|
||||
pSurfaceExtents->x = sx;
|
||||
if (sy < pSurfaceExtents->y)
|
||||
pSurfaceExtents->y = sy;
|
||||
if (sx + surf->current.width > pSurfaceExtents->width)
|
||||
pSurfaceExtents->width = sx + surf->current.width - pSurfaceExtents->x;
|
||||
if (sy + surf->current.height > pSurfaceExtents->height)
|
||||
pSurfaceExtents->height = sy + surf->current.height - pSurfaceExtents->y;
|
||||
},
|
||||
&surfaceExtents);
|
||||
|
||||
if (-surfaceExtents.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = -surfaceExtents.x;
|
||||
|
||||
if (-surfaceExtents.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = -surfaceExtents.y;
|
||||
|
||||
if (surfaceExtents.x + surfaceExtents.width > m_pWLSurface.wlr()->current.width + maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = surfaceExtents.x + surfaceExtents.width - m_pWLSurface.wlr()->current.width;
|
||||
|
||||
if (surfaceExtents.y + surfaceExtents.height > m_pWLSurface.wlr()->current.height + maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = surfaceExtents.y + surfaceExtents.height - m_pWLSurface.wlr()->current.height;
|
||||
}
|
||||
|
||||
// Add extents to the real base BB and return
|
||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
@@ -145,16 +176,22 @@ void CWindow::updateWindowDecos() {
|
||||
for (auto& wd : m_dWindowDecorations)
|
||||
wd->updateWindow(this);
|
||||
|
||||
bool recalc = false;
|
||||
|
||||
for (auto& wd : m_vDecosToRemove) {
|
||||
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == wd) {
|
||||
it = m_dWindowDecorations.erase(it);
|
||||
recalc = true;
|
||||
if (it == m_dWindowDecorations.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (recalc)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(this);
|
||||
|
||||
m_vDecosToRemove.clear();
|
||||
}
|
||||
|
||||
@@ -197,7 +234,7 @@ void CWindow::createToplevelHandle() {
|
||||
|
||||
// handle events
|
||||
hyprListener_toplevelActivate.initCallback(
|
||||
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pCompositor->focusWindow(this); }, this, "Toplevel");
|
||||
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->requestFocusForWindow(this); }, this, "Toplevel");
|
||||
|
||||
hyprListener_toplevelFullscreen.initCallback(
|
||||
&m_phForeignToplevel->events.request_fullscreen,
|
||||
@@ -268,6 +305,14 @@ void CWindow::updateSurfaceOutputs() {
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||
|
||||
wlr_surface_for_each_surface(
|
||||
m_pWLSurface.wlr(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
void CWindow::moveToWorkspace(int workspaceID) {
|
||||
@@ -276,7 +321,6 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
|
||||
m_iWorkspaceID = workspaceID;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE) {
|
||||
@@ -288,20 +332,6 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
m_pSwallowed->moveToWorkspace(workspaceID);
|
||||
m_pSwallowed->m_iMonitorID = m_iMonitorID;
|
||||
}
|
||||
|
||||
if (PMONITOR)
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
|
||||
if (!m_bIsMapped)
|
||||
return;
|
||||
|
||||
wlr_surface_for_each_surface(
|
||||
m_pWLSurface.wlr(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
CWindow* CWindow::X11TransientFor() {
|
||||
@@ -388,7 +418,8 @@ void CWindow::onMap() {
|
||||
|
||||
g_pCompositor->m_vWindowFocusHistory.push_back(this);
|
||||
|
||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->events.unmap : &m_uSurface.xdg->events.unmap, &Events::listener_unmapWindow, this, "CWindow");
|
||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
||||
"CWindow");
|
||||
}
|
||||
|
||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||
@@ -426,6 +457,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
m_sAdditionalConfigData.forceNoBorder = true;
|
||||
} else if (r.szRule == "noshadow") {
|
||||
m_sAdditionalConfigData.forceNoShadow = true;
|
||||
} else if (r.szRule == "nodim") {
|
||||
m_sAdditionalConfigData.forceNoDim = true;
|
||||
} else if (r.szRule == "forcergbx") {
|
||||
m_sAdditionalConfigData.forceRGBX = true;
|
||||
} else if (r.szRule == "opaque") {
|
||||
@@ -435,6 +468,10 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
try {
|
||||
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
|
||||
} else if (r.szRule.find("bordersize") == 0) {
|
||||
try {
|
||||
m_sAdditionalConfigData.borderSize = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Bordersize rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
|
||||
} else if (r.szRule.find("opacity") == 0) {
|
||||
try {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
@@ -486,6 +523,7 @@ void CWindow::updateDynamicRules() {
|
||||
m_sAdditionalConfigData.forceNoBlur = false;
|
||||
m_sAdditionalConfigData.forceNoBorder = false;
|
||||
m_sAdditionalConfigData.forceNoShadow = false;
|
||||
m_sAdditionalConfigData.forceNoDim = false;
|
||||
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||
m_sAdditionalConfigData.forceOpaque = false;
|
||||
m_sAdditionalConfigData.forceNoAnims = false;
|
||||
@@ -493,11 +531,14 @@ void CWindow::updateDynamicRules() {
|
||||
m_sAdditionalConfigData.rounding = -1;
|
||||
m_sAdditionalConfigData.dimAround = false;
|
||||
m_sAdditionalConfigData.forceRGBX = false;
|
||||
m_sAdditionalConfigData.borderSize = -1;
|
||||
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
|
||||
for (auto& r : WINDOWRULES) {
|
||||
applyDynamicRule(r);
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
||||
}
|
||||
|
||||
// check if the point is "hidden" under a rounded corner of the window
|
||||
@@ -618,6 +659,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
}
|
||||
|
||||
void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||
@@ -625,15 +668,17 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||
const auto PTAIL = getGroupTail();
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow) {
|
||||
const auto PHEAD = pWindow->getGroupHead();
|
||||
std::vector<CWindow*> members;
|
||||
CWindow* curr = pWindow;
|
||||
CWindow* curr = PHEAD;
|
||||
do {
|
||||
const auto PLAST = curr;
|
||||
members.push_back(curr);
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
PLAST->m_sGroupData.pNextWindow = nullptr;
|
||||
PLAST->m_sGroupData.head = false;
|
||||
} while (curr != pWindow);
|
||||
PLAST->m_sGroupData.locked = false;
|
||||
} while (curr != PHEAD);
|
||||
|
||||
for (auto& w : members) {
|
||||
insertWindowToGroup(w);
|
||||
@@ -644,8 +689,45 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||
|
||||
PTAIL->m_sGroupData.pNextWindow = pWindow;
|
||||
pWindow->m_sGroupData.pNextWindow = PHEAD;
|
||||
}
|
||||
|
||||
setGroupCurrent(pWindow);
|
||||
CWindow* CWindow::getGroupPrevious() {
|
||||
CWindow* curr = m_sGroupData.pNextWindow;
|
||||
|
||||
while (curr != this && curr->m_sGroupData.pNextWindow != this)
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
void CWindow::switchWithWindowInGroup(CWindow* pWindow) {
|
||||
if (!m_sGroupData.pNextWindow || !pWindow->m_sGroupData.pNextWindow)
|
||||
return;
|
||||
|
||||
// TODO: probably can be done more easily but I let C++ do the algorithm stuff for us
|
||||
|
||||
std::vector<CWindow*> group;
|
||||
group.push_back(this);
|
||||
CWindow* curr = this->m_sGroupData.pNextWindow;
|
||||
while (curr != this) {
|
||||
group.push_back(curr);
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
}
|
||||
|
||||
auto it1 = std::find(group.begin(), group.end(), this);
|
||||
auto it2 = std::find(group.begin(), group.end(), pWindow);
|
||||
|
||||
std::iter_swap(it1, it2);
|
||||
|
||||
for (auto it = group.begin(); it != group.end(); ++it) {
|
||||
if (std::next(it) == group.end()) {
|
||||
(*it)->m_sGroupData.pNextWindow = *group.begin();
|
||||
} else {
|
||||
(*it)->m_sGroupData.pNextWindow = *std::next(it);
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(m_sGroupData.head, pWindow->m_sGroupData.head);
|
||||
}
|
||||
|
||||
void CWindow::updateGroupOutputs() {
|
||||
@@ -677,8 +759,7 @@ bool CWindow::opaque() {
|
||||
return true;
|
||||
|
||||
const auto EXTENTS = pixman_region32_extents(&m_uSurface.xdg->surface->opaque_region);
|
||||
if (EXTENTS->x2 - EXTENTS->x1 >= m_uSurface.xdg->surface->current.buffer_width
|
||||
&& EXTENTS->y2 - EXTENTS->y1 >= m_uSurface.xdg->surface->current.buffer_height)
|
||||
if (EXTENTS->x2 - EXTENTS->x1 >= m_uSurface.xdg->surface->current.buffer_width && EXTENTS->y2 - EXTENTS->y1 >= m_uSurface.xdg->surface->current.buffer_height)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@@ -10,7 +10,8 @@
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/WLSurface.hpp"
|
||||
|
||||
enum eIdleInhibitMode {
|
||||
enum eIdleInhibitMode
|
||||
{
|
||||
IDLEINHIBIT_NONE = 0,
|
||||
IDLEINHIBIT_ALWAYS,
|
||||
IDLEINHIBIT_FULLSCREEN,
|
||||
@@ -100,7 +101,7 @@ struct SWindowSpecialRenderData {
|
||||
CWindowOverridableVar<int64_t> inactiveBorderColor = -1; // -1 means unset
|
||||
|
||||
// set by the layout
|
||||
int borderSize = -1;
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset
|
||||
bool rounding = true;
|
||||
bool border = true;
|
||||
bool decorate = true;
|
||||
@@ -116,10 +117,12 @@ struct SWindowAdditionalConfigData {
|
||||
CWindowOverridableVar<bool> forceNoAnims = false;
|
||||
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||
CWindowOverridableVar<bool> forceNoDim = false;
|
||||
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||
CWindowOverridableVar<bool> noMaxSize = false;
|
||||
CWindowOverridableVar<bool> dimAround = false;
|
||||
CWindowOverridableVar<bool> forceRGBX = false;
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
@@ -158,6 +161,8 @@ class CWindow {
|
||||
DYNLISTENER(toplevelActivate);
|
||||
DYNLISTENER(toplevelFullscreen);
|
||||
DYNLISTENER(setOverrideRedirect);
|
||||
DYNLISTENER(associateX11);
|
||||
DYNLISTENER(dissociateX11);
|
||||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
CWLSurface m_pWLSurface;
|
||||
@@ -188,7 +193,7 @@ class CWindow {
|
||||
bool m_bIsPseudotiled = false;
|
||||
Vector2D m_vPseudoSize = Vector2D(0, 0);
|
||||
|
||||
uint64_t m_iTags = 0;
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
@@ -214,6 +219,7 @@ class CWindow {
|
||||
bool m_bIsModal = false;
|
||||
bool m_bX11DoesntWantBorders = false;
|
||||
bool m_bX11ShouldntFocus = false;
|
||||
float m_fX11SurfaceScaledBy = 1.f;
|
||||
//
|
||||
|
||||
// For nofocus
|
||||
@@ -274,6 +280,9 @@ class CWindow {
|
||||
// swallowing
|
||||
CWindow* m_pSwallowed = nullptr;
|
||||
|
||||
// focus stuff
|
||||
bool m_bStayFocused = false;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
@@ -285,6 +294,7 @@ class CWindow {
|
||||
struct SGroupData {
|
||||
CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group.
|
||||
bool head = false;
|
||||
bool locked = false;
|
||||
} m_sGroupData;
|
||||
|
||||
// For the list lookup
|
||||
@@ -324,9 +334,11 @@ class CWindow {
|
||||
CWindow* getGroupHead();
|
||||
CWindow* getGroupTail();
|
||||
CWindow* getGroupCurrent();
|
||||
CWindow* getGroupPrevious();
|
||||
void setGroupCurrent(CWindow* pWindow);
|
||||
void insertWindowToGroup(CWindow* pWindow);
|
||||
void updateGroupOutputs();
|
||||
void switchWithWindowInGroup(CWindow* pWindow);
|
||||
|
||||
private:
|
||||
// For hidden windows and stuff
|
||||
|
@@ -2,8 +2,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes
|
||||
{
|
||||
enum eConfigValueDataTypes {
|
||||
CVD_TYPE_INVALID = -1,
|
||||
CVD_TYPE_GRADIENT = 0
|
||||
};
|
||||
@@ -38,7 +37,8 @@ class CGradientValueData : public ICustomConfigValueData {
|
||||
/* Float corresponding to the angle (rad) */
|
||||
float m_fAngle = 0;
|
||||
|
||||
bool operator==(const CGradientValueData& other) {
|
||||
//
|
||||
bool operator==(const CGradientValueData& other) const {
|
||||
if (other.m_vColors.size() != m_vColors.size() || m_fAngle != other.m_fAngle)
|
||||
return false;
|
||||
|
||||
|
@@ -18,19 +18,13 @@ CConfigManager::CConfigManager() {
|
||||
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
|
||||
configValues["general:col.group_border"].data = std::make_shared<CGradientValueData>(0x66777700);
|
||||
configValues["general:col.group_border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
||||
configValues["general:col.group_border_locked"].data = std::make_shared<CGradientValueData>(0x66775500);
|
||||
configValues["general:col.group_border_locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
|
||||
|
||||
setDefaultVars();
|
||||
setDefaultAnimationVars();
|
||||
|
||||
std::string CONFIGPATH;
|
||||
if (g_pCompositor->explicitConfigPath == "") {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
} else {
|
||||
CONFIGPATH = g_pCompositor->explicitConfigPath;
|
||||
}
|
||||
|
||||
configPaths.emplace_back(CONFIGPATH);
|
||||
configPaths.emplace_back(getMainConfigPath());
|
||||
|
||||
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
|
||||
Debug::disableTime = &configValues["debug:disable_time"].intValue;
|
||||
@@ -38,6 +32,23 @@ CConfigManager::CConfigManager() {
|
||||
populateEnvironment();
|
||||
}
|
||||
|
||||
std::string CConfigManager::getConfigDir() {
|
||||
static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
std::string configPath;
|
||||
if (!xdgConfigHome)
|
||||
configPath = getenv("HOME") + std::string("/.config");
|
||||
else
|
||||
configPath = xdgConfigHome;
|
||||
return configPath;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getMainConfigPath() {
|
||||
if (!g_pCompositor->explicitConfigPath.empty())
|
||||
return g_pCompositor->explicitConfigPath;
|
||||
|
||||
return getConfigDir() + "/hypr/" + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
|
||||
}
|
||||
|
||||
void CConfigManager::populateEnvironment() {
|
||||
environmentVariables.clear();
|
||||
for (char** env = environ; *env; ++env) {
|
||||
@@ -62,6 +73,8 @@ void CConfigManager::setDefaultVars() {
|
||||
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
|
||||
((CGradientValueData*)configValues["general:col.group_border"].data.get())->reset(0x66777700);
|
||||
((CGradientValueData*)configValues["general:col.group_border_active"].data.get())->reset(0x66ffff00);
|
||||
((CGradientValueData*)configValues["general:col.group_border_locked"].data.get())->reset(0x66775500);
|
||||
((CGradientValueData*)configValues["general:col.group_border_locked_active"].data.get())->reset(0x66ff5500);
|
||||
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||
configValues["general:no_cursor_warps"].intValue = 0;
|
||||
configValues["general:no_focus_fallback"].intValue = 0;
|
||||
@@ -93,6 +106,11 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["misc:render_ahead_safezone"].intValue = 1;
|
||||
configValues["misc:cursor_zoom_factor"].floatValue = 1.f;
|
||||
configValues["misc:cursor_zoom_rigid"].intValue = 0;
|
||||
configValues["misc:allow_session_lock_restore"].intValue = 0;
|
||||
configValues["misc:render_titles_in_groupbar"].intValue = 1;
|
||||
configValues["misc:groupbar_titles_font_size"].intValue = 8;
|
||||
configValues["misc:groupbar_gradients"].intValue = 1;
|
||||
configValues["misc:groupbar_text_color"].intValue = 0xffffffff;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -132,12 +150,14 @@ void CConfigManager::setDefaultVars() {
|
||||
|
||||
configValues["dwindle:pseudotile"].intValue = 0;
|
||||
configValues["dwindle:force_split"].intValue = 0;
|
||||
configValues["dwindle:permanent_direction_override"].intValue = 0;
|
||||
configValues["dwindle:preserve_split"].intValue = 0;
|
||||
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
|
||||
configValues["dwindle:no_gaps_when_only"].intValue = 0;
|
||||
configValues["dwindle:use_active_for_splits"].intValue = 1;
|
||||
configValues["dwindle:default_split_ratio"].floatValue = 1.f;
|
||||
configValues["dwindle:smart_split"].intValue = 0;
|
||||
|
||||
configValues["master:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["master:mfact"].floatValue = 0.55f;
|
||||
@@ -199,6 +219,10 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["gestures:workspace_swipe_create_new"].intValue = 1;
|
||||
configValues["gestures:workspace_swipe_forever"].intValue = 0;
|
||||
configValues["gestures:workspace_swipe_numbered"].intValue = 0;
|
||||
configValues["gestures:workspace_swipe_use_r"].intValue = 0;
|
||||
|
||||
configValues["xwayland:use_nearest_neighbor"].intValue = 1;
|
||||
configValues["xwayland:force_zero_scaling"].intValue = 0;
|
||||
|
||||
configValues["autogenerated"].intValue = 0;
|
||||
}
|
||||
@@ -286,9 +310,7 @@ void CConfigManager::init() {
|
||||
|
||||
loadConfigLoadVars();
|
||||
|
||||
const char* const ENVHOME = getenv("HOME");
|
||||
|
||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
const std::string CONFIGPATH = getMainConfigPath();
|
||||
|
||||
struct stat fileStat;
|
||||
int err = stat(CONFIGPATH.c_str(), &fileStat);
|
||||
@@ -350,8 +372,10 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
CONFIGENTRY = &it->second;
|
||||
}
|
||||
|
||||
if (!CONFIGENTRY)
|
||||
if (!CONFIGENTRY) {
|
||||
m_vFailedPluginConfigValues.emplace_back(std::make_pair<>(COMMAND, VALUE));
|
||||
return; // silent ignore
|
||||
}
|
||||
} else {
|
||||
CONFIGENTRY = &configValues.at(COMMAND);
|
||||
}
|
||||
@@ -469,6 +493,58 @@ void CConfigManager::handleRawExec(const std::string& command, const std::string
|
||||
g_pKeybindManager->spawn(args);
|
||||
}
|
||||
|
||||
static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
|
||||
auto args = CVarList(modeline, 0, 's');
|
||||
|
||||
auto keyword = args[0];
|
||||
std::transform(keyword.begin(), keyword.end(), keyword.begin(), ::tolower);
|
||||
|
||||
if (keyword != "modeline")
|
||||
return false;
|
||||
|
||||
if (args.size() < 10) {
|
||||
Debug::log(ERR, "modeline parse error: expected at least 9 arguments, got %i", args.size() - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
int argno = 1;
|
||||
|
||||
mode.type = DRM_MODE_TYPE_USERDEF;
|
||||
mode.clock = std::stof(args[argno++]) * 1000;
|
||||
mode.hdisplay = std::stoi(args[argno++]);
|
||||
mode.hsync_start = std::stoi(args[argno++]);
|
||||
mode.hsync_end = std::stoi(args[argno++]);
|
||||
mode.htotal = std::stoi(args[argno++]);
|
||||
mode.vdisplay = std::stoi(args[argno++]);
|
||||
mode.vsync_start = std::stoi(args[argno++]);
|
||||
mode.vsync_end = std::stoi(args[argno++]);
|
||||
mode.vtotal = std::stoi(args[argno++]);
|
||||
mode.vrefresh = mode.clock * 1000.0 * 1000.0 / mode.htotal / mode.vtotal;
|
||||
|
||||
static std::unordered_map<std::string, uint32_t> flagsmap = {
|
||||
{"+hsync", DRM_MODE_FLAG_PHSYNC},
|
||||
{"-hsync", DRM_MODE_FLAG_NHSYNC},
|
||||
{"+vsync", DRM_MODE_FLAG_PVSYNC},
|
||||
{"-vsync", DRM_MODE_FLAG_NVSYNC},
|
||||
};
|
||||
|
||||
for (; argno < static_cast<int>(args.size()); argno++) {
|
||||
auto key = args[argno];
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
|
||||
auto it = flagsmap.find(key);
|
||||
|
||||
if (it != flagsmap.end())
|
||||
mode.flags |= it->second;
|
||||
else
|
||||
Debug::log(ERR, "invalid flag %s in modeline", it->first.c_str());
|
||||
}
|
||||
|
||||
snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CConfigManager::handleMonitor(const std::string& command, const std::string& args) {
|
||||
|
||||
// get the monitor config
|
||||
@@ -530,6 +606,9 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
newrule.resolution = Vector2D(-1, -1);
|
||||
} else if (ARGS[1].find("highres") == 0) {
|
||||
newrule.resolution = Vector2D(-1, -2);
|
||||
} else if (parseModeLine(ARGS[1], newrule.drmMode)) {
|
||||
newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay);
|
||||
newrule.refreshRate = newrule.drmMode.vrefresh / 1000;
|
||||
} else {
|
||||
newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x')));
|
||||
newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@')));
|
||||
@@ -583,7 +662,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
wsRule.workspaceName = name;
|
||||
wsRule.workspaceId = wsId;
|
||||
|
||||
m_mWorkspaceRules[wsId] = wsRule;
|
||||
m_dWorkspaceRules.emplace_back(wsRule);
|
||||
argno++;
|
||||
} else {
|
||||
Debug::log(ERR, "Config error: invalid monitor syntax");
|
||||
@@ -706,6 +785,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
const auto BINDARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : BINDARGS) {
|
||||
@@ -717,6 +797,8 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
repeat = true;
|
||||
} else if (arg == 'm') {
|
||||
mouse = true;
|
||||
} else if (arg == 'n') {
|
||||
nonConsuming = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
@@ -774,11 +856,11 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming});
|
||||
else if (KEY.find("code:") == 0 && isNumber(KEY.substr(5)))
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,14 +877,14 @@ void CConfigManager::handleUnbind(const std::string& command, const std::string&
|
||||
bool windowRuleValid(const std::string& RULE) {
|
||||
return !(RULE != "float" && RULE != "tile" && RULE.find("opacity") != 0 && RULE.find("move") != 0 && RULE.find("size") != 0 && RULE.find("minsize") != 0 &&
|
||||
RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" &&
|
||||
RULE != "noshadow" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" &&
|
||||
RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" &&
|
||||
RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0 && RULE != "forcergbx" &&
|
||||
RULE != "noinitialfocus");
|
||||
RULE != "noshadow" && RULE != "nodim" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" &&
|
||||
RULE != "nofullscreenrequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" &&
|
||||
RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 &&
|
||||
RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && RULE.find("bordersize") != 0);
|
||||
}
|
||||
|
||||
bool layerRuleValid(const std::string& RULE) {
|
||||
return !(RULE != "noanim" && RULE != "blur" && RULE != "ignorezero");
|
||||
return !(RULE != "noanim" && RULE != "blur" && RULE.find("ignorealpha") != 0 && RULE.find("ignorezero") != 0);
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
||||
@@ -1033,12 +1115,12 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
}
|
||||
wsRule.monitor = first_ident;
|
||||
wsRule.workspaceString = wsIdent;
|
||||
wsRule.isDefault = true; // backwards compat
|
||||
rules = value.substr(WORKSPACE_DELIM + 1);
|
||||
}
|
||||
|
||||
auto assignRule = [&](std::string rule) {
|
||||
size_t delim = std::string::npos;
|
||||
Debug::log(INFO, "found workspacerule: %s", rule.c_str());
|
||||
if ((delim = rule.find("gapsin:")) != std::string::npos)
|
||||
wsRule.gapsIn = std::stoi(rule.substr(delim + 7));
|
||||
else if ((delim = rule.find("gapsout:")) != std::string::npos)
|
||||
@@ -1053,6 +1135,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
wsRule.decorate = configStringToInt(rule.substr(delim + 9));
|
||||
else if ((delim = rule.find("monitor:")) != std::string::npos)
|
||||
wsRule.monitor = rule.substr(delim + 8);
|
||||
else if ((delim = rule.find("default:")) != std::string::npos)
|
||||
wsRule.isDefault = configStringToInt(rule.substr(delim + 8));
|
||||
};
|
||||
|
||||
size_t pos = 0;
|
||||
@@ -1066,7 +1150,13 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
|
||||
wsRule.workspaceId = id;
|
||||
wsRule.workspaceName = name;
|
||||
m_mWorkspaceRules[id] = wsRule;
|
||||
|
||||
const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { return other.workspaceString == wsRule.workspaceString; });
|
||||
|
||||
if (IT == m_dWorkspaceRules.end())
|
||||
m_dWorkspaceRules.emplace_back(wsRule);
|
||||
else
|
||||
*IT = wsRule;
|
||||
}
|
||||
|
||||
void CConfigManager::handleSubmap(const std::string& command, const std::string& submap) {
|
||||
@@ -1131,16 +1221,7 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
}
|
||||
|
||||
void CConfigManager::handleBindWS(const std::string& command, const std::string& value) {
|
||||
const auto ARGS = CVarList(value);
|
||||
|
||||
const auto FOUND = std::find_if(boundWorkspaces.begin(), boundWorkspaces.end(), [&](const auto& other) { return other.first == ARGS[0]; });
|
||||
|
||||
if (FOUND != boundWorkspaces.end()) {
|
||||
FOUND->second = ARGS[1];
|
||||
return;
|
||||
}
|
||||
|
||||
boundWorkspaces.push_back({ARGS[0], ARGS[1]});
|
||||
parseError = "bindws has been deprecated in favor of workspace rules, see the wiki -> workspace rules";
|
||||
}
|
||||
|
||||
void CConfigManager::handleEnv(const std::string& command, const std::string& value) {
|
||||
@@ -1376,56 +1457,57 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
configDynamicVars.clear();
|
||||
deviceConfigs.clear();
|
||||
m_dBlurLSNamespaces.clear();
|
||||
boundWorkspaces.clear();
|
||||
m_mWorkspaceRules.clear();
|
||||
m_dWorkspaceRules.clear();
|
||||
setDefaultAnimationVars(); // reset anims
|
||||
m_vDeclaredPlugins.clear();
|
||||
m_dLayerRules.clear();
|
||||
m_vFailedPluginConfigValues.clear();
|
||||
|
||||
// paths
|
||||
configPaths.clear();
|
||||
std::string mainConfigPath = getMainConfigPath();
|
||||
Debug::log(LOG, "Using config: %s", mainConfigPath.c_str());
|
||||
configPaths.push_back(mainConfigPath);
|
||||
std::string configPath = mainConfigPath.substr(0, mainConfigPath.find_last_of('/'));
|
||||
// find_last_of never returns npos since main_config at least has /hypr/
|
||||
|
||||
std::string CONFIGPATH;
|
||||
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
|
||||
|
||||
if (g_pCompositor->explicitConfigPath == "") {
|
||||
CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
|
||||
} else {
|
||||
CONFIGPATH = g_pCompositor->explicitConfigPath;
|
||||
}
|
||||
|
||||
configPaths.push_back(CONFIGPATH);
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(CONFIGPATH);
|
||||
|
||||
if (!ifs.good()) {
|
||||
if (g_pCompositor->explicitConfigPath == "") {
|
||||
Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
|
||||
if (!std::filesystem::is_directory(configPath)) {
|
||||
Debug::log(WARN, "Creating config home directory");
|
||||
try {
|
||||
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
|
||||
} catch (...) { /* Probably doesn't exist */
|
||||
}
|
||||
|
||||
try {
|
||||
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
|
||||
std::filesystem::create_directories(CONFIGPARENTPATH);
|
||||
std::filesystem::create_directories(configPath);
|
||||
} catch (...) {
|
||||
parseError = "Broken config file! (Could not create directory)";
|
||||
parseError = "Broken config file! (Could not create config directory)";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(mainConfigPath)) {
|
||||
Debug::log(WARN, "No config file found; attempting to generate.");
|
||||
std::ofstream ofs;
|
||||
ofs.open(CONFIGPATH, std::ios::trunc);
|
||||
|
||||
ofs.open(mainConfigPath, std::ios::trunc);
|
||||
ofs << AUTOCONFIG;
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(mainConfigPath);
|
||||
|
||||
if (!ifs.good()) {
|
||||
Debug::log(WARN, "Config reading error. Attempting to generate, backing up old one if exists");
|
||||
|
||||
ifs.close();
|
||||
|
||||
if (std::filesystem::exists(mainConfigPath))
|
||||
std::filesystem::rename(mainConfigPath, mainConfigPath + ".backup");
|
||||
|
||||
// Create default config
|
||||
std::ofstream ofs;
|
||||
ofs.open(mainConfigPath, std::ios::trunc);
|
||||
ofs << AUTOCONFIG;
|
||||
ofs.close();
|
||||
|
||||
ifs.open(CONFIGPATH);
|
||||
|
||||
// Try to re-open
|
||||
ifs.open(mainConfigPath);
|
||||
if (!ifs.good()) {
|
||||
parseError = "Broken config file! (Could not open)";
|
||||
return;
|
||||
@@ -1438,17 +1520,17 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
while (std::getline(ifs, line)) {
|
||||
// Read line by line.
|
||||
try {
|
||||
configCurrentPath = "~/.config/hypr/hyprland.conf";
|
||||
configCurrentPath = mainConfigPath;
|
||||
parseLine(line);
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Error reading line from config. Line:");
|
||||
Debug::log(NONE, "%s", line.c_str());
|
||||
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): Line parsing error.";
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): Line parsing error.";
|
||||
}
|
||||
|
||||
if (parseError != "" && parseError.find("Config error at line") != 0) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): " + parseError;
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): " + parseError;
|
||||
}
|
||||
|
||||
++linenum;
|
||||
@@ -1475,7 +1557,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
if (parseError != "")
|
||||
g_pHyprError->queueCreate(parseError + "\nHyprland may not work correctly.", CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
|
||||
else if (configValues["autogenerated"].intValue == 1)
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + mainConfigPath + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
|
||||
CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
@@ -1491,6 +1573,14 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
ensureVRR();
|
||||
}
|
||||
|
||||
// Updates dynamic window rules
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
w->updateDynamicRules();
|
||||
}
|
||||
|
||||
// Update window border colors
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
@@ -1523,17 +1613,12 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
|
||||
// update plugins
|
||||
handlePluginLoads();
|
||||
|
||||
EMIT_HOOK_EVENT("configReloaded", nullptr);
|
||||
}
|
||||
|
||||
void CConfigManager::tick() {
|
||||
std::string CONFIGPATH;
|
||||
if (g_pCompositor->explicitConfigPath.empty()) {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
} else {
|
||||
CONFIGPATH = g_pCompositor->explicitConfigPath;
|
||||
}
|
||||
|
||||
std::string CONFIGPATH = getMainConfigPath();
|
||||
if (!std::filesystem::exists(CONFIGPATH)) {
|
||||
Debug::log(ERR, "Config doesn't exist??");
|
||||
return;
|
||||
@@ -1572,7 +1657,7 @@ SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
|
||||
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val, std::optional<bool> touchpad) {
|
||||
std::lock_guard<std::mutex> lg(configmtx);
|
||||
|
||||
const auto it = deviceConfigs.find(dev);
|
||||
@@ -1591,8 +1676,8 @@ SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, co
|
||||
if (foundIt == std::string::npos)
|
||||
continue;
|
||||
|
||||
if (cv.first == "input:" + val || cv.first == "input:touchpad:" + cv.first || cv.first == "input:touchdevice:" + val || cv.first == "input:tablet:" + cv.first ||
|
||||
cv.first == "input:tablet:" + val) {
|
||||
if (cv.first == "input:" + val || (touchpad.value_or(true) && cv.first == "input:touchpad:" + val) || cv.first == "input:touchdevice:" + val ||
|
||||
cv.first == "input:tablet:" + val || cv.first == "input:tablet:" + val) {
|
||||
copy = cv.second;
|
||||
}
|
||||
}
|
||||
@@ -1618,16 +1703,16 @@ std::string CConfigManager::getString(const std::string& v) {
|
||||
return VAL;
|
||||
}
|
||||
|
||||
int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v) {
|
||||
return getConfigValueSafeDevice(dev, v).intValue;
|
||||
int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v, std::optional<bool> touchpad) {
|
||||
return getConfigValueSafeDevice(dev, v, touchpad).intValue;
|
||||
}
|
||||
|
||||
float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v) {
|
||||
return getConfigValueSafeDevice(dev, v).floatValue;
|
||||
float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v, std::optional<bool> touchpad) {
|
||||
return getConfigValueSafeDevice(dev, v, touchpad).floatValue;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v) {
|
||||
auto VAL = getConfigValueSafeDevice(dev, v).strValue;
|
||||
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, std::optional<bool> touchpad) {
|
||||
auto VAL = getConfigValueSafeDevice(dev, v, touchpad).strValue;
|
||||
|
||||
if (VAL == STRVAL_EMPTY)
|
||||
return "";
|
||||
@@ -1680,14 +1765,10 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st
|
||||
}
|
||||
|
||||
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) {
|
||||
if (m_mWorkspaceRules.contains(pWorkspace->m_iID)) {
|
||||
return m_mWorkspaceRules.at(pWorkspace->m_iID);
|
||||
}
|
||||
|
||||
const auto IT = std::find_if(m_mWorkspaceRules.begin(), m_mWorkspaceRules.end(), [&](const auto& other) { return other.second.workspaceName == pWorkspace->m_szName; });
|
||||
if (IT == m_mWorkspaceRules.end())
|
||||
const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { return other.workspaceName == pWorkspace->m_szName; });
|
||||
if (IT == m_dWorkspaceRules.end())
|
||||
return SWorkspaceRule{};
|
||||
return IT->second;
|
||||
return *IT;
|
||||
}
|
||||
|
||||
std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
@@ -1701,6 +1782,10 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
|
||||
Debug::log(LOG, "Searching for matching rules for %s (title: %s)", appidclass.c_str(), title.c_str());
|
||||
|
||||
// since some rules will be applied later, we need to store some flags
|
||||
bool hasFloating = pWindow->m_bIsFloating;
|
||||
bool hasFullscreen = pWindow->m_bIsFullscreen;
|
||||
|
||||
for (auto& rule : m_dWindowRules) {
|
||||
// check if we have a matching rule
|
||||
if (!rule.v2) {
|
||||
@@ -1743,12 +1828,12 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
if (rule.bFloating != -1) {
|
||||
if (pWindow->m_bIsFloating != rule.bFloating)
|
||||
if (hasFloating != rule.bFloating)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.bFullscreen != -1) {
|
||||
if (pWindow->m_bIsFullscreen != rule.bFullscreen)
|
||||
if (hasFullscreen != rule.bFullscreen)
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1766,6 +1851,11 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
Debug::log(LOG, "Window rule %s -> %s matched %lx [%s]", rule.szRule.c_str(), rule.szValue.c_str(), pWindow, pWindow->m_szTitle.c_str());
|
||||
|
||||
returns.push_back(rule);
|
||||
|
||||
if (rule.szRule == "float")
|
||||
hasFloating = true;
|
||||
else if (rule.szRule == "fullscreen")
|
||||
hasFullscreen = true;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> PIDs = {(uint64_t)pWindow->getPID()};
|
||||
@@ -1879,6 +1969,8 @@ void CConfigManager::performMonitorReload() {
|
||||
g_pCompositor->m_bUnsafeState = false;
|
||||
|
||||
m_bWantsMonitorReload = false;
|
||||
|
||||
EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr);
|
||||
}
|
||||
|
||||
SConfigValue* CConfigManager::getConfigValuePtr(const std::string& val) {
|
||||
@@ -2020,29 +2112,29 @@ void CConfigManager::addParseError(const std::string& err) {
|
||||
}
|
||||
|
||||
CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
|
||||
for (auto& [ws, mon] : boundWorkspaces) {
|
||||
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return g_pCompositor->getMonitorFromString(mon);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
auto monitor = getBoundMonitorStringForWS(wsname);
|
||||
if (monitor.substr(0, 5) == "desc:")
|
||||
return g_pCompositor->getMonitorFromDesc(monitor.substr(5));
|
||||
else
|
||||
return g_pCompositor->getMonitorFromName(monitor);
|
||||
}
|
||||
|
||||
std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) {
|
||||
for (auto& [ws, mon] : boundWorkspaces) {
|
||||
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
|
||||
for (auto& wr : m_dWorkspaceRules) {
|
||||
const auto WSNAME = wr.workspaceName.find("name:") == 0 ? wr.workspaceName.substr(5) : wr.workspaceName;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return mon;
|
||||
return wr.monitor;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::deque<SWorkspaceRule>& CConfigManager::getAllWorkspaceRules() {
|
||||
return m_dWorkspaceRules;
|
||||
}
|
||||
|
||||
void CConfigManager::addExecRule(const SExecRequestedRule& rule) {
|
||||
execRequestedRules.push_back(rule);
|
||||
}
|
||||
@@ -2090,6 +2182,11 @@ void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name,
|
||||
}
|
||||
|
||||
(*CONFIGMAPIT->second)[name] = value;
|
||||
|
||||
if (const auto IT = std::find_if(m_vFailedPluginConfigValues.begin(), m_vFailedPluginConfigValues.end(), [&](const auto& other) { return other.first == name; });
|
||||
IT != m_vFailedPluginConfigValues.end()) {
|
||||
configSetValueSafe(IT->first, IT->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::removePluginConfig(HANDLE handle) {
|
||||
@@ -2097,8 +2194,16 @@ void CConfigManager::removePluginConfig(HANDLE handle) {
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
|
||||
const auto IT = std::find_if(m_mWorkspaceRules.begin(), m_mWorkspaceRules.end(), [&](const auto& other) { return other.second.monitor == name; });
|
||||
if (IT == m_mWorkspaceRules.end())
|
||||
return "";
|
||||
return IT->second.workspaceString;
|
||||
for (auto other = m_dWorkspaceRules.begin(); other != m_dWorkspaceRules.end(); ++other) {
|
||||
if (other->isDefault) {
|
||||
if (other->monitor == name)
|
||||
return other->workspaceString;
|
||||
if (other->monitor.substr(0, 5) == "desc:") {
|
||||
auto monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5));
|
||||
if (monitor && monitor->szName == name)
|
||||
return other->workspaceString;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
#include <xf86drmMode.h>
|
||||
#include "../Window.hpp"
|
||||
#include "../helpers/WLClasses.hpp"
|
||||
|
||||
@@ -44,6 +45,7 @@ struct SMonitorRule {
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
bool enable10bit = false;
|
||||
drmModeModeInfo drmMode = {};
|
||||
};
|
||||
|
||||
struct SWorkspaceRule {
|
||||
@@ -51,6 +53,7 @@ struct SWorkspaceRule {
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
@@ -85,12 +88,23 @@ struct SExecRequestedRule {
|
||||
|
||||
class CVarList {
|
||||
public:
|
||||
/* passing 's' as a separator will use std::isspace */
|
||||
CVarList(const std::string& in, long unsigned int lastArgNo = 0, const char separator = ',') {
|
||||
std::string curitem = "";
|
||||
std::string argZ = in;
|
||||
const bool SPACESEP = separator == 's';
|
||||
|
||||
auto nextItem = [&]() {
|
||||
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(separator);
|
||||
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : ([&]() -> size_t {
|
||||
if (!SPACESEP)
|
||||
return argZ.find_first_of(separator);
|
||||
|
||||
uint64_t pos = -1;
|
||||
while (!std::isspace(argZ[++pos]) && pos < argZ.length())
|
||||
;
|
||||
|
||||
return pos < argZ.length() ? pos : std::string::npos;
|
||||
}());
|
||||
|
||||
if (idx != std::string::npos) {
|
||||
curitem = argZ.substr(0, idx);
|
||||
@@ -153,14 +167,16 @@ class CConfigManager {
|
||||
void setInt(const std::string&, int);
|
||||
void setString(const std::string&, const std::string&);
|
||||
|
||||
int getDeviceInt(const std::string&, const std::string&);
|
||||
float getDeviceFloat(const std::string&, const std::string&);
|
||||
std::string getDeviceString(const std::string&, const std::string&);
|
||||
int getDeviceInt(const std::string&, const std::string&, std::optional<bool> touchpad = {});
|
||||
float getDeviceFloat(const std::string&, const std::string&, std::optional<bool> touchpad = {});
|
||||
std::string getDeviceString(const std::string&, const std::string&, std::optional<bool> touchpad = {});
|
||||
bool deviceConfigExists(const std::string&);
|
||||
bool shouldBlurLS(const std::string&);
|
||||
|
||||
SConfigValue* getConfigValuePtr(const std::string&);
|
||||
SConfigValue* getConfigValuePtrSafe(const std::string&);
|
||||
static std::string getConfigDir();
|
||||
static std::string getMainConfigPath();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
|
||||
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
||||
@@ -168,6 +184,7 @@ class CConfigManager {
|
||||
|
||||
CMonitor* getBoundMonitorForWS(const std::string&);
|
||||
std::string getBoundMonitorStringForWS(const std::string&);
|
||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||
@@ -216,8 +233,6 @@ class CConfigManager {
|
||||
|
||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
|
||||
|
||||
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
||||
|
||||
std::vector<std::string> m_vDeclaredPlugins;
|
||||
@@ -226,7 +241,7 @@ class CConfigManager {
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
std::unordered_map<int, SWorkspaceRule> m_mWorkspaceRules;
|
||||
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
||||
std::deque<SWindowRule> m_dWindowRules;
|
||||
std::deque<SLayerRule> m_dLayerRules;
|
||||
std::deque<std::string> m_dBlurLSNamespaces;
|
||||
@@ -237,6 +252,8 @@ class CConfigManager {
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> environmentVariables;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
|
||||
// internal methods
|
||||
void setDefaultVars();
|
||||
void setDefaultAnimationVars();
|
||||
@@ -249,7 +266,7 @@ class CConfigManager {
|
||||
void applyUserDefinedVars(std::string&, const size_t);
|
||||
void loadConfigLoadVars();
|
||||
SConfigValue getConfigValueSafe(const std::string&);
|
||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
|
||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&, std::optional<bool> touchpad);
|
||||
void parseLine(std::string&);
|
||||
void configSetValueSafe(const std::string&, const std::string&);
|
||||
void handleDeviceConfig(const std::string&, const std::string&);
|
||||
|
@@ -25,7 +25,8 @@ std::string getRandomMessage() {
|
||||
"*thud*",
|
||||
"Well this is awkward.",
|
||||
"\"stable\"",
|
||||
"I hope you didn't have any unsaved progress."};
|
||||
"I hope you didn't have any unsaved progress.",
|
||||
"All these computers..."};
|
||||
|
||||
std::random_device dev;
|
||||
std::mt19937 engine(dev());
|
||||
@@ -46,7 +47,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += getFormat("Hyprland received signal %d (%s)\n\n", sig, strsignal(sig));
|
||||
|
||||
finalCrashReport += getFormat("Version: %s\n\n", GIT_COMMIT_HASH);
|
||||
finalCrashReport += getFormat("Version: %s\nTag: %s\n\n", GIT_COMMIT_HASH, GIT_TAG);
|
||||
|
||||
if (g_pPluginSystem && !g_pPluginSystem->getAllPlugins().empty()) {
|
||||
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
|
||||
|
@@ -14,6 +14,20 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
static void trimTrailingComma(std::string& str) {
|
||||
if (!str.empty() && str.back() == ',')
|
||||
str.pop_back();
|
||||
}
|
||||
|
||||
static std::string getWorkspaceNameFromSpecialID(const int workspaceID) {
|
||||
if (workspaceID == 0)
|
||||
return "";
|
||||
const auto* workspace = g_pCompositor->getWorkspaceByID(workspaceID);
|
||||
if (!workspace)
|
||||
return "";
|
||||
return workspace->m_szName;
|
||||
}
|
||||
|
||||
std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
@@ -40,6 +54,10 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"specialWorkspace": {
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"reserved": [%i, %i, %i, %i],
|
||||
"scale": %.2f,
|
||||
"transform": %i,
|
||||
@@ -50,13 +68,13 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
m->ID, escapeJSONStrings(m->szName).c_str(), escapeJSONStrings(m->output->description ? m->output->description : "").c_str(),
|
||||
(m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x,
|
||||
(int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace,
|
||||
escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(), m->specialWorkspaceID,
|
||||
escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"));
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
@@ -64,14 +82,16 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tmake: %s\n\tmodel: %s\n\tserial: %s\n\tactive workspace: %i (%s)\n\treserved: %i "
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tmake: %s\n\tmodel: %s\n\tserial: %s\n\tactive workspace: %i (%s)\n\tspecial "
|
||||
"workspace: %i (%s)\n\treserved: %i "
|
||||
"%i %i %i\n\tscale: %.2f\n\ttransform: "
|
||||
"%i\n\tfocused: %s\n\tdpmsStatus: %i\n\tvrr: %i\n\n",
|
||||
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||
(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||
(m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(),
|
||||
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale,
|
||||
(int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus,
|
||||
m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||
(m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus,
|
||||
(int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED));
|
||||
}
|
||||
}
|
||||
@@ -175,9 +195,7 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += getWindowData(w.get(), format);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result != "[")
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
@@ -227,7 +245,7 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += ",";
|
||||
}
|
||||
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
@@ -285,8 +303,7 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, escapeJSONStrings(layer->szNamespace).c_str());
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
if (level.size() > 0)
|
||||
result += "\n ";
|
||||
@@ -296,14 +313,12 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
layerLevel++;
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "\n }\n},";
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "\n}\n";
|
||||
|
||||
@@ -347,8 +362,7 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"keyboards\": [\n";
|
||||
@@ -371,8 +385,7 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
escapeJSONStrings(KM).c_str(), (k.active ? "true" : "false"));
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"tablets\": [\n";
|
||||
@@ -409,8 +422,7 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
&d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"touch\": [\n";
|
||||
@@ -424,9 +436,7 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
&d, d.name.c_str());
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result[result.size() - 1] == ',')
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"switches\": [\n";
|
||||
@@ -440,9 +450,7 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
&d, d.pWlrDevice ? d.pWlrDevice->name : "");
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result[result.size() - 1] == ',')
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
result += "\n]\n";
|
||||
|
||||
result += "}\n";
|
||||
@@ -540,7 +548,7 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
bz.first.c_str());
|
||||
}
|
||||
|
||||
ret.pop_back();
|
||||
trimTrailingComma(ret);
|
||||
|
||||
ret += "]]";
|
||||
}
|
||||
@@ -564,7 +572,7 @@ std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
},)#",
|
||||
escapeJSONStrings(sh.appid + ":" + sh.id).c_str(), escapeJSONStrings(sh.description).c_str());
|
||||
}
|
||||
ret.pop_back();
|
||||
trimTrailingComma(ret);
|
||||
ret += "]\n";
|
||||
}
|
||||
|
||||
@@ -584,6 +592,8 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
ret += "r";
|
||||
if (kb.repeat)
|
||||
ret += "e";
|
||||
if (kb.nonConsuming)
|
||||
ret += "n";
|
||||
|
||||
ret += getFormat("\n\tmodmask: %u\n\tsubmap: %s\n\tkey: %s\n\tkeycode: %d\n\tdispatcher: %s\n\targ: %s\n\n", kb.modmask, kb.submap.c_str(), kb.key.c_str(), kb.keycode,
|
||||
kb.handler.c_str(), kb.arg.c_str());
|
||||
@@ -599,6 +609,7 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
"mouse": %s,
|
||||
"release": %s,
|
||||
"repeat": %s,
|
||||
"non_consuming": %s,
|
||||
"modmask": %u,
|
||||
"submap": "%s",
|
||||
"key": "%s",
|
||||
@@ -606,10 +617,11 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
"dispatcher": "%s",
|
||||
"arg": "%s"
|
||||
},)#",
|
||||
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.modmask,
|
||||
escapeJSONStrings(kb.submap).c_str(), escapeJSONStrings(kb.key).c_str(), kb.keycode, escapeJSONStrings(kb.handler).c_str(), escapeJSONStrings(kb.arg).c_str());
|
||||
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false",
|
||||
kb.modmask, escapeJSONStrings(kb.submap).c_str(), escapeJSONStrings(kb.key).c_str(), kb.keycode, escapeJSONStrings(kb.handler).c_str(),
|
||||
escapeJSONStrings(kb.arg).c_str());
|
||||
}
|
||||
ret.pop_back();
|
||||
trimTrailingComma(ret);
|
||||
ret += "]";
|
||||
}
|
||||
|
||||
@@ -659,8 +671,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += "\"no xwayland\",";
|
||||
#endif
|
||||
|
||||
if (result[result.length() - 1] == ',')
|
||||
result.pop_back();
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "]\n}";
|
||||
|
||||
@@ -676,7 +687,10 @@ std::string dispatchRequest(std::string in) {
|
||||
|
||||
const auto DISPATCHSTR = in.substr(0, in.find_first_of(' '));
|
||||
|
||||
const auto DISPATCHARG = in.substr(in.find_first_of(' ') + 1);
|
||||
auto DISPATCHARG = std::string();
|
||||
if ((int) in.find_first_of(' ') != -1)
|
||||
DISPATCHARG = in.substr(in.find_first_of(' ') + 1);
|
||||
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(DISPATCHSTR);
|
||||
if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end())
|
||||
@@ -722,7 +736,7 @@ std::string dispatchKeyword(std::string in) {
|
||||
}
|
||||
|
||||
// decorations will probably need a repaint
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border")) {
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace") {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
@@ -961,6 +975,8 @@ std::string dispatchSetProp(std::string request) {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoBorder.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "forcenoshadow") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "forcenodim") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "windowdancecompat") {
|
||||
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nomaxsize") {
|
||||
@@ -981,6 +997,8 @@ std::string dispatchSetProp(std::string request) {
|
||||
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "forcergbx") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "bordersize") {
|
||||
PWINDOW->m_sSpecialRenderData.borderSize.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else {
|
||||
return "prop not found";
|
||||
}
|
||||
@@ -988,6 +1006,9 @@ std::string dispatchSetProp(std::string request) {
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@@ -1287,7 +1308,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
|
||||
const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
char readBuffer[1024];
|
||||
|
||||
@@ -1318,7 +1339,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
|
||||
void HyprCtl::startHyprCtlSocket() {
|
||||
|
||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
|
@@ -4,8 +4,6 @@
|
||||
#include "helpers/WLListener.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
|
||||
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@@ -59,6 +59,8 @@ namespace Events {
|
||||
DYNLISTENFUNC(requestMinimize);
|
||||
DYNLISTENFUNC(requestMaximize);
|
||||
DYNLISTENFUNC(setOverrideRedirect);
|
||||
DYNLISTENFUNC(associateX11);
|
||||
DYNLISTENFUNC(dissociateX11);
|
||||
|
||||
// Window subsurfaces
|
||||
// LISTENER(newSubsurfaceWindow);
|
||||
@@ -101,6 +103,7 @@ namespace Events {
|
||||
DYNLISTENFUNC(monitorDamage);
|
||||
DYNLISTENFUNC(monitorNeedsFrame);
|
||||
DYNLISTENFUNC(monitorCommit);
|
||||
DYNLISTENFUNC(monitorBind);
|
||||
|
||||
// XWayland
|
||||
LISTENER(readyXWayland);
|
||||
@@ -164,4 +167,7 @@ namespace Events {
|
||||
|
||||
// Session Lock
|
||||
LISTENER(newSessionLock);
|
||||
|
||||
// Gamma control
|
||||
LISTENER(setGamma);
|
||||
};
|
||||
|
@@ -44,8 +44,8 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
||||
|
||||
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
||||
|
||||
layerSurface->layerSurface = WLRLAYERSURFACE;
|
||||
@@ -109,9 +109,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "LayerSurface %lx mapped", layersurface->layerSurface);
|
||||
|
||||
layersurface->layerSurface->mapped = true;
|
||||
layersurface->mapped = true;
|
||||
|
||||
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
||||
layersurface->surface = layersurface->layerSurface->surface;
|
||||
|
||||
// anim
|
||||
@@ -158,9 +157,11 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
|
||||
layersurface->alpha.setValue(0);
|
||||
layersurface->alpha = 1.f;
|
||||
layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN) ? 0.f : 1.f);
|
||||
layersurface->readyToDelete = false;
|
||||
layersurface->fadingOut = false;
|
||||
|
||||
@@ -204,9 +205,6 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
|
||||
if (layersurface->layerSurface->mapped)
|
||||
layersurface->layerSurface->mapped = false;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||
|
||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == layersurface->layerSurface->surface;
|
||||
@@ -323,6 +321,22 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (layersurface->layerSurface->current.keyboard_interactive &&
|
||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
|
||||
&& !layersurface->keyboardExclusive && layersurface->mapped) {
|
||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||
|
||||
const auto LOCAL =
|
||||
g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
|
||||
} else if (!layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) &&
|
||||
layersurface->keyboardExclusive) {
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
||||
|
||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
|
@@ -110,8 +110,8 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
|
||||
g_pInputManager->m_sDrag.dragIcon = wlrDrag->icon;
|
||||
wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon;
|
||||
|
||||
g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->surface->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->surface->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag,
|
||||
"DragIcon");
|
||||
@@ -214,3 +214,20 @@ void Events::listener_newSessionLock(wl_listener* listener, void* data) {
|
||||
|
||||
g_pSessionLockManager->onNewSessionLock((wlr_session_lock_v1*)data);
|
||||
}
|
||||
|
||||
void Events::listener_setGamma(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "New Gamma event at %lx", data);
|
||||
|
||||
const auto E = (wlr_gamma_control_manager_v1_set_gamma_event*)data;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(E->output);
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Gamma event object references non-existent output %lx ?", E->output);
|
||||
return;
|
||||
}
|
||||
|
||||
PMONITOR->gammaChanged = true;
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
||||
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||
|
||||
// TODO: clients off of disabled
|
||||
wlr_box BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
||||
|
||||
@@ -77,7 +76,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "Adding completely new monitor.");
|
||||
PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
|
||||
|
||||
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID();
|
||||
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
||||
}
|
||||
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
@@ -218,5 +217,10 @@ void Events::listener_monitorCommit(void* owner, void* data) {
|
||||
|
||||
const auto E = (wlr_output_event_commit*)data;
|
||||
|
||||
if (E->committed & WLR_OUTPUT_STATE_BUFFER)
|
||||
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
|
||||
}
|
||||
|
||||
void Events::listener_monitorBind(void* owner, void* data) {
|
||||
;
|
||||
}
|
||||
|
@@ -56,8 +56,8 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
pHyprPopup->popup = popup;
|
||||
|
||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_commitPopupXDG.initCallback(&popup->base->surface->events.commit, &Events::listener_commitPopupXDG, pHyprPopup, "HyprPopup");
|
||||
|
||||
@@ -202,6 +202,11 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
void Events::listener_commitPopupXDG(void* owner, void* data) {
|
||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
||||
|
||||
if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) {
|
||||
PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x;
|
||||
PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y;
|
||||
}
|
||||
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
|
@@ -58,6 +58,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bFadingOut = false;
|
||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
|
||||
PWINDOW->m_bFirstMap = true;
|
||||
|
||||
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
|
||||
g_pInputManager->releaseAllMouseButtons();
|
||||
@@ -189,6 +190,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bPinned = true;
|
||||
} else if (r.szRule == "maximize") {
|
||||
requestsMaximize = true;
|
||||
} else if (r.szRule == "stayfocused") {
|
||||
PWINDOW->m_bStayFocused = true;
|
||||
} else if (r.szRule.find("idleinhibit") == 0) {
|
||||
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
@@ -429,15 +432,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// check LS focus grab
|
||||
const auto PFORCEFOCUS = g_pCompositor->getForceFocus();
|
||||
const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
|
||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent) {
|
||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
|
||||
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(*PDIMSTRENGTH);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH);
|
||||
} else {
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||
@@ -464,7 +469,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
|
||||
"Xwayland Window Late");
|
||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
|
||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
|
||||
"Xwayland Window Late");
|
||||
|
||||
if (PWINDOW->m_iX11Type == 2)
|
||||
@@ -584,6 +589,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_bFirstMap = false;
|
||||
|
||||
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);
|
||||
|
||||
@@ -679,11 +686,11 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow) {
|
||||
if (!PWINDOWCANDIDATE)
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
else
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
} else {
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
} else {
|
||||
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
|
||||
@@ -736,9 +743,29 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->updateSurfaceOutputs();
|
||||
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
||||
|
||||
// Debug::log(LOG, "Window %lx committed", PWINDOW); // SPAM!
|
||||
if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto ISRIGID = PWINDOW->m_uSurface.xdg->toplevel->current.max_height == PWINDOW->m_uSurface.xdg->toplevel->current.min_height &&
|
||||
PWINDOW->m_uSurface.xdg->toplevel->current.max_width == PWINDOW->m_uSurface.xdg->toplevel->current.min_width;
|
||||
|
||||
if (!ISRIGID)
|
||||
return;
|
||||
|
||||
const Vector2D REQUESTEDSIZE = {PWINDOW->m_uSurface.xdg->toplevel->current.max_width, PWINDOW->m_uSurface.xdg->toplevel->current.max_height};
|
||||
|
||||
if (REQUESTEDSIZE == PWINDOW->m_vReportedSize || REQUESTEDSIZE.x < 5 || REQUESTEDSIZE.y < 5)
|
||||
return;
|
||||
|
||||
const Vector2D DELTA = PWINDOW->m_vReportedSize - REQUESTEDSIZE;
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0;
|
||||
PWINDOW->m_vRealSize = REQUESTEDSIZE;
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, REQUESTEDSIZE, true);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
|
||||
void Events::listener_destroyWindow(void* owner, void* data) {
|
||||
@@ -759,6 +786,8 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_destroyWindow.removeCallback();
|
||||
PWINDOW->hyprListener_configureX11.removeCallback();
|
||||
PWINDOW->hyprListener_setOverrideRedirect.removeCallback();
|
||||
PWINDOW->hyprListener_associateX11.removeCallback();
|
||||
PWINDOW->hyprListener_dissociateX11.removeCallback();
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
@@ -783,6 +812,8 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
return;
|
||||
|
||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", getFormat("%lx", PWINDOW)});
|
||||
EMIT_HOOK_EVENT("windowTitle", PWINDOW);
|
||||
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle});
|
||||
@@ -837,7 +868,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
} else {
|
||||
if (!PWINDOW->m_uSurface.xwayland->mapped)
|
||||
if (!PWINDOW->m_uSurface.xwayland->surface->mapped)
|
||||
return;
|
||||
|
||||
if (!PWINDOW->m_bFakeFullscreenState)
|
||||
@@ -932,7 +963,7 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
const auto E = (wlr_xwayland_surface_configure_event*)data;
|
||||
|
||||
if (!PWINDOW->m_uSurface.xwayland->mapped || !PWINDOW->m_bMappedX11) {
|
||||
if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) {
|
||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||
return;
|
||||
}
|
||||
@@ -953,6 +984,13 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y));
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
|
||||
|
||||
@@ -992,6 +1030,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 ||
|
||||
abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
|
||||
Debug::log(LOG, "Unmanaged window %lx requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y,
|
||||
@@ -1003,6 +1043,14 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
||||
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
PWINDOW->m_vSize = PWINDOW->m_vRealSize.goalv();
|
||||
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
|
||||
|
||||
g_pCompositor->moveWindowToTop(PWINDOW);
|
||||
@@ -1019,6 +1067,18 @@ void Events::listener_setOverrideRedirect(void* owner, void* data) {
|
||||
//}
|
||||
}
|
||||
|
||||
void Events::listener_associateX11(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
PWINDOW->hyprListener_mapWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.map, &Events::listener_mapWindow, PWINDOW, "XWayland Window");
|
||||
}
|
||||
|
||||
void Events::listener_dissociateX11(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
PWINDOW->hyprListener_mapWindow.removeCallback();
|
||||
}
|
||||
|
||||
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||
const auto XWSURFACE = (wlr_xwayland_surface*)data;
|
||||
|
||||
@@ -1034,7 +1094,8 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||
|
||||
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
|
||||
|
||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XWSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_associateX11.initCallback(&XWSURFACE->events.associate, &Events::listener_associateX11, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_dissociateX11.initCallback(&XWSURFACE->events.dissociate, &Events::listener_dissociateX11, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_setOverrideRedirect.initCallback(&XWSURFACE->events.set_override_redirect, &Events::listener_setOverrideRedirect, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window");
|
||||
@@ -1052,7 +1113,7 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
|
||||
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
|
||||
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
|
||||
|
||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
|
||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->surface->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
|
||||
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XDGSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XDG Window");
|
||||
}
|
||||
|
||||
|
@@ -3,14 +3,16 @@
|
||||
#include "../defines.hpp"
|
||||
#include <any>
|
||||
|
||||
enum ANIMATEDVARTYPE {
|
||||
enum ANIMATEDVARTYPE
|
||||
{
|
||||
AVARTYPE_INVALID = -1,
|
||||
AVARTYPE_FLOAT,
|
||||
AVARTYPE_VECTOR,
|
||||
AVARTYPE_COLOR
|
||||
};
|
||||
|
||||
enum AVARDAMAGEPOLICY {
|
||||
enum AVARDAMAGEPOLICY
|
||||
{
|
||||
AVARDAMAGE_NONE = -1,
|
||||
AVARDAMAGE_ENTIRE = 0,
|
||||
AVARDAMAGE_BORDER,
|
||||
@@ -30,6 +32,11 @@ class CAnimatedVariable {
|
||||
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
||||
void create(ANIMATEDVARTYPE, std::any val, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
||||
|
||||
CAnimatedVariable(const CAnimatedVariable&) = delete;
|
||||
CAnimatedVariable(CAnimatedVariable&&) = delete;
|
||||
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
|
||||
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
|
||||
|
||||
~CAnimatedVariable();
|
||||
|
||||
void unregister();
|
||||
@@ -209,10 +216,17 @@ class CAnimatedVariable {
|
||||
m_bRemoveBeginAfterRan = remove;
|
||||
}
|
||||
|
||||
/* Sets the update callback, called every time the value is animated and a step is done
|
||||
Warning: calling unregisterVar/registerVar in this handler will cause UB */
|
||||
void setUpdateCallback(std::function<void(void* thisptr)> func) {
|
||||
m_fUpdateCallback = func;
|
||||
}
|
||||
|
||||
/* resets all callbacks. Does not call any. */
|
||||
void resetAllCallbacks() {
|
||||
m_fBeginCallback = nullptr;
|
||||
m_fEndCallback = nullptr;
|
||||
m_fUpdateCallback = nullptr;
|
||||
m_bRemoveBeginAfterRan = false;
|
||||
m_bRemoveEndAfterRan = false;
|
||||
}
|
||||
@@ -249,12 +263,15 @@ class CAnimatedVariable {
|
||||
bool m_bRemoveBeginAfterRan = true;
|
||||
std::function<void(void* thisptr)> m_fEndCallback;
|
||||
std::function<void(void* thisptr)> m_fBeginCallback;
|
||||
std::function<void(void* thisptr)> m_fUpdateCallback;
|
||||
|
||||
// methods
|
||||
void onAnimationEnd() {
|
||||
if (m_fEndCallback) {
|
||||
// loading m_bRemoveEndAfterRan before calling the callback allows the callback to delete this animation safely if it is false.
|
||||
auto removeEndCallback = m_bRemoveEndAfterRan;
|
||||
m_fEndCallback(this);
|
||||
if (m_bRemoveEndAfterRan)
|
||||
if (removeEndCallback)
|
||||
m_fEndCallback = nullptr; // reset
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include <algorithm>
|
||||
#include "../Compositor.hpp"
|
||||
#include <set>
|
||||
#include <sys/utsname.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
@@ -129,9 +130,9 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
|
||||
|
||||
if (value[1] == '.') {
|
||||
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
|
||||
value.replace(0, 2, parentDir);
|
||||
value.replace(0, 2 + currentPath.empty(), parentDir);
|
||||
} else {
|
||||
value.replace(0, 1, currentDir);
|
||||
value.replace(0, 1 + currentPath.empty(), currentDir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +243,7 @@ bool isNumber(const std::string& str, bool allowfloat) {
|
||||
if (point)
|
||||
return false;
|
||||
point = true;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!std::isdigit(c))
|
||||
@@ -305,7 +306,140 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
outName = PLASTWORKSPACE->m_szName;
|
||||
return PLASTWORKSPACE->m_iID;
|
||||
} else {
|
||||
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||
if (in[0] == 'r' && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
Debug::log(ERR, "Relative monitor workspace on monitor null!");
|
||||
result = INT_MAX;
|
||||
return result;
|
||||
}
|
||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
|
||||
int remains = (int)result;
|
||||
|
||||
std::set<int> invalidWSes;
|
||||
|
||||
// Collect all the workspaces we can't jump to.
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) {
|
||||
// Can't jump to this workspace
|
||||
invalidWSes.insert(ws->m_iID);
|
||||
}
|
||||
}
|
||||
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
|
||||
if (!PMONITOR || PMONITOR->ID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
// Can't be invalid
|
||||
continue;
|
||||
}
|
||||
// WS is bound to another monitor, can't jump to this
|
||||
invalidWSes.insert(rule.workspaceId);
|
||||
}
|
||||
|
||||
// Prepare all named workspaces in case when we need them
|
||||
std::vector<int> namedWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0)
|
||||
continue;
|
||||
|
||||
namedWSes.push_back(ws->m_iID);
|
||||
}
|
||||
std::sort(namedWSes.begin(), namedWSes.end());
|
||||
|
||||
// Just take a blind guess at where we'll probably end up
|
||||
int predictedWSID = g_pCompositor->m_pLastMonitor->activeWorkspace + remains;
|
||||
int remainingWSes = 0;
|
||||
char walkDir = in[1];
|
||||
|
||||
// sanitize. 0 means invalid oob in -
|
||||
predictedWSID = std::max(predictedWSID, 0);
|
||||
|
||||
// Count how many invalidWSes are in between (how bad the prediction was)
|
||||
int beginID = in[1] == '+' ? g_pCompositor->m_pLastMonitor->activeWorkspace + 1 : predictedWSID;
|
||||
int endID = in[1] == '+' ? predictedWSID : g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
|
||||
// Handle named workspaces. They are treated like always before other workspaces
|
||||
if (g_pCompositor->m_pLastMonitor->activeWorkspace < 0) {
|
||||
// Behaviour similar to 'm'
|
||||
// Find current
|
||||
int currentItem = -1;
|
||||
for (size_t i = 0; i < namedWSes.size(); i++) {
|
||||
if (namedWSes[i] == g_pCompositor->m_pLastMonitor->activeWorkspace) {
|
||||
currentItem = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
currentItem += remains;
|
||||
currentItem = std::max(currentItem, 0);
|
||||
if (currentItem >= (int)namedWSes.size()) {
|
||||
// At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0
|
||||
int diff = currentItem - (namedWSes.size() - 1);
|
||||
predictedWSID = diff;
|
||||
int beginID = 1;
|
||||
int endID = predictedWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
walkDir = '+';
|
||||
} else {
|
||||
// We found our final ws.
|
||||
remainingWSes = 0;
|
||||
predictedWSID = namedWSes[currentItem];
|
||||
}
|
||||
}
|
||||
|
||||
// Go in the search direction for remainingWSes
|
||||
// The performance impact is directly proportional to the number of open and bound workspaces
|
||||
int finalWSID = predictedWSID;
|
||||
if (walkDir == '-') {
|
||||
int beginID = finalWSID;
|
||||
int curID = finalWSID;
|
||||
while (--curID > 0 && remainingWSes > 0) {
|
||||
if (invalidWSes.find(curID) == invalidWSes.end()) {
|
||||
remainingWSes--;
|
||||
}
|
||||
finalWSID = curID;
|
||||
}
|
||||
if (finalWSID <= 0 || invalidWSes.find(finalWSID) != invalidWSes.end()) {
|
||||
if (namedWSes.size()) {
|
||||
// Go to the named workspaces
|
||||
// Need remainingWSes more
|
||||
int namedWSIdx = namedWSes.size() - remainingWSes;
|
||||
// Sanitze
|
||||
namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1);
|
||||
finalWSID = namedWSes[namedWSIdx];
|
||||
} else {
|
||||
// Couldn't find valid workspace in negative direction, search last first one back up positive direction
|
||||
walkDir = '+';
|
||||
// We know, that everything less than beginID is invalid, so don't bother with that
|
||||
finalWSID = beginID;
|
||||
remainingWSes = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (walkDir == '+') {
|
||||
int curID = finalWSID;
|
||||
while (++curID < INT32_MAX && remainingWSes > 0) {
|
||||
if (invalidWSes.find(curID) == invalidWSes.end()) {
|
||||
remainingWSes--;
|
||||
}
|
||||
finalWSID = curID;
|
||||
}
|
||||
}
|
||||
|
||||
result = finalWSID;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(result);
|
||||
if (PWORKSPACE)
|
||||
outName = g_pCompositor->getWorkspaceByID(result)->m_szName;
|
||||
else
|
||||
outName = std::to_string(finalWSID);
|
||||
|
||||
} else if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||
bool onAllMonitors = in[0] == 'e';
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
@@ -354,7 +488,6 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
|
||||
result = validWSes[currentItem];
|
||||
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
|
||||
|
||||
} else {
|
||||
if (in[0] == '+' || in[0] == '-') {
|
||||
if (g_pCompositor->m_pLastMonitor)
|
||||
|
@@ -10,10 +10,20 @@ int ratHandler(void* data) {
|
||||
|
||||
CMonitor::CMonitor() {
|
||||
wlr_damage_ring_init(&damage);
|
||||
pixman_region32_init(&lastFrameDamage);
|
||||
}
|
||||
|
||||
CMonitor::~CMonitor() {
|
||||
wlr_damage_ring_finish(&damage);
|
||||
pixman_region32_fini(&lastFrameDamage);
|
||||
|
||||
hyprListener_monitorDestroy.removeCallback();
|
||||
hyprListener_monitorFrame.removeCallback();
|
||||
hyprListener_monitorStateRequest.removeCallback();
|
||||
hyprListener_monitorDamage.removeCallback();
|
||||
hyprListener_monitorNeedsFrame.removeCallback();
|
||||
hyprListener_monitorCommit.removeCallback();
|
||||
hyprListener_monitorBind.removeCallback();
|
||||
}
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
@@ -23,12 +33,14 @@ void CMonitor::onConnect(bool noRule) {
|
||||
hyprListener_monitorDamage.removeCallback();
|
||||
hyprListener_monitorNeedsFrame.removeCallback();
|
||||
hyprListener_monitorCommit.removeCallback();
|
||||
hyprListener_monitorBind.removeCallback();
|
||||
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
|
||||
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
|
||||
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
|
||||
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this);
|
||||
hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this);
|
||||
hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this);
|
||||
hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this);
|
||||
|
||||
if (m_bEnabled) {
|
||||
wlr_output_enable(output, 1);
|
||||
@@ -145,7 +157,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
setupDefaultWS(monitorRule);
|
||||
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_szLastMonitor == szName) {
|
||||
if (ws->m_szLastMonitor == szName || g_pCompositor->m_vMonitors.size() == 1 /* avoid lost workspaces on recover */) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(ws.get(), this);
|
||||
ws->startAnim(true, true, true);
|
||||
ws->m_szLastMonitor = "";
|
||||
@@ -232,6 +244,7 @@ void CMonitor::onDisconnect() {
|
||||
hyprListener_monitorDamage.removeCallback();
|
||||
hyprListener_monitorNeedsFrame.removeCallback();
|
||||
hyprListener_monitorCommit.removeCallback();
|
||||
hyprListener_monitorBind.removeCallback();
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
||||
@@ -503,7 +516,10 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal) {
|
||||
return;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace) {
|
||||
Debug::log(ERR, "BUG THIS: Attempted to changeWorkspace to special!");
|
||||
if (specialWorkspaceID != pWorkspace->m_iID) {
|
||||
Debug::log(LOG, "changeworkspace on special, togglespecialworkspace to id %i", pWorkspace->m_iID);
|
||||
g_pKeybindManager->m_mDispatchers["togglespecialworkspace"](pWorkspace->m_szName == "special" ? "" : pWorkspace->m_szName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -535,7 +551,7 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal) {
|
||||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
else {
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
@@ -576,11 +592,23 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (specialWorkspaceID) {
|
||||
if (const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); EXISTINGSPECIAL)
|
||||
EXISTINGSPECIAL->startAnim(false, false);
|
||||
}
|
||||
|
||||
// open special
|
||||
pWorkspace->m_iMonitorID = ID;
|
||||
specialWorkspaceID = pWorkspace->m_iID;
|
||||
pWorkspace->startAnim(true, true);
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||
w->m_iMonitorID = ID;
|
||||
w->updateSurfaceOutputs();
|
||||
}
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
|
||||
if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <xf86drmMode.h>
|
||||
#include "Timer.hpp"
|
||||
|
||||
struct SMonitorRule;
|
||||
@@ -31,6 +32,8 @@ class CMonitor {
|
||||
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||
|
||||
drmModeModeInfo customDrmMode = {};
|
||||
|
||||
// WLR stuff
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
@@ -40,6 +43,7 @@ class CMonitor {
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
bool gammaChanged = false;
|
||||
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
@@ -57,6 +61,8 @@ class CMonitor {
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
pixman_region32_t lastFrameDamage; // stores last frame damage
|
||||
|
||||
// for the special workspace. 0 means not open.
|
||||
int specialWorkspaceID = 0;
|
||||
|
||||
@@ -68,6 +74,7 @@ class CMonitor {
|
||||
DYNLISTENER(monitorDamage);
|
||||
DYNLISTENER(monitorNeedsFrame);
|
||||
DYNLISTENER(monitorCommit);
|
||||
DYNLISTENER(monitorBind);
|
||||
|
||||
// hack: a group = workspaces on a monitor.
|
||||
// I don't really care lol :P
|
||||
|
@@ -150,13 +150,13 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
|
||||
PNEWSUBSURFACE->pParent = pNode;
|
||||
|
||||
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->surface->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->surface->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
|
||||
PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner;
|
||||
|
||||
if (PSUBSURFACE->mapped)
|
||||
if (PSUBSURFACE->surface->mapped)
|
||||
listener_mapSubsurface(PNEWSUBSURFACE, nullptr);
|
||||
|
||||
wlr_subsurface* existingWlrSubsurface;
|
||||
@@ -229,6 +229,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
|
||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||
|
||||
const double SCALE = pNode->pWindowOwner && pNode->pWindowOwner->m_bIsX11 ? 1.0 / pNode->pWindowOwner->m_fX11SurfaceScaledBy : 1.0;
|
||||
|
||||
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
|
||||
// What this does is that basically, if the pNode is a child of some other node, on commit,
|
||||
// it will also damage (check & damage if needed) all its siblings.
|
||||
@@ -237,12 +239,12 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
|
||||
|
||||
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
|
||||
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
|
||||
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y, SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
if (pNode->pSurface && pNode->pSurface->exists())
|
||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly);
|
||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE);
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||
|
@@ -16,7 +16,7 @@ Vector2D::~Vector2D() {}
|
||||
|
||||
double Vector2D::normalize() {
|
||||
// get max abs
|
||||
const auto max = abs(x) > abs(y) ? abs(x) : abs(y);
|
||||
const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y);
|
||||
|
||||
x /= max;
|
||||
y /= max;
|
||||
@@ -24,16 +24,24 @@ double Vector2D::normalize() {
|
||||
return max;
|
||||
}
|
||||
|
||||
Vector2D Vector2D::floor() {
|
||||
return Vector2D((int)x, (int)y);
|
||||
Vector2D Vector2D::floor() const {
|
||||
return Vector2D(std::floor(x), std::floor(y));
|
||||
}
|
||||
|
||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
|
||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const {
|
||||
return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y));
|
||||
}
|
||||
|
||||
double Vector2D::distance(const Vector2D& other) {
|
||||
double Vector2D::distance(const Vector2D& other) const {
|
||||
double dx = x - other.x;
|
||||
double dy = y - other.y;
|
||||
return std::sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const {
|
||||
const auto a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
||||
const auto b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
||||
const auto c = 1 - a - b;
|
||||
|
||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
||||
}
|
||||
|
@@ -43,9 +43,11 @@ class Vector2D {
|
||||
return Vector2D(this->x / a.x, this->y / a.y);
|
||||
}
|
||||
|
||||
double distance(const Vector2D& other);
|
||||
double distance(const Vector2D& other) const;
|
||||
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;
|
||||
|
||||
Vector2D floor();
|
||||
Vector2D floor() const;
|
||||
|
||||
bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
|
||||
};
|
||||
|
@@ -10,14 +10,25 @@ SLayerSurface::SLayerSurface() {
|
||||
void SLayerSurface::applyRules() {
|
||||
noAnimations = false;
|
||||
forceBlur = false;
|
||||
ignoreZero = false;
|
||||
ignoreAlpha = false;
|
||||
ignoreAlphaValue = 0.f;
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
||||
if (rule.rule == "noanim")
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
forceBlur = true;
|
||||
else if (rule.rule == "ignorezero")
|
||||
ignoreZero = true;
|
||||
else if (rule.rule.find("ignorealpha") == 0 || rule.rule.find("ignorezero") == 0) {
|
||||
const auto FIRST_SPACE_POS = rule.rule.find_first_of(' ');
|
||||
std::string alphaValue = "";
|
||||
if (FIRST_SPACE_POS != std::string::npos)
|
||||
alphaValue = rule.rule.substr(FIRST_SPACE_POS + 1);
|
||||
|
||||
try {
|
||||
ignoreAlpha = true;
|
||||
if (!alphaValue.empty())
|
||||
ignoreAlphaValue = std::stof(alphaValue);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,6 +21,8 @@ struct SLayerSurface {
|
||||
wlr_layer_surface_v1* layerSurface;
|
||||
wl_list link;
|
||||
|
||||
bool keyboardExclusive = false;
|
||||
|
||||
CWLSurface surface;
|
||||
std::list<CWLSurface> popupSurfaces;
|
||||
|
||||
@@ -47,7 +49,8 @@ struct SLayerSurface {
|
||||
bool noAnimations = false;
|
||||
|
||||
bool forceBlur = false;
|
||||
bool ignoreZero = false;
|
||||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerSurface& rhs) const {
|
||||
|
@@ -36,7 +36,7 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||
m_vRenderOffset.registerVar();
|
||||
m_fAlpha.registerVar();
|
||||
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ CWorkspace::~CWorkspace() {
|
||||
m_pWlrHandle = nullptr;
|
||||
}
|
||||
|
||||
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
|
||||
g_pEventManager->postEvent({"destroyworkspace", m_szName});
|
||||
EMIT_HOOK_EVENT("destroyWorkspace", this);
|
||||
}
|
||||
|
||||
|
@@ -112,6 +112,8 @@ struct wlr_xwayland_surface {
|
||||
|
||||
struct wl_signal map;
|
||||
struct wl_signal unmap;
|
||||
struct wl_signal associate;
|
||||
struct wl_signal dissociate;
|
||||
struct wl_signal set_title;
|
||||
struct wl_signal set_class;
|
||||
struct wl_signal set_role;
|
||||
|
@@ -103,8 +103,9 @@ extern "C" {
|
||||
#include <wlr/backend/wayland.h>
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
|
||||
#include <drm_fourcc.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
#if WLR_HAS_X11_BACKEND
|
||||
#include <wlr/backend/x11.h>
|
||||
@@ -145,3 +146,4 @@ extern "C" {
|
||||
#include "helpers/Vector2D.hpp"
|
||||
|
||||
#include "ext-workspace-unstable-v1-protocol.h"
|
||||
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
||||
|
@@ -1,18 +1,24 @@
|
||||
#include "DwindleLayout.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force) {
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||
if (children[0]) {
|
||||
|
||||
const auto REVERSESPLITRATIO = 2.f - splitRatio;
|
||||
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
|
||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
if (*PPRESERVESPLIT == 0) {
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
||||
splitTop = size.y * *PFLMULT > size.x;
|
||||
}
|
||||
|
||||
if (verticalOverride == true)
|
||||
splitTop = true;
|
||||
else if (horizontalOverride == true)
|
||||
splitTop = false;
|
||||
|
||||
const auto SPLITSIDE = !splitTop;
|
||||
|
||||
if (SPLITSIDE) {
|
||||
@@ -119,7 +125,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
||||
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||
auto borderSize = WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
|
||||
auto borderSize =
|
||||
PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
|
||||
if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
|
||||
borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying();
|
||||
|
||||
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
|
||||
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW);
|
||||
@@ -305,16 +314,35 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !g_pKeybindManager->m_bGroupsLocked) {
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked &&
|
||||
!g_pKeybindManager->m_bGroupsLocked) { // target is an unlocked group
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow) { // source is not a group
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pWindow->getGroupHead()->m_sGroupData.locked) { // source is an unlocked group
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If it's not, get the node under our cursor
|
||||
|
||||
m_lDwindleNodesData.push_back(SDwindleNodeData());
|
||||
@@ -336,9 +364,59 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
const auto PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
static auto* const PERMANENTDIRECTIONOVERRIDE = &g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override")->intValue;
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
|
||||
if (*PFORCESPLIT == 0) {
|
||||
bool horizontalOverride = false;
|
||||
bool verticalOverride = false;
|
||||
|
||||
// let user select position -> top, right, bottom, left
|
||||
if (overrideDirection != OneTimeFocus::NOFOCUS) {
|
||||
|
||||
// this is horizontal
|
||||
if (overrideDirection % 2 == 0)
|
||||
verticalOverride = true;
|
||||
else
|
||||
horizontalOverride = true;
|
||||
|
||||
// 0 -> top and left | 1,2 -> right and bottom
|
||||
if (overrideDirection % 3 == 0) {
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
}
|
||||
|
||||
// whether or not the override persists after opening one window
|
||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
overrideDirection = OneTimeFocus::NOFOCUS;
|
||||
} else if (*PSMARTSPLIT == 1) {
|
||||
const auto tl = NEWPARENT->position;
|
||||
const auto tr = NEWPARENT->position + Vector2D(NEWPARENT->size.x, 0);
|
||||
const auto bl = NEWPARENT->position + Vector2D(0, NEWPARENT->size.y);
|
||||
const auto br = NEWPARENT->position + NEWPARENT->size;
|
||||
const auto cc = NEWPARENT->position + NEWPARENT->size / 2;
|
||||
|
||||
if (MOUSECOORDS.inTriangle(tl, tr, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
} else if (MOUSECOORDS.inTriangle(tr, cc, br)) {
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else if (MOUSECOORDS.inTriangle(br, bl, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
}
|
||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
if ((SIDEBYSIDE &&
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f,
|
||||
NEWPARENT->position.y + NEWPARENT->size.y)) ||
|
||||
@@ -373,9 +451,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// Update the children
|
||||
|
||||
if (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y) {
|
||||
// split left/right
|
||||
if (!verticalOverride && (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y || horizontalOverride)) {
|
||||
// split left/right -> forced
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
|
||||
@@ -391,7 +468,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
OPENINGON->pParent = NEWPARENT;
|
||||
PNODE->pParent = NEWPARENT;
|
||||
|
||||
NEWPARENT->recalcSizePosRecursive();
|
||||
NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride);
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
applyNodeDataToWindow(OPENINGON);
|
||||
@@ -511,7 +588,7 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
||||
IHyprLayout::onBeginDragWindow();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
||||
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, CWindow* pWindow) {
|
||||
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
|
||||
@@ -581,62 +658,64 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||
allowedMovement.y = 0;
|
||||
|
||||
// get the correct containers to apply splitratio to
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
// Identify inner and outer nodes for both directions.
|
||||
|
||||
if (!PPARENT)
|
||||
return; // the only window on a workspace, ignore
|
||||
SDwindleNodeData* PVOUTER = nullptr;
|
||||
SDwindleNodeData* PVINNER = nullptr;
|
||||
SDwindleNodeData* PHOUTER = nullptr;
|
||||
SDwindleNodeData* PHINNER = nullptr;
|
||||
|
||||
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
|
||||
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT;
|
||||
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT;
|
||||
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT;
|
||||
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT;
|
||||
const auto NONE = corner == CORNER_NONE;
|
||||
|
||||
// Get the parent's parent
|
||||
auto PPARENT2 = PPARENT->pParent;
|
||||
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
|
||||
const auto PPARENT = PCURRENT->pParent;
|
||||
|
||||
// No parent means we have only 2 windows, and thus one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT)))
|
||||
PVOUTER = PCURRENT;
|
||||
else if (!PVOUTER && !PVINNER && PPARENT->splitTop)
|
||||
PVINNER = PCURRENT;
|
||||
else if (!PHOUTER && !PPARENT->splitTop && (NONE || (LEFT && PPARENT->children[1] == PCURRENT) || (RIGHT && PPARENT->children[0] == PCURRENT)))
|
||||
PHOUTER = PCURRENT;
|
||||
else if (!PHOUTER && !PHINNER && !PPARENT->splitTop)
|
||||
PHINNER = PCURRENT;
|
||||
|
||||
if (PVOUTER && PHOUTER)
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
if (PHOUTER) {
|
||||
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9);
|
||||
|
||||
if (PHINNER) {
|
||||
const auto ORIGINAL = PHINNER->size.x;
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PHINNER->pParent->children[0] == PHINNER)
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
// Get first parent with other split
|
||||
while (PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
|
||||
PPARENT2 = PPARENT2->pParent;
|
||||
if (PVOUTER) {
|
||||
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9);
|
||||
|
||||
// no parent, one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PVINNER) {
|
||||
const auto ORIGINAL = PVINNER->size.y;
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PVINNER->pParent->children[0] == PVINNER)
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 2 axes of freedom
|
||||
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
|
||||
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
|
||||
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
||||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
@@ -811,8 +890,44 @@ void CHyprDwindleLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exa
|
||||
}
|
||||
|
||||
std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||
if (message == "togglesplit")
|
||||
const auto ARGS = CVarList(message, 0, ' ');
|
||||
if (ARGS[0] == "togglesplit") {
|
||||
toggleSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "preselect") {
|
||||
std::string direction = ARGS[1];
|
||||
|
||||
if (direction.empty()) {
|
||||
Debug::log(ERR, "Expected direction for preselect");
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (direction.front()) {
|
||||
case 'u':
|
||||
case 't': {
|
||||
overrideDirection = OneTimeFocus::UP;
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
case 'b': {
|
||||
overrideDirection = OneTimeFocus::DOWN;
|
||||
break;
|
||||
}
|
||||
case 'r': {
|
||||
overrideDirection = OneTimeFocus::RIGHT;
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
overrideDirection = OneTimeFocus::LEFT;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// any other character resets the focus direction
|
||||
// needed for the persistent mode
|
||||
overrideDirection = OneTimeFocus::NOFOCUS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
@@ -9,6 +9,14 @@
|
||||
class CHyprDwindleLayout;
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
enum OneTimeFocus {
|
||||
UP = 0,
|
||||
RIGHT,
|
||||
DOWN,
|
||||
LEFT,
|
||||
NOFOCUS,
|
||||
};
|
||||
|
||||
struct SDwindleNodeData {
|
||||
SDwindleNodeData* pParent = nullptr;
|
||||
bool isNode = false;
|
||||
@@ -34,7 +42,7 @@ struct SDwindleNodeData {
|
||||
children[0] == rhs.children[0] && children[1] == rhs.children[1];
|
||||
}
|
||||
|
||||
void recalcSizePosRecursive(bool force = false);
|
||||
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
|
||||
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
|
||||
CHyprDwindleLayout* layout = nullptr;
|
||||
};
|
||||
@@ -47,7 +55,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateWindow(CWindow*);
|
||||
virtual void onBeginDragWindow();
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
@@ -77,5 +85,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||
|
||||
void toggleSplit(CWindow*);
|
||||
|
||||
OneTimeFocus overrideDirection = OneTimeFocus::NOFOCUS;
|
||||
|
||||
friend struct SDwindleNodeData;
|
||||
};
|
||||
|
@@ -16,6 +16,8 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
|
||||
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
}
|
||||
|
||||
pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize;
|
||||
|
||||
onWindowCreatedTiling(pWindow);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +47,8 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
|
||||
if (pWindow->m_sGroupData.head) {
|
||||
pWindow->m_sGroupData.head = false;
|
||||
curr->m_sGroupData.head = true;
|
||||
curr->m_sGroupData.locked = pWindow->m_sGroupData.locked;
|
||||
pWindow->m_sGroupData.locked = false;
|
||||
}
|
||||
|
||||
if (pWindow == m_pLastTiledWindow)
|
||||
@@ -75,6 +79,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Window %lx (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
|
||||
return;
|
||||
@@ -91,9 +97,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// reject any windows with size <= 5x5
|
||||
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) {
|
||||
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5)
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
|
||||
}
|
||||
|
||||
if (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect) {
|
||||
|
||||
@@ -141,12 +146,16 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
|
||||
// most of these are popups
|
||||
|
||||
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
|
||||
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID)
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
|
||||
} else {
|
||||
else
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
|
||||
}
|
||||
}
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) {
|
||||
pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() / PMONITOR->scale;
|
||||
}
|
||||
|
||||
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
|
||||
@@ -189,8 +198,11 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
m_vDraggingWindowOriginalFloatSize = DRAGGINGWINDOW->m_vLastFloatingSize;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goalv() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor();
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
@@ -229,6 +241,9 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pKeybindManager->shadowKeybinds();
|
||||
|
||||
g_pCompositor->focusWindow(DRAGGINGWINDOW);
|
||||
g_pCompositor->moveWindowToTop(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void IHyprLayout::onEndDragWindow() {
|
||||
@@ -250,11 +265,10 @@ void IHyprLayout::onEndDragWindow() {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
g_pInputManager->refocus();
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pCompositor->focusWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
@@ -279,7 +293,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
||||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
|
||||
*PANIMATEMOUSE))
|
||||
return;
|
||||
|
||||
TIMER = std::chrono::high_resolution_clock::now();
|
||||
@@ -330,7 +345,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,4 +519,13 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||
return PWINDOWCANDIDATE;
|
||||
}
|
||||
|
||||
void IHyprLayout::requestFocusForWindow(CWindow* pWindow) {
|
||||
if (pWindow->isHidden() && pWindow->m_sGroupData.pNextWindow) {
|
||||
// grouped, change the current to this window
|
||||
pWindow->setGroupCurrent(pWindow);
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
}
|
||||
|
||||
IHyprLayout::~IHyprLayout() {}
|
||||
|
@@ -15,9 +15,9 @@ struct SLayoutMessageHeader {
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
enum eRectCorner
|
||||
{
|
||||
CORNER_TOPLEFT = 0,
|
||||
enum eRectCorner {
|
||||
CORNER_NONE = 0,
|
||||
CORNER_TOPLEFT,
|
||||
CORNER_TOPRIGHT,
|
||||
CORNER_BOTTOMRIGHT,
|
||||
CORNER_BOTTOMLEFT
|
||||
@@ -76,7 +76,7 @@ interface IHyprLayout {
|
||||
Vector2D holds pixel values
|
||||
Optional pWindow for a specific window
|
||||
*/
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr) = 0;
|
||||
/*
|
||||
Called when a user requests a move of the current window by a vec
|
||||
Vector2D holds pixel values
|
||||
@@ -148,11 +148,19 @@ interface IHyprLayout {
|
||||
*/
|
||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to) = 0;
|
||||
|
||||
/*
|
||||
Called via the foreign toplevel activation protocol.
|
||||
Focuses a window, bringing it to the top of its group if applicable.
|
||||
May be ignored.
|
||||
*/
|
||||
virtual void requestFocusForWindow(CWindow*);
|
||||
|
||||
private:
|
||||
Vector2D m_vBeginDragXY;
|
||||
Vector2D m_vLastDragXY;
|
||||
Vector2D m_vBeginDragPositionXY;
|
||||
Vector2D m_vBeginDragSizeXY;
|
||||
Vector2D m_vDraggingWindowOriginalFloatSize;
|
||||
eRectCorner m_eGrabbedCorner = CORNER_TOPLEFT;
|
||||
|
||||
CWindow* m_pLastTiledWindow = nullptr;
|
||||
|
@@ -91,17 +91,37 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
getNodeFromWindow(g_pCompositor->m_pLastWindow) :
|
||||
getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && OPENINGON != PNODE && !g_pKeybindManager->m_bGroupsLocked) {
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && !g_pKeybindManager->m_bGroupsLocked &&
|
||||
OPENINGON != PNODE) { // target is an unlocked group
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow) { // source is not a group
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
|
||||
if (!pWindow->getGroupHead()->m_sGroupData.locked) { // source is an unlocked group
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1 || (!pWindow->m_bFirstMap && OPENINGON->isMaster)) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
nd.isMaster = false;
|
||||
@@ -200,6 +220,10 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
@@ -489,7 +513,10 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
|
||||
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
||||
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||
auto borderSize = WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
|
||||
auto borderSize =
|
||||
PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
|
||||
if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
|
||||
borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying();
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
|
||||
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW);
|
||||
@@ -565,7 +592,7 @@ bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) {
|
||||
return getNodeFromWindow(pWindow) != nullptr;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
||||
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, CWindow* pWindow) {
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
|
@@ -9,8 +9,7 @@
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
//orientation determines which side of the screen the master area resides
|
||||
enum eOrientation : uint8_t
|
||||
{
|
||||
enum eOrientation : uint8_t {
|
||||
ORIENTATION_LEFT = 0,
|
||||
ORIENTATION_TOP,
|
||||
ORIENTATION_RIGHT,
|
||||
@@ -52,7 +51,7 @@ class CHyprMasterLayout : public IHyprLayout {
|
||||
virtual bool isWindowTiled(CWindow*);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateWindow(CWindow*);
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, CWindow* pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
|
27
src/main.cpp
27
src/main.cpp
@@ -11,10 +11,6 @@
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
#include <systemd/sd-daemon.h> // for sd_notify
|
||||
#endif
|
||||
|
||||
void help() {
|
||||
std::cout << "usage: Hyprland [arg [...]].\n";
|
||||
std::cout << "\nArguments:\n";
|
||||
@@ -51,8 +47,9 @@ int main(int argc, char** argv) {
|
||||
|
||||
ignoreSudo = true;
|
||||
} else if (it->compare("-c") == 0 || it->compare("--config") == 0) {
|
||||
if (std::next(it)->c_str() == nullptr) {
|
||||
if (std::next(it) == args.end()) {
|
||||
help();
|
||||
|
||||
return 1;
|
||||
}
|
||||
std::string next_arg = std::next(it)->c_str();
|
||||
@@ -70,9 +67,15 @@ int main(int argc, char** argv) {
|
||||
it++;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
} else if (it->compare("-h") == 0 || it->compare("--help") == 0) {
|
||||
help();
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n";
|
||||
help();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,17 +105,5 @@ int main(int argc, char** argv) {
|
||||
// If we are here it means we got yote.
|
||||
Debug::log(LOG, "Hyprland reached the end.");
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
// tell systemd it destroy bound/related units
|
||||
if (sd_booted() > 0)
|
||||
sd_notify(0, "STOPPING=1");
|
||||
#endif
|
||||
|
||||
if (g_pCompositor->m_sWLDisplay)
|
||||
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
||||
|
||||
if (g_pCompositor->m_sWLDisplay)
|
||||
wl_display_destroy(g_pCompositor->m_sWLDisplay);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -111,7 +111,7 @@ void CAnimationManager::tick() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
if (SPENT >= 1.f || av->m_fBegun == av->m_fGoal) {
|
||||
av->warp(false);
|
||||
break;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ void CAnimationManager::tick() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
if (SPENT >= 1.f || av->m_vBegun == av->m_vGoal) {
|
||||
av->warp(false);
|
||||
break;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ void CAnimationManager::tick() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
if (SPENT >= 1.f || av->m_cBegun == av->m_cGoal) {
|
||||
av->warp(false);
|
||||
break;
|
||||
}
|
||||
@@ -184,6 +184,9 @@ void CAnimationManager::tick() {
|
||||
if (!VISIBLE)
|
||||
continue;
|
||||
|
||||
if (av->m_fUpdateCallback)
|
||||
av->m_fUpdateCallback(av);
|
||||
|
||||
switch (av->m_eDamagePolicy) {
|
||||
case AVARDAMAGE_ENTIRE: {
|
||||
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
||||
|
@@ -30,6 +30,8 @@ int fdHandleWrite(int fd, uint32_t mask, void* data) {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
};
|
||||
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) {
|
||||
@@ -58,7 +60,7 @@ int fdHandleWrite(int fd, uint32_t mask, void* data) {
|
||||
|
||||
void CEventManager::startThread() {
|
||||
m_tThread = std::thread([&]() {
|
||||
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (SOCKET < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||
@@ -80,7 +82,7 @@ void CEventManager::startThread() {
|
||||
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
|
||||
|
||||
while (1) {
|
||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||
const auto ACCEPTEDCONNECTION = accept4(SOCKET, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
if (ACCEPTEDCONNECTION > 0) {
|
||||
// new connection!
|
||||
@@ -108,7 +110,9 @@ void CEventManager::flushEvents() {
|
||||
for (auto& ev : m_dQueuedEvents) {
|
||||
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
|
||||
for (auto& fd : m_dAcceptedSocketFDs) {
|
||||
try {
|
||||
write(fd.first, eventString.c_str(), eventString.length());
|
||||
} catch(...) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,9 +121,9 @@ void CEventManager::flushEvents() {
|
||||
eventQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
|
||||
void CEventManager::postEvent(const SHyprIPCEvent event) {
|
||||
|
||||
if ((m_bIgnoreEvents && !force) || g_pCompositor->m_bIsShuttingDown) {
|
||||
if (g_pCompositor->m_bIsShuttingDown) {
|
||||
Debug::log(WARN, "Suppressed (ignoreevents true / shutting down) event of type %s, content: %s", event.event.c_str(), event.data.c_str());
|
||||
return;
|
||||
}
|
||||
|
@@ -15,14 +15,11 @@ class CEventManager {
|
||||
public:
|
||||
CEventManager();
|
||||
|
||||
void postEvent(const SHyprIPCEvent event, bool force = false);
|
||||
void postEvent(const SHyprIPCEvent event);
|
||||
|
||||
void startThread();
|
||||
|
||||
bool m_bIgnoreEvents = false;
|
||||
|
||||
std::thread m_tThread;
|
||||
|
||||
private:
|
||||
void flushEvents();
|
||||
|
||||
|
@@ -32,6 +32,7 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["centerwindow"] = centerWindow;
|
||||
m_mDispatchers["togglegroup"] = toggleGroup;
|
||||
m_mDispatchers["changegroupactive"] = changeGroupActive;
|
||||
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
|
||||
m_mDispatchers["togglesplit"] = toggleSplit;
|
||||
m_mDispatchers["splitratio"] = alterSplitRatio;
|
||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||
@@ -63,6 +64,7 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
|
||||
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
|
||||
m_mDispatchers["lockgroups"] = lockGroups;
|
||||
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
|
||||
m_mDispatchers["moveintogroup"] = moveIntoGroup;
|
||||
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
|
||||
m_mDispatchers["global"] = global;
|
||||
@@ -100,6 +102,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
|
||||
|
||||
uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||
uint32_t modMask = 0;
|
||||
std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper);
|
||||
if (mods.contains("SHIFT"))
|
||||
modMask |= WLR_MODIFIER_SHIFT;
|
||||
if (mods.contains("CAPS"))
|
||||
@@ -187,12 +190,14 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
const auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(monitor->activeWorkspace);
|
||||
const auto PNEWMAINWORKSPACE = g_pCompositor->getWorkspaceByID(monitor->activeWorkspace);
|
||||
|
||||
g_pCompositor->setActiveMonitor(monitor);
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
PNEWWORKSPACE->rememberPrevWorkspace(PWORKSPACE);
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWMAINWORKSPACE->m_pWlrHandle);
|
||||
PNEWMAINWORKSPACE->setActive(true);
|
||||
PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE);
|
||||
|
||||
const auto PNEWWORKSPACE = monitor->specialWorkspaceID != 0 ? g_pCompositor->getWorkspaceByID(monitor->specialWorkspaceID) : PNEWMAINWORKSPACE;
|
||||
|
||||
const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
|
||||
if (PNEWWINDOW) {
|
||||
@@ -404,13 +409,15 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
// small TODO: fix 0-9 keys and other modified ones with shift
|
||||
|
||||
if (keysym != KBKEY && keysym != KBKEYUPPER)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pressed && k.release) {
|
||||
if (k.nonConsuming)
|
||||
return false;
|
||||
|
||||
// suppress down event
|
||||
m_kHeldBack = keysym;
|
||||
return true;
|
||||
@@ -449,6 +456,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay);
|
||||
}
|
||||
|
||||
if (!k.nonConsuming)
|
||||
found = true;
|
||||
}
|
||||
|
||||
@@ -814,6 +822,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
if (pWorkspaceToChangeTo->m_bIsSpecialWorkspace) {
|
||||
PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo);
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -837,6 +846,8 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
}
|
||||
|
||||
pWorkspaceToChangeTo->m_sPrevWorkspace = {PCURRENTWORKSPACE->m_iID, PCURRENTWORKSPACE->m_szName};
|
||||
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
void CKeybindManager::fullscreenActive(std::string args) {
|
||||
@@ -880,23 +891,31 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
CMonitor* pMonitor = nullptr;
|
||||
const auto POLDWS = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
if (pWorkspace) {
|
||||
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
g_pCompositor->setActiveMonitor(PMONITOR);
|
||||
PMONITOR->changeWorkspace(pWorkspace);
|
||||
pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
g_pCompositor->setActiveMonitor(pMonitor);
|
||||
} else {
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
||||
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
|
||||
PMONITOR->changeWorkspace(pWorkspace);
|
||||
}
|
||||
|
||||
POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID);
|
||||
|
||||
pMonitor->changeWorkspace(pWorkspace);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
|
||||
if (*PALLOWWORKSPACECYCLES)
|
||||
pWorkspace->m_sPrevWorkspace = {POLDWS->m_iID, POLDWS->m_szName};
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
@@ -977,6 +996,9 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
g_pInputManager->m_pForcedFocus = nullptr;
|
||||
|
||||
if (PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) {
|
||||
// event
|
||||
@@ -991,7 +1013,8 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
}
|
||||
};
|
||||
|
||||
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, arg == 'u' || arg == 't' || arg == 'r') :
|
||||
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ?
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
// Found window in direction, switch to it
|
||||
@@ -1134,7 +1157,7 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
||||
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
if (PWINDOWTOCHANGETO && PWINDOWTOCHANGETO->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID) {
|
||||
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
|
||||
g_pCompositor->warpCursorTo(PLASTWINDOW->m_vRealPosition.vec() + PLASTWINDOW->m_vRealSize.vec() / 2.0);
|
||||
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->m_vRealPosition.vec() + PWINDOWTOCHANGETO->m_vRealSize.vec() / 2.0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1154,13 +1177,17 @@ void CKeybindManager::toggleGroup(std::string args) {
|
||||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
if (!PWINDOW->m_sGroupData.pNextWindow) {
|
||||
PWINDOW->m_sGroupData.pNextWindow = PWINDOW;
|
||||
PWINDOW->m_sGroupData.head = true;
|
||||
PWINDOW->m_sGroupData.locked = false;
|
||||
|
||||
PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(PWINDOW));
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW);
|
||||
} else {
|
||||
if (PWINDOW->m_sGroupData.pNextWindow == PWINDOW) {
|
||||
PWINDOW->m_sGroupData.pNextWindow = nullptr;
|
||||
@@ -1183,10 +1210,13 @@ void CKeybindManager::toggleGroup(std::string args) {
|
||||
w->m_sGroupData.head = false;
|
||||
}
|
||||
|
||||
bool prevState = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
for (auto& w : members) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
g_pKeybindManager->m_bGroupsLocked = prevState;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1553,6 +1583,9 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
|
||||
if (SIZ.x < 1 || SIZ.y < 1)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
|
||||
if (g_pCompositor->m_pLastWindow->m_vRealSize.goalv().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goalv().y > 1)
|
||||
@@ -1605,7 +1638,10 @@ void CKeybindManager::resizeWindow(std::string args) {
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
|
||||
if (SIZ.x < 1 || SIZ.y < 1)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), CORNER_NONE, PWINDOW);
|
||||
|
||||
if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1)
|
||||
PWINDOW->setHidden(false);
|
||||
@@ -1801,9 +1837,8 @@ void CKeybindManager::dpms(std::string arg) {
|
||||
bool enable = arg.find("on") == 0;
|
||||
std::string port = "";
|
||||
|
||||
if (arg.find_first_of(' ') != std::string::npos) {
|
||||
if (arg.find_first_of(' ') != std::string::npos)
|
||||
port = arg.substr(arg.find_first_of(' ') + 1);
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
|
||||
@@ -1866,7 +1901,7 @@ void CKeybindManager::swapActiveWorkspaces(std::string args) {
|
||||
const auto PMON1 = g_pCompositor->getMonitorFromString(MON1);
|
||||
const auto PMON2 = g_pCompositor->getMonitorFromString(MON2);
|
||||
|
||||
if (!PMON1 || !PMON2)
|
||||
if (!PMON1 || !PMON2 || PMON1 == PMON2)
|
||||
return;
|
||||
|
||||
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
|
||||
@@ -1876,11 +1911,10 @@ void CKeybindManager::pinActive(std::string args) {
|
||||
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args != "" && args != "active" && args.length() > 1) {
|
||||
if (args != "" && args != "active" && args.length() > 1)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
} else {
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
}
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "pin: window not found");
|
||||
@@ -1957,13 +1991,30 @@ void CKeybindManager::fakeFullscreenActive(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::lockGroups(std::string args) {
|
||||
if (args == "lock" || args.empty() || args == "lockgroups") {
|
||||
if (args == "lock" || args.empty() || args == "lockgroups")
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
} else if (args == "toggle") {
|
||||
else if (args == "toggle")
|
||||
g_pKeybindManager->m_bGroupsLocked = !g_pKeybindManager->m_bGroupsLocked;
|
||||
} else {
|
||||
else
|
||||
g_pKeybindManager->m_bGroupsLocked = false;
|
||||
}
|
||||
|
||||
void CKeybindManager::lockActiveGroup(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow)
|
||||
return;
|
||||
|
||||
const auto PHEAD = PWINDOW->getGroupHead();
|
||||
|
||||
if (args == "lock")
|
||||
PHEAD->m_sGroupData.locked = true;
|
||||
else if (args == "toggle")
|
||||
PHEAD->m_sGroupData.locked = !PHEAD->m_sGroupData.locked;
|
||||
else
|
||||
PHEAD->m_sGroupData.locked = false;
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
@@ -1984,11 +2035,19 @@ void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
if (!PWINDOWINDIR || !PWINDOWINDIR->m_sGroupData.pNextWindow)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
if (!PWINDOW->m_sGroupData.pNextWindow)
|
||||
PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(PWINDOW));
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); // This removes groupped property!
|
||||
|
||||
PWINDOW->m_sGroupData.locked = false;
|
||||
PWINDOW->m_sGroupData.head = false;
|
||||
|
||||
PWINDOWINDIR->insertWindowToGroup(PWINDOW);
|
||||
|
||||
PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(PWINDOW));
|
||||
PWINDOWINDIR->setGroupCurrent(PWINDOW);
|
||||
PWINDOW->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW);
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
@@ -2020,3 +2079,16 @@ void CKeybindManager::global(std::string args) {
|
||||
|
||||
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveGroupWindow(std::string args) {
|
||||
const auto BACK = args == "b" || args == "prev";
|
||||
|
||||
if (!g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow)
|
||||
return;
|
||||
|
||||
if ((!BACK && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && g_pCompositor->m_pLastWindow->m_sGroupData.head))
|
||||
std::swap(g_pCompositor->m_pLastWindow->m_sGroupData.head, g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow->m_sGroupData.head);
|
||||
else
|
||||
g_pCompositor->m_pLastWindow->switchWithWindowInGroup(BACK ? g_pCompositor->m_pLastWindow->getGroupPrevious() : g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow);
|
||||
g_pCompositor->m_pLastWindow->updateWindowDecos();
|
||||
}
|
||||
|
@@ -21,12 +21,14 @@ struct SKeybind {
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
};
|
||||
|
||||
enum eFocusWindowMode {
|
||||
enum eFocusWindowMode
|
||||
{
|
||||
MODE_CLASS_REGEX = 0,
|
||||
MODE_TITLE_REGEX,
|
||||
MODE_ADDRESS,
|
||||
@@ -140,8 +142,10 @@ class CKeybindManager {
|
||||
static void mouse(std::string);
|
||||
static void bringActiveToTop(std::string);
|
||||
static void lockGroups(std::string);
|
||||
static void lockActiveGroup(std::string);
|
||||
static void moveIntoGroup(std::string);
|
||||
static void moveOutOfGroup(std::string);
|
||||
static void moveGroupWindow(std::string);
|
||||
static void global(std::string);
|
||||
|
||||
friend class CCompositor;
|
||||
|
@@ -42,9 +42,8 @@ bool CLayoutManager::removeLayout(IHyprLayout* layout) {
|
||||
if (IT == m_vLayouts.end() || IT->first == "dwindle" || IT->first == "master")
|
||||
return false;
|
||||
|
||||
if (m_iCurrentLayoutID == IT - m_vLayouts.begin()) {
|
||||
if (m_iCurrentLayoutID == IT - m_vLayouts.begin())
|
||||
switchToLayout("dwindle");
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Removed a layout %s at %lx", IT->first.c_str(), layout);
|
||||
|
||||
|
@@ -1,9 +1,13 @@
|
||||
#include "ProtocolManager.hpp"
|
||||
|
||||
#include "xdg-output-unstable-v1-protocol.h"
|
||||
|
||||
CProtocolManager::CProtocolManager() {
|
||||
m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>();
|
||||
m_pFractionalScaleProtocolManager = std::make_unique<CFractionalScaleProtocolManager>();
|
||||
m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>();
|
||||
m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>();
|
||||
m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>();
|
||||
|
||||
m_pXDGOutputProtocol = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput");
|
||||
}
|
@@ -6,16 +6,21 @@
|
||||
#include "../protocols/TextInputV1.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../protocols/Screencopy.hpp"
|
||||
#include "../protocols/XDGOutput.hpp"
|
||||
|
||||
class CProtocolManager {
|
||||
public:
|
||||
CProtocolManager();
|
||||
|
||||
// TODO: rewrite to use the new protocol framework
|
||||
std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager;
|
||||
std::unique_ptr<CFractionalScaleProtocolManager> m_pFractionalScaleProtocolManager;
|
||||
std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager;
|
||||
std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager;
|
||||
std::unique_ptr<CScreencopyProtocolManager> m_pScreencopyProtocolManager;
|
||||
|
||||
// New protocols
|
||||
std::unique_ptr<CXDGOutputProtocol> m_pXDGOutputProtocol;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CProtocolManager> g_pProtocolManager;
|
||||
|
@@ -44,7 +44,9 @@ static void handleSurfaceDestroy(void* owner, void* data) {
|
||||
|
||||
void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
|
||||
if (m_sSessionLock.active) {
|
||||
static auto* const PALLOWRELOCK = &g_pConfigManager->getConfigValuePtr("misc:allow_session_lock_restore")->intValue;
|
||||
|
||||
if (m_sSessionLock.active && (!*PALLOWRELOCK || m_sSessionLock.pWlrLock)) {
|
||||
Debug::log(LOG, "Attempted to lock a locked session!");
|
||||
wlr_session_lock_v1_destroy(pWlrLock);
|
||||
return;
|
||||
@@ -75,7 +77,7 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
|
||||
wlr_session_lock_surface_v1_configure(PWLRSURFACE, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
|
||||
PSURFACE->hyprListener_map.initCallback(&PWLRSURFACE->events.map, &handleSurfaceMap, PSURFACE, "SSessionLockSurface");
|
||||
PSURFACE->hyprListener_map.initCallback(&PWLRSURFACE->surface->events.map, &handleSurfaceMap, PSURFACE, "SSessionLockSurface");
|
||||
PSURFACE->hyprListener_destroy.initCallback(&PWLRSURFACE->events.destroy, &handleSurfaceDestroy, PSURFACE, "SSessionLockSurface");
|
||||
PSURFACE->hyprListener_commit.initCallback(&PWLRSURFACE->surface->events.commit, &handleSurfaceCommit, PSURFACE, "SSessionLockSurface");
|
||||
},
|
||||
@@ -113,6 +115,8 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
m_sSessionLock.pWlrLock = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
},
|
||||
|
@@ -1,6 +1,11 @@
|
||||
#include "XWaylandManager.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../events/Events.hpp"
|
||||
#include "xdg-output-unstable-v1-protocol.h"
|
||||
|
||||
#define OUTPUT_MANAGER_VERSION 3
|
||||
#define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3
|
||||
#define OUTPUT_DESCRIPTION_MUTABLE_SINCE_VERSION 3
|
||||
|
||||
CHyprXWaylandManager::CHyprXWaylandManager() {
|
||||
#ifndef NO_XWAYLAND
|
||||
@@ -36,10 +41,9 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
|
||||
return;
|
||||
|
||||
if (wlr_xdg_surface_try_from_wlr_surface(pSurface)) {
|
||||
const auto PSURF = wlr_xdg_surface_try_from_wlr_surface(pSurface);
|
||||
if (PSURF && PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
|
||||
if (const auto PSURF = wlr_xdg_surface_try_from_wlr_surface(pSurface); PSURF && PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate);
|
||||
}
|
||||
|
||||
} else if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) {
|
||||
wlr_xwayland_surface_activate(wlr_xwayland_surface_try_from_wlr_surface(pSurface), activate);
|
||||
|
||||
@@ -84,10 +88,9 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox)
|
||||
pbox->width = pWindow->m_uSurface.xwayland->width;
|
||||
pbox->height = pWindow->m_uSurface.xwayland->height;
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) {
|
||||
if (!pWindow->m_bIsMapped)
|
||||
@@ -123,21 +126,19 @@ std::string CHyprXWaylandManager::getAppIDClass(CWindow* pWindow) {
|
||||
if (pWindow->m_uSurface.xdg->toplevel && pWindow->m_uSurface.xdg->toplevel->app_id) {
|
||||
return std::string(pWindow->m_uSurface.xdg->toplevel->app_id);
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
return "";
|
||||
}
|
||||
} catch (std::logic_error& e) { Debug::log(ERR, "Error in getAppIDClass: %s", e.what()); }
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsX11) {
|
||||
if (pWindow->m_bIsX11)
|
||||
wlr_xwayland_surface_close(pWindow->m_uSurface.xwayland);
|
||||
} else {
|
||||
else
|
||||
wlr_xdg_toplevel_send_close(pWindow->m_uSurface.xdg->toplevel);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) {
|
||||
|
||||
@@ -148,8 +149,21 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec();
|
||||
pWindow->m_vReportedSize = size;
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR) {
|
||||
size = size * PMONITOR->scale;
|
||||
pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
}
|
||||
|
||||
const Vector2D POS = *PXWLFORCESCALEZERO && pWindow->m_bIsX11 ? pWindow->m_vRealPosition.vec() * pWindow->m_fX11SurfaceScaledBy : pWindow->m_vRealPosition.vec();
|
||||
|
||||
if (pWindow->m_bIsX11)
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, POS.x, POS.y, size.x, size.y);
|
||||
else
|
||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y);
|
||||
}
|
||||
@@ -204,9 +218,8 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pWindow->m_iX11Type == 2) {
|
||||
if (pWindow->m_iX11Type == 2)
|
||||
return true; // override_redirect
|
||||
}
|
||||
|
||||
const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints;
|
||||
if (SIZEHINTS && (pWindow->m_uSurface.xwayland->parent || ((SIZEHINTS->min_width == SIZEHINTS->max_width) && (SIZEHINTS->min_height == SIZEHINTS->max_height))))
|
||||
@@ -226,10 +239,11 @@ void CHyprXWaylandManager::moveXWaylandWindow(CWindow* pWindow, const Vector2D&
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsX11) {
|
||||
if (!pWindow->m_bIsX11)
|
||||
return;
|
||||
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::checkBorders(CWindow* pWindow) {
|
||||
if (!pWindow->m_bIsX11)
|
||||
@@ -255,11 +269,10 @@ void CHyprXWaylandManager::checkBorders(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen) {
|
||||
if (pWindow->m_bIsX11) {
|
||||
if (pWindow->m_bIsX11)
|
||||
wlr_xwayland_surface_set_fullscreen(pWindow->m_uSurface.xwayland, fullscreen);
|
||||
} else {
|
||||
else
|
||||
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
|
||||
}
|
||||
|
||||
if (pWindow->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../Window.hpp"
|
||||
#include <optional>
|
||||
|
||||
class CHyprXWaylandManager {
|
||||
public:
|
||||
|
@@ -42,10 +42,10 @@ void CInputManager::recheckIdleInhibitorStatus() {
|
||||
|
||||
for (auto& ii : m_lIdleInhibitors) {
|
||||
if (!ii.pWindow) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
g_pCompositor->setIdleActivityInhibit(false);
|
||||
return;
|
||||
} else if (g_pHyprRenderer->shouldRenderWindow(ii.pWindow)) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
g_pCompositor->setIdleActivityInhibit(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -56,21 +56,21 @@ void CInputManager::recheckIdleInhibitorStatus() {
|
||||
continue;
|
||||
|
||||
if (w->m_eIdleInhibitMode == IDLEINHIBIT_ALWAYS) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
g_pCompositor->setIdleActivityInhibit(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FOCUS && g_pCompositor->isWindowActive(w.get())) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
g_pCompositor->setIdleActivityInhibit(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->m_bIsFullscreen && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID)) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
g_pCompositor->setIdleActivityInhibit(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, true);
|
||||
g_pCompositor->setIdleActivityInhibit(true);
|
||||
return;
|
||||
}
|
@@ -91,9 +91,26 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
// this can happen if there are no displays hooked up to Hyprland
|
||||
if (PMONITOR == nullptr)
|
||||
return;
|
||||
|
||||
if (*PZOOMFACTOR != 1.f)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
||||
CWindow* forcedFocus = m_pForcedFocus;
|
||||
|
||||
if (!forcedFocus)
|
||||
forcedFocus = g_pCompositor->getForceFocus();
|
||||
|
||||
if (forcedFocus) {
|
||||
pFoundWindow = forcedFocus;
|
||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||
foundSurface = pFoundWindow->m_pWLSurface.wlr();
|
||||
}
|
||||
|
||||
// constraints
|
||||
// All constraints TODO: multiple mice?
|
||||
if (g_pCompositor->m_sSeat.mouse && g_pCompositor->m_sSeat.mouse->currentConstraint && !g_pCompositor->m_sSeat.exclusiveClient && !g_pSessionLockManager->isSessionLocked()) {
|
||||
@@ -255,11 +272,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
} else {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
// TODO: this causes crashes, sometimes. ???
|
||||
// if (refocus && !pFoundWindow) {
|
||||
// pFoundWindow = g_pCompositor->getFirstWindowOnWorkspace(PMONITOR->activeWorkspace);
|
||||
// }
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
@@ -288,9 +300,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (g_pHyprRenderer->m_bHasARenderedCursor) {
|
||||
// TODO: maybe wrap?
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
|
||||
else
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
}
|
||||
|
||||
m_bEmptyFocusCursorSet = true;
|
||||
@@ -308,7 +320,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
m_bEmptyFocusCursorSet = false;
|
||||
|
||||
if (time)
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos;
|
||||
|
||||
@@ -320,6 +332,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y);
|
||||
}
|
||||
|
||||
if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero
|
||||
surfaceLocal = surfaceLocal * pFoundWindow->m_fX11SurfaceScaledBy;
|
||||
|
||||
bool allowKeyboardRefocus = true;
|
||||
|
||||
if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) {
|
||||
@@ -357,7 +372,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// if (!m_bCursorImageOverridden) {
|
||||
// if (!VECINRECT(m_vLastCursorPosFloored, pFoundWindow->m_vRealPosition.vec().x, pFoundWindow->m_vRealPosition.vec().y,
|
||||
// pFoundWindow->m_vRealPosition.vec().x + pFoundWindow->m_vRealSize.vec().x, pFoundWindow->m_vRealPosition.vec().y + pFoundWindow->m_vRealSize.vec().y)) {
|
||||
// wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||
// wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
// cursorSurfaceInfo.bUsed = false;
|
||||
// } else if (!cursorSurfaceInfo.bUsed) {
|
||||
// cursorSurfaceInfo.bUsed = true;
|
||||
@@ -417,7 +432,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
EMIT_HOOK_EVENT("mouseButton", e);
|
||||
|
||||
@@ -463,7 +478,7 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
||||
}
|
||||
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL) {
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -489,7 +504,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
case CLICKMODE_DEFAULT:
|
||||
Debug::log(LOG, "SetClickMode: DEFAULT");
|
||||
m_ecbClickBehavior = CLICKMODE_DEFAULT;
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
break;
|
||||
|
||||
case CLICKMODE_KILL:
|
||||
@@ -501,7 +516,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
refocus();
|
||||
|
||||
// set cursor
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -592,7 +607,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
|
||||
bool passEvent = g_pKeybindManager->onAxisEvent(e);
|
||||
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
if (passEvent) {
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source);
|
||||
@@ -624,7 +639,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
const auto PKEYBOARD = (SKeyboard*)owner;
|
||||
const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT}, true); // force as this should ALWAYS be sent
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT});
|
||||
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{PKEYBOARD, (void*)&LAYOUT}));
|
||||
},
|
||||
PNEWKEYBOARD, "Keyboard");
|
||||
@@ -663,7 +678,7 @@ void CInputManager::newVirtualKeyboard(wlr_input_device* keyboard) {
|
||||
const auto PKEYBOARD = (SKeyboard*)owner;
|
||||
const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT}, true); // force as this should ALWAYS be sent
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT});
|
||||
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{PKEYBOARD, (void*)&LAYOUT}));
|
||||
},
|
||||
PNEWKEYBOARD, "Keyboard");
|
||||
@@ -807,7 +822,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
|
||||
const auto LAYOUTSTR = getActiveLayoutForKeyboard(pKeyboard);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUTSTR}, true); // force as this should ALWAYS be sent
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUTSTR});
|
||||
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{pKeyboard, (void*)&LAYOUTSTR}));
|
||||
|
||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
|
||||
@@ -870,24 +885,30 @@ void CInputManager::setPointerConfigs() {
|
||||
if (wlr_input_device_is_libinput(m.mouse)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) ==
|
||||
double touchw = 0, touchh = 0;
|
||||
const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
|
||||
libinput_device_get_size(LIBINPUTDEV, &touchw, &touchh) == 0; // pointer with size is a touchpad
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "clickfinger_behavior", ISTOUCHPAD) : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) ==
|
||||
0) // toggle software buttons or clickfinger
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
else
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "left_handed") : g_pConfigManager->getInt("input:left_handed")) == 0)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "left_handed", ISTOUCHPAD) : g_pConfigManager->getInt("input:left_handed")) == 0)
|
||||
libinput_device_config_left_handed_set(LIBINPUTDEV, 0);
|
||||
else
|
||||
libinput_device_config_left_handed_set(LIBINPUTDEV, 1);
|
||||
|
||||
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "middle_button_emulation", ISTOUCHPAD) :
|
||||
g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
else
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
|
||||
const auto TAP_MAP = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "tap_button_map") : g_pConfigManager->getString("input:touchpad:tap_button_map");
|
||||
const auto TAP_MAP =
|
||||
HASCONFIG ? g_pConfigManager->getDeviceString(devname, "tap_button_map", ISTOUCHPAD) : g_pConfigManager->getString("input:touchpad:tap_button_map");
|
||||
if (TAP_MAP == "" || TAP_MAP == "lrm")
|
||||
libinput_device_config_tap_set_button_map(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_MAP_LRM);
|
||||
else if (TAP_MAP == "lmr")
|
||||
@@ -896,7 +917,7 @@ void CInputManager::setPointerConfigs() {
|
||||
Debug::log(WARN, "Tap button mapping unknown");
|
||||
}
|
||||
|
||||
const auto SCROLLMETHOD = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "scroll_method") : g_pConfigManager->getString("input:scroll_method");
|
||||
const auto SCROLLMETHOD = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "scroll_method", ISTOUCHPAD) : g_pConfigManager->getString("input:scroll_method");
|
||||
if (SCROLLMETHOD == "") {
|
||||
libinput_device_config_scroll_set_method(LIBINPUTDEV, libinput_device_config_scroll_get_default_method(LIBINPUTDEV));
|
||||
} else if (SCROLLMETHOD == "no_scroll") {
|
||||
@@ -911,43 +932,42 @@ void CInputManager::setPointerConfigs() {
|
||||
Debug::log(WARN, "Scroll method unknown");
|
||||
}
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "tap-and-drag") : g_pConfigManager->getInt("input:touchpad:tap-and-drag")) == 0)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "tap-and-drag", ISTOUCHPAD) : g_pConfigManager->getInt("input:touchpad:tap-and-drag")) == 0)
|
||||
libinput_device_config_tap_set_drag_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_DISABLED);
|
||||
else
|
||||
libinput_device_config_tap_set_drag_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_ENABLED);
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "drag_lock", ISTOUCHPAD) : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0)
|
||||
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
|
||||
else
|
||||
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "tap-to-click", ISTOUCHPAD) : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
|
||||
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
|
||||
double w = 0, h = 0;
|
||||
|
||||
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
|
||||
libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
|
||||
if (ISTOUCHPAD)
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(
|
||||
LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
|
||||
LIBINPUTDEV,
|
||||
(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll", ISTOUCHPAD) : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
|
||||
else
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(
|
||||
LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll")));
|
||||
LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "natural_scroll", ISTOUCHPAD) : g_pConfigManager->getInt("input:natural_scroll")));
|
||||
}
|
||||
|
||||
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
|
||||
const auto DWT = static_cast<enum libinput_config_dwt_state>(
|
||||
(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
|
||||
const auto DWT = static_cast<enum libinput_config_dwt_state>((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "disable_while_typing", ISTOUCHPAD) :
|
||||
g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
|
||||
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
|
||||
}
|
||||
|
||||
const auto LIBINPUTSENS =
|
||||
std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(devname, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
|
||||
std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(devname, "sensitivity", ISTOUCHPAD) : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
|
||||
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
|
||||
|
||||
const auto ACCELPROFILE = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "accel_profile") : g_pConfigManager->getString("input:accel_profile");
|
||||
const auto ACCELPROFILE = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "accel_profile", ISTOUCHPAD) : g_pConfigManager->getString("input:accel_profile");
|
||||
|
||||
if (ACCELPROFILE == "") {
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
|
||||
@@ -955,11 +975,24 @@ void CInputManager::setPointerConfigs() {
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
} else if (ACCELPROFILE == "flat") {
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
} else if (ACCELPROFILE.find("custom") == 0) {
|
||||
CVarList args = {ACCELPROFILE, 0, ' '};
|
||||
try {
|
||||
double step = std::stod(args[1]);
|
||||
std::vector<double> points;
|
||||
for (size_t i = 2; i < args.size(); ++i)
|
||||
points.push_back(std::stod(args[i]));
|
||||
|
||||
const auto CONFIG = libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM);
|
||||
libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_MOTION, step, points.size(), points.data());
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM);
|
||||
libinput_config_accel_destroy(CONFIG);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Invalid values in custom accel profile"); }
|
||||
} else {
|
||||
Debug::log(WARN, "Unknown acceleration profile, falling back to default");
|
||||
}
|
||||
|
||||
const auto SCROLLBUTTON = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "scroll_button") : g_pConfigManager->getInt("input:scroll_button");
|
||||
const auto SCROLLBUTTON = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "scroll_button", ISTOUCHPAD) : g_pConfigManager->getInt("input:scroll_button");
|
||||
|
||||
libinput_device_config_scroll_set_button(LIBINPUTDEV, SCROLLBUTTON == 0 ? libinput_device_config_scroll_get_default_button(LIBINPUTDEV) : SCROLLBUTTON);
|
||||
|
||||
@@ -1034,7 +1067,7 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
|
||||
bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard);
|
||||
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
if (passEvent) {
|
||||
|
||||
@@ -1080,7 +1113,7 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||
|
||||
const auto LAYOUT = getActiveLayoutForKeyboard(pKeyboard);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUT}, true); // force as this should ALWAYS be sent
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUT});
|
||||
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{pKeyboard, (void*)&LAYOUT}));
|
||||
}
|
||||
}
|
||||
@@ -1296,7 +1329,7 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||
Debug::log(ERR, "Touch Device had no name???"); // logic error
|
||||
}
|
||||
|
||||
setTouchDeviceConfigs();
|
||||
setTouchDeviceConfigs(PNEWDEV);
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
|
||||
Debug::log(LOG, "New touch device added at %lx", PNEWDEV);
|
||||
@@ -1305,17 +1338,17 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||
&pDevice->events.destroy, [&](void* owner, void* data) { destroyTouchDevice((STouchDevice*)data); }, PNEWDEV, "TouchDevice");
|
||||
}
|
||||
|
||||
void CInputManager::setTouchDeviceConfigs() {
|
||||
for (auto& m : m_lTouchDevices) {
|
||||
const auto PTOUCHDEV = &m;
|
||||
void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
|
||||
|
||||
auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void {
|
||||
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PTOUCHDEV->name);
|
||||
|
||||
if (wlr_input_device_is_libinput(m.pWlrDevice)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.pWlrDevice);
|
||||
if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice);
|
||||
|
||||
const int ROTATION =
|
||||
std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7);
|
||||
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
|
||||
const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output") : g_pConfigManager->getString("input:touchdevice:output");
|
||||
@@ -1324,6 +1357,17 @@ void CInputManager::setTouchDeviceConfigs() {
|
||||
else
|
||||
PTOUCHDEV->boundOutput = "";
|
||||
}
|
||||
};
|
||||
|
||||
if (dev) {
|
||||
setConfig(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& m : m_lTouchDevices) {
|
||||
const auto PTOUCHDEV = &m;
|
||||
|
||||
setConfig(PTOUCHDEV);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1400,7 +1444,7 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
|
||||
}
|
||||
|
||||
void CInputManager::setCursorImageUntilUnset(std::string name) {
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, name.c_str(), g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str());
|
||||
m_bCursorImageOverridden = true;
|
||||
}
|
||||
|
||||
@@ -1410,7 +1454,7 @@ void CInputManager::unsetCursorImage() {
|
||||
|
||||
m_bCursorImageOverridden = false;
|
||||
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide)
|
||||
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
}
|
||||
|
||||
std::string CInputManager::deviceNameToInternalString(std::string in) {
|
||||
|
@@ -7,21 +7,18 @@
|
||||
#include "../../helpers/Timer.hpp"
|
||||
#include "InputMethodRelay.hpp"
|
||||
|
||||
enum eClickBehaviorMode
|
||||
{
|
||||
enum eClickBehaviorMode {
|
||||
CLICKMODE_DEFAULT = 0,
|
||||
CLICKMODE_KILL
|
||||
};
|
||||
|
||||
enum eMouseBindMode
|
||||
{
|
||||
enum eMouseBindMode {
|
||||
MBIND_INVALID = -1,
|
||||
MBIND_MOVE = 0,
|
||||
MBIND_RESIZE
|
||||
};
|
||||
|
||||
enum eBorderIconDirection
|
||||
{
|
||||
enum eBorderIconDirection {
|
||||
BORDERICON_NONE,
|
||||
BORDERICON_UP,
|
||||
BORDERICON_DOWN,
|
||||
@@ -91,7 +88,7 @@ class CInputManager {
|
||||
|
||||
void setKeyboardLayout();
|
||||
void setPointerConfigs();
|
||||
void setTouchDeviceConfigs();
|
||||
void setTouchDeviceConfigs(STouchDevice* dev = nullptr);
|
||||
void setTabletConfigs();
|
||||
|
||||
void updateDragIcon();
|
||||
@@ -114,6 +111,9 @@ class CInputManager {
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
eMouseBindMode dragMode = MBIND_INVALID;
|
||||
|
||||
// for refocus to be forced
|
||||
CWindow* m_pForcedFocus = nullptr;
|
||||
|
||||
SDrag m_sDrag;
|
||||
|
||||
std::list<SConstraint> m_lConstraints;
|
||||
|
@@ -140,8 +140,8 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
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_mapPopup.initCallback(&PNEWPOPUP->pSurface->surface->events.map, &Events::listener_mapInputPopup, PNEWPOPUP, "IME Popup");
|
||||
PNEWPOPUP->hyprListener_unmapPopup.initCallback(&PNEWPOPUP->pSurface->surface->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");
|
||||
@@ -165,7 +165,7 @@ wlr_surface* CInputMethodRelay::focusedSurface(STextInput* pTI) {
|
||||
}
|
||||
|
||||
void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
if (!pPopup->pSurface->mapped)
|
||||
if (!pPopup->pSurface->surface->mapped)
|
||||
return;
|
||||
|
||||
// damage last known pos & size
|
||||
@@ -280,7 +280,7 @@ void CInputMethodRelay::removePopup(SIMEPopup* pPopup) {
|
||||
}
|
||||
|
||||
void CInputMethodRelay::damagePopup(SIMEPopup* pPopup) {
|
||||
if (!pPopup->pSurface->mapped)
|
||||
if (!pPopup->pSurface->surface->mapped)
|
||||
return;
|
||||
|
||||
const auto PFOCUSEDTI = getFocusedTextInput();
|
||||
|
@@ -49,12 +49,13 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
static auto* const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
|
||||
static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
|
||||
static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
|
||||
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue;
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
|
||||
|
||||
// commit
|
||||
std::string wsname = "";
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : "m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : "m+1", wsname);
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname);
|
||||
|
||||
// If we've been swiping off the right end with PSWIPENEW enabled, there is
|
||||
// no workspace there yet, and we need to choose an ID for a new one now.
|
||||
@@ -191,6 +192,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
|
||||
static auto* const PSWIPEFOREVER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_forever")->intValue;
|
||||
static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
|
||||
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue;
|
||||
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
|
||||
|
||||
@@ -200,8 +202,8 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
m_sActiveSwipe.speedPoints++;
|
||||
|
||||
std::string wsname = "";
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : "m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : "m+1", wsname);
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname);
|
||||
|
||||
if ((workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
|
||||
|
@@ -40,12 +40,14 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
case WLR_TABLET_TOOL_TYPE_MOUSE:
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, EVENT->dx, EVENT->dy);
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->m_tmrLastCursorMovement.reset();
|
||||
break;
|
||||
default:
|
||||
double x = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->x : NAN;
|
||||
double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN;
|
||||
wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y);
|
||||
g_pInputManager->refocus();
|
||||
g_pInputManager->m_tmrLastCursorMovement.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -39,8 +39,7 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
} else if (m_sTouchData.touchFocusLS) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_sTouchData.touchFocusLS->geometry.x, m_sTouchData.touchFocusLS->geometry.y) -
|
||||
g_pCompositor->m_pLastMonitor->vecPosition;
|
||||
local = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_sTouchData.touchFocusLS->geometry.x, m_sTouchData.touchFocusLS->geometry.y);
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
} else {
|
||||
@@ -49,7 +48,7 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e->time_msec, e->touch_id, local.x, local.y);
|
||||
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
}
|
||||
|
||||
void CInputManager::onTouchUp(wlr_touch_up_event* e) {
|
||||
@@ -62,8 +61,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
if (m_sTouchData.touchFocusWindow && g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x,
|
||||
PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, 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;
|
||||
|
||||
@@ -72,8 +70,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
} else if (m_sTouchData.touchFocusLS) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID);
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x,
|
||||
PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, 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;
|
||||
|
||||
|
@@ -14,10 +14,9 @@ CFunctionHook::CFunctionHook(HANDLE owner, void* source, void* destination) {
|
||||
}
|
||||
|
||||
CFunctionHook::~CFunctionHook() {
|
||||
if (m_bActive) {
|
||||
if (m_bActive)
|
||||
unhook();
|
||||
}
|
||||
}
|
||||
|
||||
size_t CFunctionHook::getInstructionLenAt(void* start) {
|
||||
ud_t udis;
|
||||
@@ -117,7 +116,8 @@ bool CFunctionHook::hook() {
|
||||
}
|
||||
|
||||
// fixup trampoline addr
|
||||
*(uint64_t*)((uint8_t*)m_pTrampolineAddr + TRAMPOLINE_SIZE - sizeof(ABSOLUTE_JMP_ADDRESS) + ABSOLUTE_JMP_ADDRESS_OFFSET) = (uint64_t)((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS));
|
||||
*(uint64_t*)((uint8_t*)m_pTrampolineAddr + TRAMPOLINE_SIZE - sizeof(ABSOLUTE_JMP_ADDRESS) + ABSOLUTE_JMP_ADDRESS_OFFSET) =
|
||||
(uint64_t)((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS));
|
||||
|
||||
// make jump to hk
|
||||
mprotect((uint8_t*)m_pSource - ((uint64_t)m_pSource) % sysconf(_SC_PAGE_SIZE), sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
@@ -120,6 +120,9 @@ APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, I
|
||||
|
||||
pWindow->m_dWindowDecorations.emplace_back(pDecoration);
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -280,11 +283,11 @@ APICALL std::vector<SFunctionMatch> HyprlandAPI::findFunctionsByName(HANDLE hand
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
static const auto SYMBOLS = execAndGet(("llvm-nm -D -j " + FPATH.string()).c_str());
|
||||
static const auto SYMBOLSDEMANGLED = execAndGet(("llvm-nm -D -j --demangle " + FPATH.string()).c_str());
|
||||
static const auto SYMBOLS = execAndGet(("llvm-nm -D -j \"" + FPATH.string() + "\"").c_str());
|
||||
static const auto SYMBOLSDEMANGLED = execAndGet(("llvm-nm -D -j --demangle \"" + FPATH.string() + "\"").c_str());
|
||||
#else
|
||||
static const auto SYMBOLS = execAndGet(("nm -D -j " + FPATH.string()).c_str());
|
||||
static const auto SYMBOLSDEMANGLED = execAndGet(("nm -D -j --demangle=auto " + FPATH.string()).c_str());
|
||||
static const auto SYMBOLS = execAndGet(("nm -D -j \"" + FPATH.string() + "\"").c_str());
|
||||
static const auto SYMBOLSDEMANGLED = execAndGet(("nm -D -j --demangle=auto \"" + FPATH.string() + "\"").c_str());
|
||||
#endif
|
||||
|
||||
auto demangledFromID = [&](size_t id) -> std::string {
|
||||
@@ -301,6 +304,17 @@ APICALL std::vector<SFunctionMatch> HyprlandAPI::findFunctionsByName(HANDLE hand
|
||||
return SYMBOLSDEMANGLED.substr(pos, SYMBOLSDEMANGLED.find('\n', pos + 1) - pos);
|
||||
};
|
||||
|
||||
if (SYMBOLS.empty()) {
|
||||
Debug::log(ERR, "Unable to search for function \"%s\": no symbols found in binary (is \"%s\" in path?)", name.c_str(),
|
||||
#ifdef __clang__
|
||||
"llvm-nm"
|
||||
#else
|
||||
"nm"
|
||||
#endif
|
||||
);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<SFunctionMatch> matches;
|
||||
|
||||
std::istringstream inStream(SYMBOLS);
|
||||
|
@@ -112,6 +112,9 @@ void CPluginSystem::unloadPlugin(const CPlugin* plugin, bool eject) {
|
||||
Debug::log(LOG, " [PluginSystem] Plugin %s unloaded.", plugin->name.c_str());
|
||||
|
||||
std::erase_if(m_vLoadedPlugins, [&](const auto& other) { return other->m_pHandle == plugin->m_pHandle; });
|
||||
|
||||
// reload config to fix some stuf like e.g. unloadedPluginVars
|
||||
g_pConfigManager->m_bForceReload = true;
|
||||
}
|
||||
|
||||
void CPluginSystem::unloadAllPlugins() {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include "Screencopy.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -234,14 +233,14 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||
}
|
||||
|
||||
if (box.width == 0 && box.height == 0)
|
||||
PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x * PFRAME->pMonitor->scale), (int)(PFRAME->pMonitor->vecSize.y * PFRAME->pMonitor->scale)};
|
||||
PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)};
|
||||
else {
|
||||
PFRAME->box = box;
|
||||
scaleBox(&PFRAME->box, PFRAME->pMonitor->scale);
|
||||
}
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PFRAME->pMonitor->transform, ow, oh);
|
||||
scaleBox(&PFRAME->box, PFRAME->pMonitor->scale);
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
|
||||
@@ -327,15 +326,11 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
|
||||
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
|
||||
m_pLastMonitorBackBuffer = e->buffer;
|
||||
shareAllFrames(pMonitor, true);
|
||||
shareAllFrames(pMonitor);
|
||||
m_pLastMonitorBackBuffer = nullptr;
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
|
||||
shareAllFrames(pMonitor, false);
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf) {
|
||||
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) {
|
||||
if (m_vFramesAwaitingWrite.empty())
|
||||
return; // nothing to share
|
||||
|
||||
@@ -343,12 +338,12 @@ void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf)
|
||||
|
||||
// share frame if correct output
|
||||
for (auto& f : m_vFramesAwaitingWrite) {
|
||||
if (!f->pMonitor) {
|
||||
if (!f->pMonitor || !f->buffer) {
|
||||
framesToRemove.push_back(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f->pMonitor != pMonitor || dmabuf != (f->bufferCap == WLR_BUFFER_CAP_DMABUF))
|
||||
if (f->pMonitor != pMonitor)
|
||||
continue;
|
||||
|
||||
shareFrame(f);
|
||||
@@ -408,9 +403,18 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
|
||||
if (!frame->withDamage)
|
||||
return;
|
||||
|
||||
const auto RECT = pixman_region32_extents(g_pHyprOpenGL->m_RenderData.pDamage);
|
||||
PIXMAN_DAMAGE_FOREACH(&frame->pMonitor->lastFrameDamage) {
|
||||
const auto RECT = &RECTSARR[i];
|
||||
|
||||
if (frame->buffer->width < 1 || frame->buffer->height < 1 || frame->buffer->width - RECT->x1 < 1 || frame->buffer->height - RECT->y1 < 1) {
|
||||
Debug::log(ERR, "[sc] Failed to send damage");
|
||||
break;
|
||||
}
|
||||
|
||||
zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT->x1, 0, frame->buffer->width), std::clamp(RECT->y1, 0, frame->buffer->height),
|
||||
std::clamp(RECT->x2 - RECT->x1, 0, frame->buffer->width - RECT->x1), std::clamp(RECT->y2 - RECT->y1, 0, frame->buffer->height - RECT->y1));
|
||||
std::clamp(RECT->x2 - RECT->x1, 0, frame->buffer->width - RECT->x1),
|
||||
std::clamp(RECT->y2 - RECT->y1, 0, frame->buffer->height - RECT->y1));
|
||||
}
|
||||
}
|
||||
|
||||
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
|
||||
@@ -422,45 +426,17 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
|
||||
|
||||
// render the client
|
||||
const auto PMONITOR = frame->pMonitor;
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10);
|
||||
|
||||
if (!wlr_output_attach_render(PMONITOR->output, nullptr)) {
|
||||
Debug::log(ERR, "[screencopy] Couldn't attach render");
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) {
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto PFORMAT = get_gles2_format_from_drm(format);
|
||||
if (!PFORMAT) {
|
||||
Debug::log(ERR, "[screencopy] Cannot read pixels, unsupported format %lx", PFORMAT);
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true);
|
||||
|
||||
// we should still have the last frame by this point in the original fb
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb);
|
||||
|
||||
glFinish(); // flush
|
||||
|
||||
glReadPixels(frame->box.x, frame->box.y, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iWLROutputFb);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data);
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||
@@ -480,6 +456,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||
|
||||
float color[] = {0, 0, 0, 0};
|
||||
wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, color);
|
||||
// TODO: use hl render methods to use damage
|
||||
wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, sourceTex, glMatrix, 1.0f);
|
||||
|
||||
wlr_texture_destroy(sourceTex);
|
||||
|
@@ -77,7 +77,6 @@ class CScreencopyProtocolManager {
|
||||
|
||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
||||
|
||||
void onRenderEnd(CMonitor* pMonitor);
|
||||
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
|
||||
|
||||
private:
|
||||
@@ -91,7 +90,7 @@ class CScreencopyProtocolManager {
|
||||
|
||||
wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
|
||||
|
||||
void shareAllFrames(CMonitor* pMonitor, bool dmabuf);
|
||||
void shareAllFrames(CMonitor* pMonitor);
|
||||
void shareFrame(SScreencopyFrame* frame);
|
||||
void sendFrameDamage(SScreencopyFrame* frame);
|
||||
bool copyFrameDmabuf(SScreencopyFrame* frame);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include "ToplevelExport.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -312,9 +311,8 @@ void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
|
||||
if (!frame->buffer) {
|
||||
if (!frame->buffer || !g_pCompositor->windowValidMapped(frame->pWindow))
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: damage
|
||||
|
||||
|
75
src/protocols/WaylandProtocol.cpp
Normal file
75
src/protocols/WaylandProtocol.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
CWaylandResource::CWaylandResource(wl_client* client, const wl_interface* wlInterface, uint32_t version, uint32_t id, bool destroyInDestructor) {
|
||||
m_pWLResource = wl_resource_create(client, wlInterface, version, id);
|
||||
|
||||
if (!m_pWLResource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pWLClient = client;
|
||||
m_bDestroyInDestructor = destroyInDestructor;
|
||||
|
||||
Debug::log(LOG, "[wl res %lx] created", m_pWLResource);
|
||||
}
|
||||
|
||||
CWaylandResource::~CWaylandResource() {
|
||||
if (m_pWLResource && m_bDestroyInDestructor)
|
||||
wl_resource_destroy(m_pWLResource);
|
||||
|
||||
Debug::log(LOG, "[wl res %lx] destroyed (wl_resource_destroy %s)", m_pWLResource, (m_pWLResource && m_bDestroyInDestructor ? "sent" : "not sent"));
|
||||
}
|
||||
|
||||
bool CWaylandResource::good() {
|
||||
return resource();
|
||||
}
|
||||
|
||||
wl_resource* CWaylandResource::resource() {
|
||||
return m_pWLResource;
|
||||
}
|
||||
|
||||
uint32_t CWaylandResource::version() {
|
||||
return wl_resource_get_version(m_pWLResource);
|
||||
}
|
||||
|
||||
void CWaylandResource::setImplementation(const void* impl, void* data, wl_resource_destroy_func_t df) {
|
||||
RASSERT(!m_bImplementationSet, "Wayland Resource %lx already has an implementation, cannot re-set!", m_pWLResource);
|
||||
|
||||
wl_resource_set_implementation(m_pWLResource, impl, data, df);
|
||||
|
||||
Debug::log(LOG, "[wl res %lx] set impl to %lx", m_pWLResource, impl);
|
||||
|
||||
m_bImplementationSet = true;
|
||||
}
|
||||
|
||||
static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
((IWaylandProtocol*)data)->bindManager(client, data, ver, id);
|
||||
}
|
||||
|
||||
static void displayDestroyInternal(struct wl_listener* listener, void* data) {
|
||||
((IWaylandProtocol*)data)->onDisplayDestroy();
|
||||
}
|
||||
|
||||
void IWaylandProtocol::onDisplayDestroy() {
|
||||
wl_global_destroy(m_pGlobal);
|
||||
}
|
||||
|
||||
IWaylandProtocol::IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name) {
|
||||
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, iface, ver, this, &bindManagerInternal);
|
||||
|
||||
if (!m_pGlobal) {
|
||||
Debug::log(ERR, "[proto %s] could not create a global", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
m_liDisplayDestroy.notify = displayDestroyInternal;
|
||||
wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy);
|
||||
|
||||
Debug::log(LOG, "[proto %s] started", name.c_str());
|
||||
}
|
||||
|
||||
IWaylandProtocol::~IWaylandProtocol() {
|
||||
onDisplayDestroy();
|
||||
}
|
35
src/protocols/WaylandProtocol.hpp
Normal file
35
src/protocols/WaylandProtocol.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
class CWaylandResource {
|
||||
public:
|
||||
CWaylandResource(wl_client* client, const wl_interface* wlInterface, uint32_t version, uint32_t id, bool destroyInDestructor = false);
|
||||
~CWaylandResource();
|
||||
|
||||
bool good();
|
||||
wl_resource* resource();
|
||||
uint32_t version();
|
||||
|
||||
void setImplementation(const void* impl, void* data, wl_resource_destroy_func_t df);
|
||||
|
||||
private:
|
||||
bool m_bDestroyInDestructor = false;
|
||||
bool m_bImplementationSet = false;
|
||||
wl_client* m_pWLClient = nullptr;
|
||||
wl_resource* m_pWLResource = nullptr;
|
||||
};
|
||||
|
||||
interface IWaylandProtocol {
|
||||
public:
|
||||
IWaylandProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
~IWaylandProtocol();
|
||||
|
||||
virtual void onDisplayDestroy();
|
||||
|
||||
virtual void bindManager(wl_client * client, void* data, uint32_t ver, uint32_t id) = 0;
|
||||
|
||||
private:
|
||||
wl_global* m_pGlobal = nullptr;
|
||||
wl_listener m_liDisplayDestroy;
|
||||
};
|
127
src/protocols/XDGOutput.cpp
Normal file
127
src/protocols/XDGOutput.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "XDGOutput.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#include "xdg-output-unstable-v1-protocol.h"
|
||||
|
||||
#define OUTPUT_MANAGER_VERSION 3
|
||||
#define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3
|
||||
#define OUTPUT_DESCRIPTION_MUTABLE_SINCE_VERSION 3
|
||||
|
||||
static void destroyManagerResource(wl_client* client, wl_resource* resource) {
|
||||
((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onManagerResourceDestroy(resource);
|
||||
// will be destroyed by the destruction of the unique_ptr
|
||||
}
|
||||
|
||||
static void destroyOutputResource(wl_client* client, wl_resource* resource) {
|
||||
((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onOutputResourceDestroy(resource);
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void destroyOutputResourceOnly(wl_resource* resource) {
|
||||
((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onOutputResourceDestroy(resource);
|
||||
}
|
||||
|
||||
static void getXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) {
|
||||
((CXDGOutputProtocol*)wl_resource_get_user_data(resource))->onManagerGetXDGOutput(client, resource, id, outputResource);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static const struct zxdg_output_manager_v1_interface MANAGER_IMPL = {
|
||||
.destroy = destroyManagerResource,
|
||||
.get_xdg_output = getXDGOutput,
|
||||
};
|
||||
|
||||
static const struct zxdg_output_v1_interface OUTPUT_IMPL = {
|
||||
.destroy = destroyOutputResource,
|
||||
};
|
||||
|
||||
void CXDGOutputProtocol::onManagerResourceDestroy(wl_resource* res) {
|
||||
std::erase_if(m_vManagerResources, [&](const auto& other) { return other->resource() == res; });
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::onOutputResourceDestroy(wl_resource* res) {
|
||||
std::erase_if(m_vXDGOutputs, [&](const auto& other) { return !other->resource || other->resource->resource() == res; });
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagerResources.emplace_back(std::make_unique<CWaylandResource>(client, &zxdg_output_manager_v1_interface, ver, id, true)).get();
|
||||
|
||||
if (!RESOURCE->good()) {
|
||||
Debug::log(LOG, "Couldn't bind XDGOutputMgr");
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->setImplementation(&MANAGER_IMPL, this, nullptr);
|
||||
}
|
||||
|
||||
CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
g_pHookSystem->hookDynamic("monitorLayoutChanged", [&](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("configReloaded", [&](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("monitorRemoved", [&](void* self, std::any param) {
|
||||
const auto PMONITOR = std::any_cast<CMonitor*>(param);
|
||||
std::erase_if(m_vXDGOutputs, [&](const auto& other) { return other->monitor == PMONITOR; });
|
||||
});
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) {
|
||||
const auto OUTPUT = wlr_output_from_resource(outputResource);
|
||||
|
||||
if (!OUTPUT)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<SXDGOutput>(PMONITOR)).get();
|
||||
#ifndef NO_XWAYLAND
|
||||
if (g_pXWaylandManager->m_sWLRXWayland->server->client == client)
|
||||
pXDGOutput->isXWayland = true;
|
||||
#endif
|
||||
pXDGOutput->client = client;
|
||||
|
||||
pXDGOutput->resource = std::make_unique<CWaylandResource>(client, &zxdg_output_v1_interface, wl_resource_get_version(resource), id);
|
||||
|
||||
if (!pXDGOutput->resource->good()) {
|
||||
pXDGOutput->resource.release();
|
||||
return;
|
||||
}
|
||||
|
||||
pXDGOutput->resource->setImplementation(&OUTPUT_IMPL, this, destroyOutputResourceOnly);
|
||||
const auto XDGVER = pXDGOutput->resource->version();
|
||||
|
||||
if (XDGVER >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
|
||||
zxdg_output_v1_send_name(pXDGOutput->resource->resource(), PMONITOR->szName.c_str());
|
||||
if (XDGVER >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description)
|
||||
zxdg_output_v1_send_description(pXDGOutput->resource->resource(), PMONITOR->output->description);
|
||||
|
||||
updateOutputDetails(pXDGOutput);
|
||||
|
||||
const auto OUTPUTVER = wl_resource_get_version(outputResource);
|
||||
if (OUTPUTVER >= WL_OUTPUT_DONE_SINCE_VERSION && XDGVER >= OUTPUT_DONE_DEPRECATED_SINCE_VERSION)
|
||||
wl_output_send_done(outputResource);
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
zxdg_output_v1_send_logical_position(pOutput->resource->resource(), pOutput->monitor->vecPosition.x, pOutput->monitor->vecPosition.y);
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pOutput->isXWayland)
|
||||
zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecPixelSize.x, pOutput->monitor->vecPixelSize.y);
|
||||
else
|
||||
zxdg_output_v1_send_logical_size(pOutput->resource->resource(), pOutput->monitor->vecSize.x, pOutput->monitor->vecSize.y);
|
||||
|
||||
if (wl_resource_get_version(pOutput->resource->resource()) < OUTPUT_DONE_DEPRECATED_SINCE_VERSION)
|
||||
zxdg_output_v1_send_done(pOutput->resource->resource());
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::updateAllOutputs() {
|
||||
for (auto& o : m_vXDGOutputs) {
|
||||
updateOutputDetails(o.get());
|
||||
|
||||
wlr_output_schedule_done(o->monitor->output);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user