mirror of https://github.com/hyprwm/Hyprland
Merge branch 'main' into fix/cursor-min-padding
This commit is contained in:
commit
e58589f797
|
@ -68,6 +68,11 @@ runs:
|
||||||
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`
|
||||||
cmake --install build
|
cmake --install build
|
||||||
|
|
||||||
|
- name: Get hyprutils-git
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build
|
||||||
|
|
||||||
- name: Get Xorg pacman pkgs
|
- name: Get Xorg pacman pkgs
|
||||||
shell: bash
|
shell: bash
|
||||||
if: inputs.INSTALL_XORG_PKGS == 'true'
|
if: inputs.INSTALL_XORG_PKGS == 'true'
|
||||||
|
|
|
@ -113,7 +113,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||||
wayland-server wayland-client wayland-cursor wayland-protocols
|
wayland-server wayland-client wayland-cursor wayland-protocols
|
||||||
cairo pango pangocairo pixman-1
|
cairo pango pangocairo pixman-1
|
||||||
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
||||||
hyprlang>=0.3.2 hyprcursor>=0.1.7
|
hyprlang>=0.3.2 hyprcursor>=0.1.7 hyprutils>=0.1.1
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -42,7 +42,7 @@ uninstall:
|
||||||
pluginenv:
|
pluginenv:
|
||||||
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
|
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
|
||||||
@exit 1
|
@exit 1
|
||||||
|
|
||||||
installheaders:
|
installheaders:
|
||||||
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ dwindle {
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||||
master {
|
master {
|
||||||
new_is_master = true
|
new_status = master
|
||||||
}
|
}
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||||
|
|
57
flake.lock
57
flake.lock
|
@ -13,11 +13,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717181720,
|
"lastModified": 1718368322,
|
||||||
"narHash": "sha256-yv+QZWsusu/NWjydkxixHC2g+tIJ9v+xkE2EiVpJj6g=",
|
"narHash": "sha256-VfMg3RsnRLQzbq0hFIh1dCM09b5C/F/qPFUOgU/CRi0=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprcursor",
|
"repo": "hyprcursor",
|
||||||
"rev": "9e27a2c2ceb1e0b85bd55b0afefad196056fe87c",
|
"rev": "dd3a853c8239d1c3f3f37de7d2b8ae4b4f3840df",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -53,6 +53,9 @@
|
||||||
},
|
},
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprutils": [
|
||||||
|
"hyprutils"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
|
@ -61,11 +64,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1716473782,
|
"lastModified": 1717881852,
|
||||||
"narHash": "sha256-+qLn4lsHU6iL3+HTo1gTQ1tWzet8K9h+IfVemzEQZj8=",
|
"narHash": "sha256-XeeVoKHQgfKuXoP6q90sUqKyl7EYy3ol2dVZGM+Jj94=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "87d5d984109c839482b88b4795db073eb9ed446f",
|
"rev": "ec6938c66253429192274d612912649a0cfe4d28",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -74,6 +77,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hyprutils": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1718271409,
|
||||||
|
"narHash": "sha256-8KvVqtApNt4FWTdn1TqVvw00rpqyG9UuUPA2ilPVD1U=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprutils",
|
||||||
|
"rev": "8e10e0626fb26a14b859b3811b6ed7932400c86e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprutils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hyprwayland-scanner": {
|
"hyprwayland-scanner": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
@ -84,11 +110,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717784906,
|
"lastModified": 1718119275,
|
||||||
"narHash": "sha256-YxmfxHfWed1fosaa7fC1u7XoKp1anEZU+7Lh/ojRKoM=",
|
"narHash": "sha256-nqDYXATNkyGXVmNMkT19fT4sjtSPBDS1LLOxa3Fueo4=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprwayland-scanner",
|
"repo": "hyprwayland-scanner",
|
||||||
"rev": "0f30f9eca6e404130988554accbb64d1c9ec877d",
|
"rev": "1419520d5f7f38d35e05504da5c1b38212a38525",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -99,11 +125,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717602782,
|
"lastModified": 1718318537,
|
||||||
"narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
|
"narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
|
"rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -117,6 +143,7 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprcursor": "hyprcursor",
|
"hyprcursor": "hyprcursor",
|
||||||
"hyprlang": "hyprlang",
|
"hyprlang": "hyprlang",
|
||||||
|
"hyprutils": "hyprutils",
|
||||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"systems": "systems",
|
"systems": "systems",
|
||||||
|
@ -152,11 +179,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1716290197,
|
"lastModified": 1718272114,
|
||||||
"narHash": "sha256-1u9Exrc7yx9qtES2brDh7/DDZ8w8ap1nboIOAtCgeuM=",
|
"narHash": "sha256-KsX7sAwkEFpXiwyjt0HGTnnrUU58wW1jlzj5IA/LRz8=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
"rev": "91e48d6acd8a5a611d26f925e51559ab743bc438",
|
"rev": "24be4a26f0706e456fca1b61b8c79f7486a9e86d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
url = "github:hyprwm/hyprlang";
|
url = "github:hyprwm/hyprlang";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.systems.follows = "systems";
|
inputs.systems.follows = "systems";
|
||||||
|
inputs.hyprutils.follows = "hyprutils";
|
||||||
|
};
|
||||||
|
|
||||||
|
hyprutils = {
|
||||||
|
url = "github:hyprwm/hyprutils";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
};
|
};
|
||||||
|
|
||||||
hyprwayland-scanner = {
|
hyprwayland-scanner = {
|
||||||
|
|
|
@ -5,8 +5,12 @@ project(
|
||||||
DESCRIPTION "Control utility for Hyprland"
|
DESCRIPTION "Control utility for Hyprland"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
||||||
|
|
||||||
add_executable(hyprctl "main.cpp")
|
add_executable(hyprctl "main.cpp")
|
||||||
|
|
||||||
|
target_link_libraries(hyprctl PUBLIC PkgConfig::deps)
|
||||||
|
|
||||||
# binary
|
# binary
|
||||||
install(TARGETS hyprctl)
|
install(TARGETS hyprctl)
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ commands:
|
||||||
plugin ... → Issue a plugin request
|
plugin ... → Issue a plugin request
|
||||||
reload [config-only] → Issue a reload to force reload the config. Pass
|
reload [config-only] → Issue a reload to force reload the config. Pass
|
||||||
'config-only' to disable monitor reload
|
'config-only' to disable monitor reload
|
||||||
rollinglog → Prints tail of the log
|
rollinglog → Prints tail of the log. Also supports -f/--follow
|
||||||
|
option
|
||||||
setcursor <theme> <size> → Sets the cursor theme and reloads the cursor
|
setcursor <theme> <size> → Sets the cursor theme and reloads the cursor
|
||||||
manager
|
manager
|
||||||
seterror <color> <message...> → Sets the hyprctl error string. Color has
|
seterror <color> <message...> → Sets the hyprctl error string. Color has
|
||||||
|
@ -112,7 +113,7 @@ create <backend>:
|
||||||
remove <name>:
|
remove <name>:
|
||||||
Removes virtual output. Pass the output's name, as found in
|
Removes virtual output. Pass the output's name, as found in
|
||||||
'hyprctl monitors'
|
'hyprctl monitors'
|
||||||
|
|
||||||
flags:
|
flags:
|
||||||
See 'hyprctl --help')#";
|
See 'hyprctl --help')#";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include <ctype.h>
|
#include <cctype>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <signal.h>
|
#include <csignal>
|
||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -22,8 +22,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
#include "Strings.hpp"
|
#include "Strings.hpp"
|
||||||
|
|
||||||
|
@ -98,13 +101,53 @@ std::vector<SInstanceData> instances() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int request(std::string arg, int minArgs = 0) {
|
static volatile bool sigintReceived = false;
|
||||||
|
void intHandler(int sig) {
|
||||||
|
sigintReceived = true;
|
||||||
|
std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rollingRead(const int socket) {
|
||||||
|
sigintReceived = false;
|
||||||
|
signal(SIGINT, intHandler);
|
||||||
|
|
||||||
|
constexpr size_t BUFFER_SIZE = 8192;
|
||||||
|
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||||
|
int sizeWritten = 0;
|
||||||
|
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||||
|
while (!sigintReceived) {
|
||||||
|
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
||||||
|
if (sizeWritten < 0 && errno != EAGAIN) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl;
|
||||||
|
close(socket);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeWritten == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (sizeWritten > 0) {
|
||||||
|
std::cout << std::string(buffer.data(), sizeWritten);
|
||||||
|
buffer.fill('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(100000);
|
||||||
|
}
|
||||||
|
close(socket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
auto t = timeval{.tv_sec = 0, .tv_usec = 100000};
|
||||||
|
setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval));
|
||||||
|
|
||||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||||
|
|
||||||
if (ARGS < minArgs) {
|
if (ARGS < minArgs) {
|
||||||
log("Not enough arguments, expected at least " + minArgs);
|
log(std::format("Not enough arguments in '{}', expected at least {}", arg, minArgs));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +182,9 @@ int request(std::string arg, int minArgs = 0) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needRoll)
|
||||||
|
return rollingRead(SERVERSOCKET);
|
||||||
|
|
||||||
std::string reply = "";
|
std::string reply = "";
|
||||||
char buffer[8192] = {0};
|
char buffer[8192] = {0};
|
||||||
|
|
||||||
|
@ -270,12 +316,6 @@ std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber(const std::string& str, bool allowfloat) {
|
|
||||||
if (str.empty())
|
|
||||||
return false;
|
|
||||||
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
bool parseArgs = true;
|
bool parseArgs = true;
|
||||||
|
|
||||||
|
@ -288,6 +328,7 @@ int main(int argc, char** argv) {
|
||||||
std::string fullArgs = "";
|
std::string fullArgs = "";
|
||||||
const auto ARGS = splitArgs(argc, argv);
|
const auto ARGS = splitArgs(argc, argv);
|
||||||
bool json = false;
|
bool json = false;
|
||||||
|
bool needRoll = false;
|
||||||
std::string overrideInstance = "";
|
std::string overrideInstance = "";
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
||||||
|
@ -307,6 +348,9 @@ int main(int argc, char** argv) {
|
||||||
fullArgs += "a";
|
fullArgs += "a";
|
||||||
} else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) {
|
} else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) {
|
||||||
fullArgs += "c";
|
fullArgs += "c";
|
||||||
|
} else if ((ARGS[i] == "-f" || ARGS[i] == "--follow") && !fullArgs.contains("f")) {
|
||||||
|
fullArgs += "f";
|
||||||
|
needRoll = true;
|
||||||
} else if (ARGS[i] == "--batch") {
|
} else if (ARGS[i] == "--batch") {
|
||||||
fullRequest = "--batch ";
|
fullRequest = "--batch ";
|
||||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
||||||
|
@ -366,6 +410,11 @@ int main(int argc, char** argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needRoll && !fullRequest.contains("/rollinglog")) {
|
||||||
|
log("only 'rollinglog' command supports '--follow' option");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (overrideInstance.contains("_"))
|
if (overrideInstance.contains("_"))
|
||||||
instanceSignature = overrideInstance;
|
instanceSignature = overrideInstance;
|
||||||
else if (!overrideInstance.empty()) {
|
else if (!overrideInstance.empty()) {
|
||||||
|
@ -425,6 +474,8 @@ int main(int argc, char** argv) {
|
||||||
exitStatus = request(fullRequest, 1);
|
exitStatus = request(fullRequest, 1);
|
||||||
else if (fullRequest.contains("/--help"))
|
else if (fullRequest.contains("/--help"))
|
||||||
std::cout << USAGE << std::endl;
|
std::cout << USAGE << std::endl;
|
||||||
|
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||||
|
exitStatus = request(fullRequest, 0, true);
|
||||||
else {
|
else {
|
||||||
exitStatus = request(fullRequest);
|
exitStatus = request(fullRequest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
executable('hyprctl', 'main.cpp',
|
executable('hyprctl', 'main.cpp',
|
||||||
|
dependencies: [
|
||||||
|
dependency('hyprutils', version: '>= 0.1.1'),
|
||||||
|
],
|
||||||
install: true
|
install: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
|
||||||
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1)
|
||||||
|
|
||||||
add_executable(hyprpm ${SRCFILES})
|
add_executable(hyprpm ${SRCFILES})
|
||||||
|
|
||||||
target_link_libraries(hyprpm PUBLIC PkgConfig::tomlplusplus)
|
target_link_libraries(hyprpm PUBLIC PkgConfig::deps)
|
||||||
|
|
||||||
# binary
|
# binary
|
||||||
install(TARGETS hyprpm)
|
install(TARGETS hyprpm)
|
||||||
|
|
|
@ -19,30 +19,15 @@
|
||||||
|
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
|
|
||||||
static std::string removeBeginEndSpacesTabs(std::string str) {
|
#include <hyprutils/string/String.hpp>
|
||||||
if (str.empty())
|
using namespace Hyprutils::String;
|
||||||
return str;
|
|
||||||
|
|
||||||
int countBefore = 0;
|
|
||||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
|
||||||
countBefore++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int countAfter = 0;
|
|
||||||
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
|
||||||
countAfter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string execAndGet(std::string cmd) {
|
static std::string execAndGet(std::string cmd) {
|
||||||
cmd += " 2>&1";
|
cmd += " 2>&1";
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
std::string result;
|
std::string result;
|
||||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
|
using PcloseType = int (*)(FILE*);
|
||||||
|
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd.c_str(), "r"), static_cast<PcloseType>(pclose));
|
||||||
if (!pipe)
|
if (!pipe)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
@ -374,7 +359,7 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||||
if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland"))
|
if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
verHeader = removeBeginEndSpacesTabs(PATH.substr(2)) + "/hyprland/src/version.h";
|
verHeader = trim(PATH.substr(2)) + "/hyprland/src/version.h";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,12 +427,12 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||||
|
|
||||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||||
|
|
||||||
const bool bShallow = HLVER.branch == "main" || HLVER.branch == "";
|
const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow;
|
||||||
|
|
||||||
// let us give a bit of leg-room for shallowing
|
// let us give a bit of leg-room for shallowing
|
||||||
// due to timezones, etc.
|
// due to timezones, etc.
|
||||||
const std::string SHALLOW_DATE =
|
const std::string SHALLOW_DATE =
|
||||||
removeBeginEndSpacesTabs(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||||
|
|
||||||
if (m_bVerbose && bShallow)
|
if (m_bVerbose && bShallow)
|
||||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE);
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE);
|
||||||
|
@ -495,13 +480,16 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||||
if (m_bVerbose)
|
if (m_bVerbose)
|
||||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||||
|
|
||||||
if (ret.contains("required packages were not found")) {
|
if (ret.contains("CMake Error at")) {
|
||||||
// missing deps, let the user know.
|
// missing deps, let the user know.
|
||||||
std::string missing = ret.substr(ret.find("The following required packages were not found:"));
|
std::string missing = ret.substr(ret.find("CMake Error at"));
|
||||||
missing = missing.substr(0, missing.find("Call Stack"));
|
missing = ret.substr(ret.find_first_of('\n') + 1);
|
||||||
|
missing = missing.substr(0, missing.find("-- Configuring incomplete"));
|
||||||
missing = missing.substr(0, missing.find_last_of('\n'));
|
missing = missing.substr(0, missing.find_last_of('\n'));
|
||||||
|
|
||||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n" << missing << "\n";
|
std::cerr << "\n"
|
||||||
|
<< Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n"
|
||||||
|
<< missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,8 @@ class CPluginManager {
|
||||||
|
|
||||||
bool hasDeps();
|
bool hasDeps();
|
||||||
|
|
||||||
bool m_bVerbose = false;
|
bool m_bVerbose = false;
|
||||||
|
bool m_bNoShallow = false;
|
||||||
|
|
||||||
// will delete recursively if exists!!
|
// will delete recursively if exists!!
|
||||||
bool createSafeDirectory(const std::string& path);
|
bool createSafeDirectory(const std::string& path);
|
||||||
|
|
|
@ -26,6 +26,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||||
┣ --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)
|
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||||
|
┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources
|
||||||
┗
|
┗
|
||||||
)#";
|
)#";
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> command;
|
std::vector<std::string> command;
|
||||||
bool notify = false, verbose = false, force = false;
|
bool notify = false, verbose = false, force = false, noShallow = 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("-")) {
|
||||||
|
@ -52,6 +53,8 @@ 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] == "--no-shallow" || ARGS[i] == "-s") {
|
||||||
|
noShallow = true;
|
||||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||||
force = true;
|
force = true;
|
||||||
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||||
|
@ -69,8 +72,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||||
g_pPluginManager->m_bVerbose = verbose;
|
g_pPluginManager->m_bVerbose = verbose;
|
||||||
|
g_pPluginManager->m_bNoShallow = noShallow;
|
||||||
|
|
||||||
if (command[0] == "add") {
|
if (command[0] == "add") {
|
||||||
if (command.size() < 2) {
|
if (command.size() < 2) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ src = globber.stdout().strip().split('\n')
|
||||||
|
|
||||||
executable('hyprpm', src,
|
executable('hyprpm', src,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
dependency('hyprutils', version: '>= 0.1.1'),
|
||||||
dependency('threads'),
|
dependency('threads'),
|
||||||
dependency('tomlplusplus')
|
dependency('tomlplusplus')
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
git,
|
git,
|
||||||
hyprcursor,
|
hyprcursor,
|
||||||
hyprlang,
|
hyprlang,
|
||||||
|
hyprutils,
|
||||||
hyprwayland-scanner,
|
hyprwayland-scanner,
|
||||||
jq,
|
jq,
|
||||||
libGL,
|
libGL,
|
||||||
|
@ -110,6 +111,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||||
git
|
git
|
||||||
hyprcursor.dev
|
hyprcursor.dev
|
||||||
hyprlang
|
hyprlang
|
||||||
|
hyprutils
|
||||||
libGL
|
libGL
|
||||||
libdrm
|
libdrm
|
||||||
libdatrie
|
libdatrie
|
||||||
|
|
|
@ -23,6 +23,7 @@ in {
|
||||||
# Dependencies
|
# Dependencies
|
||||||
inputs.hyprcursor.overlays.default
|
inputs.hyprcursor.overlays.default
|
||||||
inputs.hyprlang.overlays.default
|
inputs.hyprlang.overlays.default
|
||||||
|
inputs.hyprutils.overlays.default
|
||||||
inputs.hyprwayland-scanner.overlays.default
|
inputs.hyprwayland-scanner.overlays.default
|
||||||
self.overlays.xwayland
|
self.overlays.xwayland
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"version": "0.41.0"
|
"version": "0.41.1"
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
#include <helpers/SdDaemon.hpp> // for SdNotify
|
#include <helpers/SdDaemon.hpp> // for SdNotify
|
||||||
#endif
|
#endif
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include "helpers/VarList.hpp"
|
#include "helpers/varlist/VarList.hpp"
|
||||||
#include "protocols/FractionalScale.hpp"
|
#include "protocols/FractionalScale.hpp"
|
||||||
#include "protocols/PointerConstraints.hpp"
|
#include "protocols/PointerConstraints.hpp"
|
||||||
#include "protocols/LayerShell.hpp"
|
#include "protocols/LayerShell.hpp"
|
||||||
|
@ -24,6 +24,9 @@
|
||||||
#include "desktop/LayerSurface.hpp"
|
#include "desktop/LayerSurface.hpp"
|
||||||
#include "xwayland/XWayland.hpp"
|
#include "xwayland/XWayland.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -348,6 +351,8 @@ void CCompositor::cleanup() {
|
||||||
g_pXWaylandManager.reset();
|
g_pXWaylandManager.reset();
|
||||||
g_pPointerManager.reset();
|
g_pPointerManager.reset();
|
||||||
g_pSeatManager.reset();
|
g_pSeatManager.reset();
|
||||||
|
g_pHyprCtl.reset();
|
||||||
|
g_pEventLoopManager.reset();
|
||||||
|
|
||||||
if (m_sWLRRenderer)
|
if (m_sWLRRenderer)
|
||||||
wlr_renderer_destroy(m_sWLRRenderer);
|
wlr_renderer_destroy(m_sWLRRenderer);
|
||||||
|
@ -361,6 +366,7 @@ void CCompositor::cleanup() {
|
||||||
if (m_critSigSource)
|
if (m_critSigSource)
|
||||||
wl_event_source_remove(m_critSigSource);
|
wl_event_source_remove(m_critSigSource);
|
||||||
|
|
||||||
|
wl_event_loop_destroy(m_sWLEventLoop);
|
||||||
wl_display_terminate(m_sWLDisplay);
|
wl_display_terminate(m_sWLDisplay);
|
||||||
m_sWLDisplay = nullptr;
|
m_sWLDisplay = nullptr;
|
||||||
|
|
||||||
|
@ -1056,7 +1062,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, st
|
||||||
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
|
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos());
|
auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true);
|
||||||
|
|
||||||
if (surf) {
|
if (surf) {
|
||||||
if (surf->current.input.empty())
|
if (surf->current.input.empty())
|
||||||
|
@ -1108,6 +1114,17 @@ bool CCompositor::isWorkspaceVisible(PHLWORKSPACE w) {
|
||||||
return valid(w) && w->m_bVisible;
|
return valid(w) && w->m_bVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) {
|
||||||
|
if (!valid(w))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto PMONITOR = getMonitorFromID(w->m_iMonitorID);
|
||||||
|
if (PMONITOR->activeSpecialWorkspace)
|
||||||
|
return PMONITOR->activeSpecialWorkspace->m_iID == w->m_iID;
|
||||||
|
|
||||||
|
return PMONITOR->activeWorkspace->m_iID == w->m_iID;
|
||||||
|
}
|
||||||
|
|
||||||
PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) {
|
PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) {
|
||||||
for (auto& w : m_vWorkspaces) {
|
for (auto& w : m_vWorkspaces) {
|
||||||
if (w->m_iID == id && !w->inert())
|
if (w->m_iID == id && !w->inert())
|
||||||
|
@ -1347,6 +1364,10 @@ void CCompositor::addToFadingOutSafe(PHLLS pLS) {
|
||||||
m_vSurfacesFadingOut.emplace_back(pLS);
|
m_vSurfacesFadingOut.emplace_back(pLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCompositor::removeFromFadingOutSafe(PHLLS ls) {
|
||||||
|
std::erase(m_vSurfacesFadingOut, ls);
|
||||||
|
}
|
||||||
|
|
||||||
void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
|
void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
|
||||||
const auto FOUND = std::find_if(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), [&](PHLWINDOWREF& other) { return other.lock() == pWindow; });
|
const auto FOUND = std::find_if(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), [&](PHLWINDOWREF& other) { return other.lock() == pWindow; });
|
||||||
|
|
||||||
|
@ -2084,9 +2105,11 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
|
||||||
if (POLDMON) {
|
if (POLDMON) {
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||||
updateFullscreenFadeOnWorkspace(POLDMON->activeWorkspace);
|
updateFullscreenFadeOnWorkspace(POLDMON->activeWorkspace);
|
||||||
|
updateSuspendedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFullscreenFadeOnWorkspace(pWorkspace);
|
updateFullscreenFadeOnWorkspace(pWorkspace);
|
||||||
|
updateSuspendedStates();
|
||||||
|
|
||||||
// event
|
// event
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName});
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName});
|
||||||
|
|
|
@ -118,6 +118,7 @@ class CCompositor {
|
||||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||||
|
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||||
|
@ -155,6 +156,7 @@ class CCompositor {
|
||||||
PHLWINDOW getX11Parent(PHLWINDOW);
|
PHLWINDOW getX11Parent(PHLWINDOW);
|
||||||
void scheduleFrameForMonitor(CMonitor*);
|
void scheduleFrameForMonitor(CMonitor*);
|
||||||
void addToFadingOutSafe(PHLLS);
|
void addToFadingOutSafe(PHLLS);
|
||||||
|
void removeFromFadingOutSafe(PHLLS);
|
||||||
void addToFadingOutSafe(PHLWINDOW);
|
void addToFadingOutSafe(PHLWINDOW);
|
||||||
PHLWINDOW getWindowByRegex(const std::string&);
|
PHLWINDOW getWindowByRegex(const std::string&);
|
||||||
void warpCursorTo(const Vector2D&, bool force = false);
|
void warpCursorTo(const Vector2D&, bool force = false);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/VarList.hpp"
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
enum eConfigValueDataTypes {
|
enum eConfigValueDataTypes {
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||||
#include "config/ConfigDataValues.hpp"
|
#include "config/ConfigDataValues.hpp"
|
||||||
#include "helpers/VarList.hpp"
|
#include "helpers/varlist/VarList.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -20,7 +22,8 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
extern "C" char** environ;
|
extern "C" char** environ;
|
||||||
|
|
||||||
|
@ -428,8 +431,9 @@ CConfigManager::CConfigManager() {
|
||||||
|
|
||||||
m_pConfig->addConfigValue("master:special_scale_factor", {1.f});
|
m_pConfig->addConfigValue("master:special_scale_factor", {1.f});
|
||||||
m_pConfig->addConfigValue("master:mfact", {0.55f});
|
m_pConfig->addConfigValue("master:mfact", {0.55f});
|
||||||
m_pConfig->addConfigValue("master:new_is_master", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("master:new_status", {"slave"});
|
||||||
m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("master:new_on_active", {"none"});
|
||||||
m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("master:no_gaps_when_only", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("master:orientation", {"left"});
|
m_pConfig->addConfigValue("master:orientation", {"left"});
|
||||||
|
@ -519,10 +523,13 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2});
|
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24});
|
||||||
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:default_monitor", {STRVAL_EMPTY});
|
m_pConfig->addConfigValue("cursor:default_monitor", {STRVAL_EMPTY});
|
||||||
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
||||||
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
||||||
|
@ -1955,15 +1962,16 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
// bind[fl]=SUPER,G,exec,dmenu_run <args>
|
// bind[fl]=SUPER,G,exec,dmenu_run <args>
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
bool release = false;
|
bool release = false;
|
||||||
bool repeat = false;
|
bool repeat = false;
|
||||||
bool mouse = false;
|
bool mouse = false;
|
||||||
bool nonConsuming = false;
|
bool nonConsuming = false;
|
||||||
bool transparent = false;
|
bool transparent = false;
|
||||||
bool ignoreMods = false;
|
bool ignoreMods = false;
|
||||||
bool multiKey = false;
|
bool multiKey = false;
|
||||||
const auto BINDARGS = command.substr(4);
|
bool hasDescription = false;
|
||||||
|
const auto BINDARGS = command.substr(4);
|
||||||
|
|
||||||
for (auto& arg : BINDARGS) {
|
for (auto& arg : BINDARGS) {
|
||||||
if (arg == 'l') {
|
if (arg == 'l') {
|
||||||
|
@ -1982,6 +1990,8 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
ignoreMods = true;
|
ignoreMods = true;
|
||||||
} else if (arg == 's') {
|
} else if (arg == 's') {
|
||||||
multiKey = true;
|
multiKey = true;
|
||||||
|
} else if (arg == 'd') {
|
||||||
|
hasDescription = true;
|
||||||
} else {
|
} else {
|
||||||
return "bind: invalid flag";
|
return "bind: invalid flag";
|
||||||
}
|
}
|
||||||
|
@ -1993,11 +2003,13 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
if (mouse && (repeat || release || locked))
|
if (mouse && (repeat || release || locked))
|
||||||
return "flag m is exclusive";
|
return "flag m is exclusive";
|
||||||
|
|
||||||
const auto ARGS = CVarList(value, 4);
|
const int numbArgs = hasDescription ? 5 : 4;
|
||||||
|
const auto ARGS = CVarList(value, numbArgs);
|
||||||
|
|
||||||
|
const int DESCR_OFFSET = hasDescription ? 1 : 0;
|
||||||
if ((ARGS.size() < 3 && !mouse) || (ARGS.size() < 3 && mouse))
|
if ((ARGS.size() < 3 && !mouse) || (ARGS.size() < 3 && mouse))
|
||||||
return "bind: too few args";
|
return "bind: too few args";
|
||||||
else if ((ARGS.size() > 4 && !mouse) || (ARGS.size() > 3 && mouse))
|
else if ((ARGS.size() > (size_t)4 + DESCR_OFFSET && !mouse) || (ARGS.size() > (size_t)3 + DESCR_OFFSET && mouse))
|
||||||
return "bind: too many args";
|
return "bind: too many args";
|
||||||
|
|
||||||
std::set<xkb_keysym_t> KEYSYMS;
|
std::set<xkb_keysym_t> KEYSYMS;
|
||||||
|
@ -2016,9 +2028,11 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
|
|
||||||
const auto KEY = multiKey ? "" : ARGS[1];
|
const auto KEY = multiKey ? "" : ARGS[1];
|
||||||
|
|
||||||
auto HANDLER = ARGS[2];
|
const auto DESCRIPTION = hasDescription ? ARGS[2] : "";
|
||||||
|
|
||||||
const auto COMMAND = mouse ? HANDLER : ARGS[3];
|
auto HANDLER = ARGS[2 + DESCR_OFFSET];
|
||||||
|
|
||||||
|
const auto COMMAND = mouse ? HANDLER : ARGS[3 + DESCR_OFFSET];
|
||||||
|
|
||||||
if (mouse)
|
if (mouse)
|
||||||
HANDLER = "mouse";
|
HANDLER = "mouse";
|
||||||
|
@ -2046,8 +2060,8 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
return "Invalid catchall, catchall keybinds are only allowed in submaps.";
|
return "Invalid catchall, catchall keybinds are only allowed in submaps.";
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, release,
|
g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION,
|
||||||
repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey});
|
release, repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -2087,8 +2101,8 @@ bool layerRuleValid(const std::string& RULE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
||||||
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(',')));
|
const auto RULE = trim(value.substr(0, value.find_first_of(',')));
|
||||||
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(',') + 1));
|
const auto VALUE = trim(value.substr(value.find_first_of(',') + 1));
|
||||||
|
|
||||||
// check rule and value
|
// check rule and value
|
||||||
if (RULE.empty() || VALUE.empty())
|
if (RULE.empty() || VALUE.empty())
|
||||||
|
@ -2114,8 +2128,8 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleLayerRule(const std::string& command, const std::string& value) {
|
std::optional<std::string> CConfigManager::handleLayerRule(const std::string& command, const std::string& value) {
|
||||||
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(',')));
|
const auto RULE = trim(value.substr(0, value.find_first_of(',')));
|
||||||
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(',') + 1));
|
const auto VALUE = trim(value.substr(value.find_first_of(',') + 1));
|
||||||
|
|
||||||
// check rule and value
|
// check rule and value
|
||||||
if (RULE.empty() || VALUE.empty())
|
if (RULE.empty() || VALUE.empty())
|
||||||
|
@ -2142,7 +2156,7 @@ std::optional<std::string> CConfigManager::handleLayerRule(const std::string& co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
|
std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
|
||||||
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(',')));
|
const auto RULE = trim(value.substr(0, value.find_first_of(',')));
|
||||||
const auto VALUE = value.substr(value.find_first_of(',') + 1);
|
const auto VALUE = value.substr(value.find_first_of(',') + 1);
|
||||||
|
|
||||||
if (!windowRuleValid(RULE) && RULE != "unset") {
|
if (!windowRuleValid(RULE) && RULE != "unset") {
|
||||||
|
@ -2219,7 +2233,7 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
|
||||||
|
|
||||||
result = result.substr(0, min - pos);
|
result = result.substr(0, min - pos);
|
||||||
|
|
||||||
result = removeBeginEndSpacesTabs(result);
|
result = trim(result);
|
||||||
|
|
||||||
if (!result.empty() && result.back() == ',')
|
if (!result.empty() && result.back() == ',')
|
||||||
result.pop_back();
|
result.pop_back();
|
||||||
|
@ -2341,7 +2355,7 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
std::optional<std::string> CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
||||||
if (value.starts_with("remove,")) {
|
if (value.starts_with("remove,")) {
|
||||||
const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7));
|
const auto TOREMOVE = trim(value.substr(7));
|
||||||
if (std::erase_if(m_dBlurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; }))
|
if (std::erase_if(m_dBlurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; }))
|
||||||
updateBlurredLS(TOREMOVE, false);
|
updateBlurredLS(TOREMOVE, false);
|
||||||
return {};
|
return {};
|
||||||
|
@ -2358,7 +2372,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
|
||||||
const auto FIRST_DELIM = value.find_first_of(',');
|
const auto FIRST_DELIM = value.find_first_of(',');
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
auto first_ident = removeBeginEndSpacesTabs(value.substr(0, FIRST_DELIM));
|
auto first_ident = trim(value.substr(0, FIRST_DELIM));
|
||||||
int id = getWorkspaceIDFromString(first_ident, name);
|
int id = getWorkspaceIDFromString(first_ident, name);
|
||||||
|
|
||||||
auto rules = value.substr(FIRST_DELIM + 1);
|
auto rules = value.substr(FIRST_DELIM + 1);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../helpers/Monitor.hpp"
|
#include "../helpers/Monitor.hpp"
|
||||||
#include "../helpers/VarList.hpp"
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
#include "../desktop/Window.hpp"
|
#include "../desktop/Window.hpp"
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ dwindle {
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||||
master {
|
master {
|
||||||
new_is_master = true
|
new_status = master
|
||||||
}
|
}
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "HyprCtl.hpp"
|
#include "HyprCtl.hpp"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -16,6 +17,9 @@
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
#include "../config/ConfigDataValues.hpp"
|
#include "../config/ConfigDataValues.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include "../managers/CursorManager.hpp"
|
#include "../managers/CursorManager.hpp"
|
||||||
|
@ -24,7 +28,9 @@
|
||||||
#include "../devices/IKeyboard.hpp"
|
#include "../devices/IKeyboard.hpp"
|
||||||
#include "../devices/ITouch.hpp"
|
#include "../devices/ITouch.hpp"
|
||||||
#include "../devices/Tablet.hpp"
|
#include "../devices/Tablet.hpp"
|
||||||
|
#include "debug/RollingLogFollow.hpp"
|
||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
|
#include "helpers/MiscFunctions.hpp"
|
||||||
|
|
||||||
static void trimTrailingComma(std::string& str) {
|
static void trimTrailingComma(std::string& str) {
|
||||||
if (!str.empty() && str.back() == ',')
|
if (!str.empty() && str.back() == ',')
|
||||||
|
@ -789,9 +795,11 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
ret += "e";
|
ret += "e";
|
||||||
if (kb.nonConsuming)
|
if (kb.nonConsuming)
|
||||||
ret += "n";
|
ret += "n";
|
||||||
|
if (kb.hasDescription)
|
||||||
|
ret += "d";
|
||||||
|
|
||||||
ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap, kb.key,
|
ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb.modmask, kb.submap,
|
||||||
kb.keycode, kb.catchAll, kb.handler, kb.arg);
|
kb.key, kb.keycode, kb.catchAll, kb.description, kb.handler, kb.arg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// json
|
// json
|
||||||
|
@ -805,17 +813,19 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
"release": {},
|
"release": {},
|
||||||
"repeat": {},
|
"repeat": {},
|
||||||
"non_consuming": {},
|
"non_consuming": {},
|
||||||
|
"has_description": {},
|
||||||
"modmask": {},
|
"modmask": {},
|
||||||
"submap": "{}",
|
"submap": "{}",
|
||||||
"key": "{}",
|
"key": "{}",
|
||||||
"keycode": {},
|
"keycode": {},
|
||||||
"catch_all": {},
|
"catch_all": {},
|
||||||
|
"description": "{}",
|
||||||
"dispatcher": "{}",
|
"dispatcher": "{}",
|
||||||
"arg": "{}"
|
"arg": "{}"
|
||||||
}},)#",
|
}},)#",
|
||||||
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false",
|
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false",
|
||||||
kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false", escapeJSONStrings(kb.handler),
|
kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false",
|
||||||
escapeJSONStrings(kb.arg));
|
escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg));
|
||||||
}
|
}
|
||||||
trimTrailingComma(ret);
|
trimTrailingComma(ret);
|
||||||
ret += "]";
|
ret += "]";
|
||||||
|
@ -826,7 +836,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
|
auto commitMsg = trim(GIT_COMMIT_MESSAGE);
|
||||||
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
||||||
|
|
||||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||||
|
@ -1051,7 +1061,7 @@ std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
|
||||||
request = "";
|
request = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
curitem = removeBeginEndSpacesTabs(curitem);
|
curitem = trim(curitem);
|
||||||
};
|
};
|
||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
|
@ -1305,7 +1315,7 @@ std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request)
|
||||||
request = "";
|
request = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
curitem = removeBeginEndSpacesTabs(curitem);
|
curitem = trim(curitem);
|
||||||
};
|
};
|
||||||
|
|
||||||
nextItem();
|
nextItem();
|
||||||
|
@ -1723,6 +1733,46 @@ std::string CHyprCtl::makeDynamicCall(const std::string& input) {
|
||||||
return getReply(input);
|
return getReply(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool successWrite(int fd, const std::string& data, bool needLog = true) {
|
||||||
|
if (write(fd, data.c_str(), data.length()) > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (errno == EAGAIN)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (needLog)
|
||||||
|
Debug::log(ERR, "Couldn't write to socket. Error: " + std::string(strerror(errno)));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runWritingDebugLogThread(const int conn) {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn);
|
||||||
|
//will be finished, when reading side close connection
|
||||||
|
std::thread([conn]() {
|
||||||
|
while (Debug::RollingLogFollow::Get().IsRunning()) {
|
||||||
|
if (Debug::RollingLogFollow::Get().isEmpty(conn)) {
|
||||||
|
std::this_thread::sleep_for(1000ms);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto line = Debug::RollingLogFollow::Get().GetLog(conn);
|
||||||
|
if (!successWrite(conn, line))
|
||||||
|
// We cannot write, when connection is closed. So thread will successfully exit by itself
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(100ms);
|
||||||
|
}
|
||||||
|
close(conn);
|
||||||
|
Debug::RollingLogFollow::Get().StopFor(conn);
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFollowUpRollingLogRequest(const std::string& request) {
|
||||||
|
return request.contains("rollinglog") && request.contains("f");
|
||||||
|
}
|
||||||
|
|
||||||
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1766,9 +1816,15 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||||
reply = "Err: " + std::string(e.what());
|
reply = "Err: " + std::string(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
successWrite(ACCEPTEDCONNECTION, reply);
|
||||||
|
|
||||||
close(ACCEPTEDCONNECTION);
|
if (isFollowUpRollingLogRequest(request)) {
|
||||||
|
Debug::log(LOG, "Followup rollinglog request received. Starting thread to write to socket.");
|
||||||
|
Debug::RollingLogFollow::Get().StartFor(ACCEPTEDCONNECTION);
|
||||||
|
runWritingDebugLogThread(ACCEPTEDCONNECTION);
|
||||||
|
Debug::log(LOG, Debug::RollingLogFollow::Get().DebugInfo());
|
||||||
|
} else
|
||||||
|
close(ACCEPTEDCONNECTION);
|
||||||
|
|
||||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||||
g_pConfigManager->ensureMonitorStatus();
|
g_pConfigManager->ensureMonitorStatus();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Log.hpp"
|
#include "Log.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
#include "RollingLogFollow.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -73,6 +74,9 @@ void Debug::log(LogLevel level, std::string str) {
|
||||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||||
|
|
||||||
|
if (RollingLogFollow::Get().IsRunning())
|
||||||
|
RollingLogFollow::Get().AddLog(str);
|
||||||
|
|
||||||
if (!disableLogs || !**disableLogs) {
|
if (!disableLogs || !**disableLogs) {
|
||||||
// log to a file
|
// log to a file
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
struct RollingLogFollow {
|
||||||
|
std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
|
||||||
|
std::shared_mutex m;
|
||||||
|
bool running = false;
|
||||||
|
static constexpr size_t ROLLING_LOG_FOLLOW_TOO_BIG = 8192;
|
||||||
|
|
||||||
|
// Returns true if the queue is empty for the given socket
|
||||||
|
bool isEmpty(int socket) {
|
||||||
|
std::shared_lock<std::shared_mutex> r(m);
|
||||||
|
return socketToRollingLogFollowQueue[socket].empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugInfo() {
|
||||||
|
std::shared_lock<std::shared_mutex> r(m);
|
||||||
|
return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetLog(int socket) {
|
||||||
|
std::unique_lock<std::shared_mutex> w(m);
|
||||||
|
|
||||||
|
const std::string ret = socketToRollingLogFollowQueue[socket];
|
||||||
|
socketToRollingLogFollowQueue[socket] = "";
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddLog(std::string log) {
|
||||||
|
std::unique_lock<std::shared_mutex> w(m);
|
||||||
|
running = true;
|
||||||
|
std::vector<int> to_erase;
|
||||||
|
for (const auto& p : socketToRollingLogFollowQueue)
|
||||||
|
socketToRollingLogFollowQueue[p.first] += log + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRunning() {
|
||||||
|
std::shared_lock<std::shared_mutex> r(m);
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopFor(int socket) {
|
||||||
|
std::unique_lock<std::shared_mutex> w(m);
|
||||||
|
socketToRollingLogFollowQueue.erase(socket);
|
||||||
|
if (socketToRollingLogFollowQueue.empty())
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartFor(int socket) {
|
||||||
|
std::unique_lock<std::shared_mutex> w(m);
|
||||||
|
socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket);
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RollingLogFollow& Get() {
|
||||||
|
static RollingLogFollow instance;
|
||||||
|
static std::mutex gm;
|
||||||
|
std::lock_guard<std::mutex> lock(gm);
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -116,8 +116,12 @@ void CLayerSurface::onDestroy() {
|
||||||
void CLayerSurface::onMap() {
|
void CLayerSurface::onMap() {
|
||||||
Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface);
|
Debug::log(LOG, "LayerSurface {:x} mapped", (uintptr_t)layerSurface);
|
||||||
|
|
||||||
mapped = true;
|
mapped = true;
|
||||||
keyboardExclusive = layerSurface->current.interactivity;
|
interactivity = layerSurface->current.interactivity;
|
||||||
|
|
||||||
|
// this layer might be re-mapped.
|
||||||
|
fadingOut = false;
|
||||||
|
g_pCompositor->removeFromFadingOutSafe(self.lock());
|
||||||
|
|
||||||
// fix if it changed its mon
|
// fix if it changed its mon
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||||
|
@ -133,12 +137,15 @@ void CLayerSurface::onMap() {
|
||||||
|
|
||||||
surface->resource()->enter(PMONITOR->self.lock());
|
surface->resource()->enter(PMONITOR->self.lock());
|
||||||
|
|
||||||
if (layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||||
|
|
||||||
|
if (ISEXCLUSIVE)
|
||||||
g_pInputManager->m_dExclusiveLSes.push_back(self);
|
g_pInputManager->m_dExclusiveLSes.push_back(self);
|
||||||
|
|
||||||
const bool GRABSFOCUS = layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
const bool GRABSFOCUS = ISEXCLUSIVE ||
|
||||||
// don't focus if constrained
|
(layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||||
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained());
|
// don't focus if constrained
|
||||||
|
(g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()));
|
||||||
|
|
||||||
if (GRABSFOCUS) {
|
if (GRABSFOCUS) {
|
||||||
// TODO: use the new superb really very cool grab
|
// TODO: use the new superb really very cool grab
|
||||||
|
@ -177,9 +184,6 @@ void CLayerSurface::onUnmap() {
|
||||||
|
|
||||||
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
||||||
|
|
||||||
if (!g_pInputManager->m_dExclusiveLSes.empty())
|
|
||||||
g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->surface->resource());
|
|
||||||
|
|
||||||
if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) {
|
if (!g_pCompositor->getMonitorFromID(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.");
|
||||||
|
|
||||||
|
@ -204,39 +208,12 @@ void CLayerSurface::onUnmap() {
|
||||||
|
|
||||||
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||||
|
|
||||||
surface.reset();
|
|
||||||
|
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// refocus if needed
|
// refocus if needed
|
||||||
if (WASLASTFOCUS) {
|
if (WASLASTFOCUS)
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
g_pInputManager->refocusLastWindow(PMONITOR);
|
||||||
|
|
||||||
Vector2D surfaceCoords;
|
|
||||||
PHLLS pFoundLayerSurface;
|
|
||||||
SP<CWLSurfaceResource> foundSurface = nullptr;
|
|
||||||
|
|
||||||
g_pCompositor->m_pLastFocus.reset();
|
|
||||||
|
|
||||||
// find LS-es to focus
|
|
||||||
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
|
|
||||||
&surfaceCoords, &pFoundLayerSurface);
|
|
||||||
|
|
||||||
if (!foundSurface)
|
|
||||||
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
|
|
||||||
&surfaceCoords, &pFoundLayerSurface);
|
|
||||||
|
|
||||||
if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisible(g_pCompositor->m_pLastWindow->m_pWorkspace)) {
|
|
||||||
// if there isn't any, focus the last window
|
|
||||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
|
||||||
g_pCompositor->focusWindow(nullptr);
|
|
||||||
g_pCompositor->focusWindow(PLASTWINDOW);
|
|
||||||
} else {
|
|
||||||
// otherwise, full refocus
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
@ -246,12 +223,25 @@ void CLayerSurface::onUnmap() {
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
g_pInputManager->sendMotionEventsToFocused();
|
g_pInputManager->sendMotionEventsToFocused();
|
||||||
|
|
||||||
|
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLayerSurface::onCommit() {
|
void CLayerSurface::onCommit() {
|
||||||
if (!layerSurface)
|
if (!layerSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!mapped) {
|
||||||
|
// we're re-mapping if this is the case
|
||||||
|
if (layerSurface->surface && !layerSurface->surface->current.buffer) {
|
||||||
|
fadingOut = false;
|
||||||
|
geometry = {};
|
||||||
|
g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||||
|
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
|
@ -311,18 +301,35 @@ void CLayerSurface::onCommit() {
|
||||||
realSize.setValueAndWarp(geometry.size());
|
realSize.setValueAndWarp(geometry.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained
|
if (mapped) {
|
||||||
&& !keyboardExclusive && mapped) {
|
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
|
||||||
g_pCompositor->focusSurface(surface->resource());
|
const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||||
|
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||||
|
|
||||||
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y);
|
if (!WASEXCLUSIVE && ISEXCLUSIVE)
|
||||||
g_pSeatManager->setPointerFocus(surface->resource(), LOCAL);
|
g_pInputManager->m_dExclusiveLSes.push_back(self);
|
||||||
g_pInputManager->m_bEmptyFocusCursorSet = false;
|
else if (WASEXCLUSIVE && !ISEXCLUSIVE)
|
||||||
} else if (!layerSurface->current.interactivity && (g_pSeatManager->mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) {
|
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
|
||||||
g_pInputManager->refocus();
|
|
||||||
|
// if the surface was focused and interactive but now isn't, refocus
|
||||||
|
if (WASLASTFOCUS && !layerSurface->current.interactivity) {
|
||||||
|
// moveMouseUnified won't focus non interactive layers but it won't unfocus them either,
|
||||||
|
// so unfocus the surface here.
|
||||||
|
g_pCompositor->focusSurface(nullptr);
|
||||||
|
g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID));
|
||||||
|
} else if (!WASEXCLUSIVE && ISEXCLUSIVE) {
|
||||||
|
// if now exclusive and not previously
|
||||||
|
g_pSeatManager->setGrab(nullptr);
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
g_pCompositor->focusSurface(surface->resource());
|
||||||
|
|
||||||
|
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y);
|
||||||
|
g_pSeatManager->setPointerFocus(surface->resource(), LOCAL);
|
||||||
|
g_pInputManager->m_bEmptyFocusCursorSet = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboardExclusive = layerSurface->current.interactivity;
|
interactivity = layerSurface->current.interactivity;
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(surface->resource(), position.x, position.y);
|
g_pHyprRenderer->damageSurface(surface->resource(), position.x, position.y);
|
||||||
|
|
||||||
|
@ -512,4 +519,4 @@ int CLayerSurface::popupsCount() {
|
||||||
int no = -1; // we have one dummy
|
int no = -1; // we have one dummy
|
||||||
popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no);
|
popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no);
|
||||||
return no;
|
return no;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,40 +34,41 @@ class CLayerSurface {
|
||||||
WP<CLayerShellResource> layerSurface;
|
WP<CLayerShellResource> layerSurface;
|
||||||
wl_list link;
|
wl_list link;
|
||||||
|
|
||||||
bool keyboardExclusive = false;
|
// the header providing the enum type cannot be imported here
|
||||||
|
int interactivity = 0;
|
||||||
|
|
||||||
SP<CWLSurface> surface;
|
SP<CWLSurface> surface;
|
||||||
|
|
||||||
bool mapped = false;
|
bool mapped = false;
|
||||||
uint32_t layer = 0;
|
uint32_t layer = 0;
|
||||||
|
|
||||||
int monitorID = -1;
|
int monitorID = -1;
|
||||||
|
|
||||||
bool fadingOut = false;
|
bool fadingOut = false;
|
||||||
bool readyToDelete = false;
|
bool readyToDelete = false;
|
||||||
bool noProcess = false;
|
bool noProcess = false;
|
||||||
bool noAnimations = false;
|
bool noAnimations = false;
|
||||||
|
|
||||||
bool forceBlur = false;
|
bool forceBlur = false;
|
||||||
bool forceBlurPopups = false;
|
bool forceBlurPopups = false;
|
||||||
int xray = -1;
|
int xray = -1;
|
||||||
bool ignoreAlpha = false;
|
bool ignoreAlpha = false;
|
||||||
float ignoreAlphaValue = 0.f;
|
float ignoreAlphaValue = 0.f;
|
||||||
bool dimAround = false;
|
bool dimAround = false;
|
||||||
|
|
||||||
std::optional<std::string> animationStyle;
|
std::optional<std::string> animationStyle;
|
||||||
|
|
||||||
PHLLSREF self;
|
PHLLSREF self;
|
||||||
|
|
||||||
CBox geometry = {0, 0, 0, 0};
|
CBox geometry = {0, 0, 0, 0};
|
||||||
Vector2D position;
|
Vector2D position;
|
||||||
std::string szNamespace = "";
|
std::string szNamespace = "";
|
||||||
std::unique_ptr<CPopup> popupHead;
|
std::unique_ptr<CPopup> popupHead;
|
||||||
|
|
||||||
void onDestroy();
|
void onDestroy();
|
||||||
void onMap();
|
void onMap();
|
||||||
void onUnmap();
|
void onUnmap();
|
||||||
void onCommit();
|
void onCommit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct {
|
struct {
|
||||||
|
@ -83,4 +84,4 @@ class CLayerSurface {
|
||||||
bool operator==(const CLayerSurface& rhs) const {
|
bool operator==(const CLayerSurface& rhs) const {
|
||||||
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Subsurface.hpp"
|
#include "Subsurface.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CXDGPopupResource;
|
class CXDGPopupResource;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
#include "../xwayland/XWayland.hpp"
|
#include "../xwayland/XWayland.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||||
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
||||||
|
|
||||||
|
@ -687,7 +690,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||||
CGradientValueData activeBorderGradient = {};
|
CGradientValueData activeBorderGradient = {};
|
||||||
CGradientValueData inactiveBorderGradient = {};
|
CGradientValueData inactiveBorderGradient = {};
|
||||||
bool active = true;
|
bool active = true;
|
||||||
CVarList colorsAndAngles = CVarList(removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
CVarList colorsAndAngles = CVarList(trim(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
||||||
|
|
||||||
// Basic form has only two colors, everything else can be parsed as a gradient
|
// Basic form has only two colors, everything else can be parsed as a gradient
|
||||||
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
||||||
|
@ -1537,3 +1540,58 @@ void CWindow::warpCursor() {
|
||||||
else
|
else
|
||||||
g_pCompositor->warpCursorTo(middle());
|
g_pCompositor->warpCursorTo(middle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHLWINDOW CWindow::getSwallower() {
|
||||||
|
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
||||||
|
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
||||||
|
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
||||||
|
|
||||||
|
if (!*PSWALLOW || (*PSWALLOWREGEX).empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// check parent
|
||||||
|
std::vector<PHLWINDOW> candidates;
|
||||||
|
pid_t currentPid = getPID();
|
||||||
|
// walk up the tree until we find someone, 25 iterations max.
|
||||||
|
for (size_t i = 0; i < 25; ++i) {
|
||||||
|
currentPid = getPPIDof(currentPid);
|
||||||
|
|
||||||
|
if (!currentPid)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (!w->m_bIsMapped || w->isHidden())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (w->getPID() == currentPid)
|
||||||
|
candidates.push_back(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*PSWALLOWREGEX).empty())
|
||||||
|
std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); });
|
||||||
|
|
||||||
|
if (candidates.size() <= 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!(*PSWALLOWEXREGEX).empty())
|
||||||
|
std::erase_if(candidates, [&](const auto& other) { return std::regex_match(other->m_szTitle, std::regex(*PSWALLOWEXREGEX)); });
|
||||||
|
|
||||||
|
if (candidates.size() <= 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (candidates.size() == 1)
|
||||||
|
return candidates.at(0);
|
||||||
|
|
||||||
|
// walk up the focus history and find the last focused
|
||||||
|
for (auto& w : g_pCompositor->m_vWindowFocusHistory) {
|
||||||
|
if (!w)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (std::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end())
|
||||||
|
return w.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if none are found (??) then just return the first one
|
||||||
|
return candidates.at(0);
|
||||||
|
}
|
||||||
|
|
|
@ -450,6 +450,7 @@ class CWindow {
|
||||||
std::string fetchTitle();
|
std::string fetchTitle();
|
||||||
std::string fetchClass();
|
std::string fetchClass();
|
||||||
void warpCursor();
|
void warpCursor();
|
||||||
|
PHLWINDOW getSwallower();
|
||||||
|
|
||||||
// listeners
|
// listeners
|
||||||
void onAck(uint32_t serial);
|
void onAck(uint32_t serial);
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
||||||
workspace->init(workspace);
|
workspace->init(workspace);
|
||||||
|
@ -219,7 +222,7 @@ std::string CWorkspace::getConfigName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
||||||
auto selector = removeBeginEndSpacesTabs(selector_);
|
auto selector = trim(selector_);
|
||||||
|
|
||||||
if (selector.empty())
|
if (selector.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "IKeyboard.hpp"
|
#include "IKeyboard.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/VarList.hpp"
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
#include "../managers/input/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
|
|
||||||
uint32_t IKeyboard::getCapabilities() {
|
uint32_t IKeyboard::getCapabilities() {
|
||||||
|
|
|
@ -188,6 +188,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
|
|
||||||
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
||||||
|
|
||||||
|
if (pMonitor->output->idle_frame)
|
||||||
|
wl_event_source_remove(pMonitor->output->idle_frame);
|
||||||
|
|
||||||
pMonitor->onDisconnect(true);
|
pMonitor->onDisconnect(true);
|
||||||
|
|
||||||
pMonitor->output = nullptr;
|
pMonitor->output = nullptr;
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
#include "../xwayland/XSurface.hpp"
|
#include "../xwayland/XSurface.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
// ------------------------------------------------------------ //
|
// ------------------------------------------------------------ //
|
||||||
// __ _______ _ _ _____ ______ _______ //
|
// __ _______ _ _ _____ ______ _______ //
|
||||||
// \ \ / /_ _| \ | | __ \ / __ \ \ / / ____| //
|
// \ \ / /_ _| \ | | __ \ / __ \ \ / / ____| //
|
||||||
|
@ -41,7 +44,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
||||||
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
||||||
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
||||||
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
|
||||||
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:new_window_takes_over_fullscreen");
|
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:new_window_takes_over_fullscreen");
|
||||||
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||||
|
|
||||||
|
@ -140,7 +142,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
for (auto& r : PWINDOW->m_vMatchedRules) {
|
for (auto& r : PWINDOW->m_vMatchedRules) {
|
||||||
if (r.szRule.starts_with("monitor")) {
|
if (r.szRule.starts_with("monitor")) {
|
||||||
try {
|
try {
|
||||||
const auto MONITORSTR = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find(' ')));
|
const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' ')));
|
||||||
|
|
||||||
if (MONITORSTR == "unset") {
|
if (MONITORSTR == "unset") {
|
||||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||||
|
@ -235,7 +237,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// `group` is a shorthand of `group set`
|
// `group` is a shorthand of `group set`
|
||||||
if (removeBeginEndSpacesTabs(r.szRule) == "group") {
|
if (trim(r.szRule) == "group") {
|
||||||
PWINDOW->m_eGroupRules |= GROUP_SET;
|
PWINDOW->m_eGroupRules |= GROUP_SET;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -524,71 +526,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
// verify swallowing
|
// verify swallowing
|
||||||
if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
||||||
// don't swallow ourselves
|
const auto SWALLOWER = PWINDOW->getSwallower();
|
||||||
std::regex rgx(*PSWALLOWREGEX);
|
|
||||||
if (!std::regex_match(PWINDOW->m_szClass, rgx)) {
|
|
||||||
// check parent
|
|
||||||
int ppid = getPPIDof(PWINDOW->getPID());
|
|
||||||
|
|
||||||
int curppid = 0;
|
if (SWALLOWER) {
|
||||||
|
// swallow
|
||||||
|
PWINDOW->m_pSwallowed = SWALLOWER;
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER);
|
||||||
curppid = getPPIDof(ppid);
|
|
||||||
|
|
||||||
if (curppid < 10) {
|
SWALLOWER->setHidden(true);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppid = curppid;
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
|
||||||
}
|
|
||||||
|
|
||||||
if (ppid) {
|
|
||||||
// get window by pid
|
|
||||||
std::vector<PHLWINDOW> found;
|
|
||||||
PHLWINDOW finalFound;
|
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
|
||||||
if (!w->m_bIsMapped || w->isHidden())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (w->getPID() == ppid) {
|
|
||||||
found.push_back(w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found.size() > 1) {
|
|
||||||
for (auto& w : found) {
|
|
||||||
// try get the focus, otherwise we'll ignore to avoid swallowing incorrect windows
|
|
||||||
if (w == PFOCUSEDWINDOWPREV) {
|
|
||||||
finalFound = w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (found.size() == 1) {
|
|
||||||
finalFound = found[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finalFound) {
|
|
||||||
bool valid = std::regex_match(PWINDOW->m_szClass, rgx);
|
|
||||||
|
|
||||||
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
|
||||||
std::regex exc(*PSWALLOWEXREGEX);
|
|
||||||
|
|
||||||
valid = valid && !std::regex_match(PWINDOW->m_szTitle, exc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it's the window we want & not exempt from getting swallowed
|
|
||||||
if (valid) {
|
|
||||||
// swallow
|
|
||||||
PWINDOW->m_pSwallowed = finalFound;
|
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(finalFound);
|
|
||||||
|
|
||||||
finalFound->setHidden(true);
|
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +748,7 @@ void Events::listener_commitWindow(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(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.buffer) {
|
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.buffer) {
|
||||||
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->current.bufferDamage};
|
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()};
|
||||||
|
|
||||||
if (!damageBox.empty()) {
|
if (!damageBox.empty()) {
|
||||||
if (PMONITOR->tearingState.busy) {
|
if (PMONITOR->tearingState.busy) {
|
||||||
|
|
|
@ -11,18 +11,26 @@
|
||||||
*/
|
*/
|
||||||
inline const std::vector<SPixelFormat> GLES3_FORMATS = {
|
inline const std::vector<SPixelFormat> GLES3_FORMATS = {
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_ARGB8888,
|
.drmFormat = DRM_FORMAT_ARGB8888,
|
||||||
.flipRB = true,
|
.flipRB = true,
|
||||||
.glFormat = GL_RGBA,
|
#ifndef GLES2
|
||||||
|
.glFormat = GL_RGBA,
|
||||||
|
#else
|
||||||
|
.glFormat = GL_BGRA_EXT,
|
||||||
|
#endif
|
||||||
.glType = GL_UNSIGNED_BYTE,
|
.glType = GL_UNSIGNED_BYTE,
|
||||||
.withAlpha = true,
|
.withAlpha = true,
|
||||||
.alphaStripped = DRM_FORMAT_XRGB8888,
|
.alphaStripped = DRM_FORMAT_XRGB8888,
|
||||||
.bytesPerBlock = 4,
|
.bytesPerBlock = 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_XRGB8888,
|
.drmFormat = DRM_FORMAT_XRGB8888,
|
||||||
.flipRB = true,
|
.flipRB = true,
|
||||||
.glFormat = GL_RGBA,
|
#ifndef GLES2
|
||||||
|
.glFormat = GL_RGBA,
|
||||||
|
#else
|
||||||
|
.glFormat = GL_BGRA_EXT,
|
||||||
|
#endif
|
||||||
.glType = GL_UNSIGNED_BYTE,
|
.glType = GL_UNSIGNED_BYTE,
|
||||||
.withAlpha = false,
|
.withAlpha = false,
|
||||||
.alphaStripped = DRM_FORMAT_XRGB8888,
|
.alphaStripped = DRM_FORMAT_XRGB8888,
|
||||||
|
@ -93,70 +101,100 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
|
||||||
.bytesPerBlock = 2,
|
.bytesPerBlock = 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_XBGR2101010,
|
.drmFormat = DRM_FORMAT_XBGR2101010,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
#ifndef GLES2
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||||
|
#else
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||||
|
#endif
|
||||||
.withAlpha = false,
|
.withAlpha = false,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
||||||
.bytesPerBlock = 4,
|
.bytesPerBlock = 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_ABGR2101010,
|
.drmFormat = DRM_FORMAT_ABGR2101010,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
#ifndef GLES2
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||||
|
#else
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||||
|
#endif
|
||||||
.withAlpha = true,
|
.withAlpha = true,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
||||||
.bytesPerBlock = 4,
|
.bytesPerBlock = 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_XRGB2101010,
|
.drmFormat = DRM_FORMAT_XRGB2101010,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
#ifndef GLES2
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||||
|
#else
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||||
|
#endif
|
||||||
.withAlpha = false,
|
.withAlpha = false,
|
||||||
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
||||||
.bytesPerBlock = 4,
|
.bytesPerBlock = 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_ARGB2101010,
|
.drmFormat = DRM_FORMAT_ARGB2101010,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
#ifndef GLES2
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||||
|
#else
|
||||||
|
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||||
|
#endif
|
||||||
.withAlpha = true,
|
.withAlpha = true,
|
||||||
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
||||||
.bytesPerBlock = 4,
|
.bytesPerBlock = 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_XBGR16161616F,
|
.drmFormat = DRM_FORMAT_XBGR16161616F,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_HALF_FLOAT,
|
#ifndef GLES2
|
||||||
|
.glType = GL_HALF_FLOAT,
|
||||||
|
#else
|
||||||
|
.glType = GL_HALF_FLOAT_OES,
|
||||||
|
#endif
|
||||||
.withAlpha = false,
|
.withAlpha = false,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
||||||
.bytesPerBlock = 8,
|
.bytesPerBlock = 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_ABGR16161616F,
|
.drmFormat = DRM_FORMAT_ABGR16161616F,
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA,
|
||||||
.glType = GL_HALF_FLOAT,
|
#ifndef GLES2
|
||||||
|
.glType = GL_HALF_FLOAT,
|
||||||
|
#else
|
||||||
|
.glType = GL_HALF_FLOAT_OES,
|
||||||
|
#endif
|
||||||
.withAlpha = true,
|
.withAlpha = true,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
||||||
.bytesPerBlock = 8,
|
.bytesPerBlock = 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_XBGR16161616,
|
.drmFormat = DRM_FORMAT_XBGR16161616,
|
||||||
.glInternalFormat = GL_RGBA16UI,
|
#ifndef GLES2
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA16UI,
|
||||||
.glType = GL_UNSIGNED_SHORT,
|
#else
|
||||||
.withAlpha = false,
|
.glFormat = GL_RGBA16_EXT,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
#endif
|
||||||
.bytesPerBlock = 8,
|
.glType = GL_UNSIGNED_SHORT,
|
||||||
|
.withAlpha = false,
|
||||||
|
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
||||||
|
.bytesPerBlock = 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_ABGR16161616,
|
.drmFormat = DRM_FORMAT_ABGR16161616,
|
||||||
.glInternalFormat = GL_RGBA16UI,
|
#ifndef GLES2
|
||||||
.glFormat = GL_RGBA,
|
.glFormat = GL_RGBA16UI,
|
||||||
.glType = GL_UNSIGNED_SHORT,
|
#else
|
||||||
.withAlpha = true,
|
.glFormat = GL_RGBA16_EXT,
|
||||||
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
#endif
|
||||||
.bytesPerBlock = 8,
|
.glType = GL_UNSIGNED_SHORT,
|
||||||
|
.withAlpha = true,
|
||||||
|
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
||||||
|
.bytesPerBlock = 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.drmFormat = DRM_FORMAT_YVYU,
|
.drmFormat = DRM_FORMAT_YVYU,
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#ifdef HAS_EXECINFO
|
#ifdef HAS_EXECINFO
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
@ -195,25 +197,6 @@ std::string escapeJSONStrings(const std::string& str) {
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string removeBeginEndSpacesTabs(std::string str) {
|
|
||||||
if (str.empty())
|
|
||||||
return str;
|
|
||||||
|
|
||||||
int countBefore = 0;
|
|
||||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
|
||||||
countBefore++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int countAfter = 0;
|
|
||||||
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
|
||||||
countAfter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<float> getPlusMinusKeywordResult(std::string source, float relative) {
|
std::optional<float> getPlusMinusKeywordResult(std::string source, float relative) {
|
||||||
try {
|
try {
|
||||||
return relative + stof(source);
|
return relative + stof(source);
|
||||||
|
@ -223,31 +206,6 @@ std::optional<float> getPlusMinusKeywordResult(std::string source, float relativ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber(const std::string& str, bool allowfloat) {
|
|
||||||
|
|
||||||
std::string copy = str;
|
|
||||||
if (*copy.begin() == '-')
|
|
||||||
copy = copy.substr(1);
|
|
||||||
|
|
||||||
if (copy.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool point = !allowfloat;
|
|
||||||
for (auto& c : copy) {
|
|
||||||
if (c == '.') {
|
|
||||||
if (point)
|
|
||||||
return false;
|
|
||||||
point = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::isdigit(c))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isDirection(const std::string& arg) {
|
bool isDirection(const std::string& arg) {
|
||||||
return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b";
|
return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b";
|
||||||
}
|
}
|
||||||
|
@ -579,7 +537,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||||
|
|
||||||
std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) {
|
std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) {
|
||||||
|
|
||||||
std::string cmd = removeBeginEndSpacesTabs(dirtyCmd);
|
std::string cmd = trim(dirtyCmd);
|
||||||
|
|
||||||
if (!cmd.empty()) {
|
if (!cmd.empty()) {
|
||||||
std::string rules;
|
std::string rules;
|
||||||
|
@ -622,9 +580,10 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
|
||||||
|
|
||||||
// Execute a shell command and get the output
|
// Execute a shell command and get the output
|
||||||
std::string execAndGet(const char* cmd) {
|
std::string execAndGet(const char* cmd) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
std::string result;
|
std::string result;
|
||||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
using PcloseType = int (*)(FILE*);
|
||||||
|
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd, "r"), static_cast<PcloseType>(pclose));
|
||||||
if (!pipe) {
|
if (!pipe) {
|
||||||
Debug::log(ERR, "execAndGet: failed in pipe");
|
Debug::log(ERR, "execAndGet: failed in pipe");
|
||||||
return "";
|
return "";
|
||||||
|
@ -748,7 +707,7 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||||
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
||||||
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
|
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
|
||||||
|
|
||||||
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
|
if (trim(VALUEWITHOUTFUNC).length() != 8) {
|
||||||
Debug::log(WARN, "invalid length {} for rgba", VALUEWITHOUTFUNC.length());
|
Debug::log(WARN, "invalid length {} for rgba", VALUEWITHOUTFUNC.length());
|
||||||
throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)");
|
throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)");
|
||||||
}
|
}
|
||||||
|
@ -760,7 +719,7 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||||
} else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) {
|
} else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) {
|
||||||
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
|
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
|
||||||
|
|
||||||
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {
|
if (trim(VALUEWITHOUTFUNC).length() != 6) {
|
||||||
Debug::log(WARN, "invalid length {} for rgb", VALUEWITHOUTFUNC.length());
|
Debug::log(WARN, "invalid length {} for rgb", VALUEWITHOUTFUNC.length());
|
||||||
throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)");
|
throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)");
|
||||||
}
|
}
|
||||||
|
@ -822,15 +781,6 @@ double normalizeAngleRad(double ang) {
|
||||||
return ang;
|
return ang;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace) {
|
|
||||||
size_t pos = 0;
|
|
||||||
while ((pos = subject.find(search, pos)) != std::string::npos) {
|
|
||||||
subject.replace(pos, search.length(), replace);
|
|
||||||
pos += replace.length();
|
|
||||||
}
|
|
||||||
return subject;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SCallstackFrameInfo> getBacktrace() {
|
std::vector<SCallstackFrameInfo> getBacktrace() {
|
||||||
std::vector<SCallstackFrameInfo> callstack;
|
std::vector<SCallstackFrameInfo> callstack;
|
||||||
|
|
||||||
|
@ -865,7 +815,8 @@ bool envEnabled(const std::string& env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, std::string> openExclusiveShm() {
|
std::pair<int, std::string> openExclusiveShm() {
|
||||||
std::string name = g_pTokenManager->getRandomUUID();
|
// Only absolute paths can be shared across different shm_open() calls
|
||||||
|
std::string name = "/" + g_pTokenManager->getRandomUUID();
|
||||||
|
|
||||||
for (size_t i = 0; i < 69; ++i) {
|
for (size_t i = 0; i < 69; ++i) {
|
||||||
int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||||
|
|
|
@ -17,8 +17,6 @@ std::string absolutePath(const std::string&, const std::str
|
||||||
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*);
|
void removeWLSignal(wl_listener*);
|
||||||
std::string escapeJSONStrings(const std::string& str);
|
std::string escapeJSONStrings(const std::string& str);
|
||||||
std::string removeBeginEndSpacesTabs(std::string);
|
|
||||||
bool isNumber(const std::string&, bool allowfloat = false);
|
|
||||||
bool isDirection(const std::string&);
|
bool isDirection(const std::string&);
|
||||||
bool isDirection(const char&);
|
bool isDirection(const char&);
|
||||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||||
|
@ -32,7 +30,6 @@ Vector2D configStringToVector2D(const std::string&);
|
||||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||||
double normalizeAngleRad(double ang);
|
double normalizeAngleRad(double ang);
|
||||||
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
|
|
||||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||||
void throwError(const std::string& err);
|
void throwError(const std::string& err);
|
||||||
bool envEnabled(const std::string& env);
|
bool envEnabled(const std::string& env);
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "../devices/ITouch.hpp"
|
#include "../devices/ITouch.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/PresentationTime.hpp"
|
#include "../protocols/PresentationTime.hpp"
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
int ratHandler(void* data) {
|
int ratHandler(void* data) {
|
||||||
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
||||||
|
@ -71,8 +73,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
std::erase(szDescription, ',');
|
std::erase(szDescription, ',');
|
||||||
|
|
||||||
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
||||||
szShortDescription =
|
szShortDescription = trim(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : ""));
|
||||||
removeBeginEndSpacesTabs(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : ""));
|
|
||||||
std::erase(szShortDescription, ',');
|
std::erase(szShortDescription, ',');
|
||||||
|
|
||||||
if (!wlr_backend_is_drm(output->backend))
|
if (!wlr_backend_is_drm(output->backend))
|
||||||
|
@ -361,6 +362,24 @@ void CMonitor::addDamage(const CBox* box) {
|
||||||
g_pCompositor->scheduleFrameForMonitor(this);
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
|
||||||
|
static auto PNOBREAK = CConfigValue<Hyprlang::INT>("cursor:no_break_fs_vrr");
|
||||||
|
static auto PMINRR = CConfigValue<Hyprlang::INT>("cursor:min_refresh_rate");
|
||||||
|
|
||||||
|
// skip scheduling extra frames for fullsreen apps with vrr
|
||||||
|
bool shouldSkip = *PNOBREAK && output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow &&
|
||||||
|
activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
|
|
||||||
|
// keep requested minimum refresh rate
|
||||||
|
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) {
|
||||||
|
// damage whole screen because some previous cursor box damages were skipped
|
||||||
|
wlr_damage_ring_add_whole(&damage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shouldSkip;
|
||||||
|
}
|
||||||
|
|
||||||
bool CMonitor::isMirror() {
|
bool CMonitor::isMirror() {
|
||||||
return pMirrorOf != nullptr;
|
return pMirrorOf != nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,7 @@ class CMonitor {
|
||||||
void addDamage(const pixman_region32_t* rg);
|
void addDamage(const pixman_region32_t* rg);
|
||||||
void addDamage(const CRegion* rg);
|
void addDamage(const CRegion* rg);
|
||||||
void addDamage(const CBox* box);
|
void addDamage(const CBox* box);
|
||||||
|
bool shouldSkipScheduleFrameOnMouseEvent();
|
||||||
void setMirror(const std::string&);
|
void setMirror(const std::string&);
|
||||||
bool isMirror();
|
bool isMirror();
|
||||||
bool matchesStaticSelector(const std::string& selector) const;
|
bool matchesStaticSelector(const std::string& selector) const;
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
#include "MiscFunctions.hpp"
|
|
||||||
#include "VarList.hpp"
|
|
||||||
#include <ranges>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) {
|
|
||||||
if (in.empty())
|
|
||||||
m_vArgs.emplace_back("");
|
|
||||||
|
|
||||||
std::string args{in};
|
|
||||||
size_t idx = 0;
|
|
||||||
size_t pos = 0;
|
|
||||||
std::ranges::replace_if(
|
|
||||||
args, [&](const char& c) { return delim == 's' ? std::isspace(c) : c == delim; }, 0);
|
|
||||||
|
|
||||||
for (const auto& s : args | std::views::split(0)) {
|
|
||||||
if (removeEmpty && s.empty())
|
|
||||||
continue;
|
|
||||||
if (++idx == lastArgNo) {
|
|
||||||
m_vArgs.emplace_back(removeBeginEndSpacesTabs(in.substr(pos)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos += s.size() + 1;
|
|
||||||
m_vArgs.emplace_back(removeBeginEndSpacesTabs(std::string_view{s}.data()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CVarList::join(const std::string& joiner, size_t from, size_t to) const {
|
|
||||||
size_t last = to == 0 ? size() : to;
|
|
||||||
|
|
||||||
std::string rolling;
|
|
||||||
for (size_t i = from; i < last; ++i) {
|
|
||||||
rolling += m_vArgs[i] + (i + 1 < last ? joiner : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
return rolling;
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <functional>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include "../macros.hpp"
|
|
||||||
|
|
||||||
class CVarList {
|
|
||||||
public:
|
|
||||||
/** Split string into arg list
|
|
||||||
@param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args
|
|
||||||
@param delim if delimiter is 's', use std::isspace
|
|
||||||
@param removeEmpty remove empty args from argv
|
|
||||||
*/
|
|
||||||
CVarList(const std::string& in, const size_t maxSize = 0, const char delim = ',', const bool removeEmpty = false);
|
|
||||||
|
|
||||||
~CVarList() = default;
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return m_vArgs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const;
|
|
||||||
|
|
||||||
void map(std::function<void(std::string&)> func) {
|
|
||||||
for (auto& s : m_vArgs)
|
|
||||||
func(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const std::string arg) {
|
|
||||||
m_vArgs.emplace_back(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator[](const size_t& idx) const {
|
|
||||||
if (idx >= m_vArgs.size())
|
|
||||||
return "";
|
|
||||||
return m_vArgs[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
// for range-based loops
|
|
||||||
std::vector<std::string>::iterator begin() {
|
|
||||||
return m_vArgs.begin();
|
|
||||||
}
|
|
||||||
std::vector<std::string>::const_iterator begin() const {
|
|
||||||
return m_vArgs.begin();
|
|
||||||
}
|
|
||||||
std::vector<std::string>::iterator end() {
|
|
||||||
return m_vArgs.end();
|
|
||||||
}
|
|
||||||
std::vector<std::string>::const_iterator end() const {
|
|
||||||
return m_vArgs.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains(const std::string& el) {
|
|
||||||
for (auto& a : m_vArgs) {
|
|
||||||
if (a == el)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::string> m_vArgs;
|
|
||||||
};
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "../desktop/Popup.hpp"
|
#include "../desktop/Popup.hpp"
|
||||||
#include "AnimatedVariable.hpp"
|
#include "AnimatedVariable.hpp"
|
||||||
#include "../desktop/WLSurface.hpp"
|
#include "../desktop/WLSurface.hpp"
|
||||||
#include "signal/Listener.hpp"
|
#include "signal/Signal.hpp"
|
||||||
#include "Region.hpp"
|
#include "Region.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hyprutils/memory/WeakPtr.hpp>
|
||||||
|
|
||||||
|
using namespace Hyprutils::Memory;
|
||||||
|
|
||||||
|
#define SP Hyprutils::Memory::CSharedPointer
|
||||||
|
#define WP Hyprutils::Memory::CWeakPointer
|
||||||
|
#define UP std::unique_ptr
|
|
@ -1,302 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <typeindex>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#define SP CSharedPointer
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is a custom impl of std::shared_ptr.
|
|
||||||
It is not thread-safe like the STL one,
|
|
||||||
but Hyprland is single-threaded anyways.
|
|
||||||
|
|
||||||
It differs a bit from how the STL one works,
|
|
||||||
namely in the fact that it keeps the T* inside the
|
|
||||||
control block, and that you can still make a CWeakPtr
|
|
||||||
or deref an existing one inside the destructor.
|
|
||||||
*/
|
|
||||||
namespace CSharedPointer_ {
|
|
||||||
|
|
||||||
class impl_base {
|
|
||||||
public:
|
|
||||||
virtual ~impl_base(){};
|
|
||||||
|
|
||||||
virtual void inc() noexcept = 0;
|
|
||||||
virtual void dec() noexcept = 0;
|
|
||||||
virtual void incWeak() noexcept = 0;
|
|
||||||
virtual void decWeak() noexcept = 0;
|
|
||||||
virtual unsigned int ref() noexcept = 0;
|
|
||||||
virtual unsigned int wref() noexcept = 0;
|
|
||||||
virtual void destroy() noexcept = 0;
|
|
||||||
virtual bool destroying() noexcept = 0;
|
|
||||||
virtual bool dataNonNull() noexcept = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class impl : public impl_base {
|
|
||||||
public:
|
|
||||||
impl(T* data) noexcept : _data(data) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strong refcount */
|
|
||||||
unsigned int _ref = 0;
|
|
||||||
/* weak refcount */
|
|
||||||
unsigned int _weak = 0;
|
|
||||||
|
|
||||||
T* _data = nullptr;
|
|
||||||
|
|
||||||
friend void swap(impl*& a, impl*& b) {
|
|
||||||
impl* tmp = a;
|
|
||||||
a = b;
|
|
||||||
b = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if the destructor was called,
|
|
||||||
creating shared_ptrs is no longer valid */
|
|
||||||
bool _destroying = false;
|
|
||||||
|
|
||||||
void _destroy() {
|
|
||||||
if (!_data || _destroying)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// first, we destroy the data, but keep the pointer.
|
|
||||||
// this way, weak pointers will still be able to
|
|
||||||
// reference and use, but no longer create shared ones.
|
|
||||||
_destroying = true;
|
|
||||||
__deleter(_data);
|
|
||||||
// now, we can reset the data and call it a day.
|
|
||||||
_data = nullptr;
|
|
||||||
_destroying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::default_delete<T> __deleter{};
|
|
||||||
|
|
||||||
//
|
|
||||||
virtual void inc() noexcept {
|
|
||||||
_ref++;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dec() noexcept {
|
|
||||||
_ref--;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void incWeak() noexcept {
|
|
||||||
_weak++;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void decWeak() noexcept {
|
|
||||||
_weak--;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual unsigned int ref() noexcept {
|
|
||||||
return _ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual unsigned int wref() noexcept {
|
|
||||||
return _weak;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void destroy() noexcept {
|
|
||||||
_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool destroying() noexcept {
|
|
||||||
return _destroying;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool dataNonNull() noexcept {
|
|
||||||
return _data;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~impl() {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class CSharedPointer {
|
|
||||||
public:
|
|
||||||
template <typename X>
|
|
||||||
using validHierarchy = typename std::enable_if<std::is_assignable<CSharedPointer<T>&, X>::value, CSharedPointer&>::type;
|
|
||||||
template <typename X>
|
|
||||||
using isConstructible = typename std::enable_if<std::is_constructible<T&, X&>::value>::type;
|
|
||||||
|
|
||||||
/* creates a new shared pointer managing a resource
|
|
||||||
avoid calling. Could duplicate ownership. Prefer makeShared */
|
|
||||||
explicit CSharedPointer(T* object) noexcept {
|
|
||||||
impl_ = new CSharedPointer_::impl<T>(object);
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* creates a shared pointer from a reference */
|
|
||||||
template <typename U, typename = isConstructible<U>>
|
|
||||||
CSharedPointer(const CSharedPointer<U>& ref) noexcept {
|
|
||||||
impl_ = ref.impl_;
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer(const CSharedPointer& ref) noexcept {
|
|
||||||
impl_ = ref.impl_;
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename = isConstructible<U>>
|
|
||||||
CSharedPointer(CSharedPointer<U>&& ref) noexcept {
|
|
||||||
std::swap(impl_, ref.impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer(CSharedPointer&& ref) noexcept {
|
|
||||||
std::swap(impl_, ref.impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allows weakPointer to create from an impl */
|
|
||||||
CSharedPointer(CSharedPointer_::impl_base* implementation) noexcept {
|
|
||||||
impl_ = implementation;
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* creates an empty shared pointer with no implementation */
|
|
||||||
CSharedPointer() noexcept {
|
|
||||||
; // empty
|
|
||||||
}
|
|
||||||
|
|
||||||
/* creates an empty shared pointer with no implementation */
|
|
||||||
CSharedPointer(std::nullptr_t) noexcept {
|
|
||||||
; // empty
|
|
||||||
}
|
|
||||||
|
|
||||||
~CSharedPointer() {
|
|
||||||
// we do not decrement here,
|
|
||||||
// because we want to preserve the pointer
|
|
||||||
// in case this is the last owner.
|
|
||||||
if (impl_ && impl_->ref() == 1)
|
|
||||||
destroyImpl();
|
|
||||||
else
|
|
||||||
decrement();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
validHierarchy<const CSharedPointer<U>&> operator=(const CSharedPointer<U>& rhs) {
|
|
||||||
if (impl_ == rhs.impl_)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
decrement();
|
|
||||||
impl_ = rhs.impl_;
|
|
||||||
increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer& operator=(const CSharedPointer& rhs) {
|
|
||||||
if (impl_ == rhs.impl_)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
decrement();
|
|
||||||
impl_ = rhs.impl_;
|
|
||||||
increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
validHierarchy<const CSharedPointer<U>&> operator=(CSharedPointer<U>&& rhs) {
|
|
||||||
std::swap(impl_, rhs.impl_);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer& operator=(CSharedPointer&& rhs) {
|
|
||||||
std::swap(impl_, rhs.impl_);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const {
|
|
||||||
return impl_ && impl_->dataNonNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const CSharedPointer& rhs) const {
|
|
||||||
return impl_ == rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const CSharedPointer& lhs, const CSharedPointer& rhs) const {
|
|
||||||
return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const CSharedPointer& rhs) const {
|
|
||||||
return (uintptr_t)impl_ < (uintptr_t)rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const {
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator*() const {
|
|
||||||
return *get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
decrement();
|
|
||||||
impl_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* get() const {
|
|
||||||
return (T*)(impl_ ? static_cast<CSharedPointer_::impl<T>*>(impl_)->_data : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int strongRef() const {
|
|
||||||
return impl_ ? impl_->ref() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer_::impl_base* impl_ = nullptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*
|
|
||||||
no-op if there is no impl_
|
|
||||||
may delete the stored object if ref == 0
|
|
||||||
may delete and reset impl_ if ref == 0 and weak == 0
|
|
||||||
*/
|
|
||||||
void decrement() {
|
|
||||||
if (!impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_->dec();
|
|
||||||
|
|
||||||
// if ref == 0, we can destroy impl
|
|
||||||
if (impl_->ref() == 0)
|
|
||||||
destroyImpl();
|
|
||||||
}
|
|
||||||
/* no-op if there is no impl_ */
|
|
||||||
void increment() {
|
|
||||||
if (!impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_->inc();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* destroy the pointed-to object
|
|
||||||
if able, will also destroy impl */
|
|
||||||
void destroyImpl() {
|
|
||||||
// destroy the impl contents
|
|
||||||
impl_->destroy();
|
|
||||||
|
|
||||||
// check for weak refs, if zero, we can also delete impl_
|
|
||||||
if (impl_->wref() == 0) {
|
|
||||||
delete impl_;
|
|
||||||
impl_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename U, typename... Args>
|
|
||||||
static CSharedPointer<U> makeShared(Args&&... args) {
|
|
||||||
return CSharedPointer<U>(new U(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct std::hash<CSharedPointer<T>> {
|
|
||||||
std::size_t operator()(const CSharedPointer<T>& p) const noexcept {
|
|
||||||
return std::hash<void*>{}(p.impl_);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,190 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "SharedPtr.hpp"
|
|
||||||
|
|
||||||
#define WP CWeakPointer
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is a Hyprland implementation of std::weak_ptr.
|
|
||||||
|
|
||||||
See SharedPtr.hpp for more info on how it's different.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class CWeakPointer {
|
|
||||||
public:
|
|
||||||
template <typename X>
|
|
||||||
using validHierarchy = typename std::enable_if<std::is_assignable<CWeakPointer<T>&, X>::value, CWeakPointer&>::type;
|
|
||||||
template <typename X>
|
|
||||||
using isConstructible = typename std::enable_if<std::is_constructible<T&, X&>::value>::type;
|
|
||||||
|
|
||||||
/* create a weak ptr from a reference */
|
|
||||||
template <typename U, typename = isConstructible<U>>
|
|
||||||
CWeakPointer(const CSharedPointer<U>& ref) noexcept {
|
|
||||||
if (!ref.impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_ = ref.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create a weak ptr from another weak ptr */
|
|
||||||
template <typename U, typename = isConstructible<U>>
|
|
||||||
CWeakPointer(const CWeakPointer<U>& ref) noexcept {
|
|
||||||
if (!ref.impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_ = ref.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
}
|
|
||||||
|
|
||||||
CWeakPointer(const CWeakPointer& ref) noexcept {
|
|
||||||
if (!ref.impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_ = ref.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename = isConstructible<U>>
|
|
||||||
CWeakPointer(CWeakPointer<U>&& ref) noexcept {
|
|
||||||
std::swap(impl_, ref.impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
CWeakPointer(CWeakPointer&& ref) noexcept {
|
|
||||||
std::swap(impl_, ref.impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create a weak ptr from another weak ptr with assignment */
|
|
||||||
template <typename U>
|
|
||||||
validHierarchy<const CWeakPointer<U>&> operator=(const CWeakPointer<U>& rhs) {
|
|
||||||
if (impl_ == rhs.impl_)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
decrementWeak();
|
|
||||||
impl_ = rhs.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CWeakPointer<T>& operator=(const CWeakPointer& rhs) {
|
|
||||||
if (impl_ == rhs.impl_)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
decrementWeak();
|
|
||||||
impl_ = rhs.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create a weak ptr from a shared ptr with assignment */
|
|
||||||
template <typename U>
|
|
||||||
validHierarchy<const CWeakPointer<U>&> operator=(const CSharedPointer<U>& rhs) {
|
|
||||||
if ((uintptr_t)impl_ == (uintptr_t)rhs.impl_)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
decrementWeak();
|
|
||||||
impl_ = rhs.impl_;
|
|
||||||
incrementWeak();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create an empty weak ptr */
|
|
||||||
CWeakPointer() {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CWeakPointer() {
|
|
||||||
decrementWeak();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expired MAY return true even if the pointer is still stored.
|
|
||||||
the situation would be e.g. self-weak pointer in a destructor.
|
|
||||||
for pointer validity, use valid() */
|
|
||||||
bool expired() const {
|
|
||||||
return !impl_ || !impl_->dataNonNull() || impl_->destroying();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this means the pointed-to object is not yet deleted and can still be
|
|
||||||
referenced, but it might be in the process of being deleted.
|
|
||||||
check !expired() if you want to check whether it's valid and
|
|
||||||
assignable to a SP. */
|
|
||||||
bool valid() const {
|
|
||||||
return impl_ && impl_->dataNonNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
decrementWeak();
|
|
||||||
impl_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer<T> lock() const {
|
|
||||||
if (!impl_ || !impl_->dataNonNull() || impl_->destroying())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return CSharedPointer<T>(impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this returns valid() */
|
|
||||||
operator bool() const {
|
|
||||||
return valid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const CWeakPointer<T>& rhs) const {
|
|
||||||
return impl_ == rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const CSharedPointer<T>& rhs) const {
|
|
||||||
return impl_ == rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const CWeakPointer& lhs, const CWeakPointer& rhs) const {
|
|
||||||
return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const CWeakPointer& rhs) const {
|
|
||||||
return (uintptr_t)impl_ < (uintptr_t)rhs.impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* get() const {
|
|
||||||
return (T*)(impl_ ? static_cast<CSharedPointer_::impl<T>*>(impl_)->_data : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const {
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSharedPointer_::impl_base* impl_ = nullptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/* no-op if there is no impl_ */
|
|
||||||
void decrementWeak() {
|
|
||||||
if (!impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_->decWeak();
|
|
||||||
|
|
||||||
// we need to check for ->destroying,
|
|
||||||
// because otherwise we could destroy here
|
|
||||||
// and have a shared_ptr destroy the same thing
|
|
||||||
// later (in situations where we have a weak_ptr to self)
|
|
||||||
if (impl_->wref() == 0 && impl_->ref() == 0 && !impl_->destroying()) {
|
|
||||||
delete impl_;
|
|
||||||
impl_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* no-op if there is no impl_ */
|
|
||||||
void incrementWeak() {
|
|
||||||
if (!impl_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
impl_->incWeak();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct std::hash<CWeakPointer<T>> {
|
|
||||||
std::size_t operator()(const CWeakPointer<T>& p) const noexcept {
|
|
||||||
return std::hash<void*>{}(p.impl_);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,21 +0,0 @@
|
||||||
#include "Listener.hpp"
|
|
||||||
#include "Signal.hpp"
|
|
||||||
|
|
||||||
CSignalListener::CSignalListener(std::function<void(std::any)> handler) : m_fHandler(handler) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSignalListener::emit(std::any data) {
|
|
||||||
if (!m_fHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_fHandler(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
CStaticSignalListener::CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner) : m_pOwner(owner), m_fHandler(handler) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStaticSignalListener::emit(std::any data) {
|
|
||||||
m_fHandler(m_pOwner, data);
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <any>
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
#include "../../macros.hpp"
|
|
||||||
|
|
||||||
class CSignal;
|
|
||||||
|
|
||||||
class CSignalListener {
|
|
||||||
public:
|
|
||||||
CSignalListener(std::function<void(std::any)> handler);
|
|
||||||
|
|
||||||
CSignalListener(CSignalListener&&) = delete;
|
|
||||||
CSignalListener(CSignalListener&) = delete;
|
|
||||||
CSignalListener(const CSignalListener&) = delete;
|
|
||||||
CSignalListener(const CSignalListener&&) = delete;
|
|
||||||
|
|
||||||
void emit(std::any data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::function<void(std::any)> m_fHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SP<CSignalListener> CHyprSignalListener;
|
|
||||||
|
|
||||||
class CStaticSignalListener {
|
|
||||||
public:
|
|
||||||
CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner);
|
|
||||||
|
|
||||||
CStaticSignalListener(CStaticSignalListener&&) = delete;
|
|
||||||
CStaticSignalListener(CStaticSignalListener&) = delete;
|
|
||||||
CStaticSignalListener(const CStaticSignalListener&) = delete;
|
|
||||||
CStaticSignalListener(const CStaticSignalListener&&) = delete;
|
|
||||||
|
|
||||||
void emit(std::any data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* m_pOwner = nullptr;
|
|
||||||
std::function<void(void*, std::any)> m_fHandler;
|
|
||||||
};
|
|
|
@ -1,51 +0,0 @@
|
||||||
#include "Signal.hpp"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
void CSignal::emit(std::any data) {
|
|
||||||
bool dirty = false;
|
|
||||||
|
|
||||||
std::vector<SP<CSignalListener>> listeners;
|
|
||||||
for (auto& l : m_vListeners) {
|
|
||||||
if (l.expired()) {
|
|
||||||
dirty = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
listeners.emplace_back(l.lock());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CStaticSignalListener*> statics;
|
|
||||||
for (auto& l : m_vStaticListeners) {
|
|
||||||
statics.emplace_back(l.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& l : listeners) {
|
|
||||||
// if there is only one lock, it means the event is only held by the listeners
|
|
||||||
// vector and was removed during our iteration
|
|
||||||
if (l.strongRef() == 1) {
|
|
||||||
dirty = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
l->emit(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& l : statics) {
|
|
||||||
l->emit(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// release SPs
|
|
||||||
listeners.clear();
|
|
||||||
|
|
||||||
if (dirty)
|
|
||||||
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
CHyprSignalListener CSignal::registerListener(std::function<void(std::any)> handler) {
|
|
||||||
CHyprSignalListener listener = makeShared<CSignalListener>(handler);
|
|
||||||
m_vListeners.emplace_back(WP<CSignalListener>(listener));
|
|
||||||
return listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSignal::registerStaticListener(std::function<void(void*, std::any)> handler, void* owner) {
|
|
||||||
m_vStaticListeners.emplace_back(std::make_unique<CStaticSignalListener>(handler, owner));
|
|
||||||
}
|
|
|
@ -1,24 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <hyprutils/signal/Signal.hpp>
|
||||||
#include <any>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "Listener.hpp"
|
using namespace Hyprutils::Signal;
|
||||||
|
|
||||||
class CSignal {
|
|
||||||
public:
|
|
||||||
void emit(std::any data = {});
|
|
||||||
|
|
||||||
//
|
|
||||||
[[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function<void(std::any)> handler);
|
|
||||||
|
|
||||||
// this is for static listeners. They die with this signal.
|
|
||||||
// TODO: can we somehow rid of the void* data and make it a custom this?
|
|
||||||
void registerStaticListener(std::function<void(void*, std::any)> handler, void* owner);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<WP<CSignalListener>> m_vListeners;
|
|
||||||
std::vector<std::unique_ptr<CStaticSignalListener>> m_vStaticListeners;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hyprutils/string/VarList.hpp>
|
||||||
|
|
||||||
|
using namespace Hyprutils::String;
|
|
@ -76,17 +76,31 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
|
||||||
if (pWindow->m_bIsFloating)
|
if (pWindow->m_bIsFloating)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static auto PNEWTOP = CConfigValue<Hyprlang::INT>("master:new_on_top");
|
static auto PNEWONACTIVE = CConfigValue<std::string>("master:new_on_active");
|
||||||
|
static auto PNEWONTOP = CConfigValue<Hyprlang::INT>("master:new_on_top");
|
||||||
|
static auto PNEWSTATUS = CConfigValue<std::string>("master:new_status");
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
|
|
||||||
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
const bool BNEWBEFOREACTIVE = *PNEWONACTIVE == "before";
|
||||||
|
const bool BNEWISMASTER = *PNEWSTATUS == "master";
|
||||||
|
|
||||||
|
const auto PNODE = [&]() {
|
||||||
|
if (*PNEWONACTIVE != "none" && !BNEWISMASTER) {
|
||||||
|
const auto pLastNode = getNodeFromWindow(g_pCompositor->m_pLastWindow.lock());
|
||||||
|
if (pLastNode && !(pLastNode->isMaster && (getMastersOnWorkspace(pWindow->workspaceID()) == 1 || *PNEWSTATUS == "slave"))) {
|
||||||
|
auto it = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *pLastNode);
|
||||||
|
if (!BNEWBEFOREACTIVE)
|
||||||
|
++it;
|
||||||
|
return &(*m_lMasterNodesData.emplace(it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *PNEWONTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
||||||
|
}();
|
||||||
|
|
||||||
PNODE->workspaceID = pWindow->workspaceID();
|
PNODE->workspaceID = pWindow->workspaceID();
|
||||||
PNODE->pWindow = pWindow;
|
PNODE->pWindow = pWindow;
|
||||||
|
|
||||||
static auto PNEWISMASTER = CConfigValue<Hyprlang::INT>("master:new_is_master");
|
|
||||||
|
|
||||||
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
||||||
static auto PMFACT = CConfigValue<Hyprlang::FLOAT>("master:mfact");
|
static auto PMFACT = CConfigValue<Hyprlang::FLOAT>("master:mfact");
|
||||||
float lastSplitPercent = *PMFACT;
|
float lastSplitPercent = *PMFACT;
|
||||||
|
@ -186,13 +200,27 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
if ((BNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) //
|
||||||
forceDropAsMaster) {
|
|| WINDOWSONWORKSPACE == 1 //
|
||||||
for (auto& nd : m_lMasterNodesData) {
|
|| (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) //
|
||||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
|| forceDropAsMaster //
|
||||||
nd.isMaster = false;
|
|| (*PNEWSTATUS == "inherit" && OPENINGON && OPENINGON->isMaster && g_pInputManager->dragMode != MBIND_MOVE)) {
|
||||||
lastSplitPercent = nd.percMaster;
|
|
||||||
break;
|
if (BNEWBEFOREACTIVE) {
|
||||||
|
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
|
||||||
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||||
|
nd.isMaster = false;
|
||||||
|
lastSplitPercent = nd.percMaster;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto& nd : m_lMasterNodesData) {
|
||||||
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||||
|
nd.isMaster = false;
|
||||||
|
lastSplitPercent = nd.percMaster;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1440,7 +1468,7 @@ void CHyprMasterLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() {
|
Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() {
|
||||||
static auto PNEWISMASTER = CConfigValue<Hyprlang::INT>("master:new_is_master");
|
static auto PNEWSTATUS = CConfigValue<std::string>("master:new_status");
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor)
|
if (!g_pCompositor->m_pLastMonitor)
|
||||||
return {};
|
return {};
|
||||||
|
@ -1454,7 +1482,7 @@ Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() {
|
||||||
if (!MASTER) // wtf
|
if (!MASTER) // wtf
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (*PNEWISMASTER) {
|
if (*PNEWSTATUS == "master") {
|
||||||
return MASTER->size;
|
return MASTER->size;
|
||||||
} else {
|
} else {
|
||||||
const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "helpers/memory/WeakPtr.hpp"
|
#include "helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
#define UP std::unique_ptr
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#ifdef HYPRLAND_DEBUG
|
#ifdef HYPRLAND_DEBUG
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../desktop/Window.hpp"
|
#include "../desktop/Window.hpp"
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
#include "eventLoop/EventLoopManager.hpp"
|
#include "eventLoop/EventLoopManager.hpp"
|
||||||
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
|
|
||||||
int wlTick(SP<CEventLoopTimer> self, void* data) {
|
int wlTick(SP<CEventLoopTimer> self, void* data) {
|
||||||
if (g_pAnimationManager)
|
if (g_pAnimationManager)
|
||||||
|
@ -396,6 +397,8 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
|
||||||
auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle;
|
auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle;
|
||||||
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
|
||||||
|
|
||||||
|
CVarList animList(ANIMSTYLE, 0, 's');
|
||||||
|
|
||||||
// if the window is not being animated, that means the layout set a fixed size for it, don't animate.
|
// if the window is not being animated, that means the layout set a fixed size for it, don't animate.
|
||||||
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
|
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
|
||||||
return;
|
return;
|
||||||
|
@ -407,12 +410,8 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
|
||||||
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
|
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
|
||||||
// the window has config'd special anim
|
// the window has config'd special anim
|
||||||
if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) {
|
if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) {
|
||||||
if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) {
|
CVarList animList2(pWindow->m_sAdditionalConfigData.animationStyle, 0, 's');
|
||||||
// has a direction
|
animationSlide(pWindow, animList2[1], close);
|
||||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
|
|
||||||
} else {
|
|
||||||
animationSlide(pWindow, "", close);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// anim popin, fallback
|
// anim popin, fallback
|
||||||
|
|
||||||
|
@ -429,9 +428,9 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
|
||||||
animationPopin(pWindow, close, minPerc / 100.f);
|
animationPopin(pWindow, close, minPerc / 100.f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ANIMSTYLE == "slide") {
|
if (animList[0] == "slide")
|
||||||
animationSlide(pWindow, "", close);
|
animationSlide(pWindow, animList[1], close);
|
||||||
} else {
|
else {
|
||||||
// anim popin, fallback
|
// anim popin, fallback
|
||||||
|
|
||||||
float minPerc = 0.f;
|
float minPerc = 0.f;
|
||||||
|
@ -451,9 +450,9 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
|
||||||
|
|
||||||
std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
|
std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
|
||||||
if (config.starts_with("window")) {
|
if (config.starts_with("window")) {
|
||||||
if (style == "slide") {
|
if (style.starts_with("slide"))
|
||||||
return "";
|
return "";
|
||||||
} else if (style.starts_with("popin")) {
|
else if (style.starts_with("popin")) {
|
||||||
// try parsing
|
// try parsing
|
||||||
float minPerc = 0.f;
|
float minPerc = 0.f;
|
||||||
if (style.find("%") != std::string::npos) {
|
if (style.find("%") != std::string::npos) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/memory/SharedPtr.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
struct SHyprIPCEvent {
|
struct SHyprIPCEvent {
|
||||||
std::string event;
|
std::string event;
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include "../devices/IKeyboard.hpp"
|
#include "../devices/IKeyboard.hpp"
|
||||||
#include "../managers/SeatManager.hpp"
|
#include "../managers/SeatManager.hpp"
|
||||||
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/ShortcutsInhibit.hpp"
|
#include "../protocols/ShortcutsInhibit.hpp"
|
||||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||||
#include "KeybindManager.hpp"
|
#include "KeybindManager.hpp"
|
||||||
#include "TokenManager.hpp"
|
#include "TokenManager.hpp"
|
||||||
#include "debug/Log.hpp"
|
#include "debug/Log.hpp"
|
||||||
#include "helpers/VarList.hpp"
|
#include "helpers/varlist/VarList.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -111,6 +115,7 @@ CKeybindManager::CKeybindManager() {
|
||||||
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
||||||
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
||||||
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
||||||
|
m_mDispatchers["event"] = event;
|
||||||
m_mDispatchers["global"] = global;
|
m_mDispatchers["global"] = global;
|
||||||
|
|
||||||
m_tScrollTimer.reset();
|
m_tScrollTimer.reset();
|
||||||
|
@ -836,7 +841,7 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
|
||||||
|
|
||||||
void CKeybindManager::spawn(std::string args) {
|
void CKeybindManager::spawn(std::string args) {
|
||||||
|
|
||||||
args = removeBeginEndSpacesTabs(args);
|
args = trim(args);
|
||||||
|
|
||||||
std::string RULES = "";
|
std::string RULES = "";
|
||||||
|
|
||||||
|
@ -1083,6 +1088,8 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||||
if (!PMONITORWORKSPACEOWNER)
|
if (!PMONITORWORKSPACEOWNER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
updateRelativeCursorCoords();
|
||||||
|
|
||||||
g_pCompositor->setActiveMonitor(PMONITORWORKSPACEOWNER);
|
g_pCompositor->setActiveMonitor(PMONITORWORKSPACEOWNER);
|
||||||
|
|
||||||
if (BISWORKSPACECURRENT) {
|
if (BISWORKSPACECURRENT) {
|
||||||
|
@ -1111,6 +1118,16 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||||
else
|
else
|
||||||
g_pInputManager->simulateMouseMovement();
|
g_pInputManager->simulateMouseMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const static auto PWARPONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("cursor:warp_on_change_workspace");
|
||||||
|
|
||||||
|
if (*PWARPONWORKSPACECHANGE) {
|
||||||
|
auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow();
|
||||||
|
auto HLSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock());
|
||||||
|
|
||||||
|
if (PLAST && (!HLSurface || HLSurface->getWindow()))
|
||||||
|
PLAST->warpCursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::fullscreenActive(std::string args) {
|
void CKeybindManager::fullscreenActive(std::string args) {
|
||||||
|
@ -2677,3 +2694,7 @@ void CKeybindManager::moveGroupWindow(std::string args) {
|
||||||
|
|
||||||
PLASTWINDOW->updateWindowDecos();
|
PLASTWINDOW->updateWindowDecos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKeybindManager::event(std::string args) {
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"custom", args});
|
||||||
|
}
|
||||||
|
|
|
@ -14,23 +14,25 @@ class CPluginSystem;
|
||||||
class IKeyboard;
|
class IKeyboard;
|
||||||
|
|
||||||
struct SKeybind {
|
struct SKeybind {
|
||||||
std::string key = "";
|
std::string key = "";
|
||||||
std::set<xkb_keysym_t> sMkKeys = {};
|
std::set<xkb_keysym_t> sMkKeys = {};
|
||||||
uint32_t keycode = 0;
|
uint32_t keycode = 0;
|
||||||
bool catchAll = false;
|
bool catchAll = false;
|
||||||
uint32_t modmask = 0;
|
uint32_t modmask = 0;
|
||||||
std::set<xkb_keysym_t> sMkMods = {};
|
std::set<xkb_keysym_t> sMkMods = {};
|
||||||
std::string handler = "";
|
std::string handler = "";
|
||||||
std::string arg = "";
|
std::string arg = "";
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
std::string submap = "";
|
std::string submap = "";
|
||||||
bool release = false;
|
std::string description = "";
|
||||||
bool repeat = false;
|
bool release = false;
|
||||||
bool mouse = false;
|
bool repeat = false;
|
||||||
bool nonConsuming = false;
|
bool mouse = false;
|
||||||
bool transparent = false;
|
bool nonConsuming = false;
|
||||||
bool ignoreMods = false;
|
bool transparent = false;
|
||||||
bool multiKey = false;
|
bool ignoreMods = false;
|
||||||
|
bool multiKey = false;
|
||||||
|
bool hasDescription = false;
|
||||||
|
|
||||||
// DO NOT INITIALIZE
|
// DO NOT INITIALIZE
|
||||||
bool shadowed = false;
|
bool shadowed = false;
|
||||||
|
@ -203,6 +205,7 @@ class CKeybindManager {
|
||||||
static void setIgnoreGroupLock(std::string);
|
static void setIgnoreGroupLock(std::string);
|
||||||
static void denyWindowFromGroup(std::string);
|
static void denyWindowFromGroup(std::string);
|
||||||
static void global(std::string);
|
static void global(std::string);
|
||||||
|
static void event(std::string);
|
||||||
|
|
||||||
friend class CCompositor;
|
friend class CCompositor;
|
||||||
friend class CInputManager;
|
friend class CInputManager;
|
||||||
|
|
|
@ -150,6 +150,20 @@ CPointerManager::CPointerManager() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPointerManager::lockSoftwareAll() {
|
||||||
|
for (auto& state : monitorStates)
|
||||||
|
state->softwareLocks++;
|
||||||
|
|
||||||
|
updateCursorBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPointerManager::unlockSoftwareAll() {
|
||||||
|
for (auto& state : monitorStates)
|
||||||
|
state->softwareLocks--;
|
||||||
|
|
||||||
|
updateCursorBackend();
|
||||||
|
}
|
||||||
|
|
||||||
void CPointerManager::lockSoftwareForMonitor(SP<CMonitor> mon) {
|
void CPointerManager::lockSoftwareForMonitor(SP<CMonitor> mon) {
|
||||||
auto state = stateFor(mon);
|
auto state = stateFor(mon);
|
||||||
state->softwareLocks++;
|
state->softwareLocks++;
|
||||||
|
@ -661,7 +675,7 @@ void CPointerManager::damageIfSoftware() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
||||||
g_pHyprRenderer->damageBox(&b);
|
g_pHyprRenderer->damageBox(&b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ class CPointerManager {
|
||||||
|
|
||||||
void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
void lockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
||||||
void unlockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
void unlockSoftwareForMonitor(SP<CMonitor> pMonitor);
|
||||||
|
void lockSoftwareAll();
|
||||||
|
void unlockSoftwareAll();
|
||||||
|
|
||||||
void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */);
|
void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */);
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "../protocols/TextInputV1.hpp"
|
#include "../protocols/TextInputV1.hpp"
|
||||||
#include "../protocols/GlobalShortcuts.hpp"
|
#include "../protocols/GlobalShortcuts.hpp"
|
||||||
#include "../protocols/Screencopy.hpp"
|
#include "../protocols/Screencopy.hpp"
|
||||||
#include "../helpers/memory/WeakPtr.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class CProtocolManager {
|
class CProtocolManager {
|
||||||
|
|
|
@ -94,7 +94,7 @@ void CSeatManager::setKeyboard(SP<IKeyboard> KEEB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::updateActiveKeyboardData() {
|
void CSeatManager::updateActiveKeyboardData() {
|
||||||
if (keyboard)
|
if (keyboard && keyboard->wlr())
|
||||||
PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay);
|
PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay);
|
||||||
PROTO::seat->updateKeymap();
|
PROTO::seat->updateKeymap();
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,11 @@ void CSeatManager::setPointerFocus(SP<CWLSurfaceResource> surf, const Vector2D&
|
||||||
if (state.pointerFocus == surf)
|
if (state.pointerFocus == surf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (PROTO::data->dndActive() && surf) {
|
||||||
|
Debug::log(LOG, "[seatmgr] Refusing pointer focus during an active dnd");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mouse || !mouse->wlr()) {
|
if (!mouse || !mouse->wlr()) {
|
||||||
Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set");
|
Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set");
|
||||||
return;
|
return;
|
||||||
|
@ -337,34 +342,11 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::sendTouchDown(SP<CWLSurfaceResource> surf, uint32_t timeMs, int32_t id, const Vector2D& local) {
|
void CSeatManager::sendTouchDown(SP<CWLSurfaceResource> surf, uint32_t timeMs, int32_t id, const Vector2D& local) {
|
||||||
if (state.touchFocus == surf)
|
|
||||||
return;
|
|
||||||
|
|
||||||
listeners.touchSurfaceDestroy.reset();
|
listeners.touchSurfaceDestroy.reset();
|
||||||
|
|
||||||
if (state.touchFocusResource) {
|
|
||||||
auto client = state.touchFocusResource->client();
|
|
||||||
for (auto& s : seatResources) {
|
|
||||||
if (s->resource->client() != client)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (auto& t : s->resource->touches) {
|
|
||||||
if (!t)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
t->sendUp(timeMs, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.touchFocusResource.reset();
|
state.touchFocusResource.reset();
|
||||||
state.touchFocus = surf;
|
state.touchFocus = surf;
|
||||||
|
|
||||||
if (!surf) {
|
|
||||||
events.touchFocusChange.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto client = surf->client();
|
auto client = surf->client();
|
||||||
for (auto& r : seatResources | std::views::reverse) {
|
for (auto& r : seatResources | std::views::reverse) {
|
||||||
if (r->resource->client() != client)
|
if (r->resource->client() != client)
|
||||||
|
@ -381,11 +363,34 @@ void CSeatManager::sendTouchDown(SP<CWLSurfaceResource> surf, uint32_t timeMs, i
|
||||||
|
|
||||||
listeners.touchSurfaceDestroy = surf->events.destroy.registerListener([this, timeMs, id](std::any d) { sendTouchUp(timeMs + 10, id); });
|
listeners.touchSurfaceDestroy = surf->events.destroy.registerListener([this, timeMs, id](std::any d) { sendTouchUp(timeMs + 10, id); });
|
||||||
|
|
||||||
events.touchFocusChange.emit();
|
touchLocks++;
|
||||||
|
|
||||||
|
if (touchLocks <= 1)
|
||||||
|
events.touchFocusChange.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::sendTouchUp(uint32_t timeMs, int32_t id) {
|
void CSeatManager::sendTouchUp(uint32_t timeMs, int32_t id) {
|
||||||
sendTouchDown(nullptr, timeMs, id, {});
|
if (!state.touchFocusResource || touchLocks <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto client = state.touchFocusResource->client();
|
||||||
|
for (auto& r : seatResources | std::views::reverse) {
|
||||||
|
if (r->resource->client() != client)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
state.touchFocusResource = r->resource;
|
||||||
|
for (auto& t : r->resource->touches) {
|
||||||
|
if (!t)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
t->sendUp(timeMs, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
touchLocks--;
|
||||||
|
|
||||||
|
if (touchLocks <= 0)
|
||||||
|
events.touchFocusChange.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local) {
|
void CSeatManager::sendTouchMotion(uint32_t timeMs, int32_t id, const Vector2D& local) {
|
||||||
|
|
|
@ -155,6 +155,7 @@ class CSeatManager {
|
||||||
} listeners;
|
} listeners;
|
||||||
|
|
||||||
Vector2D lastLocalCoords;
|
Vector2D lastLocalCoords;
|
||||||
|
int touchLocks = 0; // we assume there aint like 20 touch devices at once...
|
||||||
|
|
||||||
friend struct SSeatResourceContainer;
|
friend struct SSeatResourceContainer;
|
||||||
friend class CSeatGrab;
|
friend class CSeatGrab;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/Timer.hpp"
|
#include "../helpers/Timer.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
|
@ -25,5 +25,6 @@ CThreadManager::CThreadManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CThreadManager::~CThreadManager() {
|
CThreadManager::~CThreadManager() {
|
||||||
//
|
if (m_esConfigTimer)
|
||||||
|
wl_event_source_remove(m_esConfigTimer);
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "../helpers/memory/SharedPtr.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
class CUUIDToken {
|
class CUUIDToken {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "../../helpers/memory/SharedPtr.hpp"
|
#include "../../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
class CEventLoopTimer {
|
class CEventLoopTimer {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -155,6 +155,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
Vector2D surfacePos = Vector2D(-1337, -1337);
|
Vector2D surfacePos = Vector2D(-1337, -1337);
|
||||||
PHLWINDOW pFoundWindow;
|
PHLWINDOW pFoundWindow;
|
||||||
PHLLS pFoundLayerSurface;
|
PHLLS pFoundLayerSurface;
|
||||||
|
SSessionLockSurface* pSessionLock = nullptr;
|
||||||
|
|
||||||
if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState)
|
if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState)
|
||||||
return;
|
return;
|
||||||
|
@ -186,7 +187,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
if (*PZOOMFACTOR != 1.f)
|
if (*PZOOMFACTOR != 1.f)
|
||||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||||
|
|
||||||
if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0)
|
bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent();
|
||||||
|
|
||||||
|
if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule)
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||||
|
|
||||||
PHLWINDOW forcedFocus = m_pForcedFocus.lock();
|
PHLWINDOW forcedFocus = m_pForcedFocus.lock();
|
||||||
|
@ -261,12 +264,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
g_pCompositor->setActiveMonitor(PMONITOR);
|
g_pCompositor->setActiveMonitor(PMONITOR);
|
||||||
|
|
||||||
if (g_pSessionLockManager->isSessionLocked()) {
|
if (g_pSessionLockManager->isSessionLocked()) {
|
||||||
const auto PSLS = PMONITOR ? g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID) : nullptr;
|
pSessionLock = PMONITOR ? g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID) : nullptr;
|
||||||
|
|
||||||
if (!PSLS)
|
if (!pSessionLock)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foundSurface = PSLS->surface->surface();
|
foundSurface = pSessionLock->surface->surface();
|
||||||
surfacePos = PMONITOR->vecPosition;
|
surfacePos = PMONITOR->vecPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +353,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
if (pFoundWindow) {
|
if (pFoundWindow) {
|
||||||
if (!pFoundWindow->m_bIsX11) {
|
if (!pFoundWindow->m_bIsX11) {
|
||||||
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
|
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
|
||||||
|
if (!foundSurface) {
|
||||||
|
foundSurface = pFoundWindow->m_pWLSurface->resource();
|
||||||
|
surfacePos = pFoundWindow->m_vRealPosition.value();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
foundSurface = pFoundWindow->m_pWLSurface->resource();
|
foundSurface = pFoundWindow->m_pWLSurface->resource();
|
||||||
surfacePos = pFoundWindow->m_vRealPosition.value();
|
surfacePos = pFoundWindow->m_vRealPosition.value();
|
||||||
|
@ -365,7 +372,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
foundSurface =
|
foundSurface =
|
||||||
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0)
|
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule)
|
||||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
||||||
|
|
||||||
// grabs
|
// grabs
|
||||||
|
@ -455,7 +462,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
restoreCursorIconToApp();
|
restoreCursorIconToApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFoundWindow) {
|
if (pSessionLock != nullptr)
|
||||||
|
g_pCompositor->focusSurface(foundSurface);
|
||||||
|
else if (pFoundWindow) {
|
||||||
// change cursor icon if hovering over border
|
// change cursor icon if hovering over border
|
||||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||||
if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) {
|
if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) {
|
||||||
|
@ -509,7 +518,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFoundLayerSurface && (pFoundLayerSurface->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) && FOLLOWMOUSE != 3 &&
|
if (pFoundLayerSurface && (pFoundLayerSurface->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) && FOLLOWMOUSE != 3 &&
|
||||||
allowKeyboardRefocus) {
|
(allowKeyboardRefocus || pFoundLayerSurface->layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)) {
|
||||||
g_pCompositor->focusSurface(foundSurface);
|
g_pCompositor->focusSurface(foundSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,12 +1232,20 @@ void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) {
|
||||||
std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; });
|
std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; });
|
||||||
|
|
||||||
if (m_vKeyboards.size() > 0) {
|
if (m_vKeyboards.size() > 0) {
|
||||||
const auto PNEWKEYBOARD = m_vKeyboards.back();
|
bool found = false;
|
||||||
g_pSeatManager->setKeyboard(PNEWKEYBOARD);
|
for (auto& k : m_vKeyboards | std::views::reverse) {
|
||||||
PNEWKEYBOARD->active = true;
|
if (!k->wlr())
|
||||||
} else {
|
continue;
|
||||||
|
|
||||||
|
g_pSeatManager->setKeyboard(k);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
g_pSeatManager->setKeyboard(nullptr);
|
||||||
|
} else
|
||||||
g_pSeatManager->setKeyboard(nullptr);
|
g_pSeatManager->setKeyboard(nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
removeFromHIDs(pKeyboard);
|
removeFromHIDs(pKeyboard);
|
||||||
}
|
}
|
||||||
|
@ -1381,6 +1398,41 @@ void CInputManager::refocus() {
|
||||||
mouseMoveUnified(0, true);
|
mouseMoveUnified(0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInputManager::refocusLastWindow(CMonitor* pMonitor) {
|
||||||
|
if (!pMonitor) {
|
||||||
|
refocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D surfaceCoords;
|
||||||
|
PHLLS pFoundLayerSurface;
|
||||||
|
SP<CWLSurfaceResource> foundSurface = nullptr;
|
||||||
|
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
|
// first try for an exclusive layer
|
||||||
|
if (!m_dExclusiveLSes.empty())
|
||||||
|
foundSurface = m_dExclusiveLSes[m_dExclusiveLSes.size() - 1]->surface->resource();
|
||||||
|
|
||||||
|
// then any surfaces above windows on the same monitor
|
||||||
|
if (!foundSurface)
|
||||||
|
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
|
||||||
|
&surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
|
if (!foundSurface)
|
||||||
|
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
|
||||||
|
&surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
|
if (!foundSurface && g_pCompositor->m_pLastWindow.lock() && g_pCompositor->isWorkspaceVisibleNotCovered(g_pCompositor->m_pLastWindow->m_pWorkspace)) {
|
||||||
|
// then the last focused window if we're on the same workspace as it
|
||||||
|
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||||
|
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||||
|
} else {
|
||||||
|
// otherwise fall back to a normal refocus.
|
||||||
|
refocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CInputManager::unconstrainMouse() {
|
void CInputManager::unconstrainMouse() {
|
||||||
if (g_pSeatManager->mouse.expired())
|
if (g_pSeatManager->mouse.expired())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "../../helpers/WLClasses.hpp"
|
#include "../../helpers/WLClasses.hpp"
|
||||||
#include "../../helpers/Timer.hpp"
|
#include "../../helpers/Timer.hpp"
|
||||||
#include "InputMethodRelay.hpp"
|
#include "InputMethodRelay.hpp"
|
||||||
#include "../../helpers/signal/Listener.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
#include "../../devices/IPointer.hpp"
|
#include "../../devices/IPointer.hpp"
|
||||||
#include "../../devices/ITouch.hpp"
|
#include "../../devices/ITouch.hpp"
|
||||||
#include "../../devices/Tablet.hpp"
|
#include "../../devices/Tablet.hpp"
|
||||||
|
@ -104,6 +104,7 @@ class CInputManager {
|
||||||
|
|
||||||
Vector2D getMouseCoordsInternal();
|
Vector2D getMouseCoordsInternal();
|
||||||
void refocus();
|
void refocus();
|
||||||
|
void refocusLastWindow(CMonitor* pMonitor);
|
||||||
void simulateMouseMovement();
|
void simulateMouseMovement();
|
||||||
void sendMotionEventsToFocused();
|
void sendMotionEventsToFocused();
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "../../desktop/WLSurface.hpp"
|
#include "../../desktop/WLSurface.hpp"
|
||||||
#include "../../macros.hpp"
|
#include "../../macros.hpp"
|
||||||
#include "../../helpers/Box.hpp"
|
#include "../../helpers/Box.hpp"
|
||||||
#include "../../helpers/signal/Listener.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CInputMethodPopupV2;
|
class CInputMethodPopupV2;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "../../defines.hpp"
|
#include "../../defines.hpp"
|
||||||
#include "../../helpers/WLClasses.hpp"
|
#include "../../helpers/WLClasses.hpp"
|
||||||
#include "../../helpers/signal/Listener.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
#include "TextInput.hpp"
|
#include "TextInput.hpp"
|
||||||
#include "InputMethodPopup.hpp"
|
#include "InputMethodPopup.hpp"
|
||||||
#include <any>
|
#include <any>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "../../helpers/WLListener.hpp"
|
#include "../../helpers/WLListener.hpp"
|
||||||
#include "../../macros.hpp"
|
#include "../../macros.hpp"
|
||||||
#include "../../helpers/Box.hpp"
|
#include "../../helpers/Box.hpp"
|
||||||
#include "../../helpers/signal/Listener.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
struct wl_client;
|
struct wl_client;
|
||||||
|
|
|
@ -13,6 +13,7 @@ executable('Hyprland', src,
|
||||||
dependency('cairo'),
|
dependency('cairo'),
|
||||||
dependency('hyprcursor'),
|
dependency('hyprcursor'),
|
||||||
dependency('hyprlang', version: '>= 0.3.2'),
|
dependency('hyprlang', version: '>= 0.3.2'),
|
||||||
|
dependency('hyprutils', version: '>= 0.1.1'),
|
||||||
dependency('libdrm'),
|
dependency('libdrm'),
|
||||||
dependency('egl'),
|
dependency('egl'),
|
||||||
dependency('xkbcommon'),
|
dependency('xkbcommon'),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "HookSystem.hpp"
|
#include "HookSystem.hpp"
|
||||||
#include "../debug/Log.hpp"
|
#include "../debug/Log.hpp"
|
||||||
#include "../helpers/VarList.hpp"
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
#include "../managers/TokenManager.hpp"
|
#include "../managers/TokenManager.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "alpha-modifier-v1.hpp"
|
#include "alpha-modifier-v1.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CFocusGrab;
|
class CFocusGrab;
|
||||||
class CSeatGrab;
|
class CSeatGrab;
|
||||||
|
|
|
@ -122,25 +122,19 @@ void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) {
|
||||||
if (lastMonitorID == (int64_t)pMonitor->ID)
|
if (lastMonitorID == (int64_t)pMonitor->ID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto CLIENT = resource->client();
|
const auto CLIENT = resource->client();
|
||||||
|
|
||||||
struct wl_resource* outputResource;
|
|
||||||
|
|
||||||
if (const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(lastMonitorID); PLASTMONITOR) {
|
if (const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(lastMonitorID); PLASTMONITOR) {
|
||||||
wl_resource_for_each(outputResource, &PLASTMONITOR->output->resources) {
|
const auto OLDRESOURCE = PROTO::outputs.at(PLASTMONITOR->szName)->outputResourceFrom(CLIENT);
|
||||||
if (wl_resource_get_client(outputResource) != CLIENT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
resource->sendOutputLeave(outputResource);
|
if (OLDRESOURCE)
|
||||||
}
|
resource->sendOutputLeave(OLDRESOURCE->getResource()->resource());
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_resource_for_each(outputResource, &pMonitor->output->resources) {
|
const auto NEWRESOURCE = PROTO::outputs.at(pMonitor->szName)->outputResourceFrom(CLIENT);
|
||||||
if (wl_resource_get_client(outputResource) != CLIENT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
resource->sendOutputEnter(outputResource);
|
if (NEWRESOURCE)
|
||||||
}
|
resource->sendOutputEnter(NEWRESOURCE->getResource()->resource());
|
||||||
|
|
||||||
lastMonitorID = pMonitor->ID;
|
lastMonitorID = pMonitor->ID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-gamma-control-unstable-v1.hpp"
|
#include "wlr-gamma-control-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ SP<CInputMethodV2> CInputMethodKeyboardGrabV2::getOwner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_client* CInputMethodKeyboardGrabV2::client() {
|
wl_client* CInputMethodKeyboardGrabV2::client() {
|
||||||
return resource->client();
|
return resource->resource() ? resource->client() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, SP<CWLSurfaceResource> surface) : resource(resource_), owner(owner_) {
|
CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_, SP<CInputMethodV2> owner_, SP<CWLSurfaceResource> surface) : resource(resource_), owner(owner_) {
|
||||||
|
@ -373,4 +373,4 @@ void CInputMethodV2Protocol::onGetIME(CZwpInputMethodManagerV2* mgr, wl_resource
|
||||||
LOGM(LOG, "New IME with resource id {}", id);
|
LOGM(LOG, "New IME with resource id {}", id);
|
||||||
|
|
||||||
events.newIME.emit(RESOURCE);
|
events.newIME.emit(RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-output-management-unstable-v1.hpp"
|
#include "wlr-output-management-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-output-power-management-unstable-v1.hpp"
|
#include "wlr-output-power-management-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "pointer-constraints-unstable-v1.hpp"
|
#include "pointer-constraints-unstable-v1.hpp"
|
||||||
#include "../helpers/Vector2D.hpp"
|
#include "../helpers/Vector2D.hpp"
|
||||||
#include "../helpers/Region.hpp"
|
#include "../helpers/Region.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CWLSurface;
|
class CWLSurface;
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
|
|
|
@ -114,9 +114,11 @@ CSessionLock::CSessionLock(SP<CExtSessionLockV1> resource_) : resource(resource_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
events.unlockAndDestroy.emit();
|
|
||||||
inert = true;
|
|
||||||
PROTO::sessionLock->locked = false;
|
PROTO::sessionLock->locked = false;
|
||||||
|
|
||||||
|
events.unlockAndDestroy.emit();
|
||||||
|
|
||||||
|
inert = true;
|
||||||
PROTO::sessionLock->destroyResource(this);
|
PROTO::sessionLock->destroyResource(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ wlr_keyboard* CVirtualKeyboardV1Resource::wlr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_client* CVirtualKeyboardV1Resource::client() {
|
wl_client* CVirtualKeyboardV1Resource::client() {
|
||||||
return resource->client();
|
return resource->resource() ? resource->client() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVirtualKeyboardV1Resource::releasePressed() {
|
void CVirtualKeyboardV1Resource::releasePressed() {
|
||||||
|
@ -151,4 +151,4 @@ void CVirtualKeyboardProtocol::onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr,
|
||||||
LOGM(LOG, "New VKeyboard at id {}", id);
|
LOGM(LOG, "New VKeyboard at id {}", id);
|
||||||
|
|
||||||
events.newKeyboard.emit(RESOURCE);
|
events.newKeyboard.emit(RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,10 +136,12 @@ CXDGToplevelResource::CXDGToplevelResource(SP<CXdgToplevel> resource_, SP<CXDGSu
|
||||||
wl_array_release(&arr);
|
wl_array_release(&arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_LEFT);
|
if (resource->version() >= 2) {
|
||||||
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_RIGHT);
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_LEFT);
|
||||||
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_TOP);
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_RIGHT);
|
||||||
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_BOTTOM);
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_TOP);
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
resource->setSetTitle([this](CXdgToplevel* r, const char* t) {
|
resource->setSetTitle([this](CXdgToplevel* r, const char* t) {
|
||||||
state.title = t;
|
state.title = t;
|
||||||
|
@ -261,6 +263,9 @@ uint32_t CXDGToplevelResource::setActive(bool active) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CXDGToplevelResource::setSuspeneded(bool sus) {
|
uint32_t CXDGToplevelResource::setSuspeneded(bool sus) {
|
||||||
|
if (resource->version() < 6)
|
||||||
|
return owner->scheduleConfigure(); // SUSPENDED is since 6
|
||||||
|
|
||||||
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_SUSPENDED) != pendingApply.states.end();
|
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_SUSPENDED) != pendingApply.states.end();
|
||||||
|
|
||||||
if (sus == set)
|
if (sus == set)
|
||||||
|
@ -507,12 +512,12 @@ CXDGPositionerRules::CXDGPositionerRules(SP<CXDGPositionerResource> positioner)
|
||||||
state = positioner->state;
|
state = positioner->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector2D pointForAnchor(const CBox& box, xdgPositionerAnchor anchor) {
|
static Vector2D pointForAnchor(const CBox& box, const Vector2D& predictionSize, xdgPositionerAnchor anchor) {
|
||||||
switch (anchor) {
|
switch (anchor) {
|
||||||
case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F, 0};
|
case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, 0};
|
||||||
case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F, box.size().y};
|
case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F - predictionSize.x / 2.F, box.size().y};
|
||||||
case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F};
|
case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F - predictionSize.y / 2.F};
|
||||||
case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F};
|
case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F - predictionSize.y / 2.F};
|
||||||
case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos();
|
case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos();
|
||||||
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y};
|
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y};
|
||||||
case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0};
|
case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0};
|
||||||
|
@ -527,7 +532,7 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa
|
||||||
|
|
||||||
Debug::log(LOG, "GetPosition with constraint {} {} and parent {}", constraint.pos(), constraint.size(), parentCoord);
|
Debug::log(LOG, "GetPosition with constraint {} {} and parent {}", constraint.pos(), constraint.size(), parentCoord);
|
||||||
|
|
||||||
CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.anchor) + state.offset, state.requestedSize};
|
CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.requestedSize, state.anchor) + state.offset, state.requestedSize};
|
||||||
|
|
||||||
bool success = predictedBox.inside(constraint);
|
bool success = predictedBox.inside(constraint);
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,17 @@ CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataS
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resource->setDestroy([this](CWlDataOffer* r) {
|
resource->setDestroy([this](CWlDataOffer* r) {
|
||||||
if (!dead)
|
if (!dead && (recvd || accepted))
|
||||||
PROTO::data->completeDrag();
|
PROTO::data->completeDrag();
|
||||||
|
else
|
||||||
|
PROTO::data->abortDrag();
|
||||||
PROTO::data->destroyResource(this);
|
PROTO::data->destroyResource(this);
|
||||||
});
|
});
|
||||||
resource->setOnDestroy([this](CWlDataOffer* r) {
|
resource->setOnDestroy([this](CWlDataOffer* r) {
|
||||||
if (!dead)
|
if (!dead && (recvd || accepted))
|
||||||
PROTO::data->completeDrag();
|
PROTO::data->completeDrag();
|
||||||
|
else
|
||||||
|
PROTO::data->abortDrag();
|
||||||
PROTO::data->destroyResource(this);
|
PROTO::data->destroyResource(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -85,8 +89,10 @@ void CWLDataOfferResource::sendData() {
|
||||||
if (!source)
|
if (!source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resource->sendSourceActions(7);
|
if (resource->version() >= 3) {
|
||||||
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
|
resource->sendSourceActions(7);
|
||||||
|
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& m : source->mimes()) {
|
for (auto& m : source->mimes()) {
|
||||||
LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m);
|
LOGM(LOG, " | offer {:x} supports mime {}", (uintptr_t)this, m);
|
||||||
|
@ -536,6 +542,11 @@ void CWLDataDeviceProtocol::initiateDrag(WP<CWLDataSourceResource> currentSource
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// unfocus the pointer from the surface, this is part of """standard""" wayland procedure and gtk will freak out if this isn't happening.
|
||||||
|
// BTW, the spec does NOT require this explicitly...
|
||||||
|
// Fuck you gtk.
|
||||||
|
g_pSeatManager->setPointerFocus(nullptr, {});
|
||||||
|
|
||||||
// make a new offer, etc
|
// make a new offer, etc
|
||||||
updateDrag();
|
updateDrag();
|
||||||
}
|
}
|
||||||
|
@ -590,15 +601,35 @@ void CWLDataDeviceProtocol::dropDrag() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dnd.currentSource->sendDndDropPerformed();
|
if (!wasDragSuccessful()) {
|
||||||
|
abortDrag();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dnd.focusedDevice->sendDrop();
|
dnd.focusedDevice->sendDrop();
|
||||||
dnd.focusedDevice->sendLeave();
|
|
||||||
|
|
||||||
resetDndState();
|
resetDndState();
|
||||||
|
|
||||||
if (dnd.overriddenCursor)
|
if (dnd.overriddenCursor)
|
||||||
g_pInputManager->unsetCursorImage();
|
g_pInputManager->unsetCursorImage();
|
||||||
dnd.overriddenCursor = false;
|
dnd.overriddenCursor = false;
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWLDataDeviceProtocol::wasDragSuccessful() {
|
||||||
|
if (!dnd.focusedDevice || !dnd.currentSource)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto& o : m_vOffers) {
|
||||||
|
if (o->dead || !o->source || !o->source->hasDnd())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (o->recvd || o->accepted)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLDataDeviceProtocol::completeDrag() {
|
void CWLDataDeviceProtocol::completeDrag() {
|
||||||
|
@ -607,12 +638,13 @@ void CWLDataDeviceProtocol::completeDrag() {
|
||||||
if (!dnd.focusedDevice || !dnd.currentSource)
|
if (!dnd.focusedDevice || !dnd.currentSource)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dnd.currentSource->sendDndDropPerformed();
|
||||||
dnd.currentSource->sendDndFinished();
|
dnd.currentSource->sendDndFinished();
|
||||||
|
|
||||||
dnd.focusedDevice.reset();
|
dnd.focusedDevice.reset();
|
||||||
dnd.currentSource.reset();
|
dnd.currentSource.reset();
|
||||||
|
|
||||||
g_pSeatManager->resendEnterEvents();
|
g_pInputManager->simulateMouseMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLDataDeviceProtocol::abortDrag() {
|
void CWLDataDeviceProtocol::abortDrag() {
|
||||||
|
@ -631,7 +663,7 @@ void CWLDataDeviceProtocol::abortDrag() {
|
||||||
dnd.focusedDevice.reset();
|
dnd.focusedDevice.reset();
|
||||||
dnd.currentSource.reset();
|
dnd.currentSource.reset();
|
||||||
|
|
||||||
g_pSeatManager->resendEnterEvents();
|
g_pInputManager->simulateMouseMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) {
|
void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) {
|
||||||
|
@ -650,5 +682,5 @@ void CWLDataDeviceProtocol::renderDND(CMonitor* pMonitor, timespec* when) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWLDataDeviceProtocol::dndActive() {
|
bool CWLDataDeviceProtocol::dndActive() {
|
||||||
return dnd.currentSource;
|
return dnd.currentSource && dnd.mouseButton /* test a member of the state to ensure it's also present */;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,6 +175,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol {
|
||||||
void dropDrag();
|
void dropDrag();
|
||||||
void completeDrag();
|
void completeDrag();
|
||||||
void resetDndState();
|
void resetDndState();
|
||||||
|
bool wasDragSuccessful();
|
||||||
|
|
||||||
//
|
//
|
||||||
SP<CWLDataDeviceResource> dataDeviceForClient(wl_client*);
|
SP<CWLDataDeviceResource> dataDeviceForClient(wl_client*);
|
||||||
|
|
|
@ -9,6 +9,9 @@ CWLOutputResource::CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> pMoni
|
||||||
|
|
||||||
pClient = resource->client();
|
pClient = resource->client();
|
||||||
|
|
||||||
|
if (!monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
resource->setOnDestroy([this](CWlOutput* r) {
|
resource->setOnDestroy([this](CWlOutput* r) {
|
||||||
if (monitor && PROTO::outputs.contains(monitor->szName))
|
if (monitor && PROTO::outputs.contains(monitor->szName))
|
||||||
PROTO::outputs.at(monitor->szName)->destroyResource(this);
|
PROTO::outputs.at(monitor->szName)->destroyResource(this);
|
||||||
|
@ -69,6 +72,9 @@ CWLOutputProtocol::CWLOutputProtocol(const wl_interface* iface, const int& ver,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
|
if (defunct)
|
||||||
|
Debug::log(WARN, "[wl_output] Binding a wl_output that's inert?? Possible client bug.");
|
||||||
|
|
||||||
const auto RESOURCE = m_vOutputs.emplace_back(makeShared<CWLOutputResource>(makeShared<CWlOutput>(client, ver, id), monitor.lock()));
|
const auto RESOURCE = m_vOutputs.emplace_back(makeShared<CWLOutputResource>(makeShared<CWlOutput>(client, ver, id), monitor.lock()));
|
||||||
|
|
||||||
if (!RESOURCE->good()) {
|
if (!RESOURCE->good()) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../WaylandProtocol.hpp"
|
#include "../WaylandProtocol.hpp"
|
||||||
#include "wayland.hpp"
|
#include "wayland.hpp"
|
||||||
#include "../../helpers/signal/Listener.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
|
|
|
@ -25,37 +25,38 @@ void CWLTouchResource::sendDown(SP<CWLSurfaceResource> surface, uint32_t timeMs,
|
||||||
if (!owner)
|
if (!owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (currentSurface) {
|
|
||||||
LOGM(WARN, "requested CWLTouchResource::sendDown without sendUp first.");
|
|
||||||
sendUp(timeMs, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(surface->client() == owner->client());
|
ASSERT(surface->client() == owner->client());
|
||||||
|
|
||||||
currentSurface = surface;
|
currentSurface = surface;
|
||||||
listeners.destroySurface = surface->events.destroy.registerListener([this, timeMs, id](std::any d) { sendUp(timeMs + 10 /* hack */, id); });
|
listeners.destroySurface = surface->events.destroy.registerListener([this, timeMs, id](std::any d) { sendUp(timeMs + 10 /* hack */, id); });
|
||||||
|
|
||||||
resource->sendDown(g_pSeatManager->nextSerial(owner.lock()), timeMs, surface->getResource().get(), id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y));
|
resource->sendDown(g_pSeatManager->nextSerial(owner.lock()), timeMs, surface->getResource().get(), id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y));
|
||||||
|
|
||||||
|
fingers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) {
|
void CWLTouchResource::sendUp(uint32_t timeMs, int32_t id) {
|
||||||
if (!owner || !currentSurface)
|
if (!owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resource->sendUp(g_pSeatManager->nextSerial(owner.lock()), timeMs, id);
|
resource->sendUp(g_pSeatManager->nextSerial(owner.lock()), timeMs, id);
|
||||||
currentSurface.reset();
|
fingers--;
|
||||||
listeners.destroySurface.reset();
|
if (fingers <= 0) {
|
||||||
|
currentSurface.reset();
|
||||||
|
listeners.destroySurface.reset();
|
||||||
|
fingers = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLTouchResource::sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local) {
|
void CWLTouchResource::sendMotion(uint32_t timeMs, int32_t id, const Vector2D& local) {
|
||||||
if (!owner || !currentSurface)
|
if (!owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resource->sendMotion(timeMs, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y));
|
resource->sendMotion(timeMs, id, wl_fixed_from_double(local.x), wl_fixed_from_double(local.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLTouchResource::sendFrame() {
|
void CWLTouchResource::sendFrame() {
|
||||||
if (!owner || !currentSurface)
|
if (!owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
resource->sendFrame();
|
resource->sendFrame();
|
||||||
|
@ -97,6 +98,9 @@ CWLPointerResource::CWLPointerResource(SP<CWlPointer> resource_, SP<CWLSeatResou
|
||||||
|
|
||||||
g_pSeatManager->onSetCursor(owner.lock(), serial, surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hotX, hotY});
|
g_pSeatManager->onSetCursor(owner.lock(), serial, surf ? CWLSurfaceResource::fromResource(surf) : nullptr, {hotX, hotY});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (g_pSeatManager->state.pointerFocus && g_pSeatManager->state.pointerFocus->client() == resource->client())
|
||||||
|
sendEnter(g_pSeatManager->state.pointerFocus.lock(), {-1, -1} /* Coords don't really matter that much, they will be updated next move */);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWLPointerResource::good() {
|
bool CWLPointerResource::good() {
|
||||||
|
@ -199,10 +203,16 @@ CWLKeyboardResource::CWLKeyboardResource(SP<CWlKeyboard> resource_, SP<CWLSeatRe
|
||||||
resource->setRelease([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); });
|
resource->setRelease([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); });
|
||||||
resource->setOnDestroy([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); });
|
resource->setOnDestroy([this](CWlKeyboard* r) { PROTO::seat->destroyResource(this); });
|
||||||
|
|
||||||
static auto REPEAT = CConfigValue<Hyprlang::INT>("input:repeat_rate");
|
if (!g_pSeatManager->keyboard) {
|
||||||
static auto DELAY = CConfigValue<Hyprlang::INT>("input:repeat_delay");
|
LOGM(ERR, "No keyboard on bound wl_keyboard??");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sendKeymap(g_pSeatManager->keyboard.lock());
|
sendKeymap(g_pSeatManager->keyboard.lock());
|
||||||
repeatInfo(*REPEAT, *DELAY);
|
repeatInfo(g_pSeatManager->keyboard->repeatRate, g_pSeatManager->keyboard->repeatDelay);
|
||||||
|
|
||||||
|
if (g_pSeatManager->state.keyboardFocus && g_pSeatManager->state.keyboardFocus->client() == resource->client())
|
||||||
|
sendEnter(g_pSeatManager->state.keyboardFocus.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWLKeyboardResource::good() {
|
bool CWLKeyboardResource::good() {
|
||||||
|
|
|
@ -46,6 +46,8 @@ class CWLTouchResource {
|
||||||
SP<CWlTouch> resource;
|
SP<CWlTouch> resource;
|
||||||
WP<CWLSurfaceResource> currentSurface;
|
WP<CWLSurfaceResource> currentSurface;
|
||||||
|
|
||||||
|
int fingers = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CHyprSignalListener destroySurface;
|
CHyprSignalListener destroySurface;
|
||||||
} listeners;
|
} listeners;
|
||||||
|
|
|
@ -79,20 +79,20 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||||
m_tGlobalTimer.reset();
|
m_tGlobalTimer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint64_t> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
std::optional<std::vector<uint64_t>> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
||||||
// TODO: return std::expected when clang supports it
|
// TODO: return std::expected when clang supports it
|
||||||
|
|
||||||
if (!m_sExts.EXT_image_dma_buf_import_modifiers)
|
if (!m_sExts.EXT_image_dma_buf_import_modifiers)
|
||||||
return {};
|
return std::nullopt;
|
||||||
|
|
||||||
EGLint len = 0;
|
EGLint len = 0;
|
||||||
if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) {
|
if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) {
|
||||||
Debug::log(ERR, "EGL: Failed to query mods");
|
Debug::log(ERR, "EGL: Failed to query mods");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return {DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID}; // assume the driver can do linear and implicit.
|
return std::vector<uint64_t>{};
|
||||||
|
|
||||||
std::vector<uint64_t> mods;
|
std::vector<uint64_t> mods;
|
||||||
std::vector<EGLBoolean> external;
|
std::vector<EGLBoolean> external;
|
||||||
|
@ -103,13 +103,21 @@ std::vector<uint64_t> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
||||||
m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len);
|
m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len);
|
||||||
|
|
||||||
std::vector<uint64_t> result;
|
std::vector<uint64_t> result;
|
||||||
|
bool linearIsExternal = false;
|
||||||
for (size_t i = 0; i < mods.size(); ++i) {
|
for (size_t i = 0; i < mods.size(); ++i) {
|
||||||
if (external.at(i))
|
if (external.at(i)) {
|
||||||
|
if (mods.at(i) == DRM_FORMAT_MOD_LINEAR)
|
||||||
|
linearIsExternal = true;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result.push_back(mods.at(i));
|
result.push_back(mods.at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the driver doesn't mark linear as external, add it. It's allowed unless the driver says otherwise. (e.g. nvidia)
|
||||||
|
if (!linearIsExternal && std::find(mods.begin(), mods.end(), DRM_FORMAT_MOD_LINEAR) == mods.end() && mods.size() == 0)
|
||||||
|
mods.push_back(DRM_FORMAT_MOD_LINEAR);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,15 +155,19 @@ void CHyprOpenGLImpl::initDRMFormats() {
|
||||||
|
|
||||||
for (auto& fmt : formats) {
|
for (auto& fmt : formats) {
|
||||||
std::vector<uint64_t> mods;
|
std::vector<uint64_t> mods;
|
||||||
if (!DISABLE_MODS)
|
if (!DISABLE_MODS) {
|
||||||
mods = getModsForFormat(fmt);
|
auto ret = getModsForFormat(fmt);
|
||||||
else
|
if (!ret.has_value())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mods = *ret;
|
||||||
|
} else
|
||||||
mods = {DRM_FORMAT_MOD_LINEAR};
|
mods = {DRM_FORMAT_MOD_LINEAR};
|
||||||
|
|
||||||
m_bHasModifiers = m_bHasModifiers || mods.size() > 0;
|
m_bHasModifiers = m_bHasModifiers || mods.size() > 0;
|
||||||
|
|
||||||
if (mods.size() == 0)
|
// EGL can always do implicit modifiers.
|
||||||
continue;
|
mods.push_back(DRM_FORMAT_MOD_INVALID);
|
||||||
|
|
||||||
dmaFormats.push_back(SDRMFormat{
|
dmaFormats.push_back(SDRMFormat{
|
||||||
.format = fmt,
|
.format = fmt,
|
||||||
|
|
|
@ -238,7 +238,9 @@ class CHyprOpenGLImpl {
|
||||||
void createBGTextureForMonitor(CMonitor*);
|
void createBGTextureForMonitor(CMonitor*);
|
||||||
void initShaders();
|
void initShaders();
|
||||||
void initDRMFormats();
|
void initDRMFormats();
|
||||||
std::vector<uint64_t> getModsForFormat(EGLint format);
|
|
||||||
|
//
|
||||||
|
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||||
|
|
||||||
// returns the out FB, can be either Mirror or MirrorSwap
|
// returns the out FB, can be either Mirror or MirrorSwap
|
||||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||||
|
|
|
@ -90,6 +90,11 @@ CHyprRenderer::CHyprRenderer() {
|
||||||
wl_event_source_timer_update(m_pCursorTicker, 500);
|
wl_event_source_timer_update(m_pCursorTicker, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHyprRenderer::~CHyprRenderer() {
|
||||||
|
if (m_pCursorTicker)
|
||||||
|
wl_event_source_remove(m_pCursorTicker);
|
||||||
|
}
|
||||||
|
|
||||||
static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* data) {
|
static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* data) {
|
||||||
if (!surface->current.buffer || !surface->current.buffer->texture)
|
if (!surface->current.buffer || !surface->current.buffer->texture)
|
||||||
return;
|
return;
|
||||||
|
@ -1253,6 +1258,15 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
TRACY_GPU_ZONE("Render");
|
TRACY_GPU_ZONE("Render");
|
||||||
|
|
||||||
|
static bool zoomLock = false;
|
||||||
|
if (zoomLock && *PZOOMFACTOR == 1.f) {
|
||||||
|
g_pPointerManager->unlockSoftwareAll();
|
||||||
|
zoomLock = false;
|
||||||
|
} else if (!zoomLock && *PZOOMFACTOR != 1.f) {
|
||||||
|
g_pPointerManager->lockSoftwareAll();
|
||||||
|
zoomLock = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (pMonitor == g_pCompositor->getMonitorFromCursor())
|
if (pMonitor == g_pCompositor->getMonitorFromCursor())
|
||||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY);
|
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY);
|
||||||
else
|
else
|
||||||
|
@ -1265,10 +1279,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
pMonitor->forceFullFrames = 10;
|
pMonitor->forceFullFrames = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f;
|
|
||||||
if (lockSoftware)
|
|
||||||
g_pPointerManager->lockSoftwareForMonitor(pMonitor->self.lock());
|
|
||||||
|
|
||||||
CRegion damage, finalDamage;
|
CRegion damage, finalDamage;
|
||||||
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
|
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
|
||||||
Debug::log(ERR, "renderer: couldn't beginRender()!");
|
Debug::log(ERR, "renderer: couldn't beginRender()!");
|
||||||
|
@ -1370,9 +1380,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
endRender();
|
endRender();
|
||||||
|
|
||||||
if (lockSoftware)
|
|
||||||
g_pPointerManager->unlockSoftwareForMonitor(pMonitor->self.lock());
|
|
||||||
|
|
||||||
TRACY_GPU_COLLECT;
|
TRACY_GPU_COLLECT;
|
||||||
|
|
||||||
if (!pMonitor->mirrors.empty()) {
|
if (!pMonitor->mirrors.empty()) {
|
||||||
|
@ -1756,7 +1763,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||||
Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName);
|
Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::damageBox(CBox* pBox) {
|
void CHyprRenderer::damageBox(CBox* pBox, bool skipFrameSchedule) {
|
||||||
if (g_pCompositor->m_bUnsafeState)
|
if (g_pCompositor->m_bUnsafeState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1766,7 +1773,8 @@ void CHyprRenderer::damageBox(CBox* pBox) {
|
||||||
|
|
||||||
CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||||
damageBox.scale(m->scale);
|
damageBox.scale(m->scale);
|
||||||
m->addDamage(&damageBox);
|
if (!skipFrameSchedule)
|
||||||
|
m->addDamage(&damageBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
|
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
|
||||||
|
|
|
@ -42,12 +42,13 @@ struct SSessionLockSurface;
|
||||||
class CHyprRenderer {
|
class CHyprRenderer {
|
||||||
public:
|
public:
|
||||||
CHyprRenderer();
|
CHyprRenderer();
|
||||||
|
~CHyprRenderer();
|
||||||
|
|
||||||
void renderMonitor(CMonitor* pMonitor);
|
void renderMonitor(CMonitor* pMonitor);
|
||||||
void arrangeLayersForMonitor(const int&);
|
void arrangeLayersForMonitor(const int&);
|
||||||
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
||||||
void damageWindow(PHLWINDOW, bool forceFull = false);
|
void damageWindow(PHLWINDOW, bool forceFull = false);
|
||||||
void damageBox(CBox*);
|
void damageBox(CBox*, bool skipFrameSchedule = false);
|
||||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||||
void damageRegion(const CRegion&);
|
void damageRegion(const CRegion&);
|
||||||
void damageMonitor(CMonitor*);
|
void damageMonitor(CMonitor*);
|
||||||
|
|
|
@ -119,15 +119,15 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||||
g_pDecorationPositioner->repositionDeco(this);
|
g_pDecorationPositioner->repositionDeco(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int xoff = 0;
|
float xoff = 0;
|
||||||
int yoff = 0;
|
float yoff = 0;
|
||||||
|
|
||||||
for (int i = 0; i < barsToDraw; ++i) {
|
for (int i = 0; i < barsToDraw; ++i) {
|
||||||
const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i;
|
const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i;
|
||||||
|
|
||||||
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
CBox rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
||||||
ASSIGNEDBOX.y + ASSIGNEDBOX.h - yoff - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y,
|
||||||
BAR_INDICATOR_HEIGHT};
|
m_fBarWidth, BAR_INDICATOR_HEIGHT};
|
||||||
|
|
||||||
if (rect.width <= 0 || rect.height <= 0)
|
if (rect.width <= 0 || rect.height <= 0)
|
||||||
break;
|
break;
|
||||||
|
@ -151,8 +151,8 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||||
color.a *= a;
|
color.a *= a;
|
||||||
g_pHyprOpenGL->renderRect(&rect, color);
|
g_pHyprOpenGL->renderRect(&rect, color);
|
||||||
|
|
||||||
rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
||||||
ASSIGNEDBOX.y + ASSIGNEDBOX.h - yoff - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
||||||
(*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)};
|
(*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)};
|
||||||
rect.scale(pMonitor->scale);
|
rect.scale(pMonitor->scale);
|
||||||
|
|
||||||
|
@ -172,10 +172,10 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||||
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
|
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
|
||||||
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale))
|
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale))
|
||||||
.get();
|
.get();
|
||||||
rect.y += ((rect.height - pTitleTex->textHeight) / 2.0) * pMonitor->scale;
|
rect.y += (rect.height - pTitleTex->textHeight) / 2.0;
|
||||||
rect.height = (pTitleTex->textHeight) * pMonitor->scale;
|
rect.height = pTitleTex->textHeight;
|
||||||
rect.width = pTitleTex->textWidth * pMonitor->scale;
|
rect.width = pTitleTex->textWidth;
|
||||||
rect.x += m_fBarWidth / 2.0 - (pTitleTex->textWidth / 2.0) * pMonitor->scale;
|
rect.x += (m_fBarWidth * pMonitor->scale) / 2.0 - (pTitleTex->textWidth / 2.0);
|
||||||
rect.round();
|
rect.round();
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
|
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
|
||||||
|
|
|
@ -155,6 +155,14 @@ static int xwaylandReady(int fd, uint32_t mask, void* data) {
|
||||||
return g_pXWayland->pServer->ready(fd, mask);
|
return g_pXWayland->pServer->ready(fd, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool safeRemove(const std::string& path) {
|
||||||
|
try {
|
||||||
|
return std::filesystem::remove(path);
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "[XWayland] failed to remove {}", path); }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CXWaylandServer::tryOpenSockets() {
|
bool CXWaylandServer::tryOpenSockets() {
|
||||||
for (size_t i = 0; i <= 32; ++i) {
|
for (size_t i = 0; i <= 32; ++i) {
|
||||||
auto LOCK = std::format("/tmp/.X{}-lock", i);
|
auto LOCK = std::format("/tmp/.X{}-lock", i);
|
||||||
|
@ -162,7 +170,7 @@ bool CXWaylandServer::tryOpenSockets() {
|
||||||
if (int fd = open(LOCK.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); fd >= 0) {
|
if (int fd = open(LOCK.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); fd >= 0) {
|
||||||
// we managed to open the lock
|
// we managed to open the lock
|
||||||
if (!openSockets(xFDs, i)) {
|
if (!openSockets(xFDs, i)) {
|
||||||
std::filesystem::remove(LOCK);
|
safeRemove(LOCK);
|
||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +178,7 @@ bool CXWaylandServer::tryOpenSockets() {
|
||||||
const auto PIDSTR = std::format("{}", getpid());
|
const auto PIDSTR = std::format("{}", getpid());
|
||||||
|
|
||||||
if (write(fd, PIDSTR.c_str(), PIDSTR.length()) != (long)PIDSTR.length()) {
|
if (write(fd, PIDSTR.c_str(), PIDSTR.length()) != (long)PIDSTR.length()) {
|
||||||
std::filesystem::remove(LOCK);
|
safeRemove(LOCK);
|
||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +205,7 @@ bool CXWaylandServer::tryOpenSockets() {
|
||||||
} catch (...) { continue; }
|
} catch (...) { continue; }
|
||||||
|
|
||||||
if (kill(pid, 0) != 0 && errno == ESRCH) {
|
if (kill(pid, 0) != 0 && errno == ESRCH) {
|
||||||
if (!std::filesystem::remove(LOCK))
|
if (!safeRemove(LOCK))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
i--;
|
i--;
|
||||||
|
@ -228,7 +236,7 @@ CXWaylandServer::~CXWaylandServer() {
|
||||||
close(xFDs[1]);
|
close(xFDs[1]);
|
||||||
|
|
||||||
auto LOCK = std::format("/tmp/.X{}-lock", display);
|
auto LOCK = std::format("/tmp/.X{}-lock", display);
|
||||||
std::filesystem::remove(LOCK);
|
safeRemove(LOCK);
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -236,7 +244,7 @@ CXWaylandServer::~CXWaylandServer() {
|
||||||
#else
|
#else
|
||||||
path = std::format("/tmp/.X11-unix/X{}_", display);
|
path = std::format("/tmp/.X11-unix/X{}_", display);
|
||||||
#endif
|
#endif
|
||||||
std::filesystem::remove(path);
|
safeRemove(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWaylandServer::die() {
|
void CXWaylandServer::die() {
|
||||||
|
|
|
@ -179,7 +179,7 @@ void CXWaylandSurface::configure(const CBox& box) {
|
||||||
void CXWaylandSurface::activate(bool activate) {
|
void CXWaylandSurface::activate(bool activate) {
|
||||||
if (overrideRedirect && !activate)
|
if (overrideRedirect && !activate)
|
||||||
return;
|
return;
|
||||||
g_pXWayland->pWM->activateSurface(self.lock());
|
g_pXWayland->pWM->activateSurface(self.lock(), activate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWaylandSurface::setFullscreen(bool fs) {
|
void CXWaylandSurface::setFullscreen(bool fs) {
|
||||||
|
|
|
@ -248,11 +248,11 @@ void CXWM::readProp(SP<CXWaylandSurface> XSURF, uint32_t atom, xcb_get_property_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "[xwm] Unhandled prop {} -> {}", atom, propName);
|
Debug::log(TRACE, "[xwm] Unhandled prop {} -> {}", atom, propName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "[xwm] Handled prop {} -> {}", atom, propName);
|
Debug::log(TRACE, "[xwm] Handled prop {} -> {}", atom, propName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::handlePropertyNotify(xcb_property_notify_event_t* e) {
|
void CXWM::handlePropertyNotify(xcb_property_notify_event_t* e) {
|
||||||
|
@ -354,11 +354,11 @@ void CXWM::handleClientMessage(xcb_client_message_event_t* e) {
|
||||||
} else if (e->type == HYPRATOMS["_NET_ACTIVE_WINDOW"]) {
|
} else if (e->type == HYPRATOMS["_NET_ACTIVE_WINDOW"]) {
|
||||||
XSURF->events.activate.emit();
|
XSURF->events.activate.emit();
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "[xwm] Unhandled message prop {} -> {}", e->type, propName);
|
Debug::log(TRACE, "[xwm] Unhandled message prop {} -> {}", e->type, propName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "[xwm] Handled message prop {} -> {}", e->type, propName);
|
Debug::log(TRACE, "[xwm] Handled message prop {} -> {}", e->type, propName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::handleFocusIn(xcb_focus_in_event_t* e) {
|
void CXWM::handleFocusIn(xcb_focus_in_event_t* e) {
|
||||||
|
@ -394,11 +394,16 @@ void CXWM::focusWindow(SP<CXWaylandSurface> surf) {
|
||||||
if (surf == focusedSurface)
|
if (surf == focusedSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto oldSurf = focusedSurface.lock();
|
|
||||||
focusedSurface = surf;
|
focusedSurface = surf;
|
||||||
|
|
||||||
if (oldSurf)
|
// send state to all surfaces, sometimes we might lose some
|
||||||
sendState(oldSurf);
|
// that could still stick with the focused atom
|
||||||
|
for (auto& s : mappedSurfaces) {
|
||||||
|
if (!s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sendState(s.lock());
|
||||||
|
}
|
||||||
|
|
||||||
if (!surf) {
|
if (!surf) {
|
||||||
xcb_set_input_focus_checked(connection, XCB_INPUT_FOCUS_POINTER_ROOT, XCB_NONE, XCB_CURRENT_TIME);
|
xcb_set_input_focus_checked(connection, XCB_INPUT_FOCUS_POINTER_ROOT, XCB_NONE, XCB_CURRENT_TIME);
|
||||||
|
@ -490,18 +495,18 @@ std::string CXWM::mimeFromAtom(xcb_atom_t atom) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) {
|
void CXWM::handleSelectionNotify(xcb_selection_notify_event_t* e) {
|
||||||
Debug::log(LOG, "[xwm] Selection notify for {} prop {} target {}", e->selection, e->property, e->target);
|
Debug::log(TRACE, "[xwm] Selection notify for {} prop {} target {}", e->selection, e->property, e->target);
|
||||||
|
|
||||||
SXSelection& sel = clipboard;
|
SXSelection& sel = clipboard;
|
||||||
|
|
||||||
if (e->property == XCB_ATOM_NONE) {
|
if (e->property == XCB_ATOM_NONE) {
|
||||||
if (sel.transfer) {
|
if (sel.transfer) {
|
||||||
Debug::log(ERR, "[xwm] converting selection failed");
|
Debug::log(TRACE, "[xwm] converting selection failed");
|
||||||
sel.transfer.reset();
|
sel.transfer.reset();
|
||||||
}
|
}
|
||||||
} else if (e->target == HYPRATOMS["TARGETS"]) {
|
} else if (e->target == HYPRATOMS["TARGETS"]) {
|
||||||
if (!focusedSurface) {
|
if (!focusedSurface) {
|
||||||
Debug::log(LOG, "[xwm] denying access to write to clipboard because no X client is in focus");
|
Debug::log(TRACE, "[xwm] denying access to write to clipboard because no X client is in focus");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +524,7 @@ bool CXWM::handleSelectionPropertyNotify(xcb_property_notify_event_t* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) {
|
void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) {
|
||||||
Debug::log(LOG, "[xwm] Selection request for {} prop {} target {} time {} requestor {} selection {}", e->selection, e->property, e->target, e->time, e->requestor,
|
Debug::log(TRACE, "[xwm] Selection request for {} prop {} target {} time {} requestor {} selection {}", e->selection, e->property, e->target, e->time, e->requestor,
|
||||||
e->selection);
|
e->selection);
|
||||||
|
|
||||||
SXSelection& sel = clipboard;
|
SXSelection& sel = clipboard;
|
||||||
|
@ -542,7 +547,7 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_pSeatManager->state.keyboardFocusResource || g_pSeatManager->state.keyboardFocusResource->client() != g_pXWayland->pServer->xwaylandClient) {
|
if (!g_pSeatManager->state.keyboardFocusResource || g_pSeatManager->state.keyboardFocusResource->client() != g_pXWayland->pServer->xwaylandClient) {
|
||||||
Debug::log(LOG, "[xwm] Ignoring clipboard access: xwayland not in focus");
|
Debug::log(TRACE, "[xwm] Ignoring clipboard access: xwayland not in focus");
|
||||||
selectionSendNotify(e, false);
|
selectionSendNotify(e, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -585,7 +590,7 @@ void CXWM::handleSelectionRequest(xcb_selection_request_event_t* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CXWM::handleSelectionXFixesNotify(xcb_xfixes_selection_notify_event_t* e) {
|
bool CXWM::handleSelectionXFixesNotify(xcb_xfixes_selection_notify_event_t* e) {
|
||||||
Debug::log(LOG, "[xwm] Selection xfixes notify for {}", e->selection);
|
Debug::log(TRACE, "[xwm] Selection xfixes notify for {}", e->selection);
|
||||||
|
|
||||||
// IMPORTANT: mind the g_pSeatManager below
|
// IMPORTANT: mind the g_pSeatManager below
|
||||||
SXSelection& sel = clipboard;
|
SXSelection& sel = clipboard;
|
||||||
|
@ -868,13 +873,17 @@ void CXWM::createWMWindow() {
|
||||||
xcb_set_selection_owner(connection, wmWindow, HYPRATOMS["_NET_WM_CM_S0"], XCB_CURRENT_TIME);
|
xcb_set_selection_owner(connection, wmWindow, HYPRATOMS["_NET_WM_CM_S0"], XCB_CURRENT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWM::activateSurface(SP<CXWaylandSurface> surf) {
|
void CXWM::activateSurface(SP<CXWaylandSurface> surf, bool activate) {
|
||||||
if (surf == focusedSurface || (surf && surf->overrideRedirect))
|
if ((surf == focusedSurface && activate) || (surf && surf->overrideRedirect))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setActiveWindow(surf ? surf->xID : (uint32_t)XCB_WINDOW_NONE);
|
if (!activate || !surf) {
|
||||||
|
setActiveWindow((uint32_t)XCB_WINDOW_NONE);
|
||||||
focusWindow(surf);
|
focusWindow(nullptr);
|
||||||
|
} else {
|
||||||
|
setActiveWindow(surf ? surf->xID : (uint32_t)XCB_WINDOW_NONE);
|
||||||
|
focusWindow(surf);
|
||||||
|
}
|
||||||
|
|
||||||
xcb_flush(connection);
|
xcb_flush(connection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
#include "../helpers/WLListener.hpp"
|
#include "../helpers/WLListener.hpp"
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class CXWM {
|
||||||
void setActiveWindow(xcb_window_t window);
|
void setActiveWindow(xcb_window_t window);
|
||||||
void sendState(SP<CXWaylandSurface> surf);
|
void sendState(SP<CXWaylandSurface> surf);
|
||||||
void focusWindow(SP<CXWaylandSurface> surf);
|
void focusWindow(SP<CXWaylandSurface> surf);
|
||||||
void activateSurface(SP<CXWaylandSurface> surf);
|
void activateSurface(SP<CXWaylandSurface> surf, bool activate);
|
||||||
bool isWMWindow(xcb_window_t w);
|
bool isWMWindow(xcb_window_t w);
|
||||||
|
|
||||||
void sendWMMessage(SP<CXWaylandSurface> surf, xcb_client_message_data_t* data, uint32_t mask);
|
void sendWMMessage(SP<CXWaylandSurface> surf, xcb_client_message_data_t* data, uint32_t mask);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue