summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarksome <dev@darkso.me>2022-07-15 19:42:03 +0300
committerDarksome <dev@darkso.me>2022-07-15 19:42:03 +0300
commit5388b54442614cb0d3d445f101e7cd86bf64c125 (patch)
tree26057ff185e423e944e8b250ed7fe26654b69623
parentcb8a6f881b11e9a269fd5f7aa64eafe2beda0b0d (diff)
parent6306d4dae3fa221a6099e109c7faef60bac4fac5 (diff)
Merge upstream
-rw-r--r--.github/workflows/release.yaml38
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt6
-rw-r--r--Makefile17
-rw-r--r--README.md30
-rw-r--r--docs/ISSUE_GUIDELINES.md1
-rw-r--r--example/hyprland.conf5
-rw-r--r--flake.lock12
-rw-r--r--flake.nix13
-rw-r--r--hyprctl/Makefile4
-rw-r--r--hyprctl/main.cpp81
-rw-r--r--meson.build6
-rw-r--r--nix/default.nix5
-rw-r--r--nix/module.nix2
-rw-r--r--src/Compositor.cpp237
-rw-r--r--src/Compositor.hpp22
-rw-r--r--src/Window.cpp13
-rw-r--r--src/Window.hpp5
-rw-r--r--src/config/ConfigManager.cpp141
-rw-r--r--src/config/ConfigManager.hpp3
-rw-r--r--src/config/defaultConfig.hpp6
-rw-r--r--src/debug/HyprCtl.cpp437
-rw-r--r--src/debug/HyprCtl.hpp5
-rw-r--r--src/defines.hpp2
-rw-r--r--src/events/Devices.cpp224
-rw-r--r--src/events/Events.hpp10
-rw-r--r--src/events/Layers.cpp29
-rw-r--r--src/events/Misc.cpp6
-rw-r--r--src/events/Monitors.cpp60
-rw-r--r--src/events/Popups.cpp3
-rw-r--r--src/events/Windows.cpp71
-rw-r--r--src/helpers/AnimatedVariable.hpp6
-rw-r--r--src/helpers/MiscFunctions.cpp6
-rw-r--r--src/helpers/Splashes.hpp56
-rw-r--r--src/helpers/Vector2D.cpp8
-rw-r--r--src/helpers/Vector2D.hpp2
-rw-r--r--src/helpers/WLClasses.hpp50
-rw-r--r--src/helpers/Workspace.hpp1
-rw-r--r--src/hyprerror/HyprError.cpp14
-rw-r--r--src/includes.hpp5
-rw-r--r--src/layout/DwindleLayout.cpp87
-rw-r--r--src/layout/IHyprLayout.cpp24
-rw-r--r--src/main.cpp15
-rw-r--r--src/managers/AnimationManager.cpp12
-rw-r--r--src/managers/KeybindManager.cpp147
-rw-r--r--src/managers/KeybindManager.hpp5
-rw-r--r--src/managers/XWaylandManager.cpp8
-rw-r--r--src/managers/input/IdleInhibitor.cpp54
-rw-r--r--src/managers/input/InputManager.cpp98
-rw-r--r--src/managers/input/InputManager.hpp16
-rw-r--r--src/managers/input/Swipe.cpp152
-rw-r--r--src/managers/input/Tablets.cpp18
-rw-r--r--src/render/Framebuffer.cpp18
-rw-r--r--src/render/Framebuffer.hpp2
-rw-r--r--src/render/OpenGL.cpp55
-rw-r--r--src/render/OpenGL.hpp11
-rw-r--r--src/render/Renderer.cpp135
-rw-r--r--src/render/Renderer.hpp8
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp16
m---------subprojects/wlroots0
60 files changed, 1978 insertions, 547 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 00000000..cb32972f
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,38 @@
+name: Release artifacts
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+jobs:
+ source-tarball:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Hyprland
+ id: checkout
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+
+ - name: Create tarball with submodules
+ id: tar
+ run: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
+
+ - id: whatrelease
+ name: Get latest release
+ uses: pozetroninc/github-action-get-latest-release@master
+ with:
+ owner: hyprwm
+ repo: Hyprland
+ excludes: prerelease, draft
+
+ - name: Upload to release
+ id: upload
+ uses: svenstaro/upload-release-action@v2
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: source.tar.gz
+ asset_name: source-${{ steps.whatrelease.outputs.release }}.tar.gz
+ tag: ${{ steps.whatrelease.outputs.release }}
+ overwrite: true
diff --git a/.gitignore b/.gitignore
index c5ae0678..27b80f06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@ _deps
build/
result
/.vscode/
+.envrc
+.cache
*.o
*-protocol.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 90a23020..06aabd2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,12 +37,12 @@ execute_process(
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
-add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
+add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
-pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon wlroots libinput xcb)
+pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -80,7 +80,7 @@ include(CPack)
target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland
- wlroots
+ ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us
pixman-1
OpenGL
GLESv2
diff --git a/Makefile b/Makefile
index 227d340f..99ac1324 100644
--- a/Makefile
+++ b/Makefile
@@ -107,11 +107,13 @@ all:
cd ./hyprctl && make all && cd ..
install:
- [ ! -d /usr/include/wlr ] || mv /usr/include/wlr /usr/include/wlrBackup
- [ ! -f /usr/lib/libwlroots.so ] || mv /usr/lib/libwlroots.so /usr/lib/libwlroots.so.backup
- [ ! -f /usr/lib/pkgconfig/wlroots.pc ] || mv /usr/lib/pkgconfig/wlroots.pc /usr/lib/pkgconfig/wlroots.pc.backup
+ make clear
+ make fixwlr
+ cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../..
+ make protocols
+ make release
+ cd hyprctl && make all && cd ..
- make all
mkdir -p ${PREFIX}/share/wayland-sessions
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
mkdir -p ${PREFIX}/bin
@@ -122,17 +124,12 @@ install:
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
- rm -rf /usr/include/wlr
- rm -f /usr/lib/libwlroots.so
- rm -f /usr/lib/pkgconfig/wlroots.pc
- [ ! -d /usr/include/wlrBackup ] || mv /usr/include/wlrBackup /usr/include/wlr
- [ ! -f /usr/lib/libwlroots.so.backup ] || mv -f /usr/lib/libwlroots.so.backup /usr/lib/libwlroots.so
- [ ! -f /usr/lib/pkgconfig/wlroots.pc.backup ] || mv -f /usr/lib/pkgconfig/wlroots.pc.backup /usr/lib/pkgconfig/wlroots.pc
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland
rm -f ${PREFIX}/bin/hyprctl
+ rm -f /usr/lib/libwlroots.so.11032
rm -rf ${PREFIX}/share/hyprland
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o
diff --git a/README.md b/README.md
index 3f182556..6f081861 100644
--- a/README.md
+++ b/README.md
@@ -122,18 +122,18 @@ Try it out and report bugs / suggestions!
<!----------------------------------------------------------------------------->
-[Configure]: https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland
+[Configure]: https://github.com/hyprwm/Hyprland/wiki/Configuring-Hyprland
[Discord]: https://discord.gg/hQ9XvMUjjr
-[Stars]: https://starchart.cc/vaxerski/Hyprland
-[Hypr]: https://github.com/vaxerski/Hypr
+[Stars]: https://starchart.cc/hyprwm/Hyprland
+[Hypr]: https://github.com/hyprwm/Hypr
-[Pull Requests]: https://github.com/vaxerski/Hyprland/pulls
-[Issues]: https://github.com/vaxerski/Hyprland/issues
-[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
+[Pull Requests]: https://github.com/hyprwm/Hyprland/pulls
+[Issues]: https://github.com/hyprwm/Hyprland/issues
+[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
-[Contribute]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
-[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
-[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
+[Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
+[Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
+[Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
[License]: LICENSE
@@ -156,12 +156,12 @@ Try it out and report bugs / suggestions!
<!----------------------------------{ Badges }--------------------------------->
-[Badge Workflow]: https://github.com/vaxerski/Hyprland/actions/workflows/ci.yaml/badge.svg
+[Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg
[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
-[Badge Issues]: https://img.shields.io/github/issues/vaxerski/Hyprland
-[Badge Pull Requests]: https://img.shields.io/github/issues-pr/vaxerski/Hyprland
-[Badge Language]: https://img.shields.io/github/languages/top/vaxerski/Hyprland
-[Badge License]: https://img.shields.io/github/license/vaxerski/Hyprland
-[Badge Lines]: https://img.shields.io/tokei/lines/github/vaxerski/Hyprland
+[Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
+[Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
+[Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
+[Badge License]: https://img.shields.io/github/license/hyprwm/Hyprland
+[Badge Lines]: https://img.shields.io/tokei/lines/github/hyprwm/Hyprland
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4
diff --git a/docs/ISSUE_GUIDELINES.md b/docs/ISSUE_GUIDELINES.md
index 60a8ddb1..c7e9933e 100644
--- a/docs/ISSUE_GUIDELINES.md
+++ b/docs/ISSUE_GUIDELINES.md
@@ -26,6 +26,7 @@ If your bug is one that doesn't crash Hyprland, but feels like invalid behavior,
If your bug crashes Hyprland, append additionally:
- The Hyprland log
- Coredump / Coredump analysis (with a stacktrace)
+- Your config
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
diff --git a/example/hyprland.conf b/example/hyprland.conf
index 30c8559e..a42f0550 100644
--- a/example/hyprland.conf
+++ b/example/hyprland.conf
@@ -3,6 +3,11 @@
#
# Refer to the wiki for more information.
+#
+# Please note not all available settings / options are set here.
+# For a full list, see the wiki (basic and advanced configuring)
+#
+
monitor=,1280x720@60,0x0,1
workspace=DP-1,1
diff --git a/flake.lock b/flake.lock
index 2b1f3cec..ca1c9328 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1656239181,
- "narHash": "sha256-wW1xRFBn376yGloXZ4QzBE4hjipMawpV18Lshd9QSPw=",
+ "lastModified": 1657447684,
+ "narHash": "sha256-FCP9AuU1q6PE3vOeM5SFf58f/UKPBAsoSGDUGamNBbo=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5",
+ "rev": "5f43d8b088d3771274bcfb69d3c7435b1121ac88",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
- "lastModified": 1655824477,
- "narHash": "sha256-1kskHOLsnisR3kqIL5IHrQbQG/4xoXxeEf1ExMV6/RU=",
+ "lastModified": 1656865312,
+ "narHash": "sha256-xtQ0zwJZwN8sciruveM10CzKz6TWxBY8SyXa8E4jly4=",
"owner": "wlroots",
"repo": "wlroots",
- "rev": "5c4384a1330faedf975c8b8644881d50390f3613",
+ "rev": "5dc1d4671dd2ca3c1f0f09587c463fdbb542f0a4",
"type": "gitlab"
},
"original": {
diff --git a/flake.nix b/flake.nix
index b1f621fc..5ad90c4a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -32,7 +32,8 @@
src = inputs.wlroots;
});
hyprland = prev.callPackage ./nix/default.nix {
- version = "0.6.2beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
+ stdenv = prev.gcc12Stdenv;
+ version = "0.7.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};
@@ -47,6 +48,16 @@
default = self.packages.${system}.hyprland;
});
+ devShells = genSystems (system: {
+ default = pkgsFor.${system}.mkShell.override {stdenv = pkgsFor.${system}.gcc12Stdenv;} {
+ name = "hyprland-shell";
+ inputsFrom = [
+ self.packages.${system}.wlroots-hyprland
+ self.packages.${system}.hyprland
+ ];
+ };
+ });
+
formatter = genSystems (system: pkgsFor.${system}.alejandra);
nixosModules.default = import ./nix/module.nix self;
diff --git a/hyprctl/Makefile b/hyprctl/Makefile
index 0e997886..cd1df201 100644
--- a/hyprctl/Makefile
+++ b/hyprctl/Makefile
@@ -1,4 +1,4 @@
all:
- g++ -std=c++20 ./main.cpp -o ./hyprctl
+ g++ -std=c++23 ./main.cpp -o ./hyprctl
clean:
- rm ./hyprctl \ No newline at end of file
+ rm ./hyprctl
diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp
index a1a1122d..92ab4f5e 100644
--- a/hyprctl/main.cpp
+++ b/hyprctl/main.cpp
@@ -14,9 +14,11 @@
#include <string>
#include <fstream>
#include <string>
+#include <deque>
-const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
+const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
+commands:
monitors
workspaces
clients
@@ -27,8 +29,13 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
keyword
version
kill
+ splash
hyprpaper
- reload)#";
+ reload
+
+flags:
+ j -> output in JSON
+)#";
void request(std::string arg) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -153,7 +160,7 @@ void dispatchRequest(int argc, char** argv) {
return;
}
- std::string rq = "dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
+ std::string rq = "/dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
request(rq);
}
@@ -180,12 +187,21 @@ void hyprpaperRequest(int argc, char** argv) {
requestHyprpaper(rq);
}
-void batchRequest(int argc, char** argv) {
- std::string rq = "[[BATCH]]" + std::string(argv[2]);
+void batchRequest(std::string arg) {
+ std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
request(rq);
}
+std::deque<std::string> splitArgs(int argc, char** argv) {
+ std::deque<std::string> result;
+
+ for (auto i = 1 /* skip the executable */; i < argc; ++i)
+ result.push_back(std::string(argv[i]));
+
+ return result;
+}
+
int main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c;
@@ -194,20 +210,47 @@ int main(int argc, char** argv) {
return 1;
}
- if (!strcmp(argv[1], "monitors")) request("monitors");
- else if (!strcmp(argv[1], "clients")) request("clients");
- else if (!strcmp(argv[1], "workspaces")) request("workspaces");
- else if (!strcmp(argv[1], "activewindow")) request("activewindow");
- else if (!strcmp(argv[1], "layers")) request("layers");
- else if (!strcmp(argv[1], "version")) request("version");
- else if (!strcmp(argv[1], "kill")) request("kill");
- else if (!strcmp(argv[1], "devices")) request("devices");
- else if (!strcmp(argv[1], "reload")) request("reload");
- else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
- else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
- else if (!strcmp(argv[1], "hyprpaper")) hyprpaperRequest(argc, argv);
- else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
- else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
+ std::string fullRequest = "";
+ std::string fullArgs = "";
+ const auto ARGS = splitArgs(argc, argv);
+
+ for (auto i = 0; i < ARGS.size(); ++i) {
+ if (ARGS[i].contains("-")) {
+ // parse
+ if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
+ fullArgs += "j";
+ } else if (ARGS[i] == "--batch") {
+ fullRequest = "--batch ";
+ } else {
+ printf("%s\n", USAGE.c_str());
+ return 1;
+ }
+
+ continue;
+ }
+
+ fullRequest += ARGS[i] + " ";
+ }
+
+ fullRequest.pop_back(); // remove trailing space
+
+ fullRequest = fullArgs + "/" + fullRequest;
+
+ if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
+ else if (fullRequest.contains("/monitors")) request(fullRequest);
+ else if (fullRequest.contains("/clients")) request(fullRequest);
+ else if (fullRequest.contains("/workspaces")) request(fullRequest);
+ else if (fullRequest.contains("/activewindow")) request(fullRequest);
+ else if (fullRequest.contains("/layers")) request(fullRequest);
+ else if (fullRequest.contains("/version")) request(fullRequest);
+ else if (fullRequest.contains("/kill")) request(fullRequest);
+ else if (fullRequest.contains("/splash")) request(fullRequest);
+ else if (fullRequest.contains("/devices")) request(fullRequest);
+ else if (fullRequest.contains("/reload")) request(fullRequest);
+ else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
+ else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
+ else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
+ else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
else {
printf("%s\n", USAGE.c_str());
return 1;
diff --git a/meson.build b/meson.build
index 00628761..294b1ef6 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,8 @@
project('Hyprland', 'cpp', 'c',
- version : '0.6.2beta',
- default_options : ['warning_level=2', 'cpp_std=c++20', 'default_library=static', 'optimization=3'])
+ version : '0.7.0beta',
+ default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
+
+add_global_arguments('-std=c++23', language: 'cpp')
add_project_arguments(
[
diff --git a/nix/default.nix b/nix/default.nix
index 495345fd..8ad64f2f 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -61,6 +61,11 @@ stdenv.mkDerivation {
./meson-build.patch
];
+ # Fix hardcoded paths to /usr installation
+ postPatch = ''
+ sed -i "s#/usr#$out#" src/render/OpenGL.cpp
+ '';
+
passthru.providedSessions = ["hyprland"];
meta = with lib; {
diff --git a/nix/module.nix b/nix/module.nix
index 383eebb7..a7460b34 100644
--- a/nix/module.nix
+++ b/nix/module.nix
@@ -19,7 +19,7 @@ in {
package = mkOption {
type = types.package;
- default = pkgs.hyprland or self.packages.${pkgs.system}.default;
+ default = self.packages.${pkgs.system}.default;
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
description = ''
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 0d8698a6..da6ba1c5 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -1,4 +1,16 @@
#include "Compositor.hpp"
+#include "helpers/Splashes.hpp"
+#include <random>
+
+int handleCritSignal(int signo, void* data) {
+ Debug::log(LOG, "Hyprland received signal %d", signo);
+
+ if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) {
+ g_pCompositor->cleanup();
+ }
+
+ return 0; // everything went fine
+}
CCompositor::CCompositor() {
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
@@ -22,29 +34,36 @@ CCompositor::CCompositor() {
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://github.com/hyprwm/Hyprland/wiki/Crashing-and-bugs\n\n");
+ setRandomSplash();
+
+ Debug::log(LOG, "\nCurrent splash: %s\n\n", m_szCurrentSplash.c_str());
+
m_sWLDisplay = wl_display_create();
+ m_sWLEventLoop = wl_display_get_event_loop(m_sWLDisplay);
+
+ // register crit signal handler
+ wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
+ //wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
+
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
if (!m_sWLRBackend) {
Debug::log(CRIT, "m_sWLRBackend was NULL!");
- RIP("m_sWLRBackend NULL!");
- return;
+ throw std::runtime_error("wlr_backend_autocreate() failed!");
}
m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
if (m_iDRMFD < 0) {
Debug::log(CRIT, "Couldn't query the DRM FD!");
- RIP("DRMFD NULL!");
- return;
+ throw std::runtime_error("wlr_backend_get_drm_fd() failed!");
}
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
if (!m_sWLRRenderer) {
Debug::log(CRIT, "m_sWLRRenderer was NULL!");
- RIP("m_sWLRRenderer NULL!");
- return;
+ throw std::runtime_error("wlr_gles2_renderer_create_with_drm_fd() failed!");
}
wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay);
@@ -53,16 +72,14 @@ CCompositor::CCompositor() {
if (!m_sWLRAllocator) {
Debug::log(CRIT, "m_sWLRAllocator was NULL!");
- RIP("m_sWLRAllocator NULL!");
- return;
+ throw std::runtime_error("wlr_allocator_autocreate() failed!");
}
m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer);
if (!m_sWLREGL) {
Debug::log(CRIT, "m_sWLREGL was NULL!");
- RIP("m_sWLREGL NULL!");
- return;
+ throw std::runtime_error("wlr_gles2_renderer_get_egl() failed!");
}
m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, m_sWLRRenderer);
@@ -124,17 +141,26 @@ CCompositor::CCompositor() {
m_sWLRForeignRegistry = wlr_xdg_foreign_registry_create(m_sWLDisplay);
+ m_sWLRIdleInhibitMgr = wlr_idle_inhibit_v1_create(m_sWLDisplay);
+
wlr_xdg_foreign_v1_create(m_sWLDisplay, m_sWLRForeignRegistry);
wlr_xdg_foreign_v2_create(m_sWLDisplay, m_sWLRForeignRegistry);
+
+ m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay);
+
+ m_sWLRSession = wlr_backend_get_session(m_sWLRBackend);
}
CCompositor::~CCompositor() {
- cleanupExit();
+ cleanup();
}
-void handleCritSignal(int signo) {
- g_pCompositor->cleanupExit();
- exit(signo);
+void CCompositor::setRandomSplash() {
+ std::random_device dev;
+ std::mt19937 engine(dev());
+ std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1);
+
+ m_szCurrentSplash = SPLASHES[distribution(engine)];
}
void CCompositor::initAllSignals() {
@@ -145,6 +171,9 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.axis, &Events::listen_mouseAxis, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.frame, &Events::listen_mouseFrame, m_sWLRCursor, "WLRCursor");
+ addWLSignal(&m_sWLRCursor->events.swipe_begin, &Events::listen_swipeBegin, m_sWLRCursor, "WLRCursor");
+ addWLSignal(&m_sWLRCursor->events.swipe_update, &Events::listen_swipeUpdate, m_sWLRCursor, "WLRCursor");
+ addWLSignal(&m_sWLRCursor->events.swipe_end, &Events::listen_swipeEnd, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat");
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat");
@@ -160,12 +189,12 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
-
- signal(SIGINT, handleCritSignal);
- signal(SIGTERM, handleCritSignal);
+ addWLSignal(&m_sWLRIdleInhibitMgr->events.new_inhibitor, &Events::listen_newIdleInhibitor, m_sWLRIdleInhibitMgr, "WLRIdleInhibitMgr");
+ if (m_sWLRSession)
+ addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
}
-void CCompositor::cleanupExit() {
+void CCompositor::cleanup() {
if (!m_sWLDisplay)
return;
@@ -180,8 +209,7 @@ void CCompositor::cleanupExit() {
g_pXWaylandManager->m_sWLRXWayland = nullptr;
}
- wl_display_destroy_clients(m_sWLDisplay);
- wl_display_destroy(m_sWLDisplay);
+ wl_display_terminate(m_sWLDisplay);
m_sWLDisplay = nullptr;
}
@@ -245,7 +273,7 @@ void CCompositor::startCompositor() {
if (!m_szWLDisplaySocket) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
wlr_backend_destroy(m_sWLRBackend);
- RIP("m_szWLDisplaySocket NULL!");
+ throw std::runtime_error("m_szWLDisplaySocket was null! (wl_display_add_socket_auto failed)");
}
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
@@ -258,7 +286,7 @@ void CCompositor::startCompositor() {
Debug::log(CRIT, "Backend did not start!");
wlr_backend_destroy(m_sWLRBackend);
wl_display_destroy(m_sWLDisplay);
- RIP("Backend did not start!");
+ throw std::runtime_error("The backend could not start!");
}
wlr_xcursor_manager_set_cursor_image(m_sWLRXCursorMgr, "left_ptr", m_sWLRCursor);
@@ -361,6 +389,12 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
+ for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
+ wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
+ if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden)
+ return (*w).get();
+ }
+
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->m_bHidden)
@@ -404,14 +438,29 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
return nullptr;
}
+void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
+ const auto DATA = (SExtensionFindingData*)data;
+
+ wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
+
+ if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y))
+ *DATA->found = surface;
+}
+
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
+ for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
+ wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
+ if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2)
+ return (*w).get();
+ }
+
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
- if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden)
+ if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && w->m_iX11Type != 2)
return w.get();
}
}
@@ -419,13 +468,37 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
- if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
- return w->get();
+ if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2) {
+ if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
+ return w->get();
+
+ if (!(*w)->m_bIsX11) {
+ wlr_surface* resultSurf = nullptr;
+ Vector2D origin =(*w)->m_vRealPosition.vec();
+ SExtensionFindingData data = {origin, pos, &resultSurf};
+ wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data);
+
+ if (resultSurf)
+ return w->get();
+ }
+ }
}
+ // for windows, we need to check their extensions too, first.
+ for (auto& w : m_vWindows) {
+ if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2) {
+ wlr_surface* resultSurf = nullptr;
+ Vector2D origin = w->m_vRealPosition.vec();
+ SExtensionFindingData data = {origin, pos, &resultSurf};
+ wlr_xdg_surface_for_each_popup_surface(w->m_uSurface.xdg, findExtensionForVector2D, &data);
+
+ if (resultSurf)
+ return w.get();
+ }
+ }
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
- if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden)
+ if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && w->m_iX11Type != 2)
return w.get();
}
@@ -436,6 +509,12 @@ CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) {
+ for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
+ wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
+ if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && !(*w)->m_bHidden)
+ return (*w).get();
+ }
+
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped)
@@ -536,7 +615,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
if (windowValidMapped(PLASTWINDOW)) {
- updateWindowBorderColor(PLASTWINDOW);
+ updateWindowAnimatedDecorationValues(PLASTWINDOW);
if (PLASTWINDOW->m_bIsX11) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
@@ -559,7 +638,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
const auto POINTERLOCAL = g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.goalv();
wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y);
- updateWindowBorderColor(pWindow);
+ updateWindowAnimatedDecorationValues(pWindow);
// Send an event
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
@@ -573,12 +652,16 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == g_pXWaylandManager->getWindowSurface(pWindowOwner)))
return; // Don't focus when already focused on this.
- if (!pSurface)
- return;
-
// Unfocus last surface if should
- if (m_pLastFocus && m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus))
- wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(m_pLastFocus)->toplevel, false);
+ if (m_pLastFocus && ((m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) || !pSurface))
+ g_pXWaylandManager->activateSurface(m_pLastFocus, false);
+
+ if (!pSurface) {
+ wlr_seat_keyboard_clear_focus(m_sSeat.seat);
+ g_pEventManager->postEvent(SHyprIPCEvent("activewindow", ",")); // unfocused
+ return;
+ }
+
const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat);
@@ -598,6 +681,9 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, pWindowOwner->m_szTitle.c_str());
else
Debug::log(LOG, "Set keyboard focus to surface %x", pSurface);
+
+ g_pXWaylandManager->activateSurface(pSurface, false);
+ m_pLastFocus = pSurface;
}
bool CCompositor::windowValidMapped(CWindow* pWindow) {
@@ -689,6 +775,8 @@ void CCompositor::sanityCheckWorkspaces() {
if (it == m_vWorkspaces.end())
break;
+
+ continue;
}
if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) {
@@ -700,6 +788,8 @@ void CCompositor::sanityCheckWorkspaces() {
if (it == m_vWorkspaces.end())
break;
+
+ continue;
}
}
}
@@ -773,9 +863,12 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
}
}
-void CCompositor::cleanupFadingOut() {
+void CCompositor::cleanupFadingOut(const int& monid) {
for (auto& w : m_vWindowsFadingOut) {
+ if (w->m_iMonitorID != (long unsigned int)monid)
+ continue;
+
bool valid = windowExists(w);
if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) {
@@ -788,11 +881,16 @@ void CCompositor::cleanupFadingOut() {
m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
Debug::log(LOG, "Cleanup: destroyed a window");
+
+ glFlush(); // to free mem NOW.
return;
}
}
for (auto& ls : m_vSurfacesFadingOut) {
+ if (ls->monitorID != monid)
+ continue;
+
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLists) {
@@ -808,6 +906,7 @@ void CCompositor::cleanupFadingOut() {
Debug::log(LOG, "Cleanup: destroyed a layersurface");
+ glFlush(); // to free mem NOW.
return;
}
}
@@ -910,6 +1009,29 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
return nullptr;
}
+CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow) {
+ bool gotToWindow = false;
+ for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
+ if (it->get() != pWindow && !gotToWindow)
+ continue;
+
+ if (it->get() == pWindow) {
+ gotToWindow = true;
+ continue;
+ }
+
+ if ((*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
+ return it->get();
+ }
+
+ for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
+ if (it->get() != pWindow && (*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
+ return it->get();
+ }
+
+ return nullptr;
+}
+
int CCompositor::getNextAvailableNamedWorkspace() {
int lowest = -1337 + 1;
for (auto& w : m_vWorkspaces) {
@@ -1032,25 +1154,50 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
return nullptr;
}
-void CCompositor::updateAllWindowsBorders() {
+void CCompositor::updateAllWindowsAnimatedDecorationValues() {
for (auto& w : m_vWindows) {
if (!w->m_bIsMapped)
continue;
- updateWindowBorderColor(w.get());
+ updateWindowAnimatedDecorationValues(w.get());
}
}
-void CCompositor::updateWindowBorderColor(CWindow* pWindow) {
+void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
// optimization
static int64_t* ACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.active_border")->intValue;
static int64_t* INACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->intValue;
+ 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;
+
+ // border
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
if (RENDERDATA.isBorderColor)
pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
else
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL);
+
+
+ // opacity
+ if (pWindow->m_bIsFullscreen) {
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
+
+ if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
+ pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
+ else {
+ if (pWindow == m_pLastWindow)
+ pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
+ else
+ pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
+ }
+ } else {
+ if (pWindow == m_pLastWindow)
+ pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
+ else
+ pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
+ }
}
void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) {
@@ -1188,4 +1335,20 @@ CWindow* CCompositor::getX11Parent(CWindow* pWindow) {
}
return nullptr;
+}
+
+void CCompositor::updateWorkspaceWindowDecos(const int& id) {
+ for (auto& w : m_vWindows) {
+ if (w->m_iWorkspaceID != id)
+ continue;
+
+ w->updateWindowDecos();
+ }
+}
+
+void CCompositor::scheduleFrameForMonitor(SMonitor* pMonitor) {
+ if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive)
+ return;
+
+ wlr_output_schedule_frame(pMonitor->output);
} \ No newline at end of file
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 7ad3b7f8..0500387c 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -30,7 +30,9 @@ public:
// ------------------ WLR BASICS ------------------ //
wl_display* m_sWLDisplay;
+ wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
+ wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
@@ -61,11 +63,14 @@ public:
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
+ wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
+ wlr_pointer_gestures_v1* m_sWLRPointerGestures;
// ------------------------------------------------- //
const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
+ std::string m_szCurrentSplash = "error";
std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
std::vector<std::unique_ptr<CWindow>> m_vWindows;
@@ -77,7 +82,7 @@ public:
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor();
- void cleanupExit();
+ void cleanup();
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
@@ -86,6 +91,7 @@ public:
SSeat m_sSeat;
bool m_bReadyToProcess = false;
+ bool m_bSessionActive = true;
// ------------------------------------------------- //
@@ -99,7 +105,7 @@ public:
bool windowExists(CWindow*);
bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&);
- CWindow* vectorToWindowIdeal(const Vector2D&);
+ CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
@@ -113,6 +119,7 @@ public:
CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
+ void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
void fixXWaylandWindowsOnWorkspace(const int&);
@@ -120,16 +127,17 @@ public:
bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*);
void moveWindowToTop(CWindow*);
- void cleanupFadingOut();
+ void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*);
+ CWindow* getPrevWindowOnWorkspace(CWindow*);
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
SMonitor* getMonitorInDirection(const char&);
- void updateAllWindowsBorders();
- void updateWindowBorderColor(CWindow*);
+ void updateAllWindowsAnimatedDecorationValues();
+ void updateWindowAnimatedDecorationValues(CWindow*);
void moveWindowToWorkspace(CWindow*, const std::string&);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
@@ -137,9 +145,13 @@ public:
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
+ void scheduleFrameForMonitor(SMonitor*);
+
+ std::string explicitConfigPath;
private:
void initAllSignals();
+ void setRandomSplash();
};
diff --git a/src/Window.cpp b/src/Window.cpp
index fc09b330..8c8cd147 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -7,6 +7,7 @@ CWindow::CWindow() {
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
+ m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
}
@@ -77,6 +78,18 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
void CWindow::updateWindowDecos() {
for (auto& wd : m_dWindowDecorations)
wd->updateWindow(this);
+
+ 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);
+ if (it == m_dWindowDecorations.end())
+ break;
+ }
+ }
+ }
+
+ m_vDecosToRemove.clear();
}
pid_t CWindow::getPID() {
diff --git a/src/Window.hpp b/src/Window.hpp
index ca6bcbf6..3bef02b1 100644
--- a/src/Window.hpp
+++ b/src/Window.hpp
@@ -28,6 +28,7 @@ public:
DYNLISTENER(unmapWindow);
DYNLISTENER(destroyWindow);
DYNLISTENER(setTitleWindow);
+ DYNLISTENER(setGeometryX11U);
DYNLISTENER(fullscreenWindow);
DYNLISTENER(newPopupXDG);
// DYNLISTENER(newSubsurfaceWindow);
@@ -99,11 +100,15 @@ public:
// Window decorations
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
+ std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
// Special render data, rules, etc
SWindowSpecialRenderData m_sSpecialRenderData;
SWindowAdditionalConfigData m_sAdditionalConfigData;
+ // for alpha
+ CAnimatedVariable m_fActiveInactiveAlpha;
+
// For the list lookup
bool operator==(const CWindow& rhs) {
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index f313b155..e3db1856 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -12,8 +12,15 @@
CConfigManager::CConfigManager() {
setDefaultVars();
- static const char* const ENVHOME = getenv("HOME");
- const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
+
+ 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);
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
@@ -36,6 +43,10 @@ void CConfigManager::setDefaultVars() {
configValues["general:col.active_border"].intValue = 0xffffffff;
configValues["general:col.inactive_border"].intValue = 0xff444444;
configValues["general:cursor_inactive_timeout"].intValue = 0;
+
+ configValues["misc:disable_hyprland_logo"].intValue = 0;
+ configValues["misc:disable_splash_rendering"].intValue = 0;
+ configValues["misc:no_vfr"].intValue = 1;
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
@@ -66,6 +77,7 @@ void CConfigManager::setDefaultVars() {
configValues["dwindle:force_split"].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["animations:enabled"].intValue = 1;
configValues["animations:speed"].floatValue = 7.f;
@@ -102,6 +114,13 @@ void CConfigManager::setDefaultVars() {
configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
configValues["input:touchpad:middle_button_emulation"].intValue = 0;
configValues["input:touchpad:tap-to-click"].intValue = 1;
+ configValues["input:touchpad:drag_lock"].intValue = 0;
+
+ configValues["gestures:workspace_swipe"].intValue = 0;
+ configValues["gestures:workspace_swipe_distance"].intValue = 300;
+ configValues["gestures:workspace_swipe_invert"].intValue = 1;
+ configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30;
+ configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
configValues["input:follow_mouse"].intValue = 1;
@@ -124,6 +143,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
cfgValues["clickfinger_behavior"].intValue = 0;
cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1;
+ cfgValues["drag_lock"].intValue = 0;
}
void CConfigManager::init() {
@@ -147,17 +167,15 @@ void CConfigManager::init() {
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
if (configValues.find(COMMAND) == configValues.end()) {
- if (COMMAND[0] == '$') {
- // register a dynamic var
- Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
- configDynamicVars[COMMAND.substr(1)] = VALUE;
- } else {
- parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
- }
+ if (COMMAND.find("device:") != 0 /* devices parsed later */) {
+ if (COMMAND[0] == '$') {
+ // register a dynamic var
+ Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
+ configDynamicVars[COMMAND.substr(1)] = VALUE;
+ } else {
+ parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
+ }
- if (COMMAND.find("device:") == 0 /* devices parsed later */) {
- parseError = "";
- } else {
return;
}
}
@@ -191,7 +209,12 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
- } else
+ } else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
+ CONFIGENTRY->intValue = 1;
+ } else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
+ CONFIGENTRY->intValue = 0;
+ }
+ else
CONFIGENTRY->intValue = stol(VALUE);
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
@@ -354,7 +377,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@')));
- if (curitem.find_first_of('@') != std::string::npos)
+ if (curitem.contains("@"))
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
nextItem();
@@ -503,8 +526,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
return;
}
- if (KEY != "")
- g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
+ if (KEY != "") {
+ if (isNumber(KEY) && std::stoi(KEY) > 9)
+ g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
+ else
+ g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
+ }
+
}
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
@@ -550,6 +578,16 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
}
+void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
+ if (value.find("remove,") == 0) {
+ const auto TOREMOVE = value.substr(7);
+ m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
+ return;
+ }
+
+ m_dBlurLSNamespaces.emplace_back(value);
+}
+
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
const auto DISPLAY = value.substr(0, value.find_first_of(','));
@@ -575,6 +613,23 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
auto value = rawpath;
+ if (value.length() < 2) {
+ Debug::log(ERR, "source= path garbage");
+ parseError = "source path " + value + " bogus!";
+ return;
+ }
+
+ if (value[0] == '.') {
+ auto currentDir = configCurrentPath.substr(0, configCurrentPath.find_last_of('/'));
+
+ if (value[1] == '.') {
+ auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
+ value.replace(0, 2, parentDir);
+ } else {
+ value.replace(0, 1, currentDir);
+ }
+ }
+
if (value[0] == '~') {
value.replace(0, 1, std::string(ENVHOME));
}
@@ -651,6 +706,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
+ else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
else
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
@@ -663,7 +719,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update window border colors
- g_pCompositor->updateAllWindowsBorders();
+ g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return retval;
}
@@ -703,7 +759,7 @@ void CConfigManager::parseLine(std::string& line) {
line = line.substr(1);
}
- if (line.find(" {") != std::string::npos) {
+ if (line.contains(" {")) {
auto cat = line.substr(0, line.find(" {"));
transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
if (currentCategory.length() != 0) {
@@ -717,7 +773,7 @@ void CConfigManager::parseLine(std::string& line) {
return;
}
- if (line.find("}") != std::string::npos && currentCategory != "") {
+ if (line.contains("}") && currentCategory != "") {
currentCategory = "";
return;
}
@@ -753,32 +809,42 @@ void CConfigManager::loadConfigLoadVars() {
m_mAdditionalReservedAreas.clear();
configDynamicVars.clear();
deviceConfigs.clear();
+ m_dBlurLSNamespaces.clear();
// paths
configPaths.clear();
+ std::string CONFIGPATH;
+
static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
- const std::string CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
- configPaths.push_back(CONFIGPATH);
+ 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()) {
- Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
- try {
- std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
- } catch(...) { /* Probably doesn't exist */}
+ if(g_pCompositor->explicitConfigPath == "") {
+ Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
+ try {
+ std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
+ } catch(...) { /* Probably doesn't exist */}
- try {
- if (!std::filesystem::is_directory(CONFIGPARENTPATH))
- std::filesystem::create_directories(CONFIGPARENTPATH);
- }
- catch (...) {
- parseError = "Broken config file! (Could not create directory)";
- return;
+ try {
+ if (!std::filesystem::is_directory(CONFIGPARENTPATH))
+ std::filesystem::create_directories(CONFIGPARENTPATH);
+ }
+ catch (...) {
+ parseError = "Broken config file! (Could not create directory)";
+ return;
+ }
}
std::ofstream ofs;
@@ -854,7 +920,7 @@ void CConfigManager::loadConfigLoadVars() {
}
// Update window border colors
- g_pCompositor->updateAllWindowsBorders();
+ g_pCompositor->updateAllWindowsAnimatedDecorationValues();
// Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_vMonitors)
@@ -1084,3 +1150,12 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
return it != deviceConfigs.end();
}
+bool CConfigManager::shouldBlurLS(const std::string& ns) {
+ for (auto& bls : m_dBlurLSNamespaces) {
+ if (bls == ns) {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp
index bcb2fbe5..1d281c40 100644
--- a/src/config/ConfigManager.hpp
+++ b/src/config/ConfigManager.hpp
@@ -65,6 +65,7 @@ public:
float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&);
+ bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(std::string);
@@ -102,6 +103,7 @@ private:
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWindowRule> m_dWindowRules;
+ std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false;
std::deque<std::string> firstExecRequests;
@@ -127,6 +129,7 @@ private:
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
+ void handleBlurLS(const std::string&, const std::string&);
};
inline std::unique_ptr<CConfigManager> g_pConfigManager; \ No newline at end of file
diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp
index e8afb296..1577e36a 100644
--- a/src/config/defaultConfig.hpp
+++ b/src/config/defaultConfig.hpp
@@ -9,6 +9,12 @@ PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
########################################################################################
+
+#
+# Please note not all available settings / options are set here.
+# For a full list, see the wiki (basic and advanced configuring)
+#
+
autogenerated=1 # remove this line to get rid of the warning on top.
monitor=,1920x1080@60,0x0,1
diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp
index eb6c085c..1e6a8e32 100644
--- a/src/debug/HyprCtl.cpp
+++ b/src/debug/HyprCtl.cpp
@@ -13,95 +13,390 @@
#include <string>
-std::string monitorsRequest() {
+std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
- for (auto& m : g_pCompositor->m_vMonitors) {
- result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\n",
- m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform);
+ if (format == HyprCtl::FORMAT_JSON) {
+ result += "[";
+
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ result += getFormat(
+R"#({
+ "id": %i,
+ "name": "%s",
+ "width": %i,
+ "height": %i,
+ "refreshRate": %f,
+ "x": %i,
+ "y": %i,
+ "activeWorkspace": {
+ "id": %i,
+ "name": "%s"
+ },
+ "reserved": [%i, %i, %i, %i],
+ "scale": %.2f,
+ "transform": %i,
+ "active": "%s"
+},)#",
+ m->ID,
+ m->szName.c_str(),
+ (int)m->vecPixelSize.x, (int)m->vecPixelSize.y,
+ m->refreshRate,
+ (int)m->vecPosition.x, (int)m->vecPosition.y,
+ m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(),
+ (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
+ m->scale,
+ (int)m->transform,
+ (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no")
+ );
+ }
+
+ // remove trailing comma
+ result.pop_back();
+
+ result += "]";
+ } else {
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tactive: %s\n\n",
+ m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"));
+ }
}
return result;
}
-std::string clientsRequest() {
+std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
- for (auto& w : g_pCompositor->m_vWindows) {
- if (w->m_bIsMapped) {
- result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
- &w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID());
-
+ if (format == HyprCtl::FORMAT_JSON) {
+ result += "[";
+
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bIsMapped) {
+ result += getFormat(
+R"#({
+ "address": "0x%x",
+ "at": [%i, %i],
+ "size": [%i, %i],
+ "workspace": {
+ "id": %i,
+ "name": "%s"
+ },
+ "floating": %i,
+ "monitor": %i,
+ "class": "%s",
+ "title": "%s",
+ "pid": %i
+},)#",
+ &w,
+ (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
+ (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y,
+ w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()),
+ (int)w->m_bIsFloating,
+ w->m_iMonitorID,
+ g_pXWaylandManager->getAppIDClass(w.get()).c_str(),
+ g_pXWaylandManager->getTitle(w.get()).c_str(),
+ w->getPID()
+ );
+ }
+ }
+
+ // remove trailing comma
+ result.pop_back();
+
+ result += "]";
+ } else {
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bIsMapped) {
+ result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
+ &w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID());
+
+ }
}
}
return result;
}
-std::string workspacesRequest() {
+std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
- for (auto& w : g_pCompositor->m_vWorkspaces) {
- result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
- w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
+ if (format == HyprCtl::FORMAT_JSON) {
+ result += "[";
+
+ for (auto& w : g_pCompositor->m_vWorkspaces) {
+ result += getFormat(
+R"#({
+ "id": %i,
+ "name": "%s",
+ "monitor": "%s",
+ "windows": %i,
+ "hasfullscreen": %i
+},)#",
+ w->m_iID,
+ w->m_szName.c_str(),
+ g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(),
+ g_pCompositor->getWindowsOnWorkspace(w->m_iID),
+ (int)w->m_bHasFullscreenWindow
+ );
+ }
+
+ // remove trailing comma
+ result.pop_back();
+
+ result += "]";
+ } else {
+ for (auto& w : g_pCompositor->m_vWorkspaces) {
+ result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
+ w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
+ }
}
return result;
}
-std::string activeWindowRequest() {
+std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid";
- return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
- PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID());
+ if (format == HyprCtl::FORMAT_JSON) {
+ return getFormat(
+R"#({
+ "address": "0x%x",
+ "at": [%i, %i],
+ "size": [%i, %i],
+ "workspace": {
+ "id": %i,
+ "name": "%s"
+ },
+ "floating": %i,
+ "monitor": %i,
+ "class": "%s",
+ "title": "%s",
+ "pid": %i
+})#",
+ PWINDOW,
+ (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
+ (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
+ PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()),
+ (int)PWINDOW->m_bIsFloating,
+ PWINDOW->m_iMonitorID,
+ g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(),
+ g_pXWaylandManager->getTitle(PWINDOW).c_str(),
+ PWINDOW->getPID()
+ );
+ } else {
+ return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
+ PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID());
+ }
}
-std::string layersRequest() {
+std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
- for (auto& mon : g_pCompositor->m_vMonitors) {
- result += getFormat("Monitor %s:\n");
- int layerLevel = 0;
- for (auto& level : mon->m_aLayerSurfaceLists) {
- result += getFormat("\tLayer level %i:\n", layerLevel);
-
- for (auto& layer : level) {
- result += getFormat("\t\tLayer %x: xywh: %i %i %i %i\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height);
+ if (format == HyprCtl::FORMAT_JSON) {
+ result += "{\n";
+
+ for (auto& mon : g_pCompositor->m_vMonitors) {
+ result += getFormat(
+R"#("%s": {
+ "levels": {
+)#",
+ mon->szName.c_str()
+ );
+
+ int layerLevel = 0;
+ for (auto& level : mon->m_aLayerSurfaceLists) {
+ result += getFormat(
+R"#(
+ "%i": [
+)#",
+ layerLevel
+ );
+ for (auto& layer : level) {
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "x": %i,
+ "y": %i,
+ "w": %i,
+ "h": %i,
+ "namespace": "%s"
+ },)#",
+ layer,
+ layer->geometry.x,
+ layer->geometry.y,
+ layer->geometry.width,
+ layer->geometry.height,
+ layer->szNamespace.c_str()
+ );
+ }
+
+ // remove trailing comma
+ result.pop_back();
+
+ if (level.size() > 0)
+ result += "\n ";
+
+ result += "],";
+
+ layerLevel++;
}
- layerLevel++;
+ // remove trailing comma
+ result.pop_back();
+
+ result += "\n }\n},";
+ }
+
+ // remove trailing comma
+ result.pop_back();
+
+ result += "\n}\n";
+
+ } else {
+ for (auto& mon : g_pCompositor->m_vMonitors) {
+ result += getFormat("Monitor %s:\n", mon->szName.c_str());
+ int layerLevel = 0;
+ for (auto& level : mon->m_aLayerSurfaceLists) {
+ result += getFormat("\tLayer level %i:\n", layerLevel);
+
+ for (auto& layer : level) {
+ result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, layer->szNamespace.c_str());
+ }
+
+ layerLevel++;
+ }
+ result += "\n\n";
}
- result += "\n\n";
}
return result;
}
-std::string devicesRequest() {
+std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = "";
- result += "mice:\n";
+ if (format == HyprCtl::FORMAT_JSON) {
+ result += "{\n";
+ result += "\"mice\": [\n";
+
+ for (auto& m : g_pInputManager->m_lMice) {
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "name": "%s"
+ },)#",
+ &m,
+ m.mouse->name
+ );
+ }
- for (auto& m : g_pInputManager->m_lMice) {
- result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
- }
+ // remove trailing comma
+ result.pop_back();
+ result += "\n],\n";
+
+ result += "\"keyboards\": [\n";
+ for (auto& k : g_pInputManager->m_lKeyboards) {
+ const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "name": "%s",
+ "rules": "%s",
+ "model": "%s",
+ "layout": "%s",
+ "variant": "%s",
+ "options": "%s",
+ "active_keymap": "%s"
+ },)#",
+ &k,
+ k.keyboard->name,
+ k.currentRules.rules.c_str(),
+ k.currentRules.model.c_str(),
+ k.currentRules.layout.c_str(),
+ k.currentRules.variant.c_str(),
+ k.currentRules.options.c_str(),
+ KM
+ );
+ }
- result += "\n\nKeyboards:\n";
+ // remove trailing comma
+ result.pop_back();
+ result += "\n],\n";
- for (auto& k : g_pInputManager->m_lKeyboards) {
- result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
- }
+ result += "\"tablets\": [\n";
- result += "\n\nTablets:\n";
+ for (auto& d : g_pInputManager->m_lTabletPads) {
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "type": "tabletPad",
+ "belongsTo": {
+ "address": "0x%x",
+ "name": "%s"
+ }
+ },)#",
+ &d,
+ d.pTabletParent,
+ d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : ""
+ );
+ }
- for (auto& d : g_pInputManager->m_lTabletPads) {
- result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
- }
+ for (auto& d : g_pInputManager->m_lTablets) {
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "name": "%s"
+ },)#",
+ &d,
+ d.wlrDevice ? d.wlrDevice->name : ""
+ );
+ }
- for (auto& d : g_pInputManager->m_lTablets) {
- result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
- }
+ for (auto& d : g_pInputManager->m_lTabletTools) {
+ result += getFormat(
+R"#( {
+ "address": "0x%x",
+ "type": "tabletTool",
+ "belongsTo": "0x%x"
+ },)#",
+ &d,
+ d.wlrTabletTool ? d.wlrTabletTool->data : 0
+ );
+ }
+
+ // remove trailing comma
+ if (result[result.size() - 1] == ',')
+ result.pop_back();
+ result += "\n]\n";
+
+ result += "}\n";
+
+ } else {
+ result += "mice:\n";
+
+ for (auto& m : g_pInputManager->m_lMice) {
+ result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
+ }
+
+ result += "\n\nKeyboards:\n";
+
+ for (auto& k : g_pInputManager->m_lKeyboards) {
+ const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
+ result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM);
+ }
+
+ result += "\n\nTablets:\n";
+
+ for (auto& d : g_pInputManager->m_lTabletPads) {
+ result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
+ }
+
+ for (auto& d : g_pInputManager->m_lTablets) {
+ result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
+ }
- for (auto& d : g_pInputManager->m_lTabletTools) {
- result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
+ for (auto& d : g_pInputManager->m_lTabletTools) {
+ result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
+ }
}
return result;
@@ -158,7 +453,7 @@ std::string dispatchKeyword(std::string in) {
if (COMMAND == "monitor")
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
- if (COMMAND.find("input") != std::string::npos)
+ if (COMMAND.contains("input"))
g_pInputManager->setKeyboardLayout(); // update kb layout
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
@@ -181,6 +476,10 @@ std::string killRequest() {
return "ok";
}
+std::string splashRequest() {
+ return g_pCompositor->m_szCurrentSplash;
+}
+
std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
@@ -216,24 +515,46 @@ std::string dispatchBatch(std::string request) {
}
std::string getReply(std::string request) {
+ auto format = HyprCtl::FORMAT_NORMAL;
+
+ // process flags for non-batch requests
+ if (!request.contains("[[BATCH]]") && request.contains("/")) {
+ long unsigned int sepIndex = 0;
+ for (const auto& c : request) {
+ if (c == '/') { // stop at separator
+ break;
+ }
+
+ sepIndex++;
+
+ if (c == 'j')
+ format = HyprCtl::FORMAT_JSON;
+ }
+
+ if (sepIndex < request.size())
+ request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
+ }
+
if (request == "monitors")
- return monitorsRequest();
+ return monitorsRequest(format);
else if (request == "workspaces")
- return workspacesRequest();
+ return workspacesRequest(format);
else if (request == "clients")
- return clientsRequest();
+ return clientsRequest(format);
else if (request == "kill")
return killRequest();
else if (request == "activewindow")
- return activeWindowRequest();
+ return activeWindowRequest(format);
else if (request == "layers")
- return layersRequest();
+ return layersRequest(format);
else if (request == "version")
return versionRequest();
else if (request == "reload")
return reloadRequest();
else if (request == "devices")
- return devicesRequest();
+ return devicesRequest(format);
+ else if (request == "splash")
+ return splashRequest();
else if (request.find("dispatch") == 0)
return dispatchRequest(request);
else if (request.find("keyword") == 0)
@@ -264,6 +585,16 @@ void HyprCtl::tickHyprCtl() {
}
std::string getRequestFromThread(std::string rq) {
+ // we need to do something to wake hyprland up if VFR is enabled
+
+ static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
+
+ // TODO: is this safe...?
+ // this might be a race condition
+ // tested with 2 instances of `watch -n 0.1 hyprctl splash` and seems to not crash so I'll take that as a yes
+ if (!*PNOVFR)
+ g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_vMonitors.front().get());
+
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp
index 3da4aa07..60559e9f 100644
--- a/src/debug/HyprCtl.hpp
+++ b/src/debug/HyprCtl.hpp
@@ -14,4 +14,9 @@ namespace HyprCtl {
inline std::string request = "";
inline std::ifstream requestStream;
+
+ enum eHyprCtlOutputFormat {
+ FORMAT_NORMAL = 0,
+ FORMAT_JSON
+ };
}; \ No newline at end of file
diff --git a/src/defines.hpp b/src/defines.hpp
index 80750c23..375f0119 100644
--- a/src/defines.hpp
+++ b/src/defines.hpp
@@ -16,8 +16,6 @@
#define ISDEBUG false
#endif
-#define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); }
-
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
#define DYNLISTENFUNC(name) void listener_##name(void*, void*);
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name;
diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp
index 04763be1..349ffe61 100644
--- a/src/events/Devices.cpp
+++ b/src/events/Devices.cpp
@@ -15,145 +15,179 @@
// //
// ---------------------------------------------------- //
-void Events::listener_keyboardDestroy(void* owner, void* data) {
- SKeyboard* PKEYBOARD = (SKeyboard*)owner;
- g_pInputManager->destroyKeyboard(PKEYBOARD);
+void Events::listener_keyboardDestroy(void *owner, void *data) {
+ SKeyboard *PKEYBOARD = (SKeyboard *)owner;
+ g_pInputManager->destroyKeyboard(PKEYBOARD);
- Debug::log(LOG, "Destroyed keyboard %x", PKEYBOARD);
+ Debug::log(LOG, "Destroyed keyboard %x", PKEYBOARD);
}
-void Events::listener_keyboardKey(void* owner, void* data) {
- SKeyboard* PKEYBOARD = (SKeyboard*)owner;
- g_pInputManager->onKeyboardKey((wlr_keyboard_key_event*)data, PKEYBOARD);
+void Events::listener_keyboardKey(void *owner, void *data) {
+ SKeyboard *PKEYBOARD = (SKeyboard *)owner;
+ g_pInputManager->onKeyboardKey((wlr_keyboard_key_event *)data, PKEYBOARD);
}
-void Events::listener_keyboardMod(void* owner, void* data) {
- SKeyboard* PKEYBOARD = (SKeyboard*)owner;
- g_pInputManager->onKeyboardMod(data, PKEYBOARD);
+void Events::listener_keyboardMod(void *owner, void *data) {
+ SKeyboard *PKEYBOARD = (SKeyboard *)owner;
+ g_pInputManager->onKeyboardMod(data, PKEYBOARD);
}
-void Events::listener_mouseFrame(wl_listener* listener, void* data) {
- wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
+void Events::listener_mouseFrame(wl_listener *listener, void *data) {
+ wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
}
-void Events::listener_mouseMove(wl_listener* listener, void* data) {
- g_pInputManager->onMouseMoved((wlr_pointer_motion_event*)data);
+void Events::listener_mouseMove(wl_listener *listener, void *data) {
+ g_pInputManager->onMouseMoved((wlr_pointer_motion_event *)data);
}
-void Events::listener_mouseMoveAbsolute(wl_listener* listener, void* data) {
- g_pInputManager->onMouseWarp((wlr_pointer_motion_absolute_event*)data);
+void Events::listener_mouseMoveAbsolute(wl_listener *listener, void *data) {
+ g_pInputManager->onMouseWarp((wlr_pointer_motion_absolute_event *)data);
}
-void Events::listener_mouseButton(wl_listener* listener, void* data) {
- g_pInputManager->onMouseButton((wlr_pointer_button_event*)data);
+void Events::listener_mouseButton(wl_listener *listener, void *data) {
+ g_pInputManager->onMouseButton((wlr_pointer_button_event *)data);
}
-void Events::listener_mouseAxis(wl_listener* listener, void* data) {
- g_pInputManager->onMouseWheel((wlr_pointer_axis_event*)data);
+void Events::listener_mouseAxis(wl_listener *listener, void *data) {
+ g_pInputManager->onMouseWheel((wlr_pointer_axis_event *)data);
}
-void Events::listener_requestMouse(wl_listener* listener, void* data) {
- const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
+void Events::listener_requestMouse(wl_listener *listener, void *data) {
+ const auto EVENT = (wlr_seat_pointer_request_set_cursor_event *)data;
- g_pInputManager->processMouseRequest(EVENT);
+ g_pInputManager->processMouseRequest(EVENT);
}
-void Events::listener_newInput(wl_listener* listener, void* data) {
- const auto DEVICE = (wlr_input_device*)data;
+void Events::listener_newInput(wl_listener *listener, void *data) {
+ const auto DEVICE = (wlr_input_device *)data;
- switch(DEVICE->type) {
- case WLR_INPUT_DEVICE_KEYBOARD:
- Debug::log(LOG, "Attached a keyboard with name %s", DEVICE->name);
- g_pInputManager->newKeyboard(DEVICE);
- break;
- case WLR_INPUT_DEVICE_POINTER:
- Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name);
- g_pInputManager->newMouse(DEVICE);
- break;
- case WLR_INPUT_DEVICE_TOUCH:
- Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
- Debug::log(WARN, "!!!! Hyprland does not directly support touchscreens, bugs may occur !!!!");
- wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
- break;
- case WLR_INPUT_DEVICE_TABLET_TOOL:
- Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
- g_pInputManager->newTabletTool(DEVICE);
- break;
- case WLR_INPUT_DEVICE_TABLET_PAD:
- Debug::log(LOG, "Attached a tablet pad with name %s", DEVICE->name);
- g_pInputManager->newTabletPad(DEVICE);
- break;
- default:
- Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
- break;
- }
-
- g_pInputManager->updateCapabilities(DEVICE);
+ switch (DEVICE->type) {
+ case WLR_INPUT_DEVICE_KEYBOARD:
+ Debug::log(LOG, "Attached a keyboard with name %s", DEVICE->name);
+ g_pInputManager->newKeyboard(DEVICE);
+ break;
+ case WLR_INPUT_DEVICE_POINTER:
+ Debug::log(LOG, "Attached a mouse with name %s", DEVICE->name);
+ g_pInputManager->newMouse(DEVICE);
+ break;
+ case WLR_INPUT_DEVICE_TOUCH:
+ Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
+ Debug::log(WARN, "!!!! Hyprland does not directly support touchscreens, "
+ "bugs may occur !!!!");
+ wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
+ break;
+ case WLR_INPUT_DEVICE_TABLET_TOOL:
+ Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
+ g_pInputManager->newTabletTool(DEVICE);
+ break;
+ case WLR_INPUT_DEVICE_TABLET_PAD:
+ Debug::log(LOG, "Attached a tablet pad with name %s", DEVICE->name);
+ g_pInputManager->newTabletPad(DEVICE);
+ break;
+ default:
+ Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
+ break;
+ }
+
+ g_pInputManager->updateCapabilities(DEVICE);
}
-void Events::listener_newConstraint(wl_listener* listener, void* data) {
- const auto PCONSTRAINT = (wlr_pointer_constraint_v1*)data;
+void Events::listener_newConstraint(wl_listener *listener, void *data) {
+ const auto PCONSTRAINT = (wlr_pointer_constraint_v1 *)data;
- Debug::log(LOG, "New mouse constraint at %x", PCONSTRAINT);
+ Debug::log(LOG, "New mouse constraint at %x", PCONSTRAINT);
- g_pInputManager->m_lConstraints.emplace_back();
- const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
+ g_pInputManager->m_lConstraints.emplace_back();
+ const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
- CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
- CONSTRAINT->constraint = PCONSTRAINT;
+ CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
+ CONSTRAINT->constraint = PCONSTRAINT;
- CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
- CONSTRAINT->hyprListener_setConstraintRegion.initCallback(&PCONSTRAINT->events.set_region, &Events::listener_setConstraintRegion, CONSTRAINT, "Constraint");
+ CONSTRAINT->hyprListener_destroyConstraint.initCallback(
+ &PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint,
+ CONSTRAINT, "Constraint");
+ CONSTRAINT->hyprListener_setConstraintRegion.initCallback(
+ &PCONSTRAINT->events.set_region, &Events::listener_setConstraintRegion,
+ CONSTRAINT, "Constraint");
- if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
- g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
- }
+ if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
+ g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
+ }
}
-void Events::listener_destroyConstraint(void* owner, void* data) {
- const auto PCONSTRAINT = (SConstraint*)owner;
+void Events::listener_destroyConstraint(void *owner, void *data) {
+ const auto PCONSTRAINT = (SConstraint *)owner;
+
+ if (PCONSTRAINT->pMouse->currentConstraint == PCONSTRAINT->constraint) {
+ PCONSTRAINT->pMouse->hyprListener_commitConstraint.removeCallback();
+
+ const auto PWINDOW =
+ g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
+
+ if (PWINDOW) {
+ if (PWINDOW->m_bIsX11) {
+ wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
+ PCONSTRAINT->constraint->current.cursor_hint.x +
+ PWINDOW->m_uSurface.xwayland->x,
+ PWINDOW->m_uSurface.xwayland->y +
+ PCONSTRAINT->constraint->current.cursor_hint.y);
+
+ wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat,
+ PCONSTRAINT->constraint->current.cursor_hint.x,
+ PCONSTRAINT->constraint->current.cursor_hint.y);
+ } else {
+ wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
+ PCONSTRAINT->constraint->current.cursor_hint.x +
+ PWINDOW->m_vRealPosition.vec().x,
+ PCONSTRAINT->constraint->current.cursor_hint.y +
+ PWINDOW->m_vRealPosition.vec().y);
+
+ wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat,
+ PCONSTRAINT->constraint->current.cursor_hint.x,
+ PCONSTRAINT->constraint->current.cursor_hint.y);
+ }
+ }
- if (PCONSTRAINT->pMouse->currentConstraint == PCONSTRAINT->constraint) {
- PCONSTRAINT->pMouse->hyprListener_commitConstraint.removeCallback();
+ PCONSTRAINT->pMouse->currentConstraint = nullptr;
+ }
- const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
+ Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
- if (PWINDOW) {
- if (PWINDOW->m_bIsX11) {
- wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
- PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->constraint->current.cursor_hint.y);
+ g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
+}
- wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
- } else {
- wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
- PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, PCONSTRAINT->constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
+void Events::listener_setConstraintRegion(void *owner, void *data) {
+ // no
+}
- wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
- }
- }
+void Events::listener_newVirtPtr(wl_listener *listener, void *data) {
+ const auto EV = (wlr_virtual_pointer_v1_new_pointer_event *)data;
+ const auto POINTER = EV->new_pointer;
+ const auto DEVICE = &POINTER->pointer.base;
- PCONSTRAINT->pMouse->currentConstraint = nullptr;
- }
+ g_pInputManager->newMouse(DEVICE, true);
+}
- Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
+void Events::listener_destroyMouse(void *owner, void *data) {
+ const auto PMOUSE = (SMouse *)owner;
- g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
+ g_pInputManager->destroyMouse(PMOUSE->mouse);
}
-void Events::listener_setConstraintRegion(void* owner, void* data) {
- // no
+void Events::listener_swipeBegin(wl_listener *listener, void *data) {
+ const auto EVENT = (wlr_pointer_swipe_begin_event *)data;
+
+ g_pInputManager->onSwipeBegin(EVENT);
}
-void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
- const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
- const auto POINTER = EV->new_pointer;
- const auto DEVICE = &POINTER->pointer.base;
+void Events::listener_swipeUpdate(wl_listener *listener, void *data) {
+ const auto EVENT = (wlr_pointer_swipe_update_event *)data;
- g_pInputManager->newMouse(DEVICE);
+ g_pInputManager->onSwipeUpdate(EVENT);
}
-void Events::listener_destroyMouse(void* owner, void* data) {
- const auto PMOUSE = (SMouse*)owner;
+void Events::listener_swipeEnd(wl_listener *listener, void *data) {
+ const auto EVENT = (wlr_pointer_swipe_end_event *)data;
- g_pInputManager->destroyMouse(PMOUSE->mouse);
+ g_pInputManager->onSwipeEnd(EVENT);
}
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index 9d1fdb53..63e65fdc 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -49,6 +49,7 @@ namespace Events {
DYNLISTENFUNC(fullscreenWindow);
DYNLISTENFUNC(activateX11);
DYNLISTENFUNC(configureX11);
+ DYNLISTENFUNC(unmanagedSetGeometry);
// Window subsurfaces
// LISTENER(newSubsurfaceWindow);
@@ -112,4 +113,13 @@ namespace Events {
// Renderer destroy
LISTENER(RendererDestroy);
+
+ LISTENER(newIdleInhibitor);
+
+ LISTENER(swipeBegin);
+ LISTENER(swipeEnd);
+ LISTENER(swipeUpdate);
+
+ // session
+ LISTENER(sessionActive);
}; \ No newline at end of file
diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp
index 773ba909..0e2f49d5 100644
--- a/src/events/Layers.cpp
+++ b/src/events/Layers.cpp
@@ -32,8 +32,9 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
}
const auto PMONITOR = (SMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
- PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].push_back(new SLayerSurface());
- SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
+ SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].emplace_back(new SLayerSurface());
+
+ layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
if (!WLRLAYERSURFACE->output) {
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon
@@ -50,6 +51,8 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
+ layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
+
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
}
@@ -96,8 +99,6 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
layersurface->layerSurface->mapped = true;
- wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
-
// fix if it changed its mon
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
@@ -115,9 +116,15 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
- if (layersurface->layerSurface->current.keyboard_interactive)
+ if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
+ wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
+ const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
+ wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
+ wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
+ }
+
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
@@ -150,14 +157,17 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
if (layersurface->layerSurface->mapped)
layersurface->layerSurface->mapped = false;
- if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus)
- g_pCompositor->m_pLastFocus = nullptr;
-
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
if (!PMONITOR)
return;
+ // refocus if needed
+ if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
+ g_pCompositor->m_pLastFocus = nullptr;
+ g_pInputManager->refocus();
+ }
+
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);
@@ -206,5 +216,8 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
+ // update geom if it changed
+ layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
+
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
} \ No newline at end of file
diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp
index c25b1c6a..503d2111 100644
--- a/src/events/Misc.cpp
+++ b/src/events/Misc.cpp
@@ -157,4 +157,10 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
Debug::log(LOG, "!!Renderer destroyed!!");
+}
+
+void Events::listener_sessionActive(wl_listener* listener, void* data) {
+ Debug::log(LOG, "Session got activated!");
+
+ g_pCompositor->m_bSessionActive = true;
} \ No newline at end of file
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index 11527cee..24a8faa7 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -149,10 +149,10 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
PNEWWORKSPACE->setActive(true);
+ //
if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate)
pMostHzMonitor = PNEWMONITOR;
- //
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
@@ -166,6 +166,11 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
void Events::listener_monitorFrame(void* owner, void* data) {
SMonitor* const PMONITOR = (SMonitor*)owner;
+ if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive) {
+ Debug::log(WARN, "Attempted to render frame on inactive session!");
+ return; // cannot draw on session inactive (different tty)
+ }
+
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
@@ -173,6 +178,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
+ static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
@@ -181,28 +187,11 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pDebugOverlay->frameData(PMONITOR);
}
- // Hack: only check when monitor with top hz refreshes, saves a bit of resources.
- // This is for stuff that should be run every frame
- if (PMONITOR->ID == pMostHzMonitor->ID) {
- g_pCompositor->sanityCheckWorkspaces();
- g_pAnimationManager->tick();
- g_pCompositor->cleanupFadingOut();
-
- HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
-
- g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
-
- if (g_pConfigManager->m_bWantsMonitorReload)
- g_pConfigManager->performMonitorReload();
-
- g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
- }
-
if (PMONITOR->framesToSkip > 0) {
PMONITOR->framesToSkip -= 1;
if (!PMONITOR->noFrameSchedule)
- wlr_output_schedule_frame(PMONITOR->output);
+ g_pCompositor->scheduleFrameForMonitor(PMONITOR);
else {
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
}
@@ -210,6 +199,22 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
+ // checks //
+ if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
+ g_pCompositor->sanityCheckWorkspaces();
+ g_pAnimationManager->tick();
+
+ HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
+
+ g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
+
+ if (g_pConfigManager->m_bWantsMonitorReload)
+ g_pConfigManager->performMonitorReload();
+
+ g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
+ }
+ // //
+
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -228,10 +233,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return;
}
+ // we need to cleanup fading out when rendering the appropriate context
+ g_pCompositor->cleanupFadingOut(PMONITOR->ID);
+
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output);
- wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
+
+ if (*PDAMAGEBLINK || *PNOVFR)
+ g_pCompositor->scheduleFrameForMonitor(PMONITOR);
+
return;
}
@@ -266,7 +277,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// potentially can save on resources.
g_pHyprOpenGL->begin(PMONITOR, &damage);
- g_pHyprOpenGL->clear(CColor(100, 11, 11, 255));
+ g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
@@ -319,7 +330,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
wlr_output_commit(PMONITOR->output);
- wlr_output_schedule_frame(PMONITOR->output);
+ if (*PDAMAGEBLINK || *PNOVFR)
+ g_pCompositor->scheduleFrameForMonitor(PMONITOR);
if (*PDEBUGOVERLAY == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
@@ -353,8 +365,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
- g_pCompositor->cleanupExit();
- exit(1);
+ g_pCompositor->cleanup();
return;
}
@@ -386,7 +397,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr<SMonitor>& el) { return el.get() == pMonitor; }));
- // update the pMostHzMonitor
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr;
diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp
index cfb92f9b..04064696 100644
--- a/src/events/Popups.cpp
+++ b/src/events/Popups.cpp
@@ -92,6 +92,9 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
ASSERT(PWINDOW);
+ if (!PWINDOW->m_bIsMapped)
+ return;
+
Debug::log(LOG, "New layer popup created from XDG window %x -> %s", PWINDOW, PWINDOW->m_szTitle.c_str());
const auto WLRPOPUP = (wlr_xdg_popup*)data;
diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp
index 3c1d83f5..3d46931e 100644
--- a/src/events/Windows.cpp
+++ b/src/events/Windows.cpp
@@ -32,6 +32,9 @@ void addViewCoords(void* pWindow, int* x, int* y) {
void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
+ static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
+ static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
+
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
@@ -145,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
try {
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
- if (alphaPart.find_first_of(' ') != std::string::npos) {
+ if (alphaPart.contains(' ')) {
// we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
@@ -163,13 +166,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (requestedWorkspace != "") {
// process requested workspace
- if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
+ if (requestedWorkspace.contains(' ')) {
// check for silent
- if (requestedWorkspace.find("silent") != std::string::npos) {
+ if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
+
+ if (requestedWorkspace == "special") {
+ workspaceSilent = true;
+ }
}
if (!workspaceSilent) {
@@ -192,8 +199,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
- const auto SIZEX = SIZEXSTR.find('%') == std::string::npos ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
- const auto SIZEY = SIZEYSTR.find('%') == std::string::npos ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
+ const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
+ const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
@@ -208,8 +215,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
- const auto POSX = POSXSTR.find('%') == std::string::npos ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
- const auto POSY = POSYSTR.find('%') == std::string::npos ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
+ const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
+ const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
@@ -231,8 +238,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
}
- if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
+ if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) {
g_pCompositor->focusWindow(PWINDOW);
+ PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
+ } else
+ PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
@@ -246,6 +256,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
+
+ if (PWINDOW->m_iX11Type == 2)
+ PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
}
// do the animation thing
@@ -254,7 +267,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (workspaceSilent) {
// move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) {
- g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
+ if (requestedWorkspace != "special")
+ g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
+ else
+ g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
@@ -268,9 +284,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
}
+ PWINDOW->m_vRealPosition.warp();
+ PWINDOW->m_vRealSize.warp();
+
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
}
+ // recheck idle inhibitors
+ g_pInputManager->recheckIdleInhibitorStatus();
+
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
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);
@@ -293,6 +315,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->hyprListener_activateX11.removeCallback();
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
+ PWINDOW->hyprListener_setGeometryX11U.removeCallback();
}
if (PWINDOW->m_bIsFullscreen) {
@@ -350,14 +373,19 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// Destroy Foreign Toplevel
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
PWINDOW->m_phForeignToplevel = nullptr;
+
+ // recheck idle inhibitors
+ g_pInputManager->recheckIdleInhibitorStatus();
}
void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
- if (!g_pCompositor->windowValidMapped(PWINDOW))
+ if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
return;
+ g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
+
// Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
}
@@ -472,6 +500,29 @@ void Events::listener_configureX11(void* owner, void* data) {
g_pHyprRenderer->damageWindow(PWINDOW);
}
+void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
+ CWindow* PWINDOW = (CWindow*)owner;
+
+ if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden)
+ return;
+
+ const auto POS = PWINDOW->m_vRealPosition.goalv();
+ const auto SIZ = PWINDOW->m_vRealSize.goalv();
+
+ if (abs(floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
+ g_pHyprRenderer->damageWindow(PWINDOW);
+ PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y));
+
+ if (abs(floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
+ PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
+
+ g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.vec());
+ g_pCompositor->moveWindowToTop(PWINDOW);
+ PWINDOW->updateWindowDecos();
+ g_pHyprRenderer->damageWindow(PWINDOW);
+ }
+}
+
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data;
diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp
index ceda2c57..a87fff4f 100644
--- a/src/helpers/AnimatedVariable.hpp
+++ b/src/helpers/AnimatedVariable.hpp
@@ -128,10 +128,10 @@ public:
case AVARTYPE_COLOR:
return m_cValue != m_cGoal;
default:
- return false;
+ std::unreachable();
}
- return false; // unreachable
+ std::unreachable();
}
void warp() {
@@ -149,7 +149,7 @@ public:
break;
}
default:
- break;
+ std::unreachable();
}
}
diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp
index cb1d88d6..126600f3 100644
--- a/src/helpers/MiscFunctions.cpp
+++ b/src/helpers/MiscFunctions.cpp
@@ -137,7 +137,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
if (source.find_first_of("+") == 0) {
try {
- if (source.find('.') != std::string::npos)
+ if (source.contains("."))
result = relative + std::stof(source.substr(1));
else
result = relative + std::stoi(source.substr(1));
@@ -147,7 +147,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
}
} else if (source.find_first_of("-") == 0) {
try {
- if (source.find('.') != std::string::npos)
+ if (source.contains("."))
result = relative - std::stof(source.substr(1));
else
result = relative - std::stoi(source.substr(1));
@@ -157,7 +157,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
}
} else {
try {
- if (source.find('.') != std::string::npos)
+ if (source.contains("."))
result = stof(source);
else
result = stoi(source);
diff --git a/src/helpers/Splashes.hpp b/src/helpers/Splashes.hpp
new file mode 100644
index 00000000..68681ca2
--- /dev/null
+++ b/src/helpers/Splashes.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <array>
+#include <string>
+
+inline const std::vector<std::string> SPLASHES = {
+ "Woo, animations!",
+ "It's like Hypr, but better.",
+ "Release 1.0 when?",
+ "It's not awesome, it's Hyprland!",
+ "\"I commit too often, people can't catch up lmao\" - Vaxry",
+ "This text is random.",
+ "\"There are reasons to not use rust.\" - Boga",
+ "Read the wiki.",
+ "\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry",
+ "h",
+ "\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry",
+ "Compile, wait for 20 minutes, notice a new commit, compile again.",
+ "To rice, or not to rice, that is the question.",
+ "Now available on Fedora!",
+ // music reference / quote section
+ "J'remue le ciel, le jour, la nuit.",
+ "aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
+ "Wir sind schon sehr lang zusammen...",
+ "I see a red door and I want it painted black.",
+ "Take on me, take me on...",
+ "You spin me right round baby right round",
+ "Stayin' alive, stayin' alive",
+ "Say no way, say no way ya, no way!",
+ "Ground control to Major Tom...",
+ "Alors on danse",
+ "And all that I can see, is just a yellow lemon tree.",
+ "Got a one-way ticket to the blues",
+ "Is this the real life, is this just fantasy",
+ "What's in your head, in your head?",
+ "We're all living in America, America, America.",
+ "I'm still standing, better than I ever did",
+ "Here comes the sun, bringing you love and shining on everyone",
+ "Two trailer park girls go round the outside",
+ "With the lights out, it's less dangerous",
+ "Here we go back, this is the moment, tonight is the night",
+ "Now you're just somebody that I used to know...",
+ "Black bird, black moon, black sky",
+ "Some legends are told, some turn to dust or to gold",
+ "Your brain gets smart, but your head gets dumb.",
+ "Save your mercy for someone who needs it more",
+ "You're gonna hear my voice when I shout it out loud",
+ "Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
+ "Súbeme la radio que esta es mi canción",
+ "I'm beggin', beggin' you",
+ //
+ "Join the discord server!",
+ "Thanks ThatOneCalculator!",
+ "The AUR packages always work, except for the times they don't.",
+ "Funny animation compositor woo"
+}; \ No newline at end of file
diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp
index acaace13..a96411e6 100644
--- a/src/helpers/Vector2D.cpp
+++ b/src/helpers/Vector2D.cpp
@@ -1,4 +1,5 @@
#include "Vector2D.hpp"
+#include <algorithm>
Vector2D::Vector2D(double xx, double yy) {
x = xx;
@@ -20,4 +21,11 @@ double Vector2D::normalize() {
Vector2D Vector2D::floor() {
return Vector2D((int)x, (int)y);
+}
+
+Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
+ return Vector2D(
+ std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x),
+ std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)
+ );
} \ No newline at end of file
diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp
index 7288a088..7ca52a68 100644
--- a/src/helpers/Vector2D.hpp
+++ b/src/helpers/Vector2D.hpp
@@ -35,5 +35,7 @@ class Vector2D {
return a.x != x || a.y != y;
}
+ Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
+
Vector2D floor();
}; \ No newline at end of file
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 33278053..ce2d7248 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -25,10 +25,14 @@ struct SLayerSurface {
int monitorID = -1;
+ std::string szNamespace = "";
+
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
+ bool forceBlur = false;
+
// For the list lookup
bool operator==(const SLayerSurface& rhs) {
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
@@ -60,6 +64,26 @@ struct SRenderData {
// for custom round values
int rounding = -1; // -1 means not set
+
+ // for blurring
+ bool blur = false;
+
+ // for windows that animate poorly
+ bool squishOversized = false;
+};
+
+struct SExtensionFindingData {
+ Vector2D origin;
+ Vector2D vec;
+ wlr_surface** found;
+};
+
+struct SStringRuleNames {
+ std::string layout = "";
+ std::string model = "";
+ std::string variant = "";
+ std::string options = "";
+ std::string rules = "";
};
struct SKeyboard {
@@ -73,7 +97,7 @@ struct SKeyboard {
std::string name = "";
- xkb_rule_names currentRules = {0};
+ SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
@@ -94,6 +118,8 @@ struct SMouse {
std::string name = "";
+ bool virt = false;
+
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
@@ -221,3 +247,25 @@ struct STabletPad {
return wlrTabletPadV2 == b.wlrTabletPadV2;
}
};
+
+struct SIdleInhibitor {
+ wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
+ CWindow* pWindow = nullptr;
+
+ DYNLISTENER(Destroy);
+
+ bool operator==(const SIdleInhibitor& b) {
+ return pWlrInhibitor == b.pWlrInhibitor;
+ }
+};
+
+struct SSwipeGesture {
+ CWorkspace* pWorkspaceBegin = nullptr;
+
+ double delta = 0;
+
+ float avgSpeed = 0;
+ int speedPoints = 0;
+
+ SMonitor* pMonitor = nullptr;
+}; \ No newline at end of file
diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp
index 2d0c5941..5a3a24ba 100644
--- a/src/helpers/Workspace.hpp
+++ b/src/helpers/Workspace.hpp
@@ -28,6 +28,7 @@ public:
// for animations
CAnimatedVariable m_vRenderOffset;
CAnimatedVariable m_fAlpha;
+ bool m_bForceRendering = false;
// "scratchpad"
bool m_bIsSpecialWorkspace = false;
diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp
index 7255aae9..ea8d65d0 100644
--- a/src/hyprerror/HyprError.cpp
+++ b/src/hyprerror/HyprError.cpp
@@ -14,7 +14,7 @@ void CHyprError::createQueued() {
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
- const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
+ const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
const auto CAIRO = cairo_create(CAIROSURFACE);
@@ -27,12 +27,12 @@ void CHyprError::createQueued() {
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
cairo_set_source_rgba(CAIRO, m_cQueued.r / 255.f, m_cQueued.g / 255.f, m_cQueued.b / 255.f, m_cQueued.a / 255.f);
- cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecSize.x, 10 * LINECOUNT);
+ cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, 10 * LINECOUNT);
// outline
- cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecSize.y); // left
- cairo_rectangle(CAIRO, PMONITOR->vecSize.x - 1, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // right
- cairo_rectangle(CAIRO, 0, PMONITOR->vecSize.y - 1, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // bottom
+ cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
+ cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
+ cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
cairo_fill(CAIRO);
@@ -70,7 +70,7 @@ void CHyprError::createQueued() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
// delete cairo
cairo_destroy(CAIRO);
@@ -104,7 +104,7 @@ void CHyprError::draw() {
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon
- wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
+ wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
}
diff --git a/src/includes.hpp b/src/includes.hpp
index 2455171d..e8367f50 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -74,6 +74,7 @@ extern "C" {
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
+#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <wlr/util/region.h>
@@ -91,6 +92,7 @@ extern "C" {
#include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
+#include <wlr/types/wlr_pointer_gestures_v1.h>
}
#undef class
@@ -118,4 +120,5 @@ extern "C" {
#include "ext-workspace-unstable-v1-protocol.h"
-#include <algorithm> \ No newline at end of file
+#include <algorithm>
+#include <utility> \ No newline at end of file
diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp
index 33af48a3..2d9eab0f 100644
--- a/src/layout/DwindleLayout.cpp
+++ b/src/layout/DwindleLayout.cpp
@@ -23,19 +23,21 @@ void SDwindleNodeData::recalcSizePosRecursive() {
const auto REVERSESPLITRATIO = 2.f - splitRatio;
- if (g_pConfigManager->getInt("dwindle:preserve_split") == 0)
- splitTop = size.y > size.x;
+ if (g_pConfigManager->getInt("dwindle:preserve_split") == 0) {
+ const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
+ splitTop = size.y * WIDTHMULTIPLIER > size.x;
+ }
const auto SPLITSIDE = !splitTop;
if (SPLITSIDE) {
- // split sidey
+ // split left/right
children[0]->position = position;
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y);
children[1]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y);
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
} else {
- // split toppy bottomy
+ // split top/bottom
children[0]->position = position;
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio);
@@ -93,16 +95,27 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
}
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
- const auto PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
-
- if (!PMONITOR){
- Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
+ // Don't set nodes, only windows.
+ if (pNode->isNode)
return;
+
+ SMonitor* PMONITOR = nullptr;
+
+ if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
+ for (auto& m : g_pCompositor->m_vMonitors) {
+ if (m->specialWorkspaceOpen) {
+ PMONITOR = m.get();
+ break;
+ }
+ }
+ } else {
+ PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
}
- // Don't set nodes, only windows.
- if (pNode->isNode)
+ if (!PMONITOR) {
+ Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
return;
+ }
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
@@ -160,9 +173,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
}
}
- const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
-
- if (PWORKSPACE->m_bIsSpecialWorkspace) {
+ if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
// if special, we adjust the coords a bit
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
@@ -237,16 +248,19 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
+ const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
+
// if cursor over first child, make it first, etc
- const auto SIDEBYSIDE = NEWPARENT->size.x / NEWPARENT->size.y > 1.f;
+ const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * WIDTHMULTIPLIER;
NEWPARENT->splitTop = !SIDEBYSIDE;
+
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
if (FORCESPLIT == 0) {
- if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
- || (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
+ if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
+ || (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
// we are hovering over the first node, make PNODE first.
NEWPARENT->children[1] = OPENINGON;
NEWPARENT->children[0] = PNODE;
@@ -275,14 +289,16 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
}
// Update the children
- if (NEWPARENT->size.x > NEWPARENT->size.y) {
- // split sidey
+
+
+ if (NEWPARENT->size.x * WIDTHMULTIPLIER > NEWPARENT->size.y) {
+ // split left/right
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);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
} else {
- // split toppy bottomy
+ // split top/bottom
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
@@ -378,6 +394,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
if (!PWORKSPACE)
return;
+ g_pHyprRenderer->damageMonitor(PMONITOR);
+
if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
@@ -388,9 +406,26 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
}
}
- // Ignore any recalc events if we have a fullscreen window.
- if (PWORKSPACE->m_bHasFullscreenWindow)
+ // Ignore any recalc events if we have a fullscreen window, but process if fullscreen mode 2
+ if (PWORKSPACE->m_bHasFullscreenWindow) {
+ if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
+ return;
+
+ // massive hack from the fullscreen func
+ const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
+
+ SDwindleNodeData fakeNode;
+ fakeNode.pWindow = PFULLWINDOW;
+ fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
+ fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
+ fakeNode.workspaceID = PWORKSPACE->m_iID;
+ PFULLWINDOW->m_vPosition = fakeNode.position;
+ PFULLWINDOW->m_vSize = fakeNode.size;
+
+ applyNodeDataToWindow(&fakeNode);
+
return;
+ }
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
@@ -513,6 +548,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
+ g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
+
+ g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)on)));
+
if (!pWindow->m_bIsFullscreen) {
// if it got its fullscreen disabled, set back its node if it had one
const auto PNODE = getNodeFromWindow(pWindow);
@@ -562,6 +601,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
// we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
+
+ recalculateMonitor(PMONITOR->ID);
}
void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
@@ -637,6 +678,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
PPARENT->recalcSizePosRecursive();
}
+
+ g_pInputManager->refocus();
}
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
@@ -820,4 +863,4 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle";
-} \ No newline at end of file
+}
diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp
index a7f2facf..9f258b44 100644
--- a/src/layout/IHyprLayout.cpp
+++ b/src/layout/IHyprLayout.cpp
@@ -45,7 +45,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way.
- if (!g_pCompositor->isPointOnAnyMonitor(middlePoint) || (desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
+ if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
@@ -65,10 +65,12 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
}
- g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
- g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
+ if (pWindow->m_iX11Type != 2) {
+ g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
+ g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
- g_pCompositor->moveWindowToTop(pWindow);
+ g_pCompositor->moveWindowToTop(pWindow);
+ }
}
void IHyprLayout::onBeginDragWindow() {
@@ -210,9 +212,23 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else {
+ pWindow->m_vSize = pWindow->m_vRealSize.vec();
+ pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
+
onWindowRemovedTiling(pWindow);
g_pCompositor->moveWindowToTop(pWindow);
+
+ const auto POS = pWindow->m_vRealPosition.goalv();
+ const auto SIZ = pWindow->m_vRealSize.goalv();
+
+ pWindow->m_vRealPosition.setValueAndWarp(POS + Vector2D(5, 5));
+ pWindow->m_vRealSize.setValueAndWarp(SIZ - Vector2D(10, 10));
+
+ pWindow->m_vRealPosition = POS;
+ pWindow->m_vRealSize = SIZ;
+
+ g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
}
}
diff --git a/src/main.cpp b/src/main.cpp
index a437430f..9367d870 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,12 +12,22 @@ bool ignoreSudo = false;
int main(int argc, char** argv) {
if (!getenv("XDG_RUNTIME_DIR"))
- RIP("XDG_RUNTIME_DIR not set!");
+ throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
// parse some args
+ std::string configPath;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid"))
ignoreSudo = true;
+ else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) {
+ configPath = std::string(argv[++i]);
+ Debug::log(LOG, "Using config location %s.", configPath.c_str());
+ } else {
+ std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" <<
+ "--help -h | Show this help message\n" <<
+ "--config -c | Specify config file to use\n";
+ return 1;
+ }
}
system("mkdir -p /tmp/hypr");
@@ -37,6 +47,7 @@ int main(int argc, char** argv) {
// let's init the compositor.
// it initializes basic Wayland stuff in the constructor.
g_pCompositor = std::make_unique<CCompositor>();
+ g_pCompositor->explicitConfigPath = configPath;
Debug::log(LOG, "Hyprland init finished.");
@@ -46,7 +57,7 @@ int main(int argc, char** argv) {
// If we are here it means we got yote.
Debug::log(LOG, "Hyprland reached the end.");
- g_pCompositor->cleanupExit();
+ g_pCompositor->cleanup();
return EXIT_SUCCESS;
}
diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp
index e48b4d1e..053267e3 100644
--- a/src/managers/AnimationManager.cpp
+++ b/src/managers/AnimationManager.cpp
@@ -53,15 +53,18 @@ void CAnimationManager::tick() {
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
+ SMonitor* PMONITOR = nullptr;
wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
+ PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
} else if (PWORKSPACE) {
- const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
+ PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry;
+ PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
}
// beziers are with a switch unforto
@@ -188,8 +191,11 @@ void CAnimationManager::tick() {
// set size and pos if valid, but only if damage policy entire (dont if border for example)
- if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE)
+ if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2)
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
+
+ // manually schedule a frame
+ g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
}
@@ -303,7 +309,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
// the window has config'd special anim
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
- if (pWindow->m_sAdditionalConfigData.animationStyle.find(' ') != std::string::npos) {
+ if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) {
// has a direction
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
} else {
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp
index cb091c9f..60e4cdd6 100644
--- a/src/managers/KeybindManager.cpp
+++ b/src/managers/KeybindManager.cpp
@@ -41,35 +41,48 @@ void CKeybindManager::addKeybind(SKeybind kb) {
void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) {
- if (it->modmask == mod && it->key == key) {
+ if (isNumber(key) && std::stoi(key) > 9) {
+ const auto KEYNUM = std::stoi(key);
+
+ if (it->modmask == mod && it->keycode == KEYNUM) {
+ it = m_lKeybinds.erase(it);
+
+ if (it == m_lKeybinds.end())
+ break;
+ }
+ }
+ else if (it->modmask == mod && it->key == key) {
it = m_lKeybinds.erase(it);
+
+ if (it == m_lKeybinds.end())
+ break;
}
}
}
uint32_t CKeybindManager::stringToModMask(std::string mods) {
uint32_t modMask = 0;
- if (mods.find("SHIFT") != std::string::npos)
+ if (mods.contains("SHIFT"))
modMask |= WLR_MODIFIER_SHIFT;
- if (mods.find("CAPS") != std::string::npos)
+ if (mods.contains("CAPS"))
modMask |= WLR_MODIFIER_CAPS;
- if (mods.find("CTRL") != std::string::npos || mods.find("CONTROL") != std::string::npos)
+ if (mods.contains("CTRL") || mods.contains("CONTROL"))
modMask |= WLR_MODIFIER_CTRL;
- if (mods.find("ALT") != std::string::npos)
+ if (mods.contains("ALT"))
modMask |= WLR_MODIFIER_ALT;
- if (mods.find("MOD2") != std::string::npos)
+ if (mods.contains("MOD2"))
modMask |= WLR_MODIFIER_MOD2;
- if (mods.find("MOD3") != std::string::npos)
+ if (mods.contains("MOD3"))
modMask |= WLR_MODIFIER_MOD3;
- if (mods.find("SUPER") != std::string::npos || mods.find("WIN") != std::string::npos || mods.find("LOGO") != std::string::npos || mods.find("MOD4") != std::string::npos)
+ if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4"))
modMask |= WLR_MODIFIER_LOGO;
- if (mods.find("MOD5") != std::string::npos)
+ if (mods.contains("MOD5"))
modMask |= WLR_MODIFIER_MOD5;
return modMask;
}
-bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key) {
+bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key, const int& keycode) {
bool found = false;
if (handleInternalKeybinds(key))
@@ -82,15 +95,24 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap)
continue;
- // oMg such performance hit!!11!
- // 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 (key != KBKEY && key != KBKEYUPPER)
- continue;
+ if (k.keycode != -1) {
+ if (keycode != k.keycode)
+ continue;
+
+ } else {
+ if (key == 0)
+ continue; // this is a keycode check run
+
+ // oMg such performance hit!!11!
+ // 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 (key != KBKEY && key != KBKEYUPPER)
+ continue;
+ }
const auto DISPATCHER = m_mDispatchers.find(k.handler);
@@ -99,7 +121,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
} else {
// call the dispatcher
- Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
+ Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, key);
DISPATCHER->second(k.arg);
}
@@ -118,11 +140,11 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
if (PSESSION) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY);
+ g_pCompositor->m_bSessionActive = false;
for (auto& m : g_pCompositor->m_vMonitors) {
- g_pHyprOpenGL->destroyMonitorResources(m.get()); // mark resources as unusable anymore
m->noFrameSchedule = true;
- m->framesToSkip = 2;
+ m->framesToSkip = 1;
}
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
@@ -231,9 +253,6 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
}
- ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
- ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
-
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(ACTIVEWINDOW);
}
}
@@ -253,7 +272,14 @@ void CKeybindManager::changeworkspace(std::string args) {
int workspaceToChangeTo = 0;
std::string workspaceName = "";
- workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
+ if (args.find("[internal]") == 0) {
+ workspaceToChangeTo = std::stoi(args.substr(10));
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
+ if (PWORKSPACE)
+ workspaceName = PWORKSPACE->m_szName;
+ } else {
+ workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
+ }
if (workspaceToChangeTo == INT_MAX) {
Debug::log(ERR, "Error in changeworkspace, invalid value");
@@ -277,8 +303,6 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// change it
- PMONITOR->specialWorkspaceOpen = false;
-
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
@@ -451,7 +475,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
// undo the damage if we are moving to the special workspace
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
- changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
+ changeworkspace("[internal]" + std::to_string(OLDWORKSPACE->m_iID));
OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
@@ -503,8 +527,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
- changeworkspace(std::to_string(OLDWORKSPACEIDONMONITOR));
- changeworkspace(std::to_string(OLDWORKSPACEIDRETURN));
+ changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDONMONITOR));
+ changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDRETURN));
// revert animations
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
@@ -663,7 +687,7 @@ void CKeybindManager::focusMonitor(std::string arg) {
}
if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) {
- changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
+ changeworkspace("[internal]" + std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
} else {
Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
}
@@ -683,7 +707,7 @@ void CKeybindManager::focusMonitor(std::string arg) {
} else {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == arg) {
- changeworkspace(std::to_string(m->activeWorkspace));
+ changeworkspace("[internal]" + std::to_string(m->activeWorkspace));
return;
}
}
@@ -788,20 +812,20 @@ void CKeybindManager::workspaceOpt(std::string args) {
}
void CKeybindManager::exitHyprland(std::string argz) {
- g_pCompositor->cleanupExit();
- exit(0);
+ g_pCompositor->cleanup();
}
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
- if (!isNumber(args) && !isDirection(args)) {
- Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!");
- return;
- }
-
- const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
+ SMonitor* PMONITOR = nullptr;
- if (!PMONITOR) {
- Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
+ try {
+ if (!isNumber(args) && !isDirection(args)) {
+ PMONITOR = g_pCompositor->getMonitorFromName(args);
+ } else {
+ PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
+ }
+ } catch (std::exception& e) {
+ Debug::log(LOG, "moveCurrentWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
@@ -815,18 +839,25 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
}
void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
- if (args.find_first_of(' ') == std::string::npos)
+ if (!args.contains(' '))
return;
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
- if (!isNumber(monitor) && !isDirection(monitor)) {
- Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
+ SMonitor* PMONITOR = nullptr;
+
+ try {
+ if (!isNumber(monitor) && !isDirection(monitor)) {
+ PMONITOR = g_pCompositor->getMonitorFromName(monitor);
+ } else {
+ PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
+ }
+ } catch (std::exception& e) {
+ Debug::log(LOG, "moveWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
-
- const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
+
if (!PMONITOR){
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
@@ -882,11 +913,16 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
}
}
} else {
+ auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
+
+ if (!PSPECIALWORKSPACE) {
+ // ??? happens sometimes...?
+ PSPECIALWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(g_pCompositor->m_pLastMonitor->ID, "special", true)).get();
+ }
+
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
- const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
-
PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
}
@@ -910,7 +946,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
}
void CKeybindManager::resizeActive(std::string args) {
- if (args.find_first_of(' ') == std::string::npos)
+ if (!args.contains(' '))
return;
std::string x = args.substr(0, args.find_first_of(' '));
@@ -959,7 +995,7 @@ void CKeybindManager::resizeActive(std::string args) {
}
void CKeybindManager::moveActive(std::string args) {
- if (args.find_first_of(' ') == std::string::npos)
+ if (!args.contains(' '))
return;
std::string x = args.substr(0, args.find_first_of(' '));
@@ -1007,11 +1043,14 @@ void CKeybindManager::moveActive(std::string args) {
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
}
-void CKeybindManager::circleNext(std::string) {
+void CKeybindManager::circleNext(std::string arg) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
- g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
+ if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
+ g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
+ else
+ g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
@@ -1043,7 +1082,7 @@ void CKeybindManager::focusWindow(std::string regexp) {
Debug::log(LOG, "Focusing to window name: %s", w->m_szTitle.c_str());
- changeworkspace(std::to_string(w->m_iWorkspaceID));
+ changeworkspace("[internal]" + std::to_string(w->m_iWorkspaceID));
g_pCompositor->focusWindow(w.get());
diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp
index 31498677..08a1cba3 100644
--- a/src/managers/KeybindManager.hpp
+++ b/src/managers/KeybindManager.hpp
@@ -7,7 +7,8 @@
#include <functional>
struct SKeybind {
- std::string key = 0;
+ std::string key = "";
+ int keycode = -1;
uint32_t modmask = 0;
std::string handler = "";
std::string arg = "";
@@ -19,7 +20,7 @@ class CKeybindManager {
public:
CKeybindManager();
- bool handleKeybinds(const uint32_t&, const xkb_keysym_t&);
+ bool handleKeybinds(const uint32_t&, const xkb_keysym_t&, const int&);
void addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&);
uint32_t stringToModMask(std::string);
diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp
index 48687163..6ba2fa34 100644
--- a/src/managers/XWaylandManager.cpp
+++ b/src/managers/XWaylandManager.cpp
@@ -36,7 +36,9 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(pSurface)->toplevel, activate);
else if (wlr_surface_is_xwayland_surface(pSurface)) {
wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate);
- wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
+
+ if (activate)
+ wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
}
}
@@ -153,7 +155,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
if (pWindow->m_uSurface.xwayland->role) {
try {
std::string winrole = std::string(pWindow->m_uSurface.xwayland->role);
- if (winrole.find("pop-up") != std::string::npos || winrole.find("task_dialog") != std::string::npos) {
+ if (winrole.contains("pop-up") || winrole.contains("task_dialog")) {
return true;
}
} catch (std::exception& e) {
@@ -221,6 +223,4 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
-
- g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
} \ No newline at end of file
diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp
new file mode 100644
index 00000000..3efb40c6
--- /dev/null
+++ b/src/managers/input/IdleInhibitor.cpp
@@ -0,0 +1,54 @@
+#include "InputManager.hpp"
+#include "../../Compositor.hpp"
+
+void Events::listener_newIdleInhibitor(wl_listener* listener, void* data) {
+ const auto WLRIDLEINHIBITOR = (wlr_idle_inhibitor_v1*)data;
+
+ if (!WLRIDLEINHIBITOR)
+ return;
+
+ g_pInputManager->newIdleInhibitor(WLRIDLEINHIBITOR);
+}
+
+void CInputManager::newIdleInhibitor(wlr_idle_inhibitor_v1* pInhibitor) {
+ const auto PINHIBIT = &m_lIdleInhibitors.emplace_back();
+
+ Debug::log(LOG, "New idle inhibitor registered");
+
+ PINHIBIT->pWlrInhibitor = pInhibitor;
+
+ PINHIBIT->hyprListener_Destroy.initCallback(&pInhibitor->events.destroy, [](void* owner, void* data){
+
+ const auto PINH = (SIdleInhibitor*)owner;
+
+ g_pInputManager->m_lIdleInhibitors.remove(*PINH);
+
+ Debug::log(LOG, "Destroyed an idleinhibitor");
+
+ g_pInputManager->recheckIdleInhibitorStatus();
+
+ }, PINHIBIT, "IdleInhibitor");
+
+ PINHIBIT->pWindow = g_pCompositor->getWindowFromSurface(pInhibitor->surface);
+
+ if (PINHIBIT->pWindow)
+ Debug::log(LOG, "IdleInhibitor got window %x (%s)", PINHIBIT->pWindow, PINHIBIT->pWindow->m_szTitle.c_str());
+
+ recheckIdleInhibitorStatus();
+}
+
+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);
+ return;
+ } else if (g_pHyprRenderer->shouldRenderWindow(ii.pWindow)) {
+ wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
+ return;
+ }
+ }
+
+ wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, true);
+ return;
+} \ No newline at end of file
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 92a06a4c..5f1b1a3a 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -28,6 +28,8 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
+ static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
+
if (!g_pCompositor->m_bReadyToProcess)
return;
@@ -36,10 +38,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
return;
}
+ if (g_pCompositor->m_sSeat.mouse->virt)
+ return; // don't refocus on virt
+
Vector2D mouseCoords = getMouseCoordsInternal();
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
- if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored)
+ if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
return;
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
@@ -86,6 +91,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else {
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
g_pCompositor->m_sSeat.mouse->constraintActive = true;
+ didConstraintOnCursor = true;
}
}
}
@@ -138,6 +144,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
+ surfacePos = Vector2D(-1337, -1337);
} else {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
@@ -153,9 +160,21 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then windows
if (!foundSurface) {
- if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
- pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
- else
+ if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
+
+ if (PMONITOR->specialWorkspaceOpen) {
+ pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
+
+ if (pFoundWindow && pFoundWindow->m_iWorkspaceID != SPECIAL_WORKSPACE_ID) {
+ pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
+ }
+ } else {
+ pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
+
+ if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
+ pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
+ }
+ } else
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow) {
@@ -183,6 +202,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
+ if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
+ g_pCompositor->focusSurface(nullptr);
+
+ g_pCompositor->m_pLastWindow = nullptr;
+ }
+
return;
}
@@ -200,7 +225,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
if (pFoundWindow) {
- static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
if (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
// enter if change floating style
@@ -384,8 +408,8 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
- PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
- PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
+ PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
+ PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
if (m_pActiveKeyboard)
@@ -394,7 +418,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
applyConfigToKeyboard(PNEWKEYBOARD);
- wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
+ wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
}
@@ -409,6 +433,9 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
ASSERT(pKeyboard);
+ if (!wlr_keyboard_from_input_device(pKeyboard->keyboard))
+ return;
+
const auto REPEATRATE = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_rate") : g_pConfigManager->getInt("input:repeat_rate");
const auto REPEATDELAY = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_delay") : g_pConfigManager->getInt("input:repeat_delay");
@@ -421,7 +448,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_options") : g_pConfigManager->getString("input:kb_options");
try {
- if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == std::string(pKeyboard->currentRules.rules) && MODEL == std::string(pKeyboard->currentRules.model) && LAYOUT == std::string(pKeyboard->currentRules.layout) && VARIANT == std::string(pKeyboard->currentRules.variant) && OPTIONS == std::string(pKeyboard->currentRules.options)) {
+ if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return;
}
@@ -430,7 +457,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
// we can ignore those and just apply
}
- wlr_keyboard_set_repeat_info(pKeyboard->keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
+ wlr_keyboard_set_repeat_info(wlr_keyboard_from_input_device(pKeyboard->keyboard), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
pKeyboard->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE;
@@ -443,7 +470,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
.variant = VARIANT.c_str(),
.options = OPTIONS.c_str()};
- pKeyboard->currentRules = rules;
+ pKeyboard->currentRules.rules = RULES;
+ pKeyboard->currentRules.model = MODEL;
+ pKeyboard->currentRules.variant = VARIANT;
+ pKeyboard->currentRules.options = OPTIONS;
+ pKeyboard->currentRules.layout = LAYOUT;
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
@@ -460,12 +491,16 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
- pKeyboard->currentRules = rules;
+ pKeyboard->currentRules.rules = "";
+ pKeyboard->currentRules.model = "";
+ pKeyboard->currentRules.variant = "";
+ pKeyboard->currentRules.options = "";
+ pKeyboard->currentRules.layout = "";
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
- wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
+ wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP);
wlr_keyboard_modifiers wlrMods = {0};
@@ -478,7 +513,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
}
if (wlrMods.locked != 0) {
- wlr_keyboard_notify_modifiers(pKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
+ wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0);
}
xkb_keymap_unref(KEYMAP);
@@ -487,11 +522,12 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
}
-void CInputManager::newMouse(wlr_input_device* mouse) {
+void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
m_lMice.emplace_back();
const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse;
+ PMOUSE->virt = virt;
try {
PMOUSE->name = std::string(mouse->name);
} catch(std::exception& e) {
@@ -515,6 +551,11 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
}
+ if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "drag_lock") : 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(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
@@ -582,29 +623,31 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t* keysyms;
- int syms = xkb_state_key_get_syms(pKeyboard->keyboard->keyboard->xkb_state, KEYCODE, &keysyms);
+ int syms = xkb_state_key_get_syms(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE, &keysyms);
- const auto MODS = wlr_keyboard_get_modifiers(pKeyboard->keyboard->keyboard);
+ const auto MODS = accumulateModsFromAllKBs();
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
for (int i = 0; i < syms; ++i)
- found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
+ found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i], 0) || found;
+
+ found = g_pKeybindManager->handleKeybinds(MODS, 0, KEYCODE) || found;
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// hee hee
}
if (!found) {
- wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
+ wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
}
}
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
- wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
- wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &pKeyboard->keyboard->keyboard->modifiers);
+ wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
+ wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
}
void CInputManager::refocus() {
@@ -722,4 +765,15 @@ void CInputManager::updateCapabilities(wlr_input_device* pDev) {
}
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
-} \ No newline at end of file
+}
+
+uint32_t CInputManager::accumulateModsFromAllKBs() {
+
+ uint32_t finalMask = 0;
+
+ for (auto& kb : m_lKeyboards) {
+ finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
+ }
+
+ return finalMask;
+}
diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp
index 1a50c585..5e0c86b1 100644
--- a/src/managers/input/InputManager.hpp
+++ b/src/managers/input/InputManager.hpp
@@ -22,7 +22,7 @@ public:
void onKeyboardMod(void*, SKeyboard*);
void newKeyboard(wlr_input_device*);
- void newMouse(wlr_input_device*);
+ void newMouse(wlr_input_device*, bool virt = false);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
@@ -57,9 +57,20 @@ public:
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
+ // idle inhibitors
+ std::list<SIdleInhibitor> m_lIdleInhibitors;
+
void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
+ void newIdleInhibitor(wlr_idle_inhibitor_v1*);
+ void recheckIdleInhibitorStatus();
+
+ void onSwipeBegin(wlr_pointer_swipe_begin_event*);
+ void onSwipeEnd(wlr_pointer_swipe_end_event*);
+ void onSwipeUpdate(wlr_pointer_swipe_update_event*);
+
+ SSwipeGesture m_sActiveSwipe;
SKeyboard* m_pActiveKeyboard = nullptr;
@@ -81,6 +92,9 @@ private:
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
void applyConfigToKeyboard(SKeyboard*);
+
+ // for shared mods
+ uint32_t accumulateModsFromAllKBs();
};
inline std::unique_ptr<CInputManager> g_pInputManager; \ No newline at end of file
diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp
new file mode 100644
index 00000000..98f31945
--- /dev/null
+++ b/src/managers/input/Swipe.cpp
@@ -0,0 +1,152 @@
+#include "InputManager.hpp"
+#include "../../Compositor.hpp"
+
+void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
+
+ static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
+
+ if (e->fingers < 3 || *PSWIPE == 0)
+ return;
+
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
+
+ Debug::log(LOG, "Starting a swipe from %s", PWORKSPACE->m_szName.c_str());
+
+ m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE;
+ m_sActiveSwipe.delta = 0;
+ m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
+ m_sActiveSwipe.avgSpeed = 0;
+ m_sActiveSwipe.speedPoints = 0;
+}
+
+void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
+
+ if (!m_sActiveSwipe.pWorkspaceBegin)
+ return; // no valid swipe
+
+ static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
+ static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
+ static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
+
+ // commit
+ std::string wsname = "";
+ auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
+ auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
+
+ const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
+ const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
+
+ const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
+
+ if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
+ // revert
+ if (m_sActiveSwipe.delta < 0) {
+ // to left
+ PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
+ } else {
+ // to right
+ PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0});
+ }
+
+ m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
+ } else if (m_sActiveSwipe.delta < 0) {
+ // switch to left
+ const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
+
+ g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDLeft));
+
+ PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET);
+ PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f);
+
+ Debug::log(LOG, "Ended swipe to the left");
+ } else {
+ // switch to right
+ const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
+
+ g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
+
+ PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET);
+ PWORKSPACER->m_fAlpha.setValueAndWarp(255.f);
+
+ Debug::log(LOG, "Ended swipe to the right");
+ }
+
+ m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
+ m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
+
+ PWORKSPACEL->m_bForceRendering = false;
+ PWORKSPACER->m_bForceRendering = false;
+ m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
+
+ m_sActiveSwipe.pWorkspaceBegin = nullptr;
+
+ g_pInputManager->refocus();
+}
+
+void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
+ if (!m_sActiveSwipe.pWorkspaceBegin)
+ return;
+
+ static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
+ static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue;
+
+ m_sActiveSwipe.delta += *PSWIPEINVR ? -e->dx : e->dx;
+
+ m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1);
+ m_sActiveSwipe.speedPoints++;
+
+ std::string wsname = "";
+ auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
+ auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
+
+ if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
+ return;
+
+ m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST);
+
+ if (m_sActiveSwipe.delta < 0) {
+ if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){
+ m_sActiveSwipe.delta = 0;
+ return;
+ }
+
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
+
+ PWORKSPACE->m_bForceRendering = true;
+
+ if (workspaceIDLeft != workspaceIDRight) {
+ const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
+
+ PWORKSPACER->m_bForceRendering = false;
+ }
+
+ PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
+ m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
+
+ g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
+ } else {
+ if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID){
+ m_sActiveSwipe.delta = 0;
+ return;
+ }
+
+ const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight);
+
+ PWORKSPACE->m_bForceRendering = true;
+
+ if (workspaceIDLeft != workspaceIDRight) {
+ const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
+
+ PWORKSPACEL->m_bForceRendering = false;
+ }
+
+ PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
+ m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
+
+ g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight);
+ }
+
+ g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
+
+ g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
+} \ No newline at end of file
diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp
index 6a62e58e..ba79c458 100644
--- a/src/managers/input/Tablets.cpp
+++ b/src/managers/input/Tablets.cpp
@@ -10,7 +10,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
Debug::log(ERR, "Tablet had no name???"); // logic error
}
- PNEWTABLET->wlrTablet = pDevice->tablet;
+ PNEWTABLET->wlrTablet = wlr_tablet_from_input_device(pDevice);
PNEWTABLET->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWTABLET->wlrTablet->data = PNEWTABLET;
@@ -27,7 +27,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
Debug::log(LOG, "Removed a tablet");
}, PNEWTABLET, "Tablet");
- PNEWTABLET->hyprListener_Axis.initCallback(&pDevice->tablet->events.axis, [](void* owner, void* data) {
+ PNEWTABLET->hyprListener_Axis.initCallback(&wlr_tablet_from_input_device(pDevice)->events.axis, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_axis_event*)data;
const auto PTAB = (STablet*)owner;
@@ -80,7 +80,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
- PNEWTABLET->hyprListener_Tip.initCallback(&pDevice->tablet->events.tip, [](void* owner, void* data) {
+ PNEWTABLET->hyprListener_Tip.initCallback(&wlr_tablet_from_input_device(pDevice)->events.tip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_tip_event*)data;
const auto PTAB = (STablet*)owner;
@@ -98,7 +98,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
- PNEWTABLET->hyprListener_Button.initCallback(&pDevice->tablet->events.button, [](void* owner, void* data) {
+ PNEWTABLET->hyprListener_Button.initCallback(&wlr_tablet_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_button_event*)data;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
@@ -107,7 +107,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet");
- PNEWTABLET->hyprListener_Proximity.initCallback(&pDevice->tablet->events.proximity, [](void* owner, void* data) {
+ PNEWTABLET->hyprListener_Proximity.initCallback(&wlr_tablet_from_input_device(pDevice)->events.proximity, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_tool_proximity_event*)data;
const auto PTAB = (STablet*)owner;
@@ -165,7 +165,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
- PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {
+ PNEWPAD->hyprListener_Button.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_button_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -175,7 +175,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
- PNEWPAD->hyprListener_Strip.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
+ PNEWPAD->hyprListener_Strip.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_strip_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -184,7 +184,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
- PNEWPAD->hyprListener_Ring.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
+ PNEWPAD->hyprListener_Ring.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto EVENT = (wlr_tablet_pad_ring_event*)data;
const auto PPAD = (STabletPad*)owner;
@@ -193,7 +193,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad");
- PNEWPAD->hyprListener_Attach.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
+ PNEWPAD->hyprListener_Attach.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
const auto TABLET = (wlr_tablet_tool*)data;
const auto PPAD = (STabletPad*)owner;
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
index 4a5baf50..90b41a4b 100644
--- a/src/render/Framebuffer.cpp
+++ b/src/render/Framebuffer.cpp
@@ -2,15 +2,14 @@
#include "OpenGL.hpp"
bool CFramebuffer::alloc(int w, int h) {
- bool firstAlloc = false;
- if (m_iFb == (uint32_t)-1)
- {
+ bool firstAlloc = false;
+
+ if (m_iFb == (uint32_t)-1) {
firstAlloc = true;
glGenFramebuffers(1, &m_iFb);
}
- if (m_cTex.m_iTexID == 0)
- {
+ if (m_cTex.m_iTexID == 0) {
firstAlloc = true;
glGenTextures(1, &m_cTex.m_iTexID);
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
@@ -20,13 +19,11 @@ bool CFramebuffer::alloc(int w, int h) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
- if (firstAlloc || m_Size != Vector2D(w, h))
- {
+ if (firstAlloc || m_Size != Vector2D(w, h)) {
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
- glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
@@ -37,7 +34,6 @@ bool CFramebuffer::alloc(int w, int h) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
- glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0);
}
@@ -78,3 +74,7 @@ void CFramebuffer::release() {
m_cTex.m_iTexID = 0;
m_iFb = -1;
}
+
+CFramebuffer::~CFramebuffer() {
+ release();
+} \ No newline at end of file
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
index 3d15069d..6af59ca2 100644
--- a/src/render/Framebuffer.hpp
+++ b/src/render/Framebuffer.hpp
@@ -6,6 +6,8 @@
class CFramebuffer {
public:
+ ~CFramebuffer();
+
bool alloc(int w, int h);
void bind();
void release();
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 793901aa..d60e827e 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -311,21 +311,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
-void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round) {
+void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- renderTexture(CTexture(tex), pBox, alpha, round);
+ renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV);
}
-void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
+void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
- renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
+ renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowCustomUV);
scissor((wlr_box*)nullptr);
}
-void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
+void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
@@ -388,7 +388,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
- if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
+ if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
const float verts[] = {
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
@@ -702,8 +702,6 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
begin(PMONITOR, &fakeDamage, true);
- pixman_region32_fini(&fakeDamage);
-
clear(CColor(0,0,0,0)); // JIC
timespec now;
@@ -717,7 +715,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0);
- g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders);
+ g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
g_pConfigManager->setInt("decoration:blur", BLURVAL);
@@ -742,9 +740,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
#else
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
#endif
-
end();
+ pixman_region32_fini(&fakeDamage);
+
wlr_output_rollback(PMONITOR->output);
}
@@ -762,8 +761,6 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
begin(PMONITOR, &fakeDamage, true);
- pixman_region32_fini(&fakeDamage);
-
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
@@ -792,6 +789,8 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
end();
+ pixman_region32_fini(&fakeDamage);
+
wlr_output_rollback(PMONITOR->output);
}
@@ -915,9 +914,28 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
+void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
+ cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+
+ const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
+ cairo_set_font_size(CAIRO, FONTSIZE);
+
+ cairo_set_source_rgba(CAIRO, 1.f, 1.f, 1.f, 0.32f);
+
+ cairo_text_extents_t textExtents;
+ cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
+
+ cairo_move_to(CAIRO, m_RenderData.pMonitor->vecPixelSize.x / 2.f - textExtents.width / 2.f, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height - 1);
+ cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
+
+ cairo_surface_flush(CAIROSURFACE);
+}
+
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
+ static auto *const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
+
// release the last tex if exists
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
PTEX->destroyTexture();
@@ -926,6 +944,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
Debug::log(LOG, "Allocated texture for BGTex");
+ // TODO: use relative paths to the installation
+ // or configure the paths at build time
+
// check if wallpapers exist
if (!std::filesystem::exists("/usr/share/hyprland/wall_8K.png"))
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
@@ -949,6 +970,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
const auto CAIRO = cairo_create(CAIROSURFACE);
+ if (!*PNOSPLASH)
+ renderSplash(CAIRO, CAIROSURFACE);
+
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
@@ -969,9 +993,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
void CHyprOpenGLImpl::clearWithTex() {
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
- wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
+ static auto *const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
- renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
+ if (!*PRENDERTEX) {
+ wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
+ renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
+ }
}
void CHyprOpenGLImpl::destroyMonitorResources(SMonitor* pMonitor) {
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 292eba36..84cfcd39 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -6,6 +6,8 @@
#include <list>
#include <unordered_map>
+#include <cairo/cairo.h>
+
#include "Shaders.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
@@ -45,7 +47,6 @@ struct SCurrentRenderData {
pixman_region32_t* pDamage = nullptr;
- bool renderingPrimarySurface = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
};
@@ -60,8 +61,8 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
- void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
- void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
+ void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
+ void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowCustomUV = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round);
@@ -121,7 +122,9 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
- void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
+ void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false);
+
+ void renderSplash(cairo_t *const, cairo_surface_t *const);
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL; \ No newline at end of file
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index eaa3cd90..d2b5efa9 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -12,22 +12,30 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY);
wlr_box windowBox;
- if (RDATA->surface && surface == RDATA->surface) {
+ if (RDATA->surface && surface == RDATA->surface)
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
- } else { // here we clamp to 2, these might be some tiny specks
+ else // here we clamp to 2, these might be some tiny specks
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::clamp(surface->current.width, 2, 1337420), std::clamp(surface->current.height, 2, 1337420)};
+
+ // squish all oversized
+ if (RDATA->squishOversized) {
+ if (x + windowBox.width > RDATA->w)
+ windowBox.width = RDATA->w - x;
+ if (y + windowBox.height > RDATA->h)
+ windowBox.height = RDATA->h - y;
}
+
scaleBox(&windowBox, RDATA->output->scale);
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
- g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false;
-
if (RDATA->surface && surface == RDATA->surface) {
- g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
- g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
+ if (RDATA->blur)
+ g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
+ else
+ g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
if (RDATA->decorate) {
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
@@ -35,8 +43,18 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
}
}
- else
- g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
+ else {
+ if (RDATA->surface && wlr_surface_is_xdg_surface(RDATA->surface)) {
+ wlr_box geo;
+ wlr_xdg_surface_get_geometry(wlr_xdg_surface_from_wlr_surface(RDATA->surface), &geo);
+
+ windowBox.x -= geo.x;
+ windowBox.y -= geo.y;
+ }
+
+ g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false);
+ }
+
wlr_surface_send_frame_done(surface, RDATA->when);
@@ -54,8 +72,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
return true;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
- // if not, check if it maybe is active on a different monitor. vvv might be animation in progress
- if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
+ // if not, check if it maybe is active on a different monitor. vvv might be animation in progress
+ if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return true;
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
@@ -93,7 +111,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
continue;
// found it!
- renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
+ renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
pWorkspaceWindow = w.get();
}
@@ -103,7 +121,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue;
- renderWindow(w.get(), pMonitor, time, true);
+ renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
// and then special windows
@@ -118,7 +136,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
continue;
// render the bad boy
- renderWindow(w.get(), pMonitor, time, true);
+ renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
// and the overlay layers
@@ -140,7 +158,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
g_pHyprError->draw();
}
-void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) {
+void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode) {
if (pWindow->m_bHidden)
return;
@@ -160,9 +178,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
- renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
+ renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
+ renderdata.blur = true; // if it shouldn't, it will be ignored later
+ renderdata.squishOversized = pWindow->m_vRealPosition.isBeingAnimated();
// apply window special data
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
@@ -173,37 +193,40 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first, if not fullscreen full
- if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
- wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
-
- if (!pWindow->m_bIsX11) {
- // To everyone who makes apps with improperly aligned surfaces,
- // For example chromium, or GTK devs who allow shadows on windows,
- // a sincere FUCK YOU.
+ if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
+ if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
+ wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
- wlr_box geom;
- wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
+ if (!pWindow->m_bIsX11) {
+ wlr_box geom;
+ wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
- g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
- g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
- if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
- // No special UV mods needed
+ if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
+ // No special UV mods needed
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
+ }
+ } else {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
}
- }
- wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
+ wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
- g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
- g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
+ }
- if (!pWindow->m_bIsX11) {
- renderdata.dontRound = false; // restore dontround
- renderdata.pMonitor = pMonitor;
- wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
+ if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
+ if (!pWindow->m_bIsX11) {
+ renderdata.dontRound = false; // restore dontround
+ renderdata.pMonitor = pMonitor;
+ wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
+ }
}
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
@@ -217,6 +240,11 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, SMonitor* pMonitor, times
SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y};
renderdata.fadeAlpha = pLayer->alpha.fl();
+ renderdata.blur = pLayer->forceBlur;
+ renderdata.surface = pLayer->layerSurface->surface;
+ renderdata.decorate = false;
+ renderdata.w = pLayer->layerSurface->surface->current.width;
+ renderdata.h = pLayer->layerSurface->surface->current.height;
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
}
@@ -243,7 +271,25 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
return;
}
- // Non-floating
+ // Non-floating main
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
+ continue;
+
+ if (w->m_bIsFloating)
+ continue; // floating are in the second pass
+
+ if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
+ continue; // special are in the third pass
+
+ if (!shouldRenderWindow(w.get(), PMONITOR))
+ continue;
+
+ // render the bad boy
+ renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_MAIN);
+ }
+
+ // Non-floating popup
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
@@ -258,7 +304,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue;
// render the bad boy
- renderWindow(w.get(), PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_POPUP);
}
// floating on top
@@ -276,7 +322,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue;
// render the bad boy
- renderWindow(w.get(), PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
}
// and then special
@@ -291,7 +337,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue;
// render the bad boy
- renderWindow(w.get(), PMONITOR, time, true);
+ renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
}
// Render surfaces above windows for monitor
@@ -428,7 +474,7 @@ void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayer
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
for (auto& ls : layerSurfaces) {
- if (ls->fadingOut || ls->readyToDelete)
+ if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface)
continue;
const auto PLAYER = ls->layerSurface;
@@ -551,6 +597,11 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
+ // schedule frame events
+ if (!wl_list_empty(&pSurface->current.frame_callback_list)) {
+ g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
+ }
+
if (!pixman_region32_not_empty(&damageBox)) {
pixman_region32_fini(&damageBox);
return;
@@ -799,4 +850,4 @@ void CHyprRenderer::ensureCursorRenderingMode() {
bool CHyprRenderer::shouldRenderCursor() {
return m_bHasARenderedCursor;
-} \ No newline at end of file
+}
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index ff9fd4ea..c03c7117 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -17,6 +17,12 @@ enum DAMAGETRACKINGMODES {
DAMAGE_TRACKING_FULL
};
+enum eRenderPassMode {
+ RENDER_PASS_ALL = 0,
+ RENDER_PASS_MAIN,
+ RENDER_PASS_POPUP
+};
+
class CHyprRenderer {
public:
@@ -41,7 +47,7 @@ public:
private:
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
- void renderWindow(CWindow*, SMonitor*, timespec*, bool);
+ void renderWindow(CWindow*, SMonitor*, timespec*, bool, eRenderPassMode);
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
void renderDragIcon(SMonitor*, timespec*);
diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp
index abb5d90c..2d46d7a0 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.cpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.cpp
@@ -40,12 +40,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
// ????
- for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
- if (it->get() == this) {
- pWindow->m_dWindowDecorations.erase(it);
- return;
- }
- }
+ m_pWindow->m_vDecosToRemove.push_back(this);
+ return;
}
// get the group info
@@ -58,12 +54,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (m_dwGroupMembers.size() == 0) {
// remove
- for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
- if (it->get() == this) {
- pWindow->m_dWindowDecorations.erase(it);
- return;
- }
- }
+ m_pWindow->m_vDecosToRemove.push_back(this);
+ return;
}
}
diff --git a/subprojects/wlroots b/subprojects/wlroots
-Subproject 5c4384a1330faedf975c8b8644881d50390f361
+Subproject b89ed9015c3fbe8d339e9d65cf70fdca6e5645b