mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 16:45:59 +01:00
Merge branch 'hyprwm:main' into main
This commit is contained in:
commit
7263d8cec7
140 changed files with 3586 additions and 2193 deletions
5
.github/workflows/ci.yaml
vendored
5
.github/workflows/ci.yaml
vendored
|
@ -3,6 +3,7 @@ name: Build Hyprland
|
|||
on: [push, pull_request, workflow_dispatch]
|
||||
jobs:
|
||||
gcc:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
@ -44,6 +45,7 @@ jobs:
|
|||
path: Hyprland.tar.xz
|
||||
|
||||
meson:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland with Meson (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
@ -64,6 +66,7 @@ jobs:
|
|||
run: ninja -C build
|
||||
|
||||
no-pch:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland without precompiled headers (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
@ -83,6 +86,7 @@ jobs:
|
|||
run: make nopch
|
||||
|
||||
noxwayland:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland in pure Wayland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
@ -103,6 +107,7 @@ jobs:
|
|||
run: make release
|
||||
|
||||
clang-format:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Code Style (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
|
6
.github/workflows/nix-build.yml
vendored
6
.github/workflows/nix-build.yml
vendored
|
@ -15,14 +15,14 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v26
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- uses: cachix/cachix-action@v12
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
|
2
.github/workflows/nix-ci.yml
vendored
2
.github/workflows/nix-ci.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
|||
secrets: inherit
|
||||
|
||||
build:
|
||||
if: always() && !cancelled() && !contains(needs.*.result, 'failure')
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure')
|
||||
needs: update-inputs
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
|
1
.github/workflows/security-checks.yml
vendored
1
.github/workflows/security-checks.yml
vendored
|
@ -4,6 +4,7 @@ on: [push, pull_request]
|
|||
|
||||
jobs:
|
||||
flawfinder:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: Flawfinder Checks
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.27)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Get version
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
string(STRIP ${VER_RAW} VER)
|
||||
|
@ -12,6 +9,9 @@ project(
|
|||
DESCRIPTION "A Modern C++ Wayland Compositor"
|
||||
VERSION ${VER})
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(HYPRLAND_VERSION ${VER})
|
||||
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
@ -49,8 +49,6 @@ endif()
|
|||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner)
|
||||
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir)
|
||||
|
@ -64,7 +62,7 @@ else()
|
|||
endif()
|
||||
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
|
@ -89,6 +87,12 @@ else()
|
|||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(
|
||||
hyprctl_deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
hyprutils>=0.2.1)
|
||||
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
|
@ -113,9 +117,10 @@ pkg_check_modules(
|
|||
libliftoff
|
||||
libudev
|
||||
gbm
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.0)
|
||||
hyprutils>=0.2.1)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
|
@ -232,30 +237,6 @@ target_link_libraries(Hyprland rt PkgConfig::deps)
|
|||
# used by `make installheaders`, to ensure the headers are generated
|
||||
add_custom_target(generate-protocol-headers)
|
||||
|
||||
function(protocol protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h
|
||||
COMMAND ${WaylandScanner} server-header ${path}
|
||||
protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c
|
||||
COMMAND ${WaylandScanner} private-code ${path}
|
||||
protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(
|
||||
Hyprland PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h
|
||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h)
|
||||
endfunction()
|
||||
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
|
@ -288,15 +269,11 @@ endfunction()
|
|||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
|
||||
libudis86 uuid)
|
||||
|
||||
protocol(
|
||||
"subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
|
||||
protocol(
|
||||
"unstable/text-input/text-input-unstable-v1.xml"
|
||||
"text-input-unstable-v1" false)
|
||||
|
||||
protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-toplevel-export-v1" true)
|
||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
|
@ -353,24 +330,27 @@ install(
|
|||
CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/hyprland
|
||||
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
|
||||
)")
|
||||
|
||||
# session file
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/wayland-sessions)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# allow Hyprland to find wallpapers
|
||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||
|
||||
# wallpapers
|
||||
file(GLOB_RECURSE WALLPAPERS "assets/wall*")
|
||||
install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland)
|
||||
install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# default config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/hyprland)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# portal config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/xdg-desktop-portal)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal)
|
||||
|
||||
# man pages
|
||||
file(GLOB_RECURSE MANPAGES "docs/*.1")
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.41.2
|
||||
0.42.0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
wallpapers = ['0', '1', '2']
|
||||
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
|
||||
|
|
36
flake.lock
36
flake.lock
|
@ -16,11 +16,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721992626,
|
||||
"narHash": "sha256-GFDSPWxOqEkNrbuSfyoQHGIaRhJNapn2Rv0EEmBGR9A=",
|
||||
"lastModified": 1723405438,
|
||||
"narHash": "sha256-bpmC2m7OhlDvqgQZdZ2jBLyeIkq/Jld3X4bqRAxBSp8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "f95d1509370b7f40ef356ff69a332bd0356ab044",
|
||||
"rev": "9312aa28271c91e5d67ecb9def527b2bbcff0e66",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -42,11 +42,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721330371,
|
||||
"narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=",
|
||||
"lastModified": 1722623071,
|
||||
"narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc",
|
||||
"rev": "912d56025f03d41b1ad29510c423757b4379eb1c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -67,11 +67,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1718746314,
|
||||
"narHash": "sha256-HUklK5u86w2Yh9dOkk4FdsL8eehcOZ95jPhLixGDRQY=",
|
||||
"lastModified": 1721326555,
|
||||
"narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "1b61f0093afff20ab44d88ad707aed8bf2215290",
|
||||
"rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -116,11 +116,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324102,
|
||||
"narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=",
|
||||
"lastModified": 1722869141,
|
||||
"narHash": "sha256-0KU4qhyMp441qfwbirNg3+wbm489KnEjXOz2I/RbeFs=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "962582a090bc233c4de9d9897f46794280288989",
|
||||
"rev": "0252fd13e78e60fb0da512a212e56007515a49f7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -154,11 +154,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1721924956,
|
||||
"narHash": "sha256-Sb1jlyRO+N8jBXEX9Pg9Z1Qb8Bw9QyOgLDNMEpmjZ2M=",
|
||||
"lastModified": 1723175592,
|
||||
"narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5ad6a14c6bf098e98800b091668718c336effc95",
|
||||
"rev": "5e0ca22929f3342b19569b21b2f3462f053e497b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -209,11 +209,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721755049,
|
||||
"narHash": "sha256-O17b38bQnmfxv7It3OnVYx7fp1seEdI7xxnw5vJFv30=",
|
||||
"lastModified": 1722365976,
|
||||
"narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "5555f467f68ce7cdf1060991c24263073b95e9da",
|
||||
"rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
devShells = eachSystem (system: {
|
||||
default =
|
||||
pkgsFor.${system}.mkShell.override {
|
||||
stdenv = pkgsFor.${system}.gcc13Stdenv;
|
||||
stdenv = pkgsFor.${system}.gcc14Stdenv;
|
||||
} {
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [
|
||||
|
|
|
@ -9,7 +9,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
|||
|
||||
add_executable(hyprctl "main.cpp")
|
||||
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::deps)
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprctl)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <regex>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
@ -113,7 +114,7 @@ int rollingRead(const int socket) {
|
|||
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||
int sizeWritten = 0;
|
||||
long sizeWritten = 0;
|
||||
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||
while (!sigintReceived) {
|
||||
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
||||
|
@ -141,7 +142,7 @@ int rollingRead(const int socket) {
|
|||
int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
auto t = timeval{.tv_sec = 1, .tv_usec = 0};
|
||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
||||
setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval));
|
||||
|
||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||
|
|
363
hyprpm/Makefile
Normal file
363
hyprpm/Makefile
Normal file
|
@ -0,0 +1,363 @@
|
|||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Unix Makefiles" Generator, CMake Version 3.29
|
||||
|
||||
# Default target executed when no arguments are given to make.
|
||||
default_target: all
|
||||
.PHONY : default_target
|
||||
|
||||
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
|
||||
.NOTPARALLEL:
|
||||
|
||||
#=============================================================================
|
||||
# Special targets provided by cmake.
|
||||
|
||||
# Disable implicit rules so canonical targets will work.
|
||||
.SUFFIXES:
|
||||
|
||||
# Disable VCS-based implicit rules.
|
||||
% : %,v
|
||||
|
||||
# Disable VCS-based implicit rules.
|
||||
% : RCS/%
|
||||
|
||||
# Disable VCS-based implicit rules.
|
||||
% : RCS/%,v
|
||||
|
||||
# Disable VCS-based implicit rules.
|
||||
% : SCCS/s.%
|
||||
|
||||
# Disable VCS-based implicit rules.
|
||||
% : s.%
|
||||
|
||||
.SUFFIXES: .hpux_make_needs_suffix_list
|
||||
|
||||
# Command-line flag to silence nested $(MAKE).
|
||||
$(VERBOSE)MAKESILENT = -s
|
||||
|
||||
#Suppress display of executed commands.
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
# A target that is always out of date.
|
||||
cmake_force:
|
||||
.PHONY : cmake_force
|
||||
|
||||
#=============================================================================
|
||||
# Set environment variables for the build.
|
||||
|
||||
# The shell in which to execute make rules.
|
||||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E rm -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
||||
# The top-level source directory on which CMake was run.
|
||||
CMAKE_SOURCE_DIR = /home/mihai/Documents/code/git/Hyprland
|
||||
|
||||
# The top-level build directory on which CMake was run.
|
||||
CMAKE_BINARY_DIR = /home/mihai/Documents/code/git/Hyprland
|
||||
|
||||
#=============================================================================
|
||||
# Targets provided globally by CMake.
|
||||
|
||||
# Special rule for the target package
|
||||
package: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool..."
|
||||
cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackConfig.cmake
|
||||
.PHONY : package
|
||||
|
||||
# Special rule for the target package
|
||||
package/fast: package
|
||||
.PHONY : package/fast
|
||||
|
||||
# Special rule for the target package_source
|
||||
package_source:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool for source..."
|
||||
cd /home/mihai/Documents/code/git/Hyprland && /nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cpack --config ./CPackSourceConfig.cmake /home/mihai/Documents/code/git/Hyprland/CPackSourceConfig.cmake
|
||||
.PHONY : package_source
|
||||
|
||||
# Special rule for the target package_source
|
||||
package_source/fast: package_source
|
||||
.PHONY : package_source/fast
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "No interactive CMake dialog available..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache/fast: edit_cache
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# Special rule for the target list_install_components
|
||||
list_install_components:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Available install components are: \"Unspecified\""
|
||||
.PHONY : list_install_components
|
||||
|
||||
# Special rule for the target list_install_components
|
||||
list_install_components/fast: list_install_components
|
||||
.PHONY : list_install_components/fast
|
||||
|
||||
# Special rule for the target install
|
||||
install: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install
|
||||
|
||||
# Special rule for the target install
|
||||
install/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install/fast
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local/fast
|
||||
|
||||
# Special rule for the target install/strip
|
||||
install/strip: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip
|
||||
|
||||
# Special rule for the target install/strip
|
||||
install/strip/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..."
|
||||
/nix/store/aqckch626lg0vxh41dabyzrq0jx7gdk5-cmake-3.29.6/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles /home/mihai/Documents/code/git/Hyprland/hyprpm//CMakeFiles/progress.marks
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/all
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /home/mihai/Documents/code/git/Hyprland/CMakeFiles 0
|
||||
.PHONY : all
|
||||
|
||||
# The main clean target
|
||||
clean:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/clean
|
||||
.PHONY : clean
|
||||
|
||||
# The main clean target
|
||||
clean/fast: clean
|
||||
.PHONY : clean/fast
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall: all
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall
|
||||
.PHONY : preinstall
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall/fast:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/preinstall
|
||||
.PHONY : preinstall/fast
|
||||
|
||||
# clear depends
|
||||
depend:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
|
||||
.PHONY : depend
|
||||
|
||||
# Convenience name for target.
|
||||
hyprpm/CMakeFiles/hyprpm.dir/rule:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 hyprpm/CMakeFiles/hyprpm.dir/rule
|
||||
.PHONY : hyprpm/CMakeFiles/hyprpm.dir/rule
|
||||
|
||||
# Convenience name for target.
|
||||
hyprpm: hyprpm/CMakeFiles/hyprpm.dir/rule
|
||||
.PHONY : hyprpm
|
||||
|
||||
# fast build rule for target.
|
||||
hyprpm/fast:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/build
|
||||
.PHONY : hyprpm/fast
|
||||
|
||||
src/core/DataState.o: src/core/DataState.cpp.o
|
||||
.PHONY : src/core/DataState.o
|
||||
|
||||
# target to build an object file
|
||||
src/core/DataState.cpp.o:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.o
|
||||
.PHONY : src/core/DataState.cpp.o
|
||||
|
||||
src/core/DataState.i: src/core/DataState.cpp.i
|
||||
.PHONY : src/core/DataState.i
|
||||
|
||||
# target to preprocess a source file
|
||||
src/core/DataState.cpp.i:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.i
|
||||
.PHONY : src/core/DataState.cpp.i
|
||||
|
||||
src/core/DataState.s: src/core/DataState.cpp.s
|
||||
.PHONY : src/core/DataState.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
src/core/DataState.cpp.s:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/DataState.cpp.s
|
||||
.PHONY : src/core/DataState.cpp.s
|
||||
|
||||
src/core/Manifest.o: src/core/Manifest.cpp.o
|
||||
.PHONY : src/core/Manifest.o
|
||||
|
||||
# target to build an object file
|
||||
src/core/Manifest.cpp.o:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.o
|
||||
.PHONY : src/core/Manifest.cpp.o
|
||||
|
||||
src/core/Manifest.i: src/core/Manifest.cpp.i
|
||||
.PHONY : src/core/Manifest.i
|
||||
|
||||
# target to preprocess a source file
|
||||
src/core/Manifest.cpp.i:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.i
|
||||
.PHONY : src/core/Manifest.cpp.i
|
||||
|
||||
src/core/Manifest.s: src/core/Manifest.cpp.s
|
||||
.PHONY : src/core/Manifest.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
src/core/Manifest.cpp.s:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/Manifest.cpp.s
|
||||
.PHONY : src/core/Manifest.cpp.s
|
||||
|
||||
src/core/PluginManager.o: src/core/PluginManager.cpp.o
|
||||
.PHONY : src/core/PluginManager.o
|
||||
|
||||
# target to build an object file
|
||||
src/core/PluginManager.cpp.o:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.o
|
||||
.PHONY : src/core/PluginManager.cpp.o
|
||||
|
||||
src/core/PluginManager.i: src/core/PluginManager.cpp.i
|
||||
.PHONY : src/core/PluginManager.i
|
||||
|
||||
# target to preprocess a source file
|
||||
src/core/PluginManager.cpp.i:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.i
|
||||
.PHONY : src/core/PluginManager.cpp.i
|
||||
|
||||
src/core/PluginManager.s: src/core/PluginManager.cpp.s
|
||||
.PHONY : src/core/PluginManager.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
src/core/PluginManager.cpp.s:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/core/PluginManager.cpp.s
|
||||
.PHONY : src/core/PluginManager.cpp.s
|
||||
|
||||
src/main.o: src/main.cpp.o
|
||||
.PHONY : src/main.o
|
||||
|
||||
# target to build an object file
|
||||
src/main.cpp.o:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.o
|
||||
.PHONY : src/main.cpp.o
|
||||
|
||||
src/main.i: src/main.cpp.i
|
||||
.PHONY : src/main.i
|
||||
|
||||
# target to preprocess a source file
|
||||
src/main.cpp.i:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.i
|
||||
.PHONY : src/main.cpp.i
|
||||
|
||||
src/main.s: src/main.cpp.s
|
||||
.PHONY : src/main.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
src/main.cpp.s:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/main.cpp.s
|
||||
.PHONY : src/main.cpp.s
|
||||
|
||||
src/progress/CProgressBar.o: src/progress/CProgressBar.cpp.o
|
||||
.PHONY : src/progress/CProgressBar.o
|
||||
|
||||
# target to build an object file
|
||||
src/progress/CProgressBar.cpp.o:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.o
|
||||
.PHONY : src/progress/CProgressBar.cpp.o
|
||||
|
||||
src/progress/CProgressBar.i: src/progress/CProgressBar.cpp.i
|
||||
.PHONY : src/progress/CProgressBar.i
|
||||
|
||||
# target to preprocess a source file
|
||||
src/progress/CProgressBar.cpp.i:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.i
|
||||
.PHONY : src/progress/CProgressBar.cpp.i
|
||||
|
||||
src/progress/CProgressBar.s: src/progress/CProgressBar.cpp.s
|
||||
.PHONY : src/progress/CProgressBar.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
src/progress/CProgressBar.cpp.s:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(MAKE) $(MAKESILENT) -f hyprpm/CMakeFiles/hyprpm.dir/build.make hyprpm/CMakeFiles/hyprpm.dir/src/progress/CProgressBar.cpp.s
|
||||
.PHONY : src/progress/CProgressBar.cpp.s
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
@echo "The following are some of the valid targets for this Makefile:"
|
||||
@echo "... all (the default if no target is provided)"
|
||||
@echo "... clean"
|
||||
@echo "... depend"
|
||||
@echo "... edit_cache"
|
||||
@echo "... install"
|
||||
@echo "... install/local"
|
||||
@echo "... install/strip"
|
||||
@echo "... list_install_components"
|
||||
@echo "... package"
|
||||
@echo "... package_source"
|
||||
@echo "... rebuild_cache"
|
||||
@echo "... hyprpm"
|
||||
@echo "... src/core/DataState.o"
|
||||
@echo "... src/core/DataState.i"
|
||||
@echo "... src/core/DataState.s"
|
||||
@echo "... src/core/Manifest.o"
|
||||
@echo "... src/core/Manifest.i"
|
||||
@echo "... src/core/Manifest.s"
|
||||
@echo "... src/core/PluginManager.o"
|
||||
@echo "... src/core/PluginManager.i"
|
||||
@echo "... src/core/PluginManager.s"
|
||||
@echo "... src/main.o"
|
||||
@echo "... src/main.i"
|
||||
@echo "... src/main.s"
|
||||
@echo "... src/progress/CProgressBar.o"
|
||||
@echo "... src/progress/CProgressBar.i"
|
||||
@echo "... src/progress/CProgressBar.s"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets to cleanup operation of make.
|
||||
|
||||
# Special rule to run CMake to check the build system integrity.
|
||||
# No rule that depends on this can have commands that come from listfiles
|
||||
# because they might be regenerated.
|
||||
cmake_check_build_system:
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -P /home/mihai/Documents/code/git/Hyprland/CMakeFiles/VerifyGlobs.cmake
|
||||
cd /home/mihai/Documents/code/git/Hyprland && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
.PHONY : cmake_check_build_system
|
||||
|
|
@ -464,12 +464,22 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
progress.m_szCurrentMessage = "Checking out sources";
|
||||
progress.print();
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.branch + " 2>&1");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
if (ret.contains("fatal: unable to read tree")) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET
|
||||
<< " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret);
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret);
|
||||
|
@ -529,7 +539,8 @@ bool CPluginManager::updateHeaders(bool force) {
|
|||
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" +
|
||||
headerErrorShort(HEADERSVALID) + ")");
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Failed";
|
||||
progress.print();
|
||||
|
@ -880,6 +891,18 @@ std::string CPluginManager::headerError(const eHeadersErrors err) {
|
|||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
|
||||
}
|
||||
|
||||
std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
switch (err) {
|
||||
case HEADERS_CORRUPTED: return "Headers corrupted";
|
||||
case HEADERS_MISMATCHED: return "Headers version mismatched";
|
||||
case HEADERS_NOT_HYPRLAND: return "Not running on Hyprland";
|
||||
case HEADERS_MISSING: return "Headers missing";
|
||||
case HEADERS_DUPLICATED: return "Headers duplicated";
|
||||
default: break;
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
bool CPluginManager::hasDeps() {
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake"};
|
||||
for (auto& d : deps) {
|
||||
|
|
|
@ -66,6 +66,7 @@ class CPluginManager {
|
|||
|
||||
private:
|
||||
std::string headerError(const eHeadersErrors err);
|
||||
std::string headerErrorShort(const eHeadersErrors err);
|
||||
|
||||
std::string m_szWorkingPluginDirectory = "";
|
||||
};
|
||||
|
|
|
@ -6,9 +6,10 @@ project('Hyprland', 'cpp', 'c',
|
|||
'optimization=3',
|
||||
'buildtype=release',
|
||||
'debug=false',
|
||||
'cpp_std=c++23',
|
||||
'cpp_std=c++26',
|
||||
])
|
||||
|
||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Wno-unused-parameter',
|
||||
|
@ -16,6 +17,7 @@ add_project_arguments(
|
|||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
datarootdir,
|
||||
],
|
||||
language: 'cpp')
|
||||
|
||||
|
@ -32,6 +34,8 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
|
|||
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
|
||||
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
|
||||
|
||||
gio_dep = dependency('gio-2.0', required:true)
|
||||
|
||||
cmake = import('cmake')
|
||||
udis = cmake.subproject('udis86')
|
||||
udis86 = udis.dependency('libudis86')
|
||||
|
|
|
@ -71,6 +71,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
|||
src = lib.cleanSource ../.;
|
||||
};
|
||||
|
||||
patches = [
|
||||
# forces GCC to use -std=c++26
|
||||
./stdcxx.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
# Fix hardcoded paths to /usr installation
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
|
|
|
@ -31,7 +31,7 @@ in {
|
|||
date = mkDate (self.lastModifiedDate or "19700101");
|
||||
in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
stdenv = final.gcc14Stdenv;
|
||||
version = "${version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
commit = self.rev or "";
|
||||
inherit date;
|
||||
|
|
12
nix/stdcxx.patch
Normal file
12
nix/stdcxx.patch
Normal file
|
@ -0,0 +1,12 @@
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index cfbd431f..73e8e0c2 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -64,6 +64,7 @@ endif()
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
+ -std=c++26
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
|
@ -12,22 +12,12 @@ hyprland_protos = dependency('hyprland-protocols',
|
|||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
|
||||
wayland_scanner_dep = dependency('wayland-scanner', native: true)
|
||||
wayland_scanner = find_program(
|
||||
wayland_scanner_dep.get_variable('wayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
|
||||
hyprwayland_scanner = find_program(
|
||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
protocols = [
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml']
|
||||
]
|
||||
|
||||
new_protocols = [
|
||||
['wlr-gamma-control-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
|
@ -41,6 +31,7 @@ new_protocols = [
|
|||
['wayland-drm.xml'],
|
||||
['wlr-data-control-unstable-v1.xml'],
|
||||
['wlr-screencopy-unstable-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
|
@ -55,6 +46,7 @@ new_protocols = [
|
|||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
|
||||
|
@ -73,24 +65,6 @@ new_protocols = [
|
|||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
|
||||
foreach p : protocols
|
||||
xml = join_paths(p)
|
||||
wl_protos_src += custom_target(
|
||||
xml.underscorify() + '_server_c',
|
||||
input: xml,
|
||||
output: '@BASENAME@-protocol.c',
|
||||
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
wl_protos_headers += custom_target(
|
||||
xml.underscorify() + '_server_h',
|
||||
input: xml,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('includedir'), 'hyprland/protocols'),
|
||||
output: '@BASENAME@-protocol.h',
|
||||
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
new_wl_protos = []
|
||||
foreach p : new_protocols
|
||||
xml = join_paths(p)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "managers/SeatManager.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <bit>
|
||||
#include <random>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
|
@ -247,7 +248,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
|||
|
||||
if (!m_pAqBackend) {
|
||||
Debug::log(CRIT,
|
||||
"m_pAqBackend was null! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a Wayland "
|
||||
"m_pAqBackend was null! This usually means aquamarine could not find a GPU or encountered some issues. Make sure you're running either on a tty or on a Wayland "
|
||||
"session, NOT an X11 one.");
|
||||
throwError("CBackend::create() failed!");
|
||||
}
|
||||
|
@ -258,7 +259,7 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
|||
|
||||
if (!m_pAqBackend->start()) {
|
||||
Debug::log(CRIT,
|
||||
"m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a "
|
||||
"m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or encountered some issues. Make sure you're running either on a tty or on a "
|
||||
"Wayland session, NOT an X11 one.");
|
||||
throwError("CBackend::create() failed!");
|
||||
}
|
||||
|
@ -518,6 +519,8 @@ void CCompositor::cleanup() {
|
|||
|
||||
// this frees all wayland resources, including sockets
|
||||
wl_display_destroy(m_sWLDisplay);
|
||||
|
||||
Debug::close();
|
||||
}
|
||||
|
||||
void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
|
@ -549,6 +552,10 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
|||
|
||||
g_pConfigManager->init();
|
||||
g_pWatchdog = std::make_unique<CWatchdog>(); // requires config
|
||||
// wait for watchdog to initialize to not hit data races in reading config values.
|
||||
while (!g_pWatchdog->m_bWatchdogInitialized) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Creating the PointerManager!");
|
||||
g_pPointerManager = std::make_unique<CPointerManager>();
|
||||
|
@ -680,9 +687,9 @@ void CCompositor::startCompositor() {
|
|||
g_pEventLoopManager->enterLoop();
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromID(const int& id) {
|
||||
CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->ID == (uint64_t)id) {
|
||||
if (m->ID == id) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +781,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
|||
if (properties & ALLOW_FLOATING) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowBoxUnified(properties);
|
||||
CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0);
|
||||
CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0);
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
|
||||
w != pIgnoreWindow) {
|
||||
if (box.containsPoint(g_pPointerManager->position()))
|
||||
|
@ -804,7 +811,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
|||
BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y)
|
||||
continue;
|
||||
|
||||
CBox box = BB.copy().expand(w->m_iX11Type == 2 ? BORDER_GRAB_AREA : 0);
|
||||
CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0);
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
|
||||
w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
|
||||
// OR windows should add focus to parent
|
||||
|
@ -842,8 +849,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
|||
if (properties & FLOATING_ONLY)
|
||||
return floating(false);
|
||||
|
||||
const int64_t WORKSPACEID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
|
||||
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID);
|
||||
const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
|
||||
const auto PWORKSPACE = getWorkspaceByID(WSPID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
@ -857,7 +864,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
|||
if (special != w->onSpecialWorkspace())
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w;
|
||||
|
@ -869,7 +876,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
|||
continue;
|
||||
|
||||
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow)
|
||||
return w;
|
||||
}
|
||||
|
@ -1204,9 +1211,9 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
|
||||
PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() == ID && w->m_bIsFullscreen)
|
||||
if (w->workspaceID() == ID && w->isFullscreen())
|
||||
return w;
|
||||
}
|
||||
|
||||
|
@ -1228,7 +1235,7 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) {
|
|||
return PMONITOR->activeWorkspace->m_iID == w->m_iID;
|
||||
}
|
||||
|
||||
PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) {
|
||||
PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) {
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_iID == id && !w->inert())
|
||||
return w;
|
||||
|
@ -1252,7 +1259,7 @@ void CCompositor::sanityCheckWorkspaces() {
|
|||
}
|
||||
}
|
||||
|
||||
int CCompositor::getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() != id || !w->m_bIsMapped)
|
||||
|
@ -1267,7 +1274,7 @@ int CCompositor::getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTi
|
|||
return no;
|
||||
}
|
||||
|
||||
int CCompositor::getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
|
||||
int no = 0;
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() != id || !w->m_bIsMapped)
|
||||
|
@ -1292,7 +1299,7 @@ PHLWINDOW CCompositor::getUrgentWindow() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) {
|
||||
bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent)
|
||||
return true;
|
||||
|
@ -1301,7 +1308,7 @@ bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) {
|
|||
return false;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) {
|
||||
PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden())
|
||||
return w;
|
||||
|
@ -1310,7 +1317,7 @@ PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) {
|
||||
PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
|
@ -1398,12 +1405,12 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
|
|||
}
|
||||
}
|
||||
|
||||
void CCompositor::cleanupFadingOut(const int& monid) {
|
||||
void CCompositor::cleanupFadingOut(const MONITORID& monid) {
|
||||
for (auto& ww : m_vWindowsFadingOut) {
|
||||
|
||||
auto w = ww.lock();
|
||||
|
||||
if (w->m_iMonitorID != (long unsigned int)monid)
|
||||
if (w->m_iMonitorID != monid)
|
||||
continue;
|
||||
|
||||
if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) {
|
||||
|
@ -1422,12 +1429,16 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
|||
}
|
||||
}
|
||||
|
||||
bool layersDirty = false;
|
||||
|
||||
for (auto& lsr : m_vSurfacesFadingOut) {
|
||||
|
||||
auto ls = lsr.lock();
|
||||
|
||||
if (!ls)
|
||||
if (!ls) {
|
||||
layersDirty = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ls->monitorID != monid)
|
||||
continue;
|
||||
|
@ -1440,7 +1451,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
|||
for (auto& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
||||
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) {
|
||||
std::erase_if(lsl, [&](auto& other) { return other == ls; });
|
||||
std::erase_if(lsl, [&](auto& other) { return other == ls || !other; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1456,6 +1467,9 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (layersDirty)
|
||||
std::erase_if(m_vSurfacesFadingOut, [](const auto& el) { return el.expired(); });
|
||||
}
|
||||
|
||||
void CCompositor::addToFadingOutSafe(PHLLS pLS) {
|
||||
|
@ -1494,7 +1508,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
|||
if (!PMONITOR)
|
||||
return nullptr; // ??
|
||||
|
||||
const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
|
@ -1507,13 +1521,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
|||
|
||||
// for tiled windows, we calc edges
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
continue;
|
||||
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace)
|
||||
continue;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID)
|
||||
|
@ -1599,13 +1613,13 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
|
|||
constexpr float THRESHOLD = 0.3 * M_PI;
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
||||
continue;
|
||||
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace)
|
||||
continue;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
if (!*PMONITORFALLBACK && pWindow->m_iMonitorID != w->m_iMonitorID)
|
||||
|
@ -1692,8 +1706,8 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int CCompositor::getNextAvailableNamedWorkspace() {
|
||||
int lowest = -1337 + 1;
|
||||
WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
|
||||
WORKSPACEID lowest = -1337 + 1;
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_iID < -1 && w->m_iID < lowest)
|
||||
lowest = w->m_iID;
|
||||
|
@ -1887,7 +1901,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
|||
|
||||
// opacity
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
|
||||
} else {
|
||||
if (pWindow == m_pLastWindow)
|
||||
|
@ -1917,18 +1931,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
|||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
int CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
||||
if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
|
||||
return m_mMonitorIDMap[name];
|
||||
|
||||
// otherwise, find minimum available ID that is not in the map
|
||||
std::unordered_set<uint64_t> usedIDs;
|
||||
std::unordered_set<MONITORID> usedIDs;
|
||||
for (auto const& monitor : m_vRealMonitors) {
|
||||
usedIDs.insert(monitor->ID);
|
||||
}
|
||||
|
||||
uint64_t nextID = 0;
|
||||
MONITORID nextID = 0;
|
||||
while (usedIDs.count(nextID) > 0) {
|
||||
nextID++;
|
||||
}
|
||||
|
@ -1957,7 +1971,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
if (w->isFullscreen()) {
|
||||
w->m_vRealPosition = pMonitorB->vecPosition;
|
||||
w->m_vRealSize = pMonitorB->vecSize;
|
||||
}
|
||||
|
@ -1982,7 +1996,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
|||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
if (w->isFullscreen()) {
|
||||
w->m_vRealPosition = pMonitorA->vecPosition;
|
||||
w->m_vRealSize = pMonitorA->vecSize;
|
||||
}
|
||||
|
@ -2068,7 +2082,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
|||
return m_vMonitors[currentPlace].get();
|
||||
} else if (isNumber(name)) {
|
||||
// change by ID
|
||||
int monID = -1;
|
||||
MONITORID monID = MONITOR_INVALID;
|
||||
try {
|
||||
monID = std::stoi(name);
|
||||
} catch (std::exception& e) {
|
||||
|
@ -2077,7 +2091,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (monID > -1 && monID < (int)m_vMonitors.size()) {
|
||||
if (monID > -1 && monID < (MONITORID)m_vMonitors.size()) {
|
||||
return getMonitorFromID(monID);
|
||||
} else {
|
||||
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
|
||||
|
@ -2111,7 +2125,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
|
|||
const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false;
|
||||
|
||||
// fix old mon
|
||||
int nextWorkspaceOnMonitorID = -1;
|
||||
WORKSPACEID nextWorkspaceOnMonitorID = WORKSPACE_INVALID;
|
||||
if (!SWITCHINGISACTIVE)
|
||||
nextWorkspaceOnMonitorID = pWorkspace->m_iID;
|
||||
else {
|
||||
|
@ -2122,7 +2136,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
|
|||
}
|
||||
}
|
||||
|
||||
if (nextWorkspaceOnMonitorID == -1) {
|
||||
if (nextWorkspaceOnMonitorID == WORKSPACE_INVALID) {
|
||||
nextWorkspaceOnMonitorID = 1;
|
||||
|
||||
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool {
|
||||
|
@ -2159,7 +2173,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
|
|||
if (w->m_bIsFloating)
|
||||
w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition;
|
||||
|
||||
if (w->m_bIsFullscreen) {
|
||||
if (w->isFullscreen()) {
|
||||
w->m_vRealPosition = pMonitor->vecPosition;
|
||||
w->m_vRealSize = pMonitor->vecSize;
|
||||
}
|
||||
|
@ -2209,9 +2223,9 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
|
|||
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{pWorkspace, pMonitor}));
|
||||
}
|
||||
|
||||
bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) {
|
||||
int64_t lowestID = INT64_MAX;
|
||||
int64_t highestID = INT64_MIN;
|
||||
bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) {
|
||||
WORKSPACEID lowestID = INT64_MAX;
|
||||
WORKSPACEID highestID = INT64_MIN;
|
||||
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_bIsSpecialWorkspace)
|
||||
|
@ -2234,12 +2248,12 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
|
|||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace == pWorkspace) {
|
||||
|
||||
if (w->m_bFadingOut || w->m_bPinned || w->m_bIsFullscreen)
|
||||
if (w->m_bFadingOut || w->m_bPinned || w->isFullscreen())
|
||||
continue;
|
||||
|
||||
if (!FULLSCREEN)
|
||||
w->m_fAlpha = 1.f;
|
||||
else if (!w->m_bIsFullscreen)
|
||||
else if (!w->isFullscreen())
|
||||
w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f;
|
||||
}
|
||||
}
|
||||
|
@ -2249,54 +2263,87 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
|
|||
if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) {
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (!ls->fadingOut)
|
||||
ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f;
|
||||
ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMode mode) {
|
||||
static auto PNODIRECTSCANOUT = CConfigValue<Hyprlang::INT>("misc:no_direct_scanout");
|
||||
void CCompositor::changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) {
|
||||
setWindowFullscreenInternal(
|
||||
PWINDOW, (eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.internal | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.internal & (uint8_t)~MODE)));
|
||||
}
|
||||
|
||||
if (!validMapped(pWindow) || g_pCompositor->m_bUnsafeState)
|
||||
void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) {
|
||||
setWindowFullscreenClient(PWINDOW,
|
||||
(eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.client | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.client & (uint8_t)~MODE)));
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||
if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE});
|
||||
else
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||
if (PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = MODE, .client = MODE});
|
||||
else
|
||||
setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = MODE});
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenState state) {
|
||||
static auto PDIRECTSCANOUT = CConfigValue<Hyprlang::INT>("render:direct_scanout");
|
||||
|
||||
if (!validMapped(PWINDOW) || g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned) {
|
||||
Debug::log(LOG, "Pinned windows cannot be fullscreen'd");
|
||||
state.internal = std::clamp(state.internal, (eFullscreenMode)0, FSMODE_MAX);
|
||||
state.client = std::clamp(state.client, (eFullscreenMode)0, FSMODE_MAX);
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
const auto PWORKSPACE = PWINDOW->m_pWorkspace;
|
||||
|
||||
const eFullscreenMode CURRENT_EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)PWINDOW->m_sFullscreenState.internal);
|
||||
const eFullscreenMode EFFECTIVE_MODE = (eFullscreenMode)std::bit_floor((uint8_t)state.internal);
|
||||
|
||||
const bool CHANGEINTERNAL = !(PWINDOW->m_bPinned || CURRENT_EFFECTIVE_MODE == EFFECTIVE_MODE || (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen()));
|
||||
|
||||
// TODO: update the state on syncFullscreen changes
|
||||
if (!CHANGEINTERNAL && PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bIsFullscreen == on) {
|
||||
Debug::log(LOG, "Window is already in the required fullscreen state");
|
||||
PWINDOW->m_sFullscreenState.client = state.client;
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN);
|
||||
|
||||
if (!CHANGEINTERNAL)
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE);
|
||||
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
PWINDOW->m_sFullscreenState.internal = state.internal;
|
||||
PWORKSPACE->m_efFullscreenMode = EFFECTIVE_MODE;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = EFFECTIVE_MODE != FSMODE_NONE;
|
||||
|
||||
const auto MODE = mode == FULLSCREEN_INVALID ? PWORKSPACE->m_efFullscreenMode : mode;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)EFFECTIVE_MODE != FSMODE_NONE)});
|
||||
EMIT_HOOK_EVENT("fullscreen", PWINDOW);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on);
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState());
|
||||
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
PWINDOW->updateDynamicRules();
|
||||
PWINDOW->updateWindowDecos();
|
||||
updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->m_pWorkspace == PWORKSPACE && !w->m_bIsFullscreen && !w->m_bFadingOut && !w->m_bPinned)
|
||||
if (w->m_pWorkspace == PWORKSPACE && !w->isFullscreen() && !w->m_bFadingOut && !w->m_bPinned)
|
||||
w->m_bCreatedOverFullscreen = false;
|
||||
}
|
||||
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACE);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal(), true);
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
|
||||
|
||||
forceReportSizesToWindowsOnWorkspace(pWindow->workspaceID());
|
||||
forceReportSizesToWindowsOnWorkspace(PWINDOW->workspaceID());
|
||||
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
|
@ -2306,8 +2353,8 @@ void CCompositor::setWindowFullscreen(PHLWINDOW pWindow, bool on, eFullscreenMod
|
|||
|
||||
// send a scanout tranche if we are entering fullscreen, and send a regular one if we aren't.
|
||||
// ignore if DS is disabled.
|
||||
if (!*PNODIRECTSCANOUT)
|
||||
g_pHyprRenderer->setSurfaceScanoutMode(pWindow->m_pWLSurface->resource(), on ? PMONITOR->self.lock() : nullptr);
|
||||
if (*PDIRECTSCANOUT)
|
||||
g_pHyprRenderer->setSurfaceScanoutMode(PWINDOW->m_pWLSurface->resource(), EFFECTIVE_MODE != FSMODE_NONE ? PMONITOR->self.lock() : nullptr);
|
||||
|
||||
g_pConfigManager->ensureVRR(PMONITOR);
|
||||
}
|
||||
|
@ -2327,7 +2374,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::updateWorkspaceWindowDecos(const int& id) {
|
||||
void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() != id)
|
||||
continue;
|
||||
|
@ -2336,7 +2383,7 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) {
|
|||
}
|
||||
}
|
||||
|
||||
void CCompositor::updateWorkspaceWindowData(const int& id) {
|
||||
void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
|
||||
|
@ -2556,7 +2603,7 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
|
|||
return Vector2D(X, Y);
|
||||
}
|
||||
|
||||
void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
|
||||
void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) {
|
||||
g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true);
|
||||
|
@ -2564,7 +2611,7 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
|
|||
}
|
||||
}
|
||||
|
||||
PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name, bool isEmtpy) {
|
||||
PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmtpy) {
|
||||
const auto NAME = name == "" ? std::to_string(id) : name;
|
||||
auto monID = monid;
|
||||
|
||||
|
@ -2582,7 +2629,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, co
|
|||
return PWORKSPACE;
|
||||
}
|
||||
|
||||
void CCompositor::renameWorkspace(const int& id, const std::string& name) {
|
||||
void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(id);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
|
@ -2613,12 +2660,12 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
|
|||
m_pLastMonitor = pMonitor->self;
|
||||
}
|
||||
|
||||
bool CCompositor::isWorkspaceSpecial(const int& id) {
|
||||
bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) {
|
||||
return id >= SPECIAL_WORKSPACE_START && id <= -2;
|
||||
}
|
||||
|
||||
int CCompositor::getNewSpecialID() {
|
||||
int highest = SPECIAL_WORKSPACE_START;
|
||||
WORKSPACEID CCompositor::getNewSpecialID() {
|
||||
WORKSPACEID highest = SPECIAL_WORKSPACE_START;
|
||||
for (auto& ws : m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) {
|
||||
highest = ws->m_iID;
|
||||
|
@ -2639,11 +2686,11 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
|||
if (pWindow->m_bPinned && pWorkspace->m_bIsSpecialWorkspace)
|
||||
return;
|
||||
|
||||
const bool FULLSCREEN = pWindow->m_bIsFullscreen;
|
||||
const auto FULLSCREENMODE = pWindow->m_pWorkspace->m_efFullscreenMode;
|
||||
const bool FULLSCREEN = pWindow->isFullscreen();
|
||||
const auto FULLSCREENMODE = pWindow->m_sFullscreenState.internal;
|
||||
|
||||
if (FULLSCREEN)
|
||||
setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow);
|
||||
|
@ -2676,7 +2723,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
|||
}
|
||||
|
||||
if (FULLSCREEN)
|
||||
setWindowFullscreen(pWindow, true, FULLSCREENMODE);
|
||||
setWindowFullscreenInternal(pWindow, FULLSCREENMODE);
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID);
|
||||
g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID());
|
||||
|
@ -2875,39 +2922,6 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
|
|||
return {};
|
||||
}
|
||||
|
||||
static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitorName) {
|
||||
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
|
||||
static auto firstMonitorAdded = std::chrono::system_clock::now();
|
||||
static bool cursorDefaultDone = false;
|
||||
static bool firstLaunch = true;
|
||||
|
||||
const auto POS = PNEWMONITOR->middle();
|
||||
|
||||
// by default, cursor should be set to first monitor detected
|
||||
// this is needed as a default if the monitor given in config above doesn't exist
|
||||
if (firstLaunch) {
|
||||
firstLaunch = false;
|
||||
g_pCompositor->warpCursorTo(POS, true);
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY)
|
||||
return;
|
||||
|
||||
// after 10s, don't set cursor to default monitor
|
||||
auto timePassedSec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - firstMonitorAdded);
|
||||
if (timePassedSec.count() > 10) {
|
||||
cursorDefaultDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*PCURSORMONITOR == monitorName) {
|
||||
cursorDefaultDone = true;
|
||||
g_pCompositor->warpCursorTo(POS, true);
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
||||
// add it to real
|
||||
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>());
|
||||
|
@ -2922,7 +2936,7 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
|||
PNEWMONITOR->output = output;
|
||||
PNEWMONITOR->self = PNEWMONITOR;
|
||||
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false;
|
||||
PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name);
|
||||
PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name);
|
||||
PNEWMONITOR->isUnsafeFallback = FALLBACK;
|
||||
|
||||
EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR);
|
||||
|
@ -2943,11 +2957,9 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
|||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR);
|
||||
|
||||
checkDefaultCursorWarp(PNEWMONITOR, output->name);
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||
w->m_iLastSurfaceMonitorID = -1;
|
||||
w->m_iLastSurfaceMonitorID = MONITOR_INVALID;
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,55 +46,55 @@ class CCompositor {
|
|||
CCompositor();
|
||||
~CCompositor();
|
||||
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
int m_iDRMFD = -1;
|
||||
bool m_bInitialized = false;
|
||||
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
int m_iDRMFD = -1;
|
||||
bool m_bInitialized = false;
|
||||
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||
|
||||
std::string m_szHyprTempDataRoot = "";
|
||||
std::string m_szHyprTempDataRoot = "";
|
||||
|
||||
std::string m_szWLDisplaySocket = "";
|
||||
std::string m_szInstanceSignature = "";
|
||||
std::string m_szInstancePath = "";
|
||||
std::string m_szCurrentSplash = "error";
|
||||
std::string m_szWLDisplaySocket = "";
|
||||
std::string m_szInstanceSignature = "";
|
||||
std::string m_szInstancePath = "";
|
||||
std::string m_szCurrentSplash = "error";
|
||||
|
||||
std::vector<SP<CMonitor>> m_vMonitors;
|
||||
std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<PHLWINDOW> m_vWindows;
|
||||
std::vector<PHLLS> m_vLayers;
|
||||
std::vector<PHLWORKSPACE> m_vWorkspaces;
|
||||
std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
|
||||
std::vector<PHLLSREF> m_vSurfacesFadingOut;
|
||||
std::vector<SP<CMonitor>> m_vMonitors;
|
||||
std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<PHLWINDOW> m_vWindows;
|
||||
std::vector<PHLLS> m_vLayers;
|
||||
std::vector<PHLWORKSPACE> m_vWorkspaces;
|
||||
std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
|
||||
std::vector<PHLLSREF> m_vSurfacesFadingOut;
|
||||
|
||||
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||
std::unordered_map<std::string, MONITORID> m_mMonitorIDMap;
|
||||
|
||||
void initServer(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
void stopCompositor();
|
||||
void cleanup();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void bumpNofile();
|
||||
void restoreNofile();
|
||||
void initServer(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
void stopCompositor();
|
||||
void cleanup();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void bumpNofile();
|
||||
void restoreNofile();
|
||||
|
||||
WP<CWLSurfaceResource> m_pLastFocus;
|
||||
PHLWINDOWREF m_pLastWindow;
|
||||
WP<CMonitor> m_pLastMonitor;
|
||||
WP<CWLSurfaceResource> m_pLastFocus;
|
||||
PHLWINDOWREF m_pLastWindow;
|
||||
WP<CMonitor> m_pLastMonitor;
|
||||
|
||||
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromID(const MONITORID&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
|
@ -114,39 +114,43 @@ class CCompositor {
|
|||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
void updateWorkspaceWindowData(const int&);
|
||||
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
void updateWorkspaceWindowDecos(const WORKSPACEID&);
|
||||
void updateWorkspaceWindowData(const WORKSPACEID&);
|
||||
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const int&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const int&);
|
||||
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
|
||||
bool isWindowActive(PHLWINDOW);
|
||||
void changeWindowZOrder(PHLWINDOW, bool);
|
||||
void cleanupFadingOut(const int& monid);
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
int getNextAvailableNamedWorkspace();
|
||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWorkspaceWindows(const WORKSPACEID& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
void setWindowFullscreen(PHLWINDOW, bool, eFullscreenMode mode = FULLSCREEN_INVALID);
|
||||
bool workspaceIDOutOfBounds(const WORKSPACEID&);
|
||||
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state);
|
||||
void changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void updateFullscreenFadeOnWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW getX11Parent(PHLWINDOW);
|
||||
void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
|
||||
|
@ -158,12 +162,13 @@ class CCompositor {
|
|||
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
|
||||
void closeWindow(PHLWINDOW);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const int&, const std::string& name = "");
|
||||
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmtpy = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
|
||||
void setActiveMonitor(CMonitor*);
|
||||
bool isWorkspaceSpecial(const int&);
|
||||
int getNewSpecialID();
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
|
||||
PHLWINDOW getForceFocus();
|
||||
|
|
|
@ -52,4 +52,8 @@ struct SHyprCtlCommand {
|
|||
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||
};
|
||||
|
||||
typedef int64_t WINDOWID;
|
||||
typedef int64_t MONITORID;
|
||||
typedef int64_t WORKSPACEID;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "config/ConfigDataValues.hpp"
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "helpers/varlist/VarList.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
|
||||
|
@ -346,7 +347,6 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("misc:swallow_regex", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("misc:swallow_exception_regex", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("misc:focus_on_activate", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("misc:no_direct_scanout", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:mouse_move_focuses_monitor", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:render_ahead_of_time", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("misc:render_ahead_safezone", Hyprlang::INT{1});
|
||||
|
@ -533,7 +533,7 @@ CConfigManager::CConfigManager() {
|
|||
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:inactive_timeout", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f});
|
||||
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0});
|
||||
|
@ -541,6 +541,7 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
|
||||
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0});
|
||||
|
@ -562,7 +563,9 @@ CConfigManager::CConfigManager() {
|
|||
m_pConfig->addConfigValue("group:groupbar:col.locked_active", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66ff5500"});
|
||||
m_pConfig->addConfigValue("group:groupbar:col.locked_inactive", Hyprlang::CConfigCustomValueType{&configHandleGradientSet, configHandleGradientDestroy, "0x66775500"});
|
||||
|
||||
m_pConfig->addConfigValue("experimental:explicit_sync", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("render:explicit_sync", Hyprlang::INT{2});
|
||||
m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2});
|
||||
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
|
||||
|
||||
// devices
|
||||
m_pConfig->addSpecialCategory("device", {"name"});
|
||||
|
@ -644,7 +647,7 @@ std::optional<std::string> CConfigManager::generateConfig(std::string configPath
|
|||
Debug::log(WARN, "Creating config home directory");
|
||||
try {
|
||||
std::filesystem::create_directories(parentPath);
|
||||
} catch (std::exception e) { throw e; }
|
||||
} catch (std::exception& e) { throw e; }
|
||||
}
|
||||
|
||||
Debug::log(WARN, "No config file found; attempting to generate.");
|
||||
|
@ -800,6 +803,9 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
|
|||
}
|
||||
|
||||
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static int prevEnabledExplicit = *PENABLEEXPLICIT;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
w->uncacheWindowDecos();
|
||||
}
|
||||
|
@ -830,6 +836,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
|||
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)
|
||||
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
|
||||
CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
|
||||
else if (*PENABLEEXPLICIT != prevEnabledExplicit)
|
||||
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
|
||||
|
@ -918,7 +926,10 @@ void CConfigManager::init() {
|
|||
}
|
||||
|
||||
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) {
|
||||
const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str());
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static int prevEnabledExplicit = *PENABLEEXPLICIT;
|
||||
|
||||
const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str());
|
||||
|
||||
// invalidate layouts if they changed
|
||||
if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) {
|
||||
|
@ -926,6 +937,13 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
|||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
|
||||
if (COMMAND.contains("explicit")) {
|
||||
if (*PENABLEEXPLICIT != prevEnabledExplicit)
|
||||
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
|
||||
else
|
||||
g_pHyprError->destroy();
|
||||
}
|
||||
|
||||
// Update window border colors
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
|
@ -1102,7 +1120,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
|
|||
|
||||
// since some rules will be applied later, we need to store some flags
|
||||
bool hasFloating = pWindow->m_bIsFloating;
|
||||
bool hasFullscreen = pWindow->m_bIsFullscreen;
|
||||
bool hasFullscreen = pWindow->isFullscreen();
|
||||
|
||||
// local tags for dynamic tag rule match
|
||||
auto tags = pWindow->m_tags;
|
||||
|
@ -1419,7 +1437,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
|
||||
if (USEVRR == 0) {
|
||||
if (m->vrrActive) {
|
||||
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(false);
|
||||
|
||||
if (!m->state.commit())
|
||||
|
@ -1429,6 +1447,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
return;
|
||||
} else if (USEVRR == 1) {
|
||||
if (!m->vrrActive) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(true);
|
||||
|
||||
if (!m->state.test()) {
|
||||
|
@ -1450,9 +1469,10 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
if (!PWORKSPACE)
|
||||
return; // ???
|
||||
|
||||
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && (PWORKSPACE->m_efFullscreenMode & FSMODE_FULLSCREEN);
|
||||
|
||||
if (WORKSPACEFULL) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(true);
|
||||
|
||||
if (!m->state.test()) {
|
||||
|
@ -1464,6 +1484,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
|||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
||||
|
||||
} else if (!WORKSPACEFULL) {
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setAdaptiveSync(false);
|
||||
|
||||
if (!m->state.commit())
|
||||
|
@ -2101,11 +2122,11 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
|
|||
|
||||
bool windowRuleValid(const std::string& RULE) {
|
||||
static const auto rules = std::unordered_set<std::string>{
|
||||
"fakefullscreen", "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile",
|
||||
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile",
|
||||
};
|
||||
static const auto rulesPrefix = std::vector<std::string>{
|
||||
"animation", "bordercolor", "bordersize", "center", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move",
|
||||
"opacity", "plugin:", "pseudo", "rounding", "size", "suppressevent", "tag", "workspace", "xray",
|
||||
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor",
|
||||
"move", "opacity", "plugin:", "pseudo", "rounding", "size", "suppressevent", "tag", "workspace", "xray",
|
||||
};
|
||||
|
||||
const auto VALS = CVarList(RULE, 2, ' ');
|
||||
|
@ -2416,7 +2437,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
|
|||
// }
|
||||
|
||||
const static std::string ruleOnCreatedEmpty = "on-created-empty:";
|
||||
const static int ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length();
|
||||
const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length();
|
||||
|
||||
auto assignRule = [&](std::string rule) -> std::optional<std::string> {
|
||||
size_t delim = std::string::npos;
|
||||
|
|
|
@ -33,7 +33,7 @@ struct SWorkspaceRule {
|
|||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
WORKSPACEID workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
|
@ -182,6 +182,7 @@ class CConfigManager {
|
|||
{"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }},
|
||||
{"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }},
|
||||
{"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }},
|
||||
{"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }},
|
||||
{"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }},
|
||||
{"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }},
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@ using namespace Hyprutils::String;
|
|||
#include "../devices/IKeyboard.hpp"
|
||||
#include "../devices/ITouch.hpp"
|
||||
#include "../devices/Tablet.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "debug/RollingLogFollow.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "helpers/MiscFunctions.hpp"
|
||||
|
@ -70,7 +71,7 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor
|
|||
|
||||
std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
|
||||
std::string result;
|
||||
if (!m->output || m->ID == -1ull)
|
||||
if (!m->output || m->ID == -1)
|
||||
return "";
|
||||
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
|
@ -154,7 +155,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
|||
result += "]";
|
||||
} else {
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output || m->ID == -1ull)
|
||||
if (!m->output || m->ID == -1)
|
||||
continue;
|
||||
|
||||
result +=
|
||||
|
@ -239,8 +240,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
|||
"xwayland": {},
|
||||
"pinned": {},
|
||||
"fullscreen": {},
|
||||
"fullscreenMode": {},
|
||||
"fakeFullscreen": {},
|
||||
"fullscreenClient": {},
|
||||
"grouped": [{}],
|
||||
"tags": [{}],
|
||||
"swallowing": "0x{:x}",
|
||||
|
@ -251,19 +251,19 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
|||
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"),
|
||||
(int64_t)w->m_iMonitorID, escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass),
|
||||
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
|
||||
(w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0),
|
||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
(uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format),
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
} else {
|
||||
return std::format(
|
||||
"Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName),
|
||||
(int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(),
|
||||
(int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0),
|
||||
(int)w->m_bFakeFullscreenState, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
(int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format),
|
||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -776,7 +776,7 @@ std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request)
|
|||
|
||||
std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
||||
const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts();
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& sh : SHORTCUTS)
|
||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||
|
@ -1604,6 +1604,10 @@ CHyprCtl::CHyprCtl() {
|
|||
CHyprCtl::~CHyprCtl() {
|
||||
if (m_eventSource)
|
||||
wl_event_source_remove(m_eventSource);
|
||||
if (m_iSocketFD >= 0)
|
||||
close(m_iSocketFD);
|
||||
if (!m_socketPath.empty())
|
||||
unlink(m_socketPath.c_str());
|
||||
}
|
||||
|
||||
SP<SHyprCtlCommand> CHyprCtl::registerCommand(SHyprCtlCommand cmd) {
|
||||
|
@ -1821,9 +1825,9 @@ void CHyprCtl::startHyprCtlSocket() {
|
|||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
|
||||
std::string socketPath = g_pCompositor->m_szInstancePath + "/.socket.sock";
|
||||
m_socketPath = g_pCompositor->m_szInstancePath + "/.socket.sock";
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str());
|
||||
|
||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
||||
|
@ -1833,7 +1837,7 @@ void CHyprCtl::startHyprCtlSocket() {
|
|||
// 10 max queued.
|
||||
listen(m_iSocketFD, 10);
|
||||
|
||||
Debug::log(LOG, "Hypr socket started at {}", socketPath);
|
||||
Debug::log(LOG, "Hypr socket started at {}", m_socketPath);
|
||||
|
||||
m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ class CHyprCtl {
|
|||
|
||||
std::vector<SP<SHyprCtlCommand>> m_vCommands;
|
||||
wl_event_source* m_eventSource = nullptr;
|
||||
std::string m_socketPath;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
||||
|
|
|
@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
|
|||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimes.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
|
@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
|||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
|
@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||
return posY - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
|
|
|
@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay {
|
|||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(CMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||
void renderData(CMonitor* pMonitor, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
|
||||
void frameData(CMonitor* pMonitor);
|
||||
|
||||
private:
|
||||
|
@ -33,8 +33,8 @@ class CHyprDebugOverlay {
|
|||
public:
|
||||
CHyprDebugOverlay();
|
||||
void draw();
|
||||
void renderData(CMonitor*, float µs);
|
||||
void renderDataNoOverlay(CMonitor*, float µs);
|
||||
void renderData(CMonitor*, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor*, float durationUs);
|
||||
void frameData(CMonitor*);
|
||||
|
||||
private:
|
||||
|
|
|
@ -5,9 +5,17 @@
|
|||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
|
||||
void Debug::init(const std::string& IS) {
|
||||
logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||
logOfs.open(logFile, std::ios::out | std::ios::app);
|
||||
auto handle = logOfs.native_handle();
|
||||
fcntl(handle, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
void Debug::close() {
|
||||
logOfs.close();
|
||||
}
|
||||
|
||||
void Debug::log(LogLevel level, std::string str) {
|
||||
|
@ -55,11 +63,8 @@ void Debug::log(LogLevel level, std::string str) {
|
|||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << str << "\n";
|
||||
|
||||
ofs.close();
|
||||
logOfs << str << "\n";
|
||||
logOfs.flush();
|
||||
}
|
||||
|
||||
// log it to the stdout too.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
|
@ -22,6 +23,7 @@ enum LogLevel {
|
|||
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline std::ofstream logOfs;
|
||||
inline int64_t* const* disableLogs = nullptr;
|
||||
inline int64_t* const* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
|
@ -30,14 +32,18 @@ namespace Debug {
|
|||
inline int64_t* const* coloredLogs = nullptr;
|
||||
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
inline std::mutex logMutex;
|
||||
|
||||
void init(const std::string& IS);
|
||||
void close();
|
||||
|
||||
//
|
||||
void log(LogLevel level, std::string str);
|
||||
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
std::lock_guard<std::mutex> guard(logMutex);
|
||||
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
|
|
|
@ -111,6 +111,11 @@ void CLayerSurface::onDestroy() {
|
|||
layerSurface.reset();
|
||||
if (surface)
|
||||
surface->unassign();
|
||||
|
||||
listeners.unmap.reset();
|
||||
listeners.destroy.reset();
|
||||
listeners.map.reset();
|
||||
listeners.commit.reset();
|
||||
}
|
||||
|
||||
void CLayerSurface::onMap() {
|
||||
|
@ -119,6 +124,8 @@ void CLayerSurface::onMap() {
|
|||
mapped = true;
|
||||
interactivity = layerSurface->current.interactivity;
|
||||
|
||||
layerSurface->surface->map();
|
||||
|
||||
// this layer might be re-mapped.
|
||||
fadingOut = false;
|
||||
g_pCompositor->removeFromFadingOutSafe(self.lock());
|
||||
|
@ -163,7 +170,7 @@ void CLayerSurface::onMap() {
|
|||
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
const auto WORKSPACE = PMONITOR->activeWorkspace;
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN;
|
||||
|
||||
startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||
readyToDelete = false;
|
||||
|
@ -190,6 +197,8 @@ void CLayerSurface::onUnmap() {
|
|||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
|
||||
mapped = false;
|
||||
if (layerSurface && layerSurface->surface)
|
||||
layerSurface->surface->unmap();
|
||||
|
||||
startAnimation(false);
|
||||
return;
|
||||
|
@ -201,6 +210,8 @@ void CLayerSurface::onUnmap() {
|
|||
startAnimation(false);
|
||||
|
||||
mapped = false;
|
||||
if (layerSurface && layerSurface->surface)
|
||||
layerSurface->surface->unmap();
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(self.lock());
|
||||
|
||||
|
@ -213,7 +224,7 @@ void CLayerSurface::onUnmap() {
|
|||
|
||||
// refocus if needed
|
||||
// vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window
|
||||
if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable()))
|
||||
if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable()))
|
||||
g_pInputManager->refocusLastWindow(PMONITOR);
|
||||
else if (g_pCompositor->m_pLastFocus)
|
||||
g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock());
|
||||
|
@ -236,7 +247,7 @@ void CLayerSurface::onCommit() {
|
|||
|
||||
if (!mapped) {
|
||||
// we're re-mapping if this is the case
|
||||
if (layerSurface->surface && !layerSurface->surface->current.buffer) {
|
||||
if (layerSurface->surface && !layerSurface->surface->current.texture) {
|
||||
fadingOut = false;
|
||||
geometry = {};
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
|
||||
|
@ -421,8 +432,8 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
|
|||
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2},
|
||||
};
|
||||
|
||||
float closest = std::numeric_limits<float>::max();
|
||||
int leader = force;
|
||||
float closest = std::numeric_limits<float>::max();
|
||||
size_t leader = force;
|
||||
if (leader == -1) {
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
float dist = MIDDLE.distance(edgePoints[i]);
|
||||
|
|
|
@ -42,7 +42,7 @@ class CLayerSurface {
|
|||
bool mapped = false;
|
||||
uint32_t layer = 0;
|
||||
|
||||
int monitorID = -1;
|
||||
MONITORID monitorID = -1;
|
||||
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
|
@ -51,7 +51,7 @@ class CLayerSurface {
|
|||
|
||||
bool forceBlur = false;
|
||||
bool forceBlurPopups = false;
|
||||
int xray = -1;
|
||||
int64_t xray = -1;
|
||||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
bool dimAround = false;
|
||||
|
|
|
@ -22,7 +22,7 @@ CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner),
|
|||
m_pWindowOwner = pOwner->m_pWindowOwner;
|
||||
|
||||
m_vLastSize = popup->surface->current.geometry.size();
|
||||
unconstrain();
|
||||
reposition();
|
||||
|
||||
initAllSignals();
|
||||
}
|
||||
|
@ -188,18 +188,18 @@ void CPopup::onReposition() {
|
|||
|
||||
m_vLastPos = coordsRelativeToParent();
|
||||
|
||||
unconstrain();
|
||||
reposition();
|
||||
}
|
||||
|
||||
void CPopup::unconstrain() {
|
||||
void CPopup::reposition() {
|
||||
const auto COORDS = t1ParentCoords();
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition);
|
||||
CBox box = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
m_pResource->applyPositioning(box, COORDS);
|
||||
}
|
||||
|
||||
Vector2D CPopup::coordsRelativeToParent() {
|
||||
|
|
|
@ -74,11 +74,11 @@ class CPopup {
|
|||
} listeners;
|
||||
|
||||
void initAllSignals();
|
||||
void unconstrain();
|
||||
void reposition();
|
||||
void recheckChildrenRecursive();
|
||||
void sendScale();
|
||||
|
||||
Vector2D localToGlobal(const Vector2D& rel);
|
||||
Vector2D t1ParentCoords();
|
||||
static void bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -57,12 +57,12 @@ bool CWLSurface::small() const {
|
|||
if (!validMapped(m_pWindowOwner) || !exists())
|
||||
return false;
|
||||
|
||||
if (!m_pResource->current.buffer)
|
||||
if (!m_pResource->current.texture)
|
||||
return false;
|
||||
|
||||
const auto O = m_pWindowOwner.lock();
|
||||
|
||||
return O->m_vReportedSize.x > m_pResource->current.buffer->size.x + 1 || O->m_vReportedSize.y > m_pResource->current.buffer->size.y + 1;
|
||||
return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
|
@ -76,37 +76,36 @@ Vector2D CWLSurface::correctSmallVec() const {
|
|||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVecBuf() const {
|
||||
if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.buffer)
|
||||
if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
const auto SIZE = getViewporterCorrectedSize();
|
||||
const auto BS = m_pResource->current.buffer->size;
|
||||
const auto BS = m_pResource->current.bufferSize;
|
||||
|
||||
return Vector2D{(BS.x - SIZE.x) / 2, (BS.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY});
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
if (!exists() || !m_pResource->current.buffer)
|
||||
if (!exists() || !m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size;
|
||||
return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.bufferSize;
|
||||
}
|
||||
|
||||
CRegion CWLSurface::computeDamage() const {
|
||||
if (!m_pResource->current.buffer)
|
||||
if (!m_pResource->current.texture)
|
||||
return {};
|
||||
|
||||
CRegion damage = m_pResource->accumulateCurrentBufferDamage();
|
||||
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y);
|
||||
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.bufferSize.x, m_pResource->current.bufferSize.y);
|
||||
|
||||
const auto BUFSIZE = m_pResource->current.buffer->size;
|
||||
const auto BUFSIZE = m_pResource->current.bufferSize;
|
||||
const auto CORRECTVEC = correctSmallVecBuf();
|
||||
|
||||
if (m_pResource->current.viewport.hasSource)
|
||||
damage.intersect(m_pResource->current.viewport.source);
|
||||
|
||||
const auto SCALEDSRCSIZE =
|
||||
m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.buffer->size;
|
||||
const auto SCALEDSRCSIZE = m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.bufferSize;
|
||||
|
||||
damage.scale({BUFSIZE.x / SCALEDSRCSIZE.x, BUFSIZE.y / SCALEDSRCSIZE.y});
|
||||
damage.translate(CORRECTVEC);
|
||||
|
@ -114,7 +113,7 @@ CRegion CWLSurface::computeDamage() const {
|
|||
// go from buffer coords in the damage to hl logical
|
||||
|
||||
const auto BOX = getSurfaceBoxGlobal();
|
||||
const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.buffer->size :
|
||||
const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.bufferSize :
|
||||
Vector2D{1.0 / m_pResource->current.scale, 1.0 / m_pResource->current.scale /* Wrong... but we can't really do better */};
|
||||
|
||||
damage.scale(SCALE);
|
||||
|
@ -227,7 +226,7 @@ SP<CWLSurface> CWLSurface::fromResource(SP<CWLSurfaceResource> pSurface) {
|
|||
bool CWLSurface::keyboardFocusable() const {
|
||||
if (m_pWindowOwner || m_pPopupOwner || m_pSubsurfaceOwner)
|
||||
return true;
|
||||
if (m_pLayerOwner)
|
||||
if (m_pLayerOwner && m_pLayerOwner->layerSurface)
|
||||
return m_pLayerOwner->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <any>
|
||||
#include <bit>
|
||||
#include <string_view>
|
||||
#include <algorithm>
|
||||
#include "Window.hpp"
|
||||
|
@ -192,7 +193,7 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||
auto POS = m_vPosition;
|
||||
auto SIZE = m_vSize;
|
||||
|
||||
if (m_bIsFullscreen) {
|
||||
if (isFullscreen()) {
|
||||
POS = PMONITOR->vecPosition;
|
||||
SIZE = PMONITOR->vecSize;
|
||||
|
||||
|
@ -477,13 +478,7 @@ void unregisterVar(void* ptr) {
|
|||
|
||||
void CWindow::onUnmap() {
|
||||
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
||||
|
||||
if (g_pCompositor->m_pLastWindow.lock().get() == this)
|
||||
g_pCompositor->m_pLastWindow.reset();
|
||||
if (g_pInputManager->currentlyDraggedWindow.lock().get() == this)
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
|
||||
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||
|
||||
if (!m_szInitialWorkspaceToken.empty()) {
|
||||
const auto TOKEN = g_pTokenManager->getToken(m_szInitialWorkspaceToken);
|
||||
|
@ -976,8 +971,9 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
|||
return;
|
||||
|
||||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.client;
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
|
@ -985,7 +981,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
|||
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
|
||||
g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
|
||||
|
||||
PCURRENT->setHidden(true);
|
||||
pWindow->setHidden(false); // can remove m_pLastWindow
|
||||
|
@ -1003,7 +999,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
|||
g_pCompositor->focusWindow(pWindow);
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, MODE);
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
||||
|
@ -1102,18 +1098,18 @@ bool CWindow::opaque() {
|
|||
if (PWORKSPACE->m_fAlpha.value() != 1.f)
|
||||
return false;
|
||||
|
||||
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer)
|
||||
return m_pXWaylandSurface->surface->current.buffer->opaque;
|
||||
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture)
|
||||
return m_pXWaylandSurface->surface->current.texture->m_bOpaque;
|
||||
|
||||
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
|
||||
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.texture)
|
||||
return false;
|
||||
|
||||
// TODO: this is wrong
|
||||
const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents();
|
||||
if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y)
|
||||
if (EXTENTS.w >= m_pXDGSurface->surface->current.bufferSize.x && EXTENTS.h >= m_pXDGSurface->surface->current.bufferSize.y)
|
||||
return true;
|
||||
|
||||
return m_pWLSurface->resource()->current.buffer->opaque;
|
||||
return m_pWLSurface->resource()->current.texture->m_bOpaque;
|
||||
}
|
||||
|
||||
float CWindow::rounding() {
|
||||
|
@ -1146,7 +1142,7 @@ void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
|
|||
}
|
||||
|
||||
int CWindow::getRealBorderSize() {
|
||||
if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL)))
|
||||
if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)))
|
||||
return 0;
|
||||
|
||||
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
||||
|
@ -1159,11 +1155,6 @@ bool CWindow::canBeTorn() {
|
|||
return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING;
|
||||
}
|
||||
|
||||
bool CWindow::shouldSendFullscreenState() {
|
||||
const auto MODE = m_pWorkspace->m_efFullscreenMode;
|
||||
return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)));
|
||||
}
|
||||
|
||||
void CWindow::setSuspended(bool suspend) {
|
||||
if (suspend == m_bSuspended)
|
||||
return;
|
||||
|
@ -1190,7 +1181,7 @@ void CWindow::setAnimationsToMove() {
|
|||
|
||||
void CWindow::onWorkspaceAnimUpdate() {
|
||||
// clip box for animated offsets
|
||||
if (!m_bIsFloating || m_bPinned || m_bIsFullscreen) {
|
||||
if (!m_bIsFloating || m_bPinned || isFullscreen()) {
|
||||
m_vFloatingOffset = Vector2D(0, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -1244,7 +1235,15 @@ int CWindow::surfacesCount() {
|
|||
return no;
|
||||
}
|
||||
|
||||
int CWindow::workspaceID() {
|
||||
bool CWindow::isFullscreen() {
|
||||
return m_sFullscreenState.internal != FSMODE_NONE;
|
||||
}
|
||||
|
||||
bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
|
||||
return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE;
|
||||
}
|
||||
|
||||
WORKSPACEID CWindow::workspaceID() {
|
||||
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
|
||||
}
|
||||
|
||||
|
@ -1321,19 +1320,17 @@ void CWindow::onUpdateState() {
|
|||
|
||||
if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) {
|
||||
bool fs = requestsFS.value();
|
||||
|
||||
if (fs != m_bIsFullscreen && m_bIsMapped)
|
||||
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_FULL);
|
||||
if (m_bIsMapped) {
|
||||
g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value());
|
||||
}
|
||||
|
||||
if (!m_bIsMapped)
|
||||
m_bWantsInitialFullscreen = fs;
|
||||
}
|
||||
|
||||
if (requestsMX.has_value() && !(m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) {
|
||||
bool fs = requestsMX.value();
|
||||
|
||||
if (fs != m_bIsFullscreen && m_bIsMapped)
|
||||
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_MAXIMIZED);
|
||||
if (m_bIsMapped)
|
||||
g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_MAXIMIZED, requestsMX.value());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1438,7 +1435,7 @@ void CWindow::onX11Configure(CBox box) {
|
|||
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
|
||||
if (!m_bIsFloating || m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
||||
if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
||||
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true);
|
||||
g_pInputManager->refocus();
|
||||
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Popup.hpp"
|
||||
#include "Subsurface.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "Workspace.hpp"
|
||||
|
||||
class CXDGSurfaceResource;
|
||||
class CXWaylandSurface;
|
||||
|
@ -170,6 +171,7 @@ struct SWindowData {
|
|||
CWindowOverridableVar<bool> noShortcutsInhibit = false;
|
||||
CWindowOverridableVar<bool> opaque = false;
|
||||
CWindowOverridableVar<bool> RGBX = false;
|
||||
CWindowOverridableVar<bool> syncFullscreen = true;
|
||||
CWindowOverridableVar<bool> tearing = false;
|
||||
CWindowOverridableVar<bool> xray = false;
|
||||
|
||||
|
@ -208,6 +210,11 @@ struct SInitialWorkspaceToken {
|
|||
std::string workspace;
|
||||
};
|
||||
|
||||
struct sFullscreenState {
|
||||
eFullscreenMode internal = FSMODE_NONE;
|
||||
eFullscreenMode client = FSMODE_NONE;
|
||||
};
|
||||
|
||||
class CWindow {
|
||||
public:
|
||||
static PHLWINDOW create(SP<CXDGSurfaceResource>);
|
||||
|
@ -256,24 +263,23 @@ class CWindow {
|
|||
Vector2D m_vPseudoSize = Vector2D(1280, 720);
|
||||
|
||||
// for recovering relative cursor position
|
||||
Vector2D m_vRelativeCursorCoordsOnLastWarp = Vector2D(-1, -1);
|
||||
Vector2D m_vRelativeCursorCoordsOnLastWarp = Vector2D(-1, -1);
|
||||
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
bool m_bDontSendFullscreen = false;
|
||||
bool m_bWasMaximized = false;
|
||||
uint64_t m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
std::string m_szInitialClass = "";
|
||||
PHLWORKSPACE m_pWorkspace;
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bWasMaximized = false;
|
||||
sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
|
||||
MONITORID m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szClass = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
std::string m_szInitialClass = "";
|
||||
PHLWORKSPACE m_pWorkspace;
|
||||
|
||||
bool m_bIsMapped = false;
|
||||
bool m_bIsMapped = false;
|
||||
|
||||
bool m_bRequestsFloat = false;
|
||||
bool m_bRequestsFloat = false;
|
||||
|
||||
// This is for fullscreen apps
|
||||
bool m_bCreatedOverFullscreen = false;
|
||||
|
@ -322,9 +328,6 @@ class CWindow {
|
|||
// urgency hint
|
||||
bool m_bIsUrgent = false;
|
||||
|
||||
// fakefullscreen
|
||||
bool m_bFakeFullscreenState = false;
|
||||
|
||||
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
||||
PHLWINDOWREF m_pLastCycledWindow;
|
||||
|
||||
|
@ -355,8 +358,8 @@ class CWindow {
|
|||
bool m_bStayFocused = false;
|
||||
|
||||
// for toplevel monitor events
|
||||
uint64_t m_iLastToplevelMonitorID = -1;
|
||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||
MONITORID m_iLastToplevelMonitorID = -1;
|
||||
MONITORID m_iLastSurfaceMonitorID = -1;
|
||||
|
||||
// for idle inhibiting windows
|
||||
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
|
@ -416,14 +419,16 @@ class CWindow {
|
|||
bool opaque();
|
||||
float rounding();
|
||||
bool canBeTorn();
|
||||
bool shouldSendFullscreenState();
|
||||
void setSuspended(bool suspend);
|
||||
bool visibleOnMonitor(CMonitor* pMonitor);
|
||||
int workspaceID();
|
||||
WORKSPACEID workspaceID();
|
||||
bool onSpecialWorkspace();
|
||||
void activate(bool force = false);
|
||||
int surfacesCount();
|
||||
|
||||
bool isFullscreen();
|
||||
bool isEffectiveInternalFSMode(const eFullscreenMode);
|
||||
|
||||
int getRealBorderSize();
|
||||
void updateWindowData();
|
||||
void updateWindowData(const struct SWorkspaceRule&);
|
||||
|
@ -485,9 +490,9 @@ class CWindow {
|
|||
|
||||
private:
|
||||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
bool m_bSuspended = false;
|
||||
int m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
bool m_bHidden = false;
|
||||
bool m_bSuspended = false;
|
||||
WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID;
|
||||
};
|
||||
|
||||
inline bool valid(PHLWINDOW w) {
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#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(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy);
|
||||
workspace->init(workspace);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmtpy) {
|
||||
m_iMonitorID = monitorID;
|
||||
m_iID = id;
|
||||
m_szName = name;
|
||||
|
@ -190,7 +190,7 @@ void CWorkspace::setActive(bool on) {
|
|||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
void CWorkspace::moveToMonitor(const int& id) {
|
||||
void CWorkspace::moveToMonitor(const MONITORID& id) {
|
||||
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
i = std::min(NEXTSPACE, std::string::npos - 1);
|
||||
|
||||
if (cur == 'r') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("r[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
|
@ -365,7 +365,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
}
|
||||
|
||||
if (cur == 'w') {
|
||||
int from = 0, to = 0;
|
||||
WORKSPACEID from = 0, to = 0;
|
||||
if (!prop.starts_with("w[") || !prop.ends_with("]")) {
|
||||
Debug::log(LOG, "Invalid selector {}", selector);
|
||||
return false;
|
||||
|
@ -446,7 +446,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int count;
|
||||
WORKSPACEID count;
|
||||
if (wantsCountGroup)
|
||||
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
|
||||
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
|
||||
|
@ -480,16 +480,11 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
return false;
|
||||
break;
|
||||
case 0: // fullscreen full
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL)
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_FULLSCREEN)
|
||||
return false;
|
||||
break;
|
||||
case 1: // maximized
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_MAXIMIZED)
|
||||
return false;
|
||||
break;
|
||||
case 2: // fullscreen without sending fullscreen state to window
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FULLSCREEN_FULL || !g_pCompositor->getFullscreenWindowOnWorkspace(m_iID) ||
|
||||
!g_pCompositor->getFullscreenWindowOnWorkspace(m_iID)->m_bDontSendFullscreen)
|
||||
if (!m_bHasFullscreenWindow || m_efFullscreenMode != FSMODE_MAXIMIZED)
|
||||
return false;
|
||||
break;
|
||||
default: break;
|
||||
|
@ -511,7 +506,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
|
|||
void CWorkspace::markInert() {
|
||||
m_bInert = true;
|
||||
m_iID = WORKSPACE_INVALID;
|
||||
m_iMonitorID = -1;
|
||||
m_iMonitorID = MONITOR_INVALID;
|
||||
m_bVisible = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,31 +7,32 @@
|
|||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
enum eFullscreenMode : int8_t {
|
||||
FULLSCREEN_INVALID = -1,
|
||||
FULLSCREEN_FULL = 0,
|
||||
FULLSCREEN_MAXIMIZED
|
||||
FSMODE_NONE = 0,
|
||||
FSMODE_MAXIMIZED = 1 << 0,
|
||||
FSMODE_FULLSCREEN = 1 << 1,
|
||||
FSMODE_MAX = (1 << 2) - 1
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
|
||||
class CWorkspace {
|
||||
public:
|
||||
static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true);
|
||||
static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmtpy = true);
|
||||
// use create() don't use this
|
||||
CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
|
||||
~CWorkspace();
|
||||
|
||||
// Workspaces ID-based have IDs > 0
|
||||
// and workspaces name-based have IDs starting with -1337
|
||||
int m_iID = -1;
|
||||
WORKSPACEID m_iID = WORKSPACE_INVALID;
|
||||
std::string m_szName = "";
|
||||
uint64_t m_iMonitorID = -1;
|
||||
MONITORID m_iMonitorID = MONITOR_INVALID;
|
||||
// Previous workspace ID and name is stored during a workspace change, allowing travel
|
||||
// to the previous workspace.
|
||||
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
|
||||
|
||||
bool m_bHasFullscreenWindow = false;
|
||||
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
|
||||
eFullscreenMode m_efFullscreenMode = FSMODE_NONE;
|
||||
|
||||
wl_array m_wlrCoordinateArr;
|
||||
|
||||
|
@ -66,7 +67,7 @@ class CWorkspace {
|
|||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
void moveToMonitor(const int&);
|
||||
void moveToMonitor(const MONITORID&);
|
||||
|
||||
PHLWINDOW getLastFocusedWindow();
|
||||
void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace);
|
||||
|
|
|
@ -274,9 +274,9 @@ std::string IKeyboard::getActiveLayout() {
|
|||
return "none";
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs() {
|
||||
std::optional<uint32_t> IKeyboard::getLEDs() {
|
||||
if (xkbState == nullptr)
|
||||
return;
|
||||
return {};
|
||||
|
||||
uint32_t leds = 0;
|
||||
for (uint32_t i = 0; i < LED_COUNT; ++i) {
|
||||
|
@ -284,7 +284,16 @@ void IKeyboard::updateLEDs() {
|
|||
leds |= (1 << i);
|
||||
}
|
||||
|
||||
updateLEDs(leds);
|
||||
return leds;
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs() {
|
||||
std::optional<uint32_t> leds = getLEDs();
|
||||
|
||||
if (!leds.has_value())
|
||||
return;
|
||||
|
||||
updateLEDs(leds.value());
|
||||
}
|
||||
|
||||
void IKeyboard::updateLEDs(uint32_t leds) {
|
||||
|
@ -325,6 +334,13 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l
|
|||
if (!updateModifiersState())
|
||||
return;
|
||||
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
.locked = modifiersState.locked,
|
||||
.group = modifiersState.group,
|
||||
});
|
||||
|
||||
updateLEDs();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
AQUAMARINE_FORWARD(IKeyboard);
|
||||
|
@ -61,19 +62,20 @@ class IKeyboard : public IHID {
|
|||
std::string rules = "";
|
||||
};
|
||||
|
||||
void setKeymap(const SStringRuleNames& rules);
|
||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||
std::string getActiveLayout();
|
||||
void updateLEDs();
|
||||
void updateLEDs(uint32_t leds);
|
||||
uint32_t getModifiers();
|
||||
void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||
bool updateModifiersState(); // rets whether changed
|
||||
void updateXkbStateWithKey(uint32_t xkbKey, bool pressed);
|
||||
void updateKeymapFD();
|
||||
void setKeymap(const SStringRuleNames& rules);
|
||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||
std::string getActiveLayout();
|
||||
std::optional<uint32_t> getLEDs();
|
||||
void updateLEDs();
|
||||
void updateLEDs(uint32_t leds);
|
||||
uint32_t getModifiers();
|
||||
void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||
bool updateModifiersState(); // rets whether changed
|
||||
void updateXkbStateWithKey(uint32_t xkbKey, bool pressed);
|
||||
void updateKeymapFD();
|
||||
|
||||
bool active = false;
|
||||
bool enabled = true;
|
||||
bool active = false;
|
||||
bool enabled = true;
|
||||
|
||||
// if the keymap is overridden by the implementation,
|
||||
// don't try to set keyboard rules anymore, to avoid overwriting the requested one.
|
||||
|
|
|
@ -106,7 +106,8 @@ class IPointer : public IHID {
|
|||
} pointerEvents;
|
||||
|
||||
std::string hlName;
|
||||
bool connected = false; // means connected to the cursor
|
||||
bool connected = false; // means connected to the cursor
|
||||
std::string boundOutput = "";
|
||||
|
||||
WP<IPointer> self;
|
||||
};
|
||||
|
|
|
@ -38,6 +38,8 @@ CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : point
|
|||
listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); });
|
||||
listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); });
|
||||
|
||||
boundOutput = resource->boundOutput ? resource->boundOutput->szName : "entire";
|
||||
|
||||
deviceName = pointer->name;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,12 +133,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
}
|
||||
|
||||
// window rules
|
||||
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen);
|
||||
bool requestsFakeFullscreen = false;
|
||||
bool requestsMaximize = false;
|
||||
bool overridingNoFullscreen = false;
|
||||
bool overridingNoMaximize = false;
|
||||
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||
std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode;
|
||||
std::optional<sFullscreenState> requestedFSState;
|
||||
if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen))
|
||||
requestedClientFSMode = FSMODE_FULLSCREEN;
|
||||
|
||||
for (auto& r : PWINDOW->m_vMatchedRules) {
|
||||
if (r.szRule.starts_with("monitor")) {
|
||||
|
@ -149,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
} else {
|
||||
if (isNumber(MONITORSTR)) {
|
||||
const long int MONITOR = std::stoi(MONITORSTR);
|
||||
const MONITORID MONITOR = std::stoi(MONITORSTR);
|
||||
if (!g_pCompositor->getMonitorFromID(MONITOR))
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
|
@ -199,6 +198,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
} else if (r.szRule.starts_with("fullscreenstate")) {
|
||||
const auto ARGS = CVarList(r.szRule.substr(r.szRule.find_first_of(' ') + 1), 2, ' ');
|
||||
int internalMode, clientMode;
|
||||
try {
|
||||
internalMode = std::stoi(ARGS[0]);
|
||||
} catch (std::exception& e) { internalMode = 0; }
|
||||
try {
|
||||
clientMode = std::stoi(ARGS[1]);
|
||||
} catch (std::exception& e) { clientMode = 0; }
|
||||
requestedFSState = sFullscreenState{.internal = (eFullscreenMode)internalMode, .client = (eFullscreenMode)clientMode};
|
||||
} else if (r.szRule.starts_with("suppressevent")) {
|
||||
CVarList vars(r.szRule, 0, 's', true);
|
||||
for (size_t i = 1; i < vars.size(); ++i) {
|
||||
|
@ -213,16 +222,12 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
else
|
||||
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
||||
}
|
||||
} else if (r.szRule == "fullscreen") {
|
||||
requestsFullscreen = true;
|
||||
overridingNoFullscreen = true;
|
||||
} else if (r.szRule == "fakefullscreen") {
|
||||
requestsFakeFullscreen = true;
|
||||
} else if (r.szRule == "pin") {
|
||||
PWINDOW->m_bPinned = true;
|
||||
} else if (r.szRule == "fullscreen") {
|
||||
requestedInternalFSMode = FSMODE_FULLSCREEN;
|
||||
} else if (r.szRule == "maximize") {
|
||||
requestsMaximize = true;
|
||||
overridingNoMaximize = true;
|
||||
requestedInternalFSMode = FSMODE_MAXIMIZED;
|
||||
} else if (r.szRule == "stayfocused") {
|
||||
PWINDOW->m_bStayFocused = true;
|
||||
} else if (r.szRule.starts_with("group")) {
|
||||
|
@ -461,17 +466,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock());
|
||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.interactivity != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||
|
||||
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow && !requestedInternalFSMode.has_value() && !requestedClientFSMode.has_value() && !PWINDOW->m_bIsFloating) {
|
||||
if (*PNEWTAKESOVERFS == 0)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
else if (*PNEWTAKESOVERFS == 1)
|
||||
requestedInternalFSMode = PWINDOW->m_pWorkspace->m_efFullscreenMode;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), false, FULLSCREEN_INVALID);
|
||||
else if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
requestsMaximize = true;
|
||||
if (*PNEWTAKESOVERFS == 1)
|
||||
overridingNoMaximize = true;
|
||||
} else
|
||||
requestsFullscreen = true;
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE);
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus &&
|
||||
|
@ -485,24 +487,27 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||
}
|
||||
|
||||
if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) ||
|
||||
(requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
|
||||
requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_FULLSCREEN);
|
||||
if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE))
|
||||
requestedClientFSMode = (eFullscreenMode)((uint8_t)requestedClientFSMode.value_or(FSMODE_NONE) & ~(uint8_t)FSMODE_MAXIMIZED);
|
||||
|
||||
if (requestsFakeFullscreen && !PWINDOW->m_bFakeFullscreenState) {
|
||||
PWINDOW->m_bFakeFullscreenState = !PWINDOW->m_bFakeFullscreenState;
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, true);
|
||||
} else {
|
||||
overridingNoFullscreen = false;
|
||||
overridingNoMaximize = false;
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, requestsFullscreen ? FULLSCREEN_FULL : FULLSCREEN_MAXIMIZED);
|
||||
}
|
||||
if (!PWINDOW->m_bNoInitialFocus && (requestedInternalFSMode.has_value() || requestedClientFSMode.has_value() || requestedFSState.has_value())) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow)
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWINDOW->m_pWorkspace->m_iID), FSMODE_NONE);
|
||||
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
if (requestedFSState.has_value()) {
|
||||
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE);
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
|
||||
} else if (requestedInternalFSMode.has_value() && requestedClientFSMode.has_value() && !PWINDOW->m_sWindowData.syncFullscreen.valueOrDefault())
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()});
|
||||
else if (requestedInternalFSMode.has_value())
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, requestedInternalFSMode.value());
|
||||
else if (requestedClientFSMode.has_value())
|
||||
g_pCompositor->setWindowFullscreenClient(PWINDOW, requestedClientFSMode.value());
|
||||
}
|
||||
|
||||
// recheck idle inhibitors
|
||||
|
@ -558,7 +563,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||
// recalc the values for this window
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
// avoid this window being visible
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating)
|
||||
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
|
||||
|
||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale);
|
||||
|
@ -583,8 +588,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
|
||||
static auto PEXITRETAINSFS = CConfigValue<Hyprlang::INT>("misc:exit_window_retains_fullscreen");
|
||||
|
||||
const auto CURRENTWINDOWFSSTATE = PWINDOW->m_bIsFullscreen;
|
||||
const auto CURRENTWINDOWFSMODE = PWINDOW->m_pWorkspace->m_efFullscreenMode;
|
||||
const auto CURRENTWINDOWFSSTATE = PWINDOW->isFullscreen();
|
||||
const auto CURRENTFSMODE = PWINDOW->m_sFullscreenState.internal;
|
||||
|
||||
if (!PWINDOW->m_pWLSurface->exists() || !PWINDOW->m_bIsMapped) {
|
||||
Debug::log(WARN, "{} unmapped without being mapped??", PWINDOW);
|
||||
|
@ -604,8 +609,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
|
||||
PROTO::toplevelExport->onWindowUnmap(PWINDOW);
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
if (PWINDOW->isFullscreen())
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||
|
||||
// Allow the renderer to catch the last frame.
|
||||
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
|
||||
|
@ -627,10 +632,13 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
g_pInputManager->releaseAllMouseButtons();
|
||||
}
|
||||
|
||||
if (PWINDOW == g_pInputManager->currentlyDraggedWindow.lock())
|
||||
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
|
||||
|
||||
// remove the fullscreen window status from workspace if we closed it
|
||||
const auto PWORKSPACE = PWINDOW->m_pWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWINDOW->m_bIsFullscreen)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWINDOW->isFullscreen())
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
@ -647,7 +655,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow.lock() && PWINDOWCANDIDATE) {
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
if (*PEXITRETAINSFS && CURRENTWINDOWFSSTATE)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWCANDIDATE, true, CURRENTWINDOWFSMODE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWCANDIDATE, CURRENTFSMODE);
|
||||
}
|
||||
|
||||
if (!PWINDOWCANDIDATE && g_pCompositor->getWindowsOnWorkspace(PWINDOW->workspaceID()) == 0)
|
||||
|
@ -705,7 +713,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
|
||||
if (!PWINDOW->m_bIsX11 && !PWINDOW->m_bIsFullscreen && PWINDOW->m_bIsFloating) {
|
||||
if (!PWINDOW->m_bIsX11 && !PWINDOW->isFullscreen() && PWINDOW->m_bIsFloating) {
|
||||
const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize;
|
||||
const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize;
|
||||
|
||||
|
@ -744,7 +752,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
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.texture) {
|
||||
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()};
|
||||
|
||||
if (!damageBox.empty()) {
|
||||
|
@ -782,6 +790,11 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
|||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
}
|
||||
|
||||
PWINDOW->listeners.unmap.reset();
|
||||
PWINDOW->listeners.destroy.reset();
|
||||
PWINDOW->listeners.map.reset();
|
||||
PWINDOW->listeners.commit.reset();
|
||||
}
|
||||
|
||||
void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
|
@ -832,7 +845,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
|||
else
|
||||
PWINDOW->setHidden(true);
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen || !PWINDOW->m_bIsFloating) {
|
||||
if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) {
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
return;
|
||||
|
|
|
@ -30,8 +30,10 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
|||
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
|
||||
|
||||
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
|
||||
for (float i = 0.1f; i < 1.f; i += 0.1f)
|
||||
for (int j = 1; j < 10; ++j) {
|
||||
float i = j / 10.0f;
|
||||
getYForPoint(i);
|
||||
}
|
||||
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
|
||||
|
||||
Debug::log(LOG, "Created a bezier curve, baked {} points, mem usage: {:.2f}kB, time to bake: {:.2f}µs. Estimated average calc time: {:.2f}µs.", BAKEDPOINTS, POINTSSIZE,
|
||||
|
|
|
@ -249,7 +249,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
return {WORKSPACE_INVALID};
|
||||
}
|
||||
|
||||
std::set<int> invalidWSes;
|
||||
std::set<WORKSPACEID> invalidWSes;
|
||||
if (same_mon) {
|
||||
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
|
||||
|
@ -258,8 +258,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
}
|
||||
|
||||
int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
|
||||
while (++id < INT_MAX) {
|
||||
WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
|
||||
while (++id < LONG_MAX) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||
if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) {
|
||||
result.id = id;
|
||||
|
@ -296,9 +296,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
result.id = (int)PLUSMINUSRESULT.value();
|
||||
|
||||
int remains = (int)result.id;
|
||||
WORKSPACEID remains = result.id;
|
||||
|
||||
std::set<int> invalidWSes;
|
||||
std::set<WORKSPACEID> invalidWSes;
|
||||
|
||||
// Collect all the workspaces we can't jump to.
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
|
@ -318,7 +318,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
|
||||
// Prepare all named workspaces in case when we need them
|
||||
std::vector<int> namedWSes;
|
||||
std::vector<WORKSPACEID> namedWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0)
|
||||
continue;
|
||||
|
@ -347,18 +347,18 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
} else {
|
||||
|
||||
// Just take a blind guess at where we'll probably end up
|
||||
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
int predictedWSID = activeWSID + remains;
|
||||
int remainingWSes = 0;
|
||||
char walkDir = in[1];
|
||||
WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
WORKSPACEID predictedWSID = activeWSID + remains;
|
||||
int remainingWSes = 0;
|
||||
char walkDir = in[1];
|
||||
|
||||
// sanitize. 0 means invalid oob in -
|
||||
predictedWSID = std::max(predictedWSID, 0);
|
||||
predictedWSID = std::max(predictedWSID, 0L);
|
||||
|
||||
// Count how many invalidWSes are in between (how bad the prediction was)
|
||||
int beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID;
|
||||
int endID = in[1] == '+' ? predictedWSID : activeWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID;
|
||||
WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
if (activeWSID < 0) {
|
||||
// Behaviour similar to 'm'
|
||||
// Find current
|
||||
int currentItem = -1;
|
||||
size_t currentItem = -1;
|
||||
for (size_t i = 0; i < namedWSes.size(); i++) {
|
||||
if (namedWSes[i] == activeWSID) {
|
||||
currentItem = i;
|
||||
|
@ -376,14 +376,14 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
|
||||
currentItem += remains;
|
||||
currentItem = std::max(currentItem, 0);
|
||||
if (currentItem >= (int)namedWSes.size()) {
|
||||
currentItem = std::max(currentItem, 0UL);
|
||||
if (currentItem >= namedWSes.size()) {
|
||||
// At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0
|
||||
int diff = currentItem - (namedWSes.size() - 1);
|
||||
predictedWSID = diff;
|
||||
int beginID = 1;
|
||||
int endID = predictedWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
size_t diff = currentItem - (namedWSes.size() - 1);
|
||||
predictedWSID = diff;
|
||||
WORKSPACEID beginID = 1;
|
||||
WORKSPACEID endID = predictedWSID;
|
||||
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
|
||||
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) {
|
||||
remainingWSes++;
|
||||
}
|
||||
|
@ -397,10 +397,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
// Go in the search direction for remainingWSes
|
||||
// The performance impact is directly proportional to the number of open and bound workspaces
|
||||
int finalWSID = predictedWSID;
|
||||
WORKSPACEID finalWSID = predictedWSID;
|
||||
if (walkDir == '-') {
|
||||
int beginID = finalWSID;
|
||||
int curID = finalWSID;
|
||||
WORKSPACEID beginID = finalWSID;
|
||||
WORKSPACEID curID = finalWSID;
|
||||
while (--curID > 0 && remainingWSes > 0) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
|
@ -411,9 +411,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
if (namedWSes.size()) {
|
||||
// Go to the named workspaces
|
||||
// Need remainingWSes more
|
||||
int namedWSIdx = namedWSes.size() - remainingWSes;
|
||||
auto namedWSIdx = namedWSes.size() - remainingWSes;
|
||||
// Sanitze
|
||||
namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1);
|
||||
namedWSIdx = std::clamp(namedWSIdx, 0UL, namedWSes.size() - 1);
|
||||
finalWSID = namedWSes[namedWSIdx];
|
||||
} else {
|
||||
// Couldn't find valid workspace in negative direction, search last first one back up positive direction
|
||||
|
@ -425,7 +425,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
}
|
||||
}
|
||||
if (walkDir == '+') {
|
||||
int curID = finalWSID;
|
||||
WORKSPACEID curID = finalWSID;
|
||||
while (++curID < INT32_MAX && remainingWSes > 0) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
|
@ -460,9 +460,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
result.id = (int)PLUSMINUSRESULT.value();
|
||||
|
||||
// result now has +/- what we should move on mon
|
||||
int remains = (int)result.id;
|
||||
int remains = (int)result.id;
|
||||
|
||||
std::vector<int> validWSes;
|
||||
std::vector<WORKSPACEID> validWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
|
||||
continue;
|
||||
|
@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
|
||||
std::sort(validWSes.begin(), validWSes.end());
|
||||
|
||||
int currentItem = -1;
|
||||
size_t currentItem = -1;
|
||||
|
||||
if (absolute) {
|
||||
// 1-index
|
||||
|
@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
// clamp
|
||||
if (currentItem < 0) {
|
||||
currentItem = 0;
|
||||
} else if (currentItem >= (int)validWSes.size()) {
|
||||
} else if (currentItem >= validWSes.size()) {
|
||||
currentItem = validWSes.size() - 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -489,7 +489,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
|
||||
|
||||
// get the current item
|
||||
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
|
||||
for (size_t i = 0; i < validWSes.size(); i++) {
|
||||
if (validWSes[i] == activeWSID) {
|
||||
currentItem = i;
|
||||
|
@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
|
|||
currentItem += remains;
|
||||
|
||||
// sanitize
|
||||
if (currentItem >= (int)validWSes.size()) {
|
||||
if (currentItem >= validWSes.size()) {
|
||||
currentItem = currentItem % validWSes.size();
|
||||
} else if (currentItem < 0) {
|
||||
currentItem = validWSes.size() + currentItem;
|
||||
|
@ -547,9 +547,9 @@ std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceNa
|
|||
const std::string workspaceRule = "workspace " + inWorkspaceName;
|
||||
|
||||
if (cmd[0] == '[') {
|
||||
const int closingBracketIdx = cmd.find_last_of(']');
|
||||
auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
|
||||
cmd = cmd.substr(closingBracketIdx + 1);
|
||||
const auto closingBracketIdx = cmd.find_last_of(']');
|
||||
auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
|
||||
cmd = cmd.substr(closingBracketIdx + 1);
|
||||
|
||||
auto rulesList = CVarList(tmpRules, 0, ';');
|
||||
|
||||
|
@ -785,13 +785,13 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
|
|||
|
||||
#ifdef HAS_EXECINFO
|
||||
void* bt[1024];
|
||||
size_t btSize;
|
||||
int btSize;
|
||||
char** btSymbols;
|
||||
|
||||
btSize = backtrace(bt, 1024);
|
||||
btSymbols = backtrace_symbols(bt, btSize);
|
||||
|
||||
for (size_t i = 0; i < btSize; ++i) {
|
||||
for (auto i = 0; i < btSize; ++i) {
|
||||
callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}});
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "math/Math.hpp"
|
||||
#include <vector>
|
||||
#include <format>
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../macros.hpp"
|
||||
|
||||
struct SCallstackFrameInfo {
|
||||
void* adr = nullptr;
|
||||
|
@ -13,7 +15,7 @@ struct SCallstackFrameInfo {
|
|||
};
|
||||
|
||||
struct SWorkspaceIDName {
|
||||
int id = -1;
|
||||
WORKSPACEID id = WORKSPACE_INVALID;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "Monitor.hpp"
|
||||
#include "MiscFunctions.hpp"
|
||||
#include "math/Math.hpp"
|
||||
#include "sync/SyncReleaser.hpp"
|
||||
#include "ScopeGuard.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../protocols/GammaControl.hpp"
|
||||
|
@ -8,6 +10,7 @@
|
|||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/PresentationTime.hpp"
|
||||
#include "../protocols/DRMLease.hpp"
|
||||
#include "../protocols/DRMSyncobj.hpp"
|
||||
#include "../protocols/core/Output.hpp"
|
||||
#include "../managers/PointerManager.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
|
@ -77,6 +80,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
|
||||
|
||||
if (m_bEnabled) {
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(true);
|
||||
state.commit();
|
||||
return;
|
||||
|
@ -101,6 +105,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
// if it's disabled, disable and ignore
|
||||
if (monitorRule.disabled) {
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(false);
|
||||
|
||||
if (!state.commit())
|
||||
|
@ -137,6 +142,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
|
||||
m_bEnabled = true;
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(true);
|
||||
|
||||
// set mode, also applies
|
||||
|
@ -300,6 +306,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
activeWorkspace->m_bVisible = false;
|
||||
activeWorkspace.reset();
|
||||
|
||||
output->state->resetExplicitFences();
|
||||
output->state->setEnabled(false);
|
||||
|
||||
if (!state.commit())
|
||||
|
@ -354,7 +361,7 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
|
|||
|
||||
// skip scheduling extra frames for fullsreen apps with vrr
|
||||
bool shouldSkip =
|
||||
*PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
*PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN;
|
||||
|
||||
// keep requested minimum refresh rate
|
||||
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) {
|
||||
|
@ -382,8 +389,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const {
|
|||
}
|
||||
}
|
||||
|
||||
int CMonitor::findAvailableDefaultWS() {
|
||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||
WORKSPACEID CMonitor::findAvailableDefaultWS() {
|
||||
for (WORKSPACEID i = 1; i < LONG_MAX; ++i) {
|
||||
if (g_pCompositor->getWorkspaceByID(i))
|
||||
continue;
|
||||
|
||||
|
@ -393,7 +400,7 @@ int CMonitor::findAvailableDefaultWS() {
|
|||
return i;
|
||||
}
|
||||
|
||||
return INT32_MAX; // shouldn't be reachable
|
||||
return LONG_MAX; // shouldn't be reachable
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
|
@ -631,7 +638,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
|
|||
g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace);
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
|
||||
}
|
||||
|
||||
|
@ -738,7 +745,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
|
|||
g_pCompositor->updateSuspendedStates();
|
||||
}
|
||||
|
||||
void CMonitor::setSpecialWorkspace(const int& id) {
|
||||
void CMonitor::setSpecialWorkspace(const WORKSPACEID& id) {
|
||||
setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id));
|
||||
}
|
||||
|
||||
|
@ -759,11 +766,11 @@ void CMonitor::updateMatrix() {
|
|||
}
|
||||
}
|
||||
|
||||
int64_t CMonitor::activeWorkspaceID() {
|
||||
WORKSPACEID CMonitor::activeWorkspaceID() {
|
||||
return activeWorkspace ? activeWorkspace->m_iID : 0;
|
||||
}
|
||||
|
||||
int64_t CMonitor::activeSpecialWorkspaceID() {
|
||||
WORKSPACEID CMonitor::activeSpecialWorkspaceID() {
|
||||
return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0;
|
||||
}
|
||||
|
||||
|
@ -801,33 +808,84 @@ bool CMonitor::attemptDirectScanout() {
|
|||
|
||||
const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
|
||||
|
||||
if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != vecPixelSize || PSURFACE->current.transform != transform)
|
||||
if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.bufferSize != vecPixelSize || PSURFACE->current.transform != transform)
|
||||
return false;
|
||||
|
||||
// we can't scanout shm buffers.
|
||||
if (!PSURFACE->current.buffer->dmabuf().success)
|
||||
if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */)
|
||||
return false;
|
||||
|
||||
Debug::log(TRACE, "attemptDirectScanout: surface {:x} passed, will attempt", (uintptr_t)PSURFACE.get());
|
||||
|
||||
// FIXME: make sure the buffer actually follows the available scanout dmabuf formats
|
||||
// and comes from the appropriate device. This may implode on multi-gpu!!
|
||||
output->state->setBuffer(PSURFACE->current.buffer->buffer.lock());
|
||||
output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
|
||||
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
|
||||
|
||||
output->state->setBuffer(PSURFACE->current.buffer);
|
||||
output->state->setPresentationMode(Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
|
||||
|
||||
if (!state.test())
|
||||
if (!state.test()) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed basic test");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings();
|
||||
|
||||
// wait for the explicit fence if present, and if kms explicit is allowed
|
||||
bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled;
|
||||
int explicitWaitFD = -1;
|
||||
if (DOEXPLICIT) {
|
||||
explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint);
|
||||
if (explicitWaitFD < 0)
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd");
|
||||
}
|
||||
DOEXPLICIT = DOEXPLICIT && explicitWaitFD >= 0;
|
||||
|
||||
auto cleanup = CScopeGuard([explicitWaitFD, this]() {
|
||||
output->state->resetExplicitFences();
|
||||
if (explicitWaitFD >= 0)
|
||||
close(explicitWaitFD);
|
||||
});
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
Debug::log(TRACE, "presentFeedback for DS");
|
||||
PSURFACE->presentFeedback(&now, this, true);
|
||||
PSURFACE->presentFeedback(&now, this);
|
||||
|
||||
if (state.commit()) {
|
||||
output->state->addDamage(CBox{{}, vecPixelSize});
|
||||
output->state->resetExplicitFences();
|
||||
|
||||
if (DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD);
|
||||
output->state->setExplicitInFence(explicitWaitFD);
|
||||
}
|
||||
|
||||
bool ok = output->commit();
|
||||
|
||||
if (!ok && DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: EXPLICIT SYNC FAILED: commit() returned false. Resetting fences and retrying, might result in glitches.");
|
||||
output->state->resetExplicitFences();
|
||||
|
||||
ok = output->commit();
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (lastScanout.expired()) {
|
||||
lastScanout = PCANDIDATE;
|
||||
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
|
||||
}
|
||||
|
||||
// delay explicit sync feedback until kms release of the buffer
|
||||
if (DOEXPLICIT) {
|
||||
Debug::log(TRACE, "attemptDirectScanout: Delaying explicit sync release feedback until kms release");
|
||||
PSURFACE->current.buffer->releaser->drop();
|
||||
|
||||
PSURFACE->current.buffer->buffer->hlEvents.backendRelease2 = PSURFACE->current.buffer->buffer->events.backendRelease.registerListener([PSURFACE](std::any d) {
|
||||
const bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.releaseTimeline && PSURFACE->syncobj->current.releaseTimeline->timeline;
|
||||
if (DOEXPLICIT)
|
||||
PSURFACE->syncobj->current.releaseTimeline->timeline->signal(PSURFACE->syncobj->current.releasePoint);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Debug::log(TRACE, "attemptDirectScanout: failed to scanout surface");
|
||||
lastScanout.reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -863,6 +921,8 @@ bool CMonitorState::commit() {
|
|||
if (!updateSwapchain())
|
||||
return false;
|
||||
|
||||
EMIT_HOOK_EVENT("preMonitorCommit", m_pOwner);
|
||||
|
||||
ensureBufferPresent();
|
||||
|
||||
bool ret = m_pOwner->output->commit();
|
||||
|
|
|
@ -70,7 +70,7 @@ class CMonitor {
|
|||
|
||||
bool primary = false;
|
||||
|
||||
uint64_t ID = -1;
|
||||
MONITORID ID = MONITOR_INVALID;
|
||||
PHLWORKSPACE activeWorkspace = nullptr;
|
||||
PHLWORKSPACE activeSpecialWorkspace = nullptr;
|
||||
float setScale = 1; // scale set by cfg
|
||||
|
@ -121,8 +121,7 @@ class CMonitor {
|
|||
// explicit sync
|
||||
SP<CSyncTimeline> inTimeline;
|
||||
SP<CSyncTimeline> outTimeline;
|
||||
uint64_t lastWaitPoint = 0;
|
||||
uint64_t commitSeq = 0;
|
||||
uint64_t commitSeq = 0;
|
||||
|
||||
WP<CMonitor> self;
|
||||
|
||||
|
@ -156,31 +155,31 @@ class CMonitor {
|
|||
std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers;
|
||||
|
||||
// methods
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect(bool destroy = false);
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const CBox* box);
|
||||
bool shouldSkipScheduleFrameOnMouseEvent();
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
int64_t activeWorkspaceID();
|
||||
int64_t activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void scheduleDone();
|
||||
bool attemptDirectScanout();
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect(bool destroy = false);
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const CBox* box);
|
||||
bool shouldSkipScheduleFrameOnMouseEvent();
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
|
||||
void setSpecialWorkspace(const WORKSPACEID& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
WORKSPACEID activeWorkspaceID();
|
||||
WORKSPACEID activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void scheduleDone();
|
||||
bool attemptDirectScanout();
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
||||
// For the list lookup
|
||||
|
||||
|
@ -190,7 +189,7 @@ class CMonitor {
|
|||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
int findAvailableDefaultWS();
|
||||
WORKSPACEID findAvailableDefaultWS();
|
||||
|
||||
wl_event_source* doneSource = nullptr;
|
||||
|
||||
|
|
10
src/helpers/ScopeGuard.cpp
Normal file
10
src/helpers/ScopeGuard.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "ScopeGuard.hpp"
|
||||
|
||||
CScopeGuard::CScopeGuard(const std::function<void()>& fn_) : fn(fn_) {
|
||||
;
|
||||
}
|
||||
|
||||
CScopeGuard::~CScopeGuard() {
|
||||
if (fn)
|
||||
fn();
|
||||
}
|
13
src/helpers/ScopeGuard.hpp
Normal file
13
src/helpers/ScopeGuard.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
// calls a function when it goes out of scope
|
||||
class CScopeGuard {
|
||||
public:
|
||||
CScopeGuard(const std::function<void()>& fn_);
|
||||
~CScopeGuard();
|
||||
|
||||
private:
|
||||
std::function<void()> fn;
|
||||
};
|
|
@ -8,6 +8,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Systemd {
|
||||
int SdBooted(void) {
|
||||
|
|
|
@ -8,7 +8,7 @@ std::chrono::steady_clock::duration CTimer::getDuration() {
|
|||
return std::chrono::steady_clock::now() - m_tpLastReset;
|
||||
}
|
||||
|
||||
int CTimer::getMillis() {
|
||||
long CTimer::getMillis() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class CTimer {
|
|||
public:
|
||||
void reset();
|
||||
float getSeconds();
|
||||
int getMillis();
|
||||
long getMillis();
|
||||
const std::chrono::steady_clock::time_point& chrono() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -18,15 +18,14 @@ CWatchdog::CWatchdog() {
|
|||
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||
static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout");
|
||||
|
||||
while (1337) {
|
||||
std::unique_lock lk(m_mWatchdogMutex);
|
||||
m_bWatchdogInitialized = true;
|
||||
while (!m_bExitThread) {
|
||||
std::unique_lock<std::mutex> lk(m_mWatchdogMutex);
|
||||
|
||||
if (!m_bWillWatch)
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||
else {
|
||||
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||
}
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified || m_bExitThread; });
|
||||
else if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }) == false)
|
||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||
|
||||
if (m_bExitThread)
|
||||
break;
|
||||
|
|
|
@ -11,21 +11,23 @@ class CWatchdog {
|
|||
CWatchdog();
|
||||
~CWatchdog();
|
||||
|
||||
void startWatching();
|
||||
void endWatching();
|
||||
void startWatching();
|
||||
void endWatching();
|
||||
|
||||
std::atomic<bool> m_bWatchdogInitialized{false};
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point m_tTriggered;
|
||||
|
||||
pthread_t m_iMainThreadPID = 0;
|
||||
|
||||
bool m_bWatching = false;
|
||||
bool m_bWillWatch = false;
|
||||
std::atomic<bool> m_bWatching = false;
|
||||
std::atomic<bool> m_bWillWatch = false;
|
||||
|
||||
std::unique_ptr<std::thread> m_pWatchdog;
|
||||
std::mutex m_mWatchdogMutex;
|
||||
bool m_bNotified = false;
|
||||
bool m_bExitThread = false;
|
||||
std::atomic<bool> m_bNotified = false;
|
||||
std::atomic<bool> m_bExitThread = false;
|
||||
std::condition_variable m_cvWatchdogCondition;
|
||||
};
|
||||
|
||||
|
|
25
src/helpers/sync/SyncReleaser.cpp
Normal file
25
src/helpers/sync/SyncReleaser.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "SyncReleaser.hpp"
|
||||
#include "SyncTimeline.hpp"
|
||||
#include "../../render/OpenGL.hpp"
|
||||
|
||||
CSyncReleaser::CSyncReleaser(WP<CSyncTimeline> timeline_, uint64_t point_) : timeline(timeline_), point(point_) {
|
||||
;
|
||||
}
|
||||
|
||||
CSyncReleaser::~CSyncReleaser() {
|
||||
if (timeline.expired())
|
||||
return;
|
||||
|
||||
if (sync)
|
||||
timeline->importFromSyncFileFD(point, sync->fd());
|
||||
else
|
||||
timeline->signal(point);
|
||||
}
|
||||
|
||||
void CSyncReleaser::addReleaseSync(SP<CEGLSync> sync_) {
|
||||
sync = sync_;
|
||||
}
|
||||
|
||||
void CSyncReleaser::drop() {
|
||||
timeline.reset();
|
||||
}
|
31
src/helpers/sync/SyncReleaser.hpp
Normal file
31
src/helpers/sync/SyncReleaser.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include "../memory/Memory.hpp"
|
||||
|
||||
/*
|
||||
A helper (inspired by KDE's KWin) that will release the timeline point in the dtor
|
||||
*/
|
||||
|
||||
class CSyncTimeline;
|
||||
class CEGLSync;
|
||||
|
||||
class CSyncReleaser {
|
||||
public:
|
||||
CSyncReleaser(WP<CSyncTimeline> timeline_, uint64_t point_);
|
||||
~CSyncReleaser();
|
||||
|
||||
// drops the releaser, will never signal anymore
|
||||
void drop();
|
||||
|
||||
// wait for this gpu job to finish before releasing
|
||||
void addReleaseSync(SP<CEGLSync> sync);
|
||||
|
||||
private:
|
||||
WP<CSyncTimeline> timeline;
|
||||
uint64_t point = 0;
|
||||
SP<CEGLSync> sync;
|
||||
};
|
|
@ -188,3 +188,8 @@ bool CSyncTimeline::transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSyncTimeline::signal(uint64_t point) {
|
||||
if (drmSyncobjTimelineSignal(drmFD, &handle, &point, 1))
|
||||
Debug::log(ERR, "CSyncTimeline::signal: drmSyncobjTimelineSignal failed");
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ class CSyncTimeline {
|
|||
int exportAsSyncFileFD(uint64_t src);
|
||||
bool importFromSyncFileFD(uint64_t dst, int fd);
|
||||
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
||||
void signal(uint64_t point);
|
||||
|
||||
int drmFD = -1;
|
||||
uint32_t handle = 0;
|
||||
|
|
|
@ -88,14 +88,14 @@ void CHyprError::createQueued() {
|
|||
cairo_arc(CAIRO, X + RADIUS, Y + RADIUS, RADIUS, 180 * DEGREES, 270 * DEGREES);
|
||||
cairo_close_path(CAIRO);
|
||||
|
||||
cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a);
|
||||
cairo_set_source_rgba(CAIRO, 0.06, 0.06, 0.06, 1.0);
|
||||
cairo_fill_preserve(CAIRO);
|
||||
cairo_set_source_rgba(CAIRO, 0, 0, 0, 1);
|
||||
cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a);
|
||||
cairo_set_line_width(CAIRO, 2);
|
||||
cairo_stroke(CAIRO);
|
||||
|
||||
// draw the text with a common font
|
||||
const CColor textColor = m_cQueued.r + m_cQueued.g + m_cQueued.b < 0.2f ? CColor(1.0, 1.0, 1.0, 1.0) : CColor(0, 0, 0, 1.0);
|
||||
const CColor textColor = CColor(0.9, 0.9, 0.9, 1.0);
|
||||
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
|
||||
|
||||
static auto fontFamily = CConfigValue<std::string>("misc:font_family");
|
||||
|
|
|
@ -47,7 +47,7 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pD
|
|||
}
|
||||
}
|
||||
|
||||
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
||||
int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (n.workspaceID == id && n.valid)
|
||||
|
@ -56,7 +56,7 @@ int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
|||
return no;
|
||||
}
|
||||
|
||||
SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
||||
SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (n.workspaceID == id && validMapped(n.pWindow))
|
||||
return &n;
|
||||
|
@ -64,7 +64,7 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) {
|
||||
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) {
|
||||
SDwindleNodeData* res = nullptr;
|
||||
double distClosest = -1;
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
|
@ -88,7 +88,7 @@ SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
|
||||
SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) {
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (!n.pParent && n.workspaceID == id)
|
||||
return &n;
|
||||
|
@ -136,7 +136,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->unsetWindowData(PRIORITY_LAYOUT);
|
||||
|
@ -158,8 +158,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
|
||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->workspaceID());
|
||||
|
||||
if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() &&
|
||||
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||
if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (NODESONWORKSPACE == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) {
|
||||
|
||||
PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT);
|
||||
PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT);
|
||||
|
@ -178,6 +177,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
return;
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
auto calcPos = PWINDOW->m_vPosition;
|
||||
auto calcSize = PWINDOW->m_vSize;
|
||||
|
||||
|
@ -216,7 +217,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
calcPos = calcPos + RESERVED.topLeft;
|
||||
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||
|
||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->m_bIsFullscreen) {
|
||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
||||
// if special, we adjust the coords a bit
|
||||
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("dwindle:special_scale_factor");
|
||||
|
||||
|
@ -245,8 +246,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
|||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) {
|
||||
|
@ -500,8 +499,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
|||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
||||
pWindow->updateWindowData();
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
if (pWindow->isFullscreen())
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
|
@ -536,7 +535,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
|||
m_lDwindleNodesData.remove(*PNODE);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
|
||||
if (!PMONITOR || !PMONITOR->activeWorkspace)
|
||||
|
@ -560,10 +559,10 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
|
|||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
|
||||
|
||||
if (pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
|
||||
PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
|
||||
} else if (pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
|
@ -788,41 +787,19 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!validMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
// if the window wants to be fullscreen but there already is one,
|
||||
// ignore the request.
|
||||
return;
|
||||
}
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating && on) {
|
||||
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goal();
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
pWindow->updateWindowDecos();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
if (EFFECTIVE_MODE == FSMODE_NONE) {
|
||||
// if it got its fullscreen disabled, set back its node if it had one
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
if (PNODE)
|
||||
|
@ -836,12 +813,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre
|
|||
pWindow->updateWindowData();
|
||||
}
|
||||
} else {
|
||||
// if it now got fullscreen, make it fullscreen
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||
} else {
|
||||
|
@ -861,13 +834,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscre
|
|||
}
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::recalculateWindow(PHLWINDOW pWindow) {
|
||||
|
@ -905,7 +872,7 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir,
|
|||
return;
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
const int originalWorkspaceID = pWindow->workspaceID();
|
||||
const auto originalWorkspaceID = pWindow->workspaceID();
|
||||
const Vector2D originalPos = pWindow->middle();
|
||||
|
||||
if (!PNODE)
|
||||
|
@ -957,13 +924,11 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) {
|
|||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
|
||||
const bool FS1 = pWindow->m_bIsFullscreen;
|
||||
const bool FS2 = pWindow2->m_bIsFullscreen;
|
||||
const eFullscreenMode MODE1 = pWindow->m_sFullscreenState.internal;
|
||||
const eFullscreenMode MODE2 = pWindow2->m_sFullscreenState.internal;
|
||||
|
||||
if (FS1)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false);
|
||||
if (FS2)
|
||||
g_pCompositor->setWindowFullscreen(pWindow2, false);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow2, FSMODE_NONE);
|
||||
|
||||
SDwindleNodeData* ACTIVE1 = nullptr;
|
||||
SDwindleNodeData* ACTIVE2 = nullptr;
|
||||
|
@ -1001,10 +966,8 @@ void CHyprDwindleLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) {
|
|||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
g_pHyprRenderer->damageWindow(pWindow2);
|
||||
|
||||
if (FS1)
|
||||
g_pCompositor->setWindowFullscreen(pWindow2, true);
|
||||
if (FS2)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow2, MODE1);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, MODE2);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exact) {
|
||||
|
@ -1072,7 +1035,7 @@ void CHyprDwindleLayout::toggleSplit(PHLWINDOW pWindow) {
|
|||
if (!PNODE || !PNODE->pParent)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
if (pWindow->isFullscreen())
|
||||
return;
|
||||
|
||||
PNODE->pParent->splitTop = !PNODE->pParent->splitTop;
|
||||
|
@ -1086,7 +1049,7 @@ void CHyprDwindleLayout::swapSplit(PHLWINDOW pWindow) {
|
|||
if (!PNODE || !PNODE->pParent)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
if (pWindow->isFullscreen())
|
||||
return;
|
||||
|
||||
std::swap(PNODE->pParent->children[0], PNODE->pParent->children[1]);
|
||||
|
|
|
@ -24,7 +24,7 @@ struct SDwindleNodeData {
|
|||
|
||||
CBox box = {0};
|
||||
|
||||
int workspaceID = -1;
|
||||
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
||||
|
||||
float splitRatio = 1.f;
|
||||
|
||||
|
@ -48,11 +48,11 @@ class CHyprDwindleLayout : public IHyprLayout {
|
|||
virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT);
|
||||
virtual void onWindowRemovedTiling(PHLWINDOW);
|
||||
virtual bool isWindowTiled(PHLWINDOW);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateMonitor(const MONITORID&);
|
||||
virtual void recalculateWindow(PHLWINDOW);
|
||||
virtual void onBeginDragWindow();
|
||||
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool);
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(PHLWINDOW);
|
||||
virtual void switchWindows(PHLWINDOW, PHLWINDOW);
|
||||
|
@ -77,13 +77,13 @@ class CHyprDwindleLayout : public IHyprLayout {
|
|||
|
||||
std::optional<Vector2D> m_vOverrideFocalPoint; // for onWindowCreatedTiling.
|
||||
|
||||
int getNodesOnWorkspace(const int&);
|
||||
int getNodesOnWorkspace(const WORKSPACEID&);
|
||||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||
void calculateWorkspace(const PHLWORKSPACE& pWorkspace);
|
||||
SDwindleNodeData* getNodeFromWindow(PHLWINDOW);
|
||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&);
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&);
|
||||
SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&);
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
|
||||
|
||||
void toggleSplit(PHLWINDOW);
|
||||
void swapSplit(PHLWINDOW);
|
||||
|
|
|
@ -29,8 +29,8 @@ void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
|||
}
|
||||
|
||||
void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) {
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
if (pWindow->isFullscreen())
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow.expired()) {
|
||||
if (pWindow->m_sGroupData.pNextWindow.lock() == pWindow)
|
||||
|
@ -187,20 +187,20 @@ void IHyprLayout::onBeginDragWindow() {
|
|||
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
|
||||
if (!validMapped(DRAGGINGWINDOW)) {
|
||||
Debug::log(ERR, "Dragging attempted on an invalid window!");
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DRAGGINGWINDOW->m_bIsFullscreen) {
|
||||
if (DRAGGINGWINDOW->isFullscreen()) {
|
||||
Debug::log(LOG, "Dragging a fullscreen window");
|
||||
g_pCompositor->setWindowFullscreen(DRAGGINGWINDOW, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(DRAGGINGWINDOW, FSMODE_NONE);
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = DRAGGINGWINDOW->m_pWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)");
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,6 @@ void IHyprLayout::onEndDragWindow() {
|
|||
}
|
||||
|
||||
g_pInputManager->unsetCursorImage();
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pInputManager->m_bWasDraggingWindow = true;
|
||||
|
||||
|
@ -325,12 +324,14 @@ void IHyprLayout::onEndDragWindow() {
|
|||
}
|
||||
|
||||
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
if (g_pInputManager->currentlyDraggedWindow.expired())
|
||||
return;
|
||||
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock();
|
||||
|
||||
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
||||
if (!validMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
|
||||
onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
if ((!validMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D())) {
|
||||
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -474,9 +475,9 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
|||
|
||||
void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
||||
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
if (pWindow->isFullscreen()) {
|
||||
Debug::log(LOG, "changeWindowFloatingMode: fullscreen");
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
}
|
||||
|
||||
pWindow->m_bPinned = false;
|
||||
|
@ -496,7 +497,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
|||
const auto PWORKSPACE = PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false);
|
||||
g_pCompositor->setWindowFullscreenInternal(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FSMODE_NONE);
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.goal();
|
||||
|
|
|
@ -63,7 +63,7 @@ class IHyprLayout {
|
|||
Called when the monitor requires a layout recalculation
|
||||
this usually means reserved area changes
|
||||
*/
|
||||
virtual void recalculateMonitor(const int&) = 0;
|
||||
virtual void recalculateMonitor(const MONITORID&) = 0;
|
||||
|
||||
/*
|
||||
Called when the compositor requests a window
|
||||
|
@ -110,7 +110,7 @@ class IHyprLayout {
|
|||
The layout sets all the fullscreen flags.
|
||||
It can either accept or ignore.
|
||||
*/
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool) = 0;
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) = 0;
|
||||
|
||||
/*
|
||||
Called when a dispatcher requests a custom message
|
||||
|
|
|
@ -14,7 +14,7 @@ SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
|
||||
int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == ws)
|
||||
|
@ -24,7 +24,7 @@ int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
|
|||
return no;
|
||||
}
|
||||
|
||||
int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
|
||||
int CHyprMasterLayout::getMastersOnWorkspace(const WORKSPACEID& ws) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == ws && n.isMaster)
|
||||
|
@ -34,7 +34,7 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
|
|||
return no;
|
||||
}
|
||||
|
||||
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
|
||||
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const WORKSPACEID& ws) {
|
||||
for (auto& n : m_lMasterWorkspacesData) {
|
||||
if (n.workspaceID == ws)
|
||||
return &n;
|
||||
|
@ -63,7 +63,7 @@ std::string CHyprMasterLayout::getLayoutName() {
|
|||
return "Master";
|
||||
}
|
||||
|
||||
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) {
|
||||
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const WORKSPACEID& ws) {
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.isMaster && n.workspaceID == ws)
|
||||
return &n;
|
||||
|
@ -267,7 +267,8 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
|||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
||||
pWindow->updateWindowData();
|
||||
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
if (pWindow->isFullscreen())
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, FSMODE_NONE);
|
||||
|
||||
if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) {
|
||||
// find a new master from top of the list
|
||||
|
@ -303,7 +304,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
|||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
||||
void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
|
||||
if (!PMONITOR || !PMONITOR->activeWorkspace)
|
||||
|
@ -327,10 +328,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
|||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
|
||||
|
||||
if (pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
|
||||
PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
|
||||
} else if (pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
|
||||
SMasterNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
|
@ -644,7 +645,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
|||
// if user specified them in config
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(PWINDOW->m_pWorkspace);
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->unsetWindowData(PRIORITY_LAYOUT);
|
||||
|
@ -668,8 +669,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
|||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
|
||||
if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() &&
|
||||
(getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||
if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() && (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || PWINDOW->isEffectiveInternalFSMode(FSMODE_MAXIMIZED))) {
|
||||
|
||||
PWINDOW->m_sWindowData.decorate = CWindowOverridableVar(true, PRIORITY_LAYOUT);
|
||||
PWINDOW->m_sWindowData.noBorder = CWindowOverridableVar(*PNOGAPSWHENONLY != 2, PRIORITY_LAYOUT);
|
||||
|
@ -688,6 +688,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
|||
return;
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
auto calcPos = PWINDOW->m_vPosition;
|
||||
auto calcSize = PWINDOW->m_vSize;
|
||||
|
||||
|
@ -702,7 +704,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
|||
calcPos = calcPos + RESERVED.topLeft;
|
||||
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||
|
||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->m_bIsFullscreen) {
|
||||
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->isFullscreen()) {
|
||||
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("master:special_scale_factor");
|
||||
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
|
@ -730,8 +732,6 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
|||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) {
|
||||
|
@ -880,41 +880,19 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
|||
m_bForceWarps = false;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!validMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
// if the window wants to be fullscreen but there already is one,
|
||||
// ignore the request.
|
||||
return;
|
||||
}
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating && on) {
|
||||
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goal();
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
pWindow->updateWindowDecos();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
if (EFFECTIVE_MODE == FSMODE_NONE) {
|
||||
// if it got its fullscreen disabled, set back its node if it had one
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
if (PNODE)
|
||||
|
@ -928,12 +906,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree
|
|||
pWindow->updateWindowData();
|
||||
}
|
||||
} else {
|
||||
// if it now got fullscreen, make it fullscreen
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||
} else {
|
||||
|
@ -954,13 +928,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, eFullscree
|
|||
}
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::recalculateWindow(PHLWINDOW pWindow) {
|
||||
|
@ -1081,14 +1049,14 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
if (!validMapped(PWINDOWTOCHANGETO))
|
||||
return;
|
||||
|
||||
if (header.pWindow->m_bIsFullscreen) {
|
||||
if (header.pWindow->isFullscreen()) {
|
||||
const auto PWORKSPACE = header.pWindow->m_pWorkspace;
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
const auto FSMODE = header.pWindow->m_sFullscreenState.internal;
|
||||
static auto INHERITFULLSCREEN = CConfigValue<Hyprlang::INT>("master:inherit_fullscreen");
|
||||
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE);
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
if (*INHERITFULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle());
|
||||
|
@ -1208,7 +1176,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);
|
||||
|
||||
if (PWINDOWTOSWAPWITH) {
|
||||
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE);
|
||||
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
||||
switchToWindow(header.pWindow);
|
||||
}
|
||||
|
@ -1224,7 +1192,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);
|
||||
|
||||
if (PWINDOWTOSWAPWITH) {
|
||||
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenClient(header.pWindow, FSMODE_NONE);
|
||||
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
||||
switchToWindow(header.pWindow);
|
||||
}
|
||||
|
@ -1243,7 +1211,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
|
||||
if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0)
|
||||
return 0;
|
||||
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE);
|
||||
|
||||
if (!PNODE || PNODE->isMaster) {
|
||||
// first non-master node
|
||||
|
@ -1275,7 +1244,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
if (WINDOWS < 2 || MASTERS < 2)
|
||||
return 0;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE);
|
||||
|
||||
if (!PNODE || !PNODE->isMaster) {
|
||||
// first non-master node
|
||||
|
@ -1296,7 +1265,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
|||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID());
|
||||
|
||||
|
@ -1392,7 +1361,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi
|
|||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID());
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ struct SMasterNodeData {
|
|||
|
||||
float percSize = 1.f; // size multiplier for resizing children
|
||||
|
||||
int workspaceID = -1;
|
||||
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
||||
|
||||
bool ignoreFullscreenChecks = false;
|
||||
|
||||
|
@ -41,7 +41,7 @@ struct SMasterNodeData {
|
|||
};
|
||||
|
||||
struct SMasterWorkspaceData {
|
||||
int workspaceID = -1;
|
||||
WORKSPACEID workspaceID = WORKSPACE_INVALID;
|
||||
eOrientation orientation = ORIENTATION_LEFT;
|
||||
|
||||
//
|
||||
|
@ -55,10 +55,10 @@ class CHyprMasterLayout : public IHyprLayout {
|
|||
virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT);
|
||||
virtual void onWindowRemovedTiling(PHLWINDOW);
|
||||
virtual bool isWindowTiled(PHLWINDOW);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateMonitor(const MONITORID&);
|
||||
virtual void recalculateWindow(PHLWINDOW);
|
||||
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool);
|
||||
virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(PHLWINDOW);
|
||||
virtual void switchWindows(PHLWINDOW, PHLWINDOW);
|
||||
|
@ -81,14 +81,14 @@ class CHyprMasterLayout : public IHyprLayout {
|
|||
void buildOrientationCycleVectorFromEOperation(std::vector<eOrientation>& cycle);
|
||||
void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next);
|
||||
eOrientation getDynamicOrientation(PHLWORKSPACE);
|
||||
int getNodesOnWorkspace(const int&);
|
||||
int getNodesOnWorkspace(const WORKSPACEID&);
|
||||
void applyNodeDataToWindow(SMasterNodeData*);
|
||||
SMasterNodeData* getNodeFromWindow(PHLWINDOW);
|
||||
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
SMasterWorkspaceData* getMasterWorkspaceData(const int&);
|
||||
SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
|
||||
SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&);
|
||||
void calculateWorkspace(PHLWORKSPACE);
|
||||
PHLWINDOW getNextWindow(PHLWINDOW, bool);
|
||||
int getMastersOnWorkspace(const int&);
|
||||
int getMastersOnWorkspace(const WORKSPACEID&);
|
||||
|
||||
friend struct SMasterNodeData;
|
||||
friend struct SMasterWorkspaceData;
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define WORKSPACE_INVALID -1L
|
||||
#define WORKSPACE_NOT_CHANGED -101
|
||||
|
||||
#define MONITOR_INVALID -1L
|
||||
|
||||
#define LISTENER(name) \
|
||||
void listener_##name(wl_listener*, void*); \
|
||||
inline wl_listener listen_##name = {.notify = listener_##name}
|
||||
|
|
|
@ -3,15 +3,10 @@
|
|||
#include "../config/ConfigValue.hpp"
|
||||
#include "PointerManager.hpp"
|
||||
#include "../xwayland/XWayland.hpp"
|
||||
#include <cstring>
|
||||
#include "../helpers/CursorShapes.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
}
|
||||
|
||||
static int cursorAnimTimer(void* data) {
|
||||
g_pCursorManager->tickAnimatedCursor();
|
||||
static int cursorAnimTimer(SP<CEventLoopTimer> self, void* data) {
|
||||
const auto cursorMgr = reinterpret_cast<CCursorManager*>(data);
|
||||
cursorMgr->tickAnimatedCursor();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -22,85 +17,39 @@ static void hcLogger(enum eHyprcursorLogLevel level, char* message) {
|
|||
Debug::log(NONE, "[hc] {}", message);
|
||||
}
|
||||
|
||||
CCursorManager::CCursorManager() {
|
||||
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger);
|
||||
|
||||
if (!m_pHyprcursor->valid())
|
||||
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", m_szTheme);
|
||||
|
||||
// find default size. First, HYPRCURSOR_SIZE, then XCURSOR_SIZE, then 24
|
||||
auto SIZE = getenv("HYPRCURSOR_SIZE");
|
||||
if (SIZE) {
|
||||
try {
|
||||
m_iSize = std::stoi(SIZE);
|
||||
} catch (...) { ; }
|
||||
}
|
||||
|
||||
SIZE = getenv("XCURSOR_SIZE");
|
||||
if (SIZE && m_iSize == 0) {
|
||||
try {
|
||||
m_iSize = std::stoi(SIZE);
|
||||
} catch (...) { ; }
|
||||
}
|
||||
|
||||
if (m_iSize == 0)
|
||||
m_iSize = 24;
|
||||
|
||||
xcursor.loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "", m_iSize * std::ceil(m_fCursorScale));
|
||||
|
||||
m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr);
|
||||
|
||||
updateTheme();
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateTheme(); });
|
||||
}
|
||||
|
||||
CCursorManager::~CCursorManager() {
|
||||
if (m_pAnimationTimer)
|
||||
wl_event_source_remove(m_pAnimationTimer);
|
||||
}
|
||||
|
||||
void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) {
|
||||
std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; });
|
||||
}
|
||||
|
||||
CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
surface = surf;
|
||||
size = size_;
|
||||
stride = cairo_image_surface_get_stride(surf);
|
||||
}
|
||||
|
||||
CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||
pixelData = pixelData_;
|
||||
size = size_;
|
||||
stride = 4 * size_.x;
|
||||
}
|
||||
|
||||
CCursorManager::CCursorBuffer::~CCursorBuffer() {
|
||||
;
|
||||
}
|
||||
|
||||
Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() {
|
||||
Aquamarine::eBufferCapability CCursorBuffer::caps() {
|
||||
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
|
||||
}
|
||||
|
||||
Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() {
|
||||
Aquamarine::eBufferType CCursorBuffer::type() {
|
||||
return Aquamarine::eBufferType::BUFFER_TYPE_SHM;
|
||||
}
|
||||
|
||||
void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) {
|
||||
void CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) {
|
||||
;
|
||||
}
|
||||
|
||||
bool CCursorManager::CCursorBuffer::isSynchronous() {
|
||||
bool CCursorBuffer::isSynchronous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCursorManager::CCursorBuffer::good() {
|
||||
bool CCursorBuffer::good() {
|
||||
return true;
|
||||
}
|
||||
|
||||
Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() {
|
||||
Aquamarine::SSHMAttrs CCursorBuffer::shm() {
|
||||
Aquamarine::SSHMAttrs attrs;
|
||||
attrs.success = true;
|
||||
attrs.format = DRM_FORMAT_ARGB8888;
|
||||
|
@ -109,14 +58,70 @@ Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() {
|
|||
return attrs;
|
||||
}
|
||||
|
||||
std::tuple<uint8_t*, uint32_t, size_t> CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) {
|
||||
std::tuple<uint8_t*, uint32_t, size_t> CCursorBuffer::beginDataPtr(uint32_t flags) {
|
||||
return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride};
|
||||
}
|
||||
|
||||
void CCursorManager::CCursorBuffer::endDataPtr() {
|
||||
void CCursorBuffer::endDataPtr() {
|
||||
;
|
||||
}
|
||||
|
||||
CCursorManager::CCursorManager() {
|
||||
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger);
|
||||
m_pXcursor = std::make_unique<CXCursorManager>();
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
|
||||
|
||||
if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) {
|
||||
// find default size. First, HYPRCURSOR_SIZE then default to 24
|
||||
auto const* SIZE = getenv("HYPRCURSOR_SIZE");
|
||||
if (SIZE) {
|
||||
try {
|
||||
m_iSize = std::stoi(SIZE);
|
||||
} catch (...) { ; }
|
||||
}
|
||||
|
||||
if (m_iSize <= 0) {
|
||||
Debug::log(WARN, "HYPRCURSOR_SIZE size not set, defaulting to size 24");
|
||||
m_iSize = 24;
|
||||
}
|
||||
} else {
|
||||
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to Xcursor.", m_szTheme);
|
||||
|
||||
auto const* SIZE = getenv("XCURSOR_SIZE");
|
||||
if (SIZE) {
|
||||
try {
|
||||
m_iSize = std::stoi(SIZE);
|
||||
} catch (...) { ; }
|
||||
}
|
||||
|
||||
if (m_iSize <= 0) {
|
||||
Debug::log(WARN, "XCURSOR_SIZE size not set, defaulting to size 24");
|
||||
m_iSize = 24;
|
||||
}
|
||||
}
|
||||
|
||||
// since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config
|
||||
// and then later is disabled.
|
||||
m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale));
|
||||
|
||||
m_pAnimationTimer = makeShared<CEventLoopTimer>(std::nullopt, cursorAnimTimer, this);
|
||||
g_pEventLoopManager->addTimer(m_pAnimationTimer);
|
||||
|
||||
updateTheme();
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateTheme(); });
|
||||
}
|
||||
|
||||
CCursorManager::~CCursorManager() {
|
||||
if (m_pAnimationTimer && g_pEventLoopManager) {
|
||||
g_pEventLoopManager->removeTimer(m_pAnimationTimer);
|
||||
m_pAnimationTimer.reset();
|
||||
}
|
||||
|
||||
if (m_pHyprcursor->valid() && m_sCurrentStyleInfo.size > 0)
|
||||
m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo);
|
||||
}
|
||||
|
||||
SP<Aquamarine::IBuffer> CCursorManager::getCursorBuffer() {
|
||||
return !m_vCursorBuffers.empty() ? m_vCursorBuffers.back() : nullptr;
|
||||
}
|
||||
|
@ -130,106 +135,126 @@ void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotsp
|
|||
m_bOurBufferConnected = false;
|
||||
}
|
||||
|
||||
void CCursorManager::setXCursor(const std::string& name) {
|
||||
float scale = std::ceil(m_fCursorScale);
|
||||
|
||||
if (!xcursor.themeLoaded) {
|
||||
Debug::log(ERR, "XCursor failed to find theme in setXCursor");
|
||||
g_pPointerManager->resetCursorImage();
|
||||
return;
|
||||
}
|
||||
|
||||
auto& icon = xcursor.defaultCursor;
|
||||
// try to get an icon we know if we have one
|
||||
if (xcursor.cursors.contains(name))
|
||||
icon = xcursor.cursors.at(name);
|
||||
|
||||
m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>((uint8_t*)icon->pixels.data(), icon->size, icon->hotspot));
|
||||
|
||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), icon->hotspot / scale, scale);
|
||||
void CCursorManager::setCursorBuffer(SP<CCursorBuffer> buf, const Vector2D& hotspot, const float& scale) {
|
||||
m_vCursorBuffers.emplace_back(buf);
|
||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), hotspot, scale);
|
||||
if (m_vCursorBuffers.size() > 1)
|
||||
dropBufferRef(m_vCursorBuffers.at(0).get());
|
||||
std::erase_if(m_vCursorBuffers, [this](const auto& buf) { return buf.get() == m_vCursorBuffers.front().get(); });
|
||||
|
||||
m_bOurBufferConnected = true;
|
||||
}
|
||||
|
||||
void CCursorManager::setAnimationTimer(const int& frame, const int& delay) {
|
||||
if (delay > 0) {
|
||||
// arm
|
||||
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(delay));
|
||||
} else {
|
||||
// disarm
|
||||
m_pAnimationTimer->updateTimeout(std::nullopt);
|
||||
}
|
||||
|
||||
m_iCurrentAnimationFrame = frame;
|
||||
}
|
||||
|
||||
void CCursorManager::setCursorFromName(const std::string& name) {
|
||||
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
|
||||
|
||||
if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) {
|
||||
setXCursor(name);
|
||||
return;
|
||||
}
|
||||
auto setXCursor = [this](auto const& name) {
|
||||
float scale = std::ceil(m_fCursorScale);
|
||||
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo);
|
||||
auto xcursor = m_pXcursor->getShape(name, m_iSize * scale);
|
||||
auto& icon = xcursor->images.front();
|
||||
auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot);
|
||||
setCursorBuffer(buf, icon.hotspot / scale, scale);
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
// try with '_' first (old hc, etc)
|
||||
std::string newName = name;
|
||||
std::replace(newName.begin(), newName.end(), '-', '_');
|
||||
m_currentXcursor = xcursor;
|
||||
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo);
|
||||
}
|
||||
int delay = 0;
|
||||
int frame = 0;
|
||||
if (m_currentXcursor->images.size() > 1)
|
||||
delay = m_currentXcursor->images[frame].delay;
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
// fallback to a default if available
|
||||
constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"};
|
||||
setAnimationTimer(frame, delay);
|
||||
};
|
||||
|
||||
for (auto& s : fallbackShapes) {
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo);
|
||||
auto setHyprCursor = [this](auto const& name) {
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo);
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() > 0)
|
||||
break;
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
// try with '_' first (old hc, etc)
|
||||
std::string newName = name;
|
||||
std::replace(newName.begin(), newName.end(), '-', '_');
|
||||
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(newName.c_str(), m_sCurrentStyleInfo);
|
||||
}
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName");
|
||||
setXCursor(name);
|
||||
return;
|
||||
// fallback to a default if available
|
||||
constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"};
|
||||
|
||||
for (auto& s : fallbackShapes) {
|
||||
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo);
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||
Debug::log(ERR, "BUG THIS: No fallback found for a cursor in setCursorFromName");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface,
|
||||
Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}));
|
||||
auto buf =
|
||||
makeShared<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface, Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY});
|
||||
auto hotspot = Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale;
|
||||
setCursorBuffer(buf, hotspot, m_fCursorScale);
|
||||
|
||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale,
|
||||
m_fCursorScale);
|
||||
if (m_vCursorBuffers.size() > 1)
|
||||
dropBufferRef(m_vCursorBuffers.at(0).get());
|
||||
int delay = 0;
|
||||
int frame = 0;
|
||||
if (m_sCurrentCursorShapeData.images.size() > 1)
|
||||
delay = m_sCurrentCursorShapeData.images[frame].delay;
|
||||
|
||||
m_bOurBufferConnected = true;
|
||||
setAnimationTimer(frame, delay);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (m_sCurrentCursorShapeData.images.size() > 1) {
|
||||
// animated
|
||||
wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[0].delay);
|
||||
m_iCurrentAnimationFrame = 0;
|
||||
} else {
|
||||
// disarm
|
||||
wl_event_source_timer_update(m_pAnimationTimer, 0);
|
||||
}
|
||||
if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR || !setHyprCursor(name))
|
||||
setXCursor(name);
|
||||
}
|
||||
|
||||
void CCursorManager::tickAnimatedCursor() {
|
||||
if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected)
|
||||
if (!m_bOurBufferConnected)
|
||||
return;
|
||||
|
||||
m_iCurrentAnimationFrame++;
|
||||
if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size())
|
||||
m_iCurrentAnimationFrame = 0;
|
||||
if (!m_pHyprcursor->valid() && m_currentXcursor->images.size() > 1) {
|
||||
m_iCurrentAnimationFrame++;
|
||||
|
||||
m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>(
|
||||
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface,
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}));
|
||||
if ((size_t)m_iCurrentAnimationFrame >= m_currentXcursor->images.size())
|
||||
m_iCurrentAnimationFrame = 0;
|
||||
|
||||
g_pPointerManager->setCursorBuffer(
|
||||
getCursorBuffer(),
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale,
|
||||
m_fCursorScale);
|
||||
float scale = std::ceil(m_fCursorScale);
|
||||
auto& icon = m_currentXcursor->images.at(m_iCurrentAnimationFrame);
|
||||
auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot);
|
||||
setCursorBuffer(buf, icon.hotspot / scale, scale);
|
||||
setAnimationTimer(m_iCurrentAnimationFrame, m_currentXcursor->images[m_iCurrentAnimationFrame].delay);
|
||||
} else if (m_sCurrentCursorShapeData.images.size() > 1) {
|
||||
m_iCurrentAnimationFrame++;
|
||||
|
||||
wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay);
|
||||
if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size())
|
||||
m_iCurrentAnimationFrame = 0;
|
||||
|
||||
auto hotspot =
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY} / m_fCursorScale;
|
||||
auto buf = makeShared<CCursorBuffer>(
|
||||
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface,
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY});
|
||||
setCursorBuffer(buf, hotspot, m_fCursorScale);
|
||||
setAnimationTimer(m_iCurrentAnimationFrame, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay);
|
||||
}
|
||||
}
|
||||
|
||||
SCursorImageData CCursorManager::dataFor(const std::string& name) {
|
||||
|
@ -246,32 +271,39 @@ SCursorImageData CCursorManager::dataFor(const std::string& name) {
|
|||
}
|
||||
|
||||
void CCursorManager::setXWaylandCursor() {
|
||||
const auto CURSOR = dataFor("left_ptr");
|
||||
if (CURSOR.surface) {
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
|
||||
const auto CURSOR = dataFor("left_ptr");
|
||||
if (CURSOR.surface && *PUSEHYPRCURSOR)
|
||||
g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size},
|
||||
{CURSOR.hotspotX, CURSOR.hotspotY});
|
||||
} else if (xcursor.themeLoaded)
|
||||
g_pXWayland->setCursor((uint8_t*)xcursor.defaultCursor->pixels.data(), xcursor.defaultCursor->size.x * 4, xcursor.defaultCursor->size, xcursor.defaultCursor->hotspot);
|
||||
else
|
||||
Debug::log(ERR, "CursorManager: no valid cursor for xwayland");
|
||||
else {
|
||||
auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale));
|
||||
auto& icon = xcursor->images.front();
|
||||
|
||||
g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot);
|
||||
}
|
||||
}
|
||||
|
||||
void CCursorManager::updateTheme() {
|
||||
float highestScale = 1.0;
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
|
||||
float highestScale = 1.0;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->scale > highestScale)
|
||||
highestScale = m->scale;
|
||||
}
|
||||
|
||||
if (m_sCurrentStyleInfo.size && m_pHyprcursor->valid())
|
||||
m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo);
|
||||
m_fCursorScale = highestScale;
|
||||
|
||||
m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale);
|
||||
m_fCursorScale = highestScale;
|
||||
if (*PUSEHYPRCURSOR) {
|
||||
if (m_sCurrentStyleInfo.size > 0 && m_pHyprcursor->valid())
|
||||
m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo);
|
||||
|
||||
if (m_pHyprcursor->valid())
|
||||
m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo);
|
||||
m_sCurrentStyleInfo.size = std::round(m_iSize * highestScale);
|
||||
|
||||
if (m_pHyprcursor->valid())
|
||||
m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo);
|
||||
}
|
||||
|
||||
setCursorFromName("left_ptr");
|
||||
|
||||
|
@ -282,177 +314,27 @@ void CCursorManager::updateTheme() {
|
|||
}
|
||||
|
||||
bool CCursorManager::changeTheme(const std::string& name, const int size) {
|
||||
auto options = Hyprcursor::SManagerOptions();
|
||||
options.logFn = hcLogger;
|
||||
options.allowDefaultFallback = false;
|
||||
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
|
||||
m_szTheme = name.empty() ? "" : name;
|
||||
m_iSize = size <= 0 ? 24 : size;
|
||||
auto xcursor_theme = getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default";
|
||||
|
||||
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(name.empty() ? "" : name.c_str(), options);
|
||||
if (m_pHyprcursor->valid()) {
|
||||
m_szTheme = name;
|
||||
m_iSize = size;
|
||||
updateTheme();
|
||||
return true;
|
||||
}
|
||||
if (*PUSEHYPRCURSOR) {
|
||||
auto options = Hyprcursor::SManagerOptions();
|
||||
options.logFn = hcLogger;
|
||||
options.allowDefaultFallback = false;
|
||||
m_szTheme = name.empty() ? "" : name;
|
||||
m_iSize = size;
|
||||
|
||||
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to X.", name);
|
||||
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options);
|
||||
if (!m_pHyprcursor->valid()) {
|
||||
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme);
|
||||
m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize);
|
||||
}
|
||||
} else
|
||||
m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize);
|
||||
|
||||
xcursor.loadTheme(name, size);
|
||||
|
||||
m_szTheme = name;
|
||||
m_iSize = size;
|
||||
updateTheme();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c
|
||||
// however modified to fit wayland cursor shape names better.
|
||||
// _ -> -
|
||||
// clang-format off
|
||||
static std::array<const char*, 77> XCURSOR_STANDARD_NAMES = {
|
||||
"X_cursor",
|
||||
"default", // arrow
|
||||
"ns-resize", // based-arrow-down
|
||||
"ns-resize", // based-arrow-up
|
||||
"boat",
|
||||
"bogosity",
|
||||
"sw-resize", // bottom-left-corner
|
||||
"se-resize", // bottom-right-corner
|
||||
"s-resize", // bottom-side
|
||||
"bottom-tee",
|
||||
"box-spiral",
|
||||
"center-ptr",
|
||||
"circle",
|
||||
"clock",
|
||||
"coffee-mug",
|
||||
"cross",
|
||||
"cross-reverse",
|
||||
"crosshair",
|
||||
"diamond-cross",
|
||||
"dot",
|
||||
"dotbox",
|
||||
"double-arrow",
|
||||
"draft-large",
|
||||
"draft-small",
|
||||
"draped-box",
|
||||
"exchange",
|
||||
"move", // fleur
|
||||
"gobbler",
|
||||
"gumby",
|
||||
"pointer", // hand1
|
||||
"grabbing", // hand2
|
||||
"heart",
|
||||
"icon",
|
||||
"iron-cross",
|
||||
"default", // left-ptr
|
||||
"w-resize", // left-side
|
||||
"left-tee",
|
||||
"leftbutton",
|
||||
"ll-angle",
|
||||
"lr-angle",
|
||||
"man",
|
||||
"middlebutton",
|
||||
"mouse",
|
||||
"pencil",
|
||||
"pirate",
|
||||
"plus",
|
||||
"help", // question-arrow
|
||||
"right-ptr",
|
||||
"e-resize", // right-side
|
||||
"right-tee",
|
||||
"rightbutton",
|
||||
"rtl-logo",
|
||||
"sailboat",
|
||||
"ns-resize", // sb-down-arrow
|
||||
"ew-resize", // sb-h-double-arrow
|
||||
"ew-resize", // sb-left-arrow
|
||||
"ew-resize", // sb-right-arrow
|
||||
"n-resize", // sb-up-arrow
|
||||
"s-resize", // sb-v-double-arrow
|
||||
"shuttle",
|
||||
"sizing",
|
||||
"spider",
|
||||
"spraycan",
|
||||
"star",
|
||||
"target",
|
||||
"cell", // tcross
|
||||
"nw-resize", // top-left-arrow
|
||||
"nw-resize", // top-left-corner
|
||||
"ne-resize", // top-right-corner
|
||||
"n-resize", // top-side
|
||||
"top-tee",
|
||||
"trek",
|
||||
"ul-angle",
|
||||
"umbrella",
|
||||
"ur-angle",
|
||||
"wait", // watch
|
||||
"text", // xterm
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void CCursorManager::SXCursorManager::loadTheme(const std::string& name, int size) {
|
||||
if (lastLoadSize == size && themeName == name)
|
||||
return;
|
||||
|
||||
lastLoadSize = size;
|
||||
themeLoaded = false;
|
||||
themeName = name.empty() ? "default" : name;
|
||||
|
||||
auto img = XcursorShapeLoadImage(2, themeName.c_str(), size);
|
||||
|
||||
if (!img) {
|
||||
Debug::log(ERR, "XCursor failed finding theme \"{}\". Trying size 24.", themeName);
|
||||
size = 24;
|
||||
img = XcursorShapeLoadImage(2, themeName.c_str(), size);
|
||||
if (!img) {
|
||||
Debug::log(ERR, "XCursor failed finding theme \"{}\".", themeName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
defaultCursor = makeShared<SXCursor>();
|
||||
defaultCursor->size = {(int)img->width, (int)img->height};
|
||||
defaultCursor->hotspot = {(int)img->xhot, (int)img->yhot};
|
||||
|
||||
defaultCursor->pixels.resize(img->width * img->height);
|
||||
std::memcpy(defaultCursor->pixels.data(), img->pixels, img->width * img->height * sizeof(uint32_t));
|
||||
|
||||
themeLoaded = true;
|
||||
|
||||
XcursorImageDestroy(img);
|
||||
|
||||
// gather as many shapes as we can find.
|
||||
cursors.clear();
|
||||
|
||||
for (auto& shape : CURSOR_SHAPE_NAMES) {
|
||||
int id = -1;
|
||||
for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) {
|
||||
if (XCURSOR_STANDARD_NAMES.at(i) == std::string{shape}) {
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id < 0) {
|
||||
Debug::log(LOG, "XCursor has no shape {}, skipping", shape);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto xImage = XcursorShapeLoadImage(id << 1 /* wtf xcursor? */, themeName.c_str(), size);
|
||||
|
||||
if (!xImage) {
|
||||
Debug::log(LOG, "XCursor failed to find a shape with name {}, skipping", shape);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto xcursor = makeShared<SXCursor>();
|
||||
xcursor->size = {(int)xImage->width, (int)xImage->height};
|
||||
xcursor->hotspot = {(int)xImage->xhot, (int)xImage->yhot};
|
||||
|
||||
xcursor->pixels.resize(xImage->width * xImage->height);
|
||||
std::memcpy(xcursor->pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t));
|
||||
|
||||
cursors.emplace(std::string{shape}, xcursor);
|
||||
|
||||
XcursorImageDestroy(xImage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,12 +7,36 @@
|
|||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/memory/Memory.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "managers/XCursorManager.hpp"
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
|
||||
class CWLSurface;
|
||||
|
||||
AQUAMARINE_FORWARD(IBuffer);
|
||||
|
||||
class CCursorBuffer : public Aquamarine::IBuffer {
|
||||
public:
|
||||
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
||||
CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot);
|
||||
~CCursorBuffer() = default;
|
||||
|
||||
virtual Aquamarine::eBufferCapability caps();
|
||||
virtual Aquamarine::eBufferType type();
|
||||
virtual void update(const Hyprutils::Math::CRegion& damage);
|
||||
virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||
virtual bool good();
|
||||
virtual Aquamarine::SSHMAttrs shm();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
|
||||
private:
|
||||
Vector2D hotspot;
|
||||
cairo_surface_t* surface = nullptr;
|
||||
uint8_t* pixelData = nullptr;
|
||||
size_t stride = 0;
|
||||
};
|
||||
|
||||
class CCursorManager {
|
||||
public:
|
||||
CCursorManager();
|
||||
|
@ -22,7 +46,8 @@ class CCursorManager {
|
|||
|
||||
void setCursorFromName(const std::string& name);
|
||||
void setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot);
|
||||
void setXCursor(const std::string& name);
|
||||
void setCursorBuffer(SP<CCursorBuffer> buf, const Vector2D& hotspot, const float& scale);
|
||||
void setAnimationTimer(const int& frame, const int& delay);
|
||||
|
||||
bool changeTheme(const std::string& name, const int size);
|
||||
void updateTheme();
|
||||
|
@ -31,38 +56,13 @@ class CCursorManager {
|
|||
|
||||
void tickAnimatedCursor();
|
||||
|
||||
class CCursorBuffer : public Aquamarine::IBuffer {
|
||||
public:
|
||||
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
||||
CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot);
|
||||
~CCursorBuffer();
|
||||
|
||||
virtual Aquamarine::eBufferCapability caps();
|
||||
virtual Aquamarine::eBufferType type();
|
||||
virtual void update(const Hyprutils::Math::CRegion& damage);
|
||||
virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||
virtual bool good();
|
||||
virtual Aquamarine::SSHMAttrs shm();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
|
||||
private:
|
||||
Vector2D hotspot;
|
||||
cairo_surface_t* surface = nullptr;
|
||||
uint8_t* pixelData = nullptr;
|
||||
size_t stride = 0;
|
||||
|
||||
friend class CCursorManager;
|
||||
};
|
||||
|
||||
void dropBufferRef(CCursorBuffer* ref);
|
||||
|
||||
bool m_bOurBufferConnected = false;
|
||||
|
||||
private:
|
||||
bool m_bOurBufferConnected = false;
|
||||
std::vector<SP<CCursorBuffer>> m_vCursorBuffers;
|
||||
|
||||
std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor;
|
||||
std::unique_ptr<CXCursorManager> m_pXcursor;
|
||||
SP<SXCursors> m_currentXcursor;
|
||||
|
||||
std::string m_szTheme = "";
|
||||
int m_iSize = 0;
|
||||
|
@ -70,28 +70,9 @@ class CCursorManager {
|
|||
|
||||
Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo;
|
||||
|
||||
wl_event_source* m_pAnimationTimer = nullptr;
|
||||
SP<CEventLoopTimer> m_pAnimationTimer;
|
||||
int m_iCurrentAnimationFrame = 0;
|
||||
Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData;
|
||||
|
||||
// gangsta bootleg XCursor impl. Whenever Hyprland has to use
|
||||
// an xcursor, just use the pointer.
|
||||
struct SXCursor {
|
||||
Vector2D size;
|
||||
Vector2D hotspot;
|
||||
std::vector<uint32_t> pixels; // XPixel is a u32
|
||||
};
|
||||
|
||||
struct SXCursorManager {
|
||||
void loadTheme(const std::string& name, int size);
|
||||
|
||||
int lastLoadSize = 0;
|
||||
|
||||
bool themeLoaded = false;
|
||||
std::string themeName = "";
|
||||
SP<SXCursor> defaultCursor;
|
||||
std::unordered_map<std::string, SP<SXCursor>> cursors;
|
||||
} xcursor;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CCursorManager> g_pCursorManager;
|
|
@ -8,6 +8,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
CEventManager::CEventManager() {
|
||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../managers/SeatManager.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/ShortcutsInhibit.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "../devices/IKeyboard.hpp"
|
||||
#include "KeybindManager.hpp"
|
||||
|
@ -67,7 +68,7 @@ CKeybindManager::CKeybindManager() {
|
|||
m_mDispatchers["workspace"] = changeworkspace;
|
||||
m_mDispatchers["renameworkspace"] = renameWorkspace;
|
||||
m_mDispatchers["fullscreen"] = fullscreenActive;
|
||||
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
|
||||
m_mDispatchers["fullscreenstate"] = fullscreenStateActive;
|
||||
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
|
||||
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
|
||||
m_mDispatchers["pseudo"] = toggleActivePseudo;
|
||||
|
@ -179,6 +180,9 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
|||
}
|
||||
|
||||
uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) {
|
||||
if (keycode == 0)
|
||||
return 0;
|
||||
|
||||
switch (keycode - 8) {
|
||||
case KEY_LEFTMETA: return HL_MODIFIER_META;
|
||||
case KEY_RIGHTMETA: return HL_MODIFIER_META;
|
||||
|
@ -242,27 +246,14 @@ void CKeybindManager::updateXKBTranslationState() {
|
|||
}
|
||||
|
||||
bool CKeybindManager::ensureMouseBindState() {
|
||||
if (!m_bIsMouseBindActive)
|
||||
if (!g_pInputManager->currentlyDraggedWindow)
|
||||
return false;
|
||||
|
||||
if (!g_pInputManager->currentlyDraggedWindow.expired()) {
|
||||
PHLWINDOW lastDraggedWindow = g_pInputManager->currentlyDraggedWindow.lock();
|
||||
|
||||
m_bIsMouseBindActive = false;
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
|
||||
g_pCompositor->updateWorkspaceWindows(lastDraggedWindow->workspaceID());
|
||||
g_pCompositor->updateWorkspaceWindowData(lastDraggedWindow->workspaceID());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(lastDraggedWindow->m_iMonitorID);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
changeMouseBindMode(MBIND_INVALID);
|
||||
return true;
|
||||
}
|
||||
|
||||
m_bIsMouseBindActive = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -331,17 +322,17 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
|
|||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
if (PLASTWINDOW && PLASTWINDOW->m_pWorkspace == PWINDOWTOCHANGETO->m_pWorkspace && PLASTWINDOW->m_bIsFullscreen) {
|
||||
if (PLASTWINDOW && PLASTWINDOW->m_pWorkspace == PWINDOWTOCHANGETO->m_pWorkspace && PLASTWINDOW->isFullscreen()) {
|
||||
const auto PWORKSPACE = PLASTWINDOW->m_pWorkspace;
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
const auto MODE = PWORKSPACE->m_efFullscreenMode;
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE);
|
||||
} else {
|
||||
updateRelativeCursorCoords();
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
@ -540,10 +531,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) {
|
|||
}
|
||||
|
||||
void CKeybindManager::resizeWithBorder(const IPointer::SButtonEvent& e) {
|
||||
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
mouse("1resizewindow");
|
||||
else
|
||||
mouse("0resizewindow");
|
||||
changeMouseBindMode(e.state == WL_POINTER_BUTTON_STATE_PRESSED ? MBIND_RESIZE : MBIND_INVALID);
|
||||
}
|
||||
|
||||
void CKeybindManager::onSwitchEvent(const std::string& switchName) {
|
||||
|
@ -654,18 +642,17 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi
|
|||
if (found || key.submapAtPress != m_szCurrentSelectedSubmap)
|
||||
continue;
|
||||
} else {
|
||||
// in this case, we only have the keysym to go off.
|
||||
// if the keysym failed resolving, we can't do anything. It's likely missing
|
||||
// from the keymap.
|
||||
if (key.keysym == 0)
|
||||
return false;
|
||||
// in this case, we only have the keysym to go off of for this keybind, and it's invalid
|
||||
// since there might be something like keycode to match with other keybinds, try the next
|
||||
if (key.keysym == XKB_KEY_NoSymbol)
|
||||
continue;
|
||||
|
||||
// oMg such performance hit!!11!
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_NO_FLAGS);
|
||||
const auto KBKEYLOWER = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
|
||||
if (KBKEY == 0 && KBKEYLOWER == 0) {
|
||||
if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) {
|
||||
// Keysym failed to resolve from the key name of the currently iterated bind.
|
||||
// This happens for names such as `switch:off:Lid Switch` as well as some keys
|
||||
// (such as yen and ro).
|
||||
|
@ -971,7 +958,8 @@ static void toggleActiveFloatingCore(std::string args, std::optional<bool> float
|
|||
return;
|
||||
|
||||
// remove drag status
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
if (!g_pInputManager->currentlyDraggedWindow.expired())
|
||||
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
|
||||
|
||||
if (PWINDOW->m_sGroupData.pNextWindow.lock() && PWINDOW->m_sGroupData.pNextWindow.lock() != PWINDOW) {
|
||||
const auto PCURRENT = PWINDOW->getGroupCurrent();
|
||||
|
@ -1010,7 +998,7 @@ void CKeybindManager::setActiveTiled(std::string args) {
|
|||
void CKeybindManager::centerWindow(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen)
|
||||
if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
@ -1036,7 +1024,7 @@ void CKeybindManager::toggleActivePseudo(std::string args) {
|
|||
|
||||
PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled;
|
||||
|
||||
if (!PWINDOW->m_bIsFullscreen)
|
||||
if (!PWINDOW->isFullscreen())
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW);
|
||||
}
|
||||
|
||||
|
@ -1163,10 +1151,51 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
|||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
PWINDOW->m_bDontSendFullscreen = false;
|
||||
if (args == "2")
|
||||
PWINDOW->m_bDontSendFullscreen = true;
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
|
||||
const eFullscreenMode MODE = args == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN;
|
||||
|
||||
if (PWINDOW->isEffectiveInternalFSMode(MODE))
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||
else
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE);
|
||||
}
|
||||
|
||||
void CKeybindManager::fullscreenStateActive(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
const auto ARGS = CVarList(args, 2, ' ');
|
||||
|
||||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP);
|
||||
|
||||
int internalMode, clientMode;
|
||||
try {
|
||||
internalMode = std::stoi(ARGS[0]);
|
||||
} catch (std::exception& e) { internalMode = -1; }
|
||||
try {
|
||||
clientMode = std::stoi(ARGS[1]);
|
||||
} catch (std::exception& e) { clientMode = -1; }
|
||||
|
||||
const sFullscreenState STATE = sFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal),
|
||||
.client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)};
|
||||
|
||||
if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client) {
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE});
|
||||
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(true, PRIORITY_SET_PROP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal) {
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client});
|
||||
return;
|
||||
}
|
||||
|
||||
if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client) {
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, sFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE});
|
||||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->setWindowFullscreenState(PWINDOW, STATE);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
@ -1291,7 +1320,7 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ?
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
|
@ -1348,7 +1377,7 @@ void CKeybindManager::swapActive(std::string args) {
|
|||
|
||||
Debug::log(LOG, "Swapping active window in direction {}", arg);
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen)
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
@ -1386,7 +1415,7 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
|||
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen)
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
if (PLASTWINDOW->m_bIsFloating) {
|
||||
|
@ -1441,7 +1470,8 @@ void CKeybindManager::toggleGroup(std::string args) {
|
|||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
if (PWINDOW->isFullscreen())
|
||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||
|
||||
if (PWINDOW->m_sGroupData.pNextWindow.expired())
|
||||
PWINDOW->createGroup();
|
||||
|
@ -1710,7 +1740,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
const int WORKSPACEID = getWorkspaceIDNameFromString(workspace).id;
|
||||
const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id;
|
||||
|
||||
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
|
||||
|
@ -1728,7 +1758,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
|||
}
|
||||
|
||||
void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
|
||||
int workspaceID = getWorkspaceIDNameFromString(args).id;
|
||||
auto workspaceID = getWorkspaceIDNameFromString(args).id;
|
||||
if (workspaceID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
|
||||
return;
|
||||
|
@ -1788,7 +1818,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
|||
|
||||
bool requestedWorkspaceIsAlreadyOpen = false;
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
int specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID();
|
||||
auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID();
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->activeSpecialWorkspaceID() == workspaceID) {
|
||||
|
@ -1833,7 +1863,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
|||
void CKeybindManager::resizeActive(std::string args) {
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen)
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize.goal());
|
||||
|
@ -1850,7 +1880,7 @@ void CKeybindManager::resizeActive(std::string args) {
|
|||
void CKeybindManager::moveActive(std::string args) {
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen)
|
||||
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition.goal());
|
||||
|
@ -1870,7 +1900,7 @@ void CKeybindManager::moveWindow(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
if (PWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal());
|
||||
|
@ -1890,7 +1920,7 @@ void CKeybindManager::resizeWindow(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
if (PWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal());
|
||||
|
@ -1967,12 +1997,12 @@ void CKeybindManager::focusWindow(std::string regexp) {
|
|||
g_pCompositor->focusWindow(PWINDOW);
|
||||
} else {
|
||||
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(FSWINDOW, false, FULLSCREEN_FULL);
|
||||
g_pCompositor->setWindowFullscreenClient(FSWINDOW, FSMODE_NONE);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FSMODE);
|
||||
g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE);
|
||||
}
|
||||
} else
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
@ -2264,6 +2294,7 @@ void CKeybindManager::dpms(std::string arg) {
|
|||
if (!port.empty() && m->szName != port)
|
||||
continue;
|
||||
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setEnabled(enable);
|
||||
|
||||
m->dpmsStatus = enable;
|
||||
|
@ -2344,11 +2375,19 @@ void CKeybindManager::pinActive(std::string args) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen)
|
||||
if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
PWINDOW->m_bPinned = !PWINDOW->m_bPinned;
|
||||
PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
|
||||
PWINDOW->m_bPinned = !PWINDOW->m_bPinned;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "pin: monitor not found");
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_pWorkspace = PMONITOR->activeWorkspace;
|
||||
|
||||
PWINDOW->updateDynamicRules();
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
|
@ -2365,55 +2404,50 @@ void CKeybindManager::mouse(std::string args) {
|
|||
const auto ARGS = CVarList(args.substr(1), 2, ' ');
|
||||
const auto PRESSED = args[0] == '1';
|
||||
|
||||
if (!PRESSED) {
|
||||
changeMouseBindMode(MBIND_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ARGS[0] == "movewindow") {
|
||||
if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (pWindow && !pWindow->m_bIsFullscreen)
|
||||
pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_START, mouseCoords);
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow.expired())
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else if (!PRESSED && g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
||||
if (!g_pInputManager->currentlyDraggedWindow.expired()) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
changeMouseBindMode(MBIND_MOVE);
|
||||
} else {
|
||||
try {
|
||||
switch (std::stoi(ARGS[1])) {
|
||||
case 1: changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break;
|
||||
case 2: changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break;
|
||||
default: changeMouseBindMode(MBIND_RESIZE);
|
||||
}
|
||||
}
|
||||
} else if (ARGS[0] == "resizewindow") {
|
||||
if (PRESSED && g_pInputManager->dragMode == MBIND_INVALID) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
} catch (std::exception& e) { changeMouseBindMode(MBIND_RESIZE); }
|
||||
}
|
||||
}
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow =
|
||||
g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
void CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) {
|
||||
if (MODE != MBIND_INVALID) {
|
||||
if (!g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode != MBIND_INVALID)
|
||||
return;
|
||||
|
||||
try {
|
||||
switch (std::stoi(ARGS[1])) {
|
||||
case 1: g_pInputManager->dragMode = MBIND_RESIZE_FORCE_RATIO; break;
|
||||
case 2: g_pInputManager->dragMode = MBIND_RESIZE_BLOCK_RATIO; break;
|
||||
default: g_pInputManager->dragMode = MBIND_RESIZE;
|
||||
}
|
||||
} catch (std::exception& e) { g_pInputManager->dragMode = MBIND_RESIZE; }
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else if (!PRESSED &&
|
||||
(g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO || g_pInputManager->dragMode == MBIND_RESIZE)) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
const PHLWINDOW PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!g_pInputManager->currentlyDraggedWindow.expired()) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow.reset();
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
}
|
||||
}
|
||||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE)
|
||||
PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS);
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow.expired())
|
||||
g_pInputManager->currentlyDraggedWindow = PWINDOW;
|
||||
|
||||
g_pInputManager->dragMode = MODE;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
if (g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode == MBIND_INVALID)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->dragMode = MODE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2447,14 +2481,6 @@ void CKeybindManager::alterZOrder(std::string args) {
|
|||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
void CKeybindManager::fakeFullscreenActive(std::string args) {
|
||||
if (!g_pCompositor->m_pLastWindow.expired()) {
|
||||
// will also set the flag
|
||||
g_pCompositor->m_pLastWindow->m_bFakeFullscreenState = !g_pCompositor->m_pLastWindow->m_bFakeFullscreenState;
|
||||
g_pXWaylandManager->setWindowFullscreen(g_pCompositor->m_pLastWindow.lock(), g_pCompositor->m_pLastWindow->shouldSendFullscreenState());
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::lockGroups(std::string args) {
|
||||
if (args == "lock" || args.empty() || args == "lockgroups")
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
|
@ -2614,7 +2640,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
|||
}
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
if (!PWINDOW || PWINDOW->m_bIsFullscreen)
|
||||
if (!PWINDOW || PWINDOW->isFullscreen())
|
||||
return;
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
|
||||
|
@ -2684,10 +2710,10 @@ void CKeybindManager::global(std::string args) {
|
|||
if (NAME.empty())
|
||||
return;
|
||||
|
||||
if (!g_pProtocolManager->m_pGlobalShortcutsProtocolManager->globalShortcutExists(APPID, NAME))
|
||||
if (!PROTO::globalShortcuts->isTaken(APPID, NAME))
|
||||
return;
|
||||
|
||||
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed);
|
||||
PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveGroupWindow(std::string args) {
|
||||
|
|
|
@ -105,6 +105,8 @@ class CKeybindManager {
|
|||
//we also store the keyboard pointer (in the string) to differentiate between different keyboard (layouts)
|
||||
std::unordered_map<std::string, xkb_keycode_t> m_mKeyToCodeCache;
|
||||
|
||||
static void changeMouseBindMode(const eMouseBindMode mode);
|
||||
|
||||
private:
|
||||
std::deque<SPressedKeyWithMods> m_dPressedKeys;
|
||||
|
||||
|
@ -116,7 +118,6 @@ class CKeybindManager {
|
|||
uint32_t m_uLastCode = 0;
|
||||
uint32_t m_uLastMouseCode = 0;
|
||||
|
||||
bool m_bIsMouseBindActive = false;
|
||||
std::vector<SKeybind*> m_vPressedSpecialBinds;
|
||||
|
||||
int m_iPassPressed = -1; // used for pass
|
||||
|
@ -154,7 +155,7 @@ class CKeybindManager {
|
|||
static void setActiveTiled(std::string);
|
||||
static void changeworkspace(std::string);
|
||||
static void fullscreenActive(std::string);
|
||||
static void fakeFullscreenActive(std::string);
|
||||
static void fullscreenStateActive(std::string args);
|
||||
static void moveActiveToWorkspace(std::string);
|
||||
static void moveActiveToWorkspaceSilent(std::string);
|
||||
static void moveFocusTo(std::string);
|
||||
|
|
|
@ -4,19 +4,28 @@
|
|||
#include "../protocols/PointerGestures.hpp"
|
||||
#include "../protocols/FractionalScale.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/core/Seat.hpp"
|
||||
#include "eventLoop/EventLoopManager.hpp"
|
||||
#include "SeatManager.hpp"
|
||||
#include <cstring>
|
||||
#include <gbm.h>
|
||||
|
||||
CPointerManager::CPointerManager() {
|
||||
hooks.monitorAdded = g_pHookSystem->hookDynamic("newMonitor", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
auto PMONITOR = std::any_cast<SP<CMonitor>>(data);
|
||||
hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
auto PMONITOR = std::any_cast<CMonitor*>(data)->self.lock();
|
||||
|
||||
onMonitorLayoutChange();
|
||||
|
||||
PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr);
|
||||
PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr);
|
||||
PMONITOR->events.modeChanged.registerStaticListener(
|
||||
[this, PMONITOR](void* owner, std::any data) {
|
||||
g_pEventLoopManager->doLater([this, PMONITOR]() {
|
||||
onMonitorLayoutChange();
|
||||
checkDefaultCursorWarp(PMONITOR, PMONITOR->output->name);
|
||||
});
|
||||
},
|
||||
nullptr);
|
||||
PMONITOR->events.disconnect.registerStaticListener(
|
||||
[this, PMONITOR](void* owner, std::any data) { g_pEventLoopManager->doLater([this, PMONITOR]() { onMonitorLayoutChange(); }); }, nullptr);
|
||||
PMONITOR->events.destroy.registerStaticListener(
|
||||
[this](void* owner, std::any data) {
|
||||
if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown)
|
||||
|
@ -25,7 +34,7 @@ CPointerManager::CPointerManager() {
|
|||
nullptr);
|
||||
});
|
||||
|
||||
hooks.monitorPreRender = g_pHookSystem->hookDynamic("preRender", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
hooks.monitorPreRender = g_pHookSystem->hookDynamic("preMonitorCommit", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||
auto state = stateFor(std::any_cast<CMonitor*>(data)->self.lock());
|
||||
if (!state)
|
||||
return;
|
||||
|
@ -34,6 +43,38 @@ CPointerManager::CPointerManager() {
|
|||
});
|
||||
}
|
||||
|
||||
void CPointerManager::checkDefaultCursorWarp(SP<CMonitor> monitor, std::string monitorName) {
|
||||
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
|
||||
static bool cursorDefaultDone = false;
|
||||
static bool firstLaunch = true;
|
||||
|
||||
const auto POS = monitor->middle();
|
||||
|
||||
// by default, cursor should be set to first monitor detected
|
||||
// this is needed as a default if the monitor given in config above doesn't exist
|
||||
if (firstLaunch) {
|
||||
firstLaunch = false;
|
||||
g_pCompositor->warpCursorTo(POS, true);
|
||||
g_pInputManager->refocus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) {
|
||||
if (*PCURSORMONITOR == monitorName) {
|
||||
cursorDefaultDone = true;
|
||||
g_pCompositor->warpCursorTo(POS, true);
|
||||
g_pInputManager->refocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed.
|
||||
if (g_pCompositor->getMonitorFromCursor() == monitor.get()) {
|
||||
g_pCompositor->warpCursorTo(POS, true);
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
|
||||
void CPointerManager::lockSoftwareAll() {
|
||||
for (auto& state : monitorStates)
|
||||
state->softwareLocks++;
|
||||
|
@ -151,18 +192,20 @@ void CPointerManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hots
|
|||
currentCursorImage.surface = surf;
|
||||
currentCursorImage.scale = surf->resource()->current.scale;
|
||||
|
||||
surf->resource()->map();
|
||||
|
||||
currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); });
|
||||
currentCursorImage.commitSurface = surf->resource()->events.commit.registerListener([this](std::any data) {
|
||||
damageIfSoftware();
|
||||
currentCursorImage.size = currentCursorImage.surface->resource()->current.buffer ? currentCursorImage.surface->resource()->current.buffer->size : Vector2D{};
|
||||
currentCursorImage.size = currentCursorImage.surface->resource()->current.texture ? currentCursorImage.surface->resource()->current.bufferSize : Vector2D{};
|
||||
currentCursorImage.scale = currentCursorImage.surface ? currentCursorImage.surface->resource()->current.scale : 1.F;
|
||||
recheckEnteredOutputs();
|
||||
updateCursorBackend();
|
||||
damageIfSoftware();
|
||||
});
|
||||
|
||||
if (surf->resource()->current.buffer) {
|
||||
currentCursorImage.size = surf->resource()->current.buffer->size;
|
||||
if (surf->resource()->current.texture) {
|
||||
currentCursorImage.size = surf->resource()->current.bufferSize;
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
surf->resource()->frame(&now);
|
||||
|
@ -222,6 +265,8 @@ void CPointerManager::resetCursorImage(bool apply) {
|
|||
currentCursorImage.surface->resource()->leave(m);
|
||||
}
|
||||
|
||||
currentCursorImage.surface->resource()->unmap();
|
||||
|
||||
currentCursorImage.destroySurface.reset();
|
||||
currentCursorImage.commitSurface.reset();
|
||||
currentCursorImage.surface.reset();
|
||||
|
@ -426,16 +471,39 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
|||
// clear buffer
|
||||
memset(bufPtr, 0, std::get<2>(bufData));
|
||||
|
||||
auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer;
|
||||
if (currentCursorImage.pBuffer) {
|
||||
auto texAttrs = currentCursorImage.pBuffer->shm();
|
||||
|
||||
if (texBuffer) {
|
||||
auto textAttrs = texBuffer->shm();
|
||||
auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
|
||||
auto texPtr = std::get<0>(texData);
|
||||
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride);
|
||||
if (!texAttrs.success) {
|
||||
Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
|
||||
auto texPtr = std::get<0>(texData);
|
||||
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride);
|
||||
// copy cursor texture
|
||||
for (int i = 0; i < texBuffer->shm().size.y; i++)
|
||||
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride);
|
||||
for (int i = 0; i < texAttrs.size.y; i++)
|
||||
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride);
|
||||
} else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) {
|
||||
const auto SURFACE = currentCursorImage.surface->resource();
|
||||
auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE);
|
||||
Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size());
|
||||
|
||||
if (shmBuffer.data()) {
|
||||
// copy cursor texture
|
||||
// assume format is 32bpp
|
||||
size_t STRIDE = 4 * SURFACE->current.bufferSize.x;
|
||||
for (int i = 0; i < SURFACE->current.bufferSize.y; i++)
|
||||
memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE);
|
||||
} else {
|
||||
// if there is no data, hide the cursor
|
||||
memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */);
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buf->endDataPtr();
|
||||
|
@ -674,6 +742,32 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP<IHID> dev) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case HID_TYPE_POINTER: {
|
||||
IPointer* POINTER = reinterpret_cast<IPointer*>(dev.get());
|
||||
if (!POINTER->boundOutput.empty()) {
|
||||
if (POINTER->boundOutput == "entire") {
|
||||
// find x and y size of the entire space
|
||||
Vector2D bottomRight = {-9999999, -9999999}, topLeft = {9999999, 9999999};
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
const auto EXTENT = m->logicalBox().extent();
|
||||
const auto POS = m->logicalBox().pos();
|
||||
if (EXTENT.x > bottomRight.x)
|
||||
bottomRight.x = EXTENT.x;
|
||||
if (EXTENT.y > bottomRight.y)
|
||||
bottomRight.y = EXTENT.y;
|
||||
if (POS.x < topLeft.x)
|
||||
topLeft.x = POS.x;
|
||||
if (POS.y < topLeft.y)
|
||||
topLeft.y = POS.y;
|
||||
}
|
||||
mappedArea = {topLeft, bottomRight - topLeft};
|
||||
} else if (const auto PMONITOR = g_pCompositor->getMonitorFromString(POINTER->boundOutput); PMONITOR) {
|
||||
currentMonitor = PMONITOR->self.lock();
|
||||
mappedArea = currentMonitor->logicalBox();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -710,7 +804,7 @@ void CPointerManager::onMonitorLayoutChange() {
|
|||
}
|
||||
|
||||
SP<CTexture> CPointerManager::getCurrentCursorTexture() {
|
||||
if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.buffer))
|
||||
if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.texture))
|
||||
return nullptr;
|
||||
|
||||
if (currentCursorImage.pBuffer) {
|
||||
|
@ -719,7 +813,7 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() {
|
|||
return currentCursorImage.bufferTex;
|
||||
}
|
||||
|
||||
return currentCursorImage.surface->resource()->current.buffer->texture;
|
||||
return currentCursorImage.surface->resource()->current.texture;
|
||||
}
|
||||
|
||||
void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
|
|
|
@ -26,6 +26,7 @@ class CPointerManager {
|
|||
public:
|
||||
CPointerManager();
|
||||
|
||||
void checkDefaultCursorWarp(SP<CMonitor> monitor, std::string monitorName);
|
||||
void attachPointer(SP<IPointer> pointer);
|
||||
void attachTouch(SP<ITouch> touch);
|
||||
void attachTablet(SP<CTablet> tablet);
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "../protocols/DRMSyncobj.hpp"
|
||||
#include "../protocols/Screencopy.hpp"
|
||||
#include "../protocols/ToplevelExport.hpp"
|
||||
#include "../protocols/TextInputV1.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
|
||||
#include "../protocols/core/Seat.hpp"
|
||||
#include "../protocols/core/DataDevice.hpp"
|
||||
|
@ -74,7 +76,7 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) {
|
|||
|
||||
CProtocolManager::CProtocolManager() {
|
||||
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("experimental:explicit_sync");
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
|
||||
// Outputs are a bit dumb, we have to agree.
|
||||
static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) {
|
||||
|
@ -125,6 +127,7 @@ CProtocolManager::CProtocolManager() {
|
|||
PROTO::pointerGestures = std::make_unique<CPointerGesturesProtocol>(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures");
|
||||
PROTO::foreignToplevelWlr = std::make_unique<CForeignToplevelWlrProtocol>(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr");
|
||||
PROTO::shortcutsInhibit = std::make_unique<CKeyboardShortcutsInhibitProtocol>(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit");
|
||||
PROTO::textInputV1 = std::make_unique<CTextInputV1Protocol>(&zwp_text_input_manager_v1_interface, 1, "TextInputV1");
|
||||
PROTO::textInputV3 = std::make_unique<CTextInputV3Protocol>(&zwp_text_input_manager_v3_interface, 1, "TextInputV3");
|
||||
PROTO::constraints = std::make_unique<CPointerConstraintsProtocol>(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints");
|
||||
PROTO::outputPower = std::make_unique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower");
|
||||
|
@ -146,6 +149,7 @@ CProtocolManager::CProtocolManager() {
|
|||
PROTO::xwaylandShell = std::make_unique<CXWaylandShellProtocol>(&xwayland_shell_v1_interface, 1, "XWaylandShell");
|
||||
PROTO::screencopy = std::make_unique<CScreencopyProtocol>(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy");
|
||||
PROTO::toplevelExport = std::make_unique<CToplevelExportProtocol>(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport");
|
||||
PROTO::globalShortcuts = std::make_unique<CGlobalShortcutsProtocol>(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts");
|
||||
|
||||
for (auto& b : g_pCompositor->m_pAqBackend->getImplementations()) {
|
||||
if (b->type() != Aquamarine::AQ_BACKEND_DRM)
|
||||
|
@ -162,11 +166,6 @@ CProtocolManager::CProtocolManager() {
|
|||
PROTO::linuxDma = std::make_unique<CLinuxDMABufV1Protocol>(&zwp_linux_dmabuf_v1_interface, 5, "LinuxDMABUF");
|
||||
} else
|
||||
Debug::log(WARN, "ProtocolManager: Not binding linux-dmabuf and MesaDRM: DMABUF not available");
|
||||
|
||||
// Old protocol implementations.
|
||||
// TODO: rewrite them to use hyprwayland-scanner.
|
||||
m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>();
|
||||
m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>();
|
||||
}
|
||||
|
||||
CProtocolManager::~CProtocolManager() {
|
||||
|
@ -197,6 +196,7 @@ CProtocolManager::~CProtocolManager() {
|
|||
PROTO::pointerGestures.reset();
|
||||
PROTO::foreignToplevelWlr.reset();
|
||||
PROTO::shortcutsInhibit.reset();
|
||||
PROTO::textInputV1.reset();
|
||||
PROTO::textInputV3.reset();
|
||||
PROTO::constraints.reset();
|
||||
PROTO::outputPower.reset();
|
||||
|
@ -218,6 +218,7 @@ CProtocolManager::~CProtocolManager() {
|
|||
PROTO::xwaylandShell.reset();
|
||||
PROTO::screencopy.reset();
|
||||
PROTO::toplevelExport.reset();
|
||||
PROTO::globalShortcuts.reset();
|
||||
|
||||
PROTO::lease.reset();
|
||||
PROTO::sync.reset();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../protocols/TextInputV1.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/memory/Memory.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
@ -13,10 +11,6 @@ class CProtocolManager {
|
|||
CProtocolManager();
|
||||
~CProtocolManager();
|
||||
|
||||
// TODO: rewrite to use the new protocol framework
|
||||
std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager;
|
||||
std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, CHyprSignalListener> m_mModeChangeListeners;
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) {
|
|||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
});
|
||||
|
||||
m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([](std::any data) {
|
||||
m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) {
|
||||
m_pSessionLock.reset();
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
|
@ -104,7 +105,7 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64
|
|||
// We don't want the red screen to flash.
|
||||
float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) {
|
||||
if (!m_pSessionLock)
|
||||
return 0.F;
|
||||
return 1.F;
|
||||
|
||||
const auto& NOMAPPEDSURFACETIMER = m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers.find(id);
|
||||
|
||||
|
@ -123,7 +124,7 @@ void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) {
|
|||
m_pSessionLock->m_lockedMonitors.emplace(id);
|
||||
const auto MONITORS = g_pCompositor->m_vMonitors;
|
||||
const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); });
|
||||
if (LOCKED) {
|
||||
if (LOCKED && m_pSessionLock->lock->good()) {
|
||||
m_pSessionLock->lock->sendLocked();
|
||||
m_pSessionLock->m_hasSentLocked = true;
|
||||
}
|
||||
|
|
603
src/managers/XCursorManager.cpp
Normal file
603
src/managers/XCursorManager.cpp
Normal file
|
@ -0,0 +1,603 @@
|
|||
#include <cstring>
|
||||
#include <dirent.h>
|
||||
#include <filesystem>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gsettingsschema.h>
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "helpers/CursorShapes.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "XCursorManager.hpp"
|
||||
|
||||
// clang-format off
|
||||
static std::vector<uint32_t> HYPR_XCURSOR_PIXELS = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b001816, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e008173, 0x5f00564d, 0x16001412, 0x09000807, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2b002624, 0x05000404, 0x00000000, 0x35002f2b, 0xd400bead,
|
||||
0xc300b09e, 0x90008275, 0x44003e37, 0x04000403, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x67005a56,
|
||||
0x6f00615c, 0x00000000, 0x00000000, 0x8b007c72, 0xf200d7c6, 0xfa00e0cc, 0xe800d0bd, 0xa0009181, 0x44003e37, 0x1a001815, 0x06000505, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x8d007976, 0xd600b8b3, 0x2500201f, 0x00000000, 0x17001413, 0xbd00a79c, 0xf600dacb, 0xff00e3d1, 0xfc00e1ce, 0xe800d0bc, 0xbf00ac9b,
|
||||
0x95008778, 0x51004a41, 0x0f000e0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92007b7b, 0xf500d0cf, 0x9e008685, 0x00000000, 0x00000000, 0x23001f1d, 0x64005853,
|
||||
0x9b008980, 0xd900bfb3, 0xfb00dfce, 0xff00e4d0, 0xfb00e1cd, 0xec00d5c0, 0xa7009788, 0x47004139, 0x1e001b18, 0x05000504, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xa200878a, 0xff00d6d9, 0xd600b4b5,
|
||||
0x0e000c0c, 0x00000000, 0x00000000, 0x02000202, 0x0c000b0a, 0x30002a28, 0x8e007d75, 0xd600bdb0, 0xef00d4c4, 0xfb00e0ce, 0xff00e4d0, 0xe600cfbb, 0xb800a695, 0x5f00564d,
|
||||
0x06000505, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x02000202, 0xc600a3aa, 0xff00d3da, 0xea00c3c8, 0x08000707, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x2a002523, 0x61005550, 0x9500837b,
|
||||
0xd800bfb1, 0xfd00e1cf, 0xff00e5d0, 0xf500dcc7, 0x7c007065, 0x2a002622, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06000505, 0xd600aeb9, 0xff00d0dc, 0xcc00a7af, 0x04000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x01000101, 0x01000101, 0x2c002724, 0xa1008e85, 0xe600ccbd, 0xf800ddcb, 0xef00d6c3, 0xc300af9f, 0x2c002824, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708, 0xd800adbc, 0xff00cdde, 0xb90095a0, 0x02000202, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000e0d, 0x4b00423e, 0xa4009088, 0xfd00dfd0, 0xff00e3d1,
|
||||
0xae009c8f, 0x42003b36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x14001012, 0xf400c0d6,
|
||||
0xff00cadf, 0xb2008e9c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x02000202, 0x1200100f, 0xa2008e86, 0xec00cfc3, 0xfc00ded0, 0xc300ada0, 0x15001311, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x2e002429, 0xfd00c4e0, 0xff00c7e2, 0x8f00707e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1e001a19, 0x75006662, 0xfb00dbd1, 0xf700d9cc, 0x9600847c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e002f37, 0xfc00c1e1, 0xff00c5e3, 0x60004b55, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x15001212, 0xa6008f8b, 0xff00ddd5,
|
||||
0xf800d8ce, 0x36002f2d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51003d49, 0xfe00bfe5, 0xfe00c1e4, 0x4c003a44,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x01000101, 0x1d001918, 0xf400d1cd, 0xfe00dad5, 0xb3009a96, 0x03000303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x66004b5d, 0xff00bee7, 0xfd00bee5, 0x4500343f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000202, 0x82006e6e, 0xff00d8d7, 0xd800b9b6, 0x33002c2b, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x70005267, 0xff00bbe9, 0xfa00b8e3, 0x29001e25, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f003536, 0xea00c3c7, 0xf800d1d3,
|
||||
0x4a003e3f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5f004458, 0xff00b8eb, 0xf400b1e0, 0x29001e26, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x1b001617, 0xe100bac0, 0xff00d4da, 0x82006c6f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a004054, 0xfe00b4eb,
|
||||
0xfb00b3e8, 0x3b002a36, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0a000809, 0xc900a4ad, 0xff00d1dc, 0x88007075, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x44002f3f, 0xf300aae3, 0xfc00b1ea, 0x48003343, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05000404, 0xdf00b3c2, 0xff00cedd, 0x8f00747c, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x25001a23, 0xf200a6e4, 0xff00b1ef, 0x84005c7c, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000708,
|
||||
0xe400b5c8, 0xff00cbdf, 0x78006068, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x12000c11, 0xc00082b6, 0xff00aef1, 0xaa0075a0,
|
||||
0x11000c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x1e00171b, 0xf700c1db, 0xff00c8e1, 0x4b003b42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x05000305, 0x8d005f86, 0xfc00aaef, 0xed00a0e1, 0x26001a24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6f005463, 0xff00c4e3, 0xf500beda, 0x0c00090b, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3e00293b, 0xed009de2, 0xff00aaf3, 0x8b005d84, 0x04000304, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x07000506, 0xeb00b1d4, 0xff00c1e6, 0xba008ea7,
|
||||
0x02000202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb20075ab, 0xff00a7f4, 0xf300a1e9, 0x35002333,
|
||||
0x06000406, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x8900647d, 0xff00bde8, 0xfb00bce2, 0x26001d22, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x2b001c29, 0xf1009ce8, 0xfe00a5f4, 0xc60082be, 0x3b002738, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x01000101, 0x54003c4d, 0xfd00b8e8, 0xff00baea, 0x96006f89, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x78004d74, 0xe20091da, 0xff00a5f6, 0xb60077af, 0x42002b3f, 0x0c00080c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x9400688a, 0xff00b5ed, 0xff00b6ec, 0xcc0093bc, 0x02000102, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x8100527d, 0xeb0096e4, 0xf900a0f1, 0xdc008dd4,
|
||||
0x9b006595, 0x32002130, 0x0a00070a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2100161f, 0x5300394e, 0xe2009cd4, 0xff00b1ef, 0xff00b2ee, 0xc8008cba, 0x17001015,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x19001018, 0x5e003b5b, 0xcb0081c5, 0xff00a2f8, 0xfc00a1f4, 0xde0090d6, 0xa9006da3, 0x8300567e, 0x6f00496a, 0x76004e71, 0xbb007db2, 0xeb009edf, 0xfb00a9ee, 0xff00adf1,
|
||||
0xfd00adee, 0x9e006d95, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000304, 0x34002133, 0xa60069a1, 0xd70089d1, 0xf2009bea, 0xff00a3f7, 0xfb00a1f2, 0xfb00a2f2, 0xff00a6f5,
|
||||
0xff00a8f4, 0xfd00a7f2, 0xed009ee2, 0xcf008bc5, 0x14000e13, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000b11, 0x35002134, 0x5b003959,
|
||||
0x8b005887, 0xb30072ae, 0xc90080c3, 0xd10086ca, 0xa6006ba0, 0x65004261, 0x3c002839, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x01000101, 0x06000406, 0x0d00080d, 0x0f000a0f, 0x0a00060a, 0x01000101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000};
|
||||
// clang-format on
|
||||
|
||||
CXCursorManager::CXCursorManager() {
|
||||
hyprCursor = makeShared<SXCursors>();
|
||||
SXCursorImage image;
|
||||
image.size = {32, 32};
|
||||
image.hotspot = {3, 2};
|
||||
image.pixels = HYPR_XCURSOR_PIXELS;
|
||||
image.delay = 0;
|
||||
|
||||
hyprCursor->images.push_back(image);
|
||||
hyprCursor->shape = "left_ptr";
|
||||
defaultCursor = hyprCursor;
|
||||
}
|
||||
|
||||
void CXCursorManager::loadTheme(std::string const& name, int size) {
|
||||
if (lastLoadSize == size && themeName == name)
|
||||
return;
|
||||
|
||||
lastLoadSize = size;
|
||||
themeName = name.empty() ? "default" : name;
|
||||
defaultCursor.reset();
|
||||
cursors.clear();
|
||||
|
||||
auto paths = themePaths(themeName);
|
||||
if (paths.empty()) {
|
||||
Debug::log(ERR, "XCursor librarypath is empty loading standard XCursors");
|
||||
cursors = loadStandardCursors(themeName, lastLoadSize);
|
||||
} else {
|
||||
for (auto const& p : paths) {
|
||||
auto dirCursors = loadAllFromDir(p, lastLoadSize);
|
||||
std::copy_if(dirCursors.begin(), dirCursors.end(), std::back_inserter(cursors),
|
||||
[this](auto const& p) { return std::none_of(cursors.begin(), cursors.end(), [&p](auto const& dp) { return dp->shape == p->shape; }); });
|
||||
}
|
||||
}
|
||||
|
||||
if (cursors.empty()) {
|
||||
Debug::log(ERR, "XCursor failed finding any shapes in theme \"{}\".", themeName);
|
||||
defaultCursor = hyprCursor;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& shape : CURSOR_SHAPE_NAMES) {
|
||||
auto legacyName = getLegacyShapeName(shape);
|
||||
if (legacyName.empty())
|
||||
continue;
|
||||
|
||||
auto it = std::find_if(cursors.begin(), cursors.end(), [&legacyName](auto const& c) { return c->shape == legacyName; });
|
||||
|
||||
if (it == cursors.end()) {
|
||||
Debug::log(LOG, "XCursor failed to find a legacy shape with name {}, skipping", legacyName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::any_of(cursors.begin(), cursors.end(), [&shape](auto const& dp) { return dp->shape == shape; })) {
|
||||
Debug::log(LOG, "XCursor already has a shape {} loaded, skipping", shape);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto cursor = makeShared<SXCursors>();
|
||||
cursor->images = it->get()->images;
|
||||
cursor->shape = shape;
|
||||
|
||||
cursors.emplace_back(cursor);
|
||||
}
|
||||
|
||||
static auto SYNCGSETTINGS = CConfigValue<Hyprlang::INT>("cursor:sync_gsettings_theme");
|
||||
if (*SYNCGSETTINGS)
|
||||
syncGsettings();
|
||||
}
|
||||
|
||||
SP<SXCursors> CXCursorManager::getShape(std::string const& shape, int size) {
|
||||
// monitor scaling changed etc, so reload theme with new size.
|
||||
if (size != lastLoadSize)
|
||||
loadTheme(themeName, size);
|
||||
|
||||
// try to get an icon we know if we have one
|
||||
for (auto const& c : cursors) {
|
||||
if (c->shape != shape)
|
||||
continue;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Debug::log(WARN, "XCursor couldn't find shape {} , using default cursor instead", shape);
|
||||
return defaultCursor;
|
||||
}
|
||||
|
||||
SP<SXCursors> CXCursorManager::createCursor(std::string const& shape, XcursorImages* xImages) {
|
||||
auto xcursor = makeShared<SXCursors>();
|
||||
|
||||
for (int i = 0; i < xImages->nimage; i++) {
|
||||
auto xImage = xImages->images[i];
|
||||
SXCursorImage image;
|
||||
image.size = {(int)xImage->width, (int)xImage->height};
|
||||
image.hotspot = {(int)xImage->xhot, (int)xImage->yhot};
|
||||
image.pixels.resize(xImage->width * xImage->height);
|
||||
std::memcpy(image.pixels.data(), xImage->pixels, xImage->width * xImage->height * sizeof(uint32_t));
|
||||
image.delay = xImage->delay;
|
||||
|
||||
xcursor->images.emplace_back(image);
|
||||
}
|
||||
|
||||
xcursor->shape = shape;
|
||||
|
||||
return xcursor;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> CXCursorManager::themePaths(std::string const& theme) {
|
||||
auto const* path = XcursorLibraryPath();
|
||||
|
||||
auto expandTilde = [](std::string const& path) {
|
||||
if (!path.empty() && path[0] == '~') {
|
||||
const char* home = std::getenv("HOME");
|
||||
if (home)
|
||||
return std::string(home) + path.substr(1);
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
auto getInheritThemes = [](std::string const& indexTheme) {
|
||||
std::ifstream infile(indexTheme);
|
||||
std::string line;
|
||||
std::vector<std::string> themes;
|
||||
|
||||
Debug::log(LOG, "XCursor parsing index.theme {}", indexTheme);
|
||||
|
||||
while (std::getline(infile, line)) {
|
||||
if (line.empty())
|
||||
continue;
|
||||
|
||||
// Trim leading and trailing whitespace
|
||||
auto pos = line.find_first_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos)
|
||||
line.erase(0, pos);
|
||||
|
||||
pos = line.find_last_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos && pos < line.length()) {
|
||||
line.erase(pos + 1);
|
||||
}
|
||||
|
||||
if (line.rfind("Inherits", 8) != std::string::npos) { // Check if line starts with "Inherits"
|
||||
std::string inheritThemes = line.substr(8); // Extract the part after "Inherits"
|
||||
if (inheritThemes.empty())
|
||||
continue;
|
||||
|
||||
// Remove leading whitespace from inheritThemes and =
|
||||
pos = inheritThemes.find_first_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos)
|
||||
inheritThemes.erase(0, pos);
|
||||
|
||||
if (inheritThemes.empty())
|
||||
continue;
|
||||
|
||||
if (inheritThemes.at(0) == '=')
|
||||
inheritThemes.erase(0, 1);
|
||||
else
|
||||
continue; // not correct formatted index.theme
|
||||
|
||||
pos = inheritThemes.find_first_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos)
|
||||
inheritThemes.erase(0, pos);
|
||||
|
||||
std::stringstream inheritStream(inheritThemes);
|
||||
std::string inheritTheme;
|
||||
while (std::getline(inheritStream, inheritTheme, ',')) {
|
||||
if (inheritTheme.empty())
|
||||
continue;
|
||||
|
||||
// Trim leading and trailing whitespace from each theme
|
||||
pos = inheritTheme.find_first_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos)
|
||||
inheritTheme.erase(0, pos);
|
||||
|
||||
pos = inheritTheme.find_last_not_of(" \t\n\r");
|
||||
if (pos != std::string::npos && pos < inheritTheme.length())
|
||||
inheritTheme.erase(inheritTheme.find_last_not_of(" \t\n\r") + 1);
|
||||
|
||||
themes.push_back(inheritTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
infile.close();
|
||||
|
||||
return themes;
|
||||
};
|
||||
|
||||
std::unordered_set<std::string> paths;
|
||||
std::unordered_set<std::string> inherits;
|
||||
|
||||
auto scanTheme = [&path, &paths, &expandTilde, &inherits, &getInheritThemes](auto const& t) {
|
||||
std::stringstream ss(path);
|
||||
std::string line;
|
||||
|
||||
Debug::log(LOG, "XCursor scanning theme {}", t);
|
||||
|
||||
while (std::getline(ss, line, ':')) {
|
||||
auto p = expandTilde(line + "/" + t + "/cursors");
|
||||
if (std::filesystem::exists(p) && std::filesystem::is_directory(p)) {
|
||||
Debug::log(LOG, "XCursor using theme path {}", p);
|
||||
paths.insert(p);
|
||||
}
|
||||
|
||||
auto inherit = expandTilde(line + "/" + t + "/index.theme");
|
||||
if (std::filesystem::exists(inherit) && std::filesystem::is_regular_file(inherit)) {
|
||||
auto inheritThemes = getInheritThemes(inherit);
|
||||
for (auto const& i : inheritThemes) {
|
||||
Debug::log(LOG, "XCursor theme {} inherits {}", t, i);
|
||||
inherits.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (path) {
|
||||
scanTheme(theme);
|
||||
while (!inherits.empty()) {
|
||||
auto oldInherits = inherits;
|
||||
for (auto& i : oldInherits)
|
||||
scanTheme(i);
|
||||
|
||||
if (oldInherits.size() == inherits.size())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
std::string CXCursorManager::getLegacyShapeName(std::string const& shape) {
|
||||
if (shape == "invalid")
|
||||
return std::string();
|
||||
else if (shape == "default")
|
||||
return "left_ptr";
|
||||
else if (shape == "context-menu")
|
||||
return "left_ptr";
|
||||
else if (shape == "help")
|
||||
return "left_ptr";
|
||||
else if (shape == "pointer")
|
||||
return "hand2";
|
||||
else if (shape == "progress")
|
||||
return "watch";
|
||||
else if (shape == "wait")
|
||||
return "watch";
|
||||
else if (shape == "cell")
|
||||
return "plus";
|
||||
else if (shape == "crosshair")
|
||||
return "cross";
|
||||
else if (shape == "text")
|
||||
return "xterm";
|
||||
else if (shape == "vertical-text")
|
||||
return "xterm";
|
||||
else if (shape == "alias")
|
||||
return "dnd-link";
|
||||
else if (shape == "copy")
|
||||
return "dnd-copy";
|
||||
else if (shape == "move")
|
||||
return "dnd-move";
|
||||
else if (shape == "no-drop")
|
||||
return "dnd-none";
|
||||
else if (shape == "not-allowed")
|
||||
return "crossed_circle";
|
||||
else if (shape == "grab")
|
||||
return "hand1";
|
||||
else if (shape == "grabbing")
|
||||
return "hand1";
|
||||
else if (shape == "e-resize")
|
||||
return "right_side";
|
||||
else if (shape == "n-resize")
|
||||
return "top_side";
|
||||
else if (shape == "ne-resize")
|
||||
return "top_right_corner";
|
||||
else if (shape == "nw-resize")
|
||||
return "top_left_corner";
|
||||
else if (shape == "s-resize")
|
||||
return "bottom_side";
|
||||
else if (shape == "se-resize")
|
||||
return "bottom_right_corner";
|
||||
else if (shape == "sw-resize")
|
||||
return "bottom_left_corner";
|
||||
else if (shape == "w-resize")
|
||||
return "left_side";
|
||||
else if (shape == "ew-resize")
|
||||
return "sb_h_double_arrow";
|
||||
else if (shape == "ns-resize")
|
||||
return "sb_v_double_arrow";
|
||||
else if (shape == "nesw-resize")
|
||||
return "fd_double_arrow";
|
||||
else if (shape == "nwse-resize")
|
||||
return "bd_double_arrow";
|
||||
else if (shape == "col-resize")
|
||||
return "sb_h_double_arrow";
|
||||
else if (shape == "row-resize")
|
||||
return "sb_v_double_arrow";
|
||||
else if (shape == "all-scroll")
|
||||
return "fleur";
|
||||
else if (shape == "zoom-in")
|
||||
return "left_ptr";
|
||||
else if (shape == "zoom-out")
|
||||
return "left_ptr";
|
||||
|
||||
return std::string();
|
||||
};
|
||||
|
||||
// Taken from https://gitlab.freedesktop.org/xorg/lib/libxcursor/-/blob/master/src/library.c
|
||||
// clang-format off
|
||||
static std::array<const char*, 77> XCURSOR_STANDARD_NAMES = {
|
||||
"X_cursor",
|
||||
"arrow",
|
||||
"based_arrow_down",
|
||||
"based_arrow_up",
|
||||
"boat",
|
||||
"bogosity",
|
||||
"bottom_left_corner",
|
||||
"bottom_right_corner",
|
||||
"bottom_side",
|
||||
"bottom_tee",
|
||||
"box_spiral",
|
||||
"center_ptr",
|
||||
"circle",
|
||||
"clock",
|
||||
"coffee_mug",
|
||||
"cross",
|
||||
"cross_reverse",
|
||||
"crosshair",
|
||||
"diamond_cross",
|
||||
"dot",
|
||||
"dotbox",
|
||||
"double_arrow",
|
||||
"draft_large",
|
||||
"draft_small",
|
||||
"draped_box",
|
||||
"exchange",
|
||||
"fleur",
|
||||
"gobbler",
|
||||
"gumby",
|
||||
"hand1",
|
||||
"hand2",
|
||||
"heart",
|
||||
"icon",
|
||||
"iron_cross",
|
||||
"left_ptr",
|
||||
"left_side",
|
||||
"left_tee",
|
||||
"leftbutton",
|
||||
"ll_angle",
|
||||
"lr_angle",
|
||||
"man",
|
||||
"middlebutton",
|
||||
"mouse",
|
||||
"pencil",
|
||||
"pirate",
|
||||
"plus",
|
||||
"question_arrow",
|
||||
"right_ptr",
|
||||
"right_side",
|
||||
"right_tee",
|
||||
"rightbutton",
|
||||
"rtl_logo",
|
||||
"sailboat",
|
||||
"sb_down_arrow",
|
||||
"sb_h_double_arrow",
|
||||
"sb_left_arrow",
|
||||
"sb_right_arrow",
|
||||
"sb_up_arrow",
|
||||
"sb_v_double_arrow",
|
||||
"shuttle",
|
||||
"sizing",
|
||||
"spider",
|
||||
"spraycan",
|
||||
"star",
|
||||
"target",
|
||||
"tcross",
|
||||
"top_left_arrow",
|
||||
"top_left_corner",
|
||||
"top_right_corner",
|
||||
"top_side",
|
||||
"top_tee",
|
||||
"trek",
|
||||
"ul_angle",
|
||||
"umbrella",
|
||||
"ur_angle",
|
||||
"watch",
|
||||
"xterm",
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
std::vector<SP<SXCursors>> CXCursorManager::loadStandardCursors(std::string const& name, int size) {
|
||||
std::vector<SP<SXCursors>> newCursors;
|
||||
|
||||
// load the default xcursor shapes that exist in the theme
|
||||
for (size_t i = 0; i < XCURSOR_STANDARD_NAMES.size(); ++i) {
|
||||
std::string shape{XCURSOR_STANDARD_NAMES.at(i)};
|
||||
auto xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), size);
|
||||
|
||||
if (!xImages) {
|
||||
Debug::log(WARN, "XCursor failed to find a shape with name {}, trying size 24.", shape);
|
||||
xImages = XcursorShapeLoadImages(i << 1 /* wtf xcursor? */, name.c_str(), 24);
|
||||
|
||||
if (!xImages) {
|
||||
Debug::log(WARN, "XCursor failed to find a shape with name {}, skipping", shape);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto cursor = createCursor(shape, xImages);
|
||||
newCursors.emplace_back(cursor);
|
||||
|
||||
if (!defaultCursor && (shape == "left_ptr" || shape == "arrow"))
|
||||
defaultCursor = cursor;
|
||||
|
||||
XcursorImagesDestroy(xImages);
|
||||
}
|
||||
|
||||
// broken theme.. just set it.
|
||||
if (!newCursors.empty() && !defaultCursor)
|
||||
defaultCursor = newCursors.front();
|
||||
|
||||
return newCursors;
|
||||
}
|
||||
|
||||
std::vector<SP<SXCursors>> CXCursorManager::loadAllFromDir(std::string const& path, int size) {
|
||||
std::vector<SP<SXCursors>> newCursors;
|
||||
|
||||
if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) {
|
||||
for (const auto& entry : std::filesystem::directory_iterator(path)) {
|
||||
if (!entry.is_regular_file() && !entry.is_symlink())
|
||||
continue;
|
||||
|
||||
auto const& full = entry.path().string();
|
||||
using PcloseType = int (*)(FILE*);
|
||||
const std::unique_ptr<FILE, PcloseType> f(fopen(full.c_str(), "r"), static_cast<PcloseType>(fclose));
|
||||
|
||||
if (!f)
|
||||
continue;
|
||||
|
||||
auto xImages = XcursorFileLoadImages(f.get(), size);
|
||||
|
||||
if (!xImages) {
|
||||
Debug::log(WARN, "XCursor failed to load image {}, trying size 24.", full);
|
||||
xImages = XcursorFileLoadImages(f.get(), 24);
|
||||
|
||||
if (!xImages) {
|
||||
Debug::log(WARN, "XCursor failed to load image {}, skipping", full);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto const& shape = entry.path().filename().string();
|
||||
auto cursor = createCursor(shape, xImages);
|
||||
newCursors.emplace_back(cursor);
|
||||
|
||||
if (!defaultCursor && (shape == "left_ptr" || shape == "arrow"))
|
||||
defaultCursor = cursor;
|
||||
|
||||
XcursorImagesDestroy(xImages);
|
||||
}
|
||||
}
|
||||
|
||||
// broken theme.. just set it.
|
||||
if (!newCursors.empty() && !defaultCursor)
|
||||
defaultCursor = newCursors.front();
|
||||
|
||||
return newCursors;
|
||||
}
|
||||
|
||||
void CXCursorManager::syncGsettings() {
|
||||
auto checkParamExists = [](std::string const& paramName, std::string const& category) {
|
||||
auto* gSettingsSchemaSource = g_settings_schema_source_get_default();
|
||||
|
||||
if (!gSettingsSchemaSource) {
|
||||
Debug::log(WARN, "GSettings default schema source does not exist, cant sync GSettings");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* gSettingsSchema = g_settings_schema_source_lookup(gSettingsSchemaSource, category.c_str(), true);
|
||||
bool hasParam = false;
|
||||
|
||||
if (gSettingsSchema != NULL) {
|
||||
hasParam = gSettingsSchema && g_settings_schema_has_key(gSettingsSchema, paramName.c_str());
|
||||
g_settings_schema_unref(gSettingsSchema);
|
||||
}
|
||||
|
||||
return hasParam;
|
||||
};
|
||||
|
||||
using SettingValue = std::variant<std::string, int>;
|
||||
auto setValue = [&checkParamExists](std::string const& paramName, const SettingValue& paramValue, std::string const& category) {
|
||||
if (!checkParamExists(paramName, category)) {
|
||||
Debug::log(WARN, "GSettings parameter doesnt exist {} in {}", paramName, category);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* gsettings = g_settings_new(category.c_str());
|
||||
|
||||
if (!gsettings) {
|
||||
Debug::log(WARN, "GSettings failed to allocate new settings with category {}", category);
|
||||
return;
|
||||
}
|
||||
|
||||
std::visit(
|
||||
[&](auto&& value) {
|
||||
using T = std::decay_t<decltype(value)>;
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
g_settings_set_string(gsettings, paramName.c_str(), value.c_str());
|
||||
else if constexpr (std::is_same_v<T, int>)
|
||||
g_settings_set_int(gsettings, paramName.c_str(), value);
|
||||
},
|
||||
paramValue);
|
||||
|
||||
g_settings_sync();
|
||||
g_object_unref(gsettings);
|
||||
};
|
||||
|
||||
setValue("cursor-theme", themeName, "org.gnome.desktop.interface");
|
||||
setValue("cursor-size", lastLoadSize, "org.gnome.desktop.interface");
|
||||
}
|
48
src/managers/XCursorManager.hpp
Normal file
48
src/managers/XCursorManager.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
#include "helpers/memory/Memory.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
}
|
||||
|
||||
// gangsta bootleg XCursor impl. adidas balkanized
|
||||
struct SXCursorImage {
|
||||
Vector2D size;
|
||||
Vector2D hotspot;
|
||||
std::vector<uint32_t> pixels; // XPixel is a u32
|
||||
uint32_t delay; // animation delay to next frame (ms)
|
||||
};
|
||||
|
||||
struct SXCursors {
|
||||
std::vector<SXCursorImage> images;
|
||||
std::string shape;
|
||||
};
|
||||
|
||||
class CXCursorManager {
|
||||
public:
|
||||
CXCursorManager();
|
||||
~CXCursorManager() = default;
|
||||
|
||||
void loadTheme(const std::string& name, int size);
|
||||
SP<SXCursors> getShape(std::string const& shape, int size);
|
||||
|
||||
private:
|
||||
SP<SXCursors> createCursor(std::string const& shape, XcursorImages* xImages);
|
||||
std::unordered_set<std::string> themePaths(std::string const& theme);
|
||||
std::string getLegacyShapeName(std::string const& shape);
|
||||
std::vector<SP<SXCursors>> loadStandardCursors(std::string const& name, int size);
|
||||
std::vector<SP<SXCursors>> loadAllFromDir(std::string const& path, int size);
|
||||
void syncGsettings();
|
||||
|
||||
int lastLoadSize = 0;
|
||||
std::string themeName = "";
|
||||
SP<SXCursors> defaultCursor;
|
||||
SP<SXCursors> hyprCursor;
|
||||
std::vector<SP<SXCursors>> cursors;
|
||||
};
|
|
@ -27,6 +27,8 @@ CEventLoopManager::~CEventLoopManager() {
|
|||
wl_event_source_remove(m_sWayland.eventSource);
|
||||
if (m_sIdle.eventSource)
|
||||
wl_event_source_remove(m_sIdle.eventSource);
|
||||
if (m_sTimers.timerfd >= 0)
|
||||
close(m_sTimers.timerfd);
|
||||
}
|
||||
|
||||
static int timerWrite(int fd, uint32_t mask, void* data) {
|
||||
|
@ -46,7 +48,6 @@ void CEventLoopManager::enterLoop() {
|
|||
aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs();
|
||||
for (auto& fd : aqPollFDs) {
|
||||
m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get()));
|
||||
fd->onSignal(); // dispatch outstanding
|
||||
}
|
||||
|
||||
wl_display_run(m_sWayland.display);
|
||||
|
@ -74,8 +75,8 @@ void CEventLoopManager::removeTimer(SP<CEventLoopTimer> timer) {
|
|||
}
|
||||
|
||||
static void timespecAddNs(timespec* pTimespec, int64_t delta) {
|
||||
int delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC;
|
||||
int delta_s_high = delta / TIMESPEC_NSEC_PER_SEC;
|
||||
auto delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC;
|
||||
auto delta_s_high = delta / TIMESPEC_NSEC_PER_SEC;
|
||||
|
||||
pTimespec->tv_sec += delta_s_high;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ void CInputManager::recheckIdleInhibitorStatus() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->m_bIsFullscreen && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) {
|
||||
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->isFullscreen() && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) {
|
||||
PROTO::idle->setInhibit(true);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../../protocols/LayerShell.hpp"
|
||||
#include "../../protocols/core/Seat.hpp"
|
||||
#include "../../protocols/core/DataDevice.hpp"
|
||||
#include "../../protocols/core/Compositor.hpp"
|
||||
#include "../../protocols/XDGShell.hpp"
|
||||
|
||||
#include "../../devices/Mouse.hpp"
|
||||
|
@ -297,7 +298,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
|
||||
// then, we check if the workspace doesnt have a fullscreen window
|
||||
const auto PWORKSPACE = PMONITOR->activeWorkspace;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
if (!pFoundWindow) {
|
||||
|
@ -324,7 +325,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
|
||||
// then windows
|
||||
if (!foundSurface) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FSMODE_MAXIMIZED) {
|
||||
if (!foundSurface) {
|
||||
if (PMONITOR->activeSpecialWorkspace) {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
@ -469,7 +470,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
else if (pFoundWindow) {
|
||||
// change cursor icon if hovering over border
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||
if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) {
|
||||
if (!pFoundWindow->isFullscreen() && !pFoundWindow->hasPopupAt(mouseCoords)) {
|
||||
setCursorIconOnBorder(pFoundWindow);
|
||||
} else if (m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
unsetCursorImage();
|
||||
|
@ -680,7 +681,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) {
|
|||
// clicking on border triggers resize
|
||||
// TODO detect click on LS properly
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || w->m_iX11Type != 2)) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
if (w && !w->isFullscreen()) {
|
||||
const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y};
|
||||
const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA};
|
||||
|
||||
|
@ -918,6 +919,8 @@ void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
|||
applyConfigToKeyboard(keeb);
|
||||
|
||||
g_pSeatManager->setKeyboard(keeb);
|
||||
|
||||
keeb->updateLEDs();
|
||||
}
|
||||
|
||||
void CInputManager::setKeyboardLayout() {
|
||||
|
@ -1264,7 +1267,14 @@ void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
|
|||
if (!pKeyboard)
|
||||
return;
|
||||
|
||||
pKeyboard->updateLEDs();
|
||||
std::optional<uint32_t> leds = pKeyboard->getLEDs();
|
||||
|
||||
if (!leds.has_value())
|
||||
return;
|
||||
|
||||
for (auto& k : m_vKeyboards) {
|
||||
k->updateLEDs(leds.value());
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
|
@ -1382,6 +1392,12 @@ void CInputManager::refocusLastWindow(CMonitor* pMonitor) {
|
|||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
} else {
|
||||
// otherwise fall back to a normal refocus.
|
||||
|
||||
if (foundSurface && !foundSurface->hlSurface->keyboardFocusable()) {
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
}
|
||||
|
||||
refocus();
|
||||
}
|
||||
}
|
||||
|
@ -1670,7 +1686,7 @@ void CInputManager::releaseAllMouseButtons() {
|
|||
|
||||
void CInputManager::setCursorIconOnBorder(PHLWINDOW w) {
|
||||
// do not override cursor icons set by mouse binds
|
||||
if (g_pKeybindManager->m_bIsMouseBindActive) {
|
||||
if (g_pInputManager->currentlyDraggedWindow.expired()) {
|
||||
m_eBorderIconDirection = BORDERICON_NONE;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class CInputPopup {
|
|||
WP<CInputMethodPopupV2> popup;
|
||||
SP<CWLSurface> surface;
|
||||
CBox lastBoxLocal;
|
||||
uint64_t lastMonitor = -1;
|
||||
MONITORID lastMonitor = MONITOR_INVALID;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener map;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
#include "../../protocols/TextInputV3.hpp"
|
||||
#include "../../protocols/TextInputV1.hpp"
|
||||
#include "../../protocols/InputMethodV2.hpp"
|
||||
#include "../../protocols/core/Compositor.hpp"
|
||||
|
||||
|
@ -9,7 +10,8 @@ CInputMethodRelay::CInputMethodRelay() {
|
|||
static auto P =
|
||||
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<SP<CWLSurfaceResource>>(param)); });
|
||||
|
||||
listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(ti); });
|
||||
listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast<WP<CTextInputV3>>(ti)); });
|
||||
listeners.newTIV1 = PROTO::textInputV1->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast<WP<CTextInputV1>>(ti)); });
|
||||
listeners.newIME = PROTO::ime->events.newIME.registerListener([this](std::any ime) { onNewIME(std::any_cast<SP<CInputMethodV2>>(ime)); });
|
||||
}
|
||||
|
||||
|
@ -86,11 +88,11 @@ CTextInput* CInputMethodRelay::getFocusedTextInput() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewTextInput(std::any tiv3) {
|
||||
m_vTextInputs.emplace_back(std::make_unique<CTextInput>(std::any_cast<WP<CTextInputV3>>(tiv3)));
|
||||
void CInputMethodRelay::onNewTextInput(WP<CTextInputV3> tiv3) {
|
||||
m_vTextInputs.emplace_back(std::make_unique<CTextInput>(tiv3));
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewTextInput(STextInputV1* pTIV1) {
|
||||
void CInputMethodRelay::onNewTextInput(WP<CTextInputV1> pTIV1) {
|
||||
m_vTextInputs.emplace_back(std::make_unique<CTextInput>(pTIV1));
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
class CInputManager;
|
||||
class CHyprRenderer;
|
||||
struct STextInputV1;
|
||||
class CTextInputV1;
|
||||
class CInputMethodV2;
|
||||
|
||||
class CInputMethodRelay {
|
||||
|
@ -18,8 +18,8 @@ class CInputMethodRelay {
|
|||
CInputMethodRelay();
|
||||
|
||||
void onNewIME(SP<CInputMethodV2>);
|
||||
void onNewTextInput(std::any tiv3);
|
||||
void onNewTextInput(STextInputV1* pTIV1);
|
||||
void onNewTextInput(WP<CTextInputV3> tiv3);
|
||||
void onNewTextInput(WP<CTextInputV1> pTIV1);
|
||||
|
||||
void activateIME(CTextInput* pInput);
|
||||
void deactivateIME(CTextInput* pInput);
|
||||
|
@ -48,6 +48,7 @@ class CInputMethodRelay {
|
|||
|
||||
struct {
|
||||
CHyprSignalListener newTIV3;
|
||||
CHyprSignalListener newTIV1;
|
||||
CHyprSignalListener newIME;
|
||||
CHyprSignalListener commitIME;
|
||||
CHyprSignalListener destroyIME;
|
||||
|
|
|
@ -77,7 +77,7 @@ void CInputManager::endWorkspaceSwipe() {
|
|||
// left of where we started. Instead, it's one more than the greatest
|
||||
// workspace ID that currently exists.
|
||||
if (workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID && *PSWIPENEW) {
|
||||
int maxWorkspace = 0;
|
||||
WORKSPACEID maxWorkspace = 0;
|
||||
for (const auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
maxWorkspace = std::max(maxWorkspace, ws->m_iID);
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ void CInputManager::endWorkspaceSwipe() {
|
|||
|
||||
// apply alpha
|
||||
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) {
|
||||
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f;
|
||||
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#include "../../protocols/InputMethodV2.hpp"
|
||||
#include "../../protocols/core/Compositor.hpp"
|
||||
|
||||
CTextInput::CTextInput(STextInputV1* ti) : pV1Input(ti) {
|
||||
ti->pTextInput = this;
|
||||
CTextInput::CTextInput(WP<CTextInputV1> ti) : pV1Input(ti) {
|
||||
initCallbacks();
|
||||
}
|
||||
|
||||
|
@ -16,17 +15,6 @@ CTextInput::CTextInput(WP<CTextInputV3> ti) : pV3Input(ti) {
|
|||
initCallbacks();
|
||||
}
|
||||
|
||||
CTextInput::~CTextInput() {
|
||||
if (pV1Input)
|
||||
pV1Input->pTextInput = nullptr;
|
||||
}
|
||||
|
||||
void CTextInput::tiV1Destroyed() {
|
||||
pV1Input = nullptr;
|
||||
|
||||
g_pInputManager->m_sIMERelay.removeTextInput(this);
|
||||
}
|
||||
|
||||
void CTextInput::initCallbacks() {
|
||||
if (isV3()) {
|
||||
const auto INPUT = pV3Input.lock();
|
||||
|
@ -41,25 +29,19 @@ void CTextInput::initCallbacks() {
|
|||
g_pInputManager->m_sIMERelay.removeTextInput(this);
|
||||
});
|
||||
} else {
|
||||
hyprListener_textInputEnable.initCallback(&pV1Input->sEnable, [this](void* owner, void* data) { onEnabled(); }, this, "textInput");
|
||||
const auto INPUT = pV1Input.lock();
|
||||
|
||||
hyprListener_textInputCommit.initCallback(&pV1Input->sCommit, [this](void* owner, void* data) { onCommit(); }, this, "textInput");
|
||||
|
||||
hyprListener_textInputDisable.initCallback(&pV1Input->sDisable, [this](void* owner, void* data) { onDisabled(); }, this, "textInput");
|
||||
|
||||
hyprListener_textInputDestroy.initCallback(
|
||||
&pV1Input->sDestroy,
|
||||
[this](void* owner, void* data) {
|
||||
hyprListener_textInputCommit.removeCallback();
|
||||
hyprListener_textInputDestroy.removeCallback();
|
||||
hyprListener_textInputDisable.removeCallback();
|
||||
hyprListener_textInputEnable.removeCallback();
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
|
||||
g_pInputManager->m_sIMERelay.removeTextInput(this);
|
||||
},
|
||||
this, "textInput");
|
||||
listeners.enable = INPUT->events.enable.registerListener([this](std::any p) {
|
||||
const auto SURFACE = std::any_cast<SP<CWLSurfaceResource>>(p);
|
||||
onEnabled(SURFACE);
|
||||
});
|
||||
listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); });
|
||||
listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); });
|
||||
listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) {
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
g_pInputManager->m_sIMERelay.removeTextInput(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +131,7 @@ void CTextInput::setFocusedSurface(SP<CWLSurfaceResource> pSurface) {
|
|||
}
|
||||
|
||||
bool CTextInput::isV3() {
|
||||
return !pV1Input;
|
||||
return pV3Input && !pV1Input;
|
||||
}
|
||||
|
||||
void CTextInput::enter(SP<CWLSurfaceResource> pSurface) {
|
||||
|
@ -174,8 +156,7 @@ void CTextInput::enter(SP<CWLSurfaceResource> pSurface) {
|
|||
if (isV3())
|
||||
pV3Input->enter(pSurface);
|
||||
else {
|
||||
zwp_text_input_v1_send_enter(pV1Input->resourceImpl, pSurface->getResource()->resource());
|
||||
pV1Input->active = true;
|
||||
pV1Input->enter(pSurface);
|
||||
}
|
||||
|
||||
setFocusedSurface(pSurface);
|
||||
|
@ -194,8 +175,7 @@ void CTextInput::leave() {
|
|||
if (isV3() && focusedSurface())
|
||||
pV3Input->leave(focusedSurface());
|
||||
else if (focusedSurface() && pV1Input) {
|
||||
zwp_text_input_v1_send_leave(pV1Input->resourceImpl);
|
||||
pV1Input->active = false;
|
||||
pV1Input->leave();
|
||||
}
|
||||
|
||||
setFocusedSurface(nullptr);
|
||||
|
@ -208,7 +188,7 @@ SP<CWLSurfaceResource> CTextInput::focusedSurface() {
|
|||
}
|
||||
|
||||
wl_client* CTextInput::client() {
|
||||
return isV3() ? pV3Input->client() : pV1Input->client;
|
||||
return isV3() ? pV3Input->client() : pV1Input->client();
|
||||
}
|
||||
|
||||
void CTextInput::commitStateToIME(SP<CInputMethodV2> ime) {
|
||||
|
@ -223,13 +203,15 @@ void CTextInput::commitStateToIME(SP<CInputMethodV2> ime) {
|
|||
if (INPUT->current.contentType.updated)
|
||||
ime->textContentType(INPUT->current.contentType.hint, INPUT->current.contentType.purpose);
|
||||
} else {
|
||||
if (pV1Input->pendingSurrounding.isPending)
|
||||
ime->surroundingText(pV1Input->pendingSurrounding.text, pV1Input->pendingSurrounding.cursor, pV1Input->pendingSurrounding.anchor);
|
||||
const auto INPUT = pV1Input.lock();
|
||||
|
||||
if (INPUT->pendingSurrounding.isPending)
|
||||
ime->surroundingText(INPUT->pendingSurrounding.text, INPUT->pendingSurrounding.cursor, INPUT->pendingSurrounding.anchor);
|
||||
|
||||
ime->textChangeCause(ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD);
|
||||
|
||||
if (pV1Input->pendingContentType.isPending)
|
||||
ime->textContentType((zwpTextInputV3ContentHint)pV1Input->pendingContentType.hint, (zwpTextInputV3ContentPurpose)pV1Input->pendingContentType.purpose);
|
||||
ime->textContentType((zwpTextInputV3ContentHint)INPUT->pendingContentType.hint, (zwpTextInputV3ContentPurpose)INPUT->pendingContentType.purpose);
|
||||
}
|
||||
|
||||
g_pInputManager->m_sIMERelay.updateAllPopups();
|
||||
|
@ -252,25 +234,27 @@ void CTextInput::updateIMEState(SP<CInputMethodV2> ime) {
|
|||
|
||||
INPUT->sendDone();
|
||||
} else {
|
||||
const auto INPUT = pV1Input.lock();
|
||||
|
||||
if (ime->current.preeditString.committed) {
|
||||
zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin);
|
||||
zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT);
|
||||
zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str(), "");
|
||||
INPUT->preeditCursor(ime->current.preeditString.begin);
|
||||
INPUT->preeditStyling(0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT);
|
||||
INPUT->preeditString(pV1Input->serial, ime->current.preeditString.string.c_str(), "");
|
||||
} else {
|
||||
zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin);
|
||||
zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT);
|
||||
zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, "", "");
|
||||
INPUT->preeditCursor(ime->current.preeditString.begin);
|
||||
INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT);
|
||||
INPUT->preeditString(pV1Input->serial, "", "");
|
||||
}
|
||||
|
||||
if (ime->current.committedString.committed)
|
||||
zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.committedString.string.c_str());
|
||||
INPUT->commitString(pV1Input->serial, ime->current.committedString.string.c_str());
|
||||
|
||||
if (ime->current.deleteSurrounding.committed) {
|
||||
zwp_text_input_v1_send_delete_surrounding_text(pV1Input->resourceImpl, std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before,
|
||||
ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before);
|
||||
INPUT->deleteSurroundingText(std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before,
|
||||
ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before);
|
||||
|
||||
if (ime->current.preeditString.committed)
|
||||
zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str());
|
||||
INPUT->commitString(pV1Input->serial, ime->current.preeditString.string.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,4 +265,4 @@ bool CTextInput::hasCursorRectangle() {
|
|||
|
||||
CBox CTextInput::cursorBox() {
|
||||
return CBox{isV3() ? pV3Input->current.box.cursorBox : pV1Input->cursorRectangle};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
struct wl_client;
|
||||
|
||||
struct STextInputV1;
|
||||
class CTextInputV1;
|
||||
class CTextInputV3;
|
||||
class CInputMethodV2;
|
||||
class CWLSurfaceResource;
|
||||
|
@ -16,8 +16,7 @@ class CWLSurfaceResource;
|
|||
class CTextInput {
|
||||
public:
|
||||
CTextInput(WP<CTextInputV3> ti);
|
||||
CTextInput(STextInputV1* ti);
|
||||
~CTextInput();
|
||||
CTextInput(WP<CTextInputV1> ti);
|
||||
|
||||
bool isV3();
|
||||
void enter(SP<CWLSurfaceResource> pSurface);
|
||||
|
@ -43,12 +42,7 @@ class CTextInput {
|
|||
WP<CWLSurfaceResource> pFocusedSurface;
|
||||
int enterLocks = 0;
|
||||
WP<CTextInputV3> pV3Input;
|
||||
STextInputV1* pV1Input = nullptr;
|
||||
|
||||
DYNLISTENER(textInputEnable);
|
||||
DYNLISTENER(textInputDisable);
|
||||
DYNLISTENER(textInputCommit);
|
||||
DYNLISTENER(textInputDestroy);
|
||||
WP<CTextInputV1> pV1Input;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener enable;
|
||||
|
@ -58,4 +52,4 @@ class CTextInput {
|
|||
CHyprSignalListener surfaceUnmap;
|
||||
CHyprSignalListener surfaceDestroy;
|
||||
} listeners;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ executable('Hyprland', src,
|
|||
dependency('cairo'),
|
||||
dependency('hyprcursor', version: '>=0.1.7'),
|
||||
dependency('hyprlang', version: '>= 0.3.2'),
|
||||
dependency('hyprutils', version: '>= 0.2.0'),
|
||||
dependency('hyprutils', version: '>= 0.2.1'),
|
||||
dependency('libdrm'),
|
||||
dependency('egl'),
|
||||
dependency('xkbcommon'),
|
||||
|
@ -28,6 +28,7 @@ executable('Hyprland', src,
|
|||
xcb_xfixes_dep,
|
||||
backtrace_dep,
|
||||
epoll_dep,
|
||||
gio_dep,
|
||||
udis86,
|
||||
|
||||
dependency('pixman-1'),
|
||||
|
|
|
@ -80,6 +80,8 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
|||
PLUGIN->version = PLUGINDATA.version;
|
||||
PLUGIN->name = PLUGINDATA.name;
|
||||
|
||||
g_pConfigManager->m_bForceReload = true;
|
||||
|
||||
Debug::log(LOG, " [PluginSystem] Plugin {} loaded. Handle: {:x}, path: \"{}\", author: \"{}\", description: \"{}\", version: \"{}\"", PLUGINDATA.name, (uintptr_t)MODULE, path,
|
||||
PLUGINDATA.author, PLUGINDATA.description, PLUGINDATA.version);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "DRMLease.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include <aquamarine/backend/DRM.hpp>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -225,7 +226,7 @@ CDRMLeaseDevice::CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend) : backe
|
|||
auto fd = drm->getNonMasterFD();
|
||||
|
||||
if (fd < 0) {
|
||||
LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName);
|
||||
Debug::log(ERR, "[DRMLease] Failed to dup fd for drm node {}", drm->gpuName);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -247,10 +248,8 @@ CDRMLeaseProtocol::CDRMLeaseProtocol(const wl_interface* iface, const int& ver,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!primaryDevice || primaryDevice->success) {
|
||||
PROTO::lease.reset();
|
||||
return;
|
||||
}
|
||||
if (!primaryDevice || !primaryDevice->success)
|
||||
g_pEventLoopManager->doLater([]() { PROTO::lease.reset(); });
|
||||
}
|
||||
|
||||
void CDRMLeaseProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
|
|
|
@ -24,9 +24,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
|
|||
return;
|
||||
}
|
||||
|
||||
auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
|
||||
acquireTimeline = timeline;
|
||||
acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
|
||||
pending.acquireTimeline = timeline;
|
||||
pending.acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
});
|
||||
|
||||
resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) {
|
||||
|
@ -35,29 +35,33 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
|
|||
return;
|
||||
}
|
||||
|
||||
auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
|
||||
releaseTimeline = timeline;
|
||||
releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
|
||||
pending.releaseTimeline = timeline;
|
||||
pending.releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
});
|
||||
|
||||
listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
|
||||
if (!!acquireTimeline != !!releaseTimeline) {
|
||||
resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline");
|
||||
surface->pending.rejected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((acquireTimeline || releaseTimeline) && !surface->pending.buffer) {
|
||||
if ((pending.acquireTimeline || pending.releaseTimeline) && !surface->pending.texture) {
|
||||
resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer");
|
||||
surface->pending.rejected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acquireTimeline)
|
||||
if (!surface->pending.newBuffer)
|
||||
return; // this commit does not change the state here
|
||||
|
||||
if (!!pending.acquireTimeline != !!pending.releaseTimeline) {
|
||||
resource->error(pending.acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT,
|
||||
"Missing timeline");
|
||||
surface->pending.rejected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pending.acquireTimeline)
|
||||
return;
|
||||
|
||||
// wait for the acquire timeline to materialize
|
||||
auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
|
||||
auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
|
||||
if (!materialized.has_value()) {
|
||||
LOGM(ERR, "Failed to check the acquire timeline");
|
||||
resource->noMemory();
|
||||
|
@ -68,7 +72,24 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
|
|||
return;
|
||||
|
||||
surface->lockPendingState();
|
||||
acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
|
||||
pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
|
||||
});
|
||||
|
||||
listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) {
|
||||
// apply timelines if new ones have been attached, otherwise don't touch
|
||||
// the current ones
|
||||
if (pending.releaseTimeline) {
|
||||
current.releaseTimeline = pending.releaseTimeline;
|
||||
current.releasePoint = pending.releasePoint;
|
||||
}
|
||||
|
||||
if (pending.acquireTimeline) {
|
||||
current.acquireTimeline = pending.acquireTimeline;
|
||||
current.acquirePoint = pending.acquirePoint;
|
||||
}
|
||||
|
||||
pending.releaseTimeline.reset();
|
||||
pending.acquireTimeline.reset();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -93,6 +114,11 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTi
|
|||
}
|
||||
}
|
||||
|
||||
CDRMSyncobjTimelineResource::~CDRMSyncobjTimelineResource() {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
SP<CDRMSyncobjTimelineResource> CDRMSyncobjTimelineResource::fromResource(wl_resource* res) {
|
||||
auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data());
|
||||
return data ? data->self.lock() : nullptr;
|
||||
|
|
|
@ -14,23 +14,27 @@ class CDRMSyncobjSurfaceResource {
|
|||
public:
|
||||
CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_);
|
||||
|
||||
bool good();
|
||||
bool good();
|
||||
|
||||
WP<CWLSurfaceResource> surface;
|
||||
WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
|
||||
uint64_t acquirePoint = 0, releasePoint = 0;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
struct {
|
||||
WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
|
||||
uint64_t acquirePoint = 0, releasePoint = 0;
|
||||
} current, pending;
|
||||
|
||||
private:
|
||||
SP<CWpLinuxDrmSyncobjSurfaceV1> resource;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener surfacePrecommit;
|
||||
CHyprSignalListener surfaceCommit;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CDRMSyncobjTimelineResource {
|
||||
public:
|
||||
CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, int fd_);
|
||||
~CDRMSyncobjTimelineResource();
|
||||
static SP<CDRMSyncobjTimelineResource> fromResource(wl_resource*);
|
||||
|
||||
bool good();
|
||||
|
|
|
@ -51,7 +51,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
|
|||
}
|
||||
}
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
|
||||
g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_FULLSCREEN, true);
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
});
|
||||
|
||||
|
@ -64,7 +64,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
|
|||
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)
|
||||
return;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false);
|
||||
g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_FULLSCREEN, false);
|
||||
});
|
||||
|
||||
resource->setSetMaximized([this](CZwlrForeignToplevelHandleV1* p) {
|
||||
|
@ -81,7 +81,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
|
|||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_MAXIMIZED);
|
||||
g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_MAXIMIZED, true);
|
||||
});
|
||||
|
||||
resource->setUnsetMaximized([this](CZwlrForeignToplevelHandleV1* p) {
|
||||
|
@ -93,7 +93,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
|
|||
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)
|
||||
return;
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false);
|
||||
g_pCompositor->changeWindowFullscreenModeClient(PWINDOW, FSMODE_MAXIMIZED, false);
|
||||
});
|
||||
|
||||
resource->setClose([this](CZwlrForeignToplevelHandleV1* p) {
|
||||
|
@ -119,7 +119,7 @@ wl_resource* CForeignToplevelHandleWlr::res() {
|
|||
}
|
||||
|
||||
void CForeignToplevelHandleWlr::sendMonitor(CMonitor* pMonitor) {
|
||||
if (lastMonitorID == (int64_t)pMonitor->ID)
|
||||
if (lastMonitorID == pMonitor->ID)
|
||||
return;
|
||||
|
||||
const auto CLIENT = resource->client();
|
||||
|
@ -155,9 +155,9 @@ void CForeignToplevelHandleWlr::sendState() {
|
|||
*p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
if (PWINDOW->isFullscreen()) {
|
||||
auto p = (uint32_t*)wl_array_add(&state, sizeof(uint32_t));
|
||||
if (PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
if (PWINDOW->isEffectiveInternalFSMode(FSMODE_FULLSCREEN))
|
||||
*p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN;
|
||||
else
|
||||
*p = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED;
|
||||
|
|
|
@ -20,7 +20,7 @@ class CForeignToplevelHandleWlr {
|
|||
SP<CZwlrForeignToplevelHandleV1> resource;
|
||||
PHLWINDOWREF pWindow;
|
||||
bool closed = false;
|
||||
int64_t lastMonitorID = -1;
|
||||
MONITORID lastMonitorID = MONITOR_INVALID;
|
||||
|
||||
void sendMonitor(CMonitor* pMonitor);
|
||||
void sendState();
|
||||
|
|
|
@ -1,117 +1,61 @@
|
|||
#include "GlobalShortcuts.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#define GLOBAL_SHORTCUTS_VERSION 1
|
||||
#define LOGM PROTO::globalShortcuts->protoLog
|
||||
|
||||
static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) {
|
||||
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->bindManager(client, data, version, id);
|
||||
}
|
||||
|
||||
static void handleDisplayDestroy(struct wl_listener* listener, void* data) {
|
||||
CGlobalShortcutsProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
|
||||
proto->displayDestroy();
|
||||
}
|
||||
|
||||
void CGlobalShortcutsProtocolManager::displayDestroy() {
|
||||
wl_list_remove(&m_liDisplayDestroy.link);
|
||||
wl_list_init(&m_liDisplayDestroy.link);
|
||||
wl_global_destroy(m_pGlobal);
|
||||
}
|
||||
|
||||
CGlobalShortcutsProtocolManager::~CGlobalShortcutsProtocolManager() {
|
||||
displayDestroy();
|
||||
}
|
||||
|
||||
CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() {
|
||||
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_global_shortcuts_manager_v1_interface, GLOBAL_SHORTCUTS_VERSION, this, bindManagerInt);
|
||||
|
||||
if (!m_pGlobal) {
|
||||
Debug::log(ERR, "GlobalShortcutsManager could not start!");
|
||||
CShortcutClient::CShortcutClient(SP<CHyprlandGlobalShortcutsManagerV1> resource_) : resource(resource_) {
|
||||
if (!good())
|
||||
return;
|
||||
}
|
||||
|
||||
m_liDisplayDestroy.notify = handleDisplayDestroy;
|
||||
wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy);
|
||||
resource->setOnDestroy([this](CHyprlandGlobalShortcutsManagerV1* pMgr) { PROTO::globalShortcuts->destroyResource(this); });
|
||||
resource->setDestroy([this](CHyprlandGlobalShortcutsManagerV1* pMgr) { PROTO::globalShortcuts->destroyResource(this); });
|
||||
|
||||
Debug::log(LOG, "GlobalShortcutsManager started successfully!");
|
||||
}
|
||||
|
||||
static void handleRegisterShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description,
|
||||
const char* trigger_description) {
|
||||
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->registerShortcut(client, resource, shortcut, id, app_id, description, trigger_description);
|
||||
}
|
||||
|
||||
static void handleDestroy(wl_client* client, wl_resource* resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct hyprland_global_shortcuts_manager_v1_interface globalShortcutsManagerImpl = {
|
||||
.register_shortcut = handleRegisterShortcut,
|
||||
.destroy = handleDestroy,
|
||||
};
|
||||
|
||||
static const struct hyprland_global_shortcut_v1_interface shortcutImpl = {
|
||||
.destroy = handleDestroy,
|
||||
};
|
||||
|
||||
void CGlobalShortcutsProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) {
|
||||
const auto RESOURCE = wl_resource_create(client, &hyprland_global_shortcuts_manager_v1_interface, version, id);
|
||||
wl_resource_set_implementation(RESOURCE, &globalShortcutsManagerImpl, this, nullptr);
|
||||
|
||||
Debug::log(LOG, "GlobalShortcutsManager bound successfully!");
|
||||
|
||||
m_vClients.emplace_back(std::make_unique<SShortcutClient>(client));
|
||||
}
|
||||
|
||||
SShortcutClient* CGlobalShortcutsProtocolManager::clientFromWlClient(wl_client* client) {
|
||||
for (auto& c : m_vClients) {
|
||||
if (c->client == client) {
|
||||
return c.get();
|
||||
resource->setRegisterShortcut([this](CHyprlandGlobalShortcutsManagerV1* pMgr, uint32_t shortcut, const char* id, const char* app_id, const char* description,
|
||||
const char* trigger_description) {
|
||||
if (PROTO::globalShortcuts->isTaken(id, app_id)) {
|
||||
resource->error(HYPRLAND_GLOBAL_SHORTCUTS_MANAGER_V1_ERROR_ALREADY_TAKEN, "Combination is taken");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
const auto PSHORTCUT = shortcuts.emplace_back(makeShared<SShortcut>(makeShared<CHyprlandGlobalShortcutV1>(resource->client(), resource->version(), shortcut)));
|
||||
PSHORTCUT->id = id;
|
||||
PSHORTCUT->description = description;
|
||||
PSHORTCUT->appid = app_id;
|
||||
PSHORTCUT->shortcut = shortcut;
|
||||
|
||||
static void onShortcutDestroy(wl_resource* pResource) {
|
||||
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->destroyShortcut(pResource);
|
||||
}
|
||||
|
||||
void CGlobalShortcutsProtocolManager::registerShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description,
|
||||
const char* trigger_description) {
|
||||
const auto PCLIENT = clientFromWlClient(client);
|
||||
|
||||
if (!PCLIENT) {
|
||||
Debug::log(ERR, "Error at global shortcuts: no client in register?");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& c : m_vClients) {
|
||||
for (auto& sh : c->shortcuts) {
|
||||
if (sh->appid == app_id && sh->id == id) {
|
||||
wl_resource_post_error(resource, HYPRLAND_GLOBAL_SHORTCUTS_MANAGER_V1_ERROR_ALREADY_TAKEN, "Combination is taken");
|
||||
return;
|
||||
}
|
||||
if (!PSHORTCUT->resource->resource()) {
|
||||
PSHORTCUT->resource->noMemory();
|
||||
shortcuts.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const auto PSHORTCUT = PCLIENT->shortcuts.emplace_back(std::make_unique<SShortcut>()).get();
|
||||
PSHORTCUT->id = id;
|
||||
PSHORTCUT->description = description;
|
||||
PSHORTCUT->appid = app_id;
|
||||
PSHORTCUT->shortcut = shortcut;
|
||||
PSHORTCUT->resource->setDestroy([this](CHyprlandGlobalShortcutV1* pMgr) { std::erase_if(shortcuts, [&](const auto& other) { return other->resource.get() == pMgr; }); });
|
||||
});
|
||||
}
|
||||
|
||||
PSHORTCUT->resource = wl_resource_create(client, &hyprland_global_shortcut_v1_interface, 1, shortcut);
|
||||
if (!PSHORTCUT->resource) {
|
||||
bool CShortcutClient::good() {
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
CGlobalShortcutsProtocol::CGlobalShortcutsProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CGlobalShortcutsProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESROUCE = m_vClients.emplace_back(makeShared<CShortcutClient>(makeShared<CHyprlandGlobalShortcutsManagerV1>(client, ver, id)));
|
||||
|
||||
if (!RESROUCE->good()) {
|
||||
wl_client_post_no_memory(client);
|
||||
std::erase_if(PCLIENT->shortcuts, [&](const auto& other) { return other.get() == PSHORTCUT; });
|
||||
m_vClients.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation(PSHORTCUT->resource, &shortcutImpl, this, &onShortcutDestroy);
|
||||
}
|
||||
|
||||
bool CGlobalShortcutsProtocolManager::globalShortcutExists(std::string appid, std::string trigger) {
|
||||
void CGlobalShortcutsProtocol::destroyResource(CShortcutClient* client) {
|
||||
std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; });
|
||||
}
|
||||
|
||||
bool CGlobalShortcutsProtocol::isTaken(std::string appid, std::string trigger) {
|
||||
for (auto& c : m_vClients) {
|
||||
for (auto& sh : c->shortcuts) {
|
||||
if (sh->appid == appid && sh->id == trigger) {
|
||||
|
@ -123,7 +67,7 @@ bool CGlobalShortcutsProtocolManager::globalShortcutExists(std::string appid, st
|
|||
return false;
|
||||
}
|
||||
|
||||
void CGlobalShortcutsProtocolManager::sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed) {
|
||||
void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed) {
|
||||
for (auto& c : m_vClients) {
|
||||
for (auto& sh : c->shortcuts) {
|
||||
if (sh->appid == appid && sh->id == trigger) {
|
||||
|
@ -132,15 +76,15 @@ void CGlobalShortcutsProtocolManager::sendGlobalShortcutEvent(std::string appid,
|
|||
uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0;
|
||||
uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF;
|
||||
if (pressed)
|
||||
hyprland_global_shortcut_v1_send_pressed(sh->resource, tvSecHi, tvSecLo, now.tv_nsec);
|
||||
sh->resource->sendPressed(tvSecHi, tvSecLo, now.tv_nsec);
|
||||
else
|
||||
hyprland_global_shortcut_v1_send_released(sh->resource, tvSecHi, tvSecLo, now.tv_nsec);
|
||||
sh->resource->sendReleased(tvSecHi, tvSecLo, now.tv_nsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SShortcut> CGlobalShortcutsProtocolManager::getAllShortcuts() {
|
||||
std::vector<SShortcut> CGlobalShortcutsProtocol::getAllShortcuts() {
|
||||
std::vector<SShortcut> copy;
|
||||
for (auto& c : m_vClients) {
|
||||
for (auto& sh : c->shortcuts) {
|
||||
|
@ -150,9 +94,3 @@ std::vector<SShortcut> CGlobalShortcutsProtocolManager::getAllShortcuts() {
|
|||
|
||||
return copy;
|
||||
}
|
||||
|
||||
void CGlobalShortcutsProtocolManager::destroyShortcut(wl_resource* resource) {
|
||||
for (auto& c : m_vClients) {
|
||||
std::erase_if(c->shortcuts, [&](const auto& other) { return other->resource == resource; });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,43 @@
|
|||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include "hyprland-global-shortcuts-v1-protocol.h"
|
||||
#include "hyprland-global-shortcuts-v1.hpp"
|
||||
#include "../protocols/WaylandProtocol.hpp"
|
||||
#include <vector>
|
||||
|
||||
struct SShortcut {
|
||||
wl_resource* resource;
|
||||
std::string id, description, appid;
|
||||
uint32_t shortcut = 0;
|
||||
SP<CHyprlandGlobalShortcutV1> resource;
|
||||
std::string id, description, appid;
|
||||
uint32_t shortcut = 0;
|
||||
};
|
||||
|
||||
struct SShortcutClient {
|
||||
wl_client* client = nullptr;
|
||||
std::vector<std::unique_ptr<SShortcut>> shortcuts;
|
||||
};
|
||||
|
||||
class CGlobalShortcutsProtocolManager {
|
||||
class CShortcutClient {
|
||||
public:
|
||||
CGlobalShortcutsProtocolManager();
|
||||
~CGlobalShortcutsProtocolManager();
|
||||
CShortcutClient(SP<CHyprlandGlobalShortcutsManagerV1> resource);
|
||||
|
||||
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
|
||||
void displayDestroy();
|
||||
|
||||
void registerShortcut(wl_client* client, wl_resource* resource, uint32_t shortcut, const char* id, const char* app_id, const char* description,
|
||||
const char* trigger_description);
|
||||
void destroyShortcut(wl_resource* resource);
|
||||
|
||||
bool globalShortcutExists(std::string appid, std::string trigger);
|
||||
void sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed);
|
||||
|
||||
std::vector<SShortcut> getAllShortcuts();
|
||||
|
||||
wl_listener m_liDisplayDestroy;
|
||||
bool good();
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<SShortcutClient>> m_vClients;
|
||||
SP<CHyprlandGlobalShortcutsManagerV1> resource;
|
||||
std::vector<SP<SShortcut>> shortcuts;
|
||||
|
||||
SShortcutClient* clientFromWlClient(wl_client* client);
|
||||
|
||||
wl_global* m_pGlobal = nullptr;
|
||||
friend class CGlobalShortcutsProtocol;
|
||||
};
|
||||
|
||||
class CGlobalShortcutsProtocol : IWaylandProtocol {
|
||||
public:
|
||||
CGlobalShortcutsProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
|
||||
void destroyResource(CShortcutClient* client);
|
||||
|
||||
void sendGlobalShortcutEvent(std::string appid, std::string trigger, bool pressed);
|
||||
bool isTaken(std::string id, std::string app_id);
|
||||
std::vector<SShortcut> getAllShortcuts();
|
||||
|
||||
private:
|
||||
std::vector<SP<CShortcutClient>> m_vClients;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CGlobalShortcutsProtocol> globalShortcuts;
|
||||
};
|
||||
|
|
|
@ -107,14 +107,14 @@ CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_,
|
|||
});
|
||||
|
||||
listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) {
|
||||
if (pSurface->current.buffer && !mapped) {
|
||||
if (pSurface->current.texture && !mapped) {
|
||||
mapped = true;
|
||||
pSurface->map();
|
||||
events.map.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pSurface->current.buffer && mapped) {
|
||||
if (!pSurface->current.texture && mapped) {
|
||||
mapped = false;
|
||||
pSurface->unmap();
|
||||
events.unmap.emit();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue