Merge upstream

This commit is contained in:
Darksome 2022-07-15 19:42:03 +03:00
commit 5388b54442
60 changed files with 2001 additions and 570 deletions

38
.github/workflows/release.yaml vendored Normal file
View file

@ -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

2
.gitignore vendored
View file

@ -12,6 +12,8 @@ _deps
build/ build/
result result
/.vscode/ /.vscode/
.envrc
.cache
*.o *.o
*-protocol.c *-protocol.c

View file

@ -37,12 +37,12 @@ execute_process(
include_directories(. PRIVATE "subprojects/wlroots/include/") include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/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) add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
find_package(PkgConfig 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") file(GLOB_RECURSE SRCFILES "src/*.cpp")
@ -80,7 +80,7 @@ include(CPack)
target_link_libraries(Hyprland PkgConfig::deps) target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland target_link_libraries(Hyprland
wlroots ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us
pixman-1 pixman-1
OpenGL OpenGL
GLESv2 GLESv2

View file

@ -107,11 +107,13 @@ all:
cd ./hyprctl && make all && cd .. cd ./hyprctl && make all && cd ..
install: install:
[ ! -d /usr/include/wlr ] || mv /usr/include/wlr /usr/include/wlrBackup make clear
[ ! -f /usr/lib/libwlroots.so ] || mv /usr/lib/libwlroots.so /usr/lib/libwlroots.so.backup make fixwlr
[ ! -f /usr/lib/pkgconfig/wlroots.pc ] || mv /usr/lib/pkgconfig/wlroots.pc /usr/lib/pkgconfig/wlroots.pc.backup 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 mkdir -p ${PREFIX}/share/wayland-sessions
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/ cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
mkdir -p ${PREFIX}/bin mkdir -p ${PREFIX}/bin
@ -122,17 +124,12 @@ install:
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.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: uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland rm -f ${PREFIX}/bin/Hyprland
rm -f ${PREFIX}/bin/hyprctl rm -f ${PREFIX}/bin/hyprctl
rm -f /usr/lib/libwlroots.so.11032
rm -rf ${PREFIX}/share/hyprland 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 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

View file

@ -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 [Discord]: https://discord.gg/hQ9XvMUjjr
[Stars]: https://starchart.cc/vaxerski/Hyprland [Stars]: https://starchart.cc/hyprwm/Hyprland
[Hypr]: https://github.com/vaxerski/Hypr [Hypr]: https://github.com/hyprwm/Hypr
[Pull Requests]: https://github.com/vaxerski/Hyprland/pulls [Pull Requests]: https://github.com/hyprwm/Hyprland/pulls
[Issues]: https://github.com/vaxerski/Hyprland/issues [Issues]: https://github.com/hyprwm/Hyprland/issues
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta [Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
[Contribute]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging [Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation [Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start [Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
[License]: LICENSE [License]: LICENSE
@ -156,12 +156,12 @@ Try it out and report bugs / suggestions!
<!----------------------------------{ Badges }---------------------------------> <!----------------------------------{ 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 Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
[Badge Issues]: https://img.shields.io/github/issues/vaxerski/Hyprland [Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/vaxerski/Hyprland [Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
[Badge Language]: https://img.shields.io/github/languages/top/vaxerski/Hyprland [Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
[Badge License]: https://img.shields.io/github/license/vaxerski/Hyprland [Badge License]: https://img.shields.io/github/license/hyprwm/Hyprland
[Badge Lines]: https://img.shields.io/tokei/lines/github/vaxerski/Hyprland [Badge Lines]: https://img.shields.io/tokei/lines/github/hyprwm/Hyprland
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4 [Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4

View file

@ -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: If your bug crashes Hyprland, append additionally:
- The Hyprland log - The Hyprland log
- Coredump / Coredump analysis (with a stacktrace) - Coredump / Coredump analysis (with a stacktrace)
- Your config
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source. **Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.

View file

@ -3,6 +3,11 @@
# #
# Refer to the wiki for more information. # 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 monitor=,1280x720@60,0x0,1
workspace=DP-1,1 workspace=DP-1,1

View file

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1656239181, "lastModified": 1657447684,
"narHash": "sha256-wW1xRFBn376yGloXZ4QzBE4hjipMawpV18Lshd9QSPw=", "narHash": "sha256-FCP9AuU1q6PE3vOeM5SFf58f/UKPBAsoSGDUGamNBbo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5", "rev": "5f43d8b088d3771274bcfb69d3c7435b1121ac88",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -26,11 +26,11 @@
"flake": false, "flake": false,
"locked": { "locked": {
"host": "gitlab.freedesktop.org", "host": "gitlab.freedesktop.org",
"lastModified": 1655824477, "lastModified": 1656865312,
"narHash": "sha256-1kskHOLsnisR3kqIL5IHrQbQG/4xoXxeEf1ExMV6/RU=", "narHash": "sha256-xtQ0zwJZwN8sciruveM10CzKz6TWxBY8SyXa8E4jly4=",
"owner": "wlroots", "owner": "wlroots",
"repo": "wlroots", "repo": "wlroots",
"rev": "5c4384a1330faedf975c8b8644881d50390f3613", "rev": "5dc1d4671dd2ca3c1f0f09587c463fdbb542f0a4",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {

View file

@ -32,7 +32,8 @@
src = inputs.wlroots; src = inputs.wlroots;
}); });
hyprland = prev.callPackage ./nix/default.nix { 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; wlroots = wlroots-hyprland;
}; };
hyprland-debug = hyprland.override {debug = true;}; hyprland-debug = hyprland.override {debug = true;};
@ -47,6 +48,16 @@
default = self.packages.${system}.hyprland; 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); formatter = genSystems (system: pkgsFor.${system}.alejandra);
nixosModules.default = import ./nix/module.nix self; nixosModules.default = import ./nix/module.nix self;

View file

@ -1,4 +1,4 @@
all: all:
g++ -std=c++20 ./main.cpp -o ./hyprctl g++ -std=c++23 ./main.cpp -o ./hyprctl
clean: clean:
rm ./hyprctl rm ./hyprctl

View file

@ -14,9 +14,11 @@
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <string> #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 monitors
workspaces workspaces
clients clients
@ -27,8 +29,13 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
keyword keyword
version version
kill kill
splash
hyprpaper hyprpaper
reload)#"; reload
flags:
j -> output in JSON
)#";
void request(std::string arg) { void request(std::string arg) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@ -153,7 +160,7 @@ void dispatchRequest(int argc, char** argv) {
return; 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); request(rq);
} }
@ -180,12 +187,21 @@ void hyprpaperRequest(int argc, char** argv) {
requestHyprpaper(rq); requestHyprpaper(rq);
} }
void batchRequest(int argc, char** argv) { void batchRequest(std::string arg) {
std::string rq = "[[BATCH]]" + std::string(argv[2]); std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
request(rq); 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 main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c; int bflag = 0, sflag = 0, index, c;
@ -194,20 +210,47 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
if (!strcmp(argv[1], "monitors")) request("monitors"); std::string fullRequest = "";
else if (!strcmp(argv[1], "clients")) request("clients"); std::string fullArgs = "";
else if (!strcmp(argv[1], "workspaces")) request("workspaces"); const auto ARGS = splitArgs(argc, argv);
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
else if (!strcmp(argv[1], "layers")) request("layers"); for (auto i = 0; i < ARGS.size(); ++i) {
else if (!strcmp(argv[1], "version")) request("version"); if (ARGS[i].contains("-")) {
else if (!strcmp(argv[1], "kill")) request("kill"); // parse
else if (!strcmp(argv[1], "devices")) request("devices"); if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
else if (!strcmp(argv[1], "reload")) request("reload"); fullArgs += "j";
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv); } else if (ARGS[i] == "--batch") {
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv); fullRequest = "--batch ";
else if (!strcmp(argv[1], "hyprpaper")) hyprpaperRequest(argc, argv); } else {
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv); printf("%s\n", USAGE.c_str());
else if (!strcmp(argv[1], "--help")) printf("%s", 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 { else {
printf("%s\n", USAGE.c_str()); printf("%s\n", USAGE.c_str());
return 1; return 1;

View file

@ -1,6 +1,8 @@
project('Hyprland', 'cpp', 'c', project('Hyprland', 'cpp', 'c',
version : '0.6.2beta', version : '0.7.0beta',
default_options : ['warning_level=2', 'cpp_std=c++20', 'default_library=static', 'optimization=3']) default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
add_global_arguments('-std=c++23', language: 'cpp')
add_project_arguments( add_project_arguments(
[ [

View file

@ -61,6 +61,11 @@ stdenv.mkDerivation {
./meson-build.patch ./meson-build.patch
]; ];
# Fix hardcoded paths to /usr installation
postPatch = ''
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
'';
passthru.providedSessions = ["hyprland"]; passthru.providedSessions = ["hyprland"];
meta = with lib; { meta = with lib; {

View file

@ -19,7 +19,7 @@ in {
package = mkOption { package = mkOption {
type = types.package; 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"; defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }"; example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
description = '' description = ''

View file

@ -1,4 +1,16 @@
#include "Compositor.hpp" #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() { CCompositor::CCompositor() {
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL)); 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"); 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_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); m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
if (!m_sWLRBackend) { if (!m_sWLRBackend) {
Debug::log(CRIT, "m_sWLRBackend was NULL!"); Debug::log(CRIT, "m_sWLRBackend was NULL!");
RIP("m_sWLRBackend NULL!"); throw std::runtime_error("wlr_backend_autocreate() failed!");
return;
} }
m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
if (m_iDRMFD < 0) { if (m_iDRMFD < 0) {
Debug::log(CRIT, "Couldn't query the DRM FD!"); Debug::log(CRIT, "Couldn't query the DRM FD!");
RIP("DRMFD NULL!"); throw std::runtime_error("wlr_backend_get_drm_fd() failed!");
return;
} }
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
if (!m_sWLRRenderer) { if (!m_sWLRRenderer) {
Debug::log(CRIT, "m_sWLRRenderer was NULL!"); Debug::log(CRIT, "m_sWLRRenderer was NULL!");
RIP("m_sWLRRenderer NULL!"); throw std::runtime_error("wlr_gles2_renderer_create_with_drm_fd() failed!");
return;
} }
wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay); wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay);
@ -53,16 +72,14 @@ CCompositor::CCompositor() {
if (!m_sWLRAllocator) { if (!m_sWLRAllocator) {
Debug::log(CRIT, "m_sWLRAllocator was NULL!"); Debug::log(CRIT, "m_sWLRAllocator was NULL!");
RIP("m_sWLRAllocator NULL!"); throw std::runtime_error("wlr_allocator_autocreate() failed!");
return;
} }
m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer); m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer);
if (!m_sWLREGL) { if (!m_sWLREGL) {
Debug::log(CRIT, "m_sWLREGL was NULL!"); Debug::log(CRIT, "m_sWLREGL was NULL!");
RIP("m_sWLREGL NULL!"); throw std::runtime_error("wlr_gles2_renderer_get_egl() failed!");
return;
} }
m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, m_sWLRRenderer); 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_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_v1_create(m_sWLDisplay, m_sWLRForeignRegistry);
wlr_xdg_foreign_v2_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() { CCompositor::~CCompositor() {
cleanupExit(); cleanup();
} }
void handleCritSignal(int signo) { void CCompositor::setRandomSplash() {
g_pCompositor->cleanupExit(); std::random_device dev;
exit(signo); std::mt19937 engine(dev());
std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1);
m_szCurrentSplash = SPLASHES[distribution(engine)];
} }
void CCompositor::initAllSignals() { 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.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.axis, &Events::listen_mouseAxis, 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.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_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_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat");
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &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_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_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer"); addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
addWLSignal(&m_sWLRIdleInhibitMgr->events.new_inhibitor, &Events::listen_newIdleInhibitor, m_sWLRIdleInhibitMgr, "WLRIdleInhibitMgr");
signal(SIGINT, handleCritSignal); if (m_sWLRSession)
signal(SIGTERM, handleCritSignal); addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
} }
void CCompositor::cleanupExit() { void CCompositor::cleanup() {
if (!m_sWLDisplay) if (!m_sWLDisplay)
return; return;
@ -180,8 +209,7 @@ void CCompositor::cleanupExit() {
g_pXWaylandManager->m_sWLRXWayland = nullptr; g_pXWaylandManager->m_sWLRXWayland = nullptr;
} }
wl_display_destroy_clients(m_sWLDisplay); wl_display_terminate(m_sWLDisplay);
wl_display_destroy(m_sWLDisplay);
m_sWLDisplay = nullptr; m_sWLDisplay = nullptr;
} }
@ -245,7 +273,7 @@ void CCompositor::startCompositor() {
if (!m_szWLDisplaySocket) { if (!m_szWLDisplaySocket) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!"); Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
wlr_backend_destroy(m_sWLRBackend); 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); setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
@ -258,7 +286,7 @@ void CCompositor::startCompositor() {
Debug::log(CRIT, "Backend did not start!"); Debug::log(CRIT, "Backend did not start!");
wlr_backend_destroy(m_sWLRBackend); wlr_backend_destroy(m_sWLRBackend);
wl_display_destroy(m_sWLDisplay); 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); 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); const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) { 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) { 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}; 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) 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; 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) { CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
// special workspace // special workspace
if (PMONITOR->specialWorkspaceOpen) { 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) { for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; 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(); 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. // 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++) { 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}; 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) if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && (*w)->m_iX11Type != 2) {
return w->get(); 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) { for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; 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(); return w.get();
} }
@ -436,6 +509,12 @@ CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor(); const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) { 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) { for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; 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) 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 // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
if (windowValidMapped(PLASTWINDOW)) { if (windowValidMapped(PLASTWINDOW)) {
updateWindowBorderColor(PLASTWINDOW); updateWindowAnimatedDecorationValues(PLASTWINDOW);
if (PLASTWINDOW->m_bIsX11) { if (PLASTWINDOW->m_bIsX11) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat); 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(); const auto POINTERLOCAL = g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.goalv();
wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y); wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y);
updateWindowBorderColor(pWindow); updateWindowAnimatedDecorationValues(pWindow);
// Send an event // Send an event
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle)); 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))) 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. return; // Don't focus when already focused on this.
if (!pSurface)
return;
// Unfocus last surface if should // Unfocus last surface if should
if (m_pLastFocus && m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) if (m_pLastFocus && ((m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) || !pSurface))
wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(m_pLastFocus)->toplevel, false); 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); 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()); Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, pWindowOwner->m_szTitle.c_str());
else else
Debug::log(LOG, "Set keyboard focus to surface %x", pSurface); Debug::log(LOG, "Set keyboard focus to surface %x", pSurface);
g_pXWaylandManager->activateSurface(pSurface, false);
m_pLastFocus = pSurface;
} }
bool CCompositor::windowValidMapped(CWindow* pWindow) { bool CCompositor::windowValidMapped(CWindow* pWindow) {
@ -689,6 +775,8 @@ void CCompositor::sanityCheckWorkspaces() {
if (it == m_vWorkspaces.end()) if (it == m_vWorkspaces.end())
break; break;
continue;
} }
if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) { if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) {
@ -700,6 +788,8 @@ void CCompositor::sanityCheckWorkspaces() {
if (it == m_vWorkspaces.end()) if (it == m_vWorkspaces.end())
break; 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) { for (auto& w : m_vWindowsFadingOut) {
if (w->m_iMonitorID != (long unsigned int)monid)
continue;
bool valid = windowExists(w); bool valid = windowExists(w);
if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) { 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)); m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
Debug::log(LOG, "Cleanup: destroyed a window"); Debug::log(LOG, "Cleanup: destroyed a window");
glFlush(); // to free mem NOW.
return; return;
} }
} }
for (auto& ls : m_vSurfacesFadingOut) { for (auto& ls : m_vSurfacesFadingOut) {
if (ls->monitorID != monid)
continue;
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) { if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
for (auto& m : m_vMonitors) { for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLists) { for (auto& lsl : m->m_aLayerSurfaceLists) {
@ -808,6 +906,7 @@ void CCompositor::cleanupFadingOut() {
Debug::log(LOG, "Cleanup: destroyed a layersurface"); Debug::log(LOG, "Cleanup: destroyed a layersurface");
glFlush(); // to free mem NOW.
return; return;
} }
} }
@ -910,6 +1009,29 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
return nullptr; 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 CCompositor::getNextAvailableNamedWorkspace() {
int lowest = -1337 + 1; int lowest = -1337 + 1;
for (auto& w : m_vWorkspaces) { for (auto& w : m_vWorkspaces) {
@ -1032,25 +1154,50 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
return nullptr; return nullptr;
} }
void CCompositor::updateAllWindowsBorders() { void CCompositor::updateAllWindowsAnimatedDecorationValues() {
for (auto& w : m_vWindows) { for (auto& w : m_vWindows) {
if (!w->m_bIsMapped) if (!w->m_bIsMapped)
continue; continue;
updateWindowBorderColor(w.get()); updateWindowAnimatedDecorationValues(w.get());
} }
} }
void CCompositor::updateWindowBorderColor(CWindow* pWindow) { void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
// optimization // optimization
static int64_t* ACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.active_border")->intValue; 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 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); const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
if (RENDERDATA.isBorderColor) if (RENDERDATA.isBorderColor)
pWindow->m_cRealBorderColor = RENDERDATA.borderColor; pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
else else
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL); 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) { void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) {
@ -1188,4 +1335,20 @@ CWindow* CCompositor::getX11Parent(CWindow* pWindow) {
} }
return nullptr; 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);
} }

View file

@ -30,7 +30,9 @@ public:
// ------------------ WLR BASICS ------------------ // // ------------------ WLR BASICS ------------------ //
wl_display* m_sWLDisplay; wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend; wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer; wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator; wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor; wlr_compositor* m_sWLRCompositor;
@ -61,11 +63,14 @@ public:
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr; wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager; wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry; wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
// ------------------------------------------------- // // ------------------------------------------------- //
const char* m_szWLDisplaySocket; const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = ""; std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
std::vector<std::unique_ptr<SMonitor>> m_vMonitors; std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
std::vector<std::unique_ptr<CWindow>> m_vWindows; std::vector<std::unique_ptr<CWindow>> m_vWindows;
@ -77,7 +82,7 @@ public:
std::vector<SLayerSurface*> m_vSurfacesFadingOut; std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor(); void startCompositor();
void cleanupExit(); void cleanup();
wlr_surface* m_pLastFocus = nullptr; wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr; CWindow* m_pLastWindow = nullptr;
@ -86,6 +91,7 @@ public:
SSeat m_sSeat; SSeat m_sSeat;
bool m_bReadyToProcess = false; bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
// ------------------------------------------------- // // ------------------------------------------------- //
@ -99,7 +105,7 @@ public:
bool windowExists(CWindow*); bool windowExists(CWindow*);
bool windowValidMapped(CWindow*); bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&); 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&); CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*, SLayerSurface**); wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl); wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
@ -113,6 +119,7 @@ public:
CWorkspace* getWorkspaceByName(const std::string&); CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&); CWorkspace* getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces(); void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&); int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&); CWindow* getFirstWindowOnWorkspace(const int&);
void fixXWaylandWindowsOnWorkspace(const int&); void fixXWaylandWindowsOnWorkspace(const int&);
@ -120,16 +127,17 @@ public:
bool doesSeatAcceptInput(wlr_surface*); bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*); bool isWindowActive(CWindow*);
void moveWindowToTop(CWindow*); void moveWindowToTop(CWindow*);
void cleanupFadingOut(); void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char); CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr); void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*); CWindow* getNextWindowOnWorkspace(CWindow*);
CWindow* getPrevWindowOnWorkspace(CWindow*);
int getNextAvailableNamedWorkspace(); int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*); CWindow* getConstraintWindow(SMouse*);
SMonitor* getMonitorInDirection(const char&); SMonitor* getMonitorInDirection(const char&);
void updateAllWindowsBorders(); void updateAllWindowsAnimatedDecorationValues();
void updateWindowBorderColor(CWindow*); void updateWindowAnimatedDecorationValues(CWindow*);
void moveWindowToWorkspace(CWindow*, const std::string&); void moveWindowToWorkspace(CWindow*, const std::string&);
int getNextAvailableMonitorID(); int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*); void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
@ -137,9 +145,13 @@ public:
void setWindowFullscreen(CWindow*, bool, eFullscreenMode); void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*); void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*); CWindow* getX11Parent(CWindow*);
void scheduleFrameForMonitor(SMonitor*);
std::string explicitConfigPath;
private: private:
void initAllSignals(); void initAllSignals();
void setRandomSplash();
}; };

View file

@ -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_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_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_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) 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() { void CWindow::updateWindowDecos() {
for (auto& wd : m_dWindowDecorations) for (auto& wd : m_dWindowDecorations)
wd->updateWindow(this); 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() { pid_t CWindow::getPID() {

View file

@ -28,6 +28,7 @@ public:
DYNLISTENER(unmapWindow); DYNLISTENER(unmapWindow);
DYNLISTENER(destroyWindow); DYNLISTENER(destroyWindow);
DYNLISTENER(setTitleWindow); DYNLISTENER(setTitleWindow);
DYNLISTENER(setGeometryX11U);
DYNLISTENER(fullscreenWindow); DYNLISTENER(fullscreenWindow);
DYNLISTENER(newPopupXDG); DYNLISTENER(newPopupXDG);
// DYNLISTENER(newSubsurfaceWindow); // DYNLISTENER(newSubsurfaceWindow);
@ -99,11 +100,15 @@ public:
// Window decorations // Window decorations
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations; std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
// Special render data, rules, etc // Special render data, rules, etc
SWindowSpecialRenderData m_sSpecialRenderData; SWindowSpecialRenderData m_sSpecialRenderData;
SWindowAdditionalConfigData m_sAdditionalConfigData; SWindowAdditionalConfigData m_sAdditionalConfigData;
// for alpha
CAnimatedVariable m_fActiveInactiveAlpha;
// For the list lookup // For the list lookup
bool operator==(const CWindow& rhs) { 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; 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;

View file

@ -12,8 +12,15 @@
CConfigManager::CConfigManager() { CConfigManager::CConfigManager() {
setDefaultVars(); 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); configPaths.emplace_back(CONFIGPATH);
Debug::disableLogs = &configValues["debug:disable_logs"].intValue; Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
@ -36,6 +43,10 @@ void CConfigManager::setDefaultVars() {
configValues["general:col.active_border"].intValue = 0xffffffff; configValues["general:col.active_border"].intValue = 0xffffffff;
configValues["general:col.inactive_border"].intValue = 0xff444444; configValues["general:col.inactive_border"].intValue = 0xff444444;
configValues["general:cursor_inactive_timeout"].intValue = 0; 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:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0; configValues["debug:log_damage"].intValue = 0;
@ -66,6 +77,7 @@ void CConfigManager::setDefaultVars() {
configValues["dwindle:force_split"].intValue = 0; configValues["dwindle:force_split"].intValue = 0;
configValues["dwindle:preserve_split"].intValue = 0; configValues["dwindle:preserve_split"].intValue = 0;
configValues["dwindle:special_scale_factor"].floatValue = 0.8f; configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
configValues["animations:enabled"].intValue = 1; configValues["animations:enabled"].intValue = 1;
configValues["animations:speed"].floatValue = 7.f; configValues["animations:speed"].floatValue = 7.f;
@ -102,6 +114,13 @@ void CConfigManager::setDefaultVars() {
configValues["input:touchpad:clickfinger_behavior"].intValue = 0; configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
configValues["input:touchpad:middle_button_emulation"].intValue = 0; configValues["input:touchpad:middle_button_emulation"].intValue = 0;
configValues["input:touchpad:tap-to-click"].intValue = 1; 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; configValues["input:follow_mouse"].intValue = 1;
@ -124,6 +143,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
cfgValues["clickfinger_behavior"].intValue = 0; cfgValues["clickfinger_behavior"].intValue = 0;
cfgValues["middle_button_emulation"].intValue = 0; cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1; cfgValues["tap-to-click"].intValue = 1;
cfgValues["drag_lock"].intValue = 0;
} }
void CConfigManager::init() { void CConfigManager::init() {
@ -147,17 +167,15 @@ void CConfigManager::init() {
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) { void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
if (configValues.find(COMMAND) == configValues.end()) { if (configValues.find(COMMAND) == configValues.end()) {
if (COMMAND[0] == '$') { if (COMMAND.find("device:") != 0 /* devices parsed later */) {
// register a dynamic var if (COMMAND[0] == '$') {
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str()); // register a dynamic var
configDynamicVars[COMMAND.substr(1)] = VALUE; Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
} else { configDynamicVars[COMMAND.substr(1)] = VALUE;
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field."; } else {
} parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
}
if (COMMAND.find("device:") == 0 /* devices parsed later */) {
parseError = "";
} else {
return; return;
} }
} }
@ -191,7 +209,12 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
// Values with 0x are hex // Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2); const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16); 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); CONFIGENTRY->intValue = stol(VALUE);
} catch (...) { } catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str()); 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.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@'))); newrule.resolution.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)); newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
nextItem(); nextItem();
@ -503,8 +526,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
return; return;
} }
if (KEY != "") if (KEY != "") {
g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap}); 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) { 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) { void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
const auto DISPLAY = value.substr(0, value.find_first_of(',')); 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; 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] == '~') { if (value[0] == '~') {
value.replace(0, 1, std::string(ENVHOME)); 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 == "animation") handleAnimation(COMMAND, VALUE);
else if (COMMAND == "source") handleSource(COMMAND, VALUE); else if (COMMAND == "source") handleSource(COMMAND, VALUE);
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE); else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
else else
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); 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); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update window border colors // Update window border colors
g_pCompositor->updateAllWindowsBorders(); g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return retval; return retval;
} }
@ -703,7 +759,7 @@ void CConfigManager::parseLine(std::string& line) {
line = line.substr(1); line = line.substr(1);
} }
if (line.find(" {") != std::string::npos) { if (line.contains(" {")) {
auto cat = line.substr(0, line.find(" {")); auto cat = line.substr(0, line.find(" {"));
transform(cat.begin(), cat.end(), cat.begin(), ::tolower); transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
if (currentCategory.length() != 0) { if (currentCategory.length() != 0) {
@ -717,7 +773,7 @@ void CConfigManager::parseLine(std::string& line) {
return; return;
} }
if (line.find("}") != std::string::npos && currentCategory != "") { if (line.contains("}") && currentCategory != "") {
currentCategory = ""; currentCategory = "";
return; return;
} }
@ -753,32 +809,42 @@ void CConfigManager::loadConfigLoadVars() {
m_mAdditionalReservedAreas.clear(); m_mAdditionalReservedAreas.clear();
configDynamicVars.clear(); configDynamicVars.clear();
deviceConfigs.clear(); deviceConfigs.clear();
m_dBlurLSNamespaces.clear();
// paths // paths
configPaths.clear(); configPaths.clear();
std::string CONFIGPATH;
static const char* const ENVHOME = getenv("HOME"); static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/"; const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
const std::string CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
if (g_pCompositor->explicitConfigPath == "") {
CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
} else {
CONFIGPATH = g_pCompositor->explicitConfigPath;
}
configPaths.push_back(CONFIGPATH); configPaths.push_back(CONFIGPATH);
std::ifstream ifs; std::ifstream ifs;
ifs.open(CONFIGPATH); ifs.open(CONFIGPATH);
if (!ifs.good()) { if (!ifs.good()) {
Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)"); if(g_pCompositor->explicitConfigPath == "") {
try { Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup"); try {
} catch(...) { /* Probably doesn't exist */} std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
} catch(...) { /* Probably doesn't exist */}
try { try {
if (!std::filesystem::is_directory(CONFIGPARENTPATH)) if (!std::filesystem::is_directory(CONFIGPARENTPATH))
std::filesystem::create_directories(CONFIGPARENTPATH); std::filesystem::create_directories(CONFIGPARENTPATH);
} }
catch (...) { catch (...) {
parseError = "Broken config file! (Could not create directory)"; parseError = "Broken config file! (Could not create directory)";
return; return;
}
} }
std::ofstream ofs; std::ofstream ofs;
@ -854,7 +920,7 @@ void CConfigManager::loadConfigLoadVars() {
} }
// Update window border colors // Update window border colors
g_pCompositor->updateAllWindowsBorders(); g_pCompositor->updateAllWindowsAnimatedDecorationValues();
// Force the compositor to fully re-render all monitors // Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_vMonitors) for (auto& m : g_pCompositor->m_vMonitors)
@ -1084,3 +1150,12 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
return it != deviceConfigs.end(); return it != deviceConfigs.end();
} }
bool CConfigManager::shouldBlurLS(const std::string& ns) {
for (auto& bls : m_dBlurLSNamespaces) {
if (bls == ns) {
return true;
}
}
return false;
}

View file

@ -65,6 +65,7 @@ public:
float getDeviceFloat(const std::string&, const std::string&); float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&); std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&); bool deviceConfigExists(const std::string&);
bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(std::string); SConfigValue* getConfigValuePtr(std::string);
@ -102,6 +103,7 @@ private:
std::deque<SMonitorRule> m_dMonitorRules; std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWindowRule> m_dWindowRules; std::deque<SWindowRule> m_dWindowRules;
std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false; bool firstExecDispatched = false;
std::deque<std::string> firstExecRequests; std::deque<std::string> firstExecRequests;
@ -127,6 +129,7 @@ private:
void handleAnimation(const std::string&, const std::string&); void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&); void handleSource(const std::string&, const std::string&);
void handleSubmap(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; inline std::unique_ptr<CConfigManager> g_pConfigManager;

View file

@ -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. 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. autogenerated=1 # remove this line to get rid of the warning on top.
monitor=,1920x1080@60,0x0,1 monitor=,1920x1080@60,0x0,1

View file

@ -13,95 +13,390 @@
#include <string> #include <string>
std::string monitorsRequest() { std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = ""; std::string result = "";
for (auto& m : g_pCompositor->m_vMonitors) { if (format == HyprCtl::FORMAT_JSON) {
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", result += "[";
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);
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; return result;
} }
std::string clientsRequest() { std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = ""; std::string result = "";
for (auto& w : g_pCompositor->m_vWindows) { if (format == HyprCtl::FORMAT_JSON) {
if (w->m_bIsMapped) { result += "[";
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()); 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; return result;
} }
std::string workspacesRequest() { std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = ""; std::string result = "";
for (auto& w : g_pCompositor->m_vWorkspaces) { if (format == HyprCtl::FORMAT_JSON) {
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n", result += "[";
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);
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; return result;
} }
std::string activeWindowRequest() { std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto PWINDOW = g_pCompositor->m_pLastWindow; const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid"; 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", if (format == HyprCtl::FORMAT_JSON) {
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()); 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 = ""; std::string result = "";
for (auto& mon : g_pCompositor->m_vMonitors) { if (format == HyprCtl::FORMAT_JSON) {
result += getFormat("Monitor %s:\n"); result += "{\n";
int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLists) {
result += getFormat("\tLayer level %i:\n", layerLevel);
for (auto& layer : level) { for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height); 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; return result;
} }
std::string devicesRequest() { std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string result = ""; std::string result = "";
result += "mice:\n"; if (format == HyprCtl::FORMAT_JSON) {
result += "{\n";
result += "\"mice\": [\n";
for (auto& m : g_pInputManager->m_lMice) { for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name); result += getFormat(
} R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&m,
m.mouse->name
);
}
result += "\n\nKeyboards:\n"; // remove trailing comma
result.pop_back();
result += "\n],\n";
for (auto& k : g_pInputManager->m_lKeyboards) { result += "\"keyboards\": [\n";
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name); 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\nTablets:\n"; // remove trailing comma
result.pop_back();
result += "\n],\n";
for (auto& d : g_pInputManager->m_lTabletPads) { result += "\"tablets\": [\n";
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) { for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : ""); 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_lTabletTools) { for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0); result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&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);
}
} }
return result; return result;
@ -158,7 +453,7 @@ std::string dispatchKeyword(std::string in) {
if (COMMAND == "monitor") if (COMMAND == "monitor")
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords 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 g_pInputManager->setKeyboardLayout(); // update kb layout
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str()); Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
@ -181,6 +476,10 @@ std::string killRequest() {
return "ok"; return "ok";
} }
std::string splashRequest() {
return g_pCompositor->m_szCurrentSplash;
}
std::string getReply(std::string); std::string getReply(std::string);
std::string dispatchBatch(std::string request) { std::string dispatchBatch(std::string request) {
@ -216,24 +515,46 @@ std::string dispatchBatch(std::string request) {
} }
std::string getReply(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") if (request == "monitors")
return monitorsRequest(); return monitorsRequest(format);
else if (request == "workspaces") else if (request == "workspaces")
return workspacesRequest(); return workspacesRequest(format);
else if (request == "clients") else if (request == "clients")
return clientsRequest(); return clientsRequest(format);
else if (request == "kill") else if (request == "kill")
return killRequest(); return killRequest();
else if (request == "activewindow") else if (request == "activewindow")
return activeWindowRequest(); return activeWindowRequest(format);
else if (request == "layers") else if (request == "layers")
return layersRequest(); return layersRequest(format);
else if (request == "version") else if (request == "version")
return versionRequest(); return versionRequest();
else if (request == "reload") else if (request == "reload")
return reloadRequest(); return reloadRequest();
else if (request == "devices") else if (request == "devices")
return devicesRequest(); return devicesRequest(format);
else if (request == "splash")
return splashRequest();
else if (request.find("dispatch") == 0) else if (request.find("dispatch") == 0)
return dispatchRequest(request); return dispatchRequest(request);
else if (request.find("keyword") == 0) else if (request.find("keyword") == 0)
@ -264,6 +585,16 @@ void HyprCtl::tickHyprCtl() {
} }
std::string getRequestFromThread(std::string rq) { 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) { while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
} }

View file

@ -14,4 +14,9 @@ namespace HyprCtl {
inline std::string request = ""; inline std::string request = "";
inline std::ifstream requestStream; inline std::ifstream requestStream;
enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0,
FORMAT_JSON
};
}; };

View file

@ -16,8 +16,6 @@
#define ISDEBUG false #define ISDEBUG false
#endif #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 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 DYNLISTENFUNC(name) void listener_##name(void*, void*);
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name; #define DYNLISTENER(name) CHyprWLListener hyprListener_##name;

View file

@ -15,145 +15,179 @@
// // // //
// ---------------------------------------------------- // // ---------------------------------------------------- //
void Events::listener_keyboardDestroy(void* owner, void* data) { void Events::listener_keyboardDestroy(void *owner, void *data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner; SKeyboard *PKEYBOARD = (SKeyboard *)owner;
g_pInputManager->destroyKeyboard(PKEYBOARD); 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) { void Events::listener_keyboardKey(void *owner, void *data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner; SKeyboard *PKEYBOARD = (SKeyboard *)owner;
g_pInputManager->onKeyboardKey((wlr_keyboard_key_event*)data, PKEYBOARD); g_pInputManager->onKeyboardKey((wlr_keyboard_key_event *)data, PKEYBOARD);
} }
void Events::listener_keyboardMod(void* owner, void* data) { void Events::listener_keyboardMod(void *owner, void *data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner; SKeyboard *PKEYBOARD = (SKeyboard *)owner;
g_pInputManager->onKeyboardMod(data, PKEYBOARD); g_pInputManager->onKeyboardMod(data, PKEYBOARD);
} }
void Events::listener_mouseFrame(wl_listener* listener, void* data) { void Events::listener_mouseFrame(wl_listener *listener, void *data) {
wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat); wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
} }
void Events::listener_mouseMove(wl_listener* listener, void* data) { void Events::listener_mouseMove(wl_listener *listener, void *data) {
g_pInputManager->onMouseMoved((wlr_pointer_motion_event*)data); g_pInputManager->onMouseMoved((wlr_pointer_motion_event *)data);
} }
void Events::listener_mouseMoveAbsolute(wl_listener* listener, void* data) { void Events::listener_mouseMoveAbsolute(wl_listener *listener, void *data) {
g_pInputManager->onMouseWarp((wlr_pointer_motion_absolute_event*)data); g_pInputManager->onMouseWarp((wlr_pointer_motion_absolute_event *)data);
} }
void Events::listener_mouseButton(wl_listener* listener, void* data) { void Events::listener_mouseButton(wl_listener *listener, void *data) {
g_pInputManager->onMouseButton((wlr_pointer_button_event*)data); g_pInputManager->onMouseButton((wlr_pointer_button_event *)data);
} }
void Events::listener_mouseAxis(wl_listener* listener, void* data) { void Events::listener_mouseAxis(wl_listener *listener, void *data) {
g_pInputManager->onMouseWheel((wlr_pointer_axis_event*)data); g_pInputManager->onMouseWheel((wlr_pointer_axis_event *)data);
} }
void Events::listener_requestMouse(wl_listener* listener, void* data) { void Events::listener_requestMouse(wl_listener *listener, void *data) {
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)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) { void Events::listener_newInput(wl_listener *listener, void *data) {
const auto DEVICE = (wlr_input_device*)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);
}
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);
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->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);
}
}
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);
}
}
PCONSTRAINT->pMouse->currentConstraint = nullptr;
}
Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
}
void Events::listener_setConstraintRegion(void* owner, void* data) {
// no
}
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;
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); 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_destroyMouse(void* owner, void* data) { void Events::listener_newConstraint(wl_listener *listener, void *data) {
const auto PMOUSE = (SMouse*)owner; const auto PCONSTRAINT = (wlr_pointer_constraint_v1 *)data;
g_pInputManager->destroyMouse(PMOUSE->mouse); Debug::log(LOG, "New mouse constraint at %x", PCONSTRAINT);
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->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);
}
}
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);
}
}
PCONSTRAINT->pMouse->currentConstraint = nullptr;
}
Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
}
void Events::listener_setConstraintRegion(void *owner, void *data) {
// no
}
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;
g_pInputManager->newMouse(DEVICE, true);
}
void Events::listener_destroyMouse(void *owner, void *data) {
const auto PMOUSE = (SMouse *)owner;
g_pInputManager->destroyMouse(PMOUSE->mouse);
}
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_swipeUpdate(wl_listener *listener, void *data) {
const auto EVENT = (wlr_pointer_swipe_update_event *)data;
g_pInputManager->onSwipeUpdate(EVENT);
}
void Events::listener_swipeEnd(wl_listener *listener, void *data) {
const auto EVENT = (wlr_pointer_swipe_end_event *)data;
g_pInputManager->onSwipeEnd(EVENT);
} }

View file

@ -49,6 +49,7 @@ namespace Events {
DYNLISTENFUNC(fullscreenWindow); DYNLISTENFUNC(fullscreenWindow);
DYNLISTENFUNC(activateX11); DYNLISTENFUNC(activateX11);
DYNLISTENFUNC(configureX11); DYNLISTENFUNC(configureX11);
DYNLISTENFUNC(unmanagedSetGeometry);
// Window subsurfaces // Window subsurfaces
// LISTENER(newSubsurfaceWindow); // LISTENER(newSubsurfaceWindow);
@ -112,4 +113,13 @@ namespace Events {
// Renderer destroy // Renderer destroy
LISTENER(RendererDestroy); LISTENER(RendererDestroy);
LISTENER(newIdleInhibitor);
LISTENER(swipeBegin);
LISTENER(swipeEnd);
LISTENER(swipeUpdate);
// session
LISTENER(sessionActive);
}; };

View file

@ -32,8 +32,9 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
} }
const auto PMONITOR = (SMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output); 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].emplace_back(new SLayerSurface());
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
if (!WLRLAYERSURFACE->output) { if (!WLRLAYERSURFACE->output) {
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon 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; WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID; 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()); 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; layersurface->layerSurface->mapped = true;
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
// fix if it changed its mon // fix if it changed its mon
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); 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); 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); 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); 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}; 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) if (layersurface->layerSurface->mapped)
layersurface->layerSurface->mapped = false; 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); const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
if (!PMONITOR) if (!PMONITOR)
return; 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}; 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); 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); 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); g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
} }

View file

@ -157,4 +157,10 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
void Events::listener_RendererDestroy(wl_listener* listener, void* data) { void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
Debug::log(LOG, "!!Renderer destroyed!!"); 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;
} }

View file

@ -149,10 +149,10 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle); g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
PNEWWORKSPACE->setActive(true); PNEWWORKSPACE->setActive(true);
//
if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate) if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate)
pMostHzMonitor = PNEWMONITOR; pMostHzMonitor = PNEWMONITOR;
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR; 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) { void Events::listener_monitorFrame(void* owner, void* data) {
SMonitor* const PMONITOR = (SMonitor*)owner; 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 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 startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = 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 PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->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 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 static int damageBlinkCleanup = 0; // because double-buffered
@ -181,28 +187,11 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pDebugOverlay->frameData(PMONITOR); 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) { if (PMONITOR->framesToSkip > 0) {
PMONITOR->framesToSkip -= 1; PMONITOR->framesToSkip -= 1;
if (!PMONITOR->noFrameSchedule) if (!PMONITOR->noFrameSchedule)
wlr_output_schedule_frame(PMONITOR->output); g_pCompositor->scheduleFrameForMonitor(PMONITOR);
else { else {
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str()); Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
} }
@ -210,6 +199,22 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return; 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; timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
@ -228,10 +233,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return; 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) { if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output); 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; return;
} }
@ -266,7 +277,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// potentially can save on resources. // potentially can save on resources.
g_pHyprOpenGL->begin(PMONITOR, &damage); 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_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now); 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_commit(PMONITOR->output);
wlr_output_schedule_frame(PMONITOR->output); if (*PDAMAGEBLINK || *PNOVFR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
if (*PDEBUGOVERLAY == 1) { if (*PDEBUGOVERLAY == 1) {
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f; 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) { if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting."); Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
g_pCompositor->cleanupExit(); g_pCompositor->cleanup();
exit(1);
return; 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; })); 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) { if (pMostHzMonitor == pMonitor) {
int mostHz = 0; int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr; SMonitor* pMonitorMostHz = nullptr;

View file

@ -92,6 +92,9 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
ASSERT(PWINDOW); 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()); 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; const auto WLRPOPUP = (wlr_xdg_popup*)data;

View file

@ -32,6 +32,9 @@ void addViewCoords(void* pWindow, int* x, int* y) {
void Events::listener_mapWindow(void* owner, void* data) { void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner; 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 PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_iMonitorID = PMONITOR->ID;
@ -145,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
try { try {
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1); 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 // we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' '))); 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)); 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 != "") { if (requestedWorkspace != "") {
// process requested workspace // process requested workspace
if (requestedWorkspace.find_first_of(' ') != std::string::npos) { if (requestedWorkspace.contains(' ')) {
// check for silent // check for silent
if (requestedWorkspace.find("silent") != std::string::npos) { if (requestedWorkspace.contains("silent")) {
workspaceSilent = true; workspaceSilent = true;
} }
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' ')); requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
if (requestedWorkspace == "special") {
workspaceSilent = true;
}
} }
if (!workspaceSilent) { if (!workspaceSilent) {
@ -192,8 +199,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" ")); const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1); 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 SIZEX = !SIZEXSTR.contains('%') ? 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 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); 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 POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1); 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 POSX = !POSXSTR.contains('%') ? 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 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); 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); 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); 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); 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_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_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"); 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 // do the animation thing
@ -254,7 +267,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (workspaceSilent) { if (workspaceSilent) {
// move the window // move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) { 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 { } else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!"); 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); g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
} }
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL); 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); 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); 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_activateX11.removeCallback();
PWINDOW->hyprListener_configureX11.removeCallback(); PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback(); PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_setGeometryX11U.removeCallback();
} }
if (PWINDOW->m_bIsFullscreen) { if (PWINDOW->m_bIsFullscreen) {
@ -350,14 +373,19 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// Destroy Foreign Toplevel // Destroy Foreign Toplevel
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel); wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
PWINDOW->m_phForeignToplevel = nullptr; PWINDOW->m_phForeignToplevel = nullptr;
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
} }
void Events::listener_commitWindow(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner; CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
return; 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! // Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
} }
@ -472,6 +500,29 @@ void Events::listener_configureX11(void* owner, void* data) {
g_pHyprRenderer->damageWindow(PWINDOW); 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) { void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data; const auto XWSURFACE = (wlr_xwayland_surface*)data;

View file

@ -128,10 +128,10 @@ public:
case AVARTYPE_COLOR: case AVARTYPE_COLOR:
return m_cValue != m_cGoal; return m_cValue != m_cGoal;
default: default:
return false; std::unreachable();
} }
return false; // unreachable std::unreachable();
} }
void warp() { void warp() {
@ -149,7 +149,7 @@ public:
break; break;
} }
default: default:
break; std::unreachable();
} }
} }

View file

@ -137,7 +137,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
if (source.find_first_of("+") == 0) { if (source.find_first_of("+") == 0) {
try { try {
if (source.find('.') != std::string::npos) if (source.contains("."))
result = relative + std::stof(source.substr(1)); result = relative + std::stof(source.substr(1));
else else
result = relative + std::stoi(source.substr(1)); 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) { } else if (source.find_first_of("-") == 0) {
try { try {
if (source.find('.') != std::string::npos) if (source.contains("."))
result = relative - std::stof(source.substr(1)); result = relative - std::stof(source.substr(1));
else else
result = relative - std::stoi(source.substr(1)); result = relative - std::stoi(source.substr(1));
@ -157,7 +157,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
} }
} else { } else {
try { try {
if (source.find('.') != std::string::npos) if (source.contains("."))
result = stof(source); result = stof(source);
else else
result = stoi(source); result = stoi(source);

56
src/helpers/Splashes.hpp Normal file
View file

@ -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"
};

View file

@ -1,4 +1,5 @@
#include "Vector2D.hpp" #include "Vector2D.hpp"
#include <algorithm>
Vector2D::Vector2D(double xx, double yy) { Vector2D::Vector2D(double xx, double yy) {
x = xx; x = xx;
@ -20,4 +21,11 @@ double Vector2D::normalize() {
Vector2D Vector2D::floor() { Vector2D Vector2D::floor() {
return Vector2D((int)x, (int)y); 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)
);
} }

View file

@ -35,5 +35,7 @@ class Vector2D {
return a.x != x || a.y != y; return a.x != x || a.y != y;
} }
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
Vector2D floor(); Vector2D floor();
}; };

View file

@ -25,10 +25,14 @@ struct SLayerSurface {
int monitorID = -1; int monitorID = -1;
std::string szNamespace = "";
CAnimatedVariable alpha; CAnimatedVariable alpha;
bool fadingOut = false; bool fadingOut = false;
bool readyToDelete = false; bool readyToDelete = false;
bool forceBlur = false;
// For the list lookup // For the list lookup
bool operator==(const SLayerSurface& rhs) { bool operator==(const SLayerSurface& rhs) {
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID; return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
@ -60,6 +64,26 @@ struct SRenderData {
// for custom round values // for custom round values
int rounding = -1; // -1 means not set 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 { struct SKeyboard {
@ -73,7 +97,7 @@ struct SKeyboard {
std::string name = ""; std::string name = "";
xkb_rule_names currentRules = {0}; SStringRuleNames currentRules;
int repeatRate = 0; int repeatRate = 0;
int repeatDelay = 0; int repeatDelay = 0;
int numlockOn = -1; int numlockOn = -1;
@ -94,6 +118,8 @@ struct SMouse {
std::string name = ""; std::string name = "";
bool virt = false;
DYNLISTENER(commitConstraint); DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse); DYNLISTENER(destroyMouse);
@ -221,3 +247,25 @@ struct STabletPad {
return wlrTabletPadV2 == b.wlrTabletPadV2; 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;
};

View file

@ -28,6 +28,7 @@ public:
// for animations // for animations
CAnimatedVariable m_vRenderOffset; CAnimatedVariable m_vRenderOffset;
CAnimatedVariable m_fAlpha; CAnimatedVariable m_fAlpha;
bool m_bForceRendering = false;
// "scratchpad" // "scratchpad"
bool m_bIsSpecialWorkspace = false; bool m_bIsSpecialWorkspace = false;

View file

@ -14,7 +14,7 @@ void CHyprError::createQueued() {
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get(); 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); 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'); 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_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 // outline
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecSize.y); // left cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecSize.x - 1, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // right cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecSize.y - 1, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // bottom cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
cairo_fill(CAIRO); cairo_fill(CAIRO);
@ -70,7 +70,7 @@ void CHyprError::createQueued() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif #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 // delete cairo
cairo_destroy(CAIRO); cairo_destroy(CAIRO);
@ -104,7 +104,7 @@ void CHyprError::draw() {
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR) if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon 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); g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
} }

View file

@ -74,6 +74,7 @@ extern "C" {
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_foreign_toplevel_management_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/util/log.h>
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
#include <wlr/util/region.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_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h> #include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h> #include <wlr/types/wlr_xdg_foreign_v2.h>
#include <wlr/types/wlr_pointer_gestures_v1.h>
} }
#undef class #undef class
@ -118,4 +120,5 @@ extern "C" {
#include "ext-workspace-unstable-v1-protocol.h" #include "ext-workspace-unstable-v1-protocol.h"
#include <algorithm> #include <algorithm>
#include <utility>

View file

@ -23,19 +23,21 @@ void SDwindleNodeData::recalcSizePosRecursive() {
const auto REVERSESPLITRATIO = 2.f - splitRatio; const auto REVERSESPLITRATIO = 2.f - splitRatio;
if (g_pConfigManager->getInt("dwindle:preserve_split") == 0) if (g_pConfigManager->getInt("dwindle:preserve_split") == 0) {
splitTop = size.y > size.x; const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
splitTop = size.y * WIDTHMULTIPLIER > size.x;
}
const auto SPLITSIDE = !splitTop; const auto SPLITSIDE = !splitTop;
if (SPLITSIDE) { if (SPLITSIDE) {
// split sidey // split left/right
children[0]->position = position; children[0]->position = position;
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y); 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]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y);
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y); children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
} else { } else {
// split toppy bottomy // split top/bottom
children[0]->position = position; children[0]->position = position;
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio); children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio); children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio);
@ -93,17 +95,28 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
} }
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) { 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);
return;
}
// Don't set nodes, only windows. // Don't set nodes, only windows.
if (pNode->isNode) if (pNode->isNode)
return; 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);
}
if (!PMONITOR) {
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
return;
}
// for gaps outer // for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
@ -160,9 +173,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
} }
} }
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
if (PWORKSPACE->m_bIsSpecialWorkspace) {
// if special, we adjust the coords a bit // if special, we adjust the coords a bit
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue; 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->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node 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 // 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; NEWPARENT->splitTop = !SIDEBYSIDE;
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split"); const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
if (FORCESPLIT == 0) { 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)) 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, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) { || (!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. // we are hovering over the first node, make PNODE first.
NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[1] = OPENINGON;
NEWPARENT->children[0] = PNODE; NEWPARENT->children[0] = PNODE;
@ -275,14 +289,16 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
} }
// Update the children // 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->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y); 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->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y); PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
} else { } else {
// split toppy bottomy // split top/bottom
OPENINGON->position = NEWPARENT->position; OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f); 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); 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) if (!PWORKSPACE)
return; return;
g_pHyprRenderer->damageMonitor(PMONITOR);
if (PMONITOR->specialWorkspaceOpen) { if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID); 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. // Ignore any recalc events if we have a fullscreen window, but process if fullscreen mode 2
if (PWORKSPACE->m_bHasFullscreenWindow) 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; return;
}
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace); const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
@ -513,6 +548,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
pWindow->m_bIsFullscreen = on; pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; 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 (!pWindow->m_bIsFullscreen) {
// if it got its fullscreen disabled, set back its node if it had one // if it got its fullscreen disabled, set back its node if it had one
const auto PNODE = getNodeFromWindow(pWindow); 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 // we need to fix XWayland windows by sending them to NARNIA
// because otherwise they'd still be recieving mouse events // because otherwise they'd still be recieving mouse events
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace); g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
recalculateMonitor(PMONITOR->ID);
} }
void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) { void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
@ -637,6 +678,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
PPARENT->recalcSizePosRecursive(); PPARENT->recalcSizePosRecursive();
} }
g_pInputManager->refocus();
} }
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) { std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
@ -820,4 +863,4 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
std::string CHyprDwindleLayout::getLayoutName() { std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle"; return "dwindle";
} }

View file

@ -45,7 +45,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f; Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// TODO: detect a popup in a more consistent way. // 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 // 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); pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else { } else {
@ -65,10 +65,12 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv()); pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
} }
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); if (pWindow->m_iX11Type != 2) {
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace); g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
g_pCompositor->moveWindowToTop(pWindow); g_pCompositor->moveWindowToTop(pWindow);
}
} }
void IHyprLayout::onBeginDragWindow() { void IHyprLayout::onBeginDragWindow() {
@ -210,9 +212,23 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
// fix pseudo leaving artifacts // fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
} else { } else {
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
onWindowRemovedTiling(pWindow); onWindowRemovedTiling(pWindow);
g_pCompositor->moveWindowToTop(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));
} }
} }

View file

@ -12,12 +12,22 @@ bool ignoreSudo = false;
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (!getenv("XDG_RUNTIME_DIR")) if (!getenv("XDG_RUNTIME_DIR"))
RIP("XDG_RUNTIME_DIR not set!"); throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
// parse some args // parse some args
std::string configPath;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid")) if (!strcmp(argv[i], "--i-am-really-stupid"))
ignoreSudo = true; 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"); system("mkdir -p /tmp/hypr");
@ -37,6 +47,7 @@ int main(int argc, char** argv) {
// let's init the compositor. // let's init the compositor.
// it initializes basic Wayland stuff in the constructor. // it initializes basic Wayland stuff in the constructor.
g_pCompositor = std::make_unique<CCompositor>(); g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor->explicitConfigPath = configPath;
Debug::log(LOG, "Hyprland init finished."); 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. // If we are here it means we got yote.
Debug::log(LOG, "Hyprland reached the end."); Debug::log(LOG, "Hyprland reached the end.");
g_pCompositor->cleanupExit(); g_pCompositor->cleanup();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -53,15 +53,18 @@ void CAnimationManager::tick() {
const auto PWINDOW = (CWindow*)av->m_pWindow; const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace; const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer; const auto PLAYER = (SLayerSurface*)av->m_pLayer;
SMonitor* PMONITOR = nullptr;
wlr_box WLRBOXPREV = {0,0,0,0}; wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) { if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox(); WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
} else if (PWORKSPACE) { } 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}; WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) { } else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry; 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 // 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) // 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()); 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 != "") { if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
// the window has config'd special anim // the window has config'd special anim
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) { 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 // has a direction
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close); animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
} else { } else {

View file

@ -41,35 +41,48 @@ void CKeybindManager::addKeybind(SKeybind kb) {
void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) { void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { 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); it = m_lKeybinds.erase(it);
if (it == m_lKeybinds.end())
break;
} }
} }
} }
uint32_t CKeybindManager::stringToModMask(std::string mods) { uint32_t CKeybindManager::stringToModMask(std::string mods) {
uint32_t modMask = 0; uint32_t modMask = 0;
if (mods.find("SHIFT") != std::string::npos) if (mods.contains("SHIFT"))
modMask |= WLR_MODIFIER_SHIFT; modMask |= WLR_MODIFIER_SHIFT;
if (mods.find("CAPS") != std::string::npos) if (mods.contains("CAPS"))
modMask |= WLR_MODIFIER_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; modMask |= WLR_MODIFIER_CTRL;
if (mods.find("ALT") != std::string::npos) if (mods.contains("ALT"))
modMask |= WLR_MODIFIER_ALT; modMask |= WLR_MODIFIER_ALT;
if (mods.find("MOD2") != std::string::npos) if (mods.contains("MOD2"))
modMask |= WLR_MODIFIER_MOD2; modMask |= WLR_MODIFIER_MOD2;
if (mods.find("MOD3") != std::string::npos) if (mods.contains("MOD3"))
modMask |= WLR_MODIFIER_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; modMask |= WLR_MODIFIER_LOGO;
if (mods.find("MOD5") != std::string::npos) if (mods.contains("MOD5"))
modMask |= WLR_MODIFIER_MOD5; modMask |= WLR_MODIFIER_MOD5;
return modMask; 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; bool found = false;
if (handleInternalKeybinds(key)) 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) if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap)
continue; 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); 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()); Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
} else { } else {
// call the dispatcher // 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); DISPATCHER->second(k.arg);
} }
@ -118,11 +140,11 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
if (PSESSION) { if (PSESSION) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY); wlr_session_change_vt(PSESSION, TTY);
g_pCompositor->m_bSessionActive = false;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
g_pHyprOpenGL->destroyMonitorResources(m.get()); // mark resources as unusable anymore
m->noFrameSchedule = true; 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); 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)); 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); g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(ACTIVEWINDOW);
} }
} }
@ -253,7 +272,14 @@ void CKeybindManager::changeworkspace(std::string args) {
int workspaceToChangeTo = 0; int workspaceToChangeTo = 0;
std::string workspaceName = ""; 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) { if (workspaceToChangeTo == INT_MAX) {
Debug::log(ERR, "Error in changeworkspace, invalid value"); Debug::log(ERR, "Error in changeworkspace, invalid value");
@ -277,8 +303,6 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace; const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// change it // change it
PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID) if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo; PMONITOR->activeWorkspace = workspaceToChangeTo;
else else
@ -451,7 +475,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
// undo the damage if we are moving to the special workspace // undo the damage if we are moving to the special workspace
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) { 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); OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace(""); toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true); 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); PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
changeworkspace(std::to_string(OLDWORKSPACEIDONMONITOR)); changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDONMONITOR));
changeworkspace(std::to_string(OLDWORKSPACEIDRETURN)); changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDRETURN));
// revert animations // revert animations
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0,0)); 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()) { 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 { } else {
Debug::log(ERR, "Error in focusMonitor: invalid arg 1"); Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
} }
@ -683,7 +707,7 @@ void CKeybindManager::focusMonitor(std::string arg) {
} else { } else {
for (auto& m : g_pCompositor->m_vMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == arg) { if (m->szName == arg) {
changeworkspace(std::to_string(m->activeWorkspace)); changeworkspace("[internal]" + std::to_string(m->activeWorkspace));
return; return;
} }
} }
@ -788,20 +812,20 @@ void CKeybindManager::workspaceOpt(std::string args) {
} }
void CKeybindManager::exitHyprland(std::string argz) { void CKeybindManager::exitHyprland(std::string argz) {
g_pCompositor->cleanupExit(); g_pCompositor->cleanup();
exit(0);
} }
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
if (!isNumber(args) && !isDirection(args)) { SMonitor* PMONITOR = nullptr;
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)); try {
if (!isNumber(args) && !isDirection(args)) {
if (!PMONITOR) { PMONITOR = g_pCompositor->getMonitorFromName(args);
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"); } 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; return;
} }
@ -815,18 +839,25 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
} }
void CKeybindManager::moveWorkspaceToMonitor(std::string args) { void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
if (args.find_first_of(' ') == std::string::npos) if (!args.contains(' '))
return; return;
std::string workspace = args.substr(0, args.find_first_of(' ')); std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1); std::string monitor = args.substr(args.find_first_of(' ') + 1);
if (!isNumber(monitor) && !isDirection(monitor)) { SMonitor* PMONITOR = nullptr;
Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
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; return;
} }
const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
if (!PMONITOR){ if (!PMONITOR){
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist"); Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
@ -882,11 +913,16 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
} }
} }
} else { } 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_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
PSPECIALWORKSPACE->startAnim(true, true); PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID; PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
} }
@ -910,7 +946,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
} }
void CKeybindManager::resizeActive(std::string args) { void CKeybindManager::resizeActive(std::string args) {
if (args.find_first_of(' ') == std::string::npos) if (!args.contains(' '))
return; return;
std::string x = args.substr(0, args.find_first_of(' ')); 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) { void CKeybindManager::moveActive(std::string args) {
if (args.find_first_of(' ') == std::string::npos) if (!args.contains(' '))
return; return;
std::string x = args.substr(0, args.find_first_of(' ')); 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)); 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)) if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return; 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; 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()); 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()); g_pCompositor->focusWindow(w.get());

View file

@ -7,7 +7,8 @@
#include <functional> #include <functional>
struct SKeybind { struct SKeybind {
std::string key = 0; std::string key = "";
int keycode = -1;
uint32_t modmask = 0; uint32_t modmask = 0;
std::string handler = ""; std::string handler = "";
std::string arg = ""; std::string arg = "";
@ -19,7 +20,7 @@ class CKeybindManager {
public: public:
CKeybindManager(); 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 addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&); void removeKeybind(uint32_t, const std::string&);
uint32_t stringToModMask(std::string); uint32_t stringToModMask(std::string);

View file

@ -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); wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(pSurface)->toplevel, activate);
else if (wlr_surface_is_xwayland_surface(pSurface)) { else if (wlr_surface_is_xwayland_surface(pSurface)) {
wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate); 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) { if (pWindow->m_uSurface.xwayland->role) {
try { try {
std::string winrole = std::string(pWindow->m_uSurface.xwayland->role); 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; return true;
} }
} catch (std::exception& e) { } catch (std::exception& e) {
@ -221,6 +223,4 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
if (pWindow->m_phForeignToplevel) if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen); wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
} }

View file

@ -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;
}

View file

@ -28,6 +28,8 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
if (!g_pCompositor->m_bReadyToProcess) if (!g_pCompositor->m_bReadyToProcess)
return; return;
@ -36,10 +38,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
return; return;
} }
if (g_pCompositor->m_sSeat.mouse->virt)
return; // don't refocus on virt
Vector2D mouseCoords = getMouseCoordsInternal(); Vector2D mouseCoords = getMouseCoordsInternal();
const auto MOUSECOORDSFLOORED = mouseCoords.floor(); const auto MOUSECOORDSFLOORED = mouseCoords.floor();
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored) if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
return; return;
m_vLastCursorPosFloored = MOUSECOORDSFLOORED; m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
@ -86,6 +91,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else { } else {
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) { if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
g_pCompositor->m_sSeat.mouse->constraintActive = true; 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) { if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
surfacePos = Vector2D(-1337, -1337);
} else { } else {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow); foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec(); surfacePos = pFoundWindow->m_vRealPosition.vec();
@ -153,9 +160,21 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then windows // then windows
if (!foundSurface) { if (!foundSurface) {
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
else 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); pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
if (pFoundWindow) { if (pFoundWindow) {
@ -183,6 +202,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat); 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; return;
} }
@ -200,7 +225,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} }
if (pFoundWindow) { if (pFoundWindow) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
if (*PFOLLOWMOUSE != 1 && !refocus) { 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)) { 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 // 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 Debug::log(ERR, "Keyboard had no name???"); // logic error
} }
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard"); PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
if (m_pActiveKeyboard) if (m_pActiveKeyboard)
@ -394,7 +418,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
applyConfigToKeyboard(PNEWKEYBOARD); 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); 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); 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 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"); 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"); const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_options") : g_pConfigManager->getString("input:kb_options");
try { 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."); Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return; return;
} }
@ -430,7 +457,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
// we can ignore those and just apply // 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->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE; pKeyboard->repeatRate = REPEATRATE;
@ -443,7 +470,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
.variant = VARIANT.c_str(), .variant = VARIANT.c_str(),
.options = OPTIONS.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); 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); 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)); 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); 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}; wlr_keyboard_modifiers wlrMods = {0};
@ -478,7 +513,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
} }
if (wlrMods.locked != 0) { 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); 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); 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(); m_lMice.emplace_back();
const auto PMOUSE = &m_lMice.back(); const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse; PMOUSE->mouse = mouse;
PMOUSE->virt = virt;
try { try {
PMOUSE->name = std::string(mouse->name); PMOUSE->name = std::string(mouse->name);
} catch(std::exception& e) { } 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); 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 (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) 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); 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 auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t* keysyms; 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); wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
bool found = false; bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
for (int i = 0; i < syms; ++i) 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) { } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// hee hee // hee hee
} }
if (!found) { 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); wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
} }
} }
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) { void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
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_modifiers(g_pCompositor->m_sSeat.seat, &pKeyboard->keyboard->keyboard->modifiers); wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
} }
void CInputManager::refocus() { 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); wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
} }
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;
}

View file

@ -22,7 +22,7 @@ public:
void onKeyboardMod(void*, SKeyboard*); void onKeyboardMod(void*, SKeyboard*);
void newKeyboard(wlr_input_device*); void newKeyboard(wlr_input_device*);
void newMouse(wlr_input_device*); void newMouse(wlr_input_device*, bool virt = false);
void destroyKeyboard(SKeyboard*); void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*); void destroyMouse(wlr_input_device*);
@ -57,9 +57,20 @@ public:
std::list<STabletTool> m_lTabletTools; std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads; std::list<STabletPad> m_lTabletPads;
// idle inhibitors
std::list<SIdleInhibitor> m_lIdleInhibitors;
void newTabletTool(wlr_input_device*); void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*); void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false); 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; SKeyboard* m_pActiveKeyboard = nullptr;
@ -81,6 +92,9 @@ private:
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*); STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
void applyConfigToKeyboard(SKeyboard*); void applyConfigToKeyboard(SKeyboard*);
// for shared mods
uint32_t accumulateModsFromAllKBs();
}; };
inline std::unique_ptr<CInputManager> g_pInputManager; inline std::unique_ptr<CInputManager> g_pInputManager;

View file

@ -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);
}

View file

@ -10,7 +10,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
Debug::log(ERR, "Tablet had no name???"); // logic error 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->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice); PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
PNEWTABLET->wlrTablet->data = PNEWTABLET; PNEWTABLET->wlrTablet->data = PNEWTABLET;
@ -27,7 +27,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
Debug::log(LOG, "Removed a tablet"); Debug::log(LOG, "Removed a tablet");
}, PNEWTABLET, "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 EVENT = (wlr_tablet_tool_axis_event*)data;
const auto PTAB = (STablet*)owner; const auto PTAB = (STablet*)owner;
@ -80,7 +80,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet"); }, 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 EVENT = (wlr_tablet_tool_tip_event*)data;
const auto PTAB = (STablet*)owner; const auto PTAB = (STablet*)owner;
@ -98,7 +98,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet"); }, 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 EVENT = (wlr_tablet_tool_button_event*)data;
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool); const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
@ -107,7 +107,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
}, PNEWTABLET, "Tablet"); }, 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 EVENT = (wlr_tablet_tool_proximity_event*)data;
const auto PTAB = (STablet*)owner; 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->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 EVENT = (wlr_tablet_pad_button_event*)data;
const auto PPAD = (STabletPad*)owner; const auto PPAD = (STabletPad*)owner;
@ -175,7 +175,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad"); }, 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 EVENT = (wlr_tablet_pad_strip_event*)data;
const auto PPAD = (STabletPad*)owner; const auto PPAD = (STabletPad*)owner;
@ -184,7 +184,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad"); }, 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 EVENT = (wlr_tablet_pad_ring_event*)data;
const auto PPAD = (STabletPad*)owner; const auto PPAD = (STabletPad*)owner;
@ -193,7 +193,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
}, PNEWPAD, "Tablet Pad"); }, 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 TABLET = (wlr_tablet_tool*)data;
const auto PPAD = (STabletPad*)owner; const auto PPAD = (STabletPad*)owner;

View file

@ -2,15 +2,14 @@
#include "OpenGL.hpp" #include "OpenGL.hpp"
bool CFramebuffer::alloc(int w, int h) { bool CFramebuffer::alloc(int w, int h) {
bool firstAlloc = false; bool firstAlloc = false;
if (m_iFb == (uint32_t)-1)
{ if (m_iFb == (uint32_t)-1) {
firstAlloc = true; firstAlloc = true;
glGenFramebuffers(1, &m_iFb); glGenFramebuffers(1, &m_iFb);
} }
if (m_cTex.m_iTexID == 0) if (m_cTex.m_iTexID == 0) {
{
firstAlloc = true; firstAlloc = true;
glGenTextures(1, &m_cTex.m_iTexID); glGenTextures(1, &m_cTex.m_iTexID);
glBindTexture(GL_TEXTURE_2D, 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); 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); glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); 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); 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); 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); 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); 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_cTex.m_iTexID = 0;
m_iFb = -1; m_iFb = -1;
} }
CFramebuffer::~CFramebuffer() {
release();
}

View file

@ -6,6 +6,8 @@
class CFramebuffer { class CFramebuffer {
public: public:
~CFramebuffer();
bool alloc(int w, int h); bool alloc(int w, int h);
void bind(); void bind();
void release(); void release();

View file

@ -311,21 +311,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 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()!"); 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()!"); 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); 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(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); 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); 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[] = { const float verts[] = {
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
@ -702,8 +702,6 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
begin(PMONITOR, &fakeDamage, true); begin(PMONITOR, &fakeDamage, true);
pixman_region32_fini(&fakeDamage);
clear(CColor(0,0,0,0)); // JIC clear(CColor(0,0,0,0)); // JIC
timespec now; timespec now;
@ -717,7 +715,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur"); const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0); 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); g_pConfigManager->setInt("decoration:blur", BLURVAL);
@ -742,9 +740,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
#else #else
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb); glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
#endif #endif
end(); end();
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output); wlr_output_rollback(PMONITOR->output);
} }
@ -762,8 +761,6 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
begin(PMONITOR, &fakeDamage, true); begin(PMONITOR, &fakeDamage, true);
pixman_region32_fini(&fakeDamage);
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer]; const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); 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(); end();
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output); 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); 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) { void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); 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 // release the last tex if exists
const auto PTEX = &m_mMonitorBGTextures[pMonitor]; const auto PTEX = &m_mMonitorBGTextures[pMonitor];
PTEX->destroyTexture(); PTEX->destroyTexture();
@ -926,6 +944,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
Debug::log(LOG, "Allocated texture for BGTex"); 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 // check if wallpapers exist
if (!std::filesystem::exists("/usr/share/hyprland/wall_8K.png")) 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. 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); const auto CAIRO = cairo_create(CAIROSURFACE);
if (!*PNOSPLASH)
renderSplash(CAIRO, CAIROSURFACE);
// copy the data to an OpenGL texture we have // copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID); glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
@ -969,9 +993,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
void CHyprOpenGLImpl::clearWithTex() { void CHyprOpenGLImpl::clearWithTex() {
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!"); 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) { void CHyprOpenGLImpl::destroyMonitorResources(SMonitor* pMonitor) {

View file

@ -6,6 +6,8 @@
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include <cairo/cairo.h>
#include "Shaders.hpp" #include "Shaders.hpp"
#include "Shader.hpp" #include "Shader.hpp"
#include "Texture.hpp" #include "Texture.hpp"
@ -45,7 +47,6 @@ struct SCurrentRenderData {
pixman_region32_t* pDamage = nullptr; pixman_region32_t* pDamage = nullptr;
bool renderingPrimarySurface = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
}; };
@ -60,8 +61,8 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0); void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, 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(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 allowPrimary = 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 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 renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round); void renderBorder(wlr_box*, const CColor&, int round);
@ -121,7 +122,9 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); 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; inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;

View file

@ -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_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY);
wlr_box windowBox; 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}; 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)}; 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); scaleBox(&windowBox, RDATA->output->scale);
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding; float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false;
if (RDATA->surface && surface == RDATA->surface) { if (RDATA->surface && surface == RDATA->surface) {
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true; if (RDATA->blur)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding); 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) { if (RDATA->decorate) {
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col(); 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); g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
} }
} }
else else {
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false); 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); wlr_surface_send_frame_done(surface, RDATA->when);
@ -54,8 +72,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
return true; return true;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); 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 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 (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; return true;
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
@ -93,7 +111,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
continue; continue;
// found it! // 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(); 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) if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue; continue;
renderWindow(w.get(), pMonitor, time, true); renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
} }
// and then special windows // and then special windows
@ -118,7 +136,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
continue; continue;
// render the bad boy // render the bad boy
renderWindow(w.get(), pMonitor, time, true); renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
} }
// and the overlay layers // and the overlay layers
@ -140,7 +158,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
g_pHyprError->draw(); 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) if (pWindow->m_bHidden)
return; 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.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.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f); 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.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.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 // apply window special data
if (pWindow->m_sSpecialRenderData.alphaInactive == -1) if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
@ -173,37 +193,40 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow; g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first, if not fullscreen full // 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) { 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);
// To everyone who makes apps with improperly aligned surfaces, if (!pWindow->m_bIsX11) {
// For example chromium, or GTK devs who allow shadows on windows, wlr_box geom;
// a sincere FUCK YOU. wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
wlr_box 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);
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); 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); if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
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); // No special UV mods needed
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) { g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
// No special UV mods needed }
} else {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
} }
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);
} }
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
if (!pWindow->m_bIsX11) {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); renderdata.dontRound = false; // restore dontround
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); renderdata.pMonitor = pMonitor;
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
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; 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}; SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y};
renderdata.fadeAlpha = pLayer->alpha.fl(); 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); wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
} }
@ -243,7 +271,25 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
return; 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) { for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut) if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue; continue;
@ -258,7 +304,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue; continue;
// render the bad boy // render the bad boy
renderWindow(w.get(), PMONITOR, time, true); renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_POPUP);
} }
// floating on top // floating on top
@ -276,7 +322,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue; continue;
// render the bad boy // render the bad boy
renderWindow(w.get(), PMONITOR, time, true); renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
} }
// and then special // and then special
@ -291,7 +337,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue; continue;
// render the bad boy // 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 // 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}; wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
for (auto& ls : layerSurfaces) { for (auto& ls : layerSurfaces) {
if (ls->fadingOut || ls->readyToDelete) if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface)
continue; continue;
const auto PLAYER = ls->layerSurface; const auto PLAYER = ls->layerSurface;
@ -551,6 +597,11 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox); pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &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)) { if (!pixman_region32_not_empty(&damageBox)) {
pixman_region32_fini(&damageBox); pixman_region32_fini(&damageBox);
return; return;
@ -799,4 +850,4 @@ void CHyprRenderer::ensureCursorRenderingMode() {
bool CHyprRenderer::shouldRenderCursor() { bool CHyprRenderer::shouldRenderCursor() {
return m_bHasARenderedCursor; return m_bHasARenderedCursor;
} }

View file

@ -17,6 +17,12 @@ enum DAMAGETRACKINGMODES {
DAMAGE_TRACKING_FULL DAMAGE_TRACKING_FULL
}; };
enum eRenderPassMode {
RENDER_PASS_ALL = 0,
RENDER_PASS_MAIN,
RENDER_PASS_POPUP
};
class CHyprRenderer { class CHyprRenderer {
public: public:
@ -41,7 +47,7 @@ public:
private: private:
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*); void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*); void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
void renderWindow(CWindow*, SMonitor*, timespec*, bool); void renderWindow(CWindow*, SMonitor*, timespec*, bool, eRenderPassMode);
void renderLayer(SLayerSurface*, SMonitor*, timespec*); void renderLayer(SLayerSurface*, SMonitor*, timespec*);
void renderDragIcon(SMonitor*, timespec*); void renderDragIcon(SMonitor*, timespec*);

View file

@ -40,12 +40,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") { if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
// ???? // ????
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) { m_pWindow->m_vDecosToRemove.push_back(this);
if (it->get() == this) { return;
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
} }
// get the group info // get the group info
@ -58,12 +54,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
if (m_dwGroupMembers.size() == 0) { if (m_dwGroupMembers.size() == 0) {
// remove // remove
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) { m_pWindow->m_vDecosToRemove.push_back(this);
if (it->get() == this) { return;
pWindow->m_dWindowDecorations.erase(it);
return;
}
}
} }
} }

@ -1 +1 @@
Subproject commit 5c4384a1330faedf975c8b8644881d50390f3613 Subproject commit b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc