Merge branch 'hyprwm:main' into feature/cornerRadii
|
@ -58,7 +58,7 @@ ExternalProject_Add(
|
||||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||||
PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build
|
PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build
|
||||||
CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure
|
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
|
||||||
BUILD_COMMAND ninja -C build
|
BUILD_COMMAND ninja -C build
|
||||||
BUILD_ALWAYS true
|
BUILD_ALWAYS true
|
||||||
BUILD_IN_SOURCE true
|
BUILD_IN_SOURCE true
|
||||||
|
|
11
Makefile
|
@ -1,22 +1,22 @@
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
||||||
legacyrenderer:
|
legacyrenderer:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
legacyrendererdebug:
|
legacyrendererdebug:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
release:
|
release:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
chmod -R 777 ./build
|
chmod -R 777 ./build
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ install:
|
||||||
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
|
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
|
||||||
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||||
mkdir -p ${PREFIX}/share/hyprland
|
mkdir -p ${PREFIX}/share/hyprland
|
||||||
cp ./assets/wall_* ${PREFIX}/share/hyprland
|
cp ./assets/wall* ${PREFIX}/share/hyprland
|
||||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ install:
|
||||||
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/hyprland
|
||||||
rm -f ${PREFIX}/bin/hyprctl
|
rm -f ${PREFIX}/bin/hyprctl
|
||||||
rm -f ${PREFIX}/bin/hyprpm
|
rm -f ${PREFIX}/bin/hyprpm
|
||||||
rm -f ${PREFIX}/lib/libwlroots.so.13032
|
rm -f ${PREFIX}/lib/libwlroots.so.13032
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
wallpaper_types = ['', 'anime_', 'anime2_']
|
wallpapers = ['0', '1', '2']
|
||||||
|
|
||||||
foreach type : wallpaper_types
|
foreach type : wallpapers
|
||||||
foreach size : [2, 4, 8]
|
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||||
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
|
||||||
endforeach
|
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||||
|
|
BIN
assets/wall0.png
Normal file
After Width: | Height: | Size: 14 MiB |
BIN
assets/wall1.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
assets/wall2.png
Normal file
After Width: | Height: | Size: 27 MiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 511 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 502 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.6 MiB |
|
@ -112,7 +112,7 @@ gestures {
|
||||||
|
|
||||||
misc {
|
misc {
|
||||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||||
}
|
}
|
||||||
|
|
||||||
# Example per-device config
|
# Example per-device config
|
||||||
|
|
41
flake.lock
|
@ -25,7 +25,10 @@
|
||||||
},
|
},
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": [
|
||||||
|
"xdph",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704287638,
|
"lastModified": 1704287638,
|
||||||
|
@ -43,27 +46,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704194953,
|
"lastModified": 1706191920,
|
||||||
"narHash": "sha256-RtDKd8Mynhe5CFnVT8s0/0yqtWFMM9LmCzXv/YKxnq4=",
|
"narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "bd645e8668ec6612439a9ee7e71f7eac4099d4f6",
|
"rev": "ae5c332cbb5827f6b1f02572496b141021de335f",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1702645756,
|
|
||||||
"narHash": "sha256-qKI6OR3TYJYQB3Q8mAZ+DG4o/BR9ptcv9UnRV2hzljc=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "40c3c94c241286dd2243ea34d3aef8a488f9e4d0",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -101,18 +88,18 @@
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"lastModified": 1703963193,
|
"lastModified": 1706359063,
|
||||||
"narHash": "sha256-ke8drv6PTrdQDruWbajrRJffP9A9PU6FRyjJGNZRTs4=",
|
"narHash": "sha256-5HUTG0p+nCJv3cn73AmFHRZdfRV5AD5N43g8xAePSKM=",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "f81c3d93cd6f61b20ae784297679283438def8df",
|
"rev": "00b869c1a96f300a8f25da95d624524895e0ddf2",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "f81c3d93cd6f61b20ae784297679283438def8df",
|
"rev": "00b869c1a96f300a8f25da95d624524895e0ddf2",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -130,11 +117,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704400467,
|
"lastModified": 1706145785,
|
||||||
"narHash": "sha256-IsEAKBCorRlN53FwFAMbyGLRsPVu/ZrWEJtCwykPds8=",
|
"narHash": "sha256-j9MP4fv2U/vdRKAXXc2gyMTmYwVnHP6kHx1/y6jprrU=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
"rev": "1c802128f6cc3db29a8ef01552b1a22f894eeefd",
|
"rev": "5a592647587cd20b9692a347df6939b6d371b3bb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
host = "gitlab.freedesktop.org";
|
host = "gitlab.freedesktop.org";
|
||||||
owner = "wlroots";
|
owner = "wlroots";
|
||||||
repo = "wlroots";
|
repo = "wlroots";
|
||||||
rev = "f81c3d93cd6f61b20ae784297679283438def8df";
|
rev = "00b869c1a96f300a8f25da95d624524895e0ddf2";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@
|
||||||
name = "hyprland-shell";
|
name = "hyprland-shell";
|
||||||
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
||||||
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||||
|
hardeningDisable = [ "fortify" ];
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
self.packages.${system}.wlroots-hyprland
|
self.packages.${system}.wlroots-hyprland
|
||||||
self.packages.${system}.hyprland
|
self.packages.${system}.hyprland
|
||||||
|
|
|
@ -20,11 +20,18 @@ std::string DataState::getDataStatePath() {
|
||||||
return std::string{HOME} + "/.local/share/hyprpm";
|
return std::string{HOME} + "/.local/share/hyprpm";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DataState::getHeadersPath() {
|
||||||
|
return getDataStatePath() + "/headersRoot";
|
||||||
|
}
|
||||||
|
|
||||||
void DataState::ensureStateStoreExists() {
|
void DataState::ensureStateStoreExists() {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
if (!std::filesystem::exists(PATH))
|
if (!std::filesystem::exists(PATH))
|
||||||
std::filesystem::create_directories(PATH);
|
std::filesystem::create_directories(PATH);
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(getHeadersPath()))
|
||||||
|
std::filesystem::create_directories(getHeadersPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||||
|
@ -64,7 +71,10 @@ bool DataState::pluginRepoExists(const std::string& urlOrName) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -85,7 +95,10 @@ void DataState::removePluginRepo(const std::string& urlOrName) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -154,7 +167,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
||||||
std::vector<SPluginRepository> repos;
|
std::vector<SPluginRepository> repos;
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
@ -191,7 +207,10 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
||||||
const auto PATH = getDataStatePath();
|
const auto PATH = getDataStatePath();
|
||||||
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||||
if (!entry.is_directory())
|
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct SGlobalState {
|
||||||
|
|
||||||
namespace DataState {
|
namespace DataState {
|
||||||
std::string getDataStatePath();
|
std::string getDataStatePath();
|
||||||
|
std::string getHeadersPath();
|
||||||
void ensureStateStoreExists();
|
void ensureStateStoreExists();
|
||||||
void addNewPluginRepo(const SPluginRepository& repo);
|
void addNewPluginRepo(const SPluginRepository& repo);
|
||||||
void removePluginRepo(const std::string& urlOrName);
|
void removePluginRepo(const std::string& urlOrName);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
|
|
||||||
|
@ -78,6 +79,8 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||||
|
|
||||||
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
|
|
||||||
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
if (DataState::pluginRepoExists(url)) {
|
if (DataState::pluginRepoExists(url)) {
|
||||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||||
return false;
|
return false;
|
||||||
|
@ -170,6 +173,22 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
message += " version " + pl.version;
|
message += " version " + pl.version;
|
||||||
progress.printMessageAbove(message);
|
progress.printMessageAbove(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pManifest->m_sRepository.commitPins.empty()) {
|
||||||
|
// check commit pins
|
||||||
|
|
||||||
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||||
|
|
||||||
|
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||||
|
if (hl != HLVER.hash)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||||
|
|
||||||
|
execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress.m_szCurrentMessage = "Verifying headers";
|
progress.m_szCurrentMessage = "Verifying headers";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
|
@ -191,7 +210,8 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||||
|
|
||||||
for (auto& bs : p.buildSteps) {
|
for (auto& bs : p.buildSteps) {
|
||||||
out += execAndGet("cd /tmp/hyprpm/new && " + bs) + "\n";
|
std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}\" {}", DataState::getHeadersPath(), bs);
|
||||||
|
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
||||||
|
@ -265,8 +285,12 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||||
eHeadersErrors CPluginManager::headersValid() {
|
eHeadersErrors CPluginManager::headersValid() {
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
|
||||||
|
return HEADERS_MISSING;
|
||||||
|
|
||||||
// find headers commit
|
// find headers commit
|
||||||
auto headers = execAndGet("pkg-config --cflags --keep-system-cflags hyprland");
|
std::string cmd = std::format("PKG_CONFIG_PATH={}/share/pkgconfig pkg-config --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||||
|
auto headers = execAndGet(cmd.c_str());
|
||||||
|
|
||||||
if (!headers.contains("-I/"))
|
if (!headers.contains("-I/"))
|
||||||
return HEADERS_MISSING;
|
return HEADERS_MISSING;
|
||||||
|
@ -298,10 +322,6 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||||
if (!ifs.good())
|
if (!ifs.good())
|
||||||
return HEADERS_CORRUPTED;
|
return HEADERS_CORRUPTED;
|
||||||
|
|
||||||
if ((std::filesystem::exists("/usr/include/hyprland/src/version.h") && verHeader != "/usr/include/hyprland/src/version.h") ||
|
|
||||||
(std::filesystem::exists("/usr/local/include/hyprland/src/version.h") && verHeader != "/usr/local/include/hyprland/src/version.h"))
|
|
||||||
return HEADERS_DUPLICATED;
|
|
||||||
|
|
||||||
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
|
||||||
|
@ -316,7 +336,9 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||||
return HEADERS_OK;
|
return HEADERS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPluginManager::updateHeaders() {
|
bool CPluginManager::updateHeaders(bool force) {
|
||||||
|
|
||||||
|
DataState::ensureStateStoreExists();
|
||||||
|
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
|
@ -325,11 +347,8 @@ bool CPluginManager::updateHeaders() {
|
||||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headersValid() == HEADERS_OK) {
|
if (!force && headersValid() == HEADERS_OK) {
|
||||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Your headers are already up-to-date.\n";
|
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
|
||||||
DataState::updateGlobalState(GLOBALSTATE);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,23 +390,38 @@ bool CPluginManager::updateHeaders() {
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
||||||
|
|
||||||
ret = execAndGet("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja");
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||||
|
|
||||||
|
ret = execAndGet(
|
||||||
|
std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja",
|
||||||
|
DataState::getHeadersPath()));
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||||
|
|
||||||
// le hack. Wlroots has to generate its build/include
|
// le hack. Wlroots has to generate its build/include
|
||||||
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build");
|
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build");
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||||
progress.m_iSteps = 4;
|
progress.m_iSteps = 4;
|
||||||
progress.m_szCurrentMessage = "Installing sources";
|
progress.m_szCurrentMessage = "Installing sources";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
progress.printMessageAbove(
|
// progress.printMessageAbove(
|
||||||
std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
// std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
||||||
" in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
// " in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
||||||
|
|
||||||
ret = execAndGet("pkexec sh \"-c\" \"cd /tmp/hyprpm/hyprland && make installheaders\"");
|
std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders",
|
||||||
|
DataState::getHeadersPath());
|
||||||
|
if (m_bVerbose)
|
||||||
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||||
|
|
||||||
|
ret = execAndGet(cmd);
|
||||||
|
|
||||||
if (m_bVerbose)
|
if (m_bVerbose)
|
||||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "pkexec returned: " << ret << "\n";
|
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||||
|
|
||||||
// remove build files
|
// remove build files
|
||||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||||
|
@ -399,10 +433,6 @@ bool CPluginManager::updateHeaders() {
|
||||||
progress.m_szCurrentMessage = "Done!";
|
progress.m_szCurrentMessage = "Done!";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
|
||||||
DataState::updateGlobalState(GLOBALSTATE);
|
|
||||||
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
} else {
|
} else {
|
||||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||||
|
@ -436,7 +466,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
const auto HLVER = getHyprlandVersion();
|
const auto HLVER = getHyprlandVersion();
|
||||||
|
|
||||||
CProgressBar progress;
|
CProgressBar progress;
|
||||||
progress.m_iMaxSteps = REPOS.size() * 2 + 1;
|
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||||
progress.m_iSteps = 0;
|
progress.m_iSteps = 0;
|
||||||
progress.m_szCurrentMessage = "Updating repositories";
|
progress.m_szCurrentMessage = "Updating repositories";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
@ -530,7 +560,8 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||||
|
|
||||||
for (auto& bs : p.buildSteps) {
|
for (auto& bs : p.buildSteps) {
|
||||||
out += execAndGet("cd /tmp/hyprpm/update && " + bs) + "\n";
|
std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}\" {}", DataState::getHeadersPath(), bs);
|
||||||
|
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
||||||
|
@ -568,6 +599,14 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress.m_iSteps++;
|
||||||
|
progress.m_szCurrentMessage = "Updating global state...";
|
||||||
|
progress.print();
|
||||||
|
|
||||||
|
auto GLOBALSTATE = DataState::getGlobalState();
|
||||||
|
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||||
|
DataState::updateGlobalState(GLOBALSTATE);
|
||||||
|
|
||||||
progress.m_iSteps++;
|
progress.m_iSteps++;
|
||||||
progress.m_szCurrentMessage = "Done!";
|
progress.m_szCurrentMessage = "Done!";
|
||||||
progress.print();
|
progress.print();
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CPluginManager {
|
||||||
bool removePluginRepo(const std::string& urlOrName);
|
bool removePluginRepo(const std::string& urlOrName);
|
||||||
|
|
||||||
eHeadersErrors headersValid();
|
eHeadersErrors headersValid();
|
||||||
bool updateHeaders();
|
bool updateHeaders(bool force = false);
|
||||||
bool updatePlugins(bool forceUpdateAll);
|
bool updatePlugins(bool forceUpdateAll);
|
||||||
|
|
||||||
void listAllPlugins();
|
void listAllPlugins();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "progress/CProgressBar.hpp"
|
#include "progress/CProgressBar.hpp"
|
||||||
#include "helpers/Colors.hpp"
|
#include "helpers/Colors.hpp"
|
||||||
#include "core/PluginManager.hpp"
|
#include "core/PluginManager.hpp"
|
||||||
|
#include "core/DataState.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -23,6 +24,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||||
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
||||||
┣ --help | -h → Show this menu
|
┣ --help | -h → Show this menu
|
||||||
┣ --verbose | -v → Enable too much logging
|
┣ --verbose | -v → Enable too much logging
|
||||||
|
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||||
┗
|
┗
|
||||||
)#";
|
)#";
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> command;
|
std::vector<std::string> command;
|
||||||
bool notify = false, verbose = false;
|
bool notify = false, verbose = false, force = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
if (ARGS[i].starts_with("-")) {
|
if (ARGS[i].starts_with("-")) {
|
||||||
|
@ -49,6 +51,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
notify = true;
|
notify = true;
|
||||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||||
|
force = true;
|
||||||
|
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Unrecognized option " << ARGS[i];
|
std::cerr << "Unrecognized option " << ARGS[i];
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -82,9 +87,13 @@ int main(int argc, char** argv, char** envp) {
|
||||||
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
||||||
} else if (command[0] == "update") {
|
} else if (command[0] == "update") {
|
||||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
||||||
bool headers = g_pPluginManager->updateHeaders();
|
bool headers = g_pPluginManager->updateHeaders(force);
|
||||||
if (headers) {
|
if (headers) {
|
||||||
bool ret1 = g_pPluginManager->updatePlugins(!headersValid);
|
const auto HLVER = g_pPluginManager->getHyprlandVersion();
|
||||||
|
auto GLOBALSTATE = DataState::getGlobalState();
|
||||||
|
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
|
||||||
|
|
||||||
|
bool ret1 = g_pPluginManager->updatePlugins(!headersValid || force || COMPILEDOUTDATED);
|
||||||
|
|
||||||
if (!ret1)
|
if (!ret1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -10,19 +10,16 @@
|
||||||
(builtins.substring 4 2 longDate)
|
(builtins.substring 4 2 longDate)
|
||||||
(builtins.substring 6 2 longDate)
|
(builtins.substring 6 2 longDate)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
mkJoinedOverlays = overlays: final: prev:
|
|
||||||
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
|
|
||||||
in {
|
in {
|
||||||
# Contains what a user is most likely to care about:
|
# Contains what a user is most likely to care about:
|
||||||
# Hyprland itself, XDPH and the Share Picker.
|
# Hyprland itself, XDPH and the Share Picker.
|
||||||
default = mkJoinedOverlays (with self.overlays; [
|
default = lib.composeManyExtensions (with self.overlays; [
|
||||||
hyprland-packages
|
hyprland-packages
|
||||||
hyprland-extras
|
hyprland-extras
|
||||||
]);
|
]);
|
||||||
|
|
||||||
# Packages for variations of Hyprland, dependencies included.
|
# Packages for variations of Hyprland, dependencies included.
|
||||||
hyprland-packages = mkJoinedOverlays [
|
hyprland-packages = lib.composeManyExtensions [
|
||||||
# Dependencies
|
# Dependencies
|
||||||
inputs.hyprland-protocols.overlays.default
|
inputs.hyprland-protocols.overlays.default
|
||||||
self.overlays.wlroots-hyprland
|
self.overlays.wlroots-hyprland
|
||||||
|
@ -34,7 +31,7 @@ in {
|
||||||
hyprland = final.callPackage ./default.nix {
|
hyprland = final.callPackage ./default.nix {
|
||||||
stdenv = final.gcc13Stdenv;
|
stdenv = final.gcc13Stdenv;
|
||||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||||
wlroots = final.wlroots-hyprland;
|
wlroots = prev.wlroots-hyprland;
|
||||||
commit = self.rev or "";
|
commit = self.rev or "";
|
||||||
inherit (final) udis86 hyprland-protocols;
|
inherit (final) udis86 hyprland-protocols;
|
||||||
inherit date;
|
inherit date;
|
||||||
|
@ -59,7 +56,7 @@ in {
|
||||||
|
|
||||||
# Packages for extra software recommended for usage with Hyprland,
|
# Packages for extra software recommended for usage with Hyprland,
|
||||||
# including forked or patched packages for compatibility.
|
# including forked or patched packages for compatibility.
|
||||||
hyprland-extras = mkJoinedOverlays [
|
hyprland-extras = lib.composeManyExtensions [
|
||||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
||||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||||
echo "Updating wlroots..."
|
echo "Updating wlroots..."
|
||||||
# update wlroots to submodule revision
|
# update wlroots to submodule revision
|
||||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix subprojects/wlroots.wrap
|
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
|
||||||
nix flake lock
|
nix flake lock
|
||||||
|
|
||||||
echo "wlroots: $CRT_REV -> $SUB_REV"
|
echo "wlroots: $CRT_REV -> $SUB_REV"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
wayland_protos = dependency('wayland-protocols',
|
wayland_protos = dependency('wayland-protocols',
|
||||||
version: '>=1.25',
|
version: '>=1.32',
|
||||||
fallback: 'wayland-protocols',
|
fallback: 'wayland-protocols',
|
||||||
default_options: ['tests=false'],
|
default_options: ['tests=false'],
|
||||||
)
|
)
|
||||||
|
|
|
@ -81,26 +81,6 @@ CCompositor::CCompositor() {
|
||||||
|
|
||||||
CCompositor::~CCompositor() {
|
CCompositor::~CCompositor() {
|
||||||
cleanup();
|
cleanup();
|
||||||
g_pDecorationPositioner.reset();
|
|
||||||
g_pPluginSystem.reset();
|
|
||||||
g_pHyprNotificationOverlay.reset();
|
|
||||||
g_pDebugOverlay.reset();
|
|
||||||
g_pEventManager.reset();
|
|
||||||
g_pSessionLockManager.reset();
|
|
||||||
g_pProtocolManager.reset();
|
|
||||||
g_pXWaylandManager.reset();
|
|
||||||
g_pHyprRenderer.reset();
|
|
||||||
g_pHyprOpenGL.reset();
|
|
||||||
g_pInputManager.reset();
|
|
||||||
g_pThreadManager.reset();
|
|
||||||
g_pConfigManager.reset();
|
|
||||||
g_pLayoutManager.reset();
|
|
||||||
g_pHyprError.reset();
|
|
||||||
g_pConfigManager.reset();
|
|
||||||
g_pAnimationManager.reset();
|
|
||||||
g_pKeybindManager.reset();
|
|
||||||
g_pHookSystem.reset();
|
|
||||||
g_pWatchdog.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::setRandomSplash() {
|
void CCompositor::setRandomSplash() {
|
||||||
|
@ -135,10 +115,10 @@ void CCompositor::initServer() {
|
||||||
else
|
else
|
||||||
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
||||||
|
|
||||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession);
|
m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession);
|
||||||
|
|
||||||
if (!m_sWLRBackend) {
|
if (!m_sWLRBackend) {
|
||||||
Debug::log(CRIT, "m_sWLRBackend was NULL!");
|
Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||||
throwError("wlr_backend_autocreate() failed!");
|
throwError("wlr_backend_autocreate() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +131,7 @@ void CCompositor::initServer() {
|
||||||
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! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||||
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +239,7 @@ void CCompositor::initServer() {
|
||||||
|
|
||||||
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
|
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay);
|
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
||||||
|
|
||||||
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
|
@ -332,6 +312,59 @@ void CCompositor::initAllSignals() {
|
||||||
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCompositor::removeAllSignals() {
|
||||||
|
removeWLSignal(&Events::listen_newOutput);
|
||||||
|
removeWLSignal(&Events::listen_newXDGToplevel);
|
||||||
|
removeWLSignal(&Events::listen_mouseMove);
|
||||||
|
removeWLSignal(&Events::listen_mouseMoveAbsolute);
|
||||||
|
removeWLSignal(&Events::listen_mouseButton);
|
||||||
|
removeWLSignal(&Events::listen_mouseAxis);
|
||||||
|
removeWLSignal(&Events::listen_mouseFrame);
|
||||||
|
removeWLSignal(&Events::listen_swipeBegin);
|
||||||
|
removeWLSignal(&Events::listen_swipeUpdate);
|
||||||
|
removeWLSignal(&Events::listen_swipeEnd);
|
||||||
|
removeWLSignal(&Events::listen_pinchBegin);
|
||||||
|
removeWLSignal(&Events::listen_pinchUpdate);
|
||||||
|
removeWLSignal(&Events::listen_pinchEnd);
|
||||||
|
removeWLSignal(&Events::listen_touchBegin);
|
||||||
|
removeWLSignal(&Events::listen_touchEnd);
|
||||||
|
removeWLSignal(&Events::listen_touchUpdate);
|
||||||
|
removeWLSignal(&Events::listen_touchFrame);
|
||||||
|
removeWLSignal(&Events::listen_holdBegin);
|
||||||
|
removeWLSignal(&Events::listen_holdEnd);
|
||||||
|
removeWLSignal(&Events::listen_newInput);
|
||||||
|
removeWLSignal(&Events::listen_requestMouse);
|
||||||
|
removeWLSignal(&Events::listen_requestSetSel);
|
||||||
|
removeWLSignal(&Events::listen_requestDrag);
|
||||||
|
removeWLSignal(&Events::listen_startDrag);
|
||||||
|
removeWLSignal(&Events::listen_requestSetSel);
|
||||||
|
removeWLSignal(&Events::listen_requestSetPrimarySel);
|
||||||
|
removeWLSignal(&Events::listen_newLayerSurface);
|
||||||
|
removeWLSignal(&Events::listen_change);
|
||||||
|
removeWLSignal(&Events::listen_outputMgrApply);
|
||||||
|
removeWLSignal(&Events::listen_outputMgrTest);
|
||||||
|
removeWLSignal(&Events::listen_newConstraint);
|
||||||
|
removeWLSignal(&Events::listen_NewXDGDeco);
|
||||||
|
removeWLSignal(&Events::listen_newVirtPtr);
|
||||||
|
removeWLSignal(&Events::listen_newVirtualKeyboard);
|
||||||
|
removeWLSignal(&Events::listen_RendererDestroy);
|
||||||
|
removeWLSignal(&Events::listen_newIdleInhibitor);
|
||||||
|
removeWLSignal(&Events::listen_powerMgrSetMode);
|
||||||
|
removeWLSignal(&Events::listen_newIME);
|
||||||
|
removeWLSignal(&Events::listen_newTextInput);
|
||||||
|
removeWLSignal(&Events::listen_activateXDG);
|
||||||
|
removeWLSignal(&Events::listen_newSessionLock);
|
||||||
|
removeWLSignal(&Events::listen_setGamma);
|
||||||
|
removeWLSignal(&Events::listen_setCursorShape);
|
||||||
|
removeWLSignal(&Events::listen_newTearingHint);
|
||||||
|
|
||||||
|
if (m_sWRLDRMLeaseMgr)
|
||||||
|
removeWLSignal(&Events::listen_leaseRequest);
|
||||||
|
|
||||||
|
if (m_sWLRSession)
|
||||||
|
removeWLSignal(&Events::listen_sessionActive);
|
||||||
|
}
|
||||||
|
|
||||||
void CCompositor::cleanup() {
|
void CCompositor::cleanup() {
|
||||||
if (!m_sWLDisplay || m_bIsShuttingDown)
|
if (!m_sWLDisplay || m_bIsShuttingDown)
|
||||||
return;
|
return;
|
||||||
|
@ -362,8 +395,8 @@ void CCompositor::cleanup() {
|
||||||
for (auto& m : m_vMonitors) {
|
for (auto& m : m_vMonitors) {
|
||||||
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
||||||
|
|
||||||
wlr_output_enable(m->output, false);
|
wlr_output_state_set_enabled(m->state.wlr(), false);
|
||||||
wlr_output_commit(m->output);
|
m->state.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vMonitors.clear();
|
m_vMonitors.clear();
|
||||||
|
@ -373,8 +406,31 @@ void CCompositor::cleanup() {
|
||||||
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeAllSignals();
|
||||||
|
|
||||||
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
||||||
|
|
||||||
|
g_pDecorationPositioner.reset();
|
||||||
|
g_pPluginSystem.reset();
|
||||||
|
g_pHyprNotificationOverlay.reset();
|
||||||
|
g_pDebugOverlay.reset();
|
||||||
|
g_pEventManager.reset();
|
||||||
|
g_pSessionLockManager.reset();
|
||||||
|
g_pProtocolManager.reset();
|
||||||
|
g_pHyprRenderer.reset();
|
||||||
|
g_pHyprOpenGL.reset();
|
||||||
|
g_pInputManager.reset();
|
||||||
|
g_pThreadManager.reset();
|
||||||
|
g_pConfigManager.reset();
|
||||||
|
g_pLayoutManager.reset();
|
||||||
|
g_pHyprError.reset();
|
||||||
|
g_pConfigManager.reset();
|
||||||
|
g_pAnimationManager.reset();
|
||||||
|
g_pKeybindManager.reset();
|
||||||
|
g_pHookSystem.reset();
|
||||||
|
g_pWatchdog.reset();
|
||||||
|
g_pXWaylandManager.reset();
|
||||||
|
|
||||||
wl_display_terminate(m_sWLDisplay);
|
wl_display_terminate(m_sWLDisplay);
|
||||||
|
|
||||||
m_sWLDisplay = nullptr;
|
m_sWLDisplay = nullptr;
|
||||||
|
@ -654,6 +710,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||||
|
static auto* const PSPECIALFALLTHRU = &g_pConfigManager->getConfigValuePtr("input:special_fallthrough")->intValue;
|
||||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||||
|
|
||||||
// pinned windows on top of floating regardless
|
// pinned windows on top of floating regardless
|
||||||
|
@ -735,9 +792,16 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||||
};
|
};
|
||||||
|
|
||||||
// special workspace
|
// special workspace
|
||||||
if (PMONITOR->specialWorkspaceID)
|
if (PMONITOR->specialWorkspaceID && !*PSPECIALFALLTHRU)
|
||||||
return windowForWorkspace(true);
|
return windowForWorkspace(true);
|
||||||
|
|
||||||
|
if (PMONITOR->specialWorkspaceID) {
|
||||||
|
const auto PWINDOW = windowForWorkspace(true);
|
||||||
|
|
||||||
|
if (PWINDOW)
|
||||||
|
return PWINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
return windowForWorkspace(false);
|
return windowForWorkspace(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,13 +940,19 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||||
|
|
||||||
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||||
|
|
||||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||||
|
static auto* const PSPECIALFALLTHROUGH = &g_pConfigManager->getConfigValuePtr("input:special_fallthrough")->intValue;
|
||||||
|
|
||||||
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
||||||
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_pInputManager->m_dExclusiveLSes.empty()) {
|
||||||
|
Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
||||||
|
|
||||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||||
|
@ -943,7 +1013,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||||
const auto PLASTWINDOW = m_pLastWindow;
|
const auto PLASTWINDOW = m_pLastWindow;
|
||||||
m_pLastWindow = pWindow;
|
m_pLastWindow = pWindow;
|
||||||
|
|
||||||
if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID)
|
/* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which
|
||||||
|
window focuses are "via keybinds" and which ones aren't. */
|
||||||
|
if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH)
|
||||||
PMONITOR->setSpecialWorkspace(nullptr);
|
PMONITOR->setSpecialWorkspace(nullptr);
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -1091,14 +1163,6 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<
|
||||||
|
|
||||||
auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
||||||
|
|
||||||
if (ls->layerSurface->current.keyboard_interactive && ls->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
|
|
||||||
if (!SURFACEAT)
|
|
||||||
SURFACEAT = ls->layerSurface->surface;
|
|
||||||
|
|
||||||
*ppLayerSurfaceFound = ls.get();
|
|
||||||
return SURFACEAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SURFACEAT) {
|
if (SURFACEAT) {
|
||||||
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1881,15 +1945,13 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||||
if (pWindow == m_pLastWindow) {
|
if (pWindow == m_pLastWindow) {
|
||||||
const auto* const ACTIVECOLOR =
|
const auto* const ACTIVECOLOR =
|
||||||
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||||
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ?
|
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying().m_vColors.empty() ? *ACTIVECOLOR :
|
||||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) :
|
pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying());
|
||||||
*ACTIVECOLOR);
|
|
||||||
} else {
|
} else {
|
||||||
const auto* const INACTIVECOLOR =
|
const auto* const INACTIVECOLOR =
|
||||||
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||||
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ?
|
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying().m_vColors.empty() ? *INACTIVECOLOR :
|
||||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) :
|
pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying());
|
||||||
*INACTIVECOLOR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2113,7 +2175,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) {
|
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor, bool noWarpCursor) {
|
||||||
|
|
||||||
// We trust the workspace and monitor to be correct.
|
// We trust the workspace and monitor to be correct.
|
||||||
|
|
||||||
|
@ -2199,7 +2261,8 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||||
|
|
||||||
pWorkspace->startAnim(true, true, true);
|
pWorkspace->startAnim(true, true, true);
|
||||||
|
|
||||||
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
if (!noWarpCursor)
|
||||||
|
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||||
|
|
||||||
g_pInputManager->sendMotionEventsToFocused();
|
g_pInputManager->sendMotionEventsToFocused();
|
||||||
}
|
}
|
||||||
|
@ -2607,11 +2670,7 @@ int CCompositor::getNewSpecialID() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::performUserChecks() {
|
void CCompositor::performUserChecks() {
|
||||||
if (g_pConfigManager->getInt("general:allow_tearing") == 1 && !envEnabled("WLR_DRM_NO_ATOMIC")) {
|
; // intentional
|
||||||
g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding "
|
|
||||||
"env = WLR_DRM_NO_ATOMIC,1 to your config.",
|
|
||||||
CColor(0), 15000, ICON_WARNING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) {
|
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) {
|
||||||
|
@ -2786,10 +2845,27 @@ void CCompositor::leaveUnsafeState() {
|
||||||
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
||||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
||||||
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
||||||
|
|
||||||
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||||
|
if (!PSURFACE) {
|
||||||
|
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSURFACE->m_fLastScale = scale;
|
||||||
|
PSURFACE->m_iLastScale = static_cast<int32_t>(std::ceil(scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||||
|
|
||||||
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||||
|
if (!PSURFACE) {
|
||||||
|
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSURFACE->m_eLastTransform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::updateSuspendedStates() {
|
void CCompositor::updateSuspendedStates() {
|
||||||
|
|
|
@ -176,7 +176,7 @@ class CCompositor {
|
||||||
void updateWorkspaceWindows(const int64_t& id);
|
void updateWorkspaceWindows(const int64_t& id);
|
||||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||||
int getNextAvailableMonitorID(std::string const& name);
|
int getNextAvailableMonitorID(std::string const& name);
|
||||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false);
|
||||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||||
CMonitor* getMonitorFromString(const std::string&);
|
CMonitor* getMonitorFromString(const std::string&);
|
||||||
bool workspaceIDOutOfBounds(const int64_t&);
|
bool workspaceIDOutOfBounds(const int64_t&);
|
||||||
|
@ -214,6 +214,7 @@ class CCompositor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
|
void removeAllSignals();
|
||||||
void setRandomSplash();
|
void setRandomSplash();
|
||||||
void initManagers(eManagersInitStage stage);
|
void initManagers(eManagersInitStage stage);
|
||||||
void prepareFallbackOutput();
|
void prepareFallbackOutput();
|
||||||
|
|
|
@ -318,7 +318,7 @@ void CWindow::destroyToplevelHandle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateToplevel() {
|
void CWindow::updateToplevel() {
|
||||||
updateSurfaceOutputs();
|
updateSurfaceScaleTransformDetails();
|
||||||
|
|
||||||
if (!m_phForeignToplevel)
|
if (!m_phForeignToplevel)
|
||||||
return;
|
return;
|
||||||
|
@ -345,8 +345,8 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||||
wlr_surface_send_leave(pSurface, OUTPUT);
|
wlr_surface_send_leave(pSurface, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateSurfaceOutputs() {
|
void CWindow::updateSurfaceScaleTransformDetails() {
|
||||||
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden)
|
if (!m_bIsMapped || m_bHidden)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||||
|
@ -355,16 +355,23 @@ void CWindow::updateSurfaceOutputs() {
|
||||||
|
|
||||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
if (PNEWMONITOR != PLASTMONITOR) {
|
||||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||||
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||||
|
|
||||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||||
|
}
|
||||||
|
|
||||||
wlr_surface_for_each_surface(
|
wlr_surface_for_each_surface(
|
||||||
m_pWLSurface.wlr(),
|
m_pWLSurface.wlr(),
|
||||||
[](wlr_surface* surf, int x, int y, void* data) {
|
[](wlr_surface* surf, int x, int y, void* data) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
|
||||||
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(surf);
|
||||||
|
if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale);
|
||||||
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
||||||
},
|
},
|
||||||
this);
|
this);
|
||||||
|
@ -511,6 +518,14 @@ void CWindow::onMap() {
|
||||||
"CWindow");
|
"CWindow");
|
||||||
|
|
||||||
m_vReportedSize = m_vPendingReportedSize;
|
m_vReportedSize = m_vPendingReportedSize;
|
||||||
|
|
||||||
|
for (const auto& ctrl : g_pHyprRenderer->m_vTearingControllers) {
|
||||||
|
if (ctrl->pWlrHint->surface != m_pWLSurface.wlr())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_bTearingHint = ctrl->pWlrHint->current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||||
|
@ -607,14 +622,42 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||||
m_sAdditionalConfigData.animationStyle = STYLE;
|
m_sAdditionalConfigData.animationStyle = STYLE;
|
||||||
} else if (r.szRule.starts_with("bordercolor")) {
|
} else if (r.szRule.starts_with("bordercolor")) {
|
||||||
try {
|
try {
|
||||||
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
// Each vector will only get used if it has at least one color
|
||||||
|
CGradientValueData activeBorderGradient = {};
|
||||||
|
CGradientValueData inactiveBorderGradient = {};
|
||||||
|
bool active = true;
|
||||||
|
CVarList colorsAndAngles = CVarList(removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
||||||
|
|
||||||
if (colorPart.contains(' ')) {
|
// Basic form has only two colors, everything else can be parsed as a gradient
|
||||||
// we have a space, 2 values
|
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
||||||
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
|
m_sSpecialRenderData.activeBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[0])));
|
||||||
m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1));
|
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[1])));
|
||||||
} else {
|
return;
|
||||||
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart);
|
}
|
||||||
|
|
||||||
|
for (auto& token : colorsAndAngles) {
|
||||||
|
// The first angle, or an explicit "0deg", splits the two gradients
|
||||||
|
if (active && token.contains("deg")) {
|
||||||
|
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
|
active = false;
|
||||||
|
} else if (token.contains("deg"))
|
||||||
|
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
|
else if (active)
|
||||||
|
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||||
|
else
|
||||||
|
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes sanity checks for the number of colors in each gradient
|
||||||
|
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10)
|
||||||
|
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
||||||
|
else if (activeBorderGradient.m_vColors.empty())
|
||||||
|
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
||||||
|
else if (inactiveBorderGradient.m_vColors.empty())
|
||||||
|
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||||
|
else {
|
||||||
|
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||||
|
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
||||||
}
|
}
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||||
} else if (r.szRule == "dimaround") {
|
} else if (r.szRule == "dimaround") {
|
||||||
|
@ -644,8 +687,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateDynamicRules() {
|
void CWindow::updateDynamicRules() {
|
||||||
m_sSpecialRenderData.activeBorderColor = -1;
|
m_sSpecialRenderData.activeBorderColor = CGradientValueData();
|
||||||
m_sSpecialRenderData.inactiveBorderColor = -1;
|
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData();
|
||||||
m_sSpecialRenderData.alpha = 1.f;
|
m_sSpecialRenderData.alpha = 1.f;
|
||||||
m_sSpecialRenderData.alphaInactive = -1.f;
|
m_sSpecialRenderData.alphaInactive = -1.f;
|
||||||
m_sAdditionalConfigData.forceNoBlur = false;
|
m_sAdditionalConfigData.forceNoBlur = false;
|
||||||
|
@ -1028,7 +1071,7 @@ int CWindow::getRealBorderSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::canBeTorn() {
|
bool CWindow::canBeTorn() {
|
||||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied;
|
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::shouldSendFullscreenState() {
|
bool CWindow::shouldSendFullscreenState() {
|
||||||
|
|
|
@ -104,13 +104,13 @@ class CWindowOverridableVar {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SWindowSpecialRenderData {
|
struct SWindowSpecialRenderData {
|
||||||
CWindowOverridableVar<bool> alphaOverride = false;
|
CWindowOverridableVar<bool> alphaOverride = false;
|
||||||
CWindowOverridableVar<float> alpha = 1.f;
|
CWindowOverridableVar<float> alpha = 1.f;
|
||||||
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
||||||
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
||||||
|
|
||||||
CWindowOverridableVar<int64_t> activeBorderColor = -1; // -1 means unset
|
CWindowOverridableVar<CGradientValueData> activeBorderColor = CGradientValueData(); // empty color vector means unset
|
||||||
CWindowOverridableVar<int64_t> inactiveBorderColor = -1; // -1 means unset
|
CWindowOverridableVar<CGradientValueData> inactiveBorderColor = CGradientValueData(); // empty color vector means unset
|
||||||
|
|
||||||
// set by the layout
|
// set by the layout
|
||||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset
|
CWindowOverridableVar<int> borderSize = -1; // -1 means unset
|
||||||
|
@ -354,7 +354,7 @@ class CWindow {
|
||||||
void createToplevelHandle();
|
void createToplevelHandle();
|
||||||
void destroyToplevelHandle();
|
void destroyToplevelHandle();
|
||||||
void updateToplevel();
|
void updateToplevel();
|
||||||
void updateSurfaceOutputs();
|
void updateSurfaceScaleTransformDetails();
|
||||||
void moveToWorkspace(int);
|
void moveToWorkspace(int);
|
||||||
CWindow* X11TransientFor();
|
CWindow* X11TransientFor();
|
||||||
void onUnmap();
|
void onUnmap();
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ICustomConfigValueData {
|
||||||
|
|
||||||
class CGradientValueData : public ICustomConfigValueData {
|
class CGradientValueData : public ICustomConfigValueData {
|
||||||
public:
|
public:
|
||||||
|
CGradientValueData(){};
|
||||||
CGradientValueData(CColor col) {
|
CGradientValueData(CColor col) {
|
||||||
m_vColors.push_back(col);
|
m_vColors.push_back(col);
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,7 +101,6 @@ void CConfigManager::setDefaultVars() {
|
||||||
|
|
||||||
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
||||||
configValues["misc:disable_splash_rendering"].intValue = 0;
|
configValues["misc:disable_splash_rendering"].intValue = 0;
|
||||||
configValues["misc:force_hypr_chan"].intValue = 0;
|
|
||||||
configValues["misc:force_default_wallpaper"].intValue = -1;
|
configValues["misc:force_default_wallpaper"].intValue = -1;
|
||||||
configValues["misc:vfr"].intValue = 1;
|
configValues["misc:vfr"].intValue = 1;
|
||||||
configValues["misc:vrr"].intValue = 0;
|
configValues["misc:vrr"].intValue = 0;
|
||||||
|
@ -140,6 +139,7 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["group:groupbar:font_family"].strValue = "Sans";
|
configValues["group:groupbar:font_family"].strValue = "Sans";
|
||||||
configValues["group:groupbar:font_size"].intValue = 8;
|
configValues["group:groupbar:font_size"].intValue = 8;
|
||||||
configValues["group:groupbar:gradients"].intValue = 1;
|
configValues["group:groupbar:gradients"].intValue = 1;
|
||||||
|
configValues["group:groupbar:height"].intValue = 14;
|
||||||
configValues["group:groupbar:priority"].intValue = 3;
|
configValues["group:groupbar:priority"].intValue = 3;
|
||||||
configValues["group:groupbar:render_titles"].intValue = 1;
|
configValues["group:groupbar:render_titles"].intValue = 1;
|
||||||
configValues["group:groupbar:scrolling"].intValue = 1;
|
configValues["group:groupbar:scrolling"].intValue = 1;
|
||||||
|
@ -225,6 +225,7 @@ void CConfigManager::setDefaultVars() {
|
||||||
|
|
||||||
configValues["input:follow_mouse"].intValue = 1;
|
configValues["input:follow_mouse"].intValue = 1;
|
||||||
configValues["input:mouse_refocus"].intValue = 1;
|
configValues["input:mouse_refocus"].intValue = 1;
|
||||||
|
configValues["input:special_fallthrough"].intValue = 0;
|
||||||
configValues["input:sensitivity"].floatValue = 0.f;
|
configValues["input:sensitivity"].floatValue = 0.f;
|
||||||
configValues["input:accel_profile"].strValue = STRVAL_EMPTY;
|
configValues["input:accel_profile"].strValue = STRVAL_EMPTY;
|
||||||
configValues["input:kb_file"].strValue = STRVAL_EMPTY;
|
configValues["input:kb_file"].strValue = STRVAL_EMPTY;
|
||||||
|
@ -255,6 +256,7 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["input:touchpad:scroll_factor"].floatValue = 1.f;
|
configValues["input:touchpad:scroll_factor"].floatValue = 1.f;
|
||||||
configValues["input:touchdevice:transform"].intValue = 0;
|
configValues["input:touchdevice:transform"].intValue = 0;
|
||||||
configValues["input:touchdevice:output"].strValue = STRVAL_EMPTY;
|
configValues["input:touchdevice:output"].strValue = STRVAL_EMPTY;
|
||||||
|
configValues["input:touchdevice:enabled"].intValue = 1;
|
||||||
configValues["input:tablet:transform"].intValue = 0;
|
configValues["input:tablet:transform"].intValue = 0;
|
||||||
configValues["input:tablet:output"].strValue = STRVAL_EMPTY;
|
configValues["input:tablet:output"].strValue = STRVAL_EMPTY;
|
||||||
configValues["input:tablet:region_position"].vecValue = Vector2D();
|
configValues["input:tablet:region_position"].vecValue = Vector2D();
|
||||||
|
@ -320,7 +322,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
|
||||||
cfgValues["scroll_points"].strValue = STRVAL_EMPTY;
|
cfgValues["scroll_points"].strValue = STRVAL_EMPTY;
|
||||||
cfgValues["transform"].intValue = 0;
|
cfgValues["transform"].intValue = 0;
|
||||||
cfgValues["output"].strValue = STRVAL_EMPTY;
|
cfgValues["output"].strValue = STRVAL_EMPTY;
|
||||||
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
|
cfgValues["enabled"].intValue = 1; // only for mice, touchpads, and touchdevices
|
||||||
cfgValues["region_position"].vecValue = Vector2D(); // only for tablets
|
cfgValues["region_position"].vecValue = Vector2D(); // only for tablets
|
||||||
cfgValues["region_size"].vecValue = Vector2D(); // only for tablets
|
cfgValues["region_size"].vecValue = Vector2D(); // only for tablets
|
||||||
cfgValues["relative_input"].intValue = 0; // only for tablets
|
cfgValues["relative_input"].intValue = 0; // only for tablets
|
||||||
|
@ -563,7 +565,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (COMMAND == "decoration:screen_shader") {
|
if (COMMAND == "decoration:screen_shader" && VALUE != STRVAL_EMPTY) {
|
||||||
const auto PATH = absolutePath(VALUE, configCurrentPath);
|
const auto PATH = absolutePath(VALUE, configCurrentPath);
|
||||||
|
|
||||||
configPaths.push_back(PATH);
|
configPaths.push_back(PATH);
|
||||||
|
@ -2321,30 +2323,30 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
||||||
static auto* const PVRR = &getConfigValuePtr("misc:vrr")->intValue;
|
static auto* const PVRR = &getConfigValuePtr("misc:vrr")->intValue;
|
||||||
|
|
||||||
static auto ensureVRRForDisplay = [&](CMonitor* m) -> void {
|
static auto ensureVRRForDisplay = [&](CMonitor* m) -> void {
|
||||||
if (!m->output)
|
if (!m->output || m->createdByUser)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto USEVRR = m->activeMonitorRule.vrr.has_value() ? m->activeMonitorRule.vrr.value() : *PVRR;
|
const auto USEVRR = m->activeMonitorRule.vrr.has_value() ? m->activeMonitorRule.vrr.value() : *PVRR;
|
||||||
|
|
||||||
if (USEVRR == 0) {
|
if (USEVRR == 0) {
|
||||||
if (m->vrrActive) {
|
if (m->vrrActive) {
|
||||||
wlr_output_enable_adaptive_sync(m->output, 0);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
||||||
|
|
||||||
if (!wlr_output_commit(m->output))
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
||||||
}
|
}
|
||||||
m->vrrActive = false;
|
m->vrrActive = false;
|
||||||
return;
|
return;
|
||||||
} else if (USEVRR == 1) {
|
} else if (USEVRR == 1) {
|
||||||
if (!m->vrrActive) {
|
if (!m->vrrActive) {
|
||||||
wlr_output_enable_adaptive_sync(m->output, 1);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1);
|
||||||
|
|
||||||
if (!wlr_output_test(m->output)) {
|
if (!m->state.test()) {
|
||||||
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
||||||
wlr_output_enable_adaptive_sync(m->output, 0);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wlr_output_commit(m->output))
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
||||||
}
|
}
|
||||||
m->vrrActive = true;
|
m->vrrActive = true;
|
||||||
|
@ -2361,20 +2363,20 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
||||||
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
|
|
||||||
if (WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED) {
|
if (WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED) {
|
||||||
wlr_output_enable_adaptive_sync(m->output, 1);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1);
|
||||||
|
|
||||||
if (!wlr_output_test(m->output)) {
|
if (!m->state.test()) {
|
||||||
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
||||||
wlr_output_enable_adaptive_sync(m->output, 0);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wlr_output_commit(m->output))
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
||||||
|
|
||||||
} else if (!WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) {
|
} else if (!WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) {
|
||||||
wlr_output_enable_adaptive_sync(m->output, 0);
|
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
||||||
|
|
||||||
if (!wlr_output_commit(m->output))
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ gestures {
|
||||||
|
|
||||||
misc {
|
misc {
|
||||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||||
}
|
}
|
||||||
|
|
||||||
# Example per-device config
|
# Example per-device config
|
||||||
|
|
|
@ -119,7 +119,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||||
|
|
||||||
finalCrashReport += "\n\nLog tail:\n";
|
finalCrashReport += "\n\nLog tail:\n";
|
||||||
|
|
||||||
finalCrashReport += Debug::rollingLog;
|
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
|
||||||
|
|
||||||
const auto HOME = getenv("HOME");
|
const auto HOME = getenv("HOME");
|
||||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||||
|
|
|
@ -1138,9 +1138,9 @@ std::string dispatchSetProp(std::string request) {
|
||||||
} else if (PROP == "alphainactive") {
|
} else if (PROP == "alphainactive") {
|
||||||
PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock);
|
PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock);
|
||||||
} else if (PROP == "activebordercolor") {
|
} else if (PROP == "activebordercolor") {
|
||||||
PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock);
|
||||||
} else if (PROP == "inactivebordercolor") {
|
} else if (PROP == "inactivebordercolor") {
|
||||||
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock);
|
||||||
} else if (PROP == "forcergbx") {
|
} else if (PROP == "forcergbx") {
|
||||||
PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||||
} else if (PROP == "bordersize") {
|
} else if (PROP == "bordersize") {
|
||||||
|
@ -1402,13 +1402,20 @@ std::string getReply(std::string request) {
|
||||||
auto format = HyprCtl::FORMAT_NORMAL;
|
auto format = HyprCtl::FORMAT_NORMAL;
|
||||||
|
|
||||||
// process flags for non-batch requests
|
// process flags for non-batch requests
|
||||||
if (!request.contains("[[BATCH]]") && request.contains("/")) {
|
if (!request.starts_with("[[BATCH]]") && request.contains("/")) {
|
||||||
long unsigned int sepIndex = 0;
|
long unsigned int sepIndex = 0;
|
||||||
for (const auto& c : request) {
|
for (const auto& c : request) {
|
||||||
if (c == '/') { // stop at separator
|
if (c == '/') { // stop at separator
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// after whitespace assume the first word as a keyword,
|
||||||
|
// so its value can have slashes (e.g., a path)
|
||||||
|
if (c == ' ') {
|
||||||
|
sepIndex = request.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
sepIndex++;
|
sepIndex++;
|
||||||
|
|
||||||
if (c == 'j')
|
if (c == 'j')
|
||||||
|
|
|
@ -142,6 +142,9 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||||
|
|
||||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||||
|
|
||||||
|
if (layersurface->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||||
|
g_pInputManager->m_dExclusiveLSes.push_back(layersurface);
|
||||||
|
|
||||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||||
// don't focus if constrained
|
// don't focus if constrained
|
||||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||||
|
@ -183,6 +186,11 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||||
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
||||||
|
|
||||||
|
std::erase(g_pInputManager->m_dExclusiveLSes, layersurface);
|
||||||
|
|
||||||
|
if (!g_pInputManager->m_dExclusiveLSes.empty())
|
||||||
|
g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->layerSurface->surface);
|
||||||
|
|
||||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||||
|
|
||||||
|
|
|
@ -175,11 +175,17 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) {
|
||||||
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||||
Debug::log(LOG, "PowerMgr set mode!");
|
Debug::log(LOG, "PowerMgr set mode!");
|
||||||
|
|
||||||
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(EVENT->output);
|
||||||
|
|
||||||
wlr_output_enable(EVENT->output, EVENT->mode == 1);
|
if (!PMONITOR) {
|
||||||
|
Debug::log(ERR, "Invalid powerMgrSetMode output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wlr_output_commit(EVENT->output))
|
wlr_output_state_set_enabled(PMONITOR->state.wlr(), EVENT->mode == 1);
|
||||||
|
|
||||||
|
if (!PMONITOR->state.commit())
|
||||||
Debug::log(ERR, "Couldn't set power mode");
|
Debug::log(ERR, "Couldn't set power mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,14 +233,7 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
|
||||||
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
const auto TCTL = (wlr_tearing_control_v1*)data;
|
const auto TCTL = (wlr_tearing_control_v1*)data;
|
||||||
|
|
||||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TCTL->surface);
|
Debug::log(LOG, "New tearing hint at {:x}", (uintptr_t)data);
|
||||||
|
|
||||||
if (!PWINDOW) {
|
|
||||||
Debug::log(ERR, "Tearing hint {} was attached to an unknown surface", (uintptr_t)data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "New tearing hint for window {} at {}", PWINDOW, (uintptr_t)data);
|
|
||||||
|
|
||||||
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
||||||
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
||||||
|
@ -242,7 +241,7 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
NEWCTRL->hyprListener_destroy.initCallback(
|
NEWCTRL->hyprListener_destroy.initCallback(
|
||||||
&NEWCTRL->pWlrHint->events.destroy,
|
&NEWCTRL->pWlrHint->events.destroy,
|
||||||
[&](void* owner, void* data) {
|
[&](void* owner, void* data) {
|
||||||
Debug::log(LOG, "Destroyed {} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
Debug::log(LOG, "Destroyed {:x} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
||||||
|
|
||||||
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
||||||
},
|
},
|
||||||
|
@ -258,7 +257,7 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||||
if (PWINDOW) {
|
if (PWINDOW) {
|
||||||
PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current;
|
PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current;
|
||||||
|
|
||||||
Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current);
|
Debug::log(LOG, "Hint {:x} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NEWCTRL, "TearingController");
|
NEWCTRL, "TearingController");
|
||||||
|
|
|
@ -109,7 +109,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||||
w->m_iLastSurfaceMonitorID = -1;
|
w->m_iLastSurfaceMonitorID = -1;
|
||||||
w->updateSurfaceOutputs();
|
w->updateSurfaceScaleTransformDetails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,10 +209,10 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorStateRequest(void* owner, void* data) {
|
void Events::listener_monitorStateRequest(void* owner, void* data) {
|
||||||
const auto PMONITOR = (CMonitor*)owner;
|
//const auto PMONITOR = (CMonitor*)owner;
|
||||||
const auto E = (wlr_output_event_request_state*)data;
|
//const auto E = (wlr_output_event_request_state*)data;
|
||||||
|
|
||||||
wlr_output_commit_state(PMONITOR->output, E->state);
|
// TODO: maybe don't ignore?
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDamage(void* owner, void* data) {
|
void Events::listener_monitorDamage(void* owner, void* data) {
|
||||||
|
|
|
@ -639,7 +639,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||||
|
|
||||||
g_pInputManager->sendMotionEventsToFocused();
|
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive)
|
||||||
|
g_pInputManager->sendMotionEventsToFocused();
|
||||||
|
|
||||||
// fix some xwayland apps that don't behave nicely
|
// fix some xwayland apps that don't behave nicely
|
||||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||||
|
@ -803,8 +804,6 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_pPendingSizeAck.reset();
|
PWINDOW->m_pPendingSizeAck.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->updateSurfaceOutputs();
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||||
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
||||||
|
|
||||||
|
@ -1054,11 +1053,8 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||||
|
|
||||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||||
if (*PXWLFORCESCALEZERO) {
|
if (*PXWLFORCESCALEZERO) {
|
||||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
|
||||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||||
|
@ -1139,8 +1135,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv();
|
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv();
|
||||||
PWINDOW->m_vReportedSize = PWINDOW->m_vRealSize.goalv();
|
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goalv();
|
||||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vReportedSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,13 @@ CBox& CBox::expand(const double& value) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBox& CBox::noNegativeSize() {
|
||||||
|
std::clamp(w, 0.0, std::numeric_limits<double>::infinity());
|
||||||
|
std::clamp(h, 0.0, std::numeric_limits<double>::infinity());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
CBox CBox::roundInternal() {
|
CBox CBox::roundInternal() {
|
||||||
float newW = x + w - std::floor(x);
|
float newW = x + w - std::floor(x);
|
||||||
float newH = y + h - std::floor(y);
|
float newH = y + h - std::floor(y);
|
||||||
|
|
|
@ -51,6 +51,7 @@ class CBox {
|
||||||
CBox& transform(const wl_output_transform t, double w, double h);
|
CBox& transform(const wl_output_transform t, double w, double h);
|
||||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||||
CBox& expand(const double& value);
|
CBox& expand(const double& value);
|
||||||
|
CBox& noNegativeSize();
|
||||||
|
|
||||||
CBox copy() const;
|
CBox copy() const;
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,13 @@ void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const
|
||||||
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
|
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeWLSignal(wl_listener* pListener) {
|
||||||
|
wl_list_remove(&pListener->link);
|
||||||
|
wl_list_init(&pListener->link);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed listener {:x}", (uintptr_t)pListener);
|
||||||
|
}
|
||||||
|
|
||||||
void handleNoop(struct wl_listener* listener, void* data) {
|
void handleNoop(struct wl_listener* listener, void* data) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct SCallstackFrameInfo {
|
||||||
|
|
||||||
std::string absolutePath(const std::string&, const std::string&);
|
std::string absolutePath(const std::string&, const std::string&);
|
||||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||||
|
void removeWLSignal(wl_listener*);
|
||||||
std::string escapeJSONStrings(const std::string& str);
|
std::string escapeJSONStrings(const std::string& str);
|
||||||
std::string removeBeginEndSpacesTabs(std::string);
|
std::string removeBeginEndSpacesTabs(std::string);
|
||||||
bool isNumber(const std::string&, bool allowfloat = false);
|
bool isNumber(const std::string&, bool allowfloat = false);
|
||||||
|
|
|
@ -8,7 +8,7 @@ int ratHandler(void* data) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitor::CMonitor() {
|
CMonitor::CMonitor() : state(this) {
|
||||||
wlr_damage_ring_init(&damage);
|
wlr_damage_ring_init(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
||||||
|
|
||||||
if (m_bEnabled) {
|
if (m_bEnabled) {
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_state_set_enabled(state.wlr(), true);
|
||||||
wlr_output_commit(output);
|
state.commit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
// if it's disabled, disable and ignore
|
// if it's disabled, disable and ignore
|
||||||
if (monitorRule.disabled) {
|
if (monitorRule.disabled) {
|
||||||
|
|
||||||
wlr_output_set_scale(output, 1);
|
wlr_output_state_set_scale(state.wlr(), 1);
|
||||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
|
||||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
auto PREFSTATE = wlr_output_preferred_mode(output);
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
wlr_output_mode* mode;
|
wlr_output_mode* mode;
|
||||||
|
|
||||||
wl_list_for_each(mode, &output->modes, link) {
|
wl_list_for_each(mode, &output->modes, link) {
|
||||||
wlr_output_set_mode(output, PREFSTATE);
|
wlr_output_state_set_mode(state.wlr(), mode);
|
||||||
|
|
||||||
if (!wlr_output_test(output))
|
if (!wlr_output_test_state(output, state.wlr()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PREFSTATE = mode;
|
PREFSTATE = mode;
|
||||||
|
@ -83,13 +83,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PREFSTATE)
|
if (PREFSTATE)
|
||||||
wlr_output_set_mode(output, PREFSTATE);
|
wlr_output_state_set_mode(state.wlr(), PREFSTATE);
|
||||||
else
|
else
|
||||||
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
||||||
|
|
||||||
wlr_output_enable(output, 0);
|
wlr_output_state_set_enabled(state.wlr(), 0);
|
||||||
|
|
||||||
if (!wlr_output_commit(output))
|
if (!state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
||||||
|
|
||||||
m_bEnabled = false;
|
m_bEnabled = false;
|
||||||
|
@ -130,13 +130,14 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
m_bEnabled = true;
|
m_bEnabled = true;
|
||||||
|
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_state_set_enabled(state.wlr(), 1);
|
||||||
|
|
||||||
// set mode, also applies
|
// set mode, also applies
|
||||||
if (!noRule)
|
if (!noRule)
|
||||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||||
|
|
||||||
wlr_output_commit(output);
|
if (!state.commit())
|
||||||
|
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit");
|
||||||
|
|
||||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||||
|
|
||||||
|
@ -283,9 +284,10 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
if (!destroy)
|
if (!destroy)
|
||||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||||
|
|
||||||
wlr_output_enable(output, false);
|
wlr_output_state_set_enabled(state.wlr(), false);
|
||||||
|
|
||||||
wlr_output_commit(output);
|
if (!state.commit())
|
||||||
|
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect");
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor == this)
|
if (g_pCompositor->m_pLastMonitor == this)
|
||||||
g_pCompositor->setActiveMonitor(BACKUPMON);
|
g_pCompositor->setActiveMonitor(BACKUPMON);
|
||||||
|
@ -502,7 +504,7 @@ float CMonitor::getDefaultScale() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove) {
|
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove, bool noFocus) {
|
||||||
if (!pWorkspace)
|
if (!pWorkspace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -533,7 +535,7 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||||
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
||||||
|
|
||||||
|
@ -621,7 +623,7 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||||
w->m_iMonitorID = ID;
|
w->m_iMonitorID = ID;
|
||||||
w->updateSurfaceOutputs();
|
w->updateSurfaceScaleTransformDetails();
|
||||||
|
|
||||||
const auto MIDDLE = w->middle();
|
const auto MIDDLE = w->middle();
|
||||||
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
||||||
|
@ -678,3 +680,32 @@ void CMonitor::updateMatrix() {
|
||||||
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||||
|
m_pOwner = owner;
|
||||||
|
wlr_output_state_init(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMonitorState::~CMonitorState() {
|
||||||
|
wlr_output_state_finish(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_state* CMonitorState::wlr() {
|
||||||
|
return &m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitorState::clear() {
|
||||||
|
wlr_output_state_finish(&m_state);
|
||||||
|
m_state = {0};
|
||||||
|
wlr_output_state_init(&m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMonitorState::commit() {
|
||||||
|
bool ret = wlr_output_commit_state(m_pOwner->output, &m_state);
|
||||||
|
clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMonitorState::test() {
|
||||||
|
return wlr_output_test_state(m_pOwner->output, &m_state);
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,25 @@ struct SMonitorRule {
|
||||||
std::optional<int> vrr;
|
std::optional<int> vrr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CMonitor;
|
||||||
|
|
||||||
|
// Class for wrapping the wlr state
|
||||||
|
class CMonitorState {
|
||||||
|
public:
|
||||||
|
CMonitorState(CMonitor* owner);
|
||||||
|
~CMonitorState();
|
||||||
|
|
||||||
|
wlr_output_state* wlr();
|
||||||
|
void clear();
|
||||||
|
// commit() will also clear()
|
||||||
|
bool commit();
|
||||||
|
bool test();
|
||||||
|
|
||||||
|
private:
|
||||||
|
wlr_output_state m_state = {0};
|
||||||
|
CMonitor* m_pOwner;
|
||||||
|
};
|
||||||
|
|
||||||
class CMonitor {
|
class CMonitor {
|
||||||
public:
|
public:
|
||||||
CMonitor();
|
CMonitor();
|
||||||
|
@ -51,6 +70,8 @@ class CMonitor {
|
||||||
|
|
||||||
drmModeModeInfo customDrmMode = {};
|
drmModeModeInfo customDrmMode = {};
|
||||||
|
|
||||||
|
CMonitorState state;
|
||||||
|
|
||||||
// WLR stuff
|
// WLR stuff
|
||||||
wlr_damage_ring damage;
|
wlr_damage_ring damage;
|
||||||
wlr_output* output = nullptr;
|
wlr_output* output = nullptr;
|
||||||
|
@ -120,7 +141,7 @@ class CMonitor {
|
||||||
void setMirror(const std::string&);
|
void setMirror(const std::string&);
|
||||||
bool isMirror();
|
bool isMirror();
|
||||||
float getDefaultScale();
|
float getDefaultScale();
|
||||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||||
void changeWorkspace(const int& id, bool internal = false);
|
void changeWorkspace(const int& id, bool internal = false);
|
||||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||||
void setSpecialWorkspace(const int& id);
|
void setSpecialWorkspace(const int& id);
|
||||||
|
|
|
@ -19,6 +19,21 @@ inline const std::vector<std::string> SPLASHES = {
|
||||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||||
"To rice, or not to rice, that is the question.",
|
"To rice, or not to rice, that is the question.",
|
||||||
"Now available on Fedora!",
|
"Now available on Fedora!",
|
||||||
|
"\"Hyprland is so good it starts with a capital letter\" - Hazel",
|
||||||
|
"\"please make this message a splash\" - eriedaberrie",
|
||||||
|
"\"the only wayland compositor powered by fried chicken\" - raf",
|
||||||
|
"\"This will never get into Hyprland\" - Flafy",
|
||||||
|
"\"Hyprland only gives you up on -git\" - fazzi",
|
||||||
|
"Segmentation fault (core dumped)",
|
||||||
|
"\"disabling hyprland logo is a war crime\" - vaxry",
|
||||||
|
"some basic startup code",
|
||||||
|
"\"I think I am addicted to hyprland\" - mathisbuilder",
|
||||||
|
"\"hyprland is the most important package in the arch repos\" - jacekpoz",
|
||||||
|
"Thanks Brodie!",
|
||||||
|
"Thanks fufexan!",
|
||||||
|
"Thanks raf!",
|
||||||
|
"You can't use --splash to change this message :)",
|
||||||
|
"Hyprland will overtake Gnome in popularity by [insert year]",
|
||||||
// music reference / quote section
|
// music reference / quote section
|
||||||
"J'remue le ciel, le jour, la nuit.",
|
"J'remue le ciel, le jour, la nuit.",
|
||||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||||
|
|
|
@ -178,6 +178,9 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
||||||
Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface);
|
Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface);
|
||||||
|
|
||||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||||
|
|
||||||
|
if (subsurface->pWindowOwner)
|
||||||
|
subsurface->pWindowOwner->updateSurfaceScaleTransformDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||||
|
@ -259,13 +262,11 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||||
|
|
||||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
||||||
if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
if (PMONITOR && PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||||
pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
||||||
CRegion damageBox;
|
CRegion damageBox{&pNode->pSurface->wlr()->buffer_damage};
|
||||||
wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman());
|
|
||||||
|
|
||||||
if (!damageBox.empty()) {
|
if (!damageBox.empty()) {
|
||||||
|
|
||||||
if (PMONITOR->tearingState.busy) {
|
if (PMONITOR->tearingState.busy) {
|
||||||
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,14 +42,6 @@ double Vector2D::distance(const Vector2D& other) const {
|
||||||
return std::sqrt(dx * dx + dy * dy);
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const {
|
|
||||||
const auto a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
|
||||||
const auto b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
|
||||||
const auto c = 1 - a - b;
|
|
||||||
|
|
||||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vector2D::size() const {
|
double Vector2D::size() const {
|
||||||
return std::sqrt(x * x + y * y);
|
return std::sqrt(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,8 +92,6 @@ class Vector2D {
|
||||||
|
|
||||||
Vector2D floor() const;
|
Vector2D floor() const;
|
||||||
Vector2D round() const;
|
Vector2D round() const;
|
||||||
|
|
||||||
bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
void handleWrapped(wl_listener* listener, void* data) {
|
void handleWrapped(wl_listener* listener, void* data) {
|
||||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||||
|
|
||||||
g_pWatchdog->startWatching();
|
if (g_pWatchdog)
|
||||||
|
g_pWatchdog->startWatching();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pWrap->m_pSelf->emit(data);
|
pWrap->m_pSelf->emit(data);
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||||
|
|
||||||
g_pWatchdog->endWatching();
|
if (g_pWatchdog)
|
||||||
|
g_pWatchdog->endWatching();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||||
|
|
|
@ -28,8 +28,14 @@ class CWLSurface {
|
||||||
bool m_bFillIgnoreSmall = false;
|
bool m_bFillIgnoreSmall = false;
|
||||||
|
|
||||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||||
CWindow* m_pOwner = nullptr;
|
CWindow* m_pOwner = nullptr;
|
||||||
|
|
||||||
|
// track surface data and avoid dupes
|
||||||
|
float m_fLastScale = 0;
|
||||||
|
int m_iLastScale = 0;
|
||||||
|
wl_output_transform m_eLastTransform = (wl_output_transform)-1;
|
||||||
|
|
||||||
|
//
|
||||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||||
destroy();
|
destroy();
|
||||||
m_pWLRSurface = pSurface;
|
m_pWLRSurface = pSurface;
|
||||||
|
|
|
@ -22,13 +22,13 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||||
if (SPLITSIDE) {
|
if (SPLITSIDE) {
|
||||||
// split left/right
|
// split left/right
|
||||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h}.noNegativeSize();
|
||||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h};
|
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h}.noNegativeSize();
|
||||||
} else {
|
} else {
|
||||||
// split top/bottom
|
// split top/bottom
|
||||||
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE}.noNegativeSize();
|
||||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE};
|
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}.noNegativeSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
children[0]->recalcSizePosRecursive(force);
|
children[0]->recalcSizePosRecursive(force);
|
||||||
|
@ -64,6 +64,21 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) {
|
||||||
|
SDwindleNodeData* res = nullptr;
|
||||||
|
double distClosest = -1;
|
||||||
|
for (auto& n : m_lDwindleNodesData) {
|
||||||
|
if (n.workspaceID == id && n.pWindow && g_pCompositor->windowValidMapped(n.pWindow)) {
|
||||||
|
auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size());
|
||||||
|
if (!res || distAnother < distClosest) {
|
||||||
|
res = &n;
|
||||||
|
distClosest = distAnother;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
|
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
|
||||||
for (auto& n : m_lDwindleNodesData) {
|
for (auto& n : m_lDwindleNodesData) {
|
||||||
if (n.pWindow == pWindow && !n.isNode)
|
if (n.pWindow == pWindow && !n.isNode)
|
||||||
|
@ -254,26 +269,25 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
|
|
||||||
const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
|
const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
|
||||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
|
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
|
||||||
const auto TARGETCOORDS = PMONITOR->ID == MONFROMCURSOR->ID && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR) ? pWindow->middle() : MOUSECOORDS;
|
|
||||||
|
|
||||||
if (PMONITOR->ID == MONFROMCURSOR->ID &&
|
if (PMONITOR->ID == MONFROMCURSOR->ID &&
|
||||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
|
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS));
|
||||||
|
|
||||||
// happens on reserved area
|
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
|
||||||
|
|
||||||
} else if (*PUSEACTIVE) {
|
} else if (*PUSEACTIVE) {
|
||||||
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
|
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
|
||||||
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
||||||
} else {
|
} else {
|
||||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||||
|
|
||||||
|
@ -386,34 +400,41 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||||
overrideDirection = DIRECTION_DEFAULT;
|
overrideDirection = DIRECTION_DEFAULT;
|
||||||
} else if (*PSMARTSPLIT == 1) {
|
} else if (*PSMARTSPLIT == 1) {
|
||||||
const auto tl = NEWPARENT->box.pos();
|
const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w;
|
||||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
const auto DELTA = MOUSECOORDS - PARENT_CENTER;
|
||||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
const auto DELTA_SLOPE = DELTA.y / DELTA.x;
|
||||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
|
||||||
|
|
||||||
if (TARGETCOORDS.inTriangle(tl, tr, cc)) {
|
if (abs(DELTA_SLOPE) < PARENT_PROPORTIONS) {
|
||||||
NEWPARENT->splitTop = true;
|
if (DELTA.x > 0) {
|
||||||
NEWPARENT->children[0] = PNODE;
|
// right
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->splitTop = false;
|
||||||
} else if (TARGETCOORDS.inTriangle(tr, cc, br)) {
|
NEWPARENT->children[0] = OPENINGON;
|
||||||
NEWPARENT->splitTop = false;
|
NEWPARENT->children[1] = PNODE;
|
||||||
NEWPARENT->children[0] = OPENINGON;
|
} else {
|
||||||
NEWPARENT->children[1] = PNODE;
|
// left
|
||||||
} else if (TARGETCOORDS.inTriangle(br, bl, cc)) {
|
NEWPARENT->splitTop = false;
|
||||||
NEWPARENT->splitTop = true;
|
NEWPARENT->children[0] = PNODE;
|
||||||
NEWPARENT->children[0] = OPENINGON;
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
NEWPARENT->children[1] = PNODE;
|
}
|
||||||
} else {
|
} else {
|
||||||
NEWPARENT->splitTop = false;
|
if (DELTA.y > 0) {
|
||||||
NEWPARENT->children[0] = PNODE;
|
// bottom
|
||||||
NEWPARENT->children[1] = OPENINGON;
|
NEWPARENT->splitTop = true;
|
||||||
|
NEWPARENT->children[0] = OPENINGON;
|
||||||
|
NEWPARENT->children[1] = PNODE;
|
||||||
|
} else {
|
||||||
|
// top
|
||||||
|
NEWPARENT->splitTop = true;
|
||||||
|
NEWPARENT->children[0] = PNODE;
|
||||||
|
NEWPARENT->children[1] = OPENINGON;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||||
if ((SIDEBYSIDE &&
|
if ((SIDEBYSIDE &&
|
||||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||||
(!SIDEBYSIDE &&
|
(!SIDEBYSIDE &&
|
||||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 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;
|
||||||
|
@ -776,6 +797,14 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save position and size if floating
|
||||||
|
if (pWindow->m_bIsFloating && on) {
|
||||||
|
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||||
|
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||||
|
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||||
|
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise, accept it.
|
// otherwise, accept it.
|
||||||
pWindow->m_bIsFullscreen = on;
|
pWindow->m_bIsFullscreen = on;
|
||||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||||
|
@ -803,14 +832,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||||
|
|
||||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||||
|
|
||||||
// save position and size if floating
|
|
||||||
if (pWindow->m_bIsFloating) {
|
|
||||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
|
||||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply new pos and size being monitors' box
|
// apply new pos and size being monitors' box
|
||||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||||
|
|
|
@ -79,6 +79,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||||
|
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&);
|
||||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||||
|
|
||||||
void toggleSplit(CWindow*);
|
void toggleSplit(CWindow*);
|
||||||
|
|
|
@ -314,8 +314,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
|
|
||||||
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
||||||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
||||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
|
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
|
||||||
(*PANIMATEMOUSE || *PANIMATE)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TIMER = std::chrono::high_resolution_clock::now();
|
TIMER = std::chrono::high_resolution_clock::now();
|
||||||
|
@ -469,16 +468,18 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||||
|
|
||||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||||
|
|
||||||
|
CBox wb = {pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
|
||||||
|
wb.round();
|
||||||
|
|
||||||
if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) {
|
if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) {
|
||||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10};
|
wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}};
|
||||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f;
|
pWindow->m_vRealPosition = wb.pos();
|
||||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
|
pWindow->m_vRealSize = wb.size();
|
||||||
|
|
||||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
pWindow->m_vSize = wb.pos();
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
pWindow->m_vPosition = wb.size();
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||||
|
|
||||||
|
|
|
@ -879,6 +879,14 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save position and size if floating
|
||||||
|
if (pWindow->m_bIsFloating && on) {
|
||||||
|
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||||
|
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||||
|
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||||
|
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise, accept it.
|
// otherwise, accept it.
|
||||||
pWindow->m_bIsFullscreen = on;
|
pWindow->m_bIsFullscreen = on;
|
||||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||||
|
@ -906,14 +914,6 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||||
|
|
||||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||||
|
|
||||||
// save position and size if floating
|
|
||||||
if (pWindow->m_bIsFloating) {
|
|
||||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
|
||||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
|
||||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply new pos and size being monitors' box
|
// apply new pos and size being monitors' box
|
||||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||||
|
|
|
@ -19,64 +19,65 @@
|
||||||
CKeybindManager::CKeybindManager() {
|
CKeybindManager::CKeybindManager() {
|
||||||
// initialize all dispatchers
|
// initialize all dispatchers
|
||||||
|
|
||||||
m_mDispatchers["exec"] = spawn;
|
m_mDispatchers["exec"] = spawn;
|
||||||
m_mDispatchers["execr"] = spawnRaw;
|
m_mDispatchers["execr"] = spawnRaw;
|
||||||
m_mDispatchers["killactive"] = killActive;
|
m_mDispatchers["killactive"] = killActive;
|
||||||
m_mDispatchers["closewindow"] = kill;
|
m_mDispatchers["closewindow"] = kill;
|
||||||
m_mDispatchers["togglefloating"] = toggleActiveFloating;
|
m_mDispatchers["togglefloating"] = toggleActiveFloating;
|
||||||
m_mDispatchers["workspace"] = changeworkspace;
|
m_mDispatchers["workspace"] = changeworkspace;
|
||||||
m_mDispatchers["renameworkspace"] = renameWorkspace;
|
m_mDispatchers["renameworkspace"] = renameWorkspace;
|
||||||
m_mDispatchers["fullscreen"] = fullscreenActive;
|
m_mDispatchers["fullscreen"] = fullscreenActive;
|
||||||
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
|
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
|
||||||
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
|
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
|
||||||
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
|
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
|
||||||
m_mDispatchers["pseudo"] = toggleActivePseudo;
|
m_mDispatchers["pseudo"] = toggleActivePseudo;
|
||||||
m_mDispatchers["movefocus"] = moveFocusTo;
|
m_mDispatchers["movefocus"] = moveFocusTo;
|
||||||
m_mDispatchers["movewindow"] = moveActiveTo;
|
m_mDispatchers["movewindow"] = moveActiveTo;
|
||||||
m_mDispatchers["swapwindow"] = swapActive;
|
m_mDispatchers["swapwindow"] = swapActive;
|
||||||
m_mDispatchers["centerwindow"] = centerWindow;
|
m_mDispatchers["centerwindow"] = centerWindow;
|
||||||
m_mDispatchers["togglegroup"] = toggleGroup;
|
m_mDispatchers["togglegroup"] = toggleGroup;
|
||||||
m_mDispatchers["changegroupactive"] = changeGroupActive;
|
m_mDispatchers["changegroupactive"] = changeGroupActive;
|
||||||
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
|
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
|
||||||
m_mDispatchers["togglesplit"] = toggleSplit;
|
m_mDispatchers["togglesplit"] = toggleSplit;
|
||||||
m_mDispatchers["splitratio"] = alterSplitRatio;
|
m_mDispatchers["splitratio"] = alterSplitRatio;
|
||||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||||
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
||||||
m_mDispatchers["movecursor"] = moveCursor;
|
m_mDispatchers["movecursor"] = moveCursor;
|
||||||
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
||||||
m_mDispatchers["exit"] = exitHyprland;
|
m_mDispatchers["exit"] = exitHyprland;
|
||||||
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
||||||
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
m_mDispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor;
|
||||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
||||||
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||||
m_mDispatchers["resizeactive"] = resizeActive;
|
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||||
m_mDispatchers["moveactive"] = moveActive;
|
m_mDispatchers["resizeactive"] = resizeActive;
|
||||||
m_mDispatchers["cyclenext"] = circleNext;
|
m_mDispatchers["moveactive"] = moveActive;
|
||||||
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
m_mDispatchers["cyclenext"] = circleNext;
|
||||||
m_mDispatchers["focuswindow"] = focusWindow;
|
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
||||||
m_mDispatchers["submap"] = setSubmap;
|
m_mDispatchers["focuswindow"] = focusWindow;
|
||||||
m_mDispatchers["pass"] = pass;
|
m_mDispatchers["submap"] = setSubmap;
|
||||||
m_mDispatchers["layoutmsg"] = layoutmsg;
|
m_mDispatchers["pass"] = pass;
|
||||||
m_mDispatchers["toggleopaque"] = toggleOpaque;
|
m_mDispatchers["layoutmsg"] = layoutmsg;
|
||||||
m_mDispatchers["dpms"] = dpms;
|
m_mDispatchers["toggleopaque"] = toggleOpaque;
|
||||||
m_mDispatchers["movewindowpixel"] = moveWindow;
|
m_mDispatchers["dpms"] = dpms;
|
||||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
m_mDispatchers["movewindowpixel"] = moveWindow;
|
||||||
m_mDispatchers["swapnext"] = swapnext;
|
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||||
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
m_mDispatchers["swapnext"] = swapnext;
|
||||||
m_mDispatchers["pin"] = pinActive;
|
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
||||||
m_mDispatchers["mouse"] = mouse;
|
m_mDispatchers["pin"] = pinActive;
|
||||||
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
|
m_mDispatchers["mouse"] = mouse;
|
||||||
m_mDispatchers["alterzorder"] = alterZOrder;
|
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
|
||||||
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
|
m_mDispatchers["alterzorder"] = alterZOrder;
|
||||||
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
|
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
|
||||||
m_mDispatchers["lockgroups"] = lockGroups;
|
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
|
||||||
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
|
m_mDispatchers["lockgroups"] = lockGroups;
|
||||||
m_mDispatchers["moveintogroup"] = moveIntoGroup;
|
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
|
||||||
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
|
m_mDispatchers["moveintogroup"] = moveIntoGroup;
|
||||||
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
|
||||||
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
||||||
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
||||||
m_mDispatchers["global"] = global;
|
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
||||||
|
m_mDispatchers["global"] = global;
|
||||||
|
|
||||||
m_tScrollTimer.reset();
|
m_tScrollTimer.reset();
|
||||||
|
|
||||||
|
@ -313,9 +314,10 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||||
.keysym = keysym,
|
.keysym = keysym,
|
||||||
.keycode = KEYCODE,
|
.keycode = KEYCODE,
|
||||||
.modmaskAtPressTime = MODS,
|
.modmaskAtPressTime = MODS,
|
||||||
|
.sent = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool found = false;
|
bool suppressEvent = false;
|
||||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
// clean repeat
|
// clean repeat
|
||||||
if (m_pActiveKeybindEventSource) {
|
if (m_pActiveKeybindEventSource) {
|
||||||
|
@ -326,10 +328,12 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||||
|
|
||||||
m_dPressedKeys.push_back(KEY);
|
m_dPressedKeys.push_back(KEY);
|
||||||
|
|
||||||
found = handleKeybinds(MODS, KEY, true);
|
suppressEvent = handleKeybinds(MODS, KEY, true);
|
||||||
|
|
||||||
if (found)
|
if (suppressEvent)
|
||||||
shadowKeybinds(keysym, KEYCODE);
|
shadowKeybinds(keysym, KEYCODE);
|
||||||
|
|
||||||
|
m_dPressedKeys.back().sent = !suppressEvent;
|
||||||
} else { // key release
|
} else { // key release
|
||||||
// clean repeat
|
// clean repeat
|
||||||
if (m_pActiveKeybindEventSource) {
|
if (m_pActiveKeybindEventSource) {
|
||||||
|
@ -341,11 +345,10 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||||
bool foundInPressedKeys = false;
|
bool foundInPressedKeys = false;
|
||||||
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
||||||
if (it->keycode == KEYCODE) {
|
if (it->keycode == KEYCODE) {
|
||||||
if (!foundInPressedKeys) {
|
suppressEvent = handleKeybinds(MODS, *it, false);
|
||||||
found = handleKeybinds(MODS, *it, false);
|
foundInPressedKeys = true;
|
||||||
foundInPressedKeys = true;
|
suppressEvent = !it->sent;
|
||||||
}
|
it = m_dPressedKeys.erase(it);
|
||||||
it = m_dPressedKeys.erase(it);
|
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -353,13 +356,13 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||||
if (!foundInPressedKeys) {
|
if (!foundInPressedKeys) {
|
||||||
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys");
|
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys");
|
||||||
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
||||||
found = handleKeybinds(MODS, KEY, false);
|
suppressEvent = handleKeybinds(MODS, KEY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowKeybinds();
|
shadowKeybinds();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !found && !mouseBindWasActive;
|
return !suppressEvent && !mouseBindWasActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||||
|
@ -396,7 +399,7 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||||
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||||
|
|
||||||
bool found = false;
|
bool suppressEvent = false;
|
||||||
|
|
||||||
m_uLastMouseCode = e->button;
|
m_uLastMouseCode = e->button;
|
||||||
m_uLastCode = 0;
|
m_uLastCode = 0;
|
||||||
|
@ -414,19 +417,20 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||||
if (e->state == WLR_BUTTON_PRESSED) {
|
if (e->state == WLR_BUTTON_PRESSED) {
|
||||||
m_dPressedKeys.push_back(KEY);
|
m_dPressedKeys.push_back(KEY);
|
||||||
|
|
||||||
found = handleKeybinds(MODS, KEY, true);
|
suppressEvent = handleKeybinds(MODS, KEY, true);
|
||||||
|
|
||||||
if (found)
|
if (suppressEvent)
|
||||||
shadowKeybinds();
|
shadowKeybinds();
|
||||||
|
|
||||||
|
m_dPressedKeys.back().sent = !suppressEvent;
|
||||||
} else {
|
} else {
|
||||||
bool foundInPressedKeys = false;
|
bool foundInPressedKeys = false;
|
||||||
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
||||||
if (it->keyName == KEY_NAME) {
|
if (it->keyName == KEY_NAME) {
|
||||||
if (!foundInPressedKeys) {
|
suppressEvent = handleKeybinds(MODS, *it, false);
|
||||||
found = handleKeybinds(MODS, *it, false);
|
foundInPressedKeys = true;
|
||||||
foundInPressedKeys = true;
|
suppressEvent = !it->sent;
|
||||||
}
|
it = m_dPressedKeys.erase(it);
|
||||||
it = m_dPressedKeys.erase(it);
|
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -434,13 +438,13 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||||
if (!foundInPressedKeys) {
|
if (!foundInPressedKeys) {
|
||||||
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)");
|
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)");
|
||||||
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
||||||
found = handleKeybinds(MODS, KEY, false);
|
suppressEvent = handleKeybinds(MODS, KEY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowKeybinds();
|
shadowKeybinds();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !found && !mouseBindWasActive;
|
return !suppressEvent && !mouseBindWasActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) {
|
void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) {
|
||||||
|
@ -522,7 +526,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi
|
||||||
|
|
||||||
if (!pressed) {
|
if (!pressed) {
|
||||||
// Require mods to be matching when the key was first pressed.
|
// Require mods to be matching when the key was first pressed.
|
||||||
if (key.modmaskAtPressTime != modmask) {
|
if (key.modmaskAtPressTime != modmask && !k.ignoreMods) {
|
||||||
// Handle properly `bindr` where a key is itself a bind mod for example:
|
// Handle properly `bindr` where a key is itself a bind mod for example:
|
||||||
// "bindr = SUPER, SUPER_L, exec, $launcher".
|
// "bindr = SUPER, SUPER_L, exec, $launcher".
|
||||||
// This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
|
// This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
|
||||||
|
@ -1449,7 +1453,7 @@ void CKeybindManager::renameWorkspace(std::string args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::exitHyprland(std::string argz) {
|
void CKeybindManager::exitHyprland(std::string argz) {
|
||||||
g_pCompositor->cleanup();
|
g_pInputManager->m_bExitTriggered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||||
|
@ -1499,6 +1503,48 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||||
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
|
||||||
|
std::string workspaceName;
|
||||||
|
const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
|
||||||
|
|
||||||
|
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||||
|
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto PCURRMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||||
|
|
||||||
|
if (!PCURRMONITOR) {
|
||||||
|
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
|
|
||||||
|
if (!PWORKSPACE) {
|
||||||
|
PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, PCURRMONITOR->ID);
|
||||||
|
// we can skip the moving, since it's already on the current monitor
|
||||||
|
changeworkspace(PWORKSPACE->getConfigName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PWORKSPACE->m_iMonitorID != PCURRMONITOR->ID) {
|
||||||
|
const auto POLDMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||||
|
if (!POLDMONITOR) { // wat
|
||||||
|
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (POLDMONITOR->activeWorkspace == WORKSPACEID) {
|
||||||
|
g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PCURRMONITOR, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeworkspace(PWORKSPACE->getConfigName());
|
||||||
|
}
|
||||||
|
|
||||||
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||||
|
|
||||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||||
|
@ -1806,11 +1852,11 @@ void CKeybindManager::dpms(std::string arg) {
|
||||||
if (!port.empty() && m->szName != port)
|
if (!port.empty() && m->szName != port)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wlr_output_enable(m->output, enable);
|
wlr_output_state_set_enabled(m->state.wlr(), enable);
|
||||||
|
|
||||||
m->dpmsStatus = enable;
|
m->dpmsStatus = enable;
|
||||||
|
|
||||||
if (!wlr_output_commit(m->output)) {
|
if (!m->state.commit()) {
|
||||||
Debug::log(ERR, "Couldn't commit output {}", m->szName);
|
Debug::log(ERR, "Couldn't commit output {}", m->szName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct SPressedKeyWithMods {
|
||||||
xkb_keysym_t keysym = 0;
|
xkb_keysym_t keysym = 0;
|
||||||
uint32_t keycode = 0;
|
uint32_t keycode = 0;
|
||||||
uint32_t modmaskAtPressTime = 0;
|
uint32_t modmaskAtPressTime = 0;
|
||||||
|
bool sent = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CKeybindManager {
|
class CKeybindManager {
|
||||||
|
@ -133,6 +134,7 @@ class CKeybindManager {
|
||||||
static void exitHyprland(std::string);
|
static void exitHyprland(std::string);
|
||||||
static void moveCurrentWorkspaceToMonitor(std::string);
|
static void moveCurrentWorkspaceToMonitor(std::string);
|
||||||
static void moveWorkspaceToMonitor(std::string);
|
static void moveWorkspaceToMonitor(std::string);
|
||||||
|
static void focusWorkspaceOnCurrentMonitor(std::string);
|
||||||
static void toggleSpecialWorkspace(std::string);
|
static void toggleSpecialWorkspace(std::string);
|
||||||
static void forceRendererReload(std::string);
|
static void forceRendererReload(std::string);
|
||||||
static void resizeActive(std::string);
|
static void resizeActive(std::string);
|
||||||
|
|
|
@ -421,7 +421,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
m_bLastFocusOnLS = false;
|
m_bLastFocusOnLS = false;
|
||||||
return; // don't enter any new surfaces
|
return; // don't enter any new surfaces
|
||||||
} else {
|
} else {
|
||||||
if (((FOLLOWMOUSE != 3 && allowKeyboardRefocus) && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus) {
|
if (allowKeyboardRefocus && ((FOLLOWMOUSE != 3 && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus)) {
|
||||||
m_pLastMouseFocus = pFoundWindow;
|
m_pLastMouseFocus = pFoundWindow;
|
||||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||||
}
|
}
|
||||||
|
@ -695,7 +695,8 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source);
|
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source,
|
||||||
|
WLR_AXIS_RELATIVE_DIRECTION_IDENTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CInputManager::getMouseCoordsInternal() {
|
Vector2D CInputManager::getMouseCoordsInternal() {
|
||||||
|
@ -1185,6 +1186,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||||
|
|
||||||
updateKeyboardsLeds(pKeyboard->keyboard);
|
updateKeyboardsLeds(pKeyboard->keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_bExitTriggered)
|
||||||
|
g_pCompositor->cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||||
|
@ -1457,12 +1461,16 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
|
void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
|
||||||
|
|
||||||
auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void {
|
auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void {
|
||||||
if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) {
|
if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice);
|
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice);
|
||||||
|
|
||||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7);
|
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "enabled", "input:touchdevice:enabled");
|
||||||
|
const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||||
|
if (libinput_device_config_send_events_get_mode(LIBINPUTDEV) != mode)
|
||||||
|
libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode);
|
||||||
|
|
||||||
|
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7);
|
||||||
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
|
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
|
||||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||||
|
|
||||||
|
|
|
@ -142,25 +142,28 @@ class CInputManager {
|
||||||
// Switches
|
// Switches
|
||||||
std::list<SSwitchDevice> m_lSwitches;
|
std::list<SSwitchDevice> m_lSwitches;
|
||||||
|
|
||||||
void newTabletTool(wlr_input_device*);
|
// Exclusive layer surfaces
|
||||||
void newTabletPad(wlr_input_device*);
|
std::deque<SLayerSurface*> m_dExclusiveLSes;
|
||||||
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 newTabletTool(wlr_input_device*);
|
||||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
void newTabletPad(wlr_input_device*);
|
||||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||||
|
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
|
||||||
|
void recheckIdleInhibitorStatus();
|
||||||
|
|
||||||
SSwipeGesture m_sActiveSwipe;
|
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||||
|
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||||
|
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||||
|
|
||||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
SSwipeGesture m_sActiveSwipe;
|
||||||
|
|
||||||
CTimer m_tmrLastCursorMovement;
|
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||||
|
|
||||||
CInputMethodRelay m_sIMERelay;
|
CTimer m_tmrLastCursorMovement;
|
||||||
|
|
||||||
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
CInputMethodRelay m_sIMERelay;
|
||||||
|
|
||||||
|
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
||||||
|
|
||||||
// for shared mods
|
// for shared mods
|
||||||
uint32_t accumulateModsFromAllKBs();
|
uint32_t accumulateModsFromAllKBs();
|
||||||
|
@ -243,6 +246,8 @@ class CInputManager {
|
||||||
|
|
||||||
void restoreCursorIconToApp(); // no-op if restored
|
void restoreCursorIconToApp(); // no-op if restored
|
||||||
|
|
||||||
|
bool m_bExitTriggered = false; // for exit dispatcher
|
||||||
|
|
||||||
friend class CKeybindManager;
|
friend class CKeybindManager;
|
||||||
friend class CWLSurface;
|
friend class CWLSurface;
|
||||||
};
|
};
|
||||||
|
|
|
@ -265,7 +265,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||||
PWORKSPACE->m_bForceRendering = true;
|
PWORKSPACE->m_bForceRendering = true;
|
||||||
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f);
|
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f);
|
||||||
|
|
||||||
if (workspaceIDLeft != workspaceIDRight) {
|
if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_sActiveSwipe.pWorkspaceBegin->m_iID) {
|
||||||
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||||
|
|
||||||
if (PWORKSPACER) {
|
if (PWORKSPACER) {
|
||||||
|
@ -305,7 +305,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||||
PWORKSPACE->m_bForceRendering = true;
|
PWORKSPACE->m_bForceRendering = true;
|
||||||
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f);
|
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f);
|
||||||
|
|
||||||
if (workspaceIDLeft != workspaceIDRight) {
|
if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_sActiveSwipe.pWorkspaceBegin->m_iID) {
|
||||||
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||||
|
|
||||||
if (PWORKSPACEL) {
|
if (PWORKSPACEL) {
|
||||||
|
|
|
@ -74,9 +74,10 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr
|
||||||
std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline);
|
std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline);
|
||||||
if (code.contains("%rip")) {
|
if (code.contains("%rip")) {
|
||||||
CVarList tokens{code, 0, 's'};
|
CVarList tokens{code, 0, 's'};
|
||||||
size_t plusPresent = tokens[1][0] == '+' ? 1 : 0;
|
size_t plusPresent = tokens[1][0] == '+' ? 1 : 0;
|
||||||
std::string addr = tokens[1].substr(plusPresent, tokens[1].find("(%rip)") - plusPresent);
|
size_t minusPresent = tokens[1][0] == '-' ? 1 : 0;
|
||||||
const uint64_t OFFSET = configStringToInt(addr);
|
std::string addr = tokens[1].substr((plusPresent || minusPresent), tokens[1].find("(%rip)") - (plusPresent || minusPresent));
|
||||||
|
const uint64_t OFFSET = (minusPresent ? -1 : 1) * configStringToInt(addr);
|
||||||
if (OFFSET == 0)
|
if (OFFSET == 0)
|
||||||
return {};
|
return {};
|
||||||
const uint64_t DESTINATION = currentAddress + OFFSET + len;
|
const uint64_t DESTINATION = currentAddress + OFFSET + len;
|
||||||
|
|
|
@ -189,16 +189,39 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) {
|
||||||
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer* fb) {
|
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer* fb) {
|
||||||
m_RenderData.pMonitor = pMonitor;
|
m_RenderData.pMonitor = pMonitor;
|
||||||
|
|
||||||
|
#ifndef GLES2
|
||||||
|
|
||||||
|
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
|
||||||
|
if (RESETSTATUS != GL_NO_ERROR) {
|
||||||
|
std::string errStr = "";
|
||||||
|
switch (RESETSTATUS) {
|
||||||
|
case GL_GUILTY_CONTEXT_RESET: errStr = "GL_GUILTY_CONTEXT_RESET"; break;
|
||||||
|
case GL_INNOCENT_CONTEXT_RESET: errStr = "GL_INNOCENT_CONTEXT_RESET"; break;
|
||||||
|
case GL_UNKNOWN_CONTEXT_RESET: errStr = "GL_UNKNOWN_CONTEXT_RESET"; break;
|
||||||
|
default: errStr = "UNKNOWN??"; break;
|
||||||
|
}
|
||||||
|
RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
TRACY_GPU_ZONE("RenderBegin");
|
TRACY_GPU_ZONE("RenderBegin");
|
||||||
|
|
||||||
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||||
|
|
||||||
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
|
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
|
||||||
|
if (m_mMonitorRenderResources.contains(pMonitor) && m_mMonitorRenderResources.at(pMonitor).offloadFB.m_vSize != pMonitor->vecPixelSize)
|
||||||
|
destroyMonitorResources(pMonitor);
|
||||||
|
|
||||||
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
|
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
|
||||||
|
|
||||||
|
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
|
||||||
|
initShaders();
|
||||||
|
|
||||||
// ensure a framebuffer for the monitor exists
|
// ensure a framebuffer for the monitor exists
|
||||||
if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
|
if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
|
||||||
m_RenderData.pCurrentMonData->stencilTex.allocate();
|
m_RenderData.pCurrentMonData->stencilTex.allocate();
|
||||||
|
|
||||||
m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||||
|
@ -210,16 +233,11 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer*
|
||||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||||
m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||||
|
|
||||||
createBGTextureForMonitor(pMonitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty())
|
if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty())
|
||||||
m_RenderData.pCurrentMonData->monitorMirrorFB.release();
|
m_RenderData.pCurrentMonData->monitorMirrorFB.release();
|
||||||
|
|
||||||
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
|
|
||||||
initShaders();
|
|
||||||
|
|
||||||
m_RenderData.damage.set(*pDamage);
|
m_RenderData.damage.set(*pDamage);
|
||||||
|
|
||||||
m_bFakeFrame = fb;
|
m_bFakeFrame = fb;
|
||||||
|
@ -312,6 +330,15 @@ void CHyprOpenGLImpl::end() {
|
||||||
m_RenderData.mouseZoomFactor = 1.f;
|
m_RenderData.mouseZoomFactor = 1.f;
|
||||||
m_RenderData.mouseZoomUseMouse = true;
|
m_RenderData.mouseZoomUseMouse = true;
|
||||||
m_RenderData.forceIntrospection = false;
|
m_RenderData.forceIntrospection = false;
|
||||||
|
m_RenderData.currentFB = nullptr;
|
||||||
|
m_RenderData.mainFB = nullptr;
|
||||||
|
m_RenderData.outFB = nullptr;
|
||||||
|
|
||||||
|
// check for gl errors
|
||||||
|
const GLenum ERR = glGetError();
|
||||||
|
|
||||||
|
if (ERR == GL_CONTEXT_LOST) /* We don't have infra to recover from this */
|
||||||
|
RASSERT(false, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Cannot continue until proper GPU reset handling is implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::initShaders() {
|
void CHyprOpenGLImpl::initShaders() {
|
||||||
|
@ -723,7 +750,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
|
||||||
|
|
||||||
alpha = std::clamp(alpha, 0.f, 1.f);
|
alpha = std::clamp(alpha, 0.f, 1.f);
|
||||||
|
|
||||||
if (m_RenderData.damage.empty())
|
if (damage->empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox newBox = *pBox;
|
CBox newBox = *pBox;
|
||||||
|
@ -1887,10 +1914,10 @@ void CHyprOpenGLImpl::renderMirrored() {
|
||||||
renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false);
|
renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY) {
|
void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) {
|
||||||
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
|
||||||
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
|
const auto FONTSIZE = (int)(size.y / 76);
|
||||||
cairo_set_font_size(CAIRO, FONTSIZE);
|
cairo_set_font_size(CAIRO, FONTSIZE);
|
||||||
|
|
||||||
cairo_set_source_rgba(CAIRO, 1.0, 1.0, 1.0, 0.32);
|
cairo_set_source_rgba(CAIRO, 1.0, 1.0, 1.0, 0.32);
|
||||||
|
@ -1898,7 +1925,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const
|
||||||
cairo_text_extents_t textExtents;
|
cairo_text_extents_t textExtents;
|
||||||
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
|
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
|
||||||
|
|
||||||
cairo_move_to(CAIRO, (m_RenderData.pMonitor->vecPixelSize.x - textExtents.width) / 2.0, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height + offsetY);
|
cairo_move_to(CAIRO, (size.x - textExtents.width) / 2.0, size.y - textExtents.height + offsetY);
|
||||||
|
|
||||||
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
|
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
|
||||||
|
|
||||||
|
@ -1910,109 +1937,123 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
|
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
|
||||||
static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
|
static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
|
||||||
static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue;
|
|
||||||
static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue;
|
static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue;
|
||||||
|
|
||||||
const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast<int64_t>(-1L), static_cast<int64_t>(2L));
|
const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast<int64_t>(-1L), static_cast<int64_t>(2L));
|
||||||
|
|
||||||
|
static std::string texPath = "";
|
||||||
|
|
||||||
if (*PRENDERTEX)
|
if (*PRENDERTEX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// release the last tex if exists
|
// release the last tex if exists
|
||||||
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
|
const auto PFB = &m_mMonitorBGFBs[pMonitor];
|
||||||
PTEX->destroyTexture();
|
PFB->release();
|
||||||
|
|
||||||
PTEX->allocate();
|
PFB->alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||||
Debug::log(LOG, "Allocated texture for BGTex");
|
Debug::log(LOG, "Allocated texture for BGTex");
|
||||||
|
|
||||||
// TODO: use relative paths to the installation
|
// TODO: use relative paths to the installation
|
||||||
// or configure the paths at build time
|
// or configure the paths at build time
|
||||||
std::string texPath = "/usr/share/hyprland/wall_";
|
if (texPath.empty()) {
|
||||||
std::string prefixes[] = {"", "anime_", "anime2_"};
|
texPath = "/usr/share/hyprland/wall";
|
||||||
|
|
||||||
// get the adequate tex
|
// get the adequate tex
|
||||||
if (FORCEWALLPAPER == -1) {
|
if (FORCEWALLPAPER == -1) {
|
||||||
std::random_device dev;
|
std::mt19937_64 engine(time(nullptr));
|
||||||
std::mt19937 engine(dev());
|
std::uniform_int_distribution<> distribution(0, 2);
|
||||||
std::uniform_int_distribution<> distribution(0, 2);
|
|
||||||
std::uniform_int_distribution<> distribution_anime(1, 2);
|
|
||||||
|
|
||||||
if (PFORCEHYPRCHAN)
|
texPath += std::to_string(distribution(engine));
|
||||||
texPath += prefixes[distribution_anime(engine)];
|
} else
|
||||||
else
|
texPath += std::to_string(std::clamp(*PFORCEWALLPAPER, (int64_t)0, (int64_t)2));
|
||||||
texPath += prefixes[distribution(engine)];
|
|
||||||
} else
|
|
||||||
texPath += prefixes[FORCEWALLPAPER];
|
|
||||||
|
|
||||||
Vector2D textureSize;
|
texPath += ".png";
|
||||||
if (pMonitor->vecTransformedSize.x > 3850) {
|
|
||||||
textureSize = Vector2D(7680, 4320);
|
// check if wallpapers exist
|
||||||
texPath += "8K.png";
|
if (!std::filesystem::exists(texPath)) {
|
||||||
} else if (pMonitor->vecTransformedSize.x > 1930) {
|
// try local
|
||||||
textureSize = Vector2D(3840, 2160);
|
texPath = texPath.substr(0, 5) + "local/" + texPath.substr(5);
|
||||||
texPath += "4K.png";
|
|
||||||
} else {
|
if (!std::filesystem::exists(texPath))
|
||||||
textureSize = Vector2D(1920, 1080);
|
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
|
||||||
texPath += "2K.png";
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if wallpapers exist
|
// create a new one with cairo
|
||||||
if (!std::filesystem::exists(texPath)) {
|
CTexture tex;
|
||||||
// try local
|
|
||||||
texPath = texPath.substr(0, 5) + "local/" + texPath.substr(5);
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(texPath))
|
const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str());
|
||||||
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
|
const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE);
|
||||||
}
|
|
||||||
|
|
||||||
PTEX->m_vSize = textureSize;
|
tex.allocate();
|
||||||
|
const Vector2D IMAGESIZE = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)};
|
||||||
|
|
||||||
// calc the target box
|
// calc the target box
|
||||||
const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
|
const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
|
||||||
const double WPRATIO = 1.77;
|
const double WPRATIO = IMAGESIZE.x / IMAGESIZE.y;
|
||||||
|
|
||||||
Vector2D origin;
|
Vector2D origin;
|
||||||
double scale;
|
double scale;
|
||||||
|
|
||||||
if (MONRATIO > WPRATIO) {
|
if (MONRATIO > WPRATIO) {
|
||||||
scale = m_RenderData.pMonitor->vecTransformedSize.x / PTEX->m_vSize.x;
|
scale = m_RenderData.pMonitor->vecTransformedSize.x / IMAGESIZE.x;
|
||||||
|
|
||||||
origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - PTEX->m_vSize.y * scale) / 2.0;
|
origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - IMAGESIZE.y * scale) / 2.0;
|
||||||
} else {
|
} else {
|
||||||
scale = m_RenderData.pMonitor->vecTransformedSize.y / PTEX->m_vSize.y;
|
scale = m_RenderData.pMonitor->vecTransformedSize.y / IMAGESIZE.y;
|
||||||
|
|
||||||
origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - PTEX->m_vSize.x * scale) / 2.0;
|
origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - IMAGESIZE.x * scale) / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
|
const Vector2D scaledSize = IMAGESIZE * scale;
|
||||||
|
|
||||||
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
|
const auto CAIROSURFACE = cairo_image_surface_create(CAIROFORMAT, scaledSize.x, scaledSize.y);
|
||||||
|
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||||
|
|
||||||
// create a new one with cairo
|
cairo_set_antialias(CAIRO, CAIRO_ANTIALIAS_GOOD);
|
||||||
const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str());
|
cairo_scale(CAIRO, scale, scale);
|
||||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
cairo_rectangle(CAIRO, 0, 0, 100, 100);
|
||||||
|
cairo_set_source_surface(CAIRO, CAIROISURFACE, 0, 0);
|
||||||
|
cairo_paint(CAIRO);
|
||||||
|
|
||||||
// scale it to fit the current monitor
|
|
||||||
cairo_scale(CAIRO, textureSize.x / pMonitor->vecTransformedSize.x, textureSize.y / pMonitor->vecTransformedSize.y);
|
|
||||||
|
|
||||||
// render splash on wallpaper
|
|
||||||
if (!*PNOSPLASH)
|
if (!*PNOSPLASH)
|
||||||
renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO);
|
renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO * scale, IMAGESIZE);
|
||||||
|
|
||||||
|
cairo_surface_flush(CAIROSURFACE);
|
||||||
|
|
||||||
|
CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale};
|
||||||
|
tex.m_vSize = IMAGESIZE * scale;
|
||||||
|
|
||||||
// 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 GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA;
|
||||||
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
|
const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA;
|
||||||
|
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
|
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
#ifndef GLES2
|
#ifndef GLES2
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureSize.x, textureSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex.m_vSize.x, tex.m_vSize.y, 0, glFormat, glType, DATA);
|
||||||
|
|
||||||
cairo_surface_destroy(CAIROSURFACE);
|
cairo_surface_destroy(CAIROSURFACE);
|
||||||
|
cairo_surface_destroy(CAIROISURFACE);
|
||||||
cairo_destroy(CAIRO);
|
cairo_destroy(CAIRO);
|
||||||
|
|
||||||
|
// render the texture to our fb
|
||||||
|
PFB->bind();
|
||||||
|
CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
|
||||||
|
renderTextureInternalWithDamage(tex, &box, 1.0, &fakeDamage);
|
||||||
|
|
||||||
|
// bind back
|
||||||
|
if (m_RenderData.currentFB)
|
||||||
|
m_RenderData.currentFB->bind();
|
||||||
|
|
||||||
Debug::log(LOG, "Background created for monitor {}", pMonitor->szName);
|
Debug::log(LOG, "Background created for monitor {}", pMonitor->szName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2021,15 +2062,19 @@ void CHyprOpenGLImpl::clearWithTex() {
|
||||||
|
|
||||||
TRACY_GPU_ZONE("RenderClearWithTex");
|
TRACY_GPU_ZONE("RenderClearWithTex");
|
||||||
|
|
||||||
auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
|
auto TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor);
|
||||||
|
|
||||||
if (TEXIT == m_mMonitorBGTextures.end()) {
|
if (TEXIT == m_mMonitorBGFBs.end()) {
|
||||||
createBGTextureForMonitor(m_RenderData.pMonitor);
|
createBGTextureForMonitor(m_RenderData.pMonitor);
|
||||||
TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
|
TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TEXIT != m_mMonitorBGTextures.end())
|
if (TEXIT != m_mMonitorBGFBs.end()) {
|
||||||
renderTexturePrimitive(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox);
|
CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
|
m_bEndFrame = true;
|
||||||
|
renderTexture(TEXIT->second.m_cTex, &monbox, 1);
|
||||||
|
m_bEndFrame = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||||
|
@ -2047,10 +2092,10 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||||
g_pHyprOpenGL->m_mMonitorRenderResources.erase(RESIT);
|
g_pHyprOpenGL->m_mMonitorRenderResources.erase(RESIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto TEXIT = g_pHyprOpenGL->m_mMonitorBGTextures.find(pMonitor);
|
auto TEXIT = g_pHyprOpenGL->m_mMonitorBGFBs.find(pMonitor);
|
||||||
if (TEXIT != g_pHyprOpenGL->m_mMonitorBGTextures.end()) {
|
if (TEXIT != g_pHyprOpenGL->m_mMonitorBGFBs.end()) {
|
||||||
TEXIT->second.destroyTexture();
|
TEXIT->second.release();
|
||||||
g_pHyprOpenGL->m_mMonitorBGTextures.erase(TEXIT);
|
g_pHyprOpenGL->m_mMonitorBGFBs.erase(TEXIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Monitor {} -> destroyed all render data", pMonitor->szName);
|
Debug::log(LOG, "Monitor {} -> destroyed all render data", pMonitor->szName);
|
||||||
|
|
|
@ -71,8 +71,6 @@ struct SMonitorRenderData {
|
||||||
bool blurFBDirty = true;
|
bool blurFBDirty = true;
|
||||||
bool blurFBShouldRender = false;
|
bool blurFBShouldRender = false;
|
||||||
|
|
||||||
CBox backgroundTexBox;
|
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
bool m_bShadersInitialized = false;
|
bool m_bShadersInitialized = false;
|
||||||
CShader m_shQUAD;
|
CShader m_shQUAD;
|
||||||
|
@ -191,7 +189,7 @@ class CHyprOpenGLImpl {
|
||||||
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
|
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
|
||||||
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
|
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
|
||||||
std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
|
std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
|
||||||
std::unordered_map<CMonitor*, CTexture> m_mMonitorBGTextures;
|
std::unordered_map<CMonitor*, CFramebuffer> m_mMonitorBGFBs;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||||
|
@ -229,7 +227,7 @@ class CHyprOpenGLImpl {
|
||||||
void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, CCornerRadiiData radii = 0, bool discardOpaque = false, bool noAA = false,
|
void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, CCornerRadiiData radii = 0, bool discardOpaque = false, bool noAA = false,
|
||||||
bool allowCustomUV = false, bool allowDim = false);
|
bool allowCustomUV = false, bool allowDim = false);
|
||||||
void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
|
void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
|
||||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double);
|
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||||
|
|
||||||
void preBlurForCurrentMonitor();
|
void preBlurForCurrentMonitor();
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprRenderer::CHyprRenderer() {
|
CHyprRenderer::CHyprRenderer() {
|
||||||
if (envEnabled("WLR_DRM_NO_ATOMIC"))
|
|
||||||
m_bTearingEnvSatisfied = true;
|
|
||||||
|
|
||||||
if (g_pCompositor->m_sWLRSession) {
|
if (g_pCompositor->m_sWLRSession) {
|
||||||
wlr_device* dev;
|
wlr_device* dev;
|
||||||
|
@ -107,19 +105,22 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
||||||
if (windowBox.width <= 1 || windowBox.height <= 1)
|
if (windowBox.width <= 1 || windowBox.height <= 1)
|
||||||
return; // invisible
|
return; // invisible
|
||||||
|
|
||||||
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface);
|
|
||||||
|
|
||||||
windowBox.scale(RDATA->pMonitor->scale);
|
windowBox.scale(RDATA->pMonitor->scale);
|
||||||
windowBox.round();
|
windowBox.round();
|
||||||
|
|
||||||
// check for fractional scale surfaces misaligning the buffer size
|
const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ &&
|
||||||
// in those cases it's better to just force nearest neighbor
|
|
||||||
// as long as the window is not animated. During those it'd look weird
|
|
||||||
const auto NEARESTNEIGHBORSET = g_pHyprOpenGL->m_RenderData.useNearestNeighbor;
|
|
||||||
if (std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ &&
|
|
||||||
windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ &&
|
windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ &&
|
||||||
DELTALESSTHAN(windowBox.width, surface->current.buffer_width, 3) && DELTALESSTHAN(windowBox.height, surface->current.buffer_height, 3) /* off by one-or-two */ &&
|
DELTALESSTHAN(windowBox.width, surface->current.buffer_width, 3) && DELTALESSTHAN(windowBox.height, surface->current.buffer_height, 3) /* off by one-or-two */ &&
|
||||||
(!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */)
|
(!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */;
|
||||||
|
|
||||||
|
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1);
|
||||||
|
|
||||||
|
// check for fractional scale surfaces misaligning the buffer size
|
||||||
|
// in those cases it's better to just force nearest neighbor
|
||||||
|
// as long as the window is not animated. During those it'd look weird.
|
||||||
|
// UV will fixup it as well
|
||||||
|
const auto NEARESTNEIGHBORSET = g_pHyprOpenGL->m_RenderData.useNearestNeighbor;
|
||||||
|
if (MISALIGNEDFSV1)
|
||||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||||
|
|
||||||
CCornerRadiiData radii = RDATA->cornerRadii;
|
CCornerRadiiData radii = RDATA->cornerRadii;
|
||||||
|
@ -290,11 +291,14 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace || !w->m_bIsFullscreen)
|
if (!w->m_bIsFullscreen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
||||||
|
|
||||||
|
if (w->m_iWorkspaceID != pWorkspace->m_iID)
|
||||||
|
continue;
|
||||||
|
|
||||||
pWorkspaceWindow = w.get();
|
pWorkspaceWindow = w.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +457,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||||
|
|
||||||
// clip box for animated offsets
|
// clip box for animated offsets
|
||||||
const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y};
|
const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y};
|
||||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) {
|
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned && !pWindow->m_bIsFullscreen) {
|
||||||
Vector2D offset;
|
Vector2D offset;
|
||||||
|
|
||||||
if (PWORKSPACE->m_vRenderOffset.vec().x != 0) {
|
if (PWORKSPACE->m_vRenderOffset.vec().x != 0) {
|
||||||
|
@ -805,7 +809,7 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurface, bool main) {
|
void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) {
|
||||||
if (!pWindow || !pWindow->m_bIsX11) {
|
if (!pWindow || !pWindow->m_bIsX11) {
|
||||||
Vector2D uvTL;
|
Vector2D uvTL;
|
||||||
Vector2D uvBR = Vector2D(1, 1);
|
Vector2D uvBR = Vector2D(1, 1);
|
||||||
|
@ -827,6 +831,15 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (projSize != Vector2D{} && fixMisalignedFSV1) {
|
||||||
|
// instead of nearest_neighbor (we will repeat / skip)
|
||||||
|
// just cut off / expand surface
|
||||||
|
const Vector2D PIXELASUV = Vector2D{1, 1} / Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height};
|
||||||
|
const Vector2D MISALIGNMENT = Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height} - projSize;
|
||||||
|
if (MISALIGNMENT != Vector2D{})
|
||||||
|
uvBR -= MISALIGNMENT * PIXELASUV;
|
||||||
|
}
|
||||||
|
|
||||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
|
||||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR;
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR;
|
||||||
|
|
||||||
|
@ -902,9 +915,9 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// finally, we should be GTG.
|
// finally, we should be GTG.
|
||||||
wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base);
|
wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base);
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output))
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
timespec now;
|
timespec now;
|
||||||
|
@ -912,7 +925,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||||
wlr_surface_send_frame_done(PSURFACE, &now);
|
wlr_surface_send_frame_done(PSURFACE, &now);
|
||||||
wlr_presentation_surface_scanned_out_on_output(PSURFACE, pMonitor->output);
|
wlr_presentation_surface_scanned_out_on_output(PSURFACE, pMonitor->output);
|
||||||
|
|
||||||
if (wlr_output_commit(pMonitor->output)) {
|
if (pMonitor->state.commit()) {
|
||||||
if (!m_pLastScanout) {
|
if (!m_pLastScanout) {
|
||||||
m_pLastScanout = PCANDIDATE;
|
m_pLastScanout = PCANDIDATE;
|
||||||
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE, PCANDIDATE->m_szTitle);
|
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE, PCANDIDATE->m_szTitle);
|
||||||
|
@ -1013,14 +1026,15 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
const auto PGAMMACTRL = wlr_gamma_control_manager_v1_get_control(g_pCompositor->m_sWLRGammaCtrlMgr, pMonitor->output);
|
const auto PGAMMACTRL = wlr_gamma_control_manager_v1_get_control(g_pCompositor->m_sWLRGammaCtrlMgr, pMonitor->output);
|
||||||
|
|
||||||
if (!wlr_gamma_control_v1_apply(PGAMMACTRL, &pMonitor->output->pending)) {
|
if (!wlr_gamma_control_v1_apply(PGAMMACTRL, pMonitor->state.wlr())) {
|
||||||
Debug::log(ERR, "Could not apply gamma control to {}", pMonitor->szName);
|
Debug::log(ERR, "Could not apply gamma control to {}", pMonitor->szName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output)) {
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(ERR, "Output test failed for setting gamma to {}", pMonitor->szName);
|
Debug::log(ERR, "Output test failed for setting gamma to {}", pMonitor->szName);
|
||||||
wlr_output_rollback(pMonitor->output);
|
// aka rollback
|
||||||
|
wlr_gamma_control_v1_apply(nullptr, pMonitor->state.wlr());
|
||||||
wlr_gamma_control_v1_send_failed_and_destroy(PGAMMACTRL);
|
wlr_gamma_control_v1_send_failed_and_destroy(PGAMMACTRL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1149,6 +1163,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
if (UNLOCK_SC)
|
if (UNLOCK_SC)
|
||||||
wlr_output_lock_software_cursors(pMonitor->output, false);
|
wlr_output_lock_software_cursors(pMonitor->output, false);
|
||||||
|
|
||||||
|
pMonitor->state.clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,9 +1251,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("render", RENDER_POST);
|
EMIT_HOOK_EVENT("render", RENDER_POST);
|
||||||
|
|
||||||
pMonitor->output->pending.tearing_page_flip = shouldTear;
|
pMonitor->state.wlr()->tearing_page_flip = shouldTear;
|
||||||
|
|
||||||
if (!wlr_output_commit(pMonitor->output)) {
|
if (!pMonitor->state.commit()) {
|
||||||
|
|
||||||
if (UNLOCK_SC)
|
if (UNLOCK_SC)
|
||||||
wlr_output_lock_software_cursors(pMonitor->output, false);
|
wlr_output_lock_software_cursors(pMonitor->output, false);
|
||||||
|
@ -1324,6 +1340,8 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool
|
||||||
|
|
||||||
std::string commandForCfg = "";
|
std::string commandForCfg = "";
|
||||||
const auto OUTPUT = head->state.output;
|
const auto OUTPUT = head->state.output;
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||||
|
RASSERT(PMONITOR, "nullptr monitor in outputMgrApplyTest");
|
||||||
|
|
||||||
commandForCfg += std::string(OUTPUT->name) + ",";
|
commandForCfg += std::string(OUTPUT->name) + ",";
|
||||||
|
|
||||||
|
@ -1334,7 +1352,7 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_enable(OUTPUT, head->state.enabled);
|
wlr_output_state_set_enabled(PMONITOR->state.wlr(), head->state.enabled);
|
||||||
|
|
||||||
if (head->state.mode)
|
if (head->state.mode)
|
||||||
commandForCfg +=
|
commandForCfg +=
|
||||||
|
@ -1348,10 +1366,10 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool
|
||||||
|
|
||||||
if (!test) {
|
if (!test) {
|
||||||
g_pConfigManager->parseKeyword("monitor", commandForCfg, true);
|
g_pConfigManager->parseKeyword("monitor", commandForCfg, true);
|
||||||
wlr_output_state_set_adaptive_sync_enabled(&OUTPUT->pending, head->state.adaptive_sync_enabled);
|
wlr_output_state_set_adaptive_sync_enabled(PMONITOR->state.wlr(), head->state.adaptive_sync_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = wlr_output_test(OUTPUT);
|
ok = wlr_output_test_state(OUTPUT, PMONITOR->state.wlr());
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
break;
|
break;
|
||||||
|
@ -1572,8 +1590,7 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
|
||||||
y += CORRECTION.y;
|
y += CORRECTION.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRegion damageBox;
|
CRegion damageBox{&pSurface->buffer_damage};
|
||||||
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
|
|
||||||
if (scale != 1.0)
|
if (scale != 1.0)
|
||||||
wlr_region_scale(damageBox.pixman(), damageBox.pixman(), scale);
|
wlr_region_scale(damageBox.pixman(), damageBox.pixman(), scale);
|
||||||
|
|
||||||
|
@ -1750,6 +1767,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto WAS10B = pMonitor->enabled10bit;
|
||||||
|
const auto OLDRES = pMonitor->vecPixelSize;
|
||||||
|
|
||||||
// Needed in case we are switching from a custom modeline to a standard mode
|
// Needed in case we are switching from a custom modeline to a standard mode
|
||||||
pMonitor->customDrmMode = {};
|
pMonitor->customDrmMode = {};
|
||||||
bool autoScale = false;
|
bool autoScale = false;
|
||||||
|
@ -1762,10 +1782,10 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
pMonitor->scale = DEFAULTSCALE;
|
pMonitor->scale = DEFAULTSCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_set_scale(pMonitor->output, pMonitor->scale);
|
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
|
||||||
pMonitor->setScale = pMonitor->scale;
|
pMonitor->setScale = pMonitor->scale;
|
||||||
|
|
||||||
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
|
wlr_output_state_set_transform(pMonitor->state.wlr(), pMonitorRule->transform);
|
||||||
pMonitor->transform = pMonitorRule->transform;
|
pMonitor->transform = pMonitorRule->transform;
|
||||||
|
|
||||||
const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : pMonitorRule->refreshRate * 1000;
|
const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : pMonitorRule->refreshRate * 1000;
|
||||||
|
@ -1780,9 +1800,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
|
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
|
||||||
if (DELTALESSTHAN(mode->width, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(mode->height, pMonitorRule->resolution.y, 1) &&
|
if (DELTALESSTHAN(mode->width, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(mode->height, pMonitorRule->resolution.y, 1) &&
|
||||||
DELTALESSTHAN(mode->refresh / 1000.f, pMonitorRule->refreshRate, 1)) {
|
DELTALESSTHAN(mode->refresh / 1000.f, pMonitorRule->refreshRate, 1)) {
|
||||||
wlr_output_set_mode(pMonitor->output, mode);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output)) {
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1800,11 +1820,11 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
|
wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
|
||||||
pMonitor->vecSize = pMonitorRule->resolution;
|
pMonitor->vecSize = pMonitorRule->resolution;
|
||||||
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output)) {
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||||
|
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||||
|
@ -1816,7 +1836,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
||||||
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
||||||
|
@ -1838,7 +1858,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
} else {
|
} else {
|
||||||
auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &pMonitorRule->drmMode);
|
auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &pMonitorRule->drmMode);
|
||||||
if (mode) {
|
if (mode) {
|
||||||
wlr_output_set_mode(pMonitor->output, mode);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
pMonitor->customDrmMode = pMonitorRule->drmMode;
|
pMonitor->customDrmMode = pMonitorRule->drmMode;
|
||||||
} else {
|
} else {
|
||||||
Debug::log(ERR, "wlr_drm_connector_add_mode failed");
|
Debug::log(ERR, "wlr_drm_connector_add_mode failed");
|
||||||
|
@ -1846,13 +1866,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
|
wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pMonitor->vecSize = pMonitorRule->resolution;
|
pMonitor->vecSize = pMonitorRule->resolution;
|
||||||
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
||||||
|
|
||||||
if (fail || !wlr_output_test(pMonitor->output)) {
|
if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||||
|
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
||||||
|
@ -1864,7 +1884,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
||||||
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
||||||
|
@ -1888,8 +1908,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
if (pMonitorRule->resolution == Vector2D(-1, -1)) {
|
if (pMonitorRule->resolution == Vector2D(-1, -1)) {
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
||||||
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
|
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
|
||||||
wlr_output_set_mode(pMonitor->output, mode);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
if (wlr_output_test(pMonitor->output)) {
|
if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
currentWidth = mode->width;
|
currentWidth = mode->width;
|
||||||
currentHeight = mode->height;
|
currentHeight = mode->height;
|
||||||
currentRefresh = mode->refresh;
|
currentRefresh = mode->refresh;
|
||||||
|
@ -1901,8 +1921,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
||||||
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) ||
|
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) ||
|
||||||
(mode->width > currentWidth && mode->height > currentHeight)) {
|
(mode->width > currentWidth && mode->height > currentHeight)) {
|
||||||
wlr_output_set_mode(pMonitor->output, mode);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
if (wlr_output_test(pMonitor->output)) {
|
if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
currentWidth = mode->width;
|
currentWidth = mode->width;
|
||||||
currentHeight = mode->height;
|
currentHeight = mode->height;
|
||||||
currentRefresh = mode->refresh;
|
currentRefresh = mode->refresh;
|
||||||
|
@ -1925,7 +1945,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name,
|
||||||
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
pMonitorRule->resolution, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
||||||
|
@ -1950,9 +1970,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
wlr_output_mode* mode;
|
wlr_output_mode* mode;
|
||||||
|
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
||||||
wlr_output_set_mode(pMonitor->output, mode);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output)) {
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1968,7 +1988,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
||||||
|
|
||||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
||||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
||||||
|
@ -1977,7 +1997,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pMonitor->vrrActive = pMonitor->output->pending.adaptive_sync_enabled; // disabled here, will be tested in CConfigManager::ensureVRR()
|
pMonitor->vrrActive = pMonitor->state.wlr()->adaptive_sync_enabled // disabled here, will be tested in CConfigManager::ensureVRR()
|
||||||
|
|| pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
|
||||||
|
|
||||||
pMonitor->vecPixelSize = pMonitor->vecSize;
|
pMonitor->vecPixelSize = pMonitor->vecSize;
|
||||||
|
|
||||||
|
@ -1994,6 +2015,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero;
|
Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero;
|
||||||
if (logicalZero == logicalZero.round()) {
|
if (logicalZero == logicalZero.round()) {
|
||||||
pMonitor->scale = scaleZero;
|
pMonitor->scale = scaleZero;
|
||||||
|
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 1; i < 90; ++i) {
|
for (size_t i = 1; i < 90; ++i) {
|
||||||
double scaleUp = (searchScale + i) / 120.0;
|
double scaleUp = (searchScale + i) / 120.0;
|
||||||
|
@ -2031,11 +2053,15 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
} else
|
} else
|
||||||
pMonitor->scale = searchScale;
|
pMonitor->scale = searchScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for wlroots, that likes flooring, we have to do this.
|
||||||
|
double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale);
|
||||||
|
logicalX += 0.1;
|
||||||
|
|
||||||
|
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->vecPixelSize.x / logicalX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_set_scale(pMonitor->output, pMonitor->scale);
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const std::array<std::vector<std::pair<std::string, uint32_t>>, 2> formats{
|
static const std::array<std::vector<std::pair<std::string, uint32_t>>, 2> formats{
|
||||||
std::vector<std::pair<std::string, uint32_t>>{ /* 10-bit */
|
std::vector<std::pair<std::string, uint32_t>>{ /* 10-bit */
|
||||||
|
@ -2051,9 +2077,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
pMonitor->drmFormat = DRM_FORMAT_INVALID;
|
pMonitor->drmFormat = DRM_FORMAT_INVALID;
|
||||||
|
|
||||||
for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) {
|
for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) {
|
||||||
wlr_output_set_render_format(pMonitor->output, fmt.second);
|
wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second);
|
||||||
|
|
||||||
if (!wlr_output_test(pMonitor->output)) {
|
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
||||||
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
|
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
|
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
|
||||||
|
@ -2067,9 +2093,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
|
|
||||||
pMonitor->enabled10bit = set10bit;
|
pMonitor->enabled10bit = set10bit;
|
||||||
|
|
||||||
if (!wlr_output_commit(pMonitor->output)) {
|
if (!pMonitor->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name);
|
Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name);
|
||||||
}
|
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
||||||
|
@ -2085,14 +2110,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
|
|
||||||
pMonitor->updateMatrix();
|
pMonitor->updateMatrix();
|
||||||
|
|
||||||
// update renderer (here because it will call rollback, so we cannot do this before committing)
|
if (WAS10B != pMonitor->enabled10bit || OLDRES != pMonitor->vecPixelSize)
|
||||||
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
||||||
|
|
||||||
// updato wlroots
|
// updato wlroots
|
||||||
g_pCompositor->arrangeMonitors();
|
g_pCompositor->arrangeMonitors();
|
||||||
|
|
||||||
wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
|
wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
|
||||||
|
|
||||||
|
// Set scale for all surfaces on this monitor, needed for some clients
|
||||||
|
// but not on unsafe state to avoid crashes
|
||||||
|
if (!g_pCompositor->m_bUnsafeState) {
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
w->updateSurfaceScaleTransformDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
// updato us
|
// updato us
|
||||||
arrangeLayersForMonitor(pMonitor->ID);
|
arrangeLayersForMonitor(pMonitor->ID);
|
||||||
|
|
||||||
|
@ -2429,7 +2461,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
if (!wlr_output_configure_primary_swapchain(pMonitor->output, &pMonitor->output->pending, &pMonitor->output->swapchain))
|
if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &m_iLastBufferAge);
|
m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &m_iLastBufferAge);
|
||||||
|
@ -2473,7 +2505,7 @@ void CHyprRenderer::endRender() {
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
||||||
wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer);
|
wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer);
|
||||||
unsetEGL(); // flush the context
|
unsetEGL(); // flush the context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ class CHyprRenderer {
|
||||||
void ensureCursorRenderingMode();
|
void ensureCursorRenderingMode();
|
||||||
bool shouldRenderCursor();
|
bool shouldRenderCursor();
|
||||||
void setCursorHidden(bool hide);
|
void setCursorHidden(bool hide);
|
||||||
void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false);
|
void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false);
|
||||||
std::tuple<float, float, float> getRenderTimes(CMonitor* pMonitor); // avg max min
|
std::tuple<float, float, float> getRenderTimes(CMonitor* pMonitor); // avg max min
|
||||||
void renderLockscreen(CMonitor* pMonitor, timespec* now);
|
void renderLockscreen(CMonitor* pMonitor, timespec* now);
|
||||||
void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace);
|
void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace);
|
||||||
|
@ -82,7 +82,6 @@ class CHyprRenderer {
|
||||||
CMonitor* m_pMostHzMonitor = nullptr;
|
CMonitor* m_pMostHzMonitor = nullptr;
|
||||||
bool m_bDirectScanoutBlocked = false;
|
bool m_bDirectScanoutBlocked = false;
|
||||||
bool m_bSoftwareCursorsLocked = false;
|
bool m_bSoftwareCursorsLocked = false;
|
||||||
bool m_bTearingEnvSatisfied = false;
|
|
||||||
|
|
||||||
DAMAGETRACKINGMODES
|
DAMAGETRACKINGMODES
|
||||||
damageTrackingModeFromStr(const std::string&);
|
damageTrackingModeFromStr(const std::string&);
|
||||||
|
|
|
@ -26,9 +26,10 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindow
|
||||||
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {}
|
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {}
|
||||||
|
|
||||||
SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
|
SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
|
||||||
static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue;
|
static auto* const PHEIGHT = &g_pConfigManager->getConfigValuePtr("group:groupbar:height")->intValue;
|
||||||
static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue;
|
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
||||||
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue;
|
||||||
|
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue;
|
||||||
|
|
||||||
SDecorationPositioningInfo info;
|
SDecorationPositioningInfo info;
|
||||||
info.policy = DECORATION_POSITION_STICKY;
|
info.policy = DECORATION_POSITION_STICKY;
|
||||||
|
@ -37,7 +38,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
|
||||||
info.reserved = true;
|
info.reserved = true;
|
||||||
|
|
||||||
if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate)
|
if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate)
|
||||||
info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}};
|
info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}};
|
||||||
else
|
else
|
||||||
info.desiredExtents = {{0, 0}, {0, 0}};
|
info.desiredExtents = {{0, 0}, {0, 0}};
|
||||||
|
|
||||||
|
@ -90,6 +91,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||||
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
||||||
static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue;
|
static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue;
|
||||||
static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue;
|
static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue;
|
||||||
|
static auto* const PHEIGHT = &g_pConfigManager->getConfigValuePtr("group:groupbar:height")->intValue;
|
||||||
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue;
|
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue;
|
||||||
|
|
||||||
if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate)
|
if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate)
|
||||||
|
@ -99,7 +101,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||||
|
|
||||||
m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw;
|
m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw;
|
||||||
|
|
||||||
const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2;
|
const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2;
|
||||||
if (DESIREDHEIGHT != ASSIGNEDBOX.h)
|
if (DESIREDHEIGHT != ASSIGNEDBOX.h)
|
||||||
g_pDecorationPositioner->repositionDeco(this);
|
g_pDecorationPositioner->repositionDeco(this);
|
||||||
|
|
||||||
|
@ -128,12 +130,18 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||||
color.a *= a;
|
color.a *= a;
|
||||||
g_pHyprOpenGL->renderRect(&rect, color);
|
g_pHyprOpenGL->renderRect(&rect, color);
|
||||||
|
|
||||||
// render title if necessary
|
rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth,
|
||||||
if (*PRENDERTITLES) {
|
ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2};
|
||||||
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth,
|
rect.scale(pMonitor->scale);
|
||||||
ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2};
|
|
||||||
rect.scale(pMonitor->scale);
|
|
||||||
|
|
||||||
|
if (*PGRADIENTS) {
|
||||||
|
const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||||
|
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||||
|
if (GRADIENTTEX.m_iTexID != 0)
|
||||||
|
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*PRENDERTITLES) {
|
||||||
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle);
|
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle);
|
||||||
|
|
||||||
if (!pTitleTex)
|
if (!pTitleTex)
|
||||||
|
@ -142,12 +150,6 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||||
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}))
|
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}))
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
|
||||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
|
||||||
|
|
||||||
if (*PGRADIENTS && GRADIENTTEX.m_iTexID != 0)
|
|
||||||
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
|
|
||||||
|
|
||||||
rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale;
|
rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale;
|
||||||
rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale;
|
rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale;
|
||||||
|
|
||||||
|
@ -243,7 +245,7 @@ CTitleTex::~CTitleTex() {
|
||||||
tex.destroyTexture();
|
tex.destroyTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderGradientTo(CTexture& tex, const CColor& grad) {
|
void renderGradientTo(CTexture& tex, CGradientValueData* grad) {
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor)
|
if (!g_pCompositor->m_pLastMonitor)
|
||||||
return;
|
return;
|
||||||
|
@ -261,8 +263,12 @@ void renderGradientTo(CTexture& tex, const CColor& grad) {
|
||||||
|
|
||||||
cairo_pattern_t* pattern;
|
cairo_pattern_t* pattern;
|
||||||
pattern = cairo_pattern_create_linear(0, 0, 0, bufferSize.y);
|
pattern = cairo_pattern_create_linear(0, 0, 0, bufferSize.y);
|
||||||
cairo_pattern_add_color_stop_rgba(pattern, 1, grad.r, grad.g, grad.b, grad.a);
|
|
||||||
cairo_pattern_add_color_stop_rgba(pattern, 0, grad.r, grad.g, grad.b, 0);
|
for (unsigned long i = 0; i < grad->m_vColors.size(); i++) {
|
||||||
|
cairo_pattern_add_color_stop_rgba(pattern, 1 - (double)(i + 1) / (grad->m_vColors.size() + 1), grad->m_vColors[i].r, grad->m_vColors[i].g, grad->m_vColors[i].b,
|
||||||
|
grad->m_vColors[i].a);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_rectangle(CAIRO, 0, 0, bufferSize.x, bufferSize.y);
|
cairo_rectangle(CAIRO, 0, 0, bufferSize.x, bufferSize.y);
|
||||||
cairo_set_source(CAIRO, pattern);
|
cairo_set_source(CAIRO, pattern);
|
||||||
cairo_fill(CAIRO);
|
cairo_fill(CAIRO);
|
||||||
|
@ -290,13 +296,13 @@ void renderGradientTo(CTexture& tex, const CColor& grad) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshGroupBarGradients() {
|
void refreshGroupBarGradients() {
|
||||||
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue;
|
||||||
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue;
|
static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue;
|
||||||
|
|
||||||
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data;
|
CGradientValueData* PGROUPCOLACTIVE = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data.get();
|
||||||
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data;
|
CGradientValueData* PGROUPCOLINACTIVE = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data.get();
|
||||||
static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data;
|
CGradientValueData* PGROUPCOLACTIVELOCKED = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data.get();
|
||||||
static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data;
|
CGradientValueData* PGROUPCOLINACTIVELOCKED = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data.get();
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
|
|
||||||
|
@ -310,10 +316,10 @@ void refreshGroupBarGradients() {
|
||||||
if (!*PENABLED || !*PGRADIENTS)
|
if (!*PENABLED || !*PGRADIENTS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
renderGradientTo(m_tGradientActive, ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0]);
|
renderGradientTo(m_tGradientActive, PGROUPCOLACTIVE);
|
||||||
renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0]);
|
renderGradientTo(m_tGradientInactive, PGROUPCOLINACTIVE);
|
||||||
renderGradientTo(m_tGradientLockedActive, ((CGradientValueData*)PGROUPCOLACTIVELOCKED->get())->m_vColors[0]);
|
renderGradientTo(m_tGradientLockedActive, PGROUPCOLACTIVELOCKED);
|
||||||
renderGradientTo(m_tGradientLockedInactive, ((CGradientValueData*)PGROUPCOLINACTIVELOCKED->get())->m_vColors[0]);
|
renderGradientTo(m_tGradientLockedInactive, PGROUPCOLINACTIVELOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
|
bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
diff --git a/include/meson.build b/include/meson.build
|
|
||||||
index e669800..687786b 100644
|
|
||||||
--- a/include/meson.build
|
|
||||||
+++ b/include/meson.build
|
|
||||||
@@ -1,4 +1,5 @@
|
|
||||||
-subdir('wlr')
|
|
||||||
+run_command('ln', '-sf', join_paths(meson.project_source_root(), 'include', 'wlr'), join_paths(meson.project_source_root(), 'include', 'wlroots'), check: true)
|
|
||||||
+subdir('wlroots')
|
|
||||||
|
|
||||||
exclude_files = ['meson.build', 'config.h.in', 'version.h.in']
|
|
||||||
if not features.get('drm-backend')
|
|
||||||
@@ -24,8 +25,8 @@ if not features.get('session')
|
|
||||||
exclude_files += 'backend/session.h'
|
|
||||||
endif
|
|
||||||
|
|
||||||
-install_subdir('wlr',
|
|
||||||
- install_dir: get_option('includedir'),
|
|
||||||
+install_subdir('wlroots',
|
|
||||||
+ install_dir: join_paths(get_option('includedir'), 'hyprland'),
|
|
||||||
exclude_files: exclude_files,
|
|
||||||
)
|
|
||||||
|
|
||||||
diff --git a/include/wlr/meson.build b/include/wlr/meson.build
|
|
||||||
index f7ca413..0a86d54 100644
|
|
||||||
--- a/include/wlr/meson.build
|
|
||||||
+++ b/include/wlr/meson.build
|
|
||||||
@@ -22,4 +22,4 @@ ver_h = configure_file(
|
|
||||||
configuration: version_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
-install_headers(conf_h, ver_h, subdir: 'wlr')
|
|
||||||
+install_headers(conf_h, ver_h, subdir: join_paths('hyprland', 'wlroots'))
|
|
||||||
diff --git a/meson.build b/meson.build
|
|
||||||
index 29b103a..0b6e5a4 100644
|
|
||||||
--- a/meson.build
|
|
||||||
+++ b/meson.build
|
|
||||||
@@ -15,7 +15,7 @@ project(
|
|
||||||
version_major = version.split('.')[0]
|
|
||||||
version_minor = version.split('.')[1]
|
|
||||||
assert(version_major == '0')
|
|
||||||
-soversion = version_minor.to_int() - 5
|
|
||||||
+soversion = 13032
|
|
||||||
|
|
||||||
little_endian = target_machine.endian() == 'little'
|
|
||||||
big_endian = target_machine.endian() == 'big'
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f81c3d93cd6f61b20ae784297679283438def8df
|
Subproject commit 00b869c1a96f300a8f25da95d624524895e0ddf2
|
|
@ -1,7 +0,0 @@
|
||||||
[wrap-git]
|
|
||||||
directory = wlroots
|
|
||||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
|
||||||
revision = f81c3d93cd6f61b20ae784297679283438def8df
|
|
||||||
depth = 1
|
|
||||||
|
|
||||||
diff_files = wlroots-meson-build.patch
|
|