mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-15 20:13:49 -07:00
Compare commits
113 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4520b30d49 | ||
|
8405aa111d | ||
|
ad46257cce | ||
|
0cfbe618b5 | ||
|
7d0944acdf | ||
|
b9990468f3 | ||
|
736a8735b3 | ||
|
b54eecbd79 | ||
|
657aeb3946 | ||
|
6807430b18 | ||
|
0c7a7e2d56 | ||
|
0ec6072a29 | ||
|
3ca699debf | ||
|
52c0919621 | ||
|
6fbfeefc71 | ||
|
46bf87c8d1 | ||
|
595eb89f6e | ||
|
a815b14bf1 | ||
|
3a5052a714 | ||
|
8e237b006f | ||
|
1ed925b69c | ||
|
aed529f695 | ||
|
de68e065fe | ||
|
e2426942e5 | ||
|
5c6c300abf | ||
|
6bd3397141 | ||
|
68fd32c810 | ||
|
3ddb16bd5b | ||
|
f6387536f6 | ||
|
968f6a6013 | ||
|
488efab636 | ||
|
6649255d54 | ||
|
4b00cba319 | ||
|
9e418671e1 | ||
|
d73c14751a | ||
|
6f313de952 | ||
|
2cf6e7862a | ||
|
58669fef77 | ||
|
e20aef7d53 | ||
|
b2143a98e2 | ||
|
f75f8efb1b | ||
|
be96787ed0 | ||
|
89d945aabe | ||
|
27211c71e9 | ||
|
14942bca60 | ||
|
77f2a01304 | ||
|
7b56ce6521 | ||
|
32a8caf7e7 | ||
|
caaa9b11e4 | ||
|
b1ad2d8066 | ||
|
22746b3046 | ||
|
49713fab04 | ||
|
8b86ee8bf0 | ||
|
2a052c69f3 | ||
|
2320b2241c | ||
|
8f5188269b | ||
|
00c8626863 | ||
|
0a211f29f5 | ||
|
d279d7c4c6 | ||
|
6c78b03bb7 | ||
|
f79497087b | ||
|
508bde1f61 | ||
|
e5ff19ac0f | ||
|
8579066c7a | ||
|
9232bc2c00 | ||
|
db0b764a5a | ||
|
278583b8a1 | ||
|
4414cd07e2 | ||
|
9e98fb0167 | ||
|
9856378384 | ||
|
dfa1bd0cd4 | ||
|
92df6b0dce | ||
|
71963972bf | ||
|
1bc05b1f9f | ||
|
e6cf643f5a | ||
|
94140e886e | ||
|
b248d59713 | ||
|
cbc0ff6ec0 | ||
|
6b6554adb8 | ||
|
d936eb437b | ||
|
883d01084c | ||
|
0564b46a5e | ||
|
3c9716acfd | ||
|
581f6659f8 | ||
|
e72ae6b25f | ||
|
9e35656244 | ||
|
e87758529e | ||
|
eb97d949aa | ||
|
e74efd87e5 | ||
|
4dbdb556fe | ||
|
5ee4b19691 | ||
|
d35e70a8c6 | ||
|
c35ed8363f | ||
|
d505b33665 | ||
|
118be4dea0 | ||
|
73b9756b8d | ||
|
8b9e385943 | ||
|
e01da1fd7a | ||
|
7a8c013edc | ||
|
518399a95b | ||
|
155d44016d | ||
|
13f90bb87a | ||
|
c67b257e51 | ||
|
8237d7e1a4 | ||
|
85da1a17d8 | ||
|
9609b04ff9 | ||
|
04421063af | ||
|
43e1415e71 | ||
|
e1448732b3 | ||
|
7c4c402bd7 | ||
|
6179b17903 | ||
|
05b48d48d9 | ||
|
07a21fdfa9 |
19
.github/ISSUE_TEMPLATE/bug.yml
vendored
19
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -2,12 +2,13 @@ name: Bug Report
|
||||
description: Something is not working right
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
value: |
|
||||
## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
|
||||
---
|
||||
label: Already reported ? *
|
||||
description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
options:
|
||||
- label: I have searched the existing open and closed issues.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
@@ -28,10 +29,10 @@ body:
|
||||
attributes:
|
||||
label: System Info and Version
|
||||
description: |
|
||||
Paste the output of `hyprctl systeminfo -c` here (If you are on a
|
||||
version that shows you help menu, omit the `-c` and attach config files
|
||||
to the issue). If you have configs outside of the main config shown
|
||||
here, please attach.
|
||||
Paste the output of `hyprctl systeminfo -c` here. If you can't
|
||||
launch Hyprland, paste the output of `Hyprland --systeminfo`.
|
||||
If `Hyprland --systeminfo` errors out (added in 0.44.0), find
|
||||
and paste the Hyprland version manually.
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
|
12
.github/workflows/nix-build.yml
vendored
12
.github/workflows/nix-build.yml
vendored
@@ -12,21 +12,17 @@ jobs:
|
||||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
- hyprland-cross
|
||||
- xdg-desktop-portal-hyprland
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
- run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
|
3
.github/workflows/nix-ci.yml
vendored
3
.github/workflows/nix-ci.yml
vendored
@@ -9,7 +9,6 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
build:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure')
|
||||
needs: update-inputs
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
|
||||
# Get version
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
@@ -25,8 +25,18 @@ message(STATUS "Gathering git info")
|
||||
execute_process(COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# udis
|
||||
add_subdirectory("subprojects/udis86")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not
|
||||
# provide a .pc file and won't be detected this way
|
||||
pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2)
|
||||
|
||||
# Fallback to subproject
|
||||
if(NOT udis_dep_FOUND)
|
||||
add_subdirectory("subprojects/udis86")
|
||||
include_directories("subprojects/udis86")
|
||||
message(STATUS "udis86 dependency not found, falling back to subproject")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
@@ -47,8 +57,6 @@ else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
||||
@@ -63,7 +71,8 @@ else()
|
||||
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||
endif()
|
||||
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
include_directories(. "src/" "protocols/")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
@@ -91,14 +100,17 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
|
||||
|
||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine)
|
||||
|
||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
aquamarine
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
@@ -111,7 +123,7 @@ pkg_check_modules(
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.1)
|
||||
hyprutils>=0.2.3)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
@@ -220,14 +232,19 @@ target_precompile_headers(Hyprland PRIVATE
|
||||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::deps)
|
||||
target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps)
|
||||
if(udis_dep_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::udis_dep)
|
||||
else()
|
||||
target_link_libraries(Hyprland libudis86)
|
||||
endif()
|
||||
|
||||
# used by `make installheaders`, to ensure the headers are generated
|
||||
add_custom_target(generate-protocol-headers)
|
||||
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
set(path ${protoPath})
|
||||
else()
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
@@ -255,14 +272,22 @@ function(protocolWayland)
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
|
||||
libudis86)
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.2.0)
|
||||
if(hyprland_protocols_dep_FOUND)
|
||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
||||
else()
|
||||
set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols")
|
||||
message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}")
|
||||
endif()
|
||||
|
||||
protocolnew("${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("${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)
|
||||
@@ -273,8 +298,7 @@ protocolnew("protocols" "input-method-unstable-v2" true)
|
||||
protocolnew("protocols" "wlr-output-management-unstable-v1" true)
|
||||
protocolnew("protocols" "kde-server-decoration" true)
|
||||
protocolnew("protocols" "wlr-data-control-unstable-v1" true)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1"
|
||||
true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
|
||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolnew("protocols" "wayland-drm" true)
|
||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
||||
@@ -306,6 +330,7 @@ protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("staging/drm-lease" "drm-lease-v1" false)
|
||||
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
||||
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
|
24
Makefile
24
Makefile
@@ -1,28 +1,24 @@
|
||||
PREFIX = /usr/local
|
||||
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all
|
||||
chmod -R 777 ./build
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
nopch:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
clear:
|
||||
rm -rf build
|
||||
|
0
assets/install/lockdead.png
Executable file → Normal file
0
assets/install/lockdead.png
Executable file → Normal file
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
@@ -2,5 +2,9 @@ globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check:
|
||||
files = globber.stdout().strip().split('\n')
|
||||
|
||||
foreach file : files
|
||||
install_data(file, install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
install_data(
|
||||
file,
|
||||
install_dir: join_paths(get_option('datadir'), 'hypr'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
endforeach
|
||||
|
@@ -1,2 +1,7 @@
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
install_data(
|
||||
'hyprland-portals.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
|
||||
subdir('install')
|
||||
|
@@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor
|
||||
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn\[aq]t sacrifice on its looks.
|
||||
\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic
|
||||
tiling Wayland compositor that doesn\[aq]t sacrifice on its looks.
|
||||
.PP
|
||||
You can launch Hyprland by either going into a TTY and executing
|
||||
\f[B]Hyprland\f[R], or with a login manager.
|
||||
|
@@ -14,8 +14,8 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
**Hyprland** is a dynamic tiling Wayland compositor based on
|
||||
wlroots that doesn't sacrifice on its looks.
|
||||
**Hyprland** is an independent, highly customizable,
|
||||
dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
|
||||
You can launch Hyprland by either going into a TTY and
|
||||
executing **Hyprland**, or with a login manager.
|
||||
|
@@ -1,2 +1,2 @@
|
||||
install_man ('Hyprland.1')
|
||||
install_man ('hyprctl.1')
|
||||
install_man('Hyprland.1')
|
||||
install_man('hyprctl.1')
|
||||
|
@@ -59,7 +59,7 @@ env = HYPRCURSOR_SIZE,24
|
||||
# Refer to https://wiki.hyprland.org/Configuring/Variables/
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#general
|
||||
general {
|
||||
general {
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
|
||||
@@ -70,7 +70,7 @@ general {
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
||||
resize_on_border = false
|
||||
resize_on_border = false
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
@@ -96,7 +96,7 @@ decoration {
|
||||
enabled = true
|
||||
size = 3
|
||||
passes = 1
|
||||
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ master {
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
misc {
|
||||
misc {
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
|
||||
}
|
||||
@@ -229,13 +229,18 @@ bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
@@ -250,4 +255,8 @@ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
|
@@ -1,2 +1,10 @@
|
||||
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')
|
||||
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',
|
||||
)
|
||||
|
74
flake.lock
generated
74
flake.lock
generated
@@ -16,11 +16,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725199881,
|
||||
"narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=",
|
||||
"lastModified": 1727261104,
|
||||
"narHash": "sha256-rxDI7WrxIRV9it9mDCHcLa7xQykf1JloXnoXr5xQ8zI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b",
|
||||
"rev": "b82fdaff917582a9d568969e15e61b398c71e990",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -42,11 +42,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722623071,
|
||||
"narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=",
|
||||
"lastModified": 1727532803,
|
||||
"narHash": "sha256-ZaZ7h7PY8mQc4vtGmVqWLAq9CAO02gHMyNR5yY8zDmM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "912d56025f03d41b1ad29510c423757b4379eb1c",
|
||||
"rev": "b98726e431d4d3ed58bd58bee1047cdb81cec69f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -56,6 +56,29 @@
|
||||
}
|
||||
},
|
||||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727451107,
|
||||
"narHash": "sha256-qV9savtHwmZUa0eJE294WYJjKPGB2+bJhwByFShsVyo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "6b3261ee13a6d2b99de79a31d352f6996e35bde3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprland-protocols_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"xdph",
|
||||
@@ -93,11 +116,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725188252,
|
||||
"narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=",
|
||||
"lastModified": 1725997860,
|
||||
"narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "c12ab785ce1982f82594aff03b3104c598186ddd",
|
||||
"rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -116,11 +139,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1724966483,
|
||||
"narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=",
|
||||
"lastModified": 1727300645,
|
||||
"narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2",
|
||||
"rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -139,11 +162,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324119,
|
||||
"narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=",
|
||||
"lastModified": 1726874836,
|
||||
"narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30",
|
||||
"rev": "500c81a9e1a76760371049a8d99e008ea77aa59e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -154,11 +177,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1725103162,
|
||||
"narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=",
|
||||
"lastModified": 1727348695,
|
||||
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b",
|
||||
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -172,6 +195,7 @@
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
@@ -197,10 +221,16 @@
|
||||
},
|
||||
"xdph": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprland-protocols": "hyprland-protocols_2",
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -209,11 +239,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725203932,
|
||||
"narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=",
|
||||
"lastModified": 1727524473,
|
||||
"narHash": "sha256-1DGktDtSWIJpnDbVoj/qpvJSH5zg6JbOfuh6xqZMap0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251",
|
||||
"rev": "7e500e679ede40e79cf2d89b5f5fa3e34923bd26",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
24
flake.nix
24
flake.nix
@@ -22,6 +22,12 @@
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
|
||||
hyprland-protocols = {
|
||||
url = "github:hyprwm/hyprland-protocols";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@@ -46,6 +52,8 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -65,6 +73,15 @@
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
pkgsCrossFor = eachSystem (system: crossSystem:
|
||||
import nixpkgs {
|
||||
localSystem = system;
|
||||
crossSystem = crossSystem;
|
||||
overlays = with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
];
|
||||
});
|
||||
in {
|
||||
overlays = import ./nix/overlays.nix {inherit self lib inputs;};
|
||||
|
||||
@@ -90,18 +107,15 @@
|
||||
|
||||
xdg-desktop-portal-hyprland
|
||||
;
|
||||
hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland;
|
||||
});
|
||||
|
||||
devShells = eachSystem (system: {
|
||||
default =
|
||||
pkgsFor.${system}.mkShell.override {
|
||||
stdenv = pkgsFor.${system}.gcc14Stdenv;
|
||||
inherit (self.packages.${system}.default) stdenv;
|
||||
} {
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [
|
||||
expat
|
||||
libxml2
|
||||
];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [pkgsFor.${system}.hyprland];
|
||||
packages = [pkgsFor.${system}.clang-tools];
|
||||
|
@@ -1,10 +1,26 @@
|
||||
executable('hyprctl', 'main.cpp',
|
||||
executable(
|
||||
'hyprctl',
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
],
|
||||
install: true
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl')
|
||||
install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl')
|
||||
install_data(
|
||||
'hyprctl.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprctl',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'hyprctl.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprctl',
|
||||
)
|
||||
|
@@ -1,15 +1,31 @@
|
||||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('hyprpm', src,
|
||||
executable(
|
||||
'hyprpm',
|
||||
src,
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('threads'),
|
||||
dependency('tomlplusplus')
|
||||
dependency('tomlplusplus'),
|
||||
],
|
||||
install : true
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm')
|
||||
install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm')
|
||||
install_data(
|
||||
'../hyprpm.bash',
|
||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
||||
install_tag: 'runtime',
|
||||
rename: 'hyprpm',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.fish',
|
||||
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
|
||||
install_tag: 'runtime',
|
||||
)
|
||||
install_data(
|
||||
'../hyprpm.zsh',
|
||||
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
|
||||
install_tag: 'runtime',
|
||||
rename: '_hyprpm',
|
||||
)
|
||||
|
39
meson.build
39
meson.build
@@ -1,13 +1,17 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
default_options : [
|
||||
project(
|
||||
'Hyprland',
|
||||
'cpp',
|
||||
'c',
|
||||
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
'optimization=3',
|
||||
'buildtype=release',
|
||||
'debug=false',
|
||||
'cpp_std=c++26',
|
||||
])
|
||||
],
|
||||
)
|
||||
|
||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
||||
add_project_arguments(
|
||||
@@ -16,16 +20,19 @@ add_project_arguments(
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
datarootdir,
|
||||
'-Wno-pointer-arith', datarootdir,
|
||||
],
|
||||
language: 'cpp')
|
||||
language: 'cpp',
|
||||
)
|
||||
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
aquamarine = dependency('aquamarine')
|
||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||
|
||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
|
||||
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
|
||||
@@ -34,11 +41,7 @@ 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')
|
||||
gio_dep = dependency('gio-2.0', required: true)
|
||||
|
||||
if not xcb_dep.found()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
@@ -47,6 +50,7 @@ endif
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
# Handle options
|
||||
if get_option('systemd').enabled()
|
||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
||||
endif
|
||||
@@ -59,14 +63,22 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
# Generate hyprland version and populate version.h
|
||||
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
|
||||
# Install headers
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
endforeach
|
||||
|
||||
tracy = dependency('tracy', static: true, required: get_option('tracy_enable'))
|
||||
|
||||
if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized'
|
||||
warning('Profiling builds should set -- buildtype = debugoptimized')
|
||||
endif
|
||||
|
||||
subdir('protocols')
|
||||
subdir('src')
|
||||
subdir('hyprctl')
|
||||
@@ -75,6 +87,7 @@ subdir('assets')
|
||||
subdir('example')
|
||||
subdir('docs')
|
||||
|
||||
# Generate hyprland.pc
|
||||
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
||||
|
||||
import('pkgconfig').generate(
|
||||
|
@@ -1,3 +1,4 @@
|
||||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
|
||||
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
|
||||
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')
|
||||
|
248
nix/default.nix
248
nix/default.nix
@@ -1,20 +1,21 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
stdenvAdapters,
|
||||
pkg-config,
|
||||
pkgconf,
|
||||
makeWrapper,
|
||||
cmake,
|
||||
meson,
|
||||
ninja,
|
||||
aquamarine,
|
||||
binutils,
|
||||
cairo,
|
||||
git,
|
||||
hyprcursor,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
jq,
|
||||
libGL,
|
||||
libdrm,
|
||||
libexecinfo,
|
||||
@@ -24,9 +25,9 @@
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
python3,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86-hyprland,
|
||||
wayland,
|
||||
wayland-protocols,
|
||||
wayland-scanner,
|
||||
@@ -45,133 +46,140 @@
|
||||
enableNvidiaPatches ? false,
|
||||
nvidiaPatches ? false,
|
||||
hidpiXWayland ? false,
|
||||
}:
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland${lib.optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
}: let
|
||||
inherit (builtins) baseNameOf foldl';
|
||||
inherit (lib.asserts) assertMsg;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.lists) flatten concatLists optional optionals;
|
||||
inherit (lib.sources) cleanSourceWith cleanSource;
|
||||
inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
filter = name: type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (lib.hasSuffix ".nix" baseName);
|
||||
src = lib.cleanSource ../.;
|
||||
};
|
||||
adapters = flatten [
|
||||
stdenvAdapters.useMoldLinker
|
||||
];
|
||||
|
||||
patches = [
|
||||
# forces GCC to use -std=c++26
|
||||
./stdcxx.patch
|
||||
];
|
||||
customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters;
|
||||
in
|
||||
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
customStdenv.mkDerivation {
|
||||
pname = "hyprland${optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
postPatch = ''
|
||||
# Fix hardcoded paths to /usr installation
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
src = cleanSourceWith {
|
||||
filter = name: type: let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
! (hasSuffix ".nix" baseName);
|
||||
src = cleanSource ../.;
|
||||
};
|
||||
|
||||
# Remove extra @PREFIX@ to fix pkg-config paths
|
||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
postPatch = ''
|
||||
# Fix hardcoded paths to /usr installation
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = lib.optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
# Remove extra @PREFIX@ to fix pkg-config paths
|
||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
jq
|
||||
makeWrapper
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
python3 # for udis86
|
||||
wayland-scanner
|
||||
];
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"man"
|
||||
"dev"
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
makeWrapper
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs = lib.concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
# expat
|
||||
# fribidi
|
||||
git
|
||||
hyprcursor
|
||||
hyprlang
|
||||
hyprutils
|
||||
# libdatrie
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
# libselinux
|
||||
# libsepol
|
||||
# libthai
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
# pcre2
|
||||
tomlplusplus
|
||||
wayland
|
||||
wayland-protocols
|
||||
xorg.libXcursor
|
||||
]
|
||||
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(lib.optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
xorg.libXdmcp
|
||||
xorg.xcbutilerrors
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
xwayland
|
||||
])
|
||||
(lib.optionals withSystemd [systemd])
|
||||
];
|
||||
outputs = [
|
||||
"out"
|
||||
"man"
|
||||
"dev"
|
||||
];
|
||||
|
||||
cmakeBuildType =
|
||||
if debug
|
||||
then "Debug"
|
||||
else "RelWithDebInfo";
|
||||
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
|
||||
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
|
||||
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
${lib.optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${lib.makeBinPath [
|
||||
binutils
|
||||
buildInputs = concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
git
|
||||
hyprcursor
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
hyprutils
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
pkgconf
|
||||
]}
|
||||
''}
|
||||
'';
|
||||
tomlplusplus
|
||||
udis86-hyprland
|
||||
wayland
|
||||
wayland-protocols
|
||||
wayland-scanner
|
||||
xorg.libXcursor
|
||||
]
|
||||
(optionals customStdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
xorg.libXdmcp
|
||||
xorg.xcbutilerrors
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
xwayland
|
||||
])
|
||||
(optional withSystemd systemd)
|
||||
];
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
mesonBuildType =
|
||||
if debug
|
||||
then "debugoptimized"
|
||||
else "release";
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/hyprwm/Hyprland";
|
||||
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = lib.licenses.bsd3;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
mesonFlags = flatten [
|
||||
(mapAttrsToList mesonEnable {
|
||||
"xwayland" = enableXWayland;
|
||||
"legacy_renderer" = legacyRenderer;
|
||||
"systemd" = withSystemd;
|
||||
})
|
||||
(mapAttrsToList mesonBool {
|
||||
"b_pch" = false;
|
||||
"tracy_enable" = false;
|
||||
})
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
${optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${makeBinPath [
|
||||
binutils
|
||||
pciutils
|
||||
pkgconf
|
||||
]}
|
||||
''}
|
||||
'';
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/hyprwm/Hyprland";
|
||||
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = lib.licenses.bsd3;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
|
@@ -22,9 +22,11 @@ in {
|
||||
# Dependencies
|
||||
inputs.aquamarine.overlays.default
|
||||
inputs.hyprcursor.overlays.default
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
self.overlays.udis86
|
||||
|
||||
# Hyprland packages themselves
|
||||
(final: prev: let
|
||||
@@ -63,4 +65,20 @@ in {
|
||||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
# udis86 from nixpkgs is too old, and also does not provide a .pc file
|
||||
# this version is the one used in the git submodule, and allows us to
|
||||
# fetch the source without '?submodules=1'
|
||||
udis86 = final: prev: {
|
||||
udis86-hyprland = prev.udis86.overrideAttrs (self: super: {
|
||||
src = final.fetchFromGitHub {
|
||||
owner = "canihavesomecoffee";
|
||||
repo = "udis86";
|
||||
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
|
||||
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
|
||||
};
|
||||
|
||||
patches = [];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@@ -1,12 +0,0 @@
|
||||
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
|
@@ -1,77 +1,76 @@
|
||||
wayland_protos = dependency('wayland-protocols',
|
||||
wayland_protos = dependency(
|
||||
'wayland-protocols',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
|
||||
hyprland_protos = dependency('hyprland-protocols',
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.2',
|
||||
fallback: 'hyprland-protocols',
|
||||
fallback: 'hyprland-protocols',
|
||||
)
|
||||
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
|
||||
hyprwayland_scanner = find_program(
|
||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
new_protocols = [
|
||||
['wlr-gamma-control-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
['input-method-unstable-v2.xml'],
|
||||
['virtual-keyboard-unstable-v1.xml'],
|
||||
['wlr-virtual-pointer-unstable-v1.xml'],
|
||||
['wlr-output-management-unstable-v1.xml'],
|
||||
['kde-server-decoration.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['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'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
|
||||
[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'],
|
||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
||||
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/viewporter/viewporter.xml'],
|
||||
[wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-dialog/xdg-dialog-v1.xml'],
|
||||
protocols = [
|
||||
'wlr-gamma-control-unstable-v1.xml',
|
||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
'input-method-unstable-v2.xml',
|
||||
'virtual-keyboard-unstable-v1.xml',
|
||||
'wlr-virtual-pointer-unstable-v1.xml',
|
||||
'wlr-output-management-unstable-v1.xml',
|
||||
'kde-server-decoration.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'wayland-drm.xml',
|
||||
'wlr-data-control-unstable-v1.xml',
|
||||
'wlr-screencopy-unstable-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
|
||||
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
|
||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
|
||||
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
|
||||
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
|
||||
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
||||
wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
|
||||
wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
|
||||
wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
|
||||
wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
|
||||
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
|
||||
new_wl_protos = []
|
||||
foreach p : new_protocols
|
||||
xml = join_paths(p)
|
||||
new_wl_protos += custom_target(
|
||||
xml.underscorify(),
|
||||
input: xml,
|
||||
wl_protocols = []
|
||||
foreach protocol : protocols
|
||||
wl_protocols += custom_target(
|
||||
protocol.underscorify(),
|
||||
input: protocol,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
@@ -79,31 +78,26 @@ foreach p : new_protocols
|
||||
)
|
||||
endforeach
|
||||
|
||||
wayland_server_dep = dependency('wayland-server', version: '>=1.20.0')
|
||||
wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir')
|
||||
# wayland.xml generation
|
||||
wayland_scanner = dependency('wayland-scanner')
|
||||
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
|
||||
|
||||
wl_server_protos = [
|
||||
wayland_server_dir / 'wayland.xml'
|
||||
]
|
||||
wl_server_protos_gen = []
|
||||
foreach p : wl_server_protos
|
||||
wl_server_protos_gen += custom_target(
|
||||
p.underscorify(),
|
||||
input: p,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
endforeach
|
||||
wayland_xml = wayland_scanner_datadir / 'wayland.xml'
|
||||
wayland_protocol = custom_target(
|
||||
wayland_xml.underscorify(),
|
||||
input: wayland_xml,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
|
||||
lib_server_protos = static_library(
|
||||
'server_protos',
|
||||
wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen,
|
||||
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
|
||||
wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
||||
server_protos = declare_dependency(
|
||||
link_with: lib_server_protos,
|
||||
sources: wl_protos_headers + new_wl_protos,
|
||||
sources: wl_protocols + wayland_protocol,
|
||||
)
|
||||
|
@@ -23,11 +23,13 @@
|
||||
#include "protocols/PointerConstraints.hpp"
|
||||
#include "protocols/LayerShell.hpp"
|
||||
#include "protocols/XDGShell.hpp"
|
||||
#include "protocols/XDGOutput.hpp"
|
||||
#include "protocols/core/Compositor.hpp"
|
||||
#include "protocols/core/Subcompositor.hpp"
|
||||
#include "desktop/LayerSurface.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "xwayland/XWayland.hpp"
|
||||
#include "helpers/ByteOperations.hpp"
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
@@ -229,6 +231,9 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
if (envEnabled("HYPRLAND_TRACE"))
|
||||
Debug::trace = true;
|
||||
|
||||
// set the buffer size to 1MB to avoid disconnects due to an app hanging for a short while
|
||||
wl_display_set_default_max_buffer_size(m_sWLDisplay, 1_MB);
|
||||
|
||||
Aquamarine::SBackendOptions options;
|
||||
options.logFunction = aqLog;
|
||||
|
||||
@@ -2696,7 +2701,17 @@ WORKSPACEID CCompositor::getNewSpecialID() {
|
||||
}
|
||||
|
||||
void CCompositor::performUserChecks() {
|
||||
; // intentional
|
||||
static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
|
||||
|
||||
if (!*PNOCHECKXDG) {
|
||||
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
|
||||
if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") {
|
||||
g_pHyprNotificationOverlay->addNotification(
|
||||
std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.",
|
||||
CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"),
|
||||
CColor{}, 15000, ICON_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) {
|
||||
@@ -2855,6 +2870,8 @@ void CCompositor::arrangeMonitors() {
|
||||
else
|
||||
m->xwaylandScale = 1.f;
|
||||
}
|
||||
|
||||
PROTO::xdgOutput->updateAllOutputs();
|
||||
}
|
||||
|
||||
void CCompositor::enterUnsafeState() {
|
||||
@@ -2943,6 +2960,38 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
|
||||
return {};
|
||||
}
|
||||
|
||||
static void checkDefaultCursorWarp(SP<CMonitor> monitor) {
|
||||
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 == monitor->szName) {
|
||||
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 CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
||||
// add it to real
|
||||
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>(output));
|
||||
@@ -2977,6 +3026,8 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR);
|
||||
|
||||
checkDefaultCursorWarp(PNEWMONITOR);
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||
w->m_iLastSurfaceMonitorID = MONITOR_INVALID;
|
||||
|
@@ -772,6 +772,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_GRADIENT,
|
||||
.data = SConfigOptionDescription::SGradientData{"0x66775500"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "group:auto_group",
|
||||
.description = "automatically group new windows",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
|
||||
/*
|
||||
* group:groupbar:
|
||||
@@ -1049,6 +1055,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_INT,
|
||||
.data = SConfigOptionDescription::SRangeData{15, 1, 120},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "misc:disable_xdg_env_checks",
|
||||
.description = "disable the warning if XDG environment is externally managed",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
|
||||
/*
|
||||
* binds:
|
||||
@@ -1366,4 +1378,164 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
|
||||
/*
|
||||
* dwindle:
|
||||
*/
|
||||
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:pseudotile",
|
||||
.description = "enable pseudotiling. Pseudotiled windows retain their floating size when tiled.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:force_split",
|
||||
.description = "0 -> split follows mouse, 1 -> always split to the left (new = left or top) 2 -> always split to the right (new = right or bottom)",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "follow mouse,left or top,right or bottom"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:preserve_split",
|
||||
.description = "if enabled, the split (side/top) will not change regardless of what happens to the container.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:smart_split",
|
||||
.description = "if enabled, allows a more precise control over the window split direction based on the cursor's position. The window is conceptually divided into four "
|
||||
"triangles, and cursor's triangle determines the split direction. This feature also turns on preserve_split.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:smart_resizing",
|
||||
.description =
|
||||
"if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:permanent_direction_override",
|
||||
.description = "if enabled, makes the preselect direction persist until either this mode is turned off, another direction is specified, or a non-direction is specified "
|
||||
"(anything other than l,r,u/t,d/b)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:special_scale_factor",
|
||||
.description = "specifies the scale factor of windows on the special workspace [0 - 1]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{1, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:split_width_multiplier",
|
||||
.description = "specifies the auto-split width multiplier",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{1, 0.1, 3},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:no_gaps_when_only",
|
||||
.description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:use_active_for_splits",
|
||||
.description = "whether to prefer the active window or the mouse position for splits",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:default_split_ratio",
|
||||
.description = "the default split ratio on window open. 1 means even 50/50 split. [0.1 - 1.9]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{1, 0.1, 1.9},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "dwindle:split_bias",
|
||||
.description = "specifies which window will receive the larger half of a split. positional - 0, current window - 1, opening window - 2 [0/1/2]",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"},
|
||||
},
|
||||
|
||||
/*
|
||||
* master:
|
||||
*/
|
||||
|
||||
SConfigOptionDescription{
|
||||
.value = "master:allow_small_split",
|
||||
.description = "enable adding additional master windows in a horizontal split style",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:special_scale_factor",
|
||||
.description = "the scale of the special workspace windows. [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{1, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:mfact",
|
||||
.description =
|
||||
"the size as a percentage of the master window, for example `mfact = 0.70` would mean 70% of the screen will be the master window, and 30% the slave [0.0 - 1.0]",
|
||||
.type = CONFIG_OPTION_FLOAT,
|
||||
.data = SConfigOptionDescription::SFloatData{0.55, 0, 1},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:new_status",
|
||||
.description = "`master`: new window becomes master; `slave`: new windows are added to slave stack; `inherit`: inherit from focused window",
|
||||
.type = CONFIG_OPTION_STRING_SHORT,
|
||||
.data = SConfigOptionDescription::SStringData{"slave"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:new_on_top",
|
||||
.description = "whether a newly open window should be on the top of the stack",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:new_on_active",
|
||||
.description = "`before`, `after`: place new window relative to the focused window; `none`: place new window according to the value of `new_on_top`. ",
|
||||
.type = CONFIG_OPTION_STRING_SHORT,
|
||||
.data = SConfigOptionDescription::SStringData{"none"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:no_gaps_when_only",
|
||||
.description = "whether to apply gaps when there is only one window on a workspace, aka. smart gaps. (default: disabled - 0) no border - 1, with border - 2 [0/1/2]",
|
||||
.type = CONFIG_OPTION_CHOICE,
|
||||
.data = SConfigOptionDescription::SChoiceData{0, "disabled,no border,with border"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:orientation",
|
||||
.description = "default placement of the master area, can be left, right, top, bottom or center",
|
||||
.type = CONFIG_OPTION_STRING_SHORT,
|
||||
.data = SConfigOptionDescription::SStringData{"left"},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:inherit_fullscreen",
|
||||
.description = "inherit fullscreen status when cycling/swapping to another window (e.g. monocle layout)",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:always_center_master",
|
||||
.description = "when using orientation=center, keep the master window centered, even when it is the only window in the workspace.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{false},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:smart_resizing",
|
||||
.description =
|
||||
"if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
SConfigOptionDescription{
|
||||
.value = "master:drop_at_cursor",
|
||||
.description = "when enabled, dragging and dropping windows will put them at the cursor position. Otherwise, when dropped at the stack side, they will go to the "
|
||||
"top/bottom of the stack depending on new_on_top.",
|
||||
.type = CONFIG_OPTION_BOOL,
|
||||
.data = SConfigOptionDescription::SBoolData{true},
|
||||
},
|
||||
};
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include "helpers/varlist/VarList.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../xwayland/XWayland.hpp"
|
||||
#include "../protocols/OutputManagement.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -371,10 +372,12 @@ CConfigManager::CConfigManager() {
|
||||
m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15});
|
||||
m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0});
|
||||
|
||||
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY});
|
||||
m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8});
|
||||
@@ -444,6 +447,7 @@ CConfigManager::CConfigManager() {
|
||||
m_pConfig->addConfigValue("dwindle:no_gaps_when_only", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:use_active_for_splits", Hyprlang::INT{1});
|
||||
m_pConfig->addConfigValue("dwindle:default_split_ratio", {1.f});
|
||||
m_pConfig->addConfigValue("dwindle:split_bias", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:smart_split", Hyprlang::INT{0});
|
||||
m_pConfig->addConfigValue("dwindle:smart_resizing", Hyprlang::INT{1});
|
||||
|
||||
@@ -682,6 +686,10 @@ std::string CConfigManager::getMainConfigPath() {
|
||||
if (!g_pCompositor->explicitConfigPath.empty())
|
||||
return g_pCompositor->explicitConfigPath;
|
||||
|
||||
if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV)
|
||||
return CFG_ENV;
|
||||
Debug::log(TRACE, "Seems as if HYPRLAND_CONFIG isn't set, let's see what we can do with HOME.");
|
||||
|
||||
static const auto paths = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland");
|
||||
if (paths.first.has_value()) {
|
||||
return paths.first.value();
|
||||
@@ -859,8 +867,10 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
||||
if (result.error && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:suppress_errors")))
|
||||
g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
|
||||
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));
|
||||
g_pHyprError->queueCreate(
|
||||
"Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() +
|
||||
" )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\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
|
||||
@@ -1074,28 +1084,69 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s
|
||||
return VAL;
|
||||
}
|
||||
|
||||
SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
|
||||
SMonitorRule CConfigManager::getMonitorRuleFor(const SP<CMonitor> PMONITOR) {
|
||||
auto applyWlrOutputConfig = [PMONITOR](SMonitorRule rule) -> SMonitorRule {
|
||||
const auto CONFIG = PROTO::outputManagement->getOutputStateFor(PMONITOR);
|
||||
|
||||
if (!CONFIG)
|
||||
return rule;
|
||||
|
||||
Debug::log(LOG, "CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {}", PMONITOR->szName);
|
||||
|
||||
Debug::log(LOG, " > overriding enabled: {} -> {}", !rule.disabled, !CONFIG->enabled);
|
||||
rule.disabled = !CONFIG->enabled;
|
||||
|
||||
if ((CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_MODE) || (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE)) {
|
||||
Debug::log(LOG, " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz", rule.resolution.x, rule.resolution.y, rule.refreshRate, CONFIG->resolution.x,
|
||||
CONFIG->resolution.y, CONFIG->refresh / 1000.F);
|
||||
rule.resolution = CONFIG->resolution;
|
||||
rule.refreshRate = CONFIG->refresh / 1000.F;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
|
||||
Debug::log(LOG, " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f}", rule.offset.x, rule.offset.y, CONFIG->position.x, CONFIG->position.y);
|
||||
rule.offset = CONFIG->position;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
|
||||
Debug::log(LOG, " > overriding transform: {} -> {}", (uint8_t)rule.transform, (uint8_t)CONFIG->transform);
|
||||
rule.transform = CONFIG->transform;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
|
||||
Debug::log(LOG, " > overriding scale: {} -> {}", (uint8_t)rule.scale, (uint8_t)CONFIG->scale);
|
||||
rule.scale = CONFIG->scale;
|
||||
}
|
||||
|
||||
if (CONFIG->committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
|
||||
Debug::log(LOG, " > overriding vrr: {} -> {}", rule.vrr.value_or(0), CONFIG->adaptiveSync);
|
||||
rule.vrr = (int)CONFIG->adaptiveSync;
|
||||
}
|
||||
|
||||
return rule;
|
||||
};
|
||||
|
||||
for (auto const& r : m_dMonitorRules | std::views::reverse) {
|
||||
if (PMONITOR.matchesStaticSelector(r.name)) {
|
||||
return r;
|
||||
if (PMONITOR->matchesStaticSelector(r.name)) {
|
||||
return applyWlrOutputConfig(r);
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName);
|
||||
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR->szName);
|
||||
|
||||
for (auto const& r : m_dMonitorRules) {
|
||||
if (r.name.empty()) {
|
||||
return r;
|
||||
return applyWlrOutputConfig(r);
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(WARN, "No rules configured. Using the default hardcoded one.");
|
||||
|
||||
return SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
|
||||
.name = "",
|
||||
.resolution = Vector2D(0, 0),
|
||||
.offset = Vector2D(-INT32_MAX, -INT32_MAX),
|
||||
.scale = -1}; // 0, 0 is preferred and -1, -1 is auto
|
||||
return applyWlrOutputConfig(SMonitorRule{.autoDir = eAutoDirs::DIR_AUTO_RIGHT,
|
||||
.name = "",
|
||||
.resolution = Vector2D(0, 0),
|
||||
.offset = Vector2D(-INT32_MAX, -INT32_MAX),
|
||||
.scale = -1}); // 0, 0 is preferred and -1, -1 is auto
|
||||
}
|
||||
|
||||
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) {
|
||||
@@ -1454,7 +1505,7 @@ void CConfigManager::performMonitorReload() {
|
||||
if (!m->output || m->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(*m);
|
||||
auto rule = getMonitorRuleFor(m);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
@@ -1511,7 +1562,7 @@ void CConfigManager::ensureMonitorStatus() {
|
||||
if (!rm->output || rm->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(*rm);
|
||||
auto rule = getMonitorRuleFor(rm);
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled)
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
@@ -2239,7 +2290,7 @@ bool windowRuleValid(const std::string& RULE) {
|
||||
|
||||
bool layerRuleValid(const std::string& RULE) {
|
||||
static const auto rules = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"};
|
||||
static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation"};
|
||||
static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"};
|
||||
|
||||
return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); });
|
||||
}
|
||||
|
@@ -169,7 +169,7 @@ class CConfigManager {
|
||||
static std::string getMainConfigPath();
|
||||
const std::string getConfigString();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SMonitorRule getMonitorRuleFor(const SP<CMonitor>);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
|
@@ -72,7 +72,7 @@ env = HYPRCURSOR_SIZE,24
|
||||
# Refer to https://wiki.hyprland.org/Configuring/Variables/
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#general
|
||||
general {
|
||||
general {
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
|
||||
@@ -83,7 +83,7 @@ general {
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
||||
resize_on_border = false
|
||||
resize_on_border = false
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
@@ -109,7 +109,7 @@ decoration {
|
||||
enabled = true
|
||||
size = 3
|
||||
passes = 1
|
||||
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,7 @@ master {
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
misc {
|
||||
misc {
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
|
||||
}
|
||||
@@ -249,6 +249,12 @@ bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
# Requires playerctl
|
||||
bindl = , XF86AudioNext, exec, playerctl next
|
||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
##############################
|
||||
@@ -262,5 +268,9 @@ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
# Ignore maximize requests from apps. You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.*
|
||||
|
||||
# Fix some dragging issues with XWayland
|
||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
||||
)#";
|
||||
|
@@ -103,6 +103,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
||||
"focused": {},
|
||||
"dpmsStatus": {},
|
||||
"vrr": {},
|
||||
"solitary": "{:x}",
|
||||
"activelyTearing": {},
|
||||
"disabled": {},
|
||||
"currentFormat": "{}",
|
||||
@@ -114,19 +115,20 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
|
||||
m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(),
|
||||
escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"),
|
||||
(m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (uint64_t)m->solitaryClient.get(),
|
||||
(m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->output->state->state().drmFormat),
|
||||
availableModesForOutput(m.get(), format));
|
||||
|
||||
} else {
|
||||
result += std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tsolitary: {:x}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x,
|
||||
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing,
|
||||
!m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, (uint64_t)m->solitaryClient.get(),
|
||||
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -158,16 +160,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
if (!m->output || m->ID == -1)
|
||||
continue;
|
||||
|
||||
result += std::format(
|
||||
"Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\n\tavailableModes: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"),
|
||||
(int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled,
|
||||
formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
|
||||
result += CHyprCtl::getMonitorData(m, format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,45 +313,48 @@ std::string CHyprCtl::getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat form
|
||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputFormat format) {
|
||||
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
||||
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ?
|
||||
std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) :
|
||||
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
||||
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ?
|
||||
std::format(",\n \"gapsIn\": [{}, {}, {}, {}]", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) :
|
||||
"";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ?
|
||||
std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) :
|
||||
"";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ?
|
||||
std::format(",\n \"gapsOut\": [{}, {}, {}, {}]", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) :
|
||||
"";
|
||||
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||
const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : "";
|
||||
const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : "";
|
||||
const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : "";
|
||||
const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : "";
|
||||
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||
const std::string border = (bool)(r.noBorder) ? std::format(",\n \"border\": {}", boolToString(!r.noBorder.value())) : "";
|
||||
const std::string rounding = (bool)(r.noRounding) ? std::format(",\n \"rounding\": {}", boolToString(!r.noRounding.value())) : "";
|
||||
const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : "";
|
||||
const std::string shadow = (bool)(r.noShadow) ? std::format(",\n \"shadow\": {}", boolToString(!r.noShadow.value())) : "";
|
||||
const std::string defaultName = r.defaultName.has_value() ? std::format(",\n \"defaultName\": \"{}\"", escapeJSONStrings(r.defaultName.value())) : "";
|
||||
|
||||
std::string result = std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}
|
||||
std::string result =
|
||||
std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}{}{}{}
|
||||
}})#",
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow, defaultName);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
||||
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right),
|
||||
std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) :
|
||||
std::format("\tgapsIn: <unset>\n");
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right),
|
||||
std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) :
|
||||
std::format("\tgapsOut: <unset>\n");
|
||||
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
||||
const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : "<unset>");
|
||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : "<unset>");
|
||||
const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : "<unset>");
|
||||
const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : "<unset>");
|
||||
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
||||
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right),
|
||||
std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) :
|
||||
std::format("\tgapsIn: <unset>\n");
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right),
|
||||
std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) :
|
||||
std::format("\tgapsOut: <unset>\n");
|
||||
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
||||
const std::string border = std::format("\tborder: {}\n", (bool)(r.noBorder) ? boolToString(!r.noBorder.value()) : "<unset>");
|
||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.noRounding) ? boolToString(!r.noRounding.value()) : "<unset>");
|
||||
const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : "<unset>");
|
||||
const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.noShadow) ? boolToString(!r.noShadow.value()) : "<unset>");
|
||||
const std::string defaultName = std::format("\tdefaultName: {}\n", r.defaultName.value_or("<unset>"));
|
||||
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow);
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow, defaultName);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -858,7 +854,8 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
|
||||
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n";
|
||||
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" +
|
||||
"\n\nflags: (if any)\n";
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "legacyrenderer\n";
|
||||
@@ -881,8 +878,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
"commit_date": "{}",
|
||||
"tag": "{}",
|
||||
"commits": "{}",
|
||||
"buildAquamarine": "{}",
|
||||
"flags": [)#",
|
||||
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS);
|
||||
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS,
|
||||
AQUAMARINE_VERSION);
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "\"legacyrenderer\",";
|
||||
@@ -935,11 +934,14 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
|
||||
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
|
||||
|
||||
result += "plugins:\n";
|
||||
for (auto const& pl : g_pPluginSystem->getAllPlugins()) {
|
||||
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
|
||||
}
|
||||
if (g_pPluginSystem) {
|
||||
for (auto const& pl : g_pPluginSystem->getAllPlugins()) {
|
||||
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
|
||||
}
|
||||
} else
|
||||
result += "\tunknown: not runtime\n";
|
||||
|
||||
if (g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) {
|
||||
if (g_pHyprCtl && g_pHyprCtl->m_sCurrentRequestParams.sysInfoConfig) {
|
||||
result += "\n======Config-Start======\n";
|
||||
result += g_pConfigManager->getConfigString();
|
||||
result += "\n======Config-End========\n";
|
||||
@@ -987,9 +989,9 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
||||
const auto COMMAND = in.substr(0, secondSpacePos);
|
||||
const auto VALUE = in.substr(secondSpacePos + 1);
|
||||
|
||||
// If either COMMAND or VALUE is empty, handle accordingly
|
||||
if (COMMAND.empty() || VALUE.empty())
|
||||
return "Invalid input: command or value is empty";
|
||||
// If COMMAND is empty, handle accordingly
|
||||
if (COMMAND.empty())
|
||||
return "Invalid input: command is empty";
|
||||
|
||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
||||
|
||||
@@ -1621,6 +1623,14 @@ std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) {
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string submapRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string submap = g_pKeybindManager->getCurrentSubmap();
|
||||
if (submap.empty())
|
||||
submap = "default";
|
||||
|
||||
return format == FORMAT_JSON ? std::format("{{\"{}\"}}\n", escapeJSONStrings(submap)) : (submap + "\n");
|
||||
}
|
||||
|
||||
CHyprCtl::CHyprCtl() {
|
||||
registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest});
|
||||
registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest});
|
||||
@@ -1642,6 +1652,7 @@ CHyprCtl::CHyprCtl() {
|
||||
registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest});
|
||||
registerCommand(SHyprCtlCommand{"locked", true, getIsLocked});
|
||||
registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions});
|
||||
registerCommand(SHyprCtlCommand{"submap", true, submapRequest});
|
||||
|
||||
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
|
||||
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});
|
||||
|
@@ -5,6 +5,9 @@
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
// exposed for main.cpp
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include "includes.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/WLListener.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
|
@@ -394,6 +394,11 @@ void CLayerSurface::applyRules() {
|
||||
} else if (rule.rule.starts_with("animation")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
animationStyle = vars[1];
|
||||
} else if (rule.rule.starts_with("order")) {
|
||||
CVarList vars{rule.rule, 2, 's'};
|
||||
try {
|
||||
order = std::stoi(vars[1]);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,7 @@ class CLayerSurface {
|
||||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
bool dimAround = false;
|
||||
int64_t order = 0;
|
||||
|
||||
std::optional<std::string> animationStyle;
|
||||
|
||||
|
@@ -30,13 +30,7 @@ CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner)
|
||||
}
|
||||
|
||||
CSubsurface::~CSubsurface() {
|
||||
hyprListener_newSubsurface.removeCallback();
|
||||
|
||||
if (!m_pSubsurface)
|
||||
return;
|
||||
|
||||
hyprListener_commitSubsurface.removeCallback();
|
||||
hyprListener_destroySubsurface.removeCallback();
|
||||
;
|
||||
}
|
||||
|
||||
void CSubsurface::initSignals() {
|
||||
|
@@ -35,10 +35,6 @@ class CSubsurface {
|
||||
void recheckDamageForSubsurfaces();
|
||||
|
||||
private:
|
||||
DYNLISTENER(destroySubsurface);
|
||||
DYNLISTENER(commitSubsurface);
|
||||
DYNLISTENER(newSubsurface);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroySubsurface;
|
||||
CHyprSignalListener commitSubsurface;
|
||||
|
@@ -62,7 +62,7 @@ bool CWLSurface::small() const {
|
||||
|
||||
const auto O = m_pWindowOwner.lock();
|
||||
|
||||
return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1;
|
||||
return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
|
@@ -991,7 +991,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.client;
|
||||
const auto MODE = PCURRENT->m_sFullscreenState.internal;
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
||||
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
||||
|
@@ -178,13 +178,18 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
if (xkbState)
|
||||
xkb_state_unref(xkbState);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_unref(xkbSymState);
|
||||
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
xkbSymState = nullptr;
|
||||
|
||||
if (keymap) {
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
|
||||
xkbStaticState = xkb_state_new(keymap);
|
||||
xkbState = xkb_state_new(keymap);
|
||||
xkbSymState = xkb_state_new(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,6 +235,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
|
||||
xkbState = xkb_state_new(KEYMAP);
|
||||
xkbStaticState = xkb_state_new(KEYMAP);
|
||||
xkbSymState = xkb_state_new(KEYMAP);
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
@@ -252,6 +258,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
|
||||
xkbState = xkb_state_new(NEWKEYMAP);
|
||||
xkbStaticState = xkb_state_new(NEWKEYMAP);
|
||||
xkbSymState = xkb_state_new(NEWKEYMAP);
|
||||
|
||||
xkb_keymap_unref(NEWKEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
@@ -332,6 +339,9 @@ void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t l
|
||||
|
||||
xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, group);
|
||||
|
||||
if (!updateModifiersState())
|
||||
return;
|
||||
|
||||
@@ -382,6 +392,9 @@ void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) {
|
||||
xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
|
||||
if (updateModifiersState()) {
|
||||
if (xkbSymState)
|
||||
xkb_state_update_mask(xkbSymState, 0, 0, 0, 0, 0, modifiersState.group);
|
||||
|
||||
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||
.depressed = modifiersState.depressed,
|
||||
.latched = modifiersState.latched,
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
@@ -83,8 +82,9 @@ class IKeyboard : public IHID {
|
||||
bool keymapOverridden = false;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr;
|
||||
xkb_keymap* xkbKeymap = nullptr;
|
||||
xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr,
|
||||
*xkbSymState = nullptr /* Same as static but gets layouts */;
|
||||
xkb_keymap* xkbKeymap = nullptr;
|
||||
|
||||
struct {
|
||||
uint32_t depressed = 0, latched = 0, locked = 0, group = 0;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHID.hpp"
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
@@ -322,7 +322,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->updateWindowData();
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
PWINDOW->m_bCreatedOverFullscreen = true;
|
||||
|
||||
// size and move rules
|
||||
|
54
src/helpers/ByteOperations.hpp
Normal file
54
src/helpers/ByteOperations.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#define ULL unsigned long long
|
||||
#define LD long double
|
||||
|
||||
constexpr ULL operator""_kB(const ULL BYTES) {
|
||||
return BYTES * 1024;
|
||||
}
|
||||
constexpr ULL operator""_MB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024;
|
||||
}
|
||||
constexpr ULL operator""_GB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr ULL operator""_TB(const ULL BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_kB(const LD BYTES) {
|
||||
return BYTES * 1024;
|
||||
}
|
||||
constexpr LD operator""_MB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_GB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024;
|
||||
}
|
||||
constexpr LD operator""_TB(const LD BYTES) {
|
||||
return BYTES * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using __acceptable_byte_operation_type = typename std::enable_if<std::is_trivially_constructible<T, ULL>::value || std::is_trivially_constructible<T, LD>::value>::type;
|
||||
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X kBtoBytes(const X kB) {
|
||||
return kB * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X MBtoBytes(const X MB) {
|
||||
return MB * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X GBtoBytes(const X GB) {
|
||||
return GB * 1024 * 1024 * 1024;
|
||||
}
|
||||
template <typename X, typename = __acceptable_byte_operation_type<X>>
|
||||
constexpr X TBtoBytes(const X TB) {
|
||||
return TB * 1024 * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
#undef ULL
|
||||
#undef LD
|
@@ -8,8 +8,9 @@ class CColor {
|
||||
CColor(float r, float g, float b, float a);
|
||||
CColor(uint64_t);
|
||||
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
|
||||
// AR32
|
||||
uint32_t getAsHex() const;
|
||||
|
||||
CColor operator-(const CColor& c2) const {
|
||||
|
@@ -628,27 +628,6 @@ void logSystemInfo() {
|
||||
Debug::log(NONE, "{}", execAndGet("cat /etc/os-release"));
|
||||
}
|
||||
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
|
||||
memset(mat, 0, sizeof(*mat) * 9);
|
||||
|
||||
const float* t = transforms[tr];
|
||||
float x = 2.0f / w;
|
||||
float y = 2.0f / h;
|
||||
|
||||
// Rotation + reflection
|
||||
mat[0] = x * t[0];
|
||||
mat[1] = x * t[1];
|
||||
mat[3] = y * t[3];
|
||||
mat[4] = y * t[4];
|
||||
|
||||
// Translation
|
||||
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
|
||||
|
||||
// Identity
|
||||
mat[8] = 1.0f;
|
||||
}
|
||||
|
||||
int64_t getPPIDof(int64_t pid) {
|
||||
#if defined(KERN_PROC_PID)
|
||||
int mib[] = {
|
||||
|
@@ -34,7 +34,6 @@ int64_t getPPIDof(int64_t pid);
|
||||
int64_t configStringToInt(const std::string&);
|
||||
Vector2D configStringToVector2D(const std::string&);
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||
double normalizeAngleRad(double ang);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#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"
|
||||
@@ -13,11 +12,14 @@
|
||||
#include "../protocols/DRMSyncobj.hpp"
|
||||
#include "../protocols/core/Output.hpp"
|
||||
#include "../managers/PointerManager.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "sync/SyncTimeline.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::Utils;
|
||||
|
||||
int ratHandler(void* data) {
|
||||
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
||||
@@ -34,6 +36,7 @@ CMonitor::~CMonitor() {
|
||||
}
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
|
||||
|
||||
if (output->supportsExplicit) {
|
||||
inTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
|
||||
@@ -113,7 +116,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
createdByUser = true; // should be true. WL and Headless backends should be addable / removable
|
||||
|
||||
// get monitor rule that matches
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(self.lock());
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (monitorRule.disabled) {
|
||||
@@ -192,10 +195,6 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!activeMonitorRule.mirrorOf.empty())
|
||||
setMirror(activeMonitorRule.mirrorOf);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
g_pCompositor->setActiveMonitor(this);
|
||||
|
||||
@@ -224,9 +223,20 @@ void CMonitor::onConnect(bool noRule) {
|
||||
PROTO::gamma->applyGammaToState(this);
|
||||
|
||||
events.connect.emit();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
|
||||
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect(bool destroy) {
|
||||
CScopeGuard x = {[this]() {
|
||||
if (g_pCompositor->m_bIsShuttingDown)
|
||||
return;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
||||
EMIT_HOOK_EVENT("monitorRemoved", this);
|
||||
g_pCompositor->arrangeMonitors();
|
||||
}};
|
||||
|
||||
if (renderTimer) {
|
||||
wl_event_source_remove(renderTimer);
|
||||
@@ -281,9 +291,6 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||
|
||||
Debug::log(LOG, "Removed monitor {}!", szName);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
||||
EMIT_HOOK_EVENT("monitorRemoved", this);
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
||||
g_pCompositor->enterUnsafeState();
|
||||
@@ -488,7 +495,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(self.lock());
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
@@ -771,12 +778,9 @@ Vector2D CMonitor::middle() {
|
||||
}
|
||||
|
||||
void CMonitor::updateMatrix() {
|
||||
matrixIdentity(projMatrix.data());
|
||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||
matrixTranslate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0);
|
||||
matrixTransform(projMatrix.data(), wlTransformToHyprutils(transform));
|
||||
matrixTranslate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||
}
|
||||
projMatrix = Mat3x3::identity();
|
||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL)
|
||||
projMatrix.translate(vecPixelSize / 2.0).transform(wlTransformToHyprutils(transform)).translate(-vecTransformedSize / 2.0);
|
||||
}
|
||||
|
||||
WORKSPACEID CMonitor::activeWorkspaceID() {
|
||||
@@ -791,20 +795,22 @@ CBox CMonitor::logicalBox() {
|
||||
return {vecPosition, vecSize};
|
||||
}
|
||||
|
||||
static void onDoneSource(void* data) {
|
||||
auto pMonitor = (CMonitor*)data;
|
||||
|
||||
if (!PROTO::outputs.contains(pMonitor->szName))
|
||||
return;
|
||||
|
||||
PROTO::outputs.at(pMonitor->szName)->sendDone();
|
||||
}
|
||||
|
||||
void CMonitor::scheduleDone() {
|
||||
if (doneSource)
|
||||
if (doneScheduled)
|
||||
return;
|
||||
|
||||
doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this);
|
||||
doneScheduled = true;
|
||||
|
||||
g_pEventLoopManager->doLater([M = self] {
|
||||
if (!M) // if M is gone, we got destroyed, doesn't matter.
|
||||
return;
|
||||
|
||||
if (!PROTO::outputs.contains(M->szName))
|
||||
return;
|
||||
|
||||
PROTO::outputs.at(M->szName)->sendDone();
|
||||
M->doneScheduled = false;
|
||||
});
|
||||
}
|
||||
|
||||
bool CMonitor::attemptDirectScanout() {
|
||||
|
@@ -96,7 +96,7 @@ class CMonitor {
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
Mat3x3 projMatrix;
|
||||
std::optional<Vector2D> forceSize;
|
||||
SP<Aquamarine::SOutputMode> currentMode;
|
||||
SP<Aquamarine::CSwapchain> cursorSwapchain;
|
||||
@@ -190,10 +190,10 @@ class CMonitor {
|
||||
}
|
||||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
WORKSPACEID findAvailableDefaultWS();
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
WORKSPACEID findAvailableDefaultWS();
|
||||
|
||||
wl_event_source* doneSource = nullptr;
|
||||
bool doneScheduled = false;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener frame;
|
||||
|
@@ -1,10 +0,0 @@
|
||||
#include "ScopeGuard.hpp"
|
||||
|
||||
CScopeGuard::CScopeGuard(const std::function<void()>& fn_) : fn(fn_) {
|
||||
;
|
||||
}
|
||||
|
||||
CScopeGuard::~CScopeGuard() {
|
||||
if (fn)
|
||||
fn();
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
#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 <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Systemd {
|
||||
|
@@ -1,62 +0,0 @@
|
||||
#include "WLListener.hpp"
|
||||
#include "MiscFunctions.hpp"
|
||||
#include <string>
|
||||
#include "../debug/Log.hpp"
|
||||
#include "Watchdog.hpp"
|
||||
|
||||
void handleWrapped(wl_listener* listener, void* data) {
|
||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->startWatching();
|
||||
|
||||
try {
|
||||
pWrap->m_pSelf->emit(data);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} threw or timed out and was killed by Watchdog!!! This is bad. what(): {}", (uintptr_t)listener, e.what()); }
|
||||
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->endWatching();
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> const& callback, void* pOwner) {
|
||||
initCallback(pSignal, callback, pOwner);
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener() {
|
||||
m_swWrapper.m_pSelf = this;
|
||||
m_swWrapper.m_sListener.notify = &handleWrapped;
|
||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
|
||||
CHyprWLListener::~CHyprWLListener() {
|
||||
removeCallback();
|
||||
}
|
||||
|
||||
void CHyprWLListener::removeCallback() {
|
||||
if (isConnected()) {
|
||||
Debug::log(LOG, "Callback {:x} -> {:x}, {} removed.", (uintptr_t)&m_pCallback, (uintptr_t)&m_pOwner, m_szAuthor);
|
||||
wl_list_remove(&m_swWrapper.m_sListener.link);
|
||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
}
|
||||
|
||||
bool CHyprWLListener::isConnected() {
|
||||
return !wl_list_empty(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
|
||||
void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*, void*)> const& callback, void* pOwner, std::string author) {
|
||||
if (isConnected()) {
|
||||
Debug::log(ERR, "Tried to connect a listener twice?!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pOwner = pOwner;
|
||||
m_pCallback = callback;
|
||||
m_szAuthor = author;
|
||||
|
||||
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
|
||||
}
|
||||
|
||||
void CHyprWLListener::emit(void* data) {
|
||||
m_pCallback(m_pOwner, data);
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <wayland-server.h>
|
||||
|
||||
class CHyprWLListener {
|
||||
public:
|
||||
CHyprWLListener(wl_signal*, std::function<void(void*, void*)> const&, void* owner);
|
||||
CHyprWLListener();
|
||||
~CHyprWLListener();
|
||||
|
||||
CHyprWLListener(const CHyprWLListener&) = delete;
|
||||
CHyprWLListener(CHyprWLListener&&) = delete;
|
||||
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
|
||||
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
|
||||
|
||||
void initCallback(wl_signal*, std::function<void(void*, void*)> const&, void* owner, std::string author = "");
|
||||
|
||||
void removeCallback();
|
||||
|
||||
bool isConnected();
|
||||
|
||||
struct SWrapper {
|
||||
wl_listener m_sListener;
|
||||
CHyprWLListener* m_pSelf;
|
||||
};
|
||||
|
||||
void emit(void*);
|
||||
|
||||
private:
|
||||
SWrapper m_swWrapper;
|
||||
|
||||
void* m_pOwner = nullptr;
|
||||
|
||||
std::function<void(void*, void*)> m_pCallback = nullptr;
|
||||
|
||||
std::string m_szAuthor = "";
|
||||
};
|
@@ -1,6 +1,4 @@
|
||||
#include "Math.hpp"
|
||||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
|
||||
Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) {
|
||||
switch (t) {
|
||||
@@ -17,124 +15,6 @@ Hyprutils::Math::eTransform wlTransformToHyprutils(wl_output_transform t) {
|
||||
return Hyprutils::Math::eTransform::HYPRUTILS_TRANSFORM_NORMAL;
|
||||
}
|
||||
|
||||
void matrixIdentity(float mat[9]) {
|
||||
static const float identity[9] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
memcpy(mat, identity, sizeof(identity));
|
||||
}
|
||||
|
||||
void matrixMultiply(float mat[9], const float a[9], const float b[9]) {
|
||||
float product[9];
|
||||
|
||||
product[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
|
||||
product[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
|
||||
product[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
|
||||
|
||||
product[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6];
|
||||
product[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7];
|
||||
product[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8];
|
||||
|
||||
product[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6];
|
||||
product[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7];
|
||||
product[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
|
||||
|
||||
memcpy(mat, product, sizeof(product));
|
||||
}
|
||||
|
||||
void matrixTranspose(float mat[9], const float a[9]) {
|
||||
float transposition[9] = {
|
||||
a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8],
|
||||
};
|
||||
memcpy(mat, transposition, sizeof(transposition));
|
||||
}
|
||||
|
||||
void matrixTranslate(float mat[9], float x, float y) {
|
||||
float translate[9] = {
|
||||
1.0f, 0.0f, x, 0.0f, 1.0f, y, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
matrixMultiply(mat, mat, translate);
|
||||
}
|
||||
|
||||
void matrixScale(float mat[9], float x, float y) {
|
||||
float scale[9] = {
|
||||
x, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
matrixMultiply(mat, mat, scale);
|
||||
}
|
||||
|
||||
void matrixRotate(float mat[9], float rad) {
|
||||
float rotate[9] = {
|
||||
cos(rad), -sin(rad), 0.0f, sin(rad), cos(rad), 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
matrixMultiply(mat, mat, rotate);
|
||||
}
|
||||
|
||||
const std::unordered_map<eTransform, std::array<float, 9>>& getTransforms() {
|
||||
static std::unordered_map<eTransform, std::array<float, 9>> transforms = {
|
||||
{HYPRUTILS_TRANSFORM_NORMAL, {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_90, {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_180, {-1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_270, {0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED, {-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_90, {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_180, {1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{HYPRUTILS_TRANSFORM_FLIPPED_270, {0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
};
|
||||
return transforms;
|
||||
}
|
||||
|
||||
void matrixTransform(float mat[9], eTransform transform) {
|
||||
matrixMultiply(mat, mat, getTransforms().at(transform).data());
|
||||
}
|
||||
|
||||
void matrixProjection(float mat[9], int width, int height, eTransform transform) {
|
||||
memset(mat, 0, sizeof(*mat) * 9);
|
||||
|
||||
const float* t = getTransforms().at(transform).data();
|
||||
float x = 2.0f / width;
|
||||
float y = 2.0f / height;
|
||||
|
||||
// Rotation + reflection
|
||||
mat[0] = x * t[0];
|
||||
mat[1] = x * t[1];
|
||||
mat[3] = y * -t[3];
|
||||
mat[4] = y * -t[4];
|
||||
|
||||
// Translation
|
||||
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
|
||||
|
||||
// Identity
|
||||
mat[8] = 1.0f;
|
||||
}
|
||||
|
||||
void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]) {
|
||||
double x = box.x;
|
||||
double y = box.y;
|
||||
double width = box.width;
|
||||
double height = box.height;
|
||||
|
||||
matrixIdentity(mat);
|
||||
matrixTranslate(mat, x, y);
|
||||
|
||||
if (rotation != 0) {
|
||||
matrixTranslate(mat, width / 2, height / 2);
|
||||
matrixRotate(mat, rotation);
|
||||
matrixTranslate(mat, -width / 2, -height / 2);
|
||||
}
|
||||
|
||||
matrixScale(mat, width, height);
|
||||
|
||||
if (transform != HYPRUTILS_TRANSFORM_NORMAL) {
|
||||
matrixTranslate(mat, 0.5, 0.5);
|
||||
matrixTransform(mat, transform);
|
||||
matrixTranslate(mat, -0.5, -0.5);
|
||||
}
|
||||
|
||||
matrixMultiply(mat, projection, mat);
|
||||
}
|
||||
|
||||
wl_output_transform invertTransform(wl_output_transform tr) {
|
||||
if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED))
|
||||
tr = (wl_output_transform)(tr ^ (int)WL_OUTPUT_TRANSFORM_180);
|
||||
|
@@ -4,17 +4,9 @@
|
||||
|
||||
// includes box and vector as well
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Mat3x3.hpp>
|
||||
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
eTransform wlTransformToHyprutils(wl_output_transform t);
|
||||
void projectBox(float mat[9], CBox& box, eTransform transform, float rotation, const float projection[9]);
|
||||
void matrixProjection(float mat[9], int width, int height, eTransform transform);
|
||||
void matrixTransform(float mat[9], eTransform transform);
|
||||
void matrixRotate(float mat[9], float rad);
|
||||
void matrixScale(float mat[9], float x, float y);
|
||||
void matrixTranslate(float mat[9], float x, float y);
|
||||
void matrixTranspose(float mat[9], const float a[9]);
|
||||
void matrixMultiply(float mat[9], const float a[9], const float b[9]);
|
||||
void matrixIdentity(float mat[9]);
|
||||
wl_output_transform invertTransform(wl_output_transform tr);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "DwindleLayout.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||
if (children[0]) {
|
||||
@@ -340,26 +340,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow.lock()) && !m_vOverrideFocalPoint) { // we are not moving window
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
||||
(*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's not, get the node under our cursor
|
||||
// get the node under our cursor
|
||||
|
||||
m_lDwindleNodesData.push_back(SDwindleNodeData());
|
||||
const auto NEWPARENT = &m_lDwindleNodesData.back();
|
||||
@@ -459,6 +440,12 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||
}
|
||||
}
|
||||
|
||||
// split in favor of a specific window
|
||||
const auto first = NEWPARENT->children[0];
|
||||
static auto PSPLITBIAS = CConfigValue<Hyprlang::INT>("dwindle:split_bias");
|
||||
if ((*PSPLITBIAS == 1 && first == PNODE) || (*PSPLITBIAS == 2 && first == OPENINGON))
|
||||
NEWPARENT->splitRatio = 2.f - NEWPARENT->splitRatio;
|
||||
|
||||
// and update the previous parent if it exists
|
||||
if (OPENINGON->pParent) {
|
||||
if (OPENINGON->pParent->children[0] == OPENINGON) {
|
||||
@@ -992,6 +979,10 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
||||
toggleSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "swapsplit") {
|
||||
swapSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "movetoroot") {
|
||||
const auto WINDOW = ARGS[1].empty() ? header.pWindow : g_pCompositor->getWindowByRegex(ARGS[1]);
|
||||
const auto STABLE = ARGS[2].empty() || ARGS[2] != "unstable";
|
||||
moveToRoot(WINDOW, STABLE);
|
||||
} else if (ARGS[0] == "preselect") {
|
||||
std::string direction = ARGS[1];
|
||||
|
||||
@@ -1059,6 +1050,44 @@ void CHyprDwindleLayout::swapSplit(PHLWINDOW pWindow) {
|
||||
PNODE->pParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
// goal: maximize the chosen window within current dwindle layout
|
||||
// impl: swap the selected window with the other sub-tree below root
|
||||
void CHyprDwindleLayout::moveToRoot(PHLWINDOW pWindow, bool stable) {
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE || !PNODE->pParent)
|
||||
return;
|
||||
|
||||
if (pWindow->isFullscreen())
|
||||
return;
|
||||
|
||||
// already at root
|
||||
if (!PNODE->pParent->pParent)
|
||||
return;
|
||||
|
||||
auto& pNode = PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[0] : PNODE->pParent->children[1];
|
||||
|
||||
// instead of [getMasterNodeOnWorkspace], we walk back to root since we need
|
||||
// to know which children of root is our ancestor
|
||||
auto pAncestor = PNODE, pRoot = PNODE->pParent;
|
||||
while (pRoot->pParent) {
|
||||
pAncestor = pRoot;
|
||||
pRoot = pRoot->pParent;
|
||||
}
|
||||
|
||||
auto& pSwap = pRoot->children[0] == pAncestor ? pRoot->children[1] : pRoot->children[0];
|
||||
std::swap(pNode, pSwap);
|
||||
std::swap(pNode->pParent, pSwap->pParent);
|
||||
|
||||
// [stable] in that the focused window occupies same side of screen
|
||||
if (stable)
|
||||
std::swap(pRoot->children[0], pRoot->children[1]);
|
||||
|
||||
// if the workspace is visible, recalculate layout
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_pWorkspace))
|
||||
pRoot->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) {
|
||||
const auto PNODE = getNodeFromWindow(from);
|
||||
|
||||
|
@@ -87,6 +87,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||
|
||||
void toggleSplit(PHLWINDOW);
|
||||
void swapSplit(PHLWINDOW);
|
||||
void moveToRoot(PHLWINDOW, bool stable = true);
|
||||
|
||||
eDirection overrideDirection = DIRECTION_DEFAULT;
|
||||
|
||||
|
@@ -9,23 +9,25 @@
|
||||
#include "../xwayland/XSurface.hpp"
|
||||
|
||||
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
CBox desiredGeometry = {};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
||||
} else
|
||||
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
|
||||
pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize;
|
||||
|
||||
bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow);
|
||||
if (autoGrouped)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFloating)
|
||||
onWindowCreatedFloating(pWindow);
|
||||
} else {
|
||||
CBox desiredGeometry = {};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
||||
} else {
|
||||
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
}
|
||||
|
||||
pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize;
|
||||
|
||||
else
|
||||
onWindowCreatedTiling(pWindow, direction);
|
||||
}
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) {
|
||||
@@ -178,6 +180,48 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) {
|
||||
static auto PAUTOGROUP = CConfigValue<Hyprlang::INT>("group:auto_group");
|
||||
PHLWINDOW OPENINGON = g_pCompositor->m_pLastWindow.lock() && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ?
|
||||
g_pCompositor->m_pLastWindow.lock() :
|
||||
g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID());
|
||||
|
||||
if ((*PAUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group.
|
||||
&& OPENINGON // check if OPENINGON exists.
|
||||
&& OPENINGON != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group.
|
||||
&& OPENINGON->m_sGroupData.pNextWindow.lock() // check if OPENINGON is a group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON) // check if the new window can be grouped into OPENINGON
|
||||
&& !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated.
|
||||
|
||||
switch (pWindow->m_bIsFloating) {
|
||||
case false:
|
||||
if (OPENINGON->m_bIsFloating)
|
||||
pWindow->m_bIsFloating = true;
|
||||
break;
|
||||
|
||||
case true:
|
||||
if (!OPENINGON->m_bIsFloating)
|
||||
pWindow->m_bIsFloating = false;
|
||||
break;
|
||||
}
|
||||
|
||||
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
||||
(*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void IHyprLayout::onBeginDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock();
|
||||
|
||||
@@ -509,10 +553,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
||||
|
||||
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
||||
|
||||
// move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back.
|
||||
// move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back.
|
||||
pWindow->m_vPosition = Vector2D(-999999, -999999);
|
||||
|
||||
onWindowCreatedTiling(pWindow);
|
||||
onWindowCreated(pWindow);
|
||||
|
||||
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
|
||||
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
|
||||
|
@@ -47,6 +47,7 @@ class IHyprLayout {
|
||||
virtual void onWindowCreated(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT);
|
||||
virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT) = 0;
|
||||
virtual void onWindowCreatedFloating(PHLWINDOW);
|
||||
virtual bool onWindowCreatedAutoGroup(PHLWINDOW);
|
||||
|
||||
/*
|
||||
Return tiled status
|
||||
|
@@ -116,26 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow.lock())) {
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
||||
(*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pWindow->applyGroupRules();
|
||||
|
||||
static auto PDROPATCURSOR = CConfigValue<Hyprlang::INT>("master:drop_at_cursor");
|
||||
|
28
src/main.cpp
28
src/main.cpp
@@ -3,6 +3,10 @@
|
||||
#include "Compositor.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "init/initHelpers.hpp"
|
||||
#include "debug/HyprCtl.hpp"
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
@@ -20,6 +24,7 @@ void help() {
|
||||
std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n";
|
||||
std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n";
|
||||
std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n";
|
||||
std::cout << " --version -v - Print this binary's version\n";
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@@ -109,6 +114,29 @@ int main(int argc, char** argv) {
|
||||
} else if (it->compare("-h") == 0 || it->compare("--help") == 0) {
|
||||
help();
|
||||
|
||||
return 0;
|
||||
} else if (it->compare("-v") == 0 || it->compare("--version") == 0) {
|
||||
auto commitMsg = trim(GIT_COMMIT_MESSAGE);
|
||||
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
|
||||
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" +
|
||||
"\n\nflags: (if any)\n";
|
||||
|
||||
#ifdef LEGACY_RENDERER
|
||||
result += "legacyrenderer\n";
|
||||
#endif
|
||||
#ifndef ISDEBUG
|
||||
result += "debug\n";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
result += "no xwayland\n";
|
||||
#endif
|
||||
|
||||
std::cout << result;
|
||||
return 0;
|
||||
} else if (it->compare("--systeminfo") == 0) {
|
||||
const auto SYSINFO = systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "");
|
||||
std::cout << SYSINFO << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n";
|
||||
|
@@ -376,7 +376,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
|
||||
const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput
|
||||
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbState : m_pXKBTranslationState, KEYCODE);
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE);
|
||||
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE);
|
||||
|
||||
if (handleInternalKeybinds(internalKeysym))
|
||||
@@ -594,6 +594,10 @@ eMultiKeyCase CKeybindManager::mkBindMatches(const SKeybind keybind) {
|
||||
return mkKeysymSetMatches(keybind.sMkKeys, m_sMkKeys);
|
||||
}
|
||||
|
||||
std::string CKeybindManager::getCurrentSubmap() {
|
||||
return m_szCurrentSelectedSubmap;
|
||||
}
|
||||
|
||||
SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) {
|
||||
static auto PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing");
|
||||
bool found = false;
|
||||
@@ -1939,7 +1943,7 @@ SDispatchResult CKeybindManager::forceRendererReload(std::string args) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(*m);
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
@@ -2399,9 +2403,7 @@ SDispatchResult CKeybindManager::dpms(std::string arg) {
|
||||
bool enable = arg.starts_with("on");
|
||||
std::string port = "";
|
||||
|
||||
if (arg.starts_with("toggle"))
|
||||
enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off
|
||||
|
||||
bool isToggle = arg.starts_with("toggle");
|
||||
if (arg.find_first_of(' ') != std::string::npos)
|
||||
port = arg.substr(arg.find_first_of(' ') + 1);
|
||||
|
||||
@@ -2410,6 +2412,9 @@ SDispatchResult CKeybindManager::dpms(std::string arg) {
|
||||
if (!port.empty() && m->szName != port)
|
||||
continue;
|
||||
|
||||
if (isToggle)
|
||||
enable = !m->dpmsStatus;
|
||||
|
||||
m->output->state->resetExplicitFences();
|
||||
m->output->state->setEnabled(enable);
|
||||
|
||||
@@ -2730,7 +2735,7 @@ SDispatchResult CKeybindManager::moveIntoGroup(std::string args) {
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
|
||||
|
||||
if (!PWINDOW || PWINDOW->m_bIsFloating || PWINDOW->m_sGroupData.deny)
|
||||
if (!PWINDOW || PWINDOW->m_sGroupData.deny)
|
||||
return {};
|
||||
|
||||
auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
|
||||
|
@@ -96,6 +96,7 @@ class CKeybindManager {
|
||||
uint32_t keycodeToModifier(xkb_keycode_t);
|
||||
void clearKeybinds();
|
||||
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0);
|
||||
std::string getCurrentSubmap();
|
||||
|
||||
std::unordered_map<std::string, std::function<SDispatchResult(std::string)>> m_mDispatchers;
|
||||
|
||||
@@ -221,6 +222,7 @@ class CKeybindManager {
|
||||
friend class CInputManager;
|
||||
friend class CConfigManager;
|
||||
friend class CWorkspace;
|
||||
friend class CPointerManager;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
||||
|
@@ -17,16 +17,8 @@ CPointerManager::CPointerManager() {
|
||||
|
||||
onMonitorLayoutChange();
|
||||
|
||||
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.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.destroy.registerStaticListener(
|
||||
[this](void* owner, std::any data) {
|
||||
if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown)
|
||||
@@ -44,38 +36,6 @@ 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 const& state : monitorStates)
|
||||
state->softwareLocks++;
|
||||
@@ -246,9 +206,8 @@ void CPointerManager::recheckEnteredOutputs() {
|
||||
|
||||
// if we are using hw cursors, prevent
|
||||
// the cursor from being stuck at the last point.
|
||||
// if we are leaving it, move it to narnia.
|
||||
if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
|
||||
s->monitor->output->moveCursor({-1337, -420});
|
||||
setHWCursorBuffer(s, nullptr);
|
||||
|
||||
if (!currentCursorImage.surface)
|
||||
continue;
|
||||
@@ -307,6 +266,8 @@ void CPointerManager::resetCursorImage(bool apply) {
|
||||
void CPointerManager::updateCursorBackend() {
|
||||
static auto PNOHW = CConfigValue<Hyprlang::INT>("cursor:no_hardware_cursors");
|
||||
|
||||
const auto CURSORBOX = getCursorBoxGlobal();
|
||||
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
auto state = stateFor(m);
|
||||
|
||||
@@ -315,6 +276,15 @@ void CPointerManager::updateCursorBackend() {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty();
|
||||
|
||||
if (!CROSSES) {
|
||||
if (state->cursorFrontBuffer)
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state->softwareLocks > 0 || *PNOHW || !attemptHardwareCursor(state)) {
|
||||
Debug::log(TRACE, "Output {} rejected hardware cursors, falling back to sw", m->szName);
|
||||
state->box = getCursorBoxLogicalForMonitor(state->monitor.lock());
|
||||
@@ -335,17 +305,34 @@ void CPointerManager::onCursorMoved() {
|
||||
if (!hasCursor())
|
||||
return;
|
||||
|
||||
const auto CURSORBOX = getCursorBoxGlobal();
|
||||
bool recalc = false;
|
||||
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
auto state = stateFor(m);
|
||||
|
||||
state->box = getCursorBoxLogicalForMonitor(state->monitor.lock());
|
||||
|
||||
auto CROSSES = !m->logicalBox().intersection(CURSORBOX).empty();
|
||||
|
||||
if (!CROSSES && state->cursorFrontBuffer) {
|
||||
Debug::log(TRACE, "onCursorMoved for output {}: cursor left the viewport, removing it from the backend", m->szName);
|
||||
setHWCursorBuffer(state, nullptr);
|
||||
continue;
|
||||
} else if (CROSSES && !state->cursorFrontBuffer) {
|
||||
Debug::log(TRACE, "onCursorMoved for output {}: cursor entered the output, but no front buffer, forcing recalc", m->szName);
|
||||
recalc = true;
|
||||
}
|
||||
|
||||
if (state->hardwareFailed || !state->entered)
|
||||
continue;
|
||||
|
||||
const auto CURSORPOS = getCursorPosForMonitor(m);
|
||||
m->output->moveCursor(CURSORPOS);
|
||||
}
|
||||
|
||||
if (recalc)
|
||||
updateCursorBackend();
|
||||
}
|
||||
|
||||
bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) {
|
||||
@@ -670,12 +657,12 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) {
|
||||
}
|
||||
|
||||
void CPointerManager::damageIfSoftware() {
|
||||
auto b = getCursorBoxGlobal();
|
||||
auto b = getCursorBoxGlobal().expand(4);
|
||||
|
||||
static auto PNOHW = CConfigValue<Hyprlang::INT>("cursor:no_hardware_cursors");
|
||||
|
||||
for (auto const& mw : monitorStates) {
|
||||
if (mw->monitor.expired())
|
||||
if (mw->monitor.expired() || !mw->monitor->output)
|
||||
continue;
|
||||
|
||||
if ((mw->softwareLocks > 0 || mw->hardwareFailed || *PNOHW) && b.overlaps({mw->monitor->vecPosition, mw->monitor->vecSize})) {
|
||||
@@ -789,7 +776,7 @@ void CPointerManager::warpAbsolute(Vector2D abs, SP<IHID> dev) {
|
||||
void CPointerManager::onMonitorLayoutChange() {
|
||||
currentMonitorLayout.monitorBoxes.clear();
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->isMirror() || !m->m_bEnabled)
|
||||
if (m->isMirror() || !m->m_bEnabled || !m->output)
|
||||
continue;
|
||||
|
||||
currentMonitorLayout.monitorBoxes.emplace_back(CBox{m->vecPosition, m->vecSize});
|
||||
@@ -821,6 +808,9 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
static auto PMOUSEDPMS = CConfigValue<Hyprlang::INT>("misc:mouse_move_enables_dpms");
|
||||
|
||||
//
|
||||
auto listener = pointerListeners.emplace_back(makeShared<SPointerListener>());
|
||||
|
||||
listener->pointer = pointer;
|
||||
@@ -836,6 +826,9 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
g_pInputManager->onMouseMoved(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->motionAbsolute = pointer->pointerEvents.motionAbsolute.registerListener([this] (std::any e) {
|
||||
@@ -844,6 +837,9 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
g_pInputManager->onMouseWarp(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->button = pointer->pointerEvents.button.registerListener([this] (std::any e) {
|
||||
@@ -872,6 +868,9 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
g_pInputManager->onSwipeBegin(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->swipeEnd = pointer->pointerEvents.swipeEnd.registerListener([this] (std::any e) {
|
||||
@@ -896,6 +895,9 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
|
||||
PROTO::pointerGestures->pinchBegin(E.timeMs, E.fingers);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->pinchEnd = pointer->pointerEvents.pinchEnd.registerListener([this] (std::any e) {
|
||||
@@ -938,6 +940,9 @@ void CPointerManager::attachTouch(SP<ITouch> touch) {
|
||||
if (!touch)
|
||||
return;
|
||||
|
||||
static auto PMOUSEDPMS = CConfigValue<Hyprlang::INT>("misc:mouse_move_enables_dpms");
|
||||
|
||||
//
|
||||
auto listener = touchListeners.emplace_back(makeShared<STouchListener>());
|
||||
|
||||
listener->touch = touch;
|
||||
@@ -953,6 +958,9 @@ void CPointerManager::attachTouch(SP<ITouch> touch) {
|
||||
g_pInputManager->onTouchDown(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->up = touch->touchEvents.up.registerListener([this] (std::any e) {
|
||||
@@ -987,6 +995,9 @@ void CPointerManager::attachTablet(SP<CTablet> tablet) {
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
static auto PMOUSEDPMS = CConfigValue<Hyprlang::INT>("misc:mouse_move_enables_dpms");
|
||||
|
||||
//
|
||||
auto listener = tabletListeners.emplace_back(makeShared<STabletListener>());
|
||||
|
||||
listener->tablet = tablet;
|
||||
@@ -1002,6 +1013,9 @@ void CPointerManager::attachTablet(SP<CTablet> tablet) {
|
||||
g_pInputManager->onTabletAxis(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->proximity = tablet->tabletEvents.proximity.registerListener([this] (std::any e) {
|
||||
@@ -1018,6 +1032,9 @@ void CPointerManager::attachTablet(SP<CTablet> tablet) {
|
||||
g_pInputManager->onTabletTip(E);
|
||||
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS)
|
||||
g_pKeybindManager->dpms("on");
|
||||
});
|
||||
|
||||
listener->button = tablet->tabletEvents.button.registerListener([this] (std::any e) {
|
||||
|
@@ -26,7 +26,6 @@ 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);
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "../protocols/TextInputV1.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../protocols/XDGDialog.hpp"
|
||||
#include "../protocols/SinglePixel.hpp"
|
||||
|
||||
#include "../protocols/core/Seat.hpp"
|
||||
#include "../protocols/core/DataDevice.hpp"
|
||||
@@ -85,7 +86,8 @@ CProtocolManager::CProtocolManager() {
|
||||
|
||||
// ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after
|
||||
// this event is emitted iirc.
|
||||
if (M->isMirror())
|
||||
// also ignore the fallback
|
||||
if (M->isMirror() || M == g_pCompositor->m_pUnsafeOutput)
|
||||
return;
|
||||
|
||||
if (PROTO::outputs.contains(M->szName))
|
||||
@@ -152,6 +154,7 @@ CProtocolManager::CProtocolManager() {
|
||||
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");
|
||||
PROTO::xdgDialog = std::make_unique<CXDGDialogProtocol>(&xdg_dialog_v1_interface, 1, "XDGDialog");
|
||||
PROTO::singlePixel = std::make_unique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
|
||||
|
||||
for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) {
|
||||
if (b->type() != Aquamarine::AQ_BACKEND_DRM)
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include "../helpers/WLListener.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
#include "../helpers/math/Math.hpp"
|
||||
|
@@ -46,11 +46,8 @@ void CHyprXWaylandManager::activateSurface(SP<CWLSurfaceResource> pSurface, bool
|
||||
PWINDOW->m_pXWaylandSurface->restackToTop();
|
||||
}
|
||||
PWINDOW->m_pXWaylandSurface->activate(activate);
|
||||
} else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface) {
|
||||
} else if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface)
|
||||
PWINDOW->m_pXDGSurface->toplevel->setActive(activate);
|
||||
if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11)
|
||||
activateSurface(g_pCompositor->m_pLastFocus.lock(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
|
||||
|
@@ -50,6 +50,10 @@ void CEventLoopManager::enterLoop() {
|
||||
m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get()));
|
||||
}
|
||||
|
||||
// if we have a session, dispatch it to get the pending input devices
|
||||
if (g_pCompositor->m_pAqBackend->hasSession())
|
||||
g_pCompositor->m_pAqBackend->session->dispatchPendingEventsAsync();
|
||||
|
||||
wl_display_run(m_sWayland.display);
|
||||
|
||||
Debug::log(LOG, "Kicked off the event loop! :(");
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "../../managers/PointerManager.hpp"
|
||||
#include "../../managers/SeatManager.hpp"
|
||||
#include "../../managers/KeybindManager.hpp"
|
||||
|
||||
#include <aquamarine/input/Input.hpp>
|
||||
|
||||
@@ -135,7 +136,6 @@ void CInputManager::sendMotionEventsToFocused() {
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
||||
static auto PMOUSEREFOCUS = CConfigValue<Hyprlang::INT>("input:mouse_refocus");
|
||||
static auto PMOUSEDPMS = CConfigValue<Hyprlang::INT>("misc:mouse_move_enables_dpms");
|
||||
static auto PFOLLOWONDND = CConfigValue<Hyprlang::INT>("misc:always_follow_on_dnd");
|
||||
static auto PFLOATBEHAVIOR = CConfigValue<Hyprlang::INT>("input:float_switch_override_focus");
|
||||
static auto PMOUSEFOCUSMON = CConfigValue<Hyprlang::INT>("misc:mouse_move_focuses_monitor");
|
||||
@@ -157,11 +157,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown || g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->m_bDPMSStateON && *PMOUSEDPMS) {
|
||||
// enable dpms
|
||||
g_pKeybindManager->dpms("on");
|
||||
}
|
||||
|
||||
Vector2D mouseCoords = getMouseCoordsInternal();
|
||||
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
|
||||
|
||||
@@ -854,6 +849,8 @@ void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keyboard)
|
||||
}
|
||||
|
||||
void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
||||
static auto PDPMS = CConfigValue<Hyprlang::INT>("misc:key_press_enables_dpms");
|
||||
|
||||
m_vHIDs.push_back(keeb);
|
||||
|
||||
try {
|
||||
@@ -882,6 +879,9 @@ void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
||||
|
||||
if (PKEEB->enabled)
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON)
|
||||
g_pKeybindManager->dpms("on");
|
||||
},
|
||||
keeb.get());
|
||||
|
||||
@@ -893,6 +893,9 @@ void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
||||
|
||||
if (PKEEB->enabled)
|
||||
PROTO::idle->onActivity();
|
||||
|
||||
if (PKEEB->enabled && *PDPMS && !g_pCompositor->m_bDPMSStateON)
|
||||
g_pKeybindManager->dpms("on");
|
||||
},
|
||||
keeb.get());
|
||||
|
||||
@@ -1284,12 +1287,6 @@ void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", event}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP);
|
||||
|
||||
static auto PDPMS = CConfigValue<Hyprlang::INT>("misc:key_press_enables_dpms");
|
||||
if (*PDPMS && !g_pCompositor->m_bDPMSStateON) {
|
||||
// enable dpms
|
||||
g_pKeybindManager->dpms("on");
|
||||
}
|
||||
|
||||
bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard);
|
||||
|
||||
auto e = std::any_cast<IKeyboard::SKeyEvent>(event);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../helpers/WLListener.hpp"
|
||||
#include "../../desktop/WLSurface.hpp"
|
||||
#include "../../macros.hpp"
|
||||
#include "../../helpers/math/Math.hpp"
|
||||
|
@@ -106,20 +106,22 @@ void CInputMethodRelay::updateAllPopups() {
|
||||
}
|
||||
}
|
||||
|
||||
void CInputMethodRelay::activateIME(CTextInput* pInput) {
|
||||
void CInputMethodRelay::activateIME(CTextInput* pInput, bool shouldCommit) {
|
||||
if (m_pIME.expired())
|
||||
return;
|
||||
|
||||
m_pIME->activate();
|
||||
commitIMEState(pInput);
|
||||
if (shouldCommit)
|
||||
commitIMEState(pInput);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::deactivateIME(CTextInput* pInput) {
|
||||
void CInputMethodRelay::deactivateIME(CTextInput* pInput, bool shouldCommit) {
|
||||
if (m_pIME.expired())
|
||||
return;
|
||||
|
||||
m_pIME->deactivate();
|
||||
commitIMEState(pInput);
|
||||
if (shouldCommit)
|
||||
commitIMEState(pInput);
|
||||
}
|
||||
|
||||
void CInputMethodRelay::commitIMEState(CTextInput* pInput) {
|
||||
|
@@ -21,8 +21,8 @@ class CInputMethodRelay {
|
||||
void onNewTextInput(WP<CTextInputV3> tiv3);
|
||||
void onNewTextInput(WP<CTextInputV1> pTIV1);
|
||||
|
||||
void activateIME(CTextInput* pInput);
|
||||
void deactivateIME(CTextInput* pInput);
|
||||
void activateIME(CTextInput* pInput, bool shouldCommit = true);
|
||||
void deactivateIME(CTextInput* pInput, bool shouldCommit = true);
|
||||
void commitIMEState(CTextInput* pInput);
|
||||
void removeTextInput(CTextInput* pInput);
|
||||
|
||||
|
@@ -22,6 +22,7 @@ void CTextInput::initCallbacks() {
|
||||
listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { onEnabled(); });
|
||||
listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); });
|
||||
listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); });
|
||||
listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); });
|
||||
listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) {
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
@@ -41,6 +42,7 @@ void CTextInput::initCallbacks() {
|
||||
});
|
||||
listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); });
|
||||
listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); });
|
||||
listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); });
|
||||
listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) {
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
@@ -93,13 +95,28 @@ void CTextInput::onDisabled() {
|
||||
g_pInputManager->m_sIMERelay.deactivateIME(this);
|
||||
}
|
||||
|
||||
void CTextInput::onReset() {
|
||||
if (g_pInputManager->m_sIMERelay.m_pIME.expired())
|
||||
return;
|
||||
|
||||
if (!focusedSurface())
|
||||
return;
|
||||
|
||||
const auto PFOCUSEDTI = g_pInputManager->m_sIMERelay.getFocusedTextInput();
|
||||
if (!PFOCUSEDTI || PFOCUSEDTI != this)
|
||||
return;
|
||||
|
||||
g_pInputManager->m_sIMERelay.deactivateIME(this, false);
|
||||
g_pInputManager->m_sIMERelay.activateIME(this);
|
||||
}
|
||||
|
||||
void CTextInput::onCommit() {
|
||||
if (g_pInputManager->m_sIMERelay.m_pIME.expired()) {
|
||||
// Debug::log(WARN, "Committing TextInput on no IME!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(isV3() ? pV3Input->current.enabled : pV1Input->active)) {
|
||||
if (!(isV3() ? pV3Input->current.enabled.value : pV1Input->active)) {
|
||||
Debug::log(WARN, "Disabled TextInput commit?");
|
||||
return;
|
||||
}
|
||||
@@ -128,8 +145,12 @@ void CTextInput::setFocusedSurface(SP<CWLSurfaceResource> pSurface) {
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
|
||||
if (isV3() && !pV3Input.expired() && pV3Input->current.enabled)
|
||||
pV3Input->current.enabled = false;
|
||||
if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) {
|
||||
pV3Input->pending.enabled.value = false;
|
||||
pV3Input->pending.enabled.isDisablePending = false;
|
||||
pV3Input->pending.enabled.isEnablePending = false;
|
||||
pV3Input->current.enabled.value = false;
|
||||
}
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.getFocusedTextInput())
|
||||
g_pInputManager->m_sIMERelay.deactivateIME(this);
|
||||
@@ -144,8 +165,12 @@ void CTextInput::setFocusedSurface(SP<CWLSurfaceResource> pSurface) {
|
||||
listeners.surfaceUnmap.reset();
|
||||
listeners.surfaceDestroy.reset();
|
||||
|
||||
if (isV3() && !pV3Input.expired() && pV3Input->current.enabled)
|
||||
pV3Input->current.enabled = false;
|
||||
if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) {
|
||||
pV3Input->pending.enabled.value = false;
|
||||
pV3Input->pending.enabled.isDisablePending = false;
|
||||
pV3Input->pending.enabled.isEnablePending = false;
|
||||
pV3Input->current.enabled.value = false;
|
||||
}
|
||||
|
||||
if (!g_pInputManager->m_sIMERelay.getFocusedTextInput())
|
||||
g_pInputManager->m_sIMERelay.deactivateIME(this);
|
||||
@@ -192,13 +217,9 @@ void CTextInput::leave() {
|
||||
enterLocks = 0;
|
||||
}
|
||||
|
||||
if (isV3()) {
|
||||
if (isV3())
|
||||
pV3Input->leave(focusedSurface());
|
||||
if (pV3Input->current.enabled) {
|
||||
pV3Input->current.enabled = false;
|
||||
onDisabled();
|
||||
}
|
||||
} else
|
||||
else
|
||||
pV1Input->leave();
|
||||
|
||||
setFocusedSurface(nullptr);
|
||||
@@ -264,7 +285,7 @@ void CTextInput::updateIMEState(SP<CInputMethodV2> ime) {
|
||||
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 {
|
||||
INPUT->preeditCursor(ime->current.preeditString.begin);
|
||||
INPUT->preeditCursor(0);
|
||||
INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT);
|
||||
INPUT->preeditString(pV1Input->serial, "", "");
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../helpers/WLListener.hpp"
|
||||
#include "../../macros.hpp"
|
||||
#include "../../helpers/math/Math.hpp"
|
||||
#include "../../helpers/signal/Signal.hpp"
|
||||
@@ -29,6 +28,7 @@ class CTextInput {
|
||||
void onEnabled(SP<CWLSurfaceResource> surfV1 = nullptr);
|
||||
void onDisabled();
|
||||
void onCommit();
|
||||
void onReset();
|
||||
|
||||
bool hasCursorRectangle();
|
||||
CBox cursorBox();
|
||||
@@ -47,6 +47,7 @@ class CTextInput {
|
||||
struct {
|
||||
CHyprSignalListener enable;
|
||||
CHyprSignalListener disable;
|
||||
CHyprSignalListener reset;
|
||||
CHyprSignalListener commit;
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener surfaceUnmap;
|
||||
|
@@ -1,12 +1,14 @@
|
||||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('Hyprland', src,
|
||||
executable(
|
||||
'Hyprland',
|
||||
src,
|
||||
link_args: '-rdynamic',
|
||||
cpp_pch: 'pch/pch.hpp',
|
||||
dependencies: [
|
||||
server_protos,
|
||||
dependency('aquamarine'),
|
||||
aquamarine,
|
||||
dependency('gbm'),
|
||||
dependency('xcursor'),
|
||||
dependency('wayland-server'),
|
||||
@@ -14,7 +16,7 @@ executable('Hyprland', src,
|
||||
dependency('cairo'),
|
||||
dependency('hyprcursor', version: '>=0.1.7'),
|
||||
dependency('hyprlang', version: '>= 0.3.2'),
|
||||
dependency('hyprutils', version: '>= 0.2.1'),
|
||||
dependency('hyprutils', version: '>= 0.2.3'),
|
||||
dependency('libdrm'),
|
||||
dependency('egl'),
|
||||
dependency('xkbcommon'),
|
||||
@@ -29,7 +31,12 @@ executable('Hyprland', src,
|
||||
backtrace_dep,
|
||||
epoll_dep,
|
||||
gio_dep,
|
||||
udis86,
|
||||
tracy,
|
||||
|
||||
# Try to find canihavesomecoffee's udis86 using pkgconfig
|
||||
# vmt/udis86 does not provide a .pc file and won't be detected this way
|
||||
# Falls back to using the subproject through udis86.wrap
|
||||
dependency('udis86'),
|
||||
|
||||
dependency('pixman-1'),
|
||||
dependency('gl', 'opengl'),
|
||||
@@ -38,5 +45,5 @@ executable('Hyprland', src,
|
||||
dependency('pangocairo'),
|
||||
dependency('uuid'),
|
||||
],
|
||||
install : true
|
||||
install: true,
|
||||
)
|
||||
|
@@ -53,9 +53,6 @@ class CFocusGrab {
|
||||
|
||||
bool m_bGrabActive = false;
|
||||
|
||||
DYNLISTENER(pointerGrabStarted);
|
||||
DYNLISTENER(keyboardGrabStarted);
|
||||
DYNLISTENER(touchGrabStarted);
|
||||
friend class CFocusGrabSurfaceState;
|
||||
};
|
||||
|
||||
|
@@ -19,7 +19,7 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
|
||||
|
||||
pMonitor = OUTPUTRES->monitor;
|
||||
|
||||
if (!pMonitor) {
|
||||
if (!pMonitor || !pMonitor->output) {
|
||||
LOGM(ERR, "No CMonitor");
|
||||
resource->sendFailed();
|
||||
return;
|
||||
|
@@ -307,10 +307,15 @@ COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resour
|
||||
|
||||
LOGM(LOG, "disableHead on {}", PMONITOR->szName);
|
||||
|
||||
PMONITOR->activeMonitorRule.disabled = true;
|
||||
if (!g_pConfigManager->replaceMonitorRule(PMONITOR->activeMonitorRule))
|
||||
g_pConfigManager->appendMonitorRule(PMONITOR->activeMonitorRule);
|
||||
g_pHyprRenderer->applyMonitorRule(PMONITOR, &PMONITOR->activeMonitorRule, false);
|
||||
SWlrManagerSavedOutputState newState;
|
||||
if (owner->monitorStates.contains(PMONITOR->szName))
|
||||
newState = owner->monitorStates.at(PMONITOR->szName);
|
||||
|
||||
newState.enabled = false;
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
|
||||
owner->monitorStates[PMONITOR->szName] = newState;
|
||||
});
|
||||
|
||||
resource->setTest([this](CZwlrOutputConfigurationV1* r) {
|
||||
@@ -346,6 +351,11 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
|
||||
|
||||
LOGM(LOG, "Applying configuration");
|
||||
|
||||
if (!owner) {
|
||||
LOGM(ERR, "applyTestConfiguration: no owner?!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto const& headw : heads) {
|
||||
auto head = headw.lock();
|
||||
|
||||
@@ -357,41 +367,59 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
|
||||
if (!PMONITOR)
|
||||
continue;
|
||||
|
||||
LOGM(LOG, "Applying config for monitor {}", PMONITOR->szName);
|
||||
LOGM(LOG, "Saving config for monitor {}", PMONITOR->szName);
|
||||
|
||||
SMonitorRule newRule = PMONITOR->activeMonitorRule;
|
||||
newRule.name = PMONITOR->szName;
|
||||
newRule.disabled = false;
|
||||
SWlrManagerSavedOutputState newState;
|
||||
if (owner->monitorStates.contains(PMONITOR->szName))
|
||||
newState = owner->monitorStates.at(PMONITOR->szName);
|
||||
|
||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
|
||||
newRule.resolution = head->state.mode->getMode()->pixelSize;
|
||||
newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F;
|
||||
} else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
||||
newRule.resolution = head->state.customMode.size;
|
||||
newRule.refreshRate = head->state.customMode.refresh / 1000.F;
|
||||
newState.enabled = true;
|
||||
|
||||
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
|
||||
newState.resolution = head->state.mode->getMode()->pixelSize;
|
||||
newState.refresh = head->state.mode->getMode()->refreshRate;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE;
|
||||
LOGM(LOG, " > Mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh);
|
||||
} else if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
||||
newState.resolution = head->state.customMode.size;
|
||||
newState.refresh = head->state.customMode.refresh;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
|
||||
LOGM(LOG, " > Custom mode: {:.0f}x{:.0f}@{}mHz", newState.resolution.x, newState.resolution.y, newState.refresh);
|
||||
}
|
||||
|
||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION)
|
||||
newRule.offset = head->state.position;
|
||||
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION) {
|
||||
newState.position = head->state.position;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_POSITION;
|
||||
LOGM(LOG, " > Position: {:.0f}, {:.0f}", head->state.position.x, head->state.position.y);
|
||||
}
|
||||
|
||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC)
|
||||
newRule.vrr = head->state.adaptiveSync;
|
||||
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
|
||||
newState.adaptiveSync = head->state.adaptiveSync;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
|
||||
LOGM(LOG, " > vrr: {}", newState.adaptiveSync);
|
||||
}
|
||||
|
||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE)
|
||||
newRule.scale = head->state.scale;
|
||||
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE) {
|
||||
newState.scale = head->state.scale;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_SCALE;
|
||||
LOGM(LOG, " > scale: {:.2f}", newState.scale);
|
||||
}
|
||||
|
||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM)
|
||||
newRule.transform = head->state.transform;
|
||||
if (head->state.committedProperties & eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM) {
|
||||
newState.transform = head->state.transform;
|
||||
newState.committedProperties |= eWlrOutputCommittedProperties::OUTPUT_HEAD_COMMITTED_TRANSFORM;
|
||||
LOGM(LOG, " > transform: {}", (uint8_t)newState.transform);
|
||||
}
|
||||
|
||||
// reset properties for next set.
|
||||
head->committedProperties = 0;
|
||||
head->state.committedProperties = 0;
|
||||
|
||||
if (!g_pConfigManager->replaceMonitorRule(newRule))
|
||||
g_pConfigManager->appendMonitorRule(newRule);
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
|
||||
owner->monitorStates[PMONITOR->szName] = newState;
|
||||
}
|
||||
|
||||
LOGM(LOG, "Applied configuration");
|
||||
LOGM(LOG, "Saved configuration");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -417,12 +445,12 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_MODE) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_MODE) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
|
||||
state.mode = MODE;
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate);
|
||||
@@ -434,17 +462,22 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0 || refresh <= 100) {
|
||||
if (w <= 0 || h <= 0 || refresh < 0) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_CUSTOM_MODE, "Invalid mode");
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
|
||||
if (refresh == 0) {
|
||||
LOGM(LOG, " | configHead for {}: refreshRate 0, using old refresh rate of {:.2f}Hz", pMonitor->szName, pMonitor->refreshRate);
|
||||
refresh = std::round(pMonitor->refreshRate * 1000.F);
|
||||
}
|
||||
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_CUSTOM_MODE;
|
||||
state.customMode = {{w, h}, (uint32_t)refresh};
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set custom mode to {}x{}@{}", pMonitor->szName, w, h, refresh);
|
||||
@@ -456,12 +489,12 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_POSITION) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION;
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_POSITION;
|
||||
state.position = {x, y};
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set pos to {}, {}", pMonitor->szName, x, y);
|
||||
@@ -473,7 +506,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
@@ -483,7 +516,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_TRANSFORM;
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_TRANSFORM;
|
||||
state.transform = (wl_output_transform)transform;
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set transform to {}", pMonitor->szName, transform);
|
||||
@@ -495,7 +528,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_SCALE) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
@@ -507,7 +540,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_SCALE;
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_SCALE;
|
||||
state.scale = scale;
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set scale to {:.2f}", pMonitor->szName, scale);
|
||||
@@ -519,7 +552,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
if (committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
|
||||
if (state.committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC) {
|
||||
resource->error(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_ALREADY_SET, "Property already set");
|
||||
return;
|
||||
}
|
||||
@@ -529,7 +562,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||
return;
|
||||
}
|
||||
|
||||
committedProperties |= OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
|
||||
state.committedProperties |= OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC;
|
||||
state.adaptiveSync = as;
|
||||
|
||||
LOGM(LOG, " | configHead for {}: set adaptiveSync to {}", pMonitor->szName, as);
|
||||
@@ -601,3 +634,14 @@ SP<COutputMode> COutputManagementProtocol::modeFromResource(wl_resource* r) {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SP<SWlrManagerSavedOutputState> COutputManagementProtocol::getOutputStateFor(SP<CMonitor> pMonitor) {
|
||||
for (auto const& m : m_vManagers) {
|
||||
if (!m->monitorStates.contains(pMonitor->szName))
|
||||
continue;
|
||||
|
||||
return makeShared<SWlrManagerSavedOutputState>(m->monitorStates.at(pMonitor->szName));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "wlr-output-management-unstable-v1.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
@@ -13,6 +14,43 @@ class CMonitor;
|
||||
class COutputHead;
|
||||
class COutputMode;
|
||||
|
||||
struct SMonitorRule;
|
||||
|
||||
enum eWlrOutputCommittedProperties : uint32_t {
|
||||
OUTPUT_HEAD_COMMITTED_MODE = (1 << 0),
|
||||
OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1),
|
||||
OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2),
|
||||
OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3),
|
||||
OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4),
|
||||
OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5),
|
||||
};
|
||||
|
||||
struct SWlrManagerOutputState {
|
||||
uint32_t committedProperties = 0;
|
||||
|
||||
WP<COutputMode> mode;
|
||||
struct {
|
||||
Vector2D size;
|
||||
uint32_t refresh = 0;
|
||||
} customMode;
|
||||
Vector2D position;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float scale = 1.F;
|
||||
bool adaptiveSync = false;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
struct SWlrManagerSavedOutputState {
|
||||
uint32_t committedProperties = 0;
|
||||
Vector2D resolution;
|
||||
uint32_t refresh = 0;
|
||||
Vector2D position;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float scale = 1.F;
|
||||
bool adaptiveSync = false;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
class COutputManager {
|
||||
public:
|
||||
COutputManager(SP<CZwlrOutputManagerV1> resource_);
|
||||
@@ -21,6 +59,9 @@ class COutputManager {
|
||||
void ensureMonitorSent(CMonitor* pMonitor);
|
||||
void sendDone();
|
||||
|
||||
// holds the states for this manager.
|
||||
std::unordered_map<std::string, SWlrManagerSavedOutputState> monitorStates;
|
||||
|
||||
private:
|
||||
SP<CZwlrOutputManagerV1> resource;
|
||||
bool stopped = false;
|
||||
@@ -80,30 +121,9 @@ class COutputConfigurationHead {
|
||||
public:
|
||||
COutputConfigurationHead(SP<CZwlrOutputConfigurationHeadV1> resource_, CMonitor* pMonitor_);
|
||||
|
||||
bool good();
|
||||
bool good();
|
||||
|
||||
enum eCommittedProperties : uint32_t {
|
||||
OUTPUT_HEAD_COMMITTED_MODE = (1 << 0),
|
||||
OUTPUT_HEAD_COMMITTED_CUSTOM_MODE = (1 << 1),
|
||||
OUTPUT_HEAD_COMMITTED_POSITION = (1 << 2),
|
||||
OUTPUT_HEAD_COMMITTED_TRANSFORM = (1 << 3),
|
||||
OUTPUT_HEAD_COMMITTED_SCALE = (1 << 4),
|
||||
OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC = (1 << 5),
|
||||
};
|
||||
|
||||
uint32_t committedProperties = 0;
|
||||
|
||||
struct {
|
||||
WP<COutputMode> mode;
|
||||
struct {
|
||||
Vector2D size;
|
||||
uint32_t refresh = 0;
|
||||
} customMode;
|
||||
Vector2D position;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float scale = 1.F;
|
||||
bool adaptiveSync = false;
|
||||
} state;
|
||||
SWlrManagerOutputState state;
|
||||
|
||||
private:
|
||||
SP<CZwlrOutputConfigurationHeadV1> resource;
|
||||
@@ -136,6 +156,9 @@ class COutputManagementProtocol : public IWaylandProtocol {
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
// doesn't have to return one
|
||||
SP<SWlrManagerSavedOutputState> getOutputStateFor(SP<CMonitor> pMonitor);
|
||||
|
||||
private:
|
||||
void destroyResource(COutputManager* resource);
|
||||
void destroyResource(COutputHead* resource);
|
||||
|
@@ -58,8 +58,8 @@ void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> data, timespe
|
||||
if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION)
|
||||
flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
|
||||
|
||||
__time_t tv_sec = 0;
|
||||
if (sizeof(__time_t) > 4)
|
||||
time_t tv_sec = 0;
|
||||
if (sizeof(time_t) > 4)
|
||||
tv_sec = when->tv_sec >> 32;
|
||||
|
||||
if (data->wasPresented)
|
||||
|
@@ -27,8 +27,6 @@ class CQueuedPresentationData {
|
||||
WP<CMonitor> pMonitor;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
|
||||
DYNLISTENER(destroySurface);
|
||||
|
||||
friend class CPresentationFeedback;
|
||||
friend class CPresentationProtocol;
|
||||
};
|
||||
|
@@ -394,12 +394,12 @@ void CScreencopyProtocol::bindManager(wl_client* client, void* data, uint32_t ve
|
||||
void CScreencopyProtocol::destroyResource(CScreencopyClient* client) {
|
||||
std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; });
|
||||
std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; });
|
||||
}
|
||||
|
||||
void CScreencopyProtocol::destroyResource(CScreencopyFrame* frame) {
|
||||
std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; });
|
||||
}
|
||||
|
||||
void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
@@ -412,8 +412,11 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
|
||||
// share frame if correct output
|
||||
for (auto const& f : m_vFramesAwaitingWrite) {
|
||||
if (!f)
|
||||
continue;
|
||||
|
||||
if (!f->pMonitor || !f->buffer) {
|
||||
framesToRemove.push_back(f);
|
||||
framesToRemove.emplace_back(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -425,10 +428,10 @@ void CScreencopyProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
f->client->lastFrame.reset();
|
||||
++f->client->frameCounter;
|
||||
|
||||
framesToRemove.push_back(f);
|
||||
framesToRemove.emplace_back(f);
|
||||
}
|
||||
|
||||
for (auto const& f : framesToRemove) {
|
||||
destroyResource(f.get());
|
||||
std::erase(m_vFramesAwaitingWrite, f);
|
||||
}
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ class CScreencopyFrame {
|
||||
|
||||
bool good();
|
||||
|
||||
SP<CScreencopyFrame> self;
|
||||
WP<CScreencopyFrame> self;
|
||||
WP<CScreencopyClient> client;
|
||||
|
||||
private:
|
||||
@@ -92,7 +92,7 @@ class CScreencopyProtocol : public IWaylandProtocol {
|
||||
|
||||
private:
|
||||
std::vector<SP<CScreencopyFrame>> m_vFrames;
|
||||
std::vector<SP<CScreencopyFrame>> m_vFramesAwaitingWrite;
|
||||
std::vector<WP<CScreencopyFrame>> m_vFramesAwaitingWrite;
|
||||
std::vector<SP<CScreencopyClient>> m_vClients;
|
||||
|
||||
SP<CEventLoopTimer> m_pSoftwareCursorTimer;
|
||||
|
128
src/protocols/SinglePixel.cpp
Normal file
128
src/protocols/SinglePixel.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#include "SinglePixel.hpp"
|
||||
#include <limits>
|
||||
#include "render/Renderer.hpp"
|
||||
|
||||
CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) {
|
||||
LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex());
|
||||
|
||||
color = col_.getAsHex();
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
opaque = col_.a >= 1.F;
|
||||
|
||||
texture = makeShared<CTexture>(DRM_FORMAT_ARGB8888, (uint8_t*)&color, 4, Vector2D{1, 1});
|
||||
|
||||
resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
|
||||
|
||||
success = texture->m_iTexID;
|
||||
|
||||
size = {1, 1};
|
||||
|
||||
if (!success)
|
||||
Debug::log(ERR, "Failed creating a single pixel texture: null texture id");
|
||||
}
|
||||
|
||||
CSinglePixelBuffer::~CSinglePixelBuffer() {
|
||||
;
|
||||
}
|
||||
|
||||
Aquamarine::eBufferCapability CSinglePixelBuffer::caps() {
|
||||
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
|
||||
}
|
||||
|
||||
Aquamarine::eBufferType CSinglePixelBuffer::type() {
|
||||
return Aquamarine::eBufferType::BUFFER_TYPE_SHM;
|
||||
}
|
||||
|
||||
bool CSinglePixelBuffer::isSynchronous() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSinglePixelBuffer::update(const CRegion& damage) {
|
||||
;
|
||||
}
|
||||
|
||||
Aquamarine::SDMABUFAttrs CSinglePixelBuffer::dmabuf() {
|
||||
return {.success = false};
|
||||
}
|
||||
|
||||
std::tuple<uint8_t*, uint32_t, size_t> CSinglePixelBuffer::beginDataPtr(uint32_t flags) {
|
||||
return {(uint8_t*)&color, DRM_FORMAT_ARGB8888, 4};
|
||||
}
|
||||
|
||||
void CSinglePixelBuffer::endDataPtr() {
|
||||
;
|
||||
}
|
||||
|
||||
bool CSinglePixelBuffer::good() {
|
||||
return resource->good();
|
||||
}
|
||||
|
||||
CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) {
|
||||
buffer = makeShared<CSinglePixelBuffer>(id, client, color);
|
||||
|
||||
if (!buffer->good())
|
||||
return;
|
||||
|
||||
buffer->resource->buffer = buffer;
|
||||
|
||||
listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) {
|
||||
listeners.bufferResourceDestroy.reset();
|
||||
PROTO::singlePixel->destroyResource(this);
|
||||
});
|
||||
}
|
||||
|
||||
CSinglePixelBufferResource::~CSinglePixelBufferResource() {
|
||||
;
|
||||
}
|
||||
|
||||
bool CSinglePixelBufferResource::good() {
|
||||
return buffer->good();
|
||||
}
|
||||
|
||||
CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP<CWpSinglePixelBufferManagerV1> resource_) : resource(resource_) {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
resource->setDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); });
|
||||
resource->setOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); });
|
||||
|
||||
resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
|
||||
CColor color{r / (float)std::numeric_limits<uint32_t>::max(), g / (float)std::numeric_limits<uint32_t>::max(), b / (float)std::numeric_limits<uint32_t>::max(),
|
||||
a / (float)std::numeric_limits<uint32_t>::max()};
|
||||
const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared<CSinglePixelBufferResource>(id, resource->client(), color));
|
||||
|
||||
if (!RESOURCE->good()) {
|
||||
res->noMemory();
|
||||
PROTO::singlePixel->m_vBuffers.pop_back();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool CSinglePixelBufferManagerResource::good() {
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
CSinglePixelProtocol::CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CSinglePixelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CSinglePixelBufferManagerResource>(makeShared<CWpSinglePixelBufferManagerV1>(client, ver, id)));
|
||||
|
||||
if (!RESOURCE->good()) {
|
||||
wl_client_post_no_memory(client);
|
||||
m_vManagers.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CSinglePixelProtocol::destroyResource(CSinglePixelBufferManagerResource* res) {
|
||||
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; });
|
||||
}
|
||||
|
||||
void CSinglePixelProtocol::destroyResource(CSinglePixelBufferResource* surf) {
|
||||
std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == surf; });
|
||||
}
|
79
src/protocols/SinglePixel.hpp
Normal file
79
src/protocols/SinglePixel.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "single-pixel-buffer-v1.hpp"
|
||||
#include "types/Buffer.hpp"
|
||||
|
||||
class CSinglePixelBuffer : public IHLBuffer {
|
||||
public:
|
||||
CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col);
|
||||
virtual ~CSinglePixelBuffer();
|
||||
|
||||
virtual Aquamarine::eBufferCapability caps();
|
||||
virtual Aquamarine::eBufferType type();
|
||||
virtual bool isSynchronous();
|
||||
virtual void update(const CRegion& damage);
|
||||
virtual Aquamarine::SDMABUFAttrs dmabuf();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
//
|
||||
bool good();
|
||||
bool success = false;
|
||||
|
||||
private:
|
||||
uint32_t color = 0x00000000;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener resourceDestroy;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CSinglePixelBufferResource {
|
||||
public:
|
||||
CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color);
|
||||
~CSinglePixelBufferResource();
|
||||
|
||||
bool good();
|
||||
|
||||
private:
|
||||
SP<CSinglePixelBuffer> buffer;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener bufferResourceDestroy;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CSinglePixelBufferManagerResource {
|
||||
public:
|
||||
CSinglePixelBufferManagerResource(SP<CWpSinglePixelBufferManagerV1> resource_);
|
||||
|
||||
bool good();
|
||||
|
||||
private:
|
||||
SP<CWpSinglePixelBufferManagerV1> resource;
|
||||
};
|
||||
|
||||
class CSinglePixelProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
private:
|
||||
void destroyResource(CSinglePixelBufferManagerResource* resource);
|
||||
void destroyResource(CSinglePixelBufferResource* resource);
|
||||
|
||||
//
|
||||
std::vector<SP<CSinglePixelBufferManagerResource>> m_vManagers;
|
||||
std::vector<SP<CSinglePixelBufferResource>> m_vBuffers;
|
||||
|
||||
friend class CSinglePixelBufferManagerResource;
|
||||
friend class CSinglePixelBufferResource;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CSinglePixelProtocol> singlePixel;
|
||||
};
|
@@ -31,6 +31,7 @@ CTextInputV1::CTextInputV1(SP<CZwpTextInputV1> resource_) : resource(resource_)
|
||||
resource->setReset([this](CZwpTextInputV1* pMgr) {
|
||||
pendingSurrounding.isPending = false;
|
||||
pendingContentType.isPending = false;
|
||||
events.reset.emit();
|
||||
});
|
||||
|
||||
resource->setSetSurroundingText(
|
||||
|
@@ -37,6 +37,7 @@ class CTextInputV1 {
|
||||
CSignal onCommit;
|
||||
CSignal enable;
|
||||
CSignal disable;
|
||||
CSignal reset;
|
||||
CSignal destroy;
|
||||
} events;
|
||||
|
||||
|
@@ -19,17 +19,22 @@ CTextInputV3::CTextInputV3(SP<CZwpTextInputV3> resource_) : resource(resource_)
|
||||
resource->setOnDestroy([this](CZwpTextInputV3* r) { PROTO::textInputV3->destroyTextInput(this); });
|
||||
|
||||
resource->setCommit([this](CZwpTextInputV3* r) {
|
||||
bool wasEnabled = current.enabled;
|
||||
bool wasEnabled = current.enabled.value;
|
||||
|
||||
current = pending;
|
||||
serial++;
|
||||
|
||||
if (wasEnabled && !current.enabled)
|
||||
if (wasEnabled && !current.enabled.value)
|
||||
events.disable.emit();
|
||||
else if (!wasEnabled && current.enabled)
|
||||
else if (!wasEnabled && current.enabled.value)
|
||||
events.enable.emit();
|
||||
else if (current.enabled.value && current.enabled.isEnablePending && current.enabled.isDisablePending)
|
||||
events.reset.emit();
|
||||
else
|
||||
events.onCommit.emit();
|
||||
|
||||
pending.enabled.isEnablePending = false;
|
||||
pending.enabled.isDisablePending = false;
|
||||
});
|
||||
|
||||
resource->setSetSurroundingText([this](CZwpTextInputV3* r, const char* text, int32_t cursor, int32_t anchor) {
|
||||
@@ -54,10 +59,14 @@ CTextInputV3::CTextInputV3(SP<CZwpTextInputV3> resource_) : resource(resource_)
|
||||
|
||||
resource->setEnable([this](CZwpTextInputV3* r) {
|
||||
pending.reset();
|
||||
pending.enabled = true;
|
||||
pending.enabled.value = true;
|
||||
pending.enabled.isEnablePending = true;
|
||||
});
|
||||
|
||||
resource->setDisable([this](CZwpTextInputV3* r) { pending.enabled = false; });
|
||||
resource->setDisable([this](CZwpTextInputV3* r) {
|
||||
pending.enabled.value = false;
|
||||
pending.enabled.isDisablePending = true;
|
||||
});
|
||||
}
|
||||
|
||||
CTextInputV3::~CTextInputV3() {
|
||||
|
@@ -31,6 +31,7 @@ class CTextInputV3 {
|
||||
CSignal onCommit;
|
||||
CSignal enable;
|
||||
CSignal disable;
|
||||
CSignal reset;
|
||||
CSignal destroy;
|
||||
} events;
|
||||
|
||||
@@ -53,7 +54,11 @@ class CTextInputV3 {
|
||||
CBox cursorBox;
|
||||
} box;
|
||||
|
||||
bool enabled = false;
|
||||
struct {
|
||||
bool isEnablePending = false;
|
||||
bool isDisablePending = false;
|
||||
bool value = false;
|
||||
} enabled;
|
||||
|
||||
zwpTextInputV3ChangeCause cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD;
|
||||
|
||||
|
@@ -354,12 +354,12 @@ void CToplevelExportProtocol::bindManager(wl_client* client, void* data, uint32_
|
||||
void CToplevelExportProtocol::destroyResource(CToplevelExportClient* client) {
|
||||
std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; });
|
||||
std::erase_if(m_vFrames, [&](const auto& other) { return other->client.get() == client; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other->client.get() == client; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other->client.get() == client; });
|
||||
}
|
||||
|
||||
void CToplevelExportProtocol::destroyResource(CToplevelExportFrame* frame) {
|
||||
std::erase_if(m_vFrames, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other.get() == frame; });
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return !other || other.get() == frame; });
|
||||
}
|
||||
|
||||
void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
@@ -370,11 +370,17 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
|
||||
// share frame if correct output
|
||||
for (auto const& f : m_vFramesAwaitingWrite) {
|
||||
if (!f->pWindow || !validMapped(f->pWindow)) {
|
||||
framesToRemove.push_back(f);
|
||||
if (!f)
|
||||
continue;
|
||||
|
||||
if (!validMapped(f->pWindow)) {
|
||||
framesToRemove.emplace_back(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!f->pWindow)
|
||||
continue;
|
||||
|
||||
const auto PWINDOW = f->pWindow;
|
||||
|
||||
if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID))
|
||||
@@ -394,7 +400,7 @@ void CToplevelExportProtocol::onOutputCommit(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
for (auto const& f : framesToRemove) {
|
||||
destroyResource(f.get());
|
||||
std::erase(m_vFramesAwaitingWrite, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,7 @@ class CToplevelExportFrame {
|
||||
|
||||
bool good();
|
||||
|
||||
SP<CToplevelExportFrame> self;
|
||||
WP<CToplevelExportFrame> self;
|
||||
WP<CToplevelExportClient> client;
|
||||
|
||||
private:
|
||||
@@ -85,7 +85,7 @@ class CToplevelExportProtocol : IWaylandProtocol {
|
||||
private:
|
||||
std::vector<SP<CToplevelExportClient>> m_vClients;
|
||||
std::vector<SP<CToplevelExportFrame>> m_vFrames;
|
||||
std::vector<SP<CToplevelExportFrame>> m_vFramesAwaitingWrite;
|
||||
std::vector<WP<CToplevelExportFrame>> m_vFramesAwaitingWrite;
|
||||
|
||||
void shareFrame(CToplevelExportFrame* frame);
|
||||
bool copyFrameDmabuf(CToplevelExportFrame* frame, timespec* now);
|
||||
|
@@ -29,29 +29,20 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver
|
||||
return;
|
||||
}
|
||||
|
||||
RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); });
|
||||
RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { this->onManagerResourceDestroy(res->resource()); });
|
||||
RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { this->onManagerGetXDGOutput(mgr, id, output); });
|
||||
RESOURCE->setDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); });
|
||||
RESOURCE->setOnDestroy([this](CZxdgOutputManagerV1* res) { onManagerResourceDestroy(res->resource()); });
|
||||
RESOURCE->setGetXdgOutput([this](CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* output) { onManagerGetXDGOutput(mgr, id, output); });
|
||||
}
|
||||
|
||||
CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
static auto P = g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
static auto P2 = g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
static auto P3 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) {
|
||||
const auto PMONITOR = std::any_cast<CMonitor*>(param);
|
||||
for (auto const& o : m_vXDGOutputs) {
|
||||
if (o->monitor == PMONITOR)
|
||||
o->monitor = nullptr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource) {
|
||||
const auto OUTPUT = CWLOutputResource::fromResource(outputResource);
|
||||
|
||||
const auto PMONITOR = OUTPUT->monitor.get();
|
||||
|
||||
const auto CLIENT = mgr->client();
|
||||
const auto OUTPUT = CWLOutputResource::fromResource(outputResource);
|
||||
const auto PMONITOR = OUTPUT->monitor.lock();
|
||||
const auto CLIENT = mgr->client();
|
||||
|
||||
CXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<CXDGOutput>(makeShared<CZxdgOutputV1>(CLIENT, mgr->version(), id), PMONITOR)).get();
|
||||
#ifndef NO_XWAYLAND
|
||||
@@ -60,14 +51,20 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32
|
||||
#endif
|
||||
pXDGOutput->client = CLIENT;
|
||||
|
||||
pXDGOutput->outputProto = OUTPUT->owner;
|
||||
|
||||
if (!pXDGOutput->resource->resource()) {
|
||||
m_vXDGOutputs.pop_back();
|
||||
mgr->noMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PMONITOR)
|
||||
if (!PMONITOR) {
|
||||
LOGM(ERR, "New xdg_output from client {:x} ({}) has no CMonitor?!", (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGM(LOG, "New xdg_output for {}: client {:x} ({})", PMONITOR->szName, (uintptr_t)CLIENT, pXDGOutput->isXWayland ? "xwayland" : "not xwayland");
|
||||
|
||||
const auto XDGVER = pXDGOutput->resource->version();
|
||||
|
||||
@@ -84,8 +81,9 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::updateAllOutputs() {
|
||||
for (auto const& o : m_vXDGOutputs) {
|
||||
LOGM(LOG, "updating all xdg_output heads");
|
||||
|
||||
for (auto const& o : m_vXDGOutputs) {
|
||||
if (!o->monitor)
|
||||
continue;
|
||||
|
||||
@@ -97,7 +95,7 @@ void CXDGOutputProtocol::updateAllOutputs() {
|
||||
|
||||
//
|
||||
|
||||
CXDGOutput::CXDGOutput(SP<CZxdgOutputV1> resource_, CMonitor* monitor_) : monitor(monitor_), resource(resource_) {
|
||||
CXDGOutput::CXDGOutput(SP<CZxdgOutputV1> resource_, SP<CMonitor> monitor_) : monitor(monitor_), resource(resource_) {
|
||||
if (!resource->resource())
|
||||
return;
|
||||
|
||||
@@ -108,7 +106,7 @@ CXDGOutput::CXDGOutput(SP<CZxdgOutputV1> resource_, CMonitor* monitor_) : monito
|
||||
void CXDGOutput::sendDetails() {
|
||||
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
||||
|
||||
if (!monitor)
|
||||
if (!monitor || !outputProto || outputProto->isDefunct())
|
||||
return;
|
||||
|
||||
const auto POS = isXWayland ? monitor->vecXWaylandPosition : monitor->vecPosition;
|
||||
|
@@ -6,16 +6,18 @@
|
||||
|
||||
class CMonitor;
|
||||
class CXDGOutputProtocol;
|
||||
class CWLOutputProtocol;
|
||||
|
||||
class CXDGOutput {
|
||||
public:
|
||||
CXDGOutput(SP<CZxdgOutputV1> resource, CMonitor* monitor_);
|
||||
CXDGOutput(SP<CZxdgOutputV1> resource, SP<CMonitor> monitor_);
|
||||
|
||||
void sendDetails();
|
||||
|
||||
private:
|
||||
CMonitor* monitor = nullptr;
|
||||
WP<CMonitor> monitor;
|
||||
SP<CZxdgOutputV1> resource;
|
||||
WP<CWLOutputProtocol> outputProto;
|
||||
|
||||
std::optional<Vector2D> overridePosition;
|
||||
|
||||
@@ -30,12 +32,12 @@ class CXDGOutputProtocol : public IWaylandProtocol {
|
||||
CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
void updateAllOutputs();
|
||||
|
||||
private:
|
||||
void onManagerResourceDestroy(wl_resource* res);
|
||||
void onOutputResourceDestroy(wl_resource* res);
|
||||
void onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32_t id, wl_resource* outputResource);
|
||||
void updateAllOutputs();
|
||||
|
||||
//
|
||||
std::vector<UP<CZxdgOutputManagerV1>> m_vManagerResources;
|
||||
|
@@ -82,9 +82,18 @@ void CWLDataOfferResource::sendData() {
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
if (resource->version() >= 3) {
|
||||
resource->sendSourceActions(7);
|
||||
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
|
||||
const auto SOURCEACTIONS = source->actions();
|
||||
|
||||
if (resource->version() >= 3 && SOURCEACTIONS > 0) {
|
||||
resource->sendSourceActions(SOURCEACTIONS);
|
||||
if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
||||
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
|
||||
else if (SOURCEACTIONS & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
||||
else {
|
||||
LOGM(ERR, "Client bug? dnd source has no action move or copy. Sending move, f this.");
|
||||
resource->sendAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& m : source->mimes()) {
|
||||
@@ -113,7 +122,7 @@ CWLDataSourceResource::CWLDataSourceResource(SP<CWlDataSource> resource_, SP<CWL
|
||||
resource->setOffer([this](CWlDataSource* r, const char* mime) { mimeTypes.push_back(mime); });
|
||||
resource->setSetActions([this](CWlDataSource* r, uint32_t a) {
|
||||
LOGM(LOG, "DataSource {:x} actions {}", (uintptr_t)this, a);
|
||||
actions = (wl_data_device_manager_dnd_action)a;
|
||||
supportedActions = a;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -195,6 +204,10 @@ void CWLDataSourceResource::sendDndAction(wl_data_device_manager_dnd_action a) {
|
||||
resource->sendAction(a);
|
||||
}
|
||||
|
||||
uint32_t CWLDataSourceResource::actions() {
|
||||
return supportedActions;
|
||||
}
|
||||
|
||||
CWLDataDeviceResource::CWLDataDeviceResource(SP<CWlDataDevice> resource_) : resource(resource_) {
|
||||
if (!good())
|
||||
return;
|
||||
@@ -513,7 +526,10 @@ void CWLDataDeviceProtocol::initiateDrag(WP<CWLDataSourceResource> currentSource
|
||||
if (!box.has_value())
|
||||
return;
|
||||
|
||||
dnd.focusedDevice->sendMotion(0 /* this is a hack */, V - box->pos());
|
||||
timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC, &timeNow);
|
||||
|
||||
dnd.focusedDevice->sendMotion(timeNow.tv_sec * 1000 + timeNow.tv_nsec / 1000000, V - box->pos());
|
||||
LOGM(LOG, "Drag motion {}", V - box->pos());
|
||||
}
|
||||
});
|
||||
|
@@ -65,6 +65,7 @@ class CWLDataSourceResource : public IDataSource {
|
||||
virtual bool dndDone();
|
||||
virtual void error(uint32_t code, const std::string& msg);
|
||||
virtual void sendDndFinished();
|
||||
virtual uint32_t actions(); // wl_data_device_manager.dnd_action
|
||||
|
||||
void sendDndDropPerformed();
|
||||
void sendDndAction(wl_data_device_manager_dnd_action a);
|
||||
@@ -78,7 +79,7 @@ class CWLDataSourceResource : public IDataSource {
|
||||
WP<CWLDataSourceResource> self;
|
||||
|
||||
std::vector<std::string> mimeTypes;
|
||||
uint32_t actions = 0;
|
||||
uint32_t supportedActions = 0;
|
||||
|
||||
private:
|
||||
SP<CWlDataSource> resource;
|
||||
|
@@ -21,8 +21,6 @@ CWLOutputResource::CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> pMoni
|
||||
PROTO::outputs.at(monitor->szName)->destroyResource(this);
|
||||
});
|
||||
|
||||
resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(),
|
||||
monitor->output->model.c_str(), monitor->transform);
|
||||
if (resource->version() >= 4) {
|
||||
resource->sendName(monitor->szName.c_str());
|
||||
resource->sendDescription(monitor->szDescription.c_str());
|
||||
@@ -57,6 +55,9 @@ void CWLOutputResource::updateState() {
|
||||
|
||||
resource->sendMode((wl_output_mode)(WL_OUTPUT_MODE_CURRENT), monitor->vecPixelSize.x, monitor->vecPixelSize.y, monitor->refreshRate * 1000.0);
|
||||
|
||||
resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(),
|
||||
monitor->output->model.c_str(), monitor->transform);
|
||||
|
||||
if (resource->version() >= 2)
|
||||
resource->sendDone();
|
||||
}
|
||||
@@ -118,6 +119,9 @@ bool CWLOutputProtocol::isDefunct() {
|
||||
}
|
||||
|
||||
void CWLOutputProtocol::sendDone() {
|
||||
if (defunct)
|
||||
return;
|
||||
|
||||
for (auto const& r : m_vOutputs) {
|
||||
r->resource->sendDone();
|
||||
}
|
||||
|
@@ -193,11 +193,8 @@ void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, ui
|
||||
DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010,
|
||||
};
|
||||
|
||||
for (auto const& fmt : g_pHyprOpenGL->getDRMFormats()) {
|
||||
if (std::find(supportedShmFourccFormats.begin(), supportedShmFourccFormats.end(), fmt.drmFormat) == supportedShmFourccFormats.end())
|
||||
continue;
|
||||
|
||||
shmFormats.push_back(fmt.drmFormat);
|
||||
for (auto const& fmt : supportedShmFourccFormats) {
|
||||
shmFormats.push_back(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user