Compare commits
215 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1c460e98f8 | ||
|
489ac40abd | ||
|
e3373669e5 | ||
|
f26d7aa58d | ||
|
e2c286548d | ||
|
60f81b8a23 | ||
|
98034fea3c | ||
|
21f7f32dc9 | ||
|
ffd7217243 | ||
|
bc3f5b94eb | ||
|
f7a3453487 | ||
|
1742605eb8 | ||
|
81fe2ae7f1 | ||
|
dfcfb92ec6 | ||
|
9815402074 | ||
|
a14f6b570f | ||
|
7f35bff720 | ||
|
54a8329936 | ||
|
f9cfec8abb | ||
|
f534ac3fc4 | ||
|
9103af317e | ||
|
5824b0f305 | ||
|
e9528fc214 | ||
|
6f83856025 | ||
|
d92da7959a | ||
|
f27054c13e | ||
|
bdbd8d965d | ||
|
bfb1e876a8 | ||
|
ca59bd5739 | ||
|
f389f77015 | ||
|
8c3613632a | ||
|
c1ef361e02 | ||
|
35e80a64a6 | ||
|
e83bf4f7b7 | ||
|
c353b7c4f7 | ||
|
d9757b61bf | ||
|
28410922da | ||
|
cfc652e17d | ||
|
dbccbabac5 | ||
|
9a6956fe67 | ||
|
af0c8e299b | ||
|
7fbe016c15 | ||
|
0ebee80bca | ||
|
c4283abb9f | ||
|
94aeb06d6b | ||
|
ea3fd13e24 | ||
|
dad8ffd576 | ||
|
fc5ca391ad | ||
|
e5eb1bdf01 | ||
|
ddf022d61c | ||
|
13d9854897 | ||
|
cd73dda16e | ||
|
02c9a2d769 | ||
|
7ea37c9dc9 | ||
|
86be75dd97 | ||
|
030ed27cc8 | ||
|
e793f10b8b | ||
|
d62e7a5125 | ||
|
fe9c8d8745 | ||
|
df82625206 | ||
|
1763566308 | ||
|
e4790e3f8e | ||
|
69a4f08dbe | ||
|
c6b1d82c70 | ||
|
301b48b740 | ||
|
fae47ef462 | ||
|
5fc0b772c7 | ||
|
13f6f0b923 | ||
|
7e8bcd675d | ||
|
683a4b07c5 | ||
|
5261a8df81 | ||
|
289d952a6e | ||
|
294e51a857 | ||
|
cdcc5aba06 | ||
|
e3e7e1fdda | ||
|
fbf5ba87ce | ||
|
a8dae8f5e1 | ||
|
a42b984f51 | ||
|
e5ac970d6e | ||
|
770956b092 | ||
|
3cca36e773 | ||
|
ef490965a2 | ||
|
b7ab15dc80 | ||
|
9c3f3b0018 | ||
|
8d68d6bfa5 | ||
|
60834a4687 | ||
|
7f52db806c | ||
|
305b1419c8 | ||
|
d5950f7719 | ||
|
0608791480 | ||
|
2a002f31e4 | ||
|
2a3429d4cf | ||
|
95abf1220f | ||
|
b500e5699b | ||
|
61378380ee | ||
|
890307532c | ||
|
f33d73b9cf | ||
|
927da86e3e | ||
|
cca3c64301 | ||
|
6e5c78bf63 | ||
|
e4bb5fa4af | ||
|
cb258c82f4 | ||
|
658f718fa3 | ||
|
334a0f03ee | ||
|
289d4241be | ||
|
a6ccd36147 | ||
|
3d9ca6381d | ||
|
f085ed4454 | ||
|
ded174d6e5 | ||
|
181f651de2 | ||
|
8a6e428d32 | ||
|
1fd82e37a7 | ||
|
f9202f791e | ||
|
84ab8d11e8 | ||
|
60bda7ee3d | ||
|
939696f97e | ||
|
cbadf3e3f3 | ||
|
1ed4f1cb25 | ||
|
5d4ff60f53 | ||
|
504ebe1b37 | ||
|
cf1886ca44 | ||
|
341e04a36c | ||
|
d7514412d8 | ||
|
7447be8220 | ||
|
4644de2269 | ||
|
3656045ad8 | ||
|
15316aaa31 | ||
|
cfd68af5b6 | ||
|
4f804d5f96 | ||
|
e6f7724ab0 | ||
|
e65f52bf2d | ||
|
c51b3fb06f | ||
|
3ff59e7e1d | ||
|
3d0d3b6343 | ||
|
2e3f0d5991 | ||
|
91e8c42843 | ||
|
4b4bd90b14 | ||
|
7009dc9184 | ||
|
b7840c6461 | ||
|
5a90911b70 | ||
|
0e5f14d8d2 | ||
|
df990c80e2 | ||
|
352574d862 | ||
|
bfcc2adbda | ||
|
9002657bcc | ||
|
3e93fdf779 | ||
|
bc7e488a4c | ||
|
8b1069b330 | ||
|
61fd75b55e | ||
|
7b3d039388 | ||
|
12d79d6342 | ||
|
08e3519747 | ||
|
5cd7e4587e | ||
|
72987dee88 | ||
|
754eaf5b8b | ||
|
df17991b1c | ||
|
791e1b96b3 | ||
|
02b4a9bded | ||
|
4d403dac32 | ||
|
f40e382fc6 | ||
|
b86ed02d8a | ||
|
17339e0ae9 | ||
|
5eeec8860e | ||
|
9f20a15955 | ||
|
c4365f20ed | ||
|
307dd8f511 | ||
|
8342bac697 | ||
|
3c964a9fdc | ||
|
f14c5ea5c5 | ||
|
dcd7a92b01 | ||
|
b6516bad02 | ||
|
13d9a637d6 | ||
|
4cee94b91c | ||
|
c4da4b026d | ||
|
babb9c07b0 | ||
|
6b92144f15 | ||
|
8d31c84483 | ||
|
d484506600 | ||
|
b240704bee | ||
|
71166ef40b | ||
|
252aaaecfa | ||
|
f92a86af53 | ||
|
2ba2c8aeee | ||
|
955009655d | ||
|
d7d333d162 | ||
|
f5b2fd2bc3 | ||
|
44ee9915e3 | ||
|
9f2bde925b | ||
|
7904188de9 | ||
|
666ee61c13 | ||
|
7e033e48ac | ||
|
d8dbdc4a01 | ||
|
d3acf8da3b | ||
|
aeeeace102 | ||
|
880996b053 | ||
|
4d6d662c67 | ||
|
1512b81126 | ||
|
4f26c4e1eb | ||
|
3c33d4b9dd | ||
|
bd3ea8dcb5 | ||
|
813af393f1 | ||
|
583b05a8c6 | ||
|
1607e96704 | ||
|
1a4f23eb2f | ||
|
42ab06e7c8 | ||
|
46753b1f22 | ||
|
d4e68ab602 | ||
|
37b76cd1ca | ||
|
0be36cd02d | ||
|
4e0e8d933e | ||
|
c7ba460687 | ||
|
3a189c265d | ||
|
069880e374 | ||
|
fa5e812304 | ||
|
33444e1e5e |
17
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -9,12 +9,23 @@ body:
|
||||
|
||||
---
|
||||
|
||||
- type: input
|
||||
- type: textarea
|
||||
id: ver
|
||||
attributes:
|
||||
label: Hyprland Version
|
||||
description: "Paste here the output of `hyprctl version`."
|
||||
placeholder: Hyprland, built from branch main at commit...
|
||||
description: "Paste here the output of `hyprctl version`. For hyprland after 0.34.0, paste `hyprctl systeminfo` instead."
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
|
||||
```sh
|
||||
|
||||
<Paste the output of the command here>
|
||||
|
||||
```
|
||||
|
||||
|
||||
</details>"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
1
.github/actions/setup_base/action.yml
vendored
@@ -23,6 +23,7 @@ runs:
|
||||
glm \
|
||||
glslang \
|
||||
go \
|
||||
hyprlang \
|
||||
jq \
|
||||
libc++ \
|
||||
libdisplay-info \
|
||||
|
28
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information, see:
|
||||
# https://github.com/actions/stale
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '7 */4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.STALEBOT_PAT }}
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
operations-per-run: 40
|
||||
days-before-close: -1
|
2
.gitignore
vendored
@@ -31,3 +31,5 @@ gmon.out
|
||||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
|
||||
.direnv
|
||||
|
@@ -57,8 +57,8 @@ ExternalProject_Add(
|
||||
wlroots
|
||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||
PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build
|
||||
CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure
|
||||
PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build
|
||||
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
|
||||
BUILD_COMMAND ninja -C build
|
||||
BUILD_ALWAYS true
|
||||
BUILD_IN_SOURCE true
|
||||
@@ -101,7 +101,7 @@ message(STATUS "Checking deps...")
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves
|
||||
|
||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
|
13
Makefile
@@ -1,22 +1,22 @@
|
||||
PREFIX = /usr/local
|
||||
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
@@ -42,10 +42,10 @@ install:
|
||||
chmod 755 ${PREFIX}/bin/Hyprland
|
||||
chmod 755 ${PREFIX}/bin/hyprctl
|
||||
chmod 755 ${PREFIX}/bin/hyprpm
|
||||
ln -s -r ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland
|
||||
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
|
||||
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||
mkdir -p ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_* ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall* ${PREFIX}/share/hyprland
|
||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||
|
||||
@@ -60,6 +60,7 @@ install:
|
||||
uninstall:
|
||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||
rm -f ${PREFIX}/bin/Hyprland
|
||||
rm -f ${PREFIX}/bin/hyprland
|
||||
rm -f ${PREFIX}/bin/hyprctl
|
||||
rm -f ${PREFIX}/bin/hyprpm
|
||||
rm -f ${PREFIX}/lib/libwlroots.so.13032
|
||||
|
@@ -1,9 +1,7 @@
|
||||
wallpaper_types = ['', 'anime_', 'anime2_']
|
||||
wallpapers = ['0', '1', '2']
|
||||
|
||||
foreach type : wallpaper_types
|
||||
foreach size : [2, 4, 8]
|
||||
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
|
BIN
assets/wall0.png
Normal file
After Width: | Height: | Size: 14 MiB |
BIN
assets/wall1.png
Normal file
After Width: | Height: | Size: 5.9 MiB |
BIN
assets/wall2.png
Normal file
After Width: | Height: | Size: 27 MiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 511 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 502 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.6 MiB |
@@ -47,7 +47,7 @@ basically, directories in /tmp/hypr are your sessions.
|
||||
|
||||
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
|
||||
|
||||
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `~/.hyprland`
|
||||
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `$HOME/.cache/hyprland`.
|
||||
|
||||
Go to the crash report directory and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.
|
||||
|
||||
|
@@ -1,8 +0,0 @@
|
||||
# compile with HYPRLAND_HEADERS=<path_to_hl> make all
|
||||
# make sure that the path above is to the root hl repo directory, NOT src/
|
||||
# and that you have ran `make protocols` in the hl dir.
|
||||
|
||||
all:
|
||||
$(CXX) -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g `pkg-config --cflags pixman-1 libdrm hyprland` -std=c++2b
|
||||
clean:
|
||||
rm ./examplePlugin.so
|
@@ -1,74 +0,0 @@
|
||||
#include "customDecoration.hpp"
|
||||
#include <hyprland/src/Window.hpp>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "globals.hpp"
|
||||
|
||||
CCustomDecoration::CCustomDecoration(CWindow* pWindow) {
|
||||
m_pWindow = pWindow;
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||
}
|
||||
|
||||
CCustomDecoration::~CCustomDecoration() {
|
||||
damageEntire();
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CCustomDecoration::getWindowDecorationExtents() {
|
||||
return m_seExtents;
|
||||
}
|
||||
|
||||
void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
|
||||
if (!g_pCompositor->windowValidMapped(m_pWindow))
|
||||
return;
|
||||
|
||||
if (!m_pWindow->m_sSpecialRenderData.decorate)
|
||||
return;
|
||||
|
||||
static auto* const PCOLOR = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color")->intValue;
|
||||
static auto* const PROUNDING = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue;
|
||||
static auto* const PBORDERSIZE = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue;
|
||||
|
||||
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ?
|
||||
0 :
|
||||
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
|
||||
|
||||
// draw the border
|
||||
CBox fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||
|
||||
fullBox.x -= pMonitor->vecPosition.x;
|
||||
fullBox.y -= pMonitor->vecPosition.y;
|
||||
|
||||
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
|
||||
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
|
||||
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
|
||||
|
||||
fullBox.x += offset.x;
|
||||
fullBox.y += offset.y;
|
||||
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
||||
|
||||
fullBox.scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
|
||||
}
|
||||
|
||||
eDecorationType CCustomDecoration::getDecorationType() {
|
||||
return DECORATION_CUSTOM;
|
||||
}
|
||||
|
||||
void CCustomDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
damageEntire();
|
||||
}
|
||||
|
||||
void CCustomDecoration::damageEntire() {
|
||||
CBox dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WLR_USE_UNSTABLE
|
||||
|
||||
#include <hyprland/src/render/decorations/IHyprWindowDecoration.hpp>
|
||||
|
||||
class CCustomDecoration : public IHyprWindowDecoration {
|
||||
public:
|
||||
CCustomDecoration(CWindow*);
|
||||
virtual ~CCustomDecoration();
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||
|
||||
virtual void draw(CMonitor*, float a, const Vector2D& offset);
|
||||
|
||||
virtual eDecorationType getDecorationType();
|
||||
|
||||
virtual void updateWindow(CWindow*);
|
||||
|
||||
virtual void damageEntire();
|
||||
|
||||
private:
|
||||
SWindowDecorationExtents m_seExtents;
|
||||
|
||||
CWindow* m_pWindow = nullptr;
|
||||
|
||||
Vector2D m_vLastWindowPos;
|
||||
Vector2D m_vLastWindowSize;
|
||||
};
|
@@ -1,80 +0,0 @@
|
||||
#include "customLayout.hpp"
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "globals.hpp"
|
||||
|
||||
void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const auto SIZE = PMONITOR->vecSize;
|
||||
|
||||
// these are used for focus and move calculations, and are *required* to touch for moving focus to work properly.
|
||||
pWindow->m_vPosition = Vector2D{(SIZE.x / 2.0) * (m_vWindowData.size() % 2), (SIZE.y / 2.0) * (int)(m_vWindowData.size() > 1)};
|
||||
pWindow->m_vSize = SIZE / 2.0;
|
||||
|
||||
// this is the actual pos and size of the window (where it's rendered)
|
||||
pWindow->m_vRealPosition = pWindow->m_vPosition + Vector2D{10, 10};
|
||||
pWindow->m_vRealSize = pWindow->m_vSize - Vector2D{20, 20};
|
||||
|
||||
const auto PDATA = &m_vWindowData.emplace_back();
|
||||
PDATA->pWindow = pWindow;
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
std::erase_if(m_vWindowData, [&](const auto& other) { return other.pWindow == pWindow; });
|
||||
}
|
||||
|
||||
bool CHyprCustomLayout::isWindowTiled(CWindow* pWindow) {
|
||||
return std::find_if(m_vWindowData.begin(), m_vWindowData.end(), [&](const auto& other) { return other.pWindow == pWindow; }) != m_vWindowData.end();
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::recalculateMonitor(const int& eIdleInhibitMode) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::recalculateWindow(CWindow* pWindow) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode mode, bool on) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
std::any CHyprCustomLayout::layoutMessage(SLayoutMessageHeader header, std::string content) {
|
||||
return "";
|
||||
}
|
||||
|
||||
SWindowRenderLayoutHints CHyprCustomLayout::requestRenderHints(CWindow* pWindow) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
std::string CHyprCustomLayout::getLayoutName() {
|
||||
return "custom";
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||
; // empty
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::onEnable() {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
onWindowCreatedTiling(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprCustomLayout::onDisable() {
|
||||
m_vWindowData.clear();
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WLR_USE_UNSTABLE
|
||||
|
||||
#include <hyprland/src/layout/IHyprLayout.hpp>
|
||||
|
||||
struct SWindowData {
|
||||
CWindow* pWindow = nullptr;
|
||||
};
|
||||
|
||||
class CHyprCustomLayout : public IHyprLayout {
|
||||
public:
|
||||
virtual void onWindowCreatedTiling(CWindow*);
|
||||
virtual void onWindowRemovedTiling(CWindow*);
|
||||
virtual bool isWindowTiled(CWindow*);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateWindow(CWindow*);
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
virtual void switchWindows(CWindow*, CWindow*);
|
||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
||||
virtual std::string getLayoutName();
|
||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||
|
||||
virtual void onEnable();
|
||||
virtual void onDisable();
|
||||
|
||||
private:
|
||||
std::vector<SWindowData> m_vWindowData;
|
||||
};
|
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
|
||||
inline HANDLE PHANDLE = nullptr;
|
@@ -1,99 +0,0 @@
|
||||
#define WLR_USE_UNSTABLE
|
||||
|
||||
#include "globals.hpp"
|
||||
|
||||
#include <hyprland/src/Window.hpp>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include "customLayout.hpp"
|
||||
#include "customDecoration.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
// Methods
|
||||
inline std::unique_ptr<CHyprCustomLayout> g_pCustomLayout;
|
||||
inline CFunctionHook* g_pFocusHook = nullptr;
|
||||
inline CFunctionHook* g_pMotionHook = nullptr;
|
||||
inline CFunctionHook* g_pMouseDownHook = nullptr;
|
||||
typedef void (*origFocusWindow)(void*, CWindow*, wlr_surface*);
|
||||
typedef void (*origMotion)(wlr_seat*, uint32_t, double, double);
|
||||
typedef void (*origMouseDownNormal)(void*, wlr_pointer_button_event*);
|
||||
|
||||
// Do NOT change this function.
|
||||
APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
||||
return HYPRLAND_API_VERSION;
|
||||
}
|
||||
|
||||
static void onActiveWindowChange(void* self, std::any data) {
|
||||
try {
|
||||
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||
|
||||
HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: " + (PWINDOW ? PWINDOW->m_szTitle : "None"), CColor{0.f, 0.5f, 1.f, 1.f}, 5000);
|
||||
} catch (std::bad_any_cast& e) { HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: None", CColor{0.f, 0.5f, 1.f, 1.f}, 5000); }
|
||||
}
|
||||
|
||||
static void onNewWindow(void* self, std::any data) {
|
||||
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||
|
||||
HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CCustomDecoration(PWINDOW));
|
||||
}
|
||||
|
||||
void hkFocusWindow(void* thisptr, CWindow* pWindow, wlr_surface* pSurface) {
|
||||
// HyprlandAPI::addNotification(PHANDLE, getFormat("FocusWindow with %lx %lx", pWindow, pSurface), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||
(*(origFocusWindow)g_pFocusHook->m_pOriginal)(thisptr, pWindow, pSurface);
|
||||
}
|
||||
|
||||
void hkNotifyMotion(wlr_seat* wlr_seat, uint32_t time_msec, double sx, double sy) {
|
||||
// HyprlandAPI::addNotification(PHANDLE, getFormat("NotifyMotion with %lf %lf", sx, sy), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||
(*(origMotion)g_pMotionHook->m_pOriginal)(wlr_seat, time_msec, sx, sy);
|
||||
}
|
||||
|
||||
void hkProcessMouseDownNormal(void* thisptr, wlr_pointer_button_event* e) {
|
||||
// HyprlandAPI::addNotification(PHANDLE, "Mouse down normal!", CColor{0.8f, 0.2f, 0.5f, 1.0f}, 5000);
|
||||
(*(origMouseDownNormal)g_pMouseDownHook->m_pOriginal)(thisptr, e);
|
||||
}
|
||||
|
||||
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||
PHANDLE = handle;
|
||||
|
||||
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); });
|
||||
|
||||
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
|
||||
|
||||
HyprlandAPI::addLayout(PHANDLE, "custom", g_pCustomLayout.get());
|
||||
|
||||
HyprlandAPI::addConfigValue(PHANDLE, "plugin:example:border_color", SConfigValue{.intValue = configStringToInt("rgb(44ee44)")});
|
||||
|
||||
HyprlandAPI::addDispatcher(PHANDLE, "example", [](std::string arg) { HyprlandAPI::addNotification(PHANDLE, "Arg passed: " + arg, CColor{0.5f, 0.5f, 0.7f, 1.0f}, 5000); });
|
||||
|
||||
// Hook a public member
|
||||
g_pFocusHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&CCompositor::focusWindow, (void*)&hkFocusWindow);
|
||||
// Hook a public non-member
|
||||
g_pMotionHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&wlr_seat_pointer_notify_motion, (void*)&hkNotifyMotion);
|
||||
// Hook a private member
|
||||
static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "processMouseDownNormal");
|
||||
g_pMouseDownHook = HyprlandAPI::createFunctionHook(PHANDLE, METHODS[0].address, (void*)&hkProcessMouseDownNormal);
|
||||
|
||||
static auto* const PBORDERCOLOR = HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color");
|
||||
|
||||
// fancy notifications
|
||||
HyprlandAPI::addNotificationV2(
|
||||
PHANDLE,
|
||||
{{"text", "Example hint, color " + std::to_string(PBORDERCOLOR->intValue)}, {"time", (uint64_t)10000}, {"color", CColor{PBORDERCOLOR->intValue}}, {"icon", ICON_HINT}});
|
||||
|
||||
// Enable our hooks
|
||||
g_pFocusHook->hook();
|
||||
g_pMotionHook->hook();
|
||||
g_pMouseDownHook->hook();
|
||||
|
||||
HyprlandAPI::reloadConfig();
|
||||
|
||||
return {"ExamplePlugin", "An example plugin", "Vaxry", "1.0"};
|
||||
}
|
||||
|
||||
APICALL EXPORT void PLUGIN_EXIT() {
|
||||
HyprlandAPI::invokeHyprctlCommand("seterror", "disable");
|
||||
}
|
@@ -112,12 +112,13 @@ gestures {
|
||||
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
|
||||
device:epic-mouse-v1 {
|
||||
device {
|
||||
name = epic-mouse-v1
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
||||
@@ -126,7 +127,7 @@ device:epic-mouse-v1 {
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
|
47
flake.lock
generated
@@ -23,13 +23,36 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprlang": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708787654,
|
||||
"narHash": "sha256-7ACgM3ZuAhPqurXHUvR2nWMRcnmzGGPjLK6q4DSTelI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "0fce791ba2334aca183f2ed42399518947550d0d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1703438236,
|
||||
"narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
|
||||
"lastModified": 1708807242,
|
||||
"narHash": "sha256-sRTRkhMD4delO/hPxxi+XwLqPn8BuUq6nnj4JqLwOu0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
|
||||
"rev": "73de017ef2d18a04ac4bfd0c02650007ccb31c2a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -42,6 +65,7 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems",
|
||||
"wlroots": "wlroots",
|
||||
@@ -67,18 +91,18 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1701368958,
|
||||
"narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=",
|
||||
"lastModified": 1708558866,
|
||||
"narHash": "sha256-Mz6hCtommq7RQfcPnxLINigO4RYSNt23HeJHC6mVmWI=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"rev": "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
@@ -87,6 +111,9 @@
|
||||
"hyprland-protocols": [
|
||||
"hyprland-protocols"
|
||||
],
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -95,11 +122,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703514399,
|
||||
"narHash": "sha256-VRr5Xc4S/VPr/gU3fiOD3vSIL2+GJ+LUrmFTWTwnTz4=",
|
||||
"lastModified": 1708696469,
|
||||
"narHash": "sha256-shh5wmpeYy3MmsBfkm4f76yPsBDGk6OLYRVG+ARy2F0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "0a318a7a217a6402b0b705837cd5b50b0e94b31b",
|
||||
"rev": "1b713911c2f12b96c2574474686e4027ac4bf826",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
10
flake.nix
@@ -12,7 +12,7 @@
|
||||
host = "gitlab.freedesktop.org";
|
||||
owner = "wlroots";
|
||||
repo = "wlroots";
|
||||
rev = "5d639394f3e83b01596dcd166a44a9a1a2583350";
|
||||
rev = "0cb091f1a2d345f37d2ee445f4ffd04f7f4ec9e5";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
@@ -22,11 +22,18 @@
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
xdph = {
|
||||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -86,6 +93,7 @@
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
|
||||
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [
|
||||
self.packages.${system}.wlroots-hyprland
|
||||
self.packages.${system}.hyprland
|
||||
|
@@ -51,12 +51,14 @@ commands:
|
||||
setprop
|
||||
splash
|
||||
switchxkblayout
|
||||
systeminfo
|
||||
version
|
||||
workspacerules
|
||||
workspaces
|
||||
|
||||
flags:
|
||||
-j -> output in JSON
|
||||
-r -> refresh state after issuing command (e.g. for updating variables)
|
||||
--batch -> execute a batch of commands, separated by ';'
|
||||
--instance (-i) -> use a specific instance. Can be either signature or index in hyprctl instances (0, 1, etc)
|
||||
)#";
|
||||
@@ -77,7 +79,7 @@ std::vector<SInstanceData> instances() {
|
||||
std::vector<SInstanceData> result;
|
||||
|
||||
for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
|
||||
if (el.is_directory())
|
||||
if (el.is_directory() || !el.path().string().ends_with(".lock"))
|
||||
continue;
|
||||
|
||||
// read lock
|
||||
@@ -85,7 +87,9 @@ std::vector<SInstanceData> instances() {
|
||||
data->id = el.path().string();
|
||||
data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
|
||||
|
||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
||||
try {
|
||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
||||
} catch (std::exception& e) { continue; }
|
||||
|
||||
// read file
|
||||
std::ifstream ifs(el.path().string());
|
||||
@@ -93,7 +97,9 @@ std::vector<SInstanceData> instances() {
|
||||
int i = 0;
|
||||
for (std::string line; std::getline(ifs, line); ++i) {
|
||||
if (i == 0) {
|
||||
data->pid = std::stoull(line);
|
||||
try {
|
||||
data->pid = std::stoull(line);
|
||||
} catch (std::exception& e) { continue; }
|
||||
} else if (i == 1) {
|
||||
data->wlSocket = line;
|
||||
} else
|
||||
@@ -300,6 +306,8 @@ int main(int argc, char** argv) {
|
||||
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
||||
fullArgs += "j";
|
||||
json = true;
|
||||
} else if (ARGS[i] == "-r" && !fullArgs.contains("r")) {
|
||||
fullArgs += "r";
|
||||
} else if (ARGS[i] == "--batch") {
|
||||
fullRequest = "--batch ";
|
||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
||||
@@ -359,7 +367,7 @@ int main(int argc, char** argv) {
|
||||
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
|
||||
if (!ISIG) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)";
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -370,42 +378,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (fullRequest.contains("/--batch"))
|
||||
batchRequest(fullRequest);
|
||||
else if (fullRequest.contains("/monitors"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/clients"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/workspaces"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activeworkspace"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/workspacerules"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activewindow"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/layers"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/version"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/kill"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/splash"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/devices"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/reload"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/getoption"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/binds"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/cursorpos"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/animations"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/globalshortcuts"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/rollinglog"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/switchxkblayout"))
|
||||
request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/seterror"))
|
||||
@@ -426,15 +400,10 @@ int main(int argc, char** argv) {
|
||||
request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/decorations"))
|
||||
request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/layouts"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
printf("%s", USAGE.c_str());
|
||||
else {
|
||||
printf("%s\n", USAGE.c_str());
|
||||
return 1;
|
||||
request(fullRequest);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
@@ -20,11 +20,18 @@ std::string DataState::getDataStatePath() {
|
||||
return std::string{HOME} + "/.local/share/hyprpm";
|
||||
}
|
||||
|
||||
std::string DataState::getHeadersPath() {
|
||||
return getDataStatePath() + "/headersRoot";
|
||||
}
|
||||
|
||||
void DataState::ensureStateStoreExists() {
|
||||
const auto PATH = getDataStatePath();
|
||||
|
||||
if (!std::filesystem::exists(PATH))
|
||||
std::filesystem::create_directories(PATH);
|
||||
|
||||
if (!std::filesystem::exists(getHeadersPath()))
|
||||
std::filesystem::create_directories(getHeadersPath());
|
||||
}
|
||||
|
||||
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||
@@ -47,7 +54,8 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||
|
||||
DATA.emplace(p.name, toml::table{
|
||||
{"filename", p.name + ".so"},
|
||||
{"enabled", p.enabled}
|
||||
{"enabled", p.enabled},
|
||||
{"failed", p.failed}
|
||||
});
|
||||
}
|
||||
// clang-format on
|
||||
@@ -63,7 +71,10 @@ bool DataState::pluginRepoExists(const std::string& urlOrName) {
|
||||
const auto PATH = getDataStatePath();
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||
if (!entry.is_directory())
|
||||
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||
continue;
|
||||
|
||||
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||
continue;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
@@ -84,7 +95,10 @@ void DataState::removePluginRepo(const std::string& urlOrName) {
|
||||
const auto PATH = getDataStatePath();
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||
if (!entry.is_directory())
|
||||
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||
continue;
|
||||
|
||||
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||
continue;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
@@ -153,7 +167,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
||||
std::vector<SPluginRepository> repos;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||
if (!entry.is_directory())
|
||||
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||
continue;
|
||||
|
||||
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||
continue;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
@@ -172,9 +189,10 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
|
||||
continue;
|
||||
|
||||
const auto ENABLED = STATE[key]["enabled"].value_or(false);
|
||||
const auto FAILED = STATE[key]["failed"].value_or(false);
|
||||
const auto FILENAME = STATE[key]["filename"].value_or("");
|
||||
|
||||
repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED});
|
||||
repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED, FAILED});
|
||||
}
|
||||
|
||||
repos.push_back(repo);
|
||||
@@ -189,7 +207,10 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
||||
const auto PATH = getDataStatePath();
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
|
||||
if (!entry.is_directory())
|
||||
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
||||
continue;
|
||||
|
||||
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
|
||||
continue;
|
||||
|
||||
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
|
||||
@@ -201,6 +222,11 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
|
||||
if (key.str() != name)
|
||||
continue;
|
||||
|
||||
const auto FAILED = STATE[key]["failed"].value_or(false);
|
||||
|
||||
if (FAILED)
|
||||
return false;
|
||||
|
||||
(*STATE[key].as_table()).insert_or_assign("enabled", enabled);
|
||||
|
||||
std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
|
||||
|
@@ -10,6 +10,7 @@ struct SGlobalState {
|
||||
|
||||
namespace DataState {
|
||||
std::string getDataStatePath();
|
||||
std::string getHeadersPath();
|
||||
void ensureStateStoreExists();
|
||||
void addNewPluginRepo(const SPluginRepository& repo);
|
||||
void removePluginRepo(const std::string& urlOrName);
|
||||
|
@@ -19,6 +19,7 @@ class CManifest {
|
||||
std::vector<std::string> authors;
|
||||
std::vector<std::string> buildSteps;
|
||||
std::string output;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
struct {
|
||||
|
@@ -6,7 +6,8 @@
|
||||
struct SPlugin {
|
||||
std::string name;
|
||||
std::string filename;
|
||||
bool enabled;
|
||||
bool enabled = false;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
struct SPluginRepository {
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
@@ -78,6 +79,8 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||
|
||||
bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (DataState::pluginRepoExists(url)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||
return false;
|
||||
@@ -170,6 +173,22 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||
message += " version " + pl.version;
|
||||
progress.printMessageAbove(message);
|
||||
}
|
||||
|
||||
if (!pManifest->m_sRepository.commitPins.empty()) {
|
||||
// check commit pins
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
|
||||
execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin);
|
||||
}
|
||||
}
|
||||
|
||||
progress.m_szCurrentMessage = "Verifying headers";
|
||||
progress.print();
|
||||
|
||||
@@ -191,16 +210,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
out += execAndGet("cd /tmp/hyprpm/new && " + bs) + "\n";
|
||||
std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n";
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n");
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
|
||||
return false;
|
||||
p.failed = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output);
|
||||
@@ -220,7 +242,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) {
|
||||
repo.url = url;
|
||||
repo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false});
|
||||
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed});
|
||||
}
|
||||
DataState::addNewPluginRepo(repo);
|
||||
|
||||
@@ -263,8 +285,12 @@ bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
|
||||
eHeadersErrors CPluginManager::headersValid() {
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
|
||||
return HEADERS_MISSING;
|
||||
|
||||
// find headers commit
|
||||
auto headers = execAndGet("pkg-config --cflags --keep-system-cflags hyprland");
|
||||
std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkg-config --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
|
||||
auto headers = execAndGet(cmd.c_str());
|
||||
|
||||
if (!headers.contains("-I/"))
|
||||
return HEADERS_MISSING;
|
||||
@@ -296,10 +322,6 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||
if (!ifs.good())
|
||||
return HEADERS_CORRUPTED;
|
||||
|
||||
if ((std::filesystem::exists("/usr/include/hyprland/src/version.h") && verHeader != "/usr/include/hyprland/src/version.h") ||
|
||||
(std::filesystem::exists("/usr/local/include/hyprland/src/version.h") && verHeader != "/usr/local/include/hyprland/src/version.h"))
|
||||
return HEADERS_DUPLICATED;
|
||||
|
||||
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
ifs.close();
|
||||
|
||||
@@ -314,7 +336,9 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||
return HEADERS_OK;
|
||||
}
|
||||
|
||||
bool CPluginManager::updateHeaders() {
|
||||
bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
DataState::ensureStateStoreExists();
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
@@ -323,11 +347,8 @@ bool CPluginManager::updateHeaders() {
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
}
|
||||
|
||||
if (headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Your headers are already up-to-date.\n";
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
if (!force && headersValid() == HEADERS_OK) {
|
||||
std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Headers up to date.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -369,23 +390,38 @@ bool CPluginManager::updateHeaders() {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
|
||||
|
||||
ret = execAndGet("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||
|
||||
ret = execAndGet(
|
||||
std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja",
|
||||
DataState::getHeadersPath()));
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||
|
||||
// le hack. Wlroots has to generate its build/include
|
||||
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
progress.print();
|
||||
|
||||
progress.printMessageAbove(
|
||||
std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
||||
" in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
||||
// progress.printMessageAbove(
|
||||
// std::string{Colors::YELLOW} + "!" + Colors::RESET +
|
||||
// " in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running.");
|
||||
|
||||
ret = execAndGet("pkexec sh \"-c\" \"cd /tmp/hyprpm/hyprland && make installheaders\"");
|
||||
std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders",
|
||||
DataState::getHeadersPath());
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||
|
||||
ret = execAndGet(cmd);
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "pkexec returned: " << ret << "\n";
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||
@@ -397,10 +433,6 @@ bool CPluginManager::updateHeaders() {
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||
@@ -434,7 +466,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
CProgressBar progress;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 1;
|
||||
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
|
||||
progress.m_iSteps = 0;
|
||||
progress.m_szCurrentMessage = "Updating repositories";
|
||||
progress.print();
|
||||
@@ -528,7 +560,8 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
out += execAndGet("cd /tmp/hyprpm/update && " + bs) + "\n";
|
||||
std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
||||
@@ -566,6 +599,14 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||
}
|
||||
|
||||
progress.m_iSteps++;
|
||||
progress.m_szCurrentMessage = "Updating global state...";
|
||||
progress.print();
|
||||
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
GLOBALSTATE.headersHashCompiled = HLVER.hash;
|
||||
DataState::updateGlobalState(GLOBALSTATE);
|
||||
|
||||
progress.m_iSteps++;
|
||||
progress.m_szCurrentMessage = "Done!";
|
||||
progress.print();
|
||||
@@ -696,8 +737,13 @@ void CPluginManager::listAllPlugins() {
|
||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
|
||||
for (auto& p : r.plugins) {
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name + "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false")
|
||||
<< Colors::RESET << "\n";
|
||||
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||
|
||||
if (!p.failed)
|
||||
std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n";
|
||||
else
|
||||
std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ class CPluginManager {
|
||||
bool removePluginRepo(const std::string& urlOrName);
|
||||
|
||||
eHeadersErrors headersValid();
|
||||
bool updateHeaders();
|
||||
bool updateHeaders(bool force = false);
|
||||
bool updatePlugins(bool forceUpdateAll);
|
||||
|
||||
void listAllPlugins();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "progress/CProgressBar.hpp"
|
||||
#include "helpers/Colors.hpp"
|
||||
#include "core/PluginManager.hpp"
|
||||
#include "core/DataState.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -23,6 +24,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail)
|
||||
┣ --help | -h → Show this menu
|
||||
┣ --verbose | -v → Enable too much logging
|
||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||
┗
|
||||
)#";
|
||||
|
||||
@@ -38,7 +40,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, verbose = false;
|
||||
bool notify = false, verbose = false, force = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
@@ -49,6 +51,9 @@ int main(int argc, char** argv, char** envp) {
|
||||
notify = true;
|
||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||
verbose = true;
|
||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||
force = true;
|
||||
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||
} else {
|
||||
std::cerr << "Unrecognized option " << ARGS[i];
|
||||
return 1;
|
||||
@@ -82,9 +87,13 @@ int main(int argc, char** argv, char** envp) {
|
||||
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
|
||||
} else if (command[0] == "update") {
|
||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
||||
bool headers = g_pPluginManager->updateHeaders();
|
||||
bool headers = g_pPluginManager->updateHeaders(force);
|
||||
if (headers) {
|
||||
bool ret1 = g_pPluginManager->updatePlugins(!headersValid);
|
||||
const auto HLVER = g_pPluginManager->getHyprlandVersion();
|
||||
auto GLOBALSTATE = DataState::getGlobalState();
|
||||
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
|
||||
|
||||
bool ret1 = g_pPluginManager->updatePlugins(!headersValid || force || COMPILEDOUTDATED);
|
||||
|
||||
if (!ret1)
|
||||
return 1;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
cairo,
|
||||
git,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
jq,
|
||||
libGL,
|
||||
libdrm,
|
||||
@@ -75,6 +76,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
cairo
|
||||
git
|
||||
hyprland-protocols
|
||||
hyprlang
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
|
@@ -10,21 +10,19 @@
|
||||
(builtins.substring 4 2 longDate)
|
||||
(builtins.substring 6 2 longDate)
|
||||
]);
|
||||
|
||||
mkJoinedOverlays = overlays: final: prev:
|
||||
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
|
||||
in {
|
||||
# Contains what a user is most likely to care about:
|
||||
# Hyprland itself, XDPH and the Share Picker.
|
||||
default = mkJoinedOverlays (with self.overlays; [
|
||||
default = lib.composeManyExtensions (with self.overlays; [
|
||||
hyprland-packages
|
||||
hyprland-extras
|
||||
]);
|
||||
|
||||
# Packages for variations of Hyprland, dependencies included.
|
||||
hyprland-packages = mkJoinedOverlays [
|
||||
hyprland-packages = lib.composeManyExtensions [
|
||||
# Dependencies
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
self.overlays.wlroots-hyprland
|
||||
self.overlays.udis86
|
||||
# Hyprland packages themselves
|
||||
@@ -34,9 +32,9 @@ in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
wlroots = final.wlroots-hyprland;
|
||||
commit = self.rev or "";
|
||||
inherit (final) udis86 hyprland-protocols;
|
||||
wlroots = final.wlroots-hyprland; # explicit override until decided on breaking change of the name
|
||||
udis86 = final.udis86-hyprland; # explicit override until decided on breaking change of the name
|
||||
inherit date;
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
@@ -59,12 +57,12 @@ in {
|
||||
|
||||
# Packages for extra software recommended for usage with Hyprland,
|
||||
# including forked or patched packages for compatibility.
|
||||
hyprland-extras = mkJoinedOverlays [
|
||||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
udis86 = final: prev: {
|
||||
udis86 = final.callPackage ./udis86.nix {};
|
||||
udis86-hyprland = final.callPackage ./udis86.nix {};
|
||||
};
|
||||
|
||||
# Patched version of wlroots for Hyprland.
|
||||
|
@@ -34,16 +34,17 @@ index 1d2c7f9f..c5ef4e67 100644
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 0af864b9..38723b8c 100644
|
||||
index 45701f5f..3505cefe 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -9,16 +9,16 @@ executable('Hyprland', src,
|
||||
@@ -9,17 +9,17 @@ executable('Hyprland', src,
|
||||
server_protos,
|
||||
dependency('wayland-server'),
|
||||
dependency('wayland-client'),
|
||||
- wlroots.get_variable('wlroots'),
|
||||
+ dependency('wlroots'),
|
||||
dependency('cairo'),
|
||||
dependency('hyprlang', version: '>= 0.3.2'),
|
||||
dependency('libdrm'),
|
||||
dependency('egl'),
|
||||
dependency('xkbcommon'),
|
||||
|
@@ -8,7 +8,7 @@ CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
echo "Updating wlroots..."
|
||||
# update wlroots to submodule revision
|
||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix subprojects/wlroots.wrap
|
||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
|
||||
nix flake lock
|
||||
|
||||
echo "wlroots: $CRT_REV -> $SUB_REV"
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.34.0"
|
||||
"version": "0.36.0"
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
wayland_protos = dependency('wayland-protocols',
|
||||
version: '>=1.25',
|
||||
version: '>=1.32',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
|
@@ -81,26 +81,6 @@ CCompositor::CCompositor() {
|
||||
|
||||
CCompositor::~CCompositor() {
|
||||
cleanup();
|
||||
g_pDecorationPositioner.reset();
|
||||
g_pPluginSystem.reset();
|
||||
g_pHyprNotificationOverlay.reset();
|
||||
g_pDebugOverlay.reset();
|
||||
g_pEventManager.reset();
|
||||
g_pSessionLockManager.reset();
|
||||
g_pProtocolManager.reset();
|
||||
g_pXWaylandManager.reset();
|
||||
g_pHyprRenderer.reset();
|
||||
g_pHyprOpenGL.reset();
|
||||
g_pInputManager.reset();
|
||||
g_pThreadManager.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pLayoutManager.reset();
|
||||
g_pHyprError.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pAnimationManager.reset();
|
||||
g_pKeybindManager.reset();
|
||||
g_pHookSystem.reset();
|
||||
g_pWatchdog.reset();
|
||||
}
|
||||
|
||||
void CCompositor::setRandomSplash() {
|
||||
@@ -119,8 +99,11 @@ void CCompositor::initServer() {
|
||||
|
||||
// register crit signal handler
|
||||
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||
signal(SIGABRT, handleUnrecoverableSignal);
|
||||
|
||||
if (!envEnabled("HYPRLAND_NO_CRASHREPORTER")) {
|
||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||
signal(SIGABRT, handleUnrecoverableSignal);
|
||||
}
|
||||
signal(SIGUSR1, handleUserSignal);
|
||||
|
||||
initManagers(STAGE_PRIORITY);
|
||||
@@ -135,10 +118,10 @@ void CCompositor::initServer() {
|
||||
else
|
||||
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
||||
|
||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession);
|
||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession);
|
||||
|
||||
if (!m_sWLRBackend) {
|
||||
Debug::log(CRIT, "m_sWLRBackend was NULL!");
|
||||
Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||
throwError("wlr_backend_autocreate() failed!");
|
||||
}
|
||||
|
||||
@@ -151,7 +134,7 @@ void CCompositor::initServer() {
|
||||
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
|
||||
|
||||
if (!m_sWLRRenderer) {
|
||||
Debug::log(CRIT, "m_sWLRRenderer was NULL!");
|
||||
Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
||||
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
||||
}
|
||||
|
||||
@@ -259,7 +242,7 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLDisplay);
|
||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
||||
|
||||
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
@@ -324,6 +307,7 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
|
||||
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
|
||||
addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr");
|
||||
addWLSignal(&m_sWLRKbShInhibitMgr->events.new_inhibitor, &Events::listen_newShortcutInhibitor, m_sWLRKbShInhibitMgr, "ShortcutInhibitMgr");
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
||||
@@ -332,10 +316,67 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
||||
}
|
||||
|
||||
void CCompositor::removeAllSignals() {
|
||||
removeWLSignal(&Events::listen_newOutput);
|
||||
removeWLSignal(&Events::listen_newXDGToplevel);
|
||||
removeWLSignal(&Events::listen_mouseMove);
|
||||
removeWLSignal(&Events::listen_mouseMoveAbsolute);
|
||||
removeWLSignal(&Events::listen_mouseButton);
|
||||
removeWLSignal(&Events::listen_mouseAxis);
|
||||
removeWLSignal(&Events::listen_mouseFrame);
|
||||
removeWLSignal(&Events::listen_swipeBegin);
|
||||
removeWLSignal(&Events::listen_swipeUpdate);
|
||||
removeWLSignal(&Events::listen_swipeEnd);
|
||||
removeWLSignal(&Events::listen_pinchBegin);
|
||||
removeWLSignal(&Events::listen_pinchUpdate);
|
||||
removeWLSignal(&Events::listen_pinchEnd);
|
||||
removeWLSignal(&Events::listen_touchBegin);
|
||||
removeWLSignal(&Events::listen_touchEnd);
|
||||
removeWLSignal(&Events::listen_touchUpdate);
|
||||
removeWLSignal(&Events::listen_touchFrame);
|
||||
removeWLSignal(&Events::listen_holdBegin);
|
||||
removeWLSignal(&Events::listen_holdEnd);
|
||||
removeWLSignal(&Events::listen_newInput);
|
||||
removeWLSignal(&Events::listen_requestMouse);
|
||||
removeWLSignal(&Events::listen_requestSetSel);
|
||||
removeWLSignal(&Events::listen_requestDrag);
|
||||
removeWLSignal(&Events::listen_startDrag);
|
||||
removeWLSignal(&Events::listen_requestSetSel);
|
||||
removeWLSignal(&Events::listen_requestSetPrimarySel);
|
||||
removeWLSignal(&Events::listen_newLayerSurface);
|
||||
removeWLSignal(&Events::listen_change);
|
||||
removeWLSignal(&Events::listen_outputMgrApply);
|
||||
removeWLSignal(&Events::listen_outputMgrTest);
|
||||
removeWLSignal(&Events::listen_newConstraint);
|
||||
removeWLSignal(&Events::listen_NewXDGDeco);
|
||||
removeWLSignal(&Events::listen_newVirtPtr);
|
||||
removeWLSignal(&Events::listen_newVirtualKeyboard);
|
||||
removeWLSignal(&Events::listen_RendererDestroy);
|
||||
removeWLSignal(&Events::listen_newIdleInhibitor);
|
||||
removeWLSignal(&Events::listen_powerMgrSetMode);
|
||||
removeWLSignal(&Events::listen_newIME);
|
||||
removeWLSignal(&Events::listen_newTextInput);
|
||||
removeWLSignal(&Events::listen_activateXDG);
|
||||
removeWLSignal(&Events::listen_newSessionLock);
|
||||
removeWLSignal(&Events::listen_setGamma);
|
||||
removeWLSignal(&Events::listen_setCursorShape);
|
||||
removeWLSignal(&Events::listen_newTearingHint);
|
||||
removeWLSignal(&Events::listen_newShortcutInhibitor);
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
removeWLSignal(&Events::listen_leaseRequest);
|
||||
|
||||
if (m_sWLRSession)
|
||||
removeWLSignal(&Events::listen_sessionActive);
|
||||
}
|
||||
|
||||
void CCompositor::cleanup() {
|
||||
if (!m_sWLDisplay || m_bIsShuttingDown)
|
||||
return;
|
||||
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
|
||||
removeLockFile();
|
||||
|
||||
m_bIsShuttingDown = true;
|
||||
@@ -362,8 +403,8 @@ void CCompositor::cleanup() {
|
||||
for (auto& m : m_vMonitors) {
|
||||
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
||||
|
||||
wlr_output_enable(m->output, false);
|
||||
wlr_output_commit(m->output);
|
||||
wlr_output_state_set_enabled(m->state.wlr(), false);
|
||||
m->state.commit();
|
||||
}
|
||||
|
||||
m_vMonitors.clear();
|
||||
@@ -373,8 +414,32 @@ void CCompositor::cleanup() {
|
||||
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
||||
}
|
||||
|
||||
removeAllSignals();
|
||||
|
||||
g_pInputManager.reset();
|
||||
|
||||
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
||||
|
||||
g_pDecorationPositioner.reset();
|
||||
g_pPluginSystem.reset();
|
||||
g_pHyprNotificationOverlay.reset();
|
||||
g_pDebugOverlay.reset();
|
||||
g_pEventManager.reset();
|
||||
g_pSessionLockManager.reset();
|
||||
g_pProtocolManager.reset();
|
||||
g_pHyprRenderer.reset();
|
||||
g_pHyprOpenGL.reset();
|
||||
g_pThreadManager.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pLayoutManager.reset();
|
||||
g_pHyprError.reset();
|
||||
g_pConfigManager.reset();
|
||||
g_pAnimationManager.reset();
|
||||
g_pKeybindManager.reset();
|
||||
g_pHookSystem.reset();
|
||||
g_pWatchdog.reset();
|
||||
g_pXWaylandManager.reset();
|
||||
|
||||
wl_display_terminate(m_sWLDisplay);
|
||||
|
||||
m_sWLDisplay = nullptr;
|
||||
@@ -408,6 +473,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
Debug::log(LOG, "Creating the ThreadManager!");
|
||||
g_pThreadManager = std::make_unique<CThreadManager>();
|
||||
|
||||
Debug::log(LOG, "Creating CHyprCtl");
|
||||
g_pHyprCtl = std::make_unique<CHyprCtl>();
|
||||
|
||||
Debug::log(LOG, "Creating the InputManager!");
|
||||
g_pInputManager = std::make_unique<CInputManager>();
|
||||
|
||||
@@ -629,72 +697,32 @@ bool CCompositor::windowExists(CWindow* pWindow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
bool CCompositor::monitorExists(CMonitor* pMonitor) {
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if (m.get() == pMonitor)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreWindow) {
|
||||
CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, CWindow* pIgnoreWindow) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border");
|
||||
static auto* const PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size");
|
||||
static auto* const PBORDERGRABEXTEND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area");
|
||||
static auto* const PSPECIALFALLTHRU = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough");
|
||||
const auto BORDER_GRAB_AREA = **PRESIZEONBORDER ? **PBORDERSIZE + **PBORDERGRABEXTEND : 0;
|
||||
|
||||
// pinned windows on top of floating regardless
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto windowForWorkspace = [&](bool special) -> CWindow* {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
if (properties & ALLOW_FLOATING) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
|
||||
if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular
|
||||
continue;
|
||||
|
||||
const auto BB = w->getWindowInputBox();
|
||||
const auto BB = w->getWindowBoxUnified(properties);
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
continue;
|
||||
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
||||
|
||||
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
||||
// Override Redirect
|
||||
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
||||
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
||||
}
|
||||
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
||||
w.get() != pIgnoreWindow) {
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
if (w->hasPopupAt(pos))
|
||||
@@ -702,6 +730,53 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto windowForWorkspace = [&](bool special) -> CWindow* {
|
||||
auto floating = [&](bool aboveFullscreen) -> CWindow* {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
|
||||
if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular
|
||||
continue;
|
||||
|
||||
const auto BB = w->getWindowBoxUnified(properties);
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
||||
w.get() != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
continue;
|
||||
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
||||
|
||||
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
||||
// Override Redirect
|
||||
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
||||
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
||||
}
|
||||
|
||||
return w.get();
|
||||
}
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (properties & ALLOW_FLOATING) {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
auto found = floating(true);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
if (properties & FLOATING_ONLY)
|
||||
return floating(false);
|
||||
|
||||
const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID);
|
||||
@@ -709,13 +784,17 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
auto found = floating(false);
|
||||
if (found)
|
||||
return found;
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
for (auto& w : m_vWindows) {
|
||||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow) {
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
@@ -725,9 +804,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
CBox box = {w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow)
|
||||
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -735,68 +814,17 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW
|
||||
};
|
||||
|
||||
// special workspace
|
||||
if (PMONITOR->specialWorkspaceID)
|
||||
if (PMONITOR->specialWorkspaceID && !**PSPECIALFALLTHRU)
|
||||
return windowForWorkspace(true);
|
||||
|
||||
return windowForWorkspace(false);
|
||||
}
|
||||
|
||||
CWindow* CCompositor::windowFromCursor() {
|
||||
const auto PMONITOR = getMonitorFromCursor();
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) &&
|
||||
!w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
const auto PWINDOW = windowForWorkspace(true);
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
if (PWINDOW)
|
||||
return PWINDOW;
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() &&
|
||||
!w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return windowForWorkspace(false);
|
||||
}
|
||||
|
||||
wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pWindow, Vector2D& sl) {
|
||||
@@ -874,15 +902,31 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) {
|
||||
for (auto& m : m_vRealMonitors) {
|
||||
if (m->output == out) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
static auto* const PSPECIALFALLTHROUGH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:special_fallthrough");
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
||||
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pInputManager->m_dExclusiveLSes.empty()) {
|
||||
Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
||||
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
@@ -917,7 +961,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bNoFocus) {
|
||||
if (pWindow->m_sAdditionalConfigData.noFocus) {
|
||||
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
||||
return;
|
||||
}
|
||||
@@ -928,12 +972,13 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
if (pWindow->m_bPinned)
|
||||
pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace;
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID)) {
|
||||
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
// This is to fix incorrect feedback on the focus history.
|
||||
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
PWORKSPACE->m_pLastFocusedWindow = pWindow;
|
||||
PWORKSPACE->rememberPrevWorkspace(getWorkspaceByID(m_pLastMonitor->activeWorkspace));
|
||||
const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
PMONITOR->changeWorkspace(PWORKSPACE, false, true);
|
||||
// changeworkspace already calls focusWindow
|
||||
return;
|
||||
@@ -942,6 +987,11 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
const auto PLASTWINDOW = m_pLastWindow;
|
||||
m_pLastWindow = pWindow;
|
||||
|
||||
/* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which
|
||||
window focuses are "via keybinds" and which ones aren't. */
|
||||
if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !pWindow->m_bPinned && !**PSPECIALFALLTHROUGH)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
|
||||
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
||||
if (windowValidMapped(PLASTWINDOW)) {
|
||||
PLASTWINDOW->updateDynamicRules();
|
||||
@@ -1006,7 +1056,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
}
|
||||
|
||||
if (*PFOLLOWMOUSE == 0)
|
||||
if (**PFOLLOWMOUSE == 0)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
}
|
||||
|
||||
@@ -1015,10 +1065,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == pWindowOwner->m_pWLSurface.wlr()))
|
||||
return; // Don't focus when already focused on this.
|
||||
|
||||
if (g_pSessionLockManager->isSessionLocked()) {
|
||||
wlr_seat_keyboard_clear_focus(m_sSeat.seat);
|
||||
m_pLastFocus = nullptr;
|
||||
}
|
||||
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
||||
return;
|
||||
|
||||
// Unfocus last surface if should
|
||||
if (m_pLastFocus && !pWindowOwner)
|
||||
@@ -1089,14 +1137,6 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<
|
||||
|
||||
auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
||||
|
||||
if (ls->layerSurface->current.keyboard_interactive && ls->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
|
||||
if (!SURFACEAT)
|
||||
SURFACEAT = ls->layerSurface->surface;
|
||||
|
||||
*ppLayerSurfaceFound = ls.get();
|
||||
return SURFACEAT;
|
||||
}
|
||||
|
||||
if (SURFACEAT) {
|
||||
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
||||
continue;
|
||||
@@ -1483,7 +1523,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
return nullptr;
|
||||
|
||||
// 0 -> history, 1 -> shared length
|
||||
static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue;
|
||||
static auto* const PMETHOD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
@@ -1545,7 +1585,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (**PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
|
||||
// get idx
|
||||
@@ -1639,7 +1679,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
||||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -1647,7 +1687,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
||||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -1668,7 +1708,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
||||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -1676,7 +1716,7 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO
|
||||
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
||||
continue;
|
||||
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
|
||||
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -1764,8 +1804,15 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||
const auto POSA = m_pLastMonitor->vecPosition;
|
||||
const auto SIZEA = m_pLastMonitor->vecSize;
|
||||
return this->getMonitorInDirection(m_pLastMonitor, dir);
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const char& dir) {
|
||||
if (!pSourceMonitor)
|
||||
return nullptr;
|
||||
|
||||
const auto POSA = pSourceMonitor->vecPosition;
|
||||
const auto SIZEA = pSourceMonitor->vecSize;
|
||||
|
||||
auto longestIntersect = -1;
|
||||
CMonitor* longestIntersectMonitor = nullptr;
|
||||
@@ -1844,21 +1891,30 @@ void CCompositor::updateWorkspaceWindows(const int64_t& id) {
|
||||
|
||||
void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
// optimization
|
||||
static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get();
|
||||
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
||||
static auto* const NOGROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active")->data.get();
|
||||
static auto* const NOGROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border")->data.get();
|
||||
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_active")->data.get();
|
||||
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive")->data.get();
|
||||
static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active")->data.get();
|
||||
static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive")->data.get();
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
||||
static auto* const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
|
||||
static auto* const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue;
|
||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto* const PDIMENABLED = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue;
|
||||
static auto* const PACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.active_border");
|
||||
static auto* const PINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border");
|
||||
static auto* const PNOGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active");
|
||||
static auto* const PNOGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border");
|
||||
static auto* const PGROUPACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_active");
|
||||
static auto* const PGROUPINACTIVECOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive");
|
||||
static auto* const PGROUPACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active");
|
||||
static auto* const PGROUPINACTIVELOCKEDCOL = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive");
|
||||
static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity");
|
||||
static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity");
|
||||
static auto* const PFULLSCREENALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity");
|
||||
static auto* const PSHADOWCOL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow");
|
||||
static auto* const PSHADOWCOLINACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive");
|
||||
static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength");
|
||||
static auto* const PDIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_inactive");
|
||||
|
||||
auto* const ACTIVECOL = (CGradientValueData*)(*PACTIVECOL)->getData();
|
||||
auto* const INACTIVECOL = (CGradientValueData*)(*PINACTIVECOL)->getData();
|
||||
auto* const NOGROUPACTIVECOL = (CGradientValueData*)(*PNOGROUPACTIVECOL)->getData();
|
||||
auto* const NOGROUPINACTIVECOL = (CGradientValueData*)(*PNOGROUPINACTIVECOL)->getData();
|
||||
auto* const GROUPACTIVECOL = (CGradientValueData*)(*PGROUPACTIVECOL)->getData();
|
||||
auto* const GROUPINACTIVECOL = (CGradientValueData*)(*PGROUPINACTIVECOL)->getData();
|
||||
auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPACTIVELOCKEDCOL)->getData();
|
||||
auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)(*PGROUPINACTIVELOCKEDCOL)->getData();
|
||||
|
||||
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
||||
if (grad == pWindow->m_cRealBorderColor)
|
||||
@@ -1879,15 +1935,13 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
if (pWindow == m_pLastWindow) {
|
||||
const auto* const ACTIVECOLOR =
|
||||
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ?
|
||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) :
|
||||
*ACTIVECOLOR);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying().m_vColors.empty() ? *ACTIVECOLOR :
|
||||
pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying());
|
||||
} else {
|
||||
const auto* const INACTIVECOLOR =
|
||||
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ?
|
||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) :
|
||||
*INACTIVECOLOR);
|
||||
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying().m_vColors.empty() ? *INACTIVECOLOR :
|
||||
pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1898,31 +1952,31 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
// opacity
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
|
||||
pWindow->m_fActiveInactiveAlpha = **PFULLSCREENALPHA;
|
||||
} else {
|
||||
if (pWindow == m_pLastWindow)
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alpha.toUnderlying() :
|
||||
pWindow->m_sSpecialRenderData.alpha.toUnderlying() * *PACTIVEALPHA;
|
||||
pWindow->m_sSpecialRenderData.alpha.toUnderlying() * **PACTIVEALPHA;
|
||||
else
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() != -1 ?
|
||||
(pWindow->m_sSpecialRenderData.alphaInactiveOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() :
|
||||
pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * *PINACTIVEALPHA) :
|
||||
*PINACTIVEALPHA;
|
||||
pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * **PINACTIVEALPHA) :
|
||||
**PINACTIVEALPHA;
|
||||
}
|
||||
|
||||
// dim
|
||||
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) {
|
||||
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !**PDIMENABLED) {
|
||||
pWindow->m_fDimPercent = 0;
|
||||
} else {
|
||||
pWindow->m_fDimPercent = *PDIMSTRENGTH;
|
||||
pWindow->m_fDimPercent = **PDIMSTRENGTH;
|
||||
}
|
||||
|
||||
// shadow
|
||||
if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) {
|
||||
if (pWindow == m_pLastWindow) {
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CColor(**PSHADOWCOL);
|
||||
} else {
|
||||
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
||||
pWindow->m_cRealShadowColor = CColor(**PSHADOWCOLINACTIVE != INT_MAX ? **PSHADOWCOLINACTIVE : **PSHADOWCOL);
|
||||
}
|
||||
} else {
|
||||
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
|
||||
@@ -2014,7 +2068,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACEB);
|
||||
updateFullscreenFadeOnWorkspace(PWORKSPACEA);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
if (pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID || pMonitorB->ID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
const auto LASTWIN = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow();
|
||||
g_pCompositor->focusWindow(LASTWIN ? LASTWIN :
|
||||
(g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)));
|
||||
}
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
||||
@@ -2024,7 +2082,11 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
if (name[0] == '+' || name[0] == '-') {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
else if (isDirection(name))
|
||||
return getMonitorInDirection(name[0]);
|
||||
else if (name[0] == '+' || name[0] == '-') {
|
||||
// relative
|
||||
|
||||
if (m_vMonitors.size() == 1)
|
||||
@@ -2079,39 +2141,21 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
|
||||
return nullptr;
|
||||
}
|
||||
} else if (name.starts_with("desc:")) {
|
||||
const auto DESCRIPTION = name.substr(5);
|
||||
|
||||
} else {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
if (m->szDescription.starts_with(DESCRIPTION)) {
|
||||
if (m->matchesStaticSelector(name)) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
} else {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
|
||||
if (isDirection(name)) {
|
||||
const auto PMONITOR = getMonitorInDirection(name[0]);
|
||||
return PMONITOR;
|
||||
} else {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->szName == name) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) {
|
||||
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor, bool noWarpCursor) {
|
||||
|
||||
// We trust the workspace and monitor to be correct.
|
||||
|
||||
@@ -2126,7 +2170,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
|
||||
// fix old mon
|
||||
int nextWorkspaceOnMonitorID = -1;
|
||||
if (!SWITCHINGISACTIVE)
|
||||
if (!SWITCHINGISACTIVE || !POLDMON)
|
||||
nextWorkspaceOnMonitorID = pWorkspace->m_iID;
|
||||
else {
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
@@ -2151,7 +2195,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
}
|
||||
|
||||
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing {}", nextWorkspaceOnMonitorID);
|
||||
POLDMON->changeWorkspace(nextWorkspaceOnMonitorID);
|
||||
POLDMON->changeWorkspace(nextWorkspaceOnMonitorID, false, true, true);
|
||||
}
|
||||
|
||||
// move the workspace
|
||||
@@ -2192,12 +2236,14 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
|
||||
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
|
||||
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
|
||||
|
||||
setActiveMonitor(pMonitor);
|
||||
pMonitor->activeWorkspace = pWorkspace->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
|
||||
|
||||
pWorkspace->startAnim(true, true, true);
|
||||
|
||||
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||
if (!noWarpCursor)
|
||||
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
}
|
||||
@@ -2284,7 +2330,6 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState());
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
@@ -2417,9 +2462,9 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) {
|
||||
// warpCursorTo should only be used for warps that
|
||||
// should be disabled with no_cursor_warps
|
||||
|
||||
static auto* const PNOWARPS = &g_pConfigManager->getConfigValuePtr("general:no_cursor_warps")->intValue;
|
||||
static auto* const PNOWARPS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_cursor_warps");
|
||||
|
||||
if (*PNOWARPS && !force)
|
||||
if (**PNOWARPS && !force)
|
||||
return;
|
||||
|
||||
if (!m_sSeat.mouse)
|
||||
@@ -2585,7 +2630,7 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
|
||||
|
||||
const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + PWORKSPACE->m_szName});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + (PWORKSPACE ? PWORKSPACE->m_szName : "?")});
|
||||
EMIT_HOOK_EVENT("focusedMon", pMonitor);
|
||||
m_pLastMonitor = pMonitor;
|
||||
}
|
||||
@@ -2606,11 +2651,7 @@ int CCompositor::getNewSpecialID() {
|
||||
}
|
||||
|
||||
void CCompositor::performUserChecks() {
|
||||
if (g_pConfigManager->getInt("general:allow_tearing") == 1 && !envEnabled("WLR_DRM_NO_ATOMIC")) {
|
||||
g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding "
|
||||
"env = WLR_DRM_NO_ATOMIC,1 to your config.",
|
||||
CColor(0), 15000, ICON_WARNING);
|
||||
}
|
||||
; // intentional
|
||||
}
|
||||
|
||||
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) {
|
||||
@@ -2686,7 +2727,7 @@ void CCompositor::setIdleActivityInhibit(bool enabled) {
|
||||
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
||||
}
|
||||
void CCompositor::arrangeMonitors() {
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
|
||||
std::vector<CMonitor*> toArrange;
|
||||
std::vector<CMonitor*> arranged;
|
||||
@@ -2735,9 +2776,9 @@ void CCompositor::arrangeMonitors() {
|
||||
for (auto& m : m_vMonitors) {
|
||||
Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {:.2f}]", m->szName, maxOffset, 0.f);
|
||||
m->vecXWaylandPosition = {maxOffset, 0};
|
||||
maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
|
||||
maxOffset += (**PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
|
||||
|
||||
if (*PXWLFORCESCALEZERO)
|
||||
if (**PXWLFORCESCALEZERO)
|
||||
m->xwaylandScale = m->scale;
|
||||
else
|
||||
m->xwaylandScale = 1.f;
|
||||
@@ -2785,10 +2826,27 @@ void CCompositor::leaveUnsafeState() {
|
||||
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
||||
|
||||
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||
if (!PSURFACE) {
|
||||
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
PSURFACE->m_fLastScale = scale;
|
||||
PSURFACE->m_iLastScale = static_cast<int32_t>(std::ceil(scale));
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||
|
||||
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||
if (!PSURFACE) {
|
||||
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
PSURFACE->m_eLastTransform = transform;
|
||||
}
|
||||
|
||||
void CCompositor::updateSuspendedStates() {
|
||||
|
@@ -135,15 +135,14 @@ class CCompositor {
|
||||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||
bool windowExists(CWindow*);
|
||||
bool windowValidMapped(CWindow*);
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||
bool monitorExists(CMonitor*);
|
||||
CWindow* vectorToWindowUnified(const Vector2D&, uint8_t properties, CWindow* pIgnoreWindow = nullptr);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||
CWindow* windowFromCursor();
|
||||
CWindow* windowFloatingFromCursor();
|
||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
||||
CWindow* getWindowFromSurface(wlr_surface*);
|
||||
CWindow* getWindowFromHandle(uint32_t);
|
||||
@@ -172,11 +171,12 @@ class CCompositor {
|
||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CWindow* getConstraintWindow(SMouse*);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
@@ -214,6 +214,7 @@ class CCompositor {
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void removeAllSignals();
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include <functional>
|
||||
|
||||
enum eIcons {
|
||||
ICON_WARNING = 0,
|
||||
@@ -52,4 +53,20 @@ struct SWindowDecorationExtents {
|
||||
bool operator==(const SWindowDecorationExtents& other) const {
|
||||
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
||||
}
|
||||
};
|
||||
|
||||
void addExtents(const SWindowDecorationExtents& other) {
|
||||
topLeft = topLeft.getComponentMax(other.topLeft);
|
||||
bottomRight = bottomRight.getComponentMax(other.bottomRight);
|
||||
}
|
||||
};
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
|
||||
struct SHyprCtlCommand {
|
||||
std::string name = "";
|
||||
bool exact = true;
|
||||
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||
};
|
||||
|
137
src/Window.cpp
@@ -139,35 +139,25 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowInputBox() {
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||
SWindowDecorationExtents EXTENTS = {{0, 0}, {0, 0}};
|
||||
if (properties & RESERVED_EXTENTS)
|
||||
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(this));
|
||||
if (properties & INPUT_EXTENTS)
|
||||
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(this, true));
|
||||
if (properties & FULL_EXTENTS)
|
||||
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(this, false));
|
||||
|
||||
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this, true);
|
||||
CBox box = {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y};
|
||||
box.addExtents(EXTENTS);
|
||||
|
||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
|
||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
|
||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
|
||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
|
||||
// Add extents to the real base BB and return
|
||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
return box;
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowMainSurfaceBox() {
|
||||
@@ -318,7 +308,7 @@ void CWindow::destroyToplevelHandle() {
|
||||
}
|
||||
|
||||
void CWindow::updateToplevel() {
|
||||
updateSurfaceOutputs();
|
||||
updateSurfaceScaleTransformDetails();
|
||||
|
||||
if (!m_phForeignToplevel)
|
||||
return;
|
||||
@@ -345,8 +335,8 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||
wlr_surface_send_leave(pSurface, OUTPUT);
|
||||
}
|
||||
|
||||
void CWindow::updateSurfaceOutputs() {
|
||||
if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden)
|
||||
void CWindow::updateSurfaceScaleTransformDetails() {
|
||||
if (!m_bIsMapped || m_bHidden)
|
||||
return;
|
||||
|
||||
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
||||
@@ -355,16 +345,23 @@ void CWindow::updateSurfaceOutputs() {
|
||||
|
||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||
if (PNEWMONITOR != PLASTMONITOR) {
|
||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||
}
|
||||
|
||||
wlr_surface_for_each_surface(
|
||||
m_pWLSurface.wlr(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
|
||||
const auto PSURFACE = CWLSurface::surfaceFromWlr(surf);
|
||||
if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale)
|
||||
return;
|
||||
|
||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
||||
},
|
||||
this);
|
||||
@@ -374,7 +371,7 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
if (m_iWorkspaceID == workspaceID)
|
||||
return;
|
||||
|
||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
||||
static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty");
|
||||
|
||||
const int OLDWORKSPACE = m_iWorkspaceID;
|
||||
|
||||
@@ -397,7 +394,7 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
// update xwayland coords
|
||||
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && **PCLOSEONLASTSPECIAL) {
|
||||
const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE);
|
||||
|
||||
if (PWS) {
|
||||
@@ -440,7 +437,7 @@ void unregisterVar(void* ptr) {
|
||||
}
|
||||
|
||||
void CWindow::onUnmap() {
|
||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
||||
static auto* const PCLOSEONLASTSPECIAL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty");
|
||||
|
||||
if (g_pCompositor->m_pLastWindow == this)
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
@@ -462,7 +459,7 @@ void CWindow::onUnmap() {
|
||||
|
||||
hyprListener_unmapWindow.removeCallback();
|
||||
|
||||
if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) {
|
||||
if (**PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(m_iWorkspaceID) == 0 && g_pCompositor->isWorkspaceSpecial(m_iWorkspaceID)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
@@ -511,6 +508,14 @@ void CWindow::onMap() {
|
||||
"CWindow");
|
||||
|
||||
m_vReportedSize = m_vPendingReportedSize;
|
||||
|
||||
for (const auto& ctrl : g_pHyprRenderer->m_vTearingControllers) {
|
||||
if (ctrl->pWlrHint->surface != m_pWLSurface.wlr())
|
||||
continue;
|
||||
|
||||
m_bTearingHint = ctrl->pWlrHint->current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||
@@ -607,14 +612,42 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
m_sAdditionalConfigData.animationStyle = STYLE;
|
||||
} else if (r.szRule.starts_with("bordercolor")) {
|
||||
try {
|
||||
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
// Each vector will only get used if it has at least one color
|
||||
CGradientValueData activeBorderGradient = {};
|
||||
CGradientValueData inactiveBorderGradient = {};
|
||||
bool active = true;
|
||||
CVarList colorsAndAngles = CVarList(removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
||||
|
||||
if (colorPart.contains(' ')) {
|
||||
// we have a space, 2 values
|
||||
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
|
||||
m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1));
|
||||
} else {
|
||||
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart);
|
||||
// Basic form has only two colors, everything else can be parsed as a gradient
|
||||
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
||||
m_sSpecialRenderData.activeBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[0])));
|
||||
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[1])));
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& token : colorsAndAngles) {
|
||||
// The first angle, or an explicit "0deg", splits the two gradients
|
||||
if (active && token.contains("deg")) {
|
||||
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
active = false;
|
||||
} else if (token.contains("deg"))
|
||||
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||
else if (active)
|
||||
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
else
|
||||
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
||||
}
|
||||
|
||||
// Includes sanity checks for the number of colors in each gradient
|
||||
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10)
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
||||
else if (activeBorderGradient.m_vColors.empty())
|
||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
||||
else if (inactiveBorderGradient.m_vColors.empty())
|
||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||
else {
|
||||
m_sSpecialRenderData.activeBorderColor = activeBorderGradient;
|
||||
m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient;
|
||||
}
|
||||
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "dimaround") {
|
||||
@@ -644,8 +677,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
}
|
||||
|
||||
void CWindow::updateDynamicRules() {
|
||||
m_sSpecialRenderData.activeBorderColor = -1;
|
||||
m_sSpecialRenderData.inactiveBorderColor = -1;
|
||||
m_sSpecialRenderData.activeBorderColor = CGradientValueData();
|
||||
m_sSpecialRenderData.inactiveBorderColor = CGradientValueData();
|
||||
m_sSpecialRenderData.alpha = 1.f;
|
||||
m_sSpecialRenderData.alphaInactive = -1.f;
|
||||
m_sAdditionalConfigData.forceNoBlur = false;
|
||||
@@ -990,19 +1023,21 @@ bool CWindow::opaque() {
|
||||
}
|
||||
|
||||
float CWindow::rounding() {
|
||||
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
static auto* const PROUNDING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:rounding");
|
||||
|
||||
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
|
||||
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? **PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
|
||||
|
||||
return m_sSpecialRenderData.rounding ? rounding : 0;
|
||||
}
|
||||
|
||||
void CWindow::updateSpecialRenderData() {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
bool border = true;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
||||
bool border = true;
|
||||
|
||||
if (m_bIsFloating && g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue == 1)
|
||||
static auto* const* PNOBORDERONFLOATING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_border_on_floating");
|
||||
|
||||
if (m_bIsFloating && **PNOBORDERONFLOATING == 1)
|
||||
border = false;
|
||||
|
||||
m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(border);
|
||||
@@ -1022,16 +1057,18 @@ int CWindow::getRealBorderSize() {
|
||||
if (m_sSpecialRenderData.borderSize.toUnderlying() != -1)
|
||||
return m_sSpecialRenderData.borderSize.toUnderlying();
|
||||
|
||||
return g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const* PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size");
|
||||
|
||||
return **PBORDERSIZE;
|
||||
}
|
||||
|
||||
bool CWindow::canBeTorn() {
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied;
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint);
|
||||
}
|
||||
|
||||
bool CWindow::shouldSendFullscreenState() {
|
||||
const auto MODE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID)->m_efFullscreenMode;
|
||||
return m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL));
|
||||
return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)));
|
||||
}
|
||||
|
||||
void CWindow::setSuspended(bool suspend) {
|
||||
|
@@ -30,6 +30,24 @@ enum eGroupRules {
|
||||
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
||||
};
|
||||
|
||||
enum eGetWindowProperties {
|
||||
WINDOW_ONLY = 0,
|
||||
RESERVED_EXTENTS = 1 << 0,
|
||||
INPUT_EXTENTS = 1 << 1,
|
||||
FULL_EXTENTS = 1 << 2,
|
||||
FLOATING_ONLY = 1 << 3,
|
||||
ALLOW_FLOATING = 1 << 4,
|
||||
USE_PROP_TILED = 1 << 5,
|
||||
};
|
||||
|
||||
enum eSuppressEvents {
|
||||
SUPPRESS_NONE = 0,
|
||||
SUPPRESS_FULLSCREEN = 1 << 0,
|
||||
SUPPRESS_MAXIMIZE = 1 << 1,
|
||||
SUPPRESS_ACTIVATE = 1 << 2,
|
||||
SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3,
|
||||
};
|
||||
|
||||
class IWindowTransformer;
|
||||
|
||||
template <typename T>
|
||||
@@ -106,13 +124,13 @@ class CWindowOverridableVar {
|
||||
};
|
||||
|
||||
struct SWindowSpecialRenderData {
|
||||
CWindowOverridableVar<bool> alphaOverride = false;
|
||||
CWindowOverridableVar<float> alpha = 1.f;
|
||||
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
||||
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
||||
CWindowOverridableVar<bool> alphaOverride = false;
|
||||
CWindowOverridableVar<float> alpha = 1.f;
|
||||
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
||||
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
||||
|
||||
CWindowOverridableVar<int64_t> activeBorderColor = -1; // -1 means unset
|
||||
CWindowOverridableVar<int64_t> inactiveBorderColor = -1; // -1 means unset
|
||||
CWindowOverridableVar<CGradientValueData> activeBorderColor = CGradientValueData(); // empty color vector means unset
|
||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor = CGradientValueData(); // empty color vector means unset
|
||||
|
||||
// set by the layout
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset
|
||||
@@ -133,6 +151,7 @@ struct SWindowAdditionalConfigData {
|
||||
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||
CWindowOverridableVar<bool> forceNoDim = false;
|
||||
CWindowOverridableVar<bool> noFocus = false;
|
||||
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||
CWindowOverridableVar<bool> noMaxSize = false;
|
||||
CWindowOverridableVar<bool> dimAround = false;
|
||||
@@ -221,16 +240,17 @@ class CWindow {
|
||||
bool m_bIsPseudotiled = false;
|
||||
Vector2D m_vPseudoSize = Vector2D(0, 0);
|
||||
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
bool m_bWasMaximized = false;
|
||||
uint64_t m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
std::string m_szInitialClass = "";
|
||||
int m_iWorkspaceID = -1;
|
||||
bool m_bFirstMap = false; // for layouts
|
||||
bool m_bIsFloating = false;
|
||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||
bool m_bIsFullscreen = false;
|
||||
bool m_bDontSendFullscreen = false;
|
||||
bool m_bWasMaximized = false;
|
||||
uint64_t m_iMonitorID = -1;
|
||||
std::string m_szTitle = "";
|
||||
std::string m_szInitialTitle = "";
|
||||
std::string m_szInitialClass = "";
|
||||
int m_iWorkspaceID = -1;
|
||||
|
||||
bool m_bIsMapped = false;
|
||||
|
||||
@@ -250,13 +270,13 @@ class CWindow {
|
||||
//
|
||||
|
||||
// For nofocus
|
||||
bool m_bNoFocus = false;
|
||||
bool m_bNoInitialFocus = false;
|
||||
|
||||
// Fullscreen and Maximize
|
||||
bool m_bWantsInitialFullscreen = false;
|
||||
bool m_bNoFullscreenRequest = false;
|
||||
bool m_bNoMaximizeRequest = false;
|
||||
bool m_bWantsInitialFullscreen = false;
|
||||
|
||||
// bitfield eSuppressEvents
|
||||
uint64_t m_eSuppressedEvents = SUPPRESS_NONE;
|
||||
|
||||
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
||||
|
||||
@@ -342,7 +362,7 @@ class CWindow {
|
||||
// methods
|
||||
CBox getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
CBox getWindowInputBox();
|
||||
CBox getWindowBoxUnified(uint64_t props);
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||
@@ -356,7 +376,7 @@ class CWindow {
|
||||
void createToplevelHandle();
|
||||
void destroyToplevelHandle();
|
||||
void updateToplevel();
|
||||
void updateSurfaceOutputs();
|
||||
void updateSurfaceScaleTransformDetails();
|
||||
void moveToWorkspace(int);
|
||||
CWindow* X11TransientFor();
|
||||
void onUnmap();
|
||||
|
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes {
|
||||
CVD_TYPE_INVALID = -1,
|
||||
CVD_TYPE_GRADIENT = 0
|
||||
CVD_TYPE_INVALID = -1,
|
||||
CVD_TYPE_GRADIENT = 0,
|
||||
CVD_TYPE_CSS_VALUE = 1
|
||||
};
|
||||
|
||||
class ICustomConfigValueData {
|
||||
@@ -16,6 +18,7 @@ class ICustomConfigValueData {
|
||||
|
||||
class CGradientValueData : public ICustomConfigValueData {
|
||||
public:
|
||||
CGradientValueData(){};
|
||||
CGradientValueData(CColor col) {
|
||||
m_vColors.push_back(col);
|
||||
};
|
||||
@@ -49,3 +52,55 @@ class CGradientValueData : public ICustomConfigValueData {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CCssGapData : public ICustomConfigValueData {
|
||||
public:
|
||||
CCssGapData() : top(0), right(0), bottom(0), left(0){};
|
||||
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){};
|
||||
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){};
|
||||
|
||||
/* Css like directions */
|
||||
int64_t top;
|
||||
int64_t right;
|
||||
int64_t bottom;
|
||||
int64_t left;
|
||||
|
||||
void parseGapData(CVarList varlist) {
|
||||
switch (varlist.size()) {
|
||||
case 1: {
|
||||
*this = CCssGapData(std::stoi(varlist[0]));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]));
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Debug::log(WARN, "Too many arguments provided for gaps.");
|
||||
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset(int64_t global) {
|
||||
top = global;
|
||||
right = global;
|
||||
bottom = global;
|
||||
left = global;
|
||||
}
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() {
|
||||
return CVD_TYPE_CSS_VALUE;
|
||||
}
|
||||
};
|
||||
|
@@ -21,21 +21,13 @@
|
||||
#include "defaultConfig.hpp"
|
||||
#include "ConfigDataValues.hpp"
|
||||
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
#define INITANIMCFG(name) animationConfig[name] = {}
|
||||
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
||||
|
||||
#define HANDLE void*
|
||||
|
||||
struct SConfigValue {
|
||||
int64_t intValue = -INT64_MAX;
|
||||
float floatValue = -__FLT_MAX__;
|
||||
std::string strValue = "";
|
||||
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
|
||||
std::shared_ptr<ICustomConfigValueData> data;
|
||||
|
||||
bool set = false; // used for device configs
|
||||
};
|
||||
|
||||
struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
@@ -43,14 +35,15 @@ struct SWorkspaceRule {
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
std::optional<CCssGapData> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::optional<std::string> defaultName;
|
||||
std::map<std::string, std::string> layoutopts;
|
||||
};
|
||||
|
||||
@@ -74,9 +67,14 @@ struct SAnimationPropertyConfig {
|
||||
};
|
||||
|
||||
struct SPluginKeyword {
|
||||
HANDLE handle = 0;
|
||||
std::string name = "";
|
||||
std::function<void(const std::string&, const std::string&)> fn;
|
||||
HANDLE handle = 0;
|
||||
std::string name = "";
|
||||
Hyprlang::PCONFIGHANDLERFUNC fn = nullptr;
|
||||
};
|
||||
|
||||
struct SPluginVariable {
|
||||
HANDLE handle = 0;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
struct SExecRequestedRule {
|
||||
@@ -91,28 +89,21 @@ class CConfigManager {
|
||||
void tick();
|
||||
void init();
|
||||
|
||||
int getInt(const std::string&);
|
||||
float getFloat(const std::string&);
|
||||
Vector2D getVec(const std::string&);
|
||||
std::string getString(const std::string&);
|
||||
void setFloat(const std::string&, float);
|
||||
void setInt(const std::string&, int);
|
||||
void setVec(const std::string&, Vector2D);
|
||||
void setString(const std::string&, const std::string&);
|
||||
|
||||
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
bool deviceConfigExists(const std::string&);
|
||||
Hyprlang::CConfigValue* getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback);
|
||||
bool shouldBlurLS(const std::string&);
|
||||
|
||||
SConfigValue* getConfigValuePtr(const std::string&);
|
||||
SConfigValue* getConfigValuePtrSafe(const std::string&);
|
||||
void* const* getConfigValuePtr(const std::string&);
|
||||
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
|
||||
void onPluginLoadUnload(const std::string& name, bool load);
|
||||
static std::string getConfigDir();
|
||||
static std::string getMainConfigPath();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
||||
std::string getDefaultWorkspaceFor(const std::string&);
|
||||
|
||||
@@ -120,15 +111,15 @@ class CConfigManager {
|
||||
std::string getBoundMonitorStringForWS(const std::string&);
|
||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*, bool dynamic = true);
|
||||
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& cmd, const std::string& val)> fun);
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
|
||||
void removePluginConfig(HANDLE handle);
|
||||
|
||||
// no-op when done.
|
||||
@@ -141,7 +132,7 @@ class CConfigManager {
|
||||
void ensureMonitorStatus();
|
||||
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||
|
||||
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
||||
std::string parseKeyword(const std::string&, const std::string&);
|
||||
|
||||
void addParseError(const std::string&);
|
||||
|
||||
@@ -151,77 +142,65 @@ class CConfigManager {
|
||||
|
||||
void handlePluginLoads();
|
||||
|
||||
std::string configCurrentPath;
|
||||
// keywords
|
||||
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleMonitor(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBind(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleUnbind(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWindowRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleLayerRule(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWindowRuleV2(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBezier(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBlurLS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleEnv(const std::string&, const std::string&);
|
||||
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
private:
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
std::vector<std::pair<std::string, std::string>> configDynamicVars; // stores dynamic vars declared by the user
|
||||
std::unordered_map<std::string, SConfigValue> configValues;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
|
||||
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||
std::deque<std::string> configPaths; // stores all the config paths
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
|
||||
std::string currentCategory = ""; // For storing the category of the current item
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||
|
||||
std::string parseError = ""; // For storing a parse error to display later
|
||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||
|
||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
||||
|
||||
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
||||
std::vector<std::string> m_vDeclaredPlugins;
|
||||
std::vector<SPluginKeyword> pluginKeywords;
|
||||
std::vector<SPluginVariable> pluginVariables;
|
||||
|
||||
std::vector<std::string> m_vDeclaredPlugins;
|
||||
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
||||
std::vector<SPluginKeyword> pluginKeywords;
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
||||
std::deque<SWindowRule> m_dWindowRules;
|
||||
std::deque<SLayerRule> m_dLayerRules;
|
||||
std::deque<std::string> m_dBlurLSNamespaces;
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
std::deque<SWorkspaceRule> m_dWorkspaceRules;
|
||||
std::deque<SWindowRule> m_dWindowRules;
|
||||
std::deque<SLayerRule> m_dLayerRules;
|
||||
std::deque<std::string> m_dBlurLSNamespaces;
|
||||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
|
||||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> environmentVariables;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
|
||||
// internal methods
|
||||
void setDefaultVars();
|
||||
void setDefaultAnimationVars();
|
||||
void setDeviceDefaultVars(const std::string&);
|
||||
void populateEnvironment();
|
||||
|
||||
void setAnimForChildren(SAnimationPropertyConfig* const);
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
|
||||
void applyUserDefinedVars(std::string&, const size_t);
|
||||
void loadConfigLoadVars();
|
||||
SConfigValue getConfigValueSafe(const std::string&);
|
||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
void parseLine(std::string&);
|
||||
void configSetValueSafe(const std::string&, const std::string&);
|
||||
void handleDeviceConfig(const std::string&, const std::string&);
|
||||
void handleRawExec(const std::string&, const std::string&);
|
||||
void handleMonitor(const std::string&, const std::string&);
|
||||
void handleBind(const std::string&, const std::string&);
|
||||
void handleUnbind(const std::string&, const std::string&);
|
||||
void handleWindowRule(const std::string&, const std::string&);
|
||||
void handleLayerRule(const std::string&, const std::string&);
|
||||
void handleWindowRuleV2(const std::string&, const std::string&);
|
||||
void handleWorkspaceRules(const std::string&, const std::string&);
|
||||
void handleBezier(const std::string&, const std::string&);
|
||||
void handleAnimation(const std::string&, const std::string&);
|
||||
void handleSource(const std::string&, const std::string&);
|
||||
void handleSubmap(const std::string&, const std::string&);
|
||||
void handleBlurLS(const std::string&, const std::string&);
|
||||
void handleBindWS(const std::string&, const std::string&);
|
||||
void handleEnv(const std::string&, const std::string&);
|
||||
void handlePlugin(const std::string&, const std::string&);
|
||||
void setAnimForChildren(SAnimationPropertyConfig* const);
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
void reload();
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#include <string>
|
||||
|
||||
inline const std::string AUTOCONFIG = R"#(
|
||||
########################################################################################
|
||||
AUTOGENERATED HYPR CONFIG.
|
||||
PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
########################################################################################
|
||||
# #######################################################################################
|
||||
# AUTOGENERATED HYPR CONFIG.
|
||||
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
# #######################################################################################
|
||||
|
||||
#
|
||||
# Please note not all available settings / options are set here.
|
||||
@@ -51,7 +51,7 @@ input {
|
||||
natural_scroll = no
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
sensitivity = 0 # -1.0 to 1.0, 0 means no modification.
|
||||
}
|
||||
|
||||
general {
|
||||
@@ -119,12 +119,13 @@ gestures {
|
||||
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||
device:epic-mouse-v1 {
|
||||
device {
|
||||
name = epic-mouse-v1
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
||||
@@ -133,7 +134,7 @@ device:epic-mouse-v1 {
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <fstream>
|
||||
#include <signal.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
|
||||
@@ -105,21 +106,38 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
||||
#endif
|
||||
|
||||
std::string addrs = "";
|
||||
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
||||
finalCrashReport += std::format("\t#{} | {}\n", i, CALLSTACK[i].desc);
|
||||
// convert in memory address to VMA address
|
||||
Dl_info info;
|
||||
struct link_map* linkMap;
|
||||
dladdr1((void*)CALLSTACK[i].adr, &info, (void**)&linkMap, RTLD_DL_LINKMAP);
|
||||
size_t vmaAddr = (size_t)CALLSTACK[i].adr - linkMap->l_addr;
|
||||
|
||||
addrs += std::format("0x{:x} ", vmaAddr);
|
||||
}
|
||||
#ifdef __clang__
|
||||
const auto CMD = std::format("llvm-addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
|
||||
const auto CMD = std::format("llvm-addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
|
||||
#else
|
||||
const auto CMD = std::format("addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
|
||||
const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
|
||||
#endif
|
||||
const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t");
|
||||
finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2);
|
||||
|
||||
const auto ADDR2LINE = execAndGet(CMD.c_str());
|
||||
|
||||
std::stringstream ssin(ADDR2LINE);
|
||||
|
||||
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
||||
finalCrashReport += std::format("\t#{} | {}", i, CALLSTACK[i].desc);
|
||||
std::string functionInfo;
|
||||
std::string fileLineInfo;
|
||||
std::getline(ssin, functionInfo);
|
||||
std::getline(ssin, fileLineInfo);
|
||||
finalCrashReport += std::format("\n\t\t{}\n\t\t{}\n", functionInfo, fileLineInfo);
|
||||
}
|
||||
|
||||
finalCrashReport += "\n\nLog tail:\n";
|
||||
|
||||
finalCrashReport += Debug::rollingLog;
|
||||
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||
@@ -128,21 +146,18 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
return;
|
||||
|
||||
std::ofstream ofs;
|
||||
std::string path;
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty()) {
|
||||
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland"))
|
||||
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
|
||||
std::string reportDir;
|
||||
|
||||
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty())
|
||||
reportDir = std::string(HOME) + "/.cache/hyprland";
|
||||
else
|
||||
reportDir = std::string(CACHE_HOME) + "/hyprland";
|
||||
|
||||
} else {
|
||||
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland"))
|
||||
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
|
||||
if (!std::filesystem::exists(reportDir))
|
||||
std::filesystem::create_directory(reportDir);
|
||||
const auto path = reportDir + "/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
|
||||
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
}
|
||||
ofs.open(path, std::ios::trunc);
|
||||
|
||||
ofs << finalCrashReport;
|
||||
|
||||
|
@@ -7,12 +7,13 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
|
||||
static void trimTrailingComma(std::string& str) {
|
||||
if (!str.empty() && str.back() == ',')
|
||||
@@ -28,7 +29,7 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) {
|
||||
return workspace->m_szName;
|
||||
}
|
||||
|
||||
std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
auto allMonitors = false;
|
||||
|
||||
@@ -39,7 +40,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||
allMonitors = true;
|
||||
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
@@ -75,7 +76,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||
"vrr": {},
|
||||
"activelyTearing": {}
|
||||
}},)#",
|
||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||
(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||
m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID,
|
||||
escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
@@ -97,7 +98,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||
"workspace: {} ({})\n\treserved: {} "
|
||||
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
||||
"{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\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->szDescription,
|
||||
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->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace,
|
||||
(m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID,
|
||||
getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x,
|
||||
@@ -109,8 +110,8 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const bool isJson = format == HyprCtl::FORMAT_JSON;
|
||||
static std::string getGroupedData(CWindow* w, eHyprCtlOutputFormat format) {
|
||||
const bool isJson = format == eHyprCtlOutputFormat::FORMAT_JSON;
|
||||
if (!w->m_sGroupData.pNextWindow)
|
||||
return isJson ? "" : "0";
|
||||
|
||||
@@ -133,7 +134,7 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
|
||||
return result.str();
|
||||
}
|
||||
|
||||
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
static std::string getWindowData(CWindow* w, eHyprCtlOutputFormat format) {
|
||||
auto getFocusHistoryID = [](CWindow* wnd) -> int {
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
||||
@@ -142,7 +143,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
return std::format(
|
||||
R"#({{
|
||||
"address": "0x{:x}",
|
||||
@@ -198,9 +199,9 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
}
|
||||
}
|
||||
|
||||
std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
@@ -218,10 +219,10 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
static std::string getWorkspaceData(CWorkspace* w, eHyprCtlOutputFormat format) {
|
||||
const auto PLASTW = w->getLastFocusedWindow();
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(w->m_iMonitorID);
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
return std::format(R"#({{
|
||||
"id": {},
|
||||
"name": "{}",
|
||||
@@ -242,14 +243,18 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputFormat format) {
|
||||
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
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()) : "";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : "";
|
||||
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 borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||
const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : "";
|
||||
const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : "";
|
||||
@@ -266,8 +271,12 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||
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 = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : "<unset>");
|
||||
const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : "<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.border) ? boolToString(r.border.value()) : "<unset>");
|
||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : "<unset>");
|
||||
@@ -280,7 +289,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||
return result;
|
||||
}
|
||||
}
|
||||
std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return "unsafe state";
|
||||
|
||||
@@ -293,10 +302,10 @@ std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return getWorkspaceData(w, format);
|
||||
}
|
||||
|
||||
std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += getWorkspaceData(w.get(), format);
|
||||
@@ -314,9 +323,9 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
@@ -334,24 +343,24 @@ std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return format == HyprCtl::FORMAT_JSON ? "{}" : "Invalid";
|
||||
return format == eHyprCtlOutputFormat::FORMAT_JSON ? "{}" : "Invalid";
|
||||
|
||||
auto result = getWindowData(PWINDOW, format);
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON)
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON)
|
||||
result.pop_back();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
@@ -422,9 +431,9 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
@@ -444,10 +453,10 @@ std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
result += "\"mice\": [\n";
|
||||
|
||||
@@ -603,9 +612,9 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
ret += "animations:\n";
|
||||
|
||||
for (auto& ac : g_pConfigManager->getAnimationConfig()) {
|
||||
@@ -656,10 +665,10 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[\n\"log\":\"";
|
||||
result += escapeJSONStrings(Debug::rollingLog);
|
||||
result += "\"]";
|
||||
@@ -670,10 +679,10 @@ std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& sh : SHORTCUTS)
|
||||
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
|
||||
} else {
|
||||
@@ -693,9 +702,9 @@ std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string ret = "";
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
|
||||
ret += "bind";
|
||||
if (kb.locked)
|
||||
@@ -741,12 +750,12 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
|
||||
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
|
||||
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
|
||||
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
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 + "\n\nflags: (if any)\n";
|
||||
|
||||
@@ -793,7 +802,40 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return ""; // make the compiler happy
|
||||
}
|
||||
|
||||
std::string dispatchRequest(std::string in) {
|
||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string result = versionRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "");
|
||||
|
||||
result += "\n\nSystem Information:\n";
|
||||
|
||||
struct utsname unameInfo;
|
||||
|
||||
uname(&unameInfo);
|
||||
|
||||
result += "System name: " + std::string{unameInfo.sysname} + "\n";
|
||||
result += "Node name: " + std::string{unameInfo.nodename} + "\n";
|
||||
result += "Release: " + std::string{unameInfo.release} + "\n";
|
||||
result += "Version: " + std::string{unameInfo.version} + "\n";
|
||||
|
||||
result += "\n\n";
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||
#else
|
||||
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||
#endif
|
||||
result += "GPU information: \n" + GPUINFO + "\n\n";
|
||||
|
||||
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
|
||||
|
||||
result += "plugins:\n";
|
||||
for (auto& pl : g_pPluginSystem->getAllPlugins()) {
|
||||
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) {
|
||||
// get rid of the dispatch keyword
|
||||
in = in.substr(in.find_first_of(' ') + 1);
|
||||
|
||||
@@ -814,7 +856,7 @@ std::string dispatchRequest(std::string in) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchKeyword(std::string in) {
|
||||
std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
|
||||
// get rid of the keyword keyword
|
||||
in = in.substr(in.find_first_of(' ') + 1);
|
||||
|
||||
@@ -822,32 +864,35 @@ std::string dispatchKeyword(std::string in) {
|
||||
|
||||
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
|
||||
|
||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE, true);
|
||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
||||
|
||||
if (COMMAND == "monitor")
|
||||
// if we are executing a dynamic source we have to reload everything, so every if will have a check for source.
|
||||
if (COMMAND == "monitor" || COMMAND == "source")
|
||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||
|
||||
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
|
||||
if (COMMAND.contains("input") || COMMAND.contains("device") || COMMAND == "source") {
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||
g_pInputManager->setTabletConfigs(); // update tablets
|
||||
}
|
||||
|
||||
if (COMMAND.contains("general:layout"))
|
||||
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
|
||||
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout");
|
||||
|
||||
if (COMMAND.contains("decoration:screen_shader"))
|
||||
if (COMMAND.contains("general:layout"))
|
||||
g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout
|
||||
|
||||
if (COMMAND.contains("decoration:screen_shader") || COMMAND == "source")
|
||||
g_pHyprOpenGL->m_bReloadScreenShader = true;
|
||||
|
||||
if (COMMAND.contains("blur")) {
|
||||
if (COMMAND.contains("blur") || COMMAND == "source") {
|
||||
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
||||
rd.blurFBDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
// decorations will probably need a repaint
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("cursor_zoom_factor")) {
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("cursor_zoom_factor") || COMMAND == "source") {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
@@ -862,7 +907,7 @@ std::string dispatchKeyword(std::string in) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string reloadRequest(const std::string& request) {
|
||||
std::string reloadRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
|
||||
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
|
||||
|
||||
@@ -877,20 +922,20 @@ std::string reloadRequest(const std::string& request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string killRequest() {
|
||||
std::string killRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
g_pInputManager->setClickMode(CLICKMODE_KILL);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string splashRequest() {
|
||||
std::string splashRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
return g_pCompositor->m_szCurrentSplash;
|
||||
}
|
||||
|
||||
std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
|
||||
|
||||
if (format == HyprCtl::FORMAT_NORMAL) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
|
||||
return std::format("{}, {}", (int)CURSORPOS.x, (int)CURSORPOS.y);
|
||||
} else {
|
||||
return std::format(R"#(
|
||||
@@ -905,9 +950,7 @@ std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return "error";
|
||||
}
|
||||
|
||||
std::string getReply(std::string);
|
||||
|
||||
std::string dispatchBatch(std::string request) {
|
||||
std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
|
||||
// split by ;
|
||||
|
||||
request = request.substr(9);
|
||||
@@ -930,8 +973,8 @@ std::string dispatchBatch(std::string request) {
|
||||
|
||||
nextItem();
|
||||
|
||||
while (curitem != "") {
|
||||
reply += getReply(curitem);
|
||||
while (curitem != "" || request != "") {
|
||||
reply += g_pHyprCtl->getReply(curitem);
|
||||
|
||||
nextItem();
|
||||
}
|
||||
@@ -939,7 +982,7 @@ std::string dispatchBatch(std::string request) {
|
||||
return reply;
|
||||
}
|
||||
|
||||
std::string dispatchSetCursor(std::string request) {
|
||||
std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
const auto SIZESTR = vars[vars.size() - 1];
|
||||
@@ -971,7 +1014,7 @@ std::string dispatchSetCursor(std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string switchXKBLayoutRequest(const std::string& request) {
|
||||
std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
const auto KB = vars[1];
|
||||
@@ -1017,7 +1060,7 @@ std::string switchXKBLayoutRequest(const std::string& request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchSeterror(std::string request) {
|
||||
std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
std::string errorMessage = "";
|
||||
@@ -1046,13 +1089,14 @@ std::string dispatchSeterror(std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchSetProp(std::string request) {
|
||||
std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 4)
|
||||
return "not enough args";
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
|
||||
if (!PWINDOW)
|
||||
return "window not found";
|
||||
@@ -1060,6 +1104,8 @@ std::string dispatchSetProp(std::string request) {
|
||||
const auto PROP = vars[2];
|
||||
const auto VAL = vars[3];
|
||||
|
||||
auto noFocus = PWINDOW->m_sAdditionalConfigData.noFocus;
|
||||
|
||||
bool lock = false;
|
||||
|
||||
if (vars.size() > 4) {
|
||||
@@ -1089,6 +1135,8 @@ std::string dispatchSetProp(std::string request) {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoShadow.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "forcenodim") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceNoDim.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nofocus") {
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "windowdancecompat") {
|
||||
PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nomaxsize") {
|
||||
@@ -1104,9 +1152,9 @@ std::string dispatchSetProp(std::string request) {
|
||||
} else if (PROP == "alphainactive") {
|
||||
PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock);
|
||||
} else if (PROP == "activebordercolor") {
|
||||
PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock);
|
||||
} else if (PROP == "inactivebordercolor") {
|
||||
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock);
|
||||
} else if (PROP == "forcergbx") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "bordersize") {
|
||||
@@ -1124,13 +1172,19 @@ std::string dispatchSetProp(std::string request) {
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
if (!(PWINDOW->m_sAdditionalConfigData.noFocus.toUnderlying() == noFocus.toUnderlying())) {
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string curitem = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
@@ -1150,31 +1204,43 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat
|
||||
nextItem();
|
||||
nextItem();
|
||||
|
||||
const auto PCFGOPT = g_pConfigManager->getConfigValuePtrSafe(curitem);
|
||||
const auto VAR = g_pConfigManager->getHyprlangConfigValuePtr(curitem);
|
||||
|
||||
if (!PCFGOPT)
|
||||
if (!VAR)
|
||||
return "no such option";
|
||||
|
||||
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
|
||||
return std::format("option {}\n\tint: {}\n\tfloat: {:.5f}\n\tstr: \"{}\"\n\tdata: {:x}\n\tset: {}", curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue,
|
||||
(uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
||||
else {
|
||||
return std::format(
|
||||
R"#(
|
||||
{{
|
||||
"option": "{}",
|
||||
"int": {},
|
||||
"float": {:.5f},
|
||||
"str": "{}",
|
||||
"data": "0x{:x}",
|
||||
"set": {}
|
||||
}}
|
||||
)#",
|
||||
curitem, PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue, (uintptr_t)PCFGOPT->data.get(), PCFGOPT->set);
|
||||
const auto VAL = VAR->getValue();
|
||||
const auto TYPE = std::type_index(VAL.type());
|
||||
|
||||
if (format == FORMAT_NORMAL) {
|
||||
if (TYPE == typeid(Hyprlang::INT))
|
||||
return std::format("int: {}\nset: {}", std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||
return std::format("float: {:2f}\nset: {}", std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||
return std::format("vec2: [{}, {}]\nset: {}", std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y, VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::STRING))
|
||||
return std::format("str: {}\nset: {}", std::any_cast<Hyprlang::STRING>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*))
|
||||
return std::format("custom type at: {:x}\nset: {}", (uintptr_t)std::any_cast<Hyprlang::CUSTOMTYPE*>(VAL), VAR->m_bSetByUser);
|
||||
} else {
|
||||
if (TYPE == typeid(Hyprlang::INT))
|
||||
return std::format("{{\"option\": \"{}\", \"int\": {}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::INT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::FLOAT))
|
||||
return std::format("{{\"option\": \"{}\", \"float\": {:2f}, \"set\": {} }}", curitem, std::any_cast<Hyprlang::FLOAT>(VAL), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::VEC2))
|
||||
return std::format("{{\"option\": \"{}\", \"vec2\": [{},{}], \"set\": {} }}", curitem, std::any_cast<Hyprlang::VEC2>(VAL).x, std::any_cast<Hyprlang::VEC2>(VAL).y,
|
||||
VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::STRING))
|
||||
return std::format("{{\"option\": \"{}\", \"str\": \"{}\", \"set\": {} }}", curitem, escapeJSONStrings(std::any_cast<Hyprlang::STRING>(VAL)), VAR->m_bSetByUser);
|
||||
else if (TYPE == typeid(Hyprlang::CUSTOMTYPE*))
|
||||
return std::format("{{\"option\": \"{}\", \"custom\": \"{:x}\", \"set\": {} }}", curitem, (uintptr_t)std::any_cast<Hyprlang::CUSTOMTYPE*>(VAL), VAR->m_bSetByUser);
|
||||
}
|
||||
|
||||
return "invalid type (internal error)";
|
||||
}
|
||||
|
||||
std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
|
||||
|
||||
@@ -1182,7 +1248,7 @@ std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat
|
||||
return "none";
|
||||
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& wd : PWINDOW->m_dWindowDecorations) {
|
||||
result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},";
|
||||
@@ -1231,7 +1297,7 @@ void createOutputIter(wlr_backend* backend, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string dispatchOutput(std::string request) {
|
||||
std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
||||
std::string curitem = "";
|
||||
|
||||
auto nextItem = [&]() {
|
||||
@@ -1280,7 +1346,7 @@ std::string dispatchOutput(std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchPlugin(std::string request) {
|
||||
std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 2)
|
||||
@@ -1323,7 +1389,7 @@ std::string dispatchPlugin(std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string dispatchNotify(std::string request) {
|
||||
std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
|
||||
if (vars.size() < 5)
|
||||
@@ -1364,92 +1430,137 @@ std::string dispatchNotify(std::string request) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string getReply(std::string request) {
|
||||
auto format = HyprCtl::FORMAT_NORMAL;
|
||||
CHyprCtl::CHyprCtl() {
|
||||
registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest});
|
||||
registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest});
|
||||
registerCommand(SHyprCtlCommand{"activeworkspace", true, activeWorkspaceRequest});
|
||||
registerCommand(SHyprCtlCommand{"clients", true, clientsRequest});
|
||||
registerCommand(SHyprCtlCommand{"kill", true, killRequest});
|
||||
registerCommand(SHyprCtlCommand{"activewindow", true, activeWindowRequest});
|
||||
registerCommand(SHyprCtlCommand{"layers", true, layersRequest});
|
||||
registerCommand(SHyprCtlCommand{"version", true, versionRequest});
|
||||
registerCommand(SHyprCtlCommand{"devices", true, devicesRequest});
|
||||
registerCommand(SHyprCtlCommand{"splash", true, splashRequest});
|
||||
registerCommand(SHyprCtlCommand{"cursorpos", true, cursorPosRequest});
|
||||
registerCommand(SHyprCtlCommand{"binds", true, bindsRequest});
|
||||
registerCommand(SHyprCtlCommand{"globalshortcuts", true, globalShortcutsRequest});
|
||||
registerCommand(SHyprCtlCommand{"systeminfo", true, systemInfoRequest});
|
||||
registerCommand(SHyprCtlCommand{"animations", true, animationsRequest});
|
||||
registerCommand(SHyprCtlCommand{"rollinglog", true, rollinglogRequest});
|
||||
registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest});
|
||||
|
||||
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
|
||||
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});
|
||||
registerCommand(SHyprCtlCommand{"plugin", false, dispatchPlugin});
|
||||
registerCommand(SHyprCtlCommand{"notify", false, dispatchNotify});
|
||||
registerCommand(SHyprCtlCommand{"setprop", false, dispatchSetProp});
|
||||
registerCommand(SHyprCtlCommand{"seterror", false, dispatchSeterror});
|
||||
registerCommand(SHyprCtlCommand{"switchxkblayout", false, switchXKBLayoutRequest});
|
||||
registerCommand(SHyprCtlCommand{"output", false, dispatchOutput});
|
||||
registerCommand(SHyprCtlCommand{"dispatch", false, dispatchRequest});
|
||||
registerCommand(SHyprCtlCommand{"keyword", false, dispatchKeyword});
|
||||
registerCommand(SHyprCtlCommand{"setcursor", false, dispatchSetCursor});
|
||||
registerCommand(SHyprCtlCommand{"getoption", false, dispatchGetOption});
|
||||
registerCommand(SHyprCtlCommand{"decorations", false, decorationRequest});
|
||||
registerCommand(SHyprCtlCommand{"[[BATCH]]", false, dispatchBatch});
|
||||
|
||||
startHyprCtlSocket();
|
||||
}
|
||||
|
||||
std::shared_ptr<SHyprCtlCommand> CHyprCtl::registerCommand(SHyprCtlCommand cmd) {
|
||||
return m_vCommands.emplace_back(std::make_shared<SHyprCtlCommand>(cmd));
|
||||
}
|
||||
|
||||
void CHyprCtl::unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd) {
|
||||
std::erase(m_vCommands, cmd);
|
||||
}
|
||||
|
||||
std::string CHyprCtl::getReply(std::string request) {
|
||||
auto format = eHyprCtlOutputFormat::FORMAT_NORMAL;
|
||||
bool reloadAll = false;
|
||||
|
||||
// process flags for non-batch requests
|
||||
if (!request.contains("[[BATCH]]") && request.contains("/")) {
|
||||
if (!request.starts_with("[[BATCH]]") && request.contains("/")) {
|
||||
long unsigned int sepIndex = 0;
|
||||
for (const auto& c : request) {
|
||||
if (c == '/') { // stop at separator
|
||||
break;
|
||||
}
|
||||
|
||||
// after whitespace assume the first word as a keyword,
|
||||
// so its value can have slashes (e.g., a path)
|
||||
if (c == ' ') {
|
||||
sepIndex = request.size();
|
||||
break;
|
||||
}
|
||||
|
||||
sepIndex++;
|
||||
|
||||
if (c == 'j')
|
||||
format = HyprCtl::FORMAT_JSON;
|
||||
format = eHyprCtlOutputFormat::FORMAT_JSON;
|
||||
if (c == 'r')
|
||||
reloadAll = true;
|
||||
}
|
||||
|
||||
if (sepIndex < request.size())
|
||||
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
||||
}
|
||||
|
||||
if (request.starts_with("monitors"))
|
||||
return monitorsRequest(request, format);
|
||||
else if (request == "workspaces")
|
||||
return workspacesRequest(format);
|
||||
else if (request == "workspacerules")
|
||||
return workspaceRulesRequest(format);
|
||||
else if (request == "activeworkspace")
|
||||
return activeWorkspaceRequest(format);
|
||||
else if (request == "clients")
|
||||
return clientsRequest(format);
|
||||
else if (request == "kill")
|
||||
return killRequest();
|
||||
else if (request == "activewindow")
|
||||
return activeWindowRequest(format);
|
||||
else if (request == "layers")
|
||||
return layersRequest(format);
|
||||
else if (request == "version")
|
||||
return versionRequest(format);
|
||||
else if (request.starts_with("reload"))
|
||||
return reloadRequest(request);
|
||||
else if (request == "devices")
|
||||
return devicesRequest(format);
|
||||
else if (request == "splash")
|
||||
return splashRequest();
|
||||
else if (request == "cursorpos")
|
||||
return cursorPosRequest(format);
|
||||
else if (request == "binds")
|
||||
return bindsRequest(format);
|
||||
else if (request == "globalshortcuts")
|
||||
return globalShortcutsRequest(format);
|
||||
else if (request == "animations")
|
||||
return animationsRequest(format);
|
||||
else if (request == "rollinglog")
|
||||
return rollinglogRequest(format);
|
||||
else if (request == "layouts")
|
||||
return layoutsRequest(format);
|
||||
else if (request.starts_with("plugin"))
|
||||
return dispatchPlugin(request);
|
||||
else if (request.starts_with("notify"))
|
||||
return dispatchNotify(request);
|
||||
else if (request.starts_with("setprop"))
|
||||
return dispatchSetProp(request);
|
||||
else if (request.starts_with("seterror"))
|
||||
return dispatchSeterror(request);
|
||||
else if (request.starts_with("switchxkblayout"))
|
||||
return switchXKBLayoutRequest(request);
|
||||
else if (request.starts_with("output"))
|
||||
return dispatchOutput(request);
|
||||
else if (request.starts_with("dispatch"))
|
||||
return dispatchRequest(request);
|
||||
else if (request.starts_with("keyword"))
|
||||
return dispatchKeyword(request);
|
||||
else if (request.starts_with("setcursor"))
|
||||
return dispatchSetCursor(request);
|
||||
else if (request.starts_with("getoption"))
|
||||
return dispatchGetOption(request, format);
|
||||
else if (request.starts_with("decorations"))
|
||||
return decorationRequest(request, format);
|
||||
else if (request.starts_with("[[BATCH]]"))
|
||||
return dispatchBatch(request);
|
||||
std::string result = "";
|
||||
|
||||
return "unknown request";
|
||||
// parse exact cmds first, then non-exact.
|
||||
for (auto& cmd : m_vCommands) {
|
||||
if (!cmd->exact)
|
||||
continue;
|
||||
|
||||
if (cmd->name == request) {
|
||||
result = cmd->fn(format, request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.empty())
|
||||
for (auto& cmd : m_vCommands) {
|
||||
if (cmd->exact)
|
||||
continue;
|
||||
|
||||
if (request.starts_with(cmd->name)) {
|
||||
result = cmd->fn(format, request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.empty())
|
||||
return "unknown request";
|
||||
|
||||
if (reloadAll) {
|
||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
g_pInputManager->setPointerConfigs(); // update mouse cfgs
|
||||
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
|
||||
g_pInputManager->setTabletConfigs(); // update tablets
|
||||
|
||||
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("general:layout");
|
||||
|
||||
g_pLayoutManager->switchToLayout(*PLAYOUT); // update layout
|
||||
|
||||
g_pHyprOpenGL->m_bReloadScreenShader = true;
|
||||
|
||||
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
|
||||
rd.blurFBDirty = true;
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string HyprCtl::makeDynamicCall(const std::string& input) {
|
||||
std::string CHyprCtl::makeDynamicCall(const std::string& input) {
|
||||
return getReply(input);
|
||||
}
|
||||
|
||||
@@ -1460,7 +1571,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
std::array<char, 1024> readBuffer;
|
||||
|
||||
@@ -1490,7 +1601,7 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
std::string reply = "";
|
||||
|
||||
try {
|
||||
reply = getReply(request);
|
||||
reply = g_pHyprCtl->getReply(request);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Error in request: {}", e.what());
|
||||
reply = "Err: " + std::string(e.what());
|
||||
@@ -1500,18 +1611,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->ensureMonitorStatus();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HyprCtl::startHyprCtlSocket() {
|
||||
void CHyprCtl::startHyprCtlSocket() {
|
||||
|
||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (iSocketFD < 0) {
|
||||
if (m_iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
@@ -1522,15 +1632,15 @@ void HyprCtl::startHyprCtlSocket() {
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
|
||||
if (bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 10 max queued.
|
||||
listen(iSocketFD, 10);
|
||||
listen(m_iSocketFD, 10);
|
||||
|
||||
Debug::log(LOG, "Hypr socket started at {}", socketPath);
|
||||
|
||||
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
}
|
||||
|
@@ -3,24 +3,23 @@
|
||||
#include "../Compositor.hpp"
|
||||
#include <fstream>
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace HyprCtl {
|
||||
void startHyprCtlSocket();
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
|
||||
// very simple thread-safe request method
|
||||
inline bool requestMade = false;
|
||||
inline bool requestReady = false;
|
||||
inline std::string request = "";
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
std::shared_ptr<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd);
|
||||
std::string getReply(std::string);
|
||||
|
||||
inline std::ifstream requestStream;
|
||||
int m_iSocketFD = -1;
|
||||
|
||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
||||
private:
|
||||
void startHyprCtlSocket();
|
||||
|
||||
inline int iSocketFD = -1;
|
||||
std::vector<std::shared_ptr<SHyprCtlCommand>> m_vCommands;
|
||||
};
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
};
|
||||
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
@@ -226,4 +226,8 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
||||
|
||||
bool CHyprNotificationOverlay::hasAny() {
|
||||
return !m_dNotifications.empty();
|
||||
}
|
@@ -41,6 +41,7 @@ class CHyprNotificationOverlay {
|
||||
|
||||
void draw(CMonitor* pMonitor);
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||
bool hasAny();
|
||||
|
||||
private:
|
||||
CBox drawNotifications(CMonitor* pMonitor);
|
||||
|
@@ -22,7 +22,7 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||
|
||||
rollingLog += output + "\n";
|
||||
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
|
@@ -21,16 +21,16 @@ enum LogLevel {
|
||||
};
|
||||
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline int64_t* disableLogs = nullptr;
|
||||
inline int64_t* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
inline bool trace = false;
|
||||
inline bool shuttingDown = false;
|
||||
inline std::string logFile;
|
||||
inline int64_t* const* disableLogs = nullptr;
|
||||
inline int64_t* const* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
inline bool trace = false;
|
||||
inline bool shuttingDown = false;
|
||||
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
|
||||
void init(const std::string& IS);
|
||||
void init(const std::string& IS);
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
if (level == TRACE && !trace)
|
||||
@@ -52,7 +52,7 @@ namespace Debug {
|
||||
}
|
||||
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !*disableTime) {
|
||||
if (disableTime && !**disableTime) {
|
||||
#ifndef _LIBCPP_VERSION
|
||||
logMsg += std::format("[{:%T}] ", std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())});
|
||||
#else
|
||||
@@ -73,7 +73,7 @@ namespace Debug {
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
|
@@ -174,4 +174,7 @@ namespace Events {
|
||||
|
||||
// Tearing hints
|
||||
LISTENER(newTearingHint);
|
||||
|
||||
// Shortcut inhibitor
|
||||
LISTENER(newShortcutInhibitor);
|
||||
};
|
||||
|
@@ -142,6 +142,9 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
|
||||
if (layersurface->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||
g_pInputManager->m_dExclusiveLSes.push_back(layersurface);
|
||||
|
||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||
// don't focus if constrained
|
||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
@@ -183,6 +186,11 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
||||
|
||||
std::erase(g_pInputManager->m_dExclusiveLSes, layersurface);
|
||||
|
||||
if (!g_pInputManager->m_dExclusiveLSes.empty())
|
||||
g_pCompositor->focusSurface(g_pInputManager->m_dExclusiveLSes[0]->layerSurface->surface);
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||
|
||||
|
@@ -128,6 +128,8 @@ void Events::listener_destroyDrag(void* owner, void* data) {
|
||||
g_pInputManager->m_sDrag.drag = nullptr;
|
||||
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
||||
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
||||
|
||||
g_pCompositor->focusWindow(g_pCompositor->m_pLastWindow, g_pCompositor->m_pLastWindow ? g_pXWaylandManager->getWindowSurface(g_pCompositor->m_pLastWindow) : nullptr);
|
||||
}
|
||||
|
||||
void Events::listener_mapDragIcon(void* owner, void* data) {
|
||||
@@ -175,11 +177,17 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) {
|
||||
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "PowerMgr set mode!");
|
||||
|
||||
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
||||
const auto EVENT = (wlr_output_power_v1_set_mode_event*)data;
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(EVENT->output);
|
||||
|
||||
wlr_output_enable(EVENT->output, EVENT->mode == 1);
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Invalid powerMgrSetMode output");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wlr_output_commit(EVENT->output))
|
||||
wlr_output_state_set_enabled(PMONITOR->state.wlr(), EVENT->mode == 1);
|
||||
|
||||
if (!PMONITOR->state.commit())
|
||||
Debug::log(ERR, "Couldn't set power mode");
|
||||
}
|
||||
|
||||
@@ -225,16 +233,7 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
|
||||
}
|
||||
|
||||
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||
const auto TCTL = (wlr_tearing_control_v1*)data;
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TCTL->surface);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "Tearing hint {} was attached to an unknown surface", (uintptr_t)data);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "New tearing hint for window {} at {}", PWINDOW, (uintptr_t)data);
|
||||
Debug::log(LOG, "New tearing hint at {:x}", (uintptr_t)data);
|
||||
|
||||
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
||||
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
||||
@@ -242,7 +241,7 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||
NEWCTRL->hyprListener_destroy.initCallback(
|
||||
&NEWCTRL->pWlrHint->events.destroy,
|
||||
[&](void* owner, void* data) {
|
||||
Debug::log(LOG, "Destroyed {} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
||||
Debug::log(LOG, "Destroyed {:x} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
||||
|
||||
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
||||
},
|
||||
@@ -256,10 +255,27 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
|
||||
|
||||
if (PWINDOW) {
|
||||
PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint;
|
||||
PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current;
|
||||
|
||||
Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->hint);
|
||||
Debug::log(LOG, "Hint {:x} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current);
|
||||
}
|
||||
},
|
||||
NEWCTRL, "TearingController");
|
||||
}
|
||||
|
||||
void Events::listener_newShortcutInhibitor(wl_listener* listener, void* data) {
|
||||
const auto INHIBITOR = (wlr_keyboard_shortcuts_inhibitor_v1*)data;
|
||||
|
||||
const auto PINH = &g_pKeybindManager->m_lShortcutInhibitors.emplace_back();
|
||||
PINH->hyprListener_destroy.initCallback(
|
||||
&INHIBITOR->events.destroy,
|
||||
[](void* owner, void* data) {
|
||||
const auto OWNER = (SShortcutInhibitor*)owner;
|
||||
g_pKeybindManager->m_lShortcutInhibitors.remove(*OWNER);
|
||||
},
|
||||
PINH, "ShortcutInhibitor");
|
||||
|
||||
PINH->pWlrInhibitor = INHIBITOR;
|
||||
|
||||
Debug::log(LOG, "New shortcut inhibitor for surface {:x}", (uintptr_t)INHIBITOR->surface);
|
||||
}
|
||||
|
@@ -109,7 +109,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||
w->m_iLastSurfaceMonitorID = -1;
|
||||
w->updateSurfaceOutputs();
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,12 +147,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
PMONITOR->tearingState.frameScheduledWhileBusy = false;
|
||||
}
|
||||
|
||||
static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
|
||||
static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
|
||||
static auto* const PENABLERAT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time");
|
||||
static auto* const PRATSAFE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone");
|
||||
|
||||
PMONITOR->lastPresentationTimer.reset();
|
||||
|
||||
if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||
if (**PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||
if (!PMONITOR->RATScheduled) {
|
||||
// render
|
||||
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||
@@ -162,14 +162,14 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
|
||||
const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
|
||||
|
||||
if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||
if (max + **PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||
return;
|
||||
|
||||
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
|
||||
|
||||
PMONITOR->RATScheduled = true;
|
||||
|
||||
const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
|
||||
const auto ESTRENDERTIME = std::ceil(avg + **PRATSAFE);
|
||||
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
|
||||
|
||||
if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
|
||||
@@ -212,7 +212,17 @@ void Events::listener_monitorStateRequest(void* owner, void* data) {
|
||||
const auto PMONITOR = (CMonitor*)owner;
|
||||
const auto E = (wlr_output_event_request_state*)data;
|
||||
|
||||
wlr_output_commit_state(PMONITOR->output, E->state);
|
||||
if (!PMONITOR->createdByUser)
|
||||
return;
|
||||
|
||||
const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
|
||||
|
||||
PMONITOR->forceSize = SIZE;
|
||||
|
||||
SMonitorRule rule = PMONITOR->activeMonitorRule;
|
||||
rule.resolution = SIZE;
|
||||
|
||||
g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
|
||||
}
|
||||
|
||||
void Events::listener_monitorDamage(void* owner, void* data) {
|
||||
|
@@ -55,7 +55,7 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
pHyprPopup->popup = popup;
|
||||
|
||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
|
||||
@@ -228,6 +228,11 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
void Events::listener_commitPopupXDG(void* owner, void* data) {
|
||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
||||
|
||||
if (PPOPUP->popup->base->initial_commit) {
|
||||
wlr_xdg_surface_schedule_configure(PPOPUP->popup->base);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) {
|
||||
PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x;
|
||||
PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y;
|
||||
|
@@ -40,17 +40,16 @@ void setAnimToMove(void* data) {
|
||||
void Events::listener_mapWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
|
||||
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
|
||||
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
|
||||
static auto* const PSWALLOWEXREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex")->strValue;
|
||||
static auto* const PNEWTAKESOVERFS = &g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen")->intValue;
|
||||
static auto* const PINACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity");
|
||||
static auto* const PACTIVEALPHA = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:active_opacity");
|
||||
static auto* const PDIMSTRENGTH = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("decoration:dim_strength");
|
||||
static auto* const PSWALLOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:enable_swallow");
|
||||
static auto* const PSWALLOWREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_regex");
|
||||
static auto* const PSWALLOWEXREGEX = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex");
|
||||
static auto* const PNEWTAKESOVERFS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen");
|
||||
|
||||
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PWORKSPACE =
|
||||
PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||
PWINDOW->m_bIsMapped = true;
|
||||
@@ -101,7 +100,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// window rules
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||
std::string requestedWorkspace = "";
|
||||
bool workspaceSilent = false;
|
||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
||||
@@ -173,13 +172,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
} else if (r.szRule.starts_with("pseudo")) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.starts_with("nofocus")) {
|
||||
PWINDOW->m_bNoFocus = true;
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus = true;
|
||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
} else if (r.szRule.starts_with("nofullscreenrequest")) {
|
||||
PWINDOW->m_bNoFullscreenRequest = true;
|
||||
} else if (r.szRule.starts_with("nomaximizerequest")) {
|
||||
PWINDOW->m_bNoMaximizeRequest = true;
|
||||
} else if (r.szRule.starts_with("suppressevent")) {
|
||||
CVarList vars(r.szRule, 0, 's', true);
|
||||
for (size_t i = 1; i < vars.size(); ++i) {
|
||||
if (vars[i] == "fullscreen")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN;
|
||||
else if (vars[i] == "maximize")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_MAXIMIZE;
|
||||
else if (vars[i] == "activate")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
|
||||
else if (vars[i] == "activatefocus")
|
||||
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
||||
else
|
||||
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
||||
}
|
||||
} else if (r.szRule == "fullscreen") {
|
||||
requestsFullscreen = true;
|
||||
overridingNoFullscreen = true;
|
||||
@@ -270,6 +279,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (!pWorkspace)
|
||||
pWorkspace = g_pCompositor->createNewWorkspace(REQUESTEDWORKSPACEID, PWINDOW->m_iMonitorID, requestedWorkspaceName);
|
||||
|
||||
PWORKSPACE = pWorkspace;
|
||||
|
||||
PWINDOW->m_iWorkspaceID = pWorkspace->m_iID;
|
||||
PWINDOW->m_iMonitorID = pWorkspace->m_iMonitorID;
|
||||
|
||||
@@ -443,9 +454,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
|
||||
PWINDOW->m_bNoFocus = false;
|
||||
PWINDOW->m_bNoInitialFocus = false;
|
||||
PWINDOW->m_bX11ShouldntFocus = false;
|
||||
PWINDOW->m_sAdditionalConfigData.noFocus = false;
|
||||
PWINDOW->m_bNoInitialFocus = false;
|
||||
PWINDOW->m_bX11ShouldntFocus = false;
|
||||
}
|
||||
|
||||
// check LS focus grab
|
||||
@@ -454,9 +465,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||
if (*PNEWTAKESOVERFS == 0)
|
||||
if (**PNEWTAKESOVERFS == 0)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
else if (**PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
||||
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
||||
requestsMaximize = true;
|
||||
@@ -464,14 +475,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
requestsFullscreen = true;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
|
||||
if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus &&
|
||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
|
||||
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : *PDIMSTRENGTH);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH);
|
||||
} else {
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PINACTIVEALPHA);
|
||||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||
}
|
||||
|
||||
@@ -504,8 +515,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
"XWayland Window Late");
|
||||
}
|
||||
|
||||
if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) ||
|
||||
requestsFakeFullscreen) {
|
||||
if ((requestsFullscreen && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN) || overridingNoFullscreen)) ||
|
||||
(requestsMaximize && (!(PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE) || overridingNoMaximize)) || requestsFakeFullscreen) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
@@ -540,7 +551,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// verify swallowing
|
||||
if (*PSWALLOW && *PSWALLOWREGEX != STRVAL_EMPTY) {
|
||||
if (**PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
||||
// don't swallow ourselves
|
||||
std::regex rgx(*PSWALLOWREGEX);
|
||||
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
|
||||
@@ -587,7 +598,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (finalFound) {
|
||||
bool valid = std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx);
|
||||
|
||||
if (*PSWALLOWEXREGEX != STRVAL_EMPTY) {
|
||||
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
||||
std::regex exc(*PSWALLOWEXREGEX);
|
||||
|
||||
valid = valid && !std::regex_match(g_pXWaylandManager->getTitle(finalFound), exc);
|
||||
@@ -639,7 +650,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
|
||||
// fix some xwayland apps that don't behave nicely
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||
@@ -793,6 +805,11 @@ void Events::listener_ackConfigure(void* owner, void* data) {
|
||||
void Events::listener_commitWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) {
|
||||
wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden())
|
||||
return;
|
||||
|
||||
@@ -803,8 +820,6 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
PWINDOW->m_pPendingSizeAck.reset();
|
||||
}
|
||||
|
||||
PWINDOW->updateSurfaceOutputs();
|
||||
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
|
||||
|
||||
@@ -906,7 +921,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
|
||||
if (PWINDOW->isHidden() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
|
||||
return;
|
||||
|
||||
bool requestedFullState = false;
|
||||
@@ -960,7 +975,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
|
||||
|
||||
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
|
||||
static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate");
|
||||
|
||||
Debug::log(LOG, "Activate request for surface at {:x}", (uintptr_t)E->surface);
|
||||
|
||||
@@ -969,7 +984,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
|
||||
|
||||
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
|
||||
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
|
||||
return;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
||||
@@ -977,7 +992,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||
|
||||
PWINDOW->m_bIsUrgent = true;
|
||||
|
||||
if (!*PFOCUSONACTIVATE)
|
||||
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||
return;
|
||||
|
||||
if (PWINDOW->m_bIsFloating)
|
||||
@@ -990,7 +1005,7 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
|
||||
void Events::listener_activateX11(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
|
||||
static auto* const PFOCUSONACTIVATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:focus_on_activate");
|
||||
|
||||
Debug::log(LOG, "X11 Activate request for window {}", PWINDOW);
|
||||
|
||||
@@ -1001,17 +1016,20 @@ void Events::listener_activateX11(void* owner, void* data) {
|
||||
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->getPID() != PWINDOW->getPID())
|
||||
return;
|
||||
|
||||
if (!wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))
|
||||
return;
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow)
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
|
||||
return;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)PWINDOW)});
|
||||
EMIT_HOOK_EVENT("urgent", PWINDOW);
|
||||
|
||||
if (!*PFOCUSONACTIVATE)
|
||||
if (!**PFOCUSONACTIVATE || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
|
||||
return;
|
||||
|
||||
if (PWINDOW->m_bIsFloating)
|
||||
@@ -1052,13 +1070,10 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(LOGICALPOS);
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
if (**PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
@@ -1106,7 +1121,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
|
||||
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y});
|
||||
|
||||
@@ -1121,7 +1136,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
||||
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (**PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
@@ -1139,8 +1154,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vRealSize.goalv();
|
||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vReportedSize;
|
||||
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goalv();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,7 +1225,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
|
||||
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (PWINDOW->m_bNoMaximizeRequest)
|
||||
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_MAXIMIZE)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Maximize request for {}", PWINDOW);
|
||||
|
@@ -75,6 +75,9 @@ float CAnimatedVariable::getPercent() {
|
||||
}
|
||||
|
||||
float CAnimatedVariable::getCurveValue() {
|
||||
if (!m_bIsBeingAnimated)
|
||||
return 1.f;
|
||||
|
||||
const auto SPENT = getPercent();
|
||||
|
||||
if (SPENT >= 1.f)
|
||||
|
@@ -1,4 +1,8 @@
|
||||
#include "Box.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
wlr_box CBox::wlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
@@ -105,6 +109,13 @@ CBox& CBox::expand(const double& value) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::noNegativeSize() {
|
||||
std::clamp(w, 0.0, std::numeric_limits<double>::infinity());
|
||||
std::clamp(h, 0.0, std::numeric_limits<double>::infinity());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox CBox::roundInternal() {
|
||||
float newW = x + w - std::floor(x);
|
||||
float newH = y + h - std::floor(y);
|
||||
|
@@ -51,6 +51,7 @@ class CBox {
|
||||
CBox& transform(const wl_output_transform t, double w, double h);
|
||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||
CBox& expand(const double& value);
|
||||
CBox& noNegativeSize();
|
||||
|
||||
CBox copy() const;
|
||||
|
||||
@@ -73,6 +74,8 @@ class CBox {
|
||||
double height;
|
||||
};
|
||||
|
||||
double rot = 0; /* rad, ccw */
|
||||
|
||||
//
|
||||
bool operator==(const CBox& rhs) const {
|
||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||
|
@@ -159,6 +159,13 @@ void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const
|
||||
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
|
||||
}
|
||||
|
||||
void removeWLSignal(wl_listener* pListener) {
|
||||
wl_list_remove(&pListener->link);
|
||||
wl_list_init(&pListener->link);
|
||||
|
||||
Debug::log(LOG, "Removed listener {:x}", (uintptr_t)pListener);
|
||||
}
|
||||
|
||||
void handleNoop(struct wl_listener* listener, void* data) {
|
||||
// Do nothing
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ struct SCallstackFrameInfo {
|
||||
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
void removeWLSignal(wl_listener*);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
std::string removeBeginEndSpacesTabs(std::string);
|
||||
bool isNumber(const std::string&, bool allowfloat = false);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "Monitor.hpp"
|
||||
|
||||
#include "MiscFunctions.hpp"
|
||||
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
int ratHandler(void* data) {
|
||||
@@ -8,7 +10,7 @@ int ratHandler(void* data) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMonitor::CMonitor() {
|
||||
CMonitor::CMonitor() : state(this) {
|
||||
wlr_damage_ring_init(&damage);
|
||||
}
|
||||
|
||||
@@ -43,8 +45,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
||||
|
||||
if (m_bEnabled) {
|
||||
wlr_output_enable(output, 1);
|
||||
wlr_output_commit(output);
|
||||
wlr_output_state_set_enabled(state.wlr(), true);
|
||||
state.commit();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,17 +56,21 @@ void CMonitor::onConnect(bool noRule) {
|
||||
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
||||
szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end());
|
||||
|
||||
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
||||
szShortDescription =
|
||||
removeBeginEndSpacesTabs(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : ""));
|
||||
|
||||
if (!wlr_backend_is_drm(output->backend))
|
||||
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
||||
|
||||
// get monitor rule that matches
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
|
||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (monitorRule.disabled) {
|
||||
|
||||
wlr_output_set_scale(output, 1);
|
||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
wlr_output_state_set_scale(state.wlr(), 1);
|
||||
wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
||||
|
||||
@@ -72,9 +78,9 @@ void CMonitor::onConnect(bool noRule) {
|
||||
wlr_output_mode* mode;
|
||||
|
||||
wl_list_for_each(mode, &output->modes, link) {
|
||||
wlr_output_set_mode(output, PREFSTATE);
|
||||
wlr_output_state_set_mode(state.wlr(), mode);
|
||||
|
||||
if (!wlr_output_test(output))
|
||||
if (!wlr_output_test_state(output, state.wlr()))
|
||||
continue;
|
||||
|
||||
PREFSTATE = mode;
|
||||
@@ -83,13 +89,13 @@ void CMonitor::onConnect(bool noRule) {
|
||||
}
|
||||
|
||||
if (PREFSTATE)
|
||||
wlr_output_set_mode(output, PREFSTATE);
|
||||
wlr_output_state_set_mode(state.wlr(), PREFSTATE);
|
||||
else
|
||||
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
||||
|
||||
wlr_output_enable(output, 0);
|
||||
wlr_output_state_set_enabled(state.wlr(), 0);
|
||||
|
||||
if (!wlr_output_commit(output))
|
||||
if (!state.commit())
|
||||
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
||||
|
||||
m_bEnabled = false;
|
||||
@@ -130,13 +136,28 @@ void CMonitor::onConnect(bool noRule) {
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
wlr_output_enable(output, 1);
|
||||
wlr_output_state_set_enabled(state.wlr(), 1);
|
||||
|
||||
// set mode, also applies
|
||||
if (!noRule)
|
||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||
|
||||
wlr_output_commit(output);
|
||||
for (const auto& PTOUCHDEV : g_pInputManager->m_lTouchDevices) {
|
||||
if (matchesStaticSelector(PTOUCHDEV.boundOutput)) {
|
||||
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV.name, szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV.pWlrDevice, output);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& PTABLET : g_pInputManager->m_lTablets) {
|
||||
if (matchesStaticSelector(PTABLET.boundOutput)) {
|
||||
Debug::log(LOG, "Binding tablet {} to output {}", PTABLET.name, szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTABLET.wlrDevice, output);
|
||||
}
|
||||
}
|
||||
|
||||
if (!state.commit())
|
||||
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onCommit");
|
||||
|
||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||
|
||||
@@ -162,6 +183,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
//
|
||||
|
||||
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
|
||||
@@ -283,9 +305,10 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||
if (!destroy)
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
|
||||
wlr_output_enable(output, false);
|
||||
wlr_output_state_set_enabled(state.wlr(), false);
|
||||
|
||||
wlr_output_commit(output);
|
||||
if (!state.commit())
|
||||
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect");
|
||||
|
||||
if (g_pCompositor->m_pLastMonitor == this)
|
||||
g_pCompositor->setActiveMonitor(BACKUPMON);
|
||||
@@ -307,13 +330,11 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||
}
|
||||
|
||||
void CMonitor::addDamage(const pixman_region32_t* rg) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
if (wlr_damage_ring_add(&damage, rg))
|
||||
} else if (wlr_damage_ring_add(&damage, rg))
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
@@ -322,8 +343,8 @@ void CMonitor::addDamage(const CRegion* rg) {
|
||||
}
|
||||
|
||||
void CMonitor::addDamage(const CBox* box) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||
if (**PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
@@ -336,6 +357,19 @@ bool CMonitor::isMirror() {
|
||||
return pMirrorOf != nullptr;
|
||||
}
|
||||
|
||||
bool CMonitor::matchesStaticSelector(const std::string& selector) const {
|
||||
if (selector.starts_with("desc:")) {
|
||||
// match by description
|
||||
const auto DESCRIPTIONSELECTOR = selector.substr(5);
|
||||
const auto DESCRIPTION = removeBeginEndSpacesTabs(szDescription.substr(0, szDescription.find_first_of('(')));
|
||||
|
||||
return DESCRIPTIONSELECTOR == szDescription || DESCRIPTIONSELECTOR == DESCRIPTION;
|
||||
} else {
|
||||
// match by selector
|
||||
return szName == selector;
|
||||
}
|
||||
}
|
||||
|
||||
int CMonitor::findAvailableDefaultWS() {
|
||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||
if (g_pCompositor->getWorkspaceByID(i))
|
||||
@@ -415,7 +449,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName, this->output->description ? this->output->description : "");
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(*this);
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
@@ -502,7 +536,7 @@ float CMonitor::getDefaultScale() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove) {
|
||||
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove, bool noFocus) {
|
||||
if (!pWorkspace)
|
||||
return;
|
||||
|
||||
@@ -533,13 +567,13 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) {
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
CWindow* pWindow = pWorkspace->getLastFocusedWindow();
|
||||
|
||||
if (!pWindow) {
|
||||
if (*PFOLLOWMOUSE == 1)
|
||||
pWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
|
||||
if (**PFOLLOWMOUSE == 1)
|
||||
pWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindow)
|
||||
pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID);
|
||||
@@ -569,8 +603,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||
g_pCompositor->updateSuspendedStates();
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal);
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) {
|
||||
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
|
||||
}
|
||||
|
||||
void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||
@@ -621,7 +655,7 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||
w->m_iMonitorID = ID;
|
||||
w->updateSurfaceOutputs();
|
||||
w->updateSurfaceScaleTransformDetails();
|
||||
|
||||
const auto MIDDLE = w->middle();
|
||||
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) {
|
||||
@@ -678,3 +712,32 @@ void CMonitor::updateMatrix() {
|
||||
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||
m_pOwner = owner;
|
||||
wlr_output_state_init(&m_state);
|
||||
}
|
||||
|
||||
CMonitorState::~CMonitorState() {
|
||||
wlr_output_state_finish(&m_state);
|
||||
}
|
||||
|
||||
wlr_output_state* CMonitorState::wlr() {
|
||||
return &m_state;
|
||||
}
|
||||
|
||||
void CMonitorState::clear() {
|
||||
wlr_output_state_finish(&m_state);
|
||||
m_state = {0};
|
||||
wlr_output_state_init(&m_state);
|
||||
}
|
||||
|
||||
bool CMonitorState::commit() {
|
||||
bool ret = wlr_output_commit_state(m_pOwner->output, &m_state);
|
||||
clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMonitorState::test() {
|
||||
return wlr_output_test_state(m_pOwner->output, &m_state);
|
||||
}
|
||||
|
@@ -25,6 +25,25 @@ struct SMonitorRule {
|
||||
std::optional<int> vrr;
|
||||
};
|
||||
|
||||
class CMonitor;
|
||||
|
||||
// Class for wrapping the wlr state
|
||||
class CMonitorState {
|
||||
public:
|
||||
CMonitorState(CMonitor* owner);
|
||||
~CMonitorState();
|
||||
|
||||
wlr_output_state* wlr();
|
||||
void clear();
|
||||
// commit() will also clear()
|
||||
bool commit();
|
||||
bool test();
|
||||
|
||||
private:
|
||||
wlr_output_state m_state = {0};
|
||||
CMonitor* m_pOwner;
|
||||
};
|
||||
|
||||
class CMonitor {
|
||||
public:
|
||||
CMonitor();
|
||||
@@ -43,49 +62,51 @@ class CMonitor {
|
||||
float setScale = 1; // scale set by cfg
|
||||
float scale = 1; // real scale
|
||||
|
||||
std::string szName = "";
|
||||
std::string szDescription = "";
|
||||
std::string szName = "";
|
||||
std::string szDescription = "";
|
||||
std::string szShortDescription = "";
|
||||
|
||||
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||
|
||||
drmModeModeInfo customDrmMode = {};
|
||||
|
||||
CMonitorState state;
|
||||
|
||||
// WLR stuff
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
float refreshRate = 60;
|
||||
int framesToSkip = 0;
|
||||
int forceFullFrames = 0;
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
float refreshRate = 60;
|
||||
int framesToSkip = 0;
|
||||
int forceFullFrames = 0;
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
std::optional<Vector2D> forceSize;
|
||||
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
bool isUnsafeFallback = false;
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
bool isUnsafeFallback = false;
|
||||
|
||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool renderingActive = false;
|
||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool renderingActive = false;
|
||||
|
||||
wl_event_source* renderTimer = nullptr; // for RAT
|
||||
bool RATScheduled = false;
|
||||
CTimer lastPresentationTimer;
|
||||
wl_event_source* renderTimer = nullptr; // for RAT
|
||||
bool RATScheduled = false;
|
||||
CTimer lastPresentationTimer;
|
||||
|
||||
SMonitorRule activeMonitorRule;
|
||||
SMonitorRule activeMonitorRule;
|
||||
|
||||
// mirroring
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
CRegion lastFrameDamage; // stores last frame damage
|
||||
|
||||
// for tearing
|
||||
CWindow* solitaryClient = nullptr;
|
||||
|
||||
@@ -119,9 +140,10 @@ class CMonitor {
|
||||
void addDamage(const CBox* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
bool matchesStaticSelector(const std::string& selector) const;
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
|
@@ -112,6 +112,11 @@ CRegion& CRegion::scale(float scale) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::scale(const Vector2D& scale) {
|
||||
wlr_region_scale_xy(&m_rRegion, &m_rRegion, scale.x, scale.y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<pixman_box32_t> CRegion::getRects() const {
|
||||
std::vector<pixman_box32_t> result;
|
||||
|
||||
|
@@ -49,6 +49,7 @@ class CRegion {
|
||||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CRegion& scale(const Vector2D& scale);
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
@@ -57,7 +58,8 @@ class CRegion {
|
||||
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
pixman_region32_t* pixman() {
|
||||
//
|
||||
pixman_region32_t* pixman() {
|
||||
return &m_rRegion;
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,21 @@ inline const std::vector<std::string> SPLASHES = {
|
||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||
"To rice, or not to rice, that is the question.",
|
||||
"Now available on Fedora!",
|
||||
"\"Hyprland is so good it starts with a capital letter\" - Hazel",
|
||||
"\"please make this message a splash\" - eriedaberrie",
|
||||
"\"the only wayland compositor powered by fried chicken\" - raf",
|
||||
"\"This will never get into Hyprland\" - Flafy",
|
||||
"\"Hyprland only gives you up on -git\" - fazzi",
|
||||
"Segmentation fault (core dumped)",
|
||||
"\"disabling hyprland logo is a war crime\" - vaxry",
|
||||
"some basic startup code",
|
||||
"\"I think I am addicted to hyprland\" - mathisbuilder",
|
||||
"\"hyprland is the most important package in the arch repos\" - jacekpoz",
|
||||
"Thanks Brodie!",
|
||||
"Thanks fufexan!",
|
||||
"Thanks raf!",
|
||||
"You can't use --splash to change this message :)",
|
||||
"Hyprland will overtake Gnome in popularity by [insert year]",
|
||||
// music reference / quote section
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||
|
@@ -178,6 +178,9 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
||||
Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface);
|
||||
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||
|
||||
if (subsurface->pWindowOwner)
|
||||
subsurface->pWindowOwner->updateSurfaceScaleTransformDetails();
|
||||
}
|
||||
|
||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
@@ -222,8 +225,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
||||
pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{};
|
||||
|
||||
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
if (*PLOGDAMAGE)
|
||||
static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage");
|
||||
if (**PLOGDAMAGE)
|
||||
Debug::log(LOG, "Refusing to commit damage from {} because it's invisible.", pNode->pWindowOwner);
|
||||
return;
|
||||
}
|
||||
@@ -259,13 +262,11 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
||||
if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||
if (PMONITOR && PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||
pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
||||
CRegion damageBox;
|
||||
wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman());
|
||||
CRegion damageBox{&pNode->pSurface->wlr()->buffer_damage};
|
||||
|
||||
if (!damageBox.empty()) {
|
||||
|
||||
if (PMONITOR->tearingState.busy) {
|
||||
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
||||
} else {
|
||||
|
@@ -12,6 +12,11 @@ Vector2D::Vector2D() {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
Vector2D::Vector2D(const Hyprlang::VEC2& ref) {
|
||||
x = ref.x;
|
||||
y = ref.y;
|
||||
}
|
||||
|
||||
Vector2D::~Vector2D() {}
|
||||
|
||||
double Vector2D::normalize() {
|
||||
@@ -42,14 +47,10 @@ double Vector2D::distance(const Vector2D& other) const {
|
||||
return std::sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const {
|
||||
const auto a = ((p2.y - p3.y) * (x - p3.x) + (p3.x - p2.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
||||
const auto b = ((p3.y - p1.y) * (x - p3.x) + (p1.x - p3.x) * (y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
|
||||
const auto c = 1 - a - b;
|
||||
|
||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
||||
}
|
||||
|
||||
double Vector2D::size() const {
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Vector2D Vector2D::getComponentMax(const Vector2D& other) const {
|
||||
return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y));
|
||||
}
|
||||
|
@@ -3,12 +3,14 @@
|
||||
#include <cmath>
|
||||
#include <format>
|
||||
#include "../macros.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
class Vector2D {
|
||||
public:
|
||||
Vector2D(double, double);
|
||||
Vector2D();
|
||||
~Vector2D();
|
||||
Vector2D(const Hyprlang::VEC2&);
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
@@ -88,12 +90,12 @@ class Vector2D {
|
||||
|
||||
double distance(const Vector2D& other) const;
|
||||
double size() const;
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const;
|
||||
|
||||
Vector2D floor() const;
|
||||
Vector2D round() const;
|
||||
|
||||
bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
|
||||
Vector2D getComponentMax(const Vector2D& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -127,15 +127,17 @@ struct SKeyboard {
|
||||
bool active = false;
|
||||
bool enabled = true;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state* xkbTranslationState = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
std::string xkbFilePath = "";
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
int repeatDelay = 0;
|
||||
int numlockOn = -1;
|
||||
int repeatRate = 0;
|
||||
int repeatDelay = 0;
|
||||
int numlockOn = -1;
|
||||
bool resolveBindsBySym = false;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SKeyboard& rhs) const {
|
||||
@@ -259,6 +261,8 @@ struct STablet {
|
||||
|
||||
std::string name = "";
|
||||
|
||||
std::string boundOutput = "";
|
||||
|
||||
//
|
||||
bool operator==(const STablet& b) const {
|
||||
return wlrDevice == b.wlrDevice;
|
||||
@@ -410,3 +414,13 @@ struct STearingController {
|
||||
return pWlrHint == other.pWlrHint;
|
||||
}
|
||||
};
|
||||
|
||||
struct SShortcutInhibitor {
|
||||
wlr_keyboard_shortcuts_inhibitor_v1* pWlrInhibitor = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const SShortcutInhibitor& other) {
|
||||
return pWlrInhibitor == other.pWlrInhibitor;
|
||||
}
|
||||
};
|
||||
|
@@ -7,13 +7,15 @@
|
||||
void handleWrapped(wl_listener* listener, void* data) {
|
||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||
|
||||
g_pWatchdog->startWatching();
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->startWatching();
|
||||
|
||||
try {
|
||||
pWrap->m_pSelf->emit(data);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||
|
||||
g_pWatchdog->endWatching();
|
||||
if (g_pWatchdog)
|
||||
g_pWatchdog->endWatching();
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||
|
@@ -52,6 +52,29 @@ Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||
}
|
||||
|
||||
CRegion CWLSurface::logicalDamage() const {
|
||||
CRegion damage{&m_pWLRSurface->buffer_damage};
|
||||
damage.transform(m_pWLRSurface->current.transform, m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height);
|
||||
damage.scale(1.0 / m_pWLRSurface->current.scale);
|
||||
|
||||
const auto VPSIZE = getViewporterCorrectedSize();
|
||||
const auto CORRECTVEC = correctSmallVec();
|
||||
|
||||
if (m_pWLRSurface->current.viewport.has_src) {
|
||||
damage.intersect(CBox{std::floor(m_pWLRSurface->current.viewport.src.x), std::floor(m_pWLRSurface->current.viewport.src.y),
|
||||
std::ceil(m_pWLRSurface->current.viewport.src.width), std::ceil(m_pWLRSurface->current.viewport.src.height)});
|
||||
}
|
||||
|
||||
const auto SCALEDSRCSIZE = m_pWLRSurface->current.viewport.has_src ?
|
||||
Vector2D{m_pWLRSurface->current.viewport.src.width, m_pWLRSurface->current.viewport.src.height} * m_pWLRSurface->current.scale :
|
||||
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||
|
||||
damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y});
|
||||
damage.translate(CORRECTVEC);
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
void CWLSurface::destroy() {
|
||||
if (!m_pWLRSurface)
|
||||
return;
|
||||
@@ -60,11 +83,11 @@ void CWLSurface::destroy() {
|
||||
m_pWLRSurface->data = nullptr;
|
||||
m_pOwner = nullptr;
|
||||
|
||||
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||
if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||
if (g_pInputManager && g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||
g_pInputManager->m_pLastMouseSurface = nullptr;
|
||||
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||
if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||
g_pHyprRenderer->m_sLastCursorData.surf.reset();
|
||||
|
||||
m_pWLRSurface = nullptr;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "Region.hpp"
|
||||
|
||||
class CWindow;
|
||||
|
||||
@@ -23,13 +24,20 @@ class CWLSurface {
|
||||
bool small() const; // means surface is smaller than the requested size
|
||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||
Vector2D getViewporterCorrectedSize() const;
|
||||
CRegion logicalDamage() const;
|
||||
|
||||
// allow stretching. Useful for plugins.
|
||||
bool m_bFillIgnoreSmall = false;
|
||||
|
||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||
CWindow* m_pOwner = nullptr;
|
||||
CWindow* m_pOwner = nullptr;
|
||||
|
||||
// track surface data and avoid dupes
|
||||
float m_fLastScale = 0;
|
||||
int m_iLastScale = 0;
|
||||
wl_output_transform m_eLastTransform = (wl_output_transform)-1;
|
||||
|
||||
//
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
|
@@ -13,7 +13,7 @@ CWatchdog::CWatchdog() {
|
||||
m_iMainThreadPID = pthread_self();
|
||||
|
||||
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||
static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout");
|
||||
|
||||
while (1337) {
|
||||
std::unique_lock lk(m_mWatchdogMutex);
|
||||
@@ -21,7 +21,7 @@ CWatchdog::CWatchdog() {
|
||||
if (!m_bWillWatch)
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||
else {
|
||||
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(**PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ CWatchdog::CWatchdog() {
|
||||
}
|
||||
|
||||
void CWatchdog::startWatching() {
|
||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||
static auto* const PTIMEOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout");
|
||||
|
||||
if (*PTIMEOUT == 0)
|
||||
if (**PTIMEOUT == 0)
|
||||
return;
|
||||
|
||||
m_tTriggered = std::chrono::high_resolution_clock::now();
|
||||
|
@@ -24,6 +24,10 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||
m_vRenderOffset.registerVar();
|
||||
m_fAlpha.registerVar();
|
||||
|
||||
const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(this);
|
||||
if (RULEFORTHIS.defaultName.has_value())
|
||||
m_szName = RULEFORTHIS.defaultName.value();
|
||||
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||
}
|
||||
@@ -38,8 +42,8 @@ CWorkspace::~CWorkspace() {
|
||||
}
|
||||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
const auto PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue;
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces");
|
||||
|
||||
if (ANIMSTYLE.starts_with("slidefade")) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
@@ -91,7 +95,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
} else if (ANIMSTYLE == "slidevert") {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
|
||||
const auto YDISTANCE = PMONITOR->vecSize.y + **PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
@@ -104,7 +108,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
} else {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
|
||||
const auto XDISTANCE = PMONITOR->vecSize.x + **PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
|
@@ -4,13 +4,12 @@
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||
if (children[0]) {
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
|
||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||
static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split");
|
||||
static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
|
||||
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
||||
splitTop = box.h * *PFLMULT > box.w;
|
||||
}
|
||||
if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0)
|
||||
splitTop = box.h * **PFLMULT > box.w;
|
||||
|
||||
if (verticalOverride == true)
|
||||
splitTop = true;
|
||||
@@ -22,13 +21,13 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
if (SPLITSIDE) {
|
||||
// split left/right
|
||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h};
|
||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h}.noNegativeSize();
|
||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h}.noNegativeSize();
|
||||
} else {
|
||||
// split top/bottom
|
||||
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE};
|
||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE}.noNegativeSize();
|
||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}.noNegativeSize();
|
||||
}
|
||||
|
||||
children[0]->recalcSizePosRecursive(force);
|
||||
@@ -64,6 +63,21 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) {
|
||||
SDwindleNodeData* res = nullptr;
|
||||
double distClosest = -1;
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (n.workspaceID == id && n.pWindow && g_pCompositor->windowValidMapped(n.pWindow)) {
|
||||
auto distAnother = vecToRectDistanceSquared(point, n.box.pos(), n.box.pos() + n.box.size());
|
||||
if (!res || distAnother < distClosest) {
|
||||
res = &n;
|
||||
distClosest = distAnother;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
|
||||
for (auto& n : m_lDwindleNodesData) {
|
||||
if (n.pWindow == pWindow && !n.isNode)
|
||||
@@ -120,9 +134,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only");
|
||||
static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in");
|
||||
static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out");
|
||||
auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData();
|
||||
auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData();
|
||||
|
||||
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
||||
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||
@@ -141,10 +157,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||
if (**PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
|
||||
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(**PNOGAPSWHENONLY == 2);
|
||||
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.shadow = false;
|
||||
@@ -164,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
auto calcPos = PWINDOW->m_vPosition;
|
||||
auto calcSize = PWINDOW->m_vSize;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top);
|
||||
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn);
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom);
|
||||
|
||||
calcPos = calcPos + OFFSETTOPLEFT;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
@@ -201,9 +217,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||
// if special, we adjust the coords a bit
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
||||
static auto* const PSCALEFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor");
|
||||
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
CBox wb = {calcPos + (calcSize - calcSize * **PSCALEFACTOR) / 2.f, calcSize * **PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
@@ -211,10 +227,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
CBox wb = {calcPos, calcSize};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
}
|
||||
|
||||
if (force) {
|
||||
@@ -238,8 +257,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
static auto* const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
|
||||
static auto* const PDEFAULTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio")->floatValue;
|
||||
static auto* const PUSEACTIVE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits");
|
||||
static auto* const PDEFAULTSPLIT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:default_split_ratio");
|
||||
|
||||
if (direction != DIRECTION_DEFAULT && overrideDirection == DIRECTION_DEFAULT)
|
||||
overrideDirection = direction;
|
||||
@@ -254,26 +273,25 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
|
||||
const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal());
|
||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS);
|
||||
const auto TARGETCOORDS = PMONITOR->ID == MONFROMCURSOR->ID && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR) ? pWindow->middle() : MOUSECOORDS;
|
||||
|
||||
if (PMONITOR->ID == MONFROMCURSOR->ID &&
|
||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
||||
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !**PUSEACTIVE) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS));
|
||||
|
||||
// happens on reserved area
|
||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||
|
||||
} else if (*PUSEACTIVE) {
|
||||
} else if (**PUSEACTIVE) {
|
||||
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
|
||||
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
|
||||
} else {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS));
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS));
|
||||
}
|
||||
|
||||
if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0)
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
if (!OPENINGON && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR))
|
||||
OPENINGON = getClosestNodeOnWorkspace(PNODE->workspaceID, MOUSECOORDS);
|
||||
|
||||
} else
|
||||
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
@@ -325,8 +343,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
(**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
@@ -349,17 +367,17 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
NEWPARENT->isNode = true; // it is a node
|
||||
NEWPARENT->splitRatio = std::clamp(*PDEFAULTSPLIT, 0.1f, 1.9f);
|
||||
NEWPARENT->splitRatio = std::clamp(**PDEFAULTSPLIT, 0.1f, 1.9f);
|
||||
|
||||
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
const auto PWIDTHMULTIPLIER = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
|
||||
|
||||
// if cursor over first child, make it first, etc
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * **PWIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
static auto* const PERMANENTDIRECTIONOVERRIDE = &g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override")->intValue;
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PFORCESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:force_split");
|
||||
static auto* const PERMANENTDIRECTIONOVERRIDE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override");
|
||||
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
|
||||
|
||||
bool horizontalOverride = false;
|
||||
bool verticalOverride = false;
|
||||
@@ -383,37 +401,44 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// whether or not the override persists after opening one window
|
||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
if (**PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
overrideDirection = DIRECTION_DEFAULT;
|
||||
} else if (*PSMARTSPLIT == 1) {
|
||||
const auto tl = NEWPARENT->box.pos();
|
||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
} else if (**PSMARTSPLIT == 1) {
|
||||
const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w;
|
||||
const auto DELTA = MOUSECOORDS - PARENT_CENTER;
|
||||
const auto DELTA_SLOPE = DELTA.y / DELTA.x;
|
||||
|
||||
if (TARGETCOORDS.inTriangle(tl, tr, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
} else if (TARGETCOORDS.inTriangle(tr, cc, br)) {
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else if (TARGETCOORDS.inTriangle(br, bl, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
if (abs(DELTA_SLOPE) < PARENT_PROPORTIONS) {
|
||||
if (DELTA.x > 0) {
|
||||
// right
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
// left
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
}
|
||||
} else {
|
||||
NEWPARENT->splitTop = false;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
if (DELTA.y > 0) {
|
||||
// bottom
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = OPENINGON;
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
// top
|
||||
NEWPARENT->splitTop = true;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
}
|
||||
}
|
||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
} else if (**PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
if ((SIDEBYSIDE &&
|
||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||
(!SIDEBYSIDE &&
|
||||
VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / **PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
||||
// we are hovering over the first node, make PNODE first.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
@@ -423,7 +448,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
NEWPARENT->children[1] = PNODE;
|
||||
}
|
||||
} else {
|
||||
if (*PFORCESPLIT == 1) {
|
||||
if (**PFORCESPLIT == 1) {
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
@@ -442,7 +467,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// Update the children
|
||||
if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
||||
if (!verticalOverride && (NEWPARENT->box.w * **PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
||||
// split left/right -> forced
|
||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
@@ -586,8 +611,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
const auto PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing")->intValue;
|
||||
const auto PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||
const auto PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing");
|
||||
|
||||
// get some data about our window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
@@ -624,11 +649,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
else
|
||||
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
||||
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
|
||||
CBox wbox = PNODE->box;
|
||||
wbox.round();
|
||||
|
||||
PWINDOW->m_vPseudoSize = {std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, wbox.w), std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, wbox.h)};
|
||||
|
||||
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
|
||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PNODE->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -642,7 +669,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||
allowedMovement.y = 0;
|
||||
|
||||
if (*PSMARTRESIZING == 1) {
|
||||
if (**PSMARTRESIZING == 1) {
|
||||
// Identify inner and outer nodes for both directions
|
||||
SDwindleNodeData* PVOUTER = nullptr;
|
||||
SDwindleNodeData* PVINNER = nullptr;
|
||||
@@ -676,14 +703,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
|
||||
if (PHINNER) {
|
||||
const auto ORIGINAL = PHINNER->box.w;
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
if (PHINNER->pParent->children[0] == PHINNER)
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PHINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PHOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
if (PVOUTER) {
|
||||
@@ -691,14 +718,14 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
|
||||
if (PVINNER) {
|
||||
const auto ORIGINAL = PVINNER->box.h;
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
if (PVINNER->pParent->children[0] == PVINNER)
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PVINNER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PVOUTER->pParent->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
} else {
|
||||
// get the correct containers to apply splitratio to
|
||||
@@ -717,11 +744,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -736,11 +763,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
PPARENT->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -755,8 +782,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
SIDECONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
TOPCONTAINER->recalcSizePosRecursive(**PANIMATE == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,10 +803,21 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
return;
|
||||
}
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating && on) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
pWindow->updateWindowDecos();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||
|
||||
@@ -800,14 +838,6 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
}
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
@@ -824,7 +854,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
pWindow->m_vPosition = fakeNode.box.pos();
|
||||
pWindow->m_vSize = fakeNode.box.size();
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
applyNodeDataToWindow(&fakeNode, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,6 +997,8 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
||||
const auto ARGS = CVarList(message, 0, ' ');
|
||||
if (ARGS[0] == "togglesplit") {
|
||||
toggleSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "swapsplit") {
|
||||
swapSplit(header.pWindow);
|
||||
} else if (ARGS[0] == "preselect") {
|
||||
std::string direction = ARGS[1];
|
||||
|
||||
@@ -1020,6 +1052,20 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||
PNODE->pParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::swapSplit(CWindow* pWindow) {
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE || !PNODE->pParent)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
std::swap(PNODE->pParent->children[0], PNODE->pParent->children[1]);
|
||||
|
||||
PNODE->pParent->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||
const auto PNODE = getNodeFromWindow(from);
|
||||
|
||||
|
@@ -79,9 +79,11 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
|
||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&);
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
||||
void toggleSplit(CWindow*);
|
||||
void swapSplit(CWindow*);
|
||||
|
||||
eDirection overrideDirection = DIRECTION_DEFAULT;
|
||||
|
||||
|
@@ -87,7 +87,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
desiredGeometry.y = xy.y;
|
||||
}
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "{:m} has an invalid monitor in onWindowCreatedFloating!!!", pWindow);
|
||||
@@ -151,7 +151,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
||||
if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11)
|
||||
pWindow->m_vRealSize = pWindow->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
|
||||
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
|
||||
@@ -268,15 +268,15 @@ void IHyprLayout::onEndDragWindow() {
|
||||
} else if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS, DRAGGINGWINDOW);
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY, DRAGGINGWINDOW);
|
||||
|
||||
if (pWindow && pWindow->m_bIsFloating) {
|
||||
if (pWindow) {
|
||||
if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW))
|
||||
return;
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
(**USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
@@ -309,13 +309,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||
|
||||
static auto* const PANIMATEMOUSE = &g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging")->intValue;
|
||||
static auto* const PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
static auto* const PANIMATEMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_mouse_windowdragging");
|
||||
static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||
|
||||
if ((abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f) ||
|
||||
(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - TIMER).count() <
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate &&
|
||||
(*PANIMATEMOUSE || *PANIMATE)))
|
||||
1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate))
|
||||
return;
|
||||
|
||||
TIMER = std::chrono::high_resolution_clock::now();
|
||||
@@ -329,7 +328,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATEMOUSE)
|
||||
if (**PANIMATEMOUSE)
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
else
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
@@ -387,7 +386,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
CBox wb = {newPos, newSize};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATE) {
|
||||
if (**PANIMATE) {
|
||||
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
} else {
|
||||
@@ -469,16 +468,18 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
|
||||
CBox wb = {pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
|
||||
wb.round();
|
||||
|
||||
if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) {
|
||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10};
|
||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20};
|
||||
wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}};
|
||||
}
|
||||
|
||||
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f;
|
||||
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
|
||||
pWindow->m_vRealPosition = wb.pos();
|
||||
pWindow->m_vRealSize = wb.size();
|
||||
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = wb.pos();
|
||||
pWindow->m_vPosition = wb.size();
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
|
||||
@@ -529,7 +530,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||
// find whether there is a floating window below this one
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus && w.get() != pWindow) {
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pWindow) {
|
||||
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
|
||||
w->m_vPosition.y + w->m_vSize.y)) {
|
||||
return w.get();
|
||||
@@ -542,13 +543,14 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||
return m_pLastTiledWindow;
|
||||
|
||||
// if we don't, let's try to find any window that is in the middle
|
||||
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->middle()); PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
|
||||
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
|
||||
return PWINDOWCANDIDATE;
|
||||
|
||||
// if not, floating window
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus && w.get() != pWindow)
|
||||
!w->m_sAdditionalConfigData.noFocus && w.get() != pWindow)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -557,7 +559,7 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// if it was a tiled window, we first try to find the window that will replace it.
|
||||
auto pWindowCandidate = g_pCompositor->vectorToWindowIdeal(pWindow->middle());
|
||||
auto pWindowCandidate = g_pCompositor->vectorToWindowUnified(pWindow->middle(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!pWindowCandidate)
|
||||
pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "MasterLayout.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "config/ConfigDataValues.hpp"
|
||||
#include <ranges>
|
||||
|
||||
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) {
|
||||
@@ -39,11 +40,11 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
|
||||
}
|
||||
|
||||
//create on the fly if it doesn't exist yet
|
||||
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
|
||||
PWORKSPACEDATA->workspaceID = ws;
|
||||
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
|
||||
const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts;
|
||||
auto orientationForWs = *orientation;
|
||||
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
|
||||
PWORKSPACEDATA->workspaceID = ws;
|
||||
const auto orientation = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("master:orientation");
|
||||
const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts;
|
||||
std::string orientationForWs = *orientation;
|
||||
|
||||
if (layoutoptsForWs.contains("orientation"))
|
||||
orientationForWs = layoutoptsForWs.at("orientation");
|
||||
@@ -80,20 +81,20 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
if (pWindow->m_bIsFloating)
|
||||
return;
|
||||
|
||||
static auto* const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
|
||||
static auto* const PNEWTOP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_on_top");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
||||
const auto PNODE = **PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
||||
|
||||
PNODE->workspaceID = pWindow->m_iWorkspaceID;
|
||||
PNODE->pWindow = pWindow;
|
||||
|
||||
static auto* const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
|
||||
static auto* const PNEWISMASTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_is_master");
|
||||
|
||||
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
||||
static auto* const PMFACT = &g_pConfigManager->getConfigValuePtr("master:mfact")->floatValue;
|
||||
float lastSplitPercent = *PMFACT;
|
||||
static auto* const PMFACT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("master:mfact");
|
||||
float lastSplitPercent = **PMFACT;
|
||||
|
||||
auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID ?
|
||||
getNodeFromWindow(g_pCompositor->m_pLastWindow) :
|
||||
@@ -112,8 +113,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
(**USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
@@ -128,14 +129,14 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
|
||||
pWindow->applyGroupRules();
|
||||
|
||||
static auto* const PDROPATCURSOR = &g_pConfigManager->getConfigValuePtr("master:drop_at_cursor")->intValue;
|
||||
static auto* const PDROPATCURSOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:drop_at_cursor");
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID);
|
||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
||||
|
||||
bool forceDropAsMaster = false;
|
||||
// if dragging window to move, drop it at the cursor position instead of bottom/top of stack
|
||||
if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
if (**PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
if (WINDOWSONWORKSPACE > 2) {
|
||||
for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) {
|
||||
if (it->workspaceID != pWindow->m_iWorkspaceID)
|
||||
@@ -191,7 +192,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
}
|
||||
}
|
||||
|
||||
if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
||||
if ((**PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
||||
forceDropAsMaster) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
@@ -239,14 +240,14 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto WORKSPACEID = PNODE->workspaceID;
|
||||
const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID);
|
||||
static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue;
|
||||
static const auto* SMALLSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:allow_small_split");
|
||||
|
||||
pWindow->updateSpecialRenderData();
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) {
|
||||
if (PNODE->isMaster && (MASTERSLEFT <= 1 || **SMALLSPLIT == 1)) {
|
||||
// find a new master from top of the list
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (!nd.isMaster && nd.workspaceID == WORKSPACEID) {
|
||||
@@ -338,8 +339,8 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
|
||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||
bool centerMasterWindow = false;
|
||||
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue;
|
||||
static auto* const PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("master:smart_resizing")->intValue;
|
||||
static auto* const ALWAYSCENTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:always_center_master");
|
||||
static auto* const PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:smart_resizing");
|
||||
|
||||
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
|
||||
const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID);
|
||||
@@ -348,7 +349,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
|
||||
if (orientation == ORIENTATION_CENTER) {
|
||||
if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) {
|
||||
if (STACKWINDOWS >= 2 || (**ALWAYSCENTER == 1)) {
|
||||
centerMasterWindow = true;
|
||||
} else {
|
||||
orientation = ORIENTATION_LEFT;
|
||||
@@ -361,7 +362,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
float masterAccumulatedSize = 0;
|
||||
float slaveAccumulatedSize = 0;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
// check the total width and height so that later
|
||||
// if larger/smaller than screen size them down/up
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
@@ -399,7 +400,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (WIDTH > widthLeft * 0.9f && mastersLeft > 1)
|
||||
WIDTH = widthLeft * 0.9f;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
nd.percSize *= WSSIZE.x / masterAccumulatedSize;
|
||||
WIDTH = masterAverageSize * nd.percSize;
|
||||
}
|
||||
@@ -436,7 +437,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
nd.percSize *= WSSIZE.y / masterAccumulatedSize;
|
||||
HEIGHT = masterAverageSize * nd.percSize;
|
||||
}
|
||||
@@ -473,7 +474,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
|
||||
WIDTH = widthLeft * 0.9f;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
nd.percSize *= WSSIZE.x / slaveAccumulatedSize;
|
||||
WIDTH = slaveAverageSize * nd.percSize;
|
||||
}
|
||||
@@ -503,7 +504,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
nd.percSize *= WSSIZE.y / slaveAccumulatedSize;
|
||||
HEIGHT = slaveAverageSize * nd.percSize;
|
||||
}
|
||||
@@ -534,7 +535,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
const float slaveAverageHeightR = WSSIZE.y / slavesLeftR;
|
||||
float slaveAccumulatedHeightL = 0;
|
||||
float slaveAccumulatedHeightR = 0;
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
||||
continue;
|
||||
@@ -569,7 +570,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
|
||||
if (*PSMARTRESIZING) {
|
||||
if (**PSMARTRESIZING) {
|
||||
if (onRight) {
|
||||
nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR;
|
||||
HEIGHT = slaveAverageHeightR * nd.percSize;
|
||||
@@ -633,10 +634,12 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
static auto* const PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
|
||||
static auto* const PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
|
||||
static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only");
|
||||
static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes");
|
||||
static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in");
|
||||
static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out");
|
||||
auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData();
|
||||
auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData();
|
||||
|
||||
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
||||
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
||||
@@ -649,11 +652,11 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
|
||||
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||
if (**PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||
(getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 ||
|
||||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||
|
||||
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
|
||||
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(**PNOGAPSWHENONLY == 2);
|
||||
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
|
||||
PWINDOW->m_sSpecialRenderData.rounding = false;
|
||||
PWINDOW->m_sSpecialRenderData.shadow = false;
|
||||
@@ -673,9 +676,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
auto calcPos = PWINDOW->m_vPosition;
|
||||
auto calcSize = PWINDOW->m_vSize;
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top);
|
||||
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn);
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom);
|
||||
|
||||
calcPos = calcPos + OFFSETTOPLEFT;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
@@ -685,9 +688,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
|
||||
static auto* const PSCALEFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("master:special_scale_factor");
|
||||
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
CBox wb = {calcPos + (calcSize - calcSize * **PSCALEFACTOR) / 2.f, calcSize * **PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
@@ -736,11 +739,11 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace);
|
||||
static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue;
|
||||
static auto* const PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("master:smart_resizing")->intValue;
|
||||
static auto* const ALWAYSCENTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:always_center_master");
|
||||
static auto* const PSMARTRESIZING = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:smart_resizing");
|
||||
|
||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||
bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1);
|
||||
bool centered = orientation == ORIENTATION_CENTER && (**ALWAYSCENTER == 1);
|
||||
double delta = 0;
|
||||
|
||||
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
@@ -797,7 +800,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||
const auto SIZE = isStackVertical ? WSSIZE.y / nodesInSameColumn : WSSIZE.x / nodesInSameColumn;
|
||||
|
||||
if (RESIZEDELTA != 0 && nodesInSameColumn > 1) {
|
||||
if (!*PSMARTRESIZING) {
|
||||
if (!**PSMARTRESIZING) {
|
||||
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
|
||||
} else {
|
||||
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
||||
@@ -879,10 +882,21 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
return;
|
||||
}
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating && on) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
pWindow->updateWindowDecos();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
||||
|
||||
@@ -903,14 +917,6 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating) {
|
||||
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
|
||||
}
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
@@ -1052,8 +1058,8 @@ bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
|
||||
//if the current window is fullscreen, make it normal again if we are about to lose focus
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
static auto* const INHERIT = &g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen")->intValue;
|
||||
return *INHERIT == 1;
|
||||
static auto* const INHERIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen");
|
||||
return **INHERIT == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1230,9 +1236,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
|
||||
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID);
|
||||
const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID);
|
||||
static const auto* SMALLSPLIT = &g_pConfigManager->getConfigValuePtr("master:allow_small_split")->intValue;
|
||||
static const auto* SMALLSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:allow_small_split");
|
||||
|
||||
if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0)
|
||||
if (MASTERS + 2 > WINDOWS && **SMALLSPLIT == 0)
|
||||
return 0;
|
||||
prepareLoseFocus(header.pWindow);
|
||||
|
||||
@@ -1328,7 +1334,13 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
const auto PWINDOW = header.pWindow;
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
||||
if (!PNODE)
|
||||
return 0;
|
||||
|
||||
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
||||
if (!OLDMASTER)
|
||||
return 0;
|
||||
|
||||
const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER);
|
||||
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
@@ -1350,7 +1362,13 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
const auto PWINDOW = header.pWindow;
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
||||
if (!PNODE)
|
||||
return 0;
|
||||
|
||||
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
||||
if (!OLDMASTER)
|
||||
return 0;
|
||||
|
||||
const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER);
|
||||
|
||||
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
|
||||
|
@@ -85,7 +85,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (!ignoreSudo && Init::isSudo()) {
|
||||
std::cerr << "[ ERROR ] Hyprland was launched with superuser priveleges, but the privileges check is not omitted.\n";
|
||||
std::cerr << "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n";
|
||||
std::cerr << " Hint: Use the --i-am-really-stupid flag to omit that check.\n";
|
||||
|
||||
return 1;
|
||||
|
@@ -53,12 +53,12 @@ void CAnimationManager::tick() {
|
||||
|
||||
bool animGlobalDisabled = false;
|
||||
|
||||
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
|
||||
static auto* const PANIMENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("animations:enabled");
|
||||
|
||||
if (!*PANIMENABLED)
|
||||
if (!**PANIMENABLED)
|
||||
animGlobalDisabled = true;
|
||||
|
||||
static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:drop_shadow");
|
||||
|
||||
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
|
||||
|
||||
@@ -66,7 +66,7 @@ void CAnimationManager::tick() {
|
||||
|
||||
for (auto& av : m_vActiveAnimatedVariables) {
|
||||
|
||||
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
|
||||
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !**PSHADOWSENABLED) {
|
||||
av->warp(false);
|
||||
animationEndedVars.push_back(av);
|
||||
continue;
|
||||
@@ -223,6 +223,11 @@ void CAnimationManager::tick() {
|
||||
} else if (PLAYER) {
|
||||
if (PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
|
||||
|
||||
// some fucking layers miss 1 pixel???
|
||||
CBox expandBox = WLRBOXPREV;
|
||||
expandBox.expand(5);
|
||||
g_pHyprRenderer->damageBox(&expandBox);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -232,9 +237,9 @@ void CAnimationManager::tick() {
|
||||
// TODO: move this to the border class
|
||||
|
||||
// damage only the border.
|
||||
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
const auto ROUNDINGSIZE = *PROUNDING + 1;
|
||||
const auto BORDERSIZE = PWINDOW->getRealBorderSize();
|
||||
const auto ROUNDING = PWINDOW->rounding();
|
||||
const auto ROUNDINGSIZE = ROUNDING + 1;
|
||||
const auto BORDERSIZE = PWINDOW->getRealBorderSize();
|
||||
|
||||
// damage for old box
|
||||
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
|
||||
|
@@ -19,13 +19,69 @@
|
||||
CEventManager::CEventManager() {}
|
||||
|
||||
int fdHandleWrite(int fd, uint32_t mask, void* data) {
|
||||
const auto PEVMGR = (CEventManager*)data;
|
||||
return PEVMGR->onFDWrite(fd, mask);
|
||||
}
|
||||
|
||||
auto removeFD = [&](int fd) -> void {
|
||||
const auto ACCEPTEDFDS = (std::deque<std::pair<int, wl_event_source*>>*)data;
|
||||
for (auto it = ACCEPTEDFDS->begin(); it != ACCEPTEDFDS->end();) {
|
||||
int socket2HandleWrite(int fd, uint32_t mask, void* data) {
|
||||
const auto PEVMGR = (CEventManager*)data;
|
||||
return PEVMGR->onSocket2Write(fd, mask);
|
||||
}
|
||||
|
||||
void CEventManager::startThread() {
|
||||
|
||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (m_iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
|
||||
strncpy(SERVERADDRESS.sun_path, socketPath.c_str(), sizeof(SERVERADDRESS.sun_path) - 1);
|
||||
|
||||
bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
// 10 max queued.
|
||||
listen(m_iSocketFD, 10);
|
||||
|
||||
m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, socket2HandleWrite, this);
|
||||
}
|
||||
|
||||
int CEventManager::onSocket2Write(int fd, uint32_t mask) {
|
||||
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) {
|
||||
Debug::log(ERR, "Socket2 hangup?? IPC broke");
|
||||
wl_event_source_remove(m_pEventSource);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
const auto ACCEPTEDCONNECTION = accept4(m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK);
|
||||
|
||||
if (ACCEPTEDCONNECTION > 0) {
|
||||
Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION);
|
||||
|
||||
// add to event loop so we can close it when we need to
|
||||
m_dAcceptedSocketFDs.push_back(
|
||||
std::make_pair<>(ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, this)));
|
||||
} else {
|
||||
Debug::log(ERR, "Socket2 failed receiving connection, errno: {}", errno);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CEventManager::onFDWrite(int fd, uint32_t mask) {
|
||||
auto removeFD = [this](int fd) -> void {
|
||||
for (auto it = m_dAcceptedSocketFDs.begin(); it != m_dAcceptedSocketFDs.end();) {
|
||||
if (it->first == fd) {
|
||||
wl_event_source_remove(it->second); // remove this fd listener
|
||||
it = ACCEPTEDFDS->erase(it);
|
||||
it = m_dAcceptedSocketFDs.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
@@ -58,52 +114,6 @@ int fdHandleWrite(int fd, uint32_t mask, void* data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CEventManager::startThread() {
|
||||
m_tThread = std::thread([&]() {
|
||||
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (SOCKET < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
|
||||
strncpy(SERVERADDRESS.sun_path, socketPath.c_str(), sizeof(SERVERADDRESS.sun_path) - 1);
|
||||
|
||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
// 10 max queued.
|
||||
listen(SOCKET, 10);
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
Debug::log(LOG, "Hypr socket 2 started at {}", socketPath);
|
||||
|
||||
while (1) {
|
||||
const auto ACCEPTEDCONNECTION = accept4(SOCKET, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
if (ACCEPTEDCONNECTION > 0) {
|
||||
// new connection!
|
||||
|
||||
int flagsNew = fcntl(ACCEPTEDCONNECTION, F_GETFL, 0);
|
||||
fcntl(ACCEPTEDCONNECTION, F_SETFL, flagsNew | O_NONBLOCK);
|
||||
|
||||
Debug::log(LOG, "Socket 2 accepted a new client at FD {}", ACCEPTEDCONNECTION);
|
||||
|
||||
// add to event loop so we can close it when we need to
|
||||
m_dAcceptedSocketFDs.push_back(
|
||||
{ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, &m_dAcceptedSocketFDs)});
|
||||
}
|
||||
}
|
||||
|
||||
close(SOCKET);
|
||||
});
|
||||
|
||||
m_tThread.detach();
|
||||
}
|
||||
|
||||
void CEventManager::flushEvents() {
|
||||
eventQueueMutex.lock();
|
||||
|
||||
|
@@ -21,6 +21,11 @@ class CEventManager {
|
||||
|
||||
std::thread m_tThread;
|
||||
|
||||
int m_iSocketFD = -1;
|
||||
|
||||
int onSocket2Write(int fd, uint32_t mask);
|
||||
int onFDWrite(int fd, uint32_t mask);
|
||||
|
||||
private:
|
||||
void flushEvents();
|
||||
|
||||
@@ -28,6 +33,8 @@ class CEventManager {
|
||||
std::deque<SHyprIPCEvent> m_dQueuedEvents;
|
||||
|
||||
std::deque<std::pair<int, wl_event_source*>> m_dAcceptedSocketFDs;
|
||||
|
||||
wl_event_source* m_pEventSource = nullptr;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CEventManager> g_pEventManager;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <vector>
|
||||
#if defined(__linux__)
|
||||
#include <linux/vt.h>
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
@@ -18,64 +19,66 @@
|
||||
CKeybindManager::CKeybindManager() {
|
||||
// initialize all dispatchers
|
||||
|
||||
m_mDispatchers["exec"] = spawn;
|
||||
m_mDispatchers["execr"] = spawnRaw;
|
||||
m_mDispatchers["killactive"] = killActive;
|
||||
m_mDispatchers["closewindow"] = kill;
|
||||
m_mDispatchers["togglefloating"] = toggleActiveFloating;
|
||||
m_mDispatchers["workspace"] = changeworkspace;
|
||||
m_mDispatchers["renameworkspace"] = renameWorkspace;
|
||||
m_mDispatchers["fullscreen"] = fullscreenActive;
|
||||
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
|
||||
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
|
||||
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
|
||||
m_mDispatchers["pseudo"] = toggleActivePseudo;
|
||||
m_mDispatchers["movefocus"] = moveFocusTo;
|
||||
m_mDispatchers["movewindow"] = moveActiveTo;
|
||||
m_mDispatchers["swapwindow"] = swapActive;
|
||||
m_mDispatchers["centerwindow"] = centerWindow;
|
||||
m_mDispatchers["togglegroup"] = toggleGroup;
|
||||
m_mDispatchers["changegroupactive"] = changeGroupActive;
|
||||
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
|
||||
m_mDispatchers["togglesplit"] = toggleSplit;
|
||||
m_mDispatchers["splitratio"] = alterSplitRatio;
|
||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
||||
m_mDispatchers["movecursor"] = moveCursor;
|
||||
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
||||
m_mDispatchers["exit"] = exitHyprland;
|
||||
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
||||
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||
m_mDispatchers["resizeactive"] = resizeActive;
|
||||
m_mDispatchers["moveactive"] = moveActive;
|
||||
m_mDispatchers["cyclenext"] = circleNext;
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
||||
m_mDispatchers["focuswindow"] = focusWindow;
|
||||
m_mDispatchers["submap"] = setSubmap;
|
||||
m_mDispatchers["pass"] = pass;
|
||||
m_mDispatchers["layoutmsg"] = layoutmsg;
|
||||
m_mDispatchers["toggleopaque"] = toggleOpaque;
|
||||
m_mDispatchers["dpms"] = dpms;
|
||||
m_mDispatchers["movewindowpixel"] = moveWindow;
|
||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||
m_mDispatchers["swapnext"] = swapnext;
|
||||
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
||||
m_mDispatchers["pin"] = pinActive;
|
||||
m_mDispatchers["mouse"] = mouse;
|
||||
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
|
||||
m_mDispatchers["alterzorder"] = alterZOrder;
|
||||
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
|
||||
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
|
||||
m_mDispatchers["lockgroups"] = lockGroups;
|
||||
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
|
||||
m_mDispatchers["moveintogroup"] = moveIntoGroup;
|
||||
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
|
||||
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
||||
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
||||
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
||||
m_mDispatchers["global"] = global;
|
||||
m_mDispatchers["exec"] = spawn;
|
||||
m_mDispatchers["execr"] = spawnRaw;
|
||||
m_mDispatchers["killactive"] = killActive;
|
||||
m_mDispatchers["closewindow"] = kill;
|
||||
m_mDispatchers["togglefloating"] = toggleActiveFloating;
|
||||
m_mDispatchers["workspace"] = changeworkspace;
|
||||
m_mDispatchers["renameworkspace"] = renameWorkspace;
|
||||
m_mDispatchers["fullscreen"] = fullscreenActive;
|
||||
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
|
||||
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
|
||||
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
|
||||
m_mDispatchers["pseudo"] = toggleActivePseudo;
|
||||
m_mDispatchers["movefocus"] = moveFocusTo;
|
||||
m_mDispatchers["movewindow"] = moveActiveTo;
|
||||
m_mDispatchers["swapwindow"] = swapActive;
|
||||
m_mDispatchers["centerwindow"] = centerWindow;
|
||||
m_mDispatchers["togglegroup"] = toggleGroup;
|
||||
m_mDispatchers["changegroupactive"] = changeGroupActive;
|
||||
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
|
||||
m_mDispatchers["togglesplit"] = toggleSplit;
|
||||
m_mDispatchers["swapsplit"] = swapSplit;
|
||||
m_mDispatchers["splitratio"] = alterSplitRatio;
|
||||
m_mDispatchers["focusmonitor"] = focusMonitor;
|
||||
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
|
||||
m_mDispatchers["movecursor"] = moveCursor;
|
||||
m_mDispatchers["workspaceopt"] = workspaceOpt;
|
||||
m_mDispatchers["exit"] = exitHyprland;
|
||||
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
||||
m_mDispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor;
|
||||
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||
m_mDispatchers["forcerendererreload"] = forceRendererReload;
|
||||
m_mDispatchers["resizeactive"] = resizeActive;
|
||||
m_mDispatchers["moveactive"] = moveActive;
|
||||
m_mDispatchers["cyclenext"] = circleNext;
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
||||
m_mDispatchers["focuswindow"] = focusWindow;
|
||||
m_mDispatchers["submap"] = setSubmap;
|
||||
m_mDispatchers["pass"] = pass;
|
||||
m_mDispatchers["layoutmsg"] = layoutmsg;
|
||||
m_mDispatchers["toggleopaque"] = toggleOpaque;
|
||||
m_mDispatchers["dpms"] = dpms;
|
||||
m_mDispatchers["movewindowpixel"] = moveWindow;
|
||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||
m_mDispatchers["swapnext"] = swapnext;
|
||||
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
||||
m_mDispatchers["pin"] = pinActive;
|
||||
m_mDispatchers["mouse"] = mouse;
|
||||
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
|
||||
m_mDispatchers["alterzorder"] = alterZOrder;
|
||||
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
|
||||
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
|
||||
m_mDispatchers["lockgroups"] = lockGroups;
|
||||
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
|
||||
m_mDispatchers["moveintogroup"] = moveIntoGroup;
|
||||
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
|
||||
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
|
||||
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
|
||||
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
|
||||
m_mDispatchers["global"] = global;
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
|
||||
@@ -95,7 +98,7 @@ void CKeybindManager::addKeybind(SKeybind kb) {
|
||||
void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
|
||||
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) {
|
||||
if (isNumber(key) && std::stoi(key) > 9) {
|
||||
const auto KEYNUM = std::stoi(key);
|
||||
const uint32_t KEYNUM = std::stoi(key);
|
||||
|
||||
if (it->modmask == mod && it->keycode == KEYNUM) {
|
||||
it = m_lKeybinds.erase(it);
|
||||
@@ -137,6 +140,22 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||
return modMask;
|
||||
}
|
||||
|
||||
uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) {
|
||||
switch (keycode - 8) {
|
||||
case KEY_LEFTMETA: return WLR_MODIFIER_LOGO;
|
||||
case KEY_RIGHTMETA: return WLR_MODIFIER_LOGO;
|
||||
case KEY_LEFTSHIFT: return WLR_MODIFIER_SHIFT;
|
||||
case KEY_RIGHTSHIFT: return WLR_MODIFIER_SHIFT;
|
||||
case KEY_LEFTCTRL: return WLR_MODIFIER_CTRL;
|
||||
case KEY_RIGHTCTRL: return WLR_MODIFIER_CTRL;
|
||||
case KEY_LEFTALT: return WLR_MODIFIER_ALT;
|
||||
case KEY_RIGHTALT: return WLR_MODIFIER_ALT;
|
||||
case KEY_CAPSLOCK: return WLR_MODIFIER_CAPS;
|
||||
case KEY_NUMLOCK: return WLR_MODIFIER_MOD2;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::updateXKBTranslationState() {
|
||||
if (m_pXKBTranslationState) {
|
||||
xkb_keymap_unref(xkb_state_get_keymap(m_pXKBTranslationState));
|
||||
@@ -145,19 +164,26 @@ void CKeybindManager::updateXKBTranslationState() {
|
||||
m_pXKBTranslationState = nullptr;
|
||||
}
|
||||
|
||||
const auto FILEPATH = g_pConfigManager->getString("input:kb_file");
|
||||
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
|
||||
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
||||
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
|
||||
static auto* const PFILEPATH = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_file");
|
||||
static auto* const PRULES = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_rules");
|
||||
static auto* const PMODEL = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_model");
|
||||
static auto* const PLAYOUT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_layout");
|
||||
static auto* const PVARIANT = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_variant");
|
||||
static auto* const POPTIONS = (Hyprlang::STRING const*)g_pConfigManager->getConfigValuePtr("input:kb_options");
|
||||
|
||||
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
FILE* const KEYMAPFILE = FILEPATH == "" ? NULL : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r");
|
||||
const std::string FILEPATH = std::string{*PFILEPATH} == STRVAL_EMPTY ? "" : *PFILEPATH;
|
||||
const std::string RULES = std::string{*PRULES} == STRVAL_EMPTY ? "" : *PRULES;
|
||||
const std::string MODEL = std::string{*PMODEL} == STRVAL_EMPTY ? "" : *PMODEL;
|
||||
const std::string LAYOUT = std::string{*PLAYOUT} == STRVAL_EMPTY ? "" : *PLAYOUT;
|
||||
const std::string VARIANT = std::string{*PVARIANT} == STRVAL_EMPTY ? "" : *PVARIANT;
|
||||
const std::string OPTIONS = std::string{*POPTIONS} == STRVAL_EMPTY ? "" : *POPTIONS;
|
||||
|
||||
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) :
|
||||
xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
FILE* const KEYMAPFILE = FILEPATH == "" ? NULL : fopen(absolutePath(FILEPATH, g_pConfigManager->configCurrentPath).c_str(), "r");
|
||||
|
||||
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) :
|
||||
xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
if (KEYMAPFILE)
|
||||
fclose(KEYMAPFILE);
|
||||
|
||||
@@ -261,8 +287,7 @@ void CKeybindManager::switchToWindow(CWindow* PWINDOWTOCHANGETO) {
|
||||
|
||||
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
if (!g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||
m_dPressedKeycodes.clear();
|
||||
m_dPressedKeysyms.clear();
|
||||
m_dPressedKeys.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -279,7 +304,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* 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(m_pXKBTranslationState, KEYCODE);
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE);
|
||||
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
|
||||
|
||||
if (handleInternalKeybinds(internalKeysym))
|
||||
@@ -291,9 +316,16 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_uLastCode = KEYCODE;
|
||||
m_uLastMouseCode = 0;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
bool found = false;
|
||||
const auto KEY = SPressedKeyWithMods{
|
||||
.keysym = keysym,
|
||||
.keycode = KEYCODE,
|
||||
.modmaskAtPressTime = MODS,
|
||||
.sent = true,
|
||||
};
|
||||
|
||||
bool suppressEvent = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
// clean repeat
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
@@ -302,16 +334,15 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.push_back(KEYCODE);
|
||||
m_dPressedKeysyms.push_back(keysym);
|
||||
m_dPressedKeys.push_back(KEY);
|
||||
|
||||
found = handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found;
|
||||
suppressEvent = handleKeybinds(MODS, KEY, true);
|
||||
|
||||
found = handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found;
|
||||
|
||||
if (found)
|
||||
if (suppressEvent)
|
||||
shadowKeybinds(keysym, KEYCODE);
|
||||
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
|
||||
m_dPressedKeys.back().sent = !suppressEvent;
|
||||
} else { // key release
|
||||
// clean repeat
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
@@ -319,25 +350,35 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end());
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym), m_dPressedKeysyms.end());
|
||||
|
||||
found = handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
|
||||
|
||||
found = handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found;
|
||||
bool foundInPressedKeys = false;
|
||||
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
||||
if (it->keycode == KEYCODE) {
|
||||
suppressEvent = handleKeybinds(MODS, *it, false);
|
||||
foundInPressedKeys = true;
|
||||
suppressEvent = !it->sent;
|
||||
it = m_dPressedKeys.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!foundInPressedKeys) {
|
||||
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys");
|
||||
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
||||
suppressEvent = handleKeybinds(MODS, KEY, false);
|
||||
}
|
||||
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found && !mouseBindWasActive;
|
||||
return !suppressEvent && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
static auto* const PDELAY = &g_pConfigManager->getConfigValuePtr("binds:scroll_event_delay")->intValue;
|
||||
static auto* const PDELAY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:scroll_event_delay");
|
||||
|
||||
if (m_tScrollTimer.getMillis() < *PDELAY) {
|
||||
if (m_tScrollTimer.getMillis() < **PDELAY) {
|
||||
m_tScrollTimer.reset();
|
||||
return true; // timer hasn't passed yet!
|
||||
}
|
||||
@@ -347,14 +388,14 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
bool found = false;
|
||||
if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
|
||||
if (e->delta < 0)
|
||||
found = handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true);
|
||||
else
|
||||
found = handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true);
|
||||
} else if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_HORIZONTAL) {
|
||||
if (e->delta < 0)
|
||||
found = handleKeybinds(MODS, "mouse_left", 0, 0, true, 0);
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true);
|
||||
else
|
||||
found = handleKeybinds(MODS, "mouse_right", 0, 0, true, 0);
|
||||
found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true);
|
||||
}
|
||||
|
||||
if (found)
|
||||
@@ -366,26 +407,52 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
bool found = false;
|
||||
bool suppressEvent = false;
|
||||
|
||||
m_uLastMouseCode = e->button;
|
||||
m_uLastCode = 0;
|
||||
m_uTimeLastMs = e->time_msec;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
const auto KEY_NAME = "mouse:" + std::to_string(e->button);
|
||||
|
||||
const auto KEY = SPressedKeyWithMods{
|
||||
.keyName = KEY_NAME,
|
||||
.modmaskAtPressTime = MODS,
|
||||
};
|
||||
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
|
||||
m_dPressedKeys.push_back(KEY);
|
||||
|
||||
if (found)
|
||||
suppressEvent = handleKeybinds(MODS, KEY, true);
|
||||
|
||||
if (suppressEvent)
|
||||
shadowKeybinds();
|
||||
|
||||
m_dPressedKeys.back().sent = !suppressEvent;
|
||||
} else {
|
||||
found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0);
|
||||
bool foundInPressedKeys = false;
|
||||
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
|
||||
if (it->keyName == KEY_NAME) {
|
||||
suppressEvent = handleKeybinds(MODS, *it, false);
|
||||
foundInPressedKeys = true;
|
||||
suppressEvent = !it->sent;
|
||||
it = m_dPressedKeys.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!foundInPressedKeys) {
|
||||
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)");
|
||||
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
|
||||
suppressEvent = handleKeybinds(MODS, KEY, false);
|
||||
}
|
||||
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found && !mouseBindWasActive;
|
||||
return !suppressEvent && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) {
|
||||
@@ -397,15 +464,15 @@ void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) {
|
||||
}
|
||||
|
||||
void CKeybindManager::onSwitchEvent(const std::string& switchName) {
|
||||
handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0);
|
||||
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:" + switchName}, true);
|
||||
}
|
||||
|
||||
void CKeybindManager::onSwitchOnEvent(const std::string& switchName) {
|
||||
handleKeybinds(0, "switch:on:" + switchName, 0, 0, true, 0);
|
||||
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:on:" + switchName}, true);
|
||||
}
|
||||
|
||||
void CKeybindManager::onSwitchOffEvent(const std::string& switchName) {
|
||||
handleKeybinds(0, "switch:off:" + switchName, 0, 0, true, 0);
|
||||
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true);
|
||||
}
|
||||
|
||||
int repeatKeyHandler(void* data) {
|
||||
@@ -424,12 +491,21 @@ int repeatKeyHandler(void* data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode, bool pressed, uint32_t time) {
|
||||
bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) {
|
||||
bool found = false;
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient)
|
||||
Debug::log(LOG, "Keybind handling only locked (inhibitor)");
|
||||
|
||||
if (!m_lShortcutInhibitors.empty()) {
|
||||
for (auto& i : m_lShortcutInhibitors) {
|
||||
if (i.pWlrInhibitor->surface == g_pCompositor->m_pLastFocus) {
|
||||
Debug::log(LOG, "Keybind handling is disabled due to an inhibitor for surface {:x}", (uintptr_t)i.pWlrInhibitor->surface);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
const bool SPECIALDISPATCHER = k.handler == "global" || k.handler == "pass" || k.handler == "mouse";
|
||||
const bool SPECIALTRIGGERED =
|
||||
@@ -441,22 +517,31 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
continue;
|
||||
|
||||
if (!key.empty()) {
|
||||
if (key != k.key)
|
||||
if (!key.keyName.empty()) {
|
||||
if (key.keyName != k.key)
|
||||
continue;
|
||||
} else if (k.keycode != -1) {
|
||||
if (keycode != k.keycode)
|
||||
} else if (k.keycode != 0) {
|
||||
if (key.keycode != k.keycode)
|
||||
continue;
|
||||
} else {
|
||||
if (keysym == 0)
|
||||
continue; // this is a keycode check run
|
||||
|
||||
// oMg such performance hit!!11!
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
|
||||
if (KBKEY == 0) {
|
||||
// Keysym failed to resolve from the key name of the the currently iterated bind.
|
||||
// This happens for names such as `switch:off:Lid Switch` as well as some keys
|
||||
// (such as yen and ro).
|
||||
//
|
||||
// We can't let compare a 0-value with currently pressed key below,
|
||||
// because if this key also have no keysym (i.e. key.keysym == 0) it will incorrectly trigger the
|
||||
// currently iterated bind. That's confirmed to be happening with yen and ro keys.
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
|
||||
if (keysym != KBKEY && keysym != KBKEYUPPER)
|
||||
if (key.keysym != KBKEY && key.keysym != KBKEYUPPER)
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -468,12 +553,24 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pressed && !k.release && !SPECIALDISPATCHER) {
|
||||
if (k.nonConsuming)
|
||||
continue;
|
||||
if (!pressed) {
|
||||
// Require mods to be matching when the key was first pressed.
|
||||
if (key.modmaskAtPressTime != modmask && !k.ignoreMods) {
|
||||
// Handle properly `bindr` where a key is itself a bind mod for example:
|
||||
// "bindr = SUPER, SUPER_L, exec, $launcher".
|
||||
// This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
|
||||
// from currently pressed keys as programs see them, but it doesn't yet include the currently
|
||||
// pressed mod key, which is still being handled internally.
|
||||
if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime)
|
||||
continue;
|
||||
|
||||
found = true; // suppress the event
|
||||
continue;
|
||||
} else if (!k.release && !SPECIALDISPATCHER) {
|
||||
if (k.nonConsuming)
|
||||
continue;
|
||||
|
||||
found = true; // suppress the event
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
||||
@@ -488,7 +585,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler);
|
||||
} else {
|
||||
// call the dispatcher
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key, keysym);
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym);
|
||||
|
||||
m_iPassPressed = (int)pressed;
|
||||
|
||||
@@ -521,7 +618,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
return found;
|
||||
}
|
||||
|
||||
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int& doesntHaveCode) {
|
||||
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) {
|
||||
// shadow disables keybinds after one has been triggered
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
@@ -534,22 +631,20 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int&
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
|
||||
for (auto& pk : m_dPressedKeysyms) {
|
||||
if ((pk == KBKEY || pk == KBKEYUPPER)) {
|
||||
for (auto& pk : m_dPressedKeys) {
|
||||
if ((pk.keysym != 0 && (pk.keysym == KBKEY || pk.keysym == KBKEYUPPER))) {
|
||||
shadow = true;
|
||||
|
||||
if (pk == doesntHave && doesntHave != 0) {
|
||||
if (pk.keysym == doesntHave && doesntHave != 0) {
|
||||
shadow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pk : m_dPressedKeycodes) {
|
||||
if (pk == k.keycode) {
|
||||
if (pk.keycode != 0 && pk.keycode == k.keycode) {
|
||||
shadow = true;
|
||||
|
||||
if (pk == doesntHaveCode && doesntHaveCode != 0 && doesntHaveCode != -1) {
|
||||
if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) {
|
||||
shadow = false;
|
||||
break;
|
||||
}
|
||||
@@ -730,7 +825,7 @@ void CKeybindManager::clearKeybinds() {
|
||||
void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args != "" && args != "active" && args.length() > 1)
|
||||
if (args != "active" && args.length() > 1)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
@@ -797,9 +892,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
// Workspace_back_and_forth being enabled means that an attempt to switch to
|
||||
// the current workspace will instead switch to the previous.
|
||||
static auto* const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
|
||||
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
static auto* const PWORKSPACECENTERON = &g_pConfigManager->getConfigValuePtr("binds:workspace_center_on")->intValue;
|
||||
static auto* const PBACKANDFORTH = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth");
|
||||
static auto* const PALLOWWORKSPACECYCLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles");
|
||||
static auto* const PWORKSPACECENTERON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:workspace_center_on");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
@@ -834,7 +929,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID;
|
||||
|
||||
if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1))
|
||||
if (BISWORKSPACECURRENT && (!(**PBACKANDFORTH || EXPLICITPREVIOUS) || PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1))
|
||||
return;
|
||||
|
||||
g_pInputManager->unconstrainMouse();
|
||||
@@ -866,14 +961,14 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
Vector2D middle = PMONITORWORKSPACEOWNER->middle();
|
||||
if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) {
|
||||
g_pCompositor->focusWindow(PLAST);
|
||||
if (*PWORKSPACECENTERON == 1)
|
||||
if (**PWORKSPACECENTERON == 1)
|
||||
middle = PLAST->middle();
|
||||
}
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
}
|
||||
|
||||
if (BISWORKSPACECURRENT) {
|
||||
if (*PALLOWWORKSPACECYCLES)
|
||||
if (**PALLOWWORKSPACECYCLES)
|
||||
pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE);
|
||||
else if (!EXPLICITPREVIOUS)
|
||||
pWorkspaceToChangeTo->rememberPrevWorkspace(nullptr);
|
||||
@@ -897,6 +992,9 @@ void CKeybindManager::fullscreenActive(std::string args) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
PWINDOW->m_bDontSendFullscreen = false;
|
||||
if (args == "2")
|
||||
PWINDOW->m_bDontSendFullscreen = true;
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
@@ -931,7 +1029,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
CMonitor* pMonitor = nullptr;
|
||||
const auto POLDWS = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
static auto* const PALLOWWORKSPACECYCLES = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles");
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
@@ -957,7 +1055,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
|
||||
if (*PALLOWWORKSPACECYCLES)
|
||||
if (**PALLOWWORKSPACECYCLES)
|
||||
pWorkspace->rememberPrevWorkspace(POLDWS);
|
||||
}
|
||||
|
||||
@@ -1000,14 +1098,16 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
|
||||
}
|
||||
|
||||
if (const auto PATCOORDS = g_pCompositor->vectorToWindowIdeal(OLDMIDDLE); PATCOORDS && PATCOORDS != PWINDOW)
|
||||
g_pCompositor->focusWindow(PATCOORDS);
|
||||
else
|
||||
g_pInputManager->refocus();
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) {
|
||||
if (const auto PATCOORDS = g_pCompositor->vectorToWindowUnified(OLDMIDDLE, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, PWINDOW); PATCOORDS)
|
||||
g_pCompositor->focusWindow(PATCOORDS);
|
||||
else
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::moveFocusTo(std::string args) {
|
||||
static auto* const PFULLCYCLE = &g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen")->intValue;
|
||||
static auto* const PFULLCYCLE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen");
|
||||
char arg = args[0];
|
||||
|
||||
if (!isDirection(args)) {
|
||||
@@ -1024,7 +1124,7 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ?
|
||||
const auto PWINDOWTOCHANGETO = **PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ?
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
@@ -1039,8 +1139,8 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
if (tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg)))
|
||||
return;
|
||||
|
||||
static auto* const PNOFALLBACK = &g_pConfigManager->getConfigValuePtr("general:no_focus_fallback")->intValue;
|
||||
if (*PNOFALLBACK)
|
||||
static auto* const PNOFALLBACK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:no_focus_fallback");
|
||||
if (**PNOFALLBACK)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "No monitor found in direction {}, falling back to next window on current workspace", arg);
|
||||
@@ -1218,6 +1318,21 @@ void CKeybindManager::toggleSplit(std::string args) {
|
||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglesplit");
|
||||
}
|
||||
|
||||
void CKeybindManager::swapSplit(std::string args) {
|
||||
SLayoutMessageHeader header;
|
||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!header.pWindow)
|
||||
return;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "swapsplit");
|
||||
}
|
||||
|
||||
void CKeybindManager::alterSplitRatio(std::string args) {
|
||||
std::optional<float> splitResult;
|
||||
bool exact = false;
|
||||
@@ -1385,20 +1500,24 @@ void CKeybindManager::renameWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::exitHyprland(std::string argz) {
|
||||
g_pCompositor->cleanup();
|
||||
g_pInputManager->m_bExitTriggered = true;
|
||||
}
|
||||
|
||||
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||
CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args);
|
||||
|
||||
if (!PMONITOR)
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the current workspace
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
|
||||
if (!PCURRENTWORKSPACE)
|
||||
if (!PCURRENTWORKSPACE) {
|
||||
Debug::log(ERR, "moveCurrentWorkspaceToMonitor invalid workspace!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR);
|
||||
}
|
||||
@@ -1435,9 +1554,51 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
||||
}
|
||||
|
||||
void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
|
||||
std::string workspaceName;
|
||||
const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
|
||||
|
||||
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PCURRMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
if (!PCURRMONITOR) {
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
if (!PWORKSPACE) {
|
||||
PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, PCURRMONITOR->ID);
|
||||
// we can skip the moving, since it's already on the current monitor
|
||||
changeworkspace(PWORKSPACE->getConfigName());
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_iMonitorID != PCURRMONITOR->ID) {
|
||||
const auto POLDMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
if (!POLDMONITOR) { // wat
|
||||
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!");
|
||||
return;
|
||||
}
|
||||
if (POLDMONITOR->activeWorkspace == WORKSPACEID) {
|
||||
g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR);
|
||||
return;
|
||||
} else {
|
||||
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PCURRMONITOR, true);
|
||||
}
|
||||
}
|
||||
|
||||
changeworkspace(PWORKSPACE->getConfigName());
|
||||
}
|
||||
|
||||
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
|
||||
std::string workspaceName = "";
|
||||
int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName);
|
||||
@@ -1448,7 +1609,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
bool requestedWorkspaceIsAlreadyOpen = false;
|
||||
const auto PMONITOR = *PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor;
|
||||
const auto PMONITOR = **PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor;
|
||||
int specialOpenOnMonitor = PMONITOR->specialWorkspaceID;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
@@ -1480,7 +1641,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->szDescription);
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(*m);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
@@ -1596,17 +1757,40 @@ void CKeybindManager::focusWindow(std::string regexp) {
|
||||
|
||||
Debug::log(LOG, "Focusing to window name: {}", PWINDOW->m_szTitle);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
if (!PWORKSPACE) {
|
||||
Debug::log(ERR, "BUG THIS: null workspace in focusWindow");
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->m_pLastMonitor->activeWorkspace != PWINDOW->m_iWorkspaceID) {
|
||||
Debug::log(LOG, "Fake executing workspace to move focus");
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
if (!PWORKSPACE) {
|
||||
Debug::log(ERR, "BUG THIS: null workspace in focusWindow");
|
||||
return;
|
||||
}
|
||||
changeworkspace(PWORKSPACE->getConfigName());
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto FSWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
// don't make floating implicitly fs
|
||||
if (!PWINDOW->m_bCreatedOverFullscreen) {
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, true);
|
||||
g_pCompositor->updateFullscreenFadeOnWorkspace(PWORKSPACE);
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
} else {
|
||||
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(FSWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FSMODE);
|
||||
}
|
||||
} else
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
}
|
||||
@@ -1742,11 +1926,11 @@ void CKeybindManager::dpms(std::string arg) {
|
||||
if (!port.empty() && m->szName != port)
|
||||
continue;
|
||||
|
||||
wlr_output_enable(m->output, enable);
|
||||
wlr_output_state_set_enabled(m->state.wlr(), enable);
|
||||
|
||||
m->dpmsStatus = enable;
|
||||
|
||||
if (!wlr_output_commit(m->output)) {
|
||||
if (!m->state.commit()) {
|
||||
Debug::log(ERR, "Couldn't commit output {}", m->szName);
|
||||
}
|
||||
|
||||
@@ -1808,7 +1992,7 @@ void CKeybindManager::pinActive(std::string args) {
|
||||
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args != "" && args != "active" && args.length() > 1)
|
||||
if (args != "active" && args.length() > 1)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
@@ -1829,7 +2013,7 @@ void CKeybindManager::pinActive(std::string args) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal());
|
||||
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS);
|
||||
}
|
||||
|
||||
void CKeybindManager::mouse(std::string args) {
|
||||
@@ -1841,7 +2025,7 @@ void CKeybindManager::mouse(std::string args) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (pWindow && !pWindow->m_bIsFullscreen)
|
||||
pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_START, mouseCoords);
|
||||
@@ -1864,7 +2048,8 @@ void CKeybindManager::mouse(std::string args) {
|
||||
if (PRESSED) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
|
||||
g_pInputManager->currentlyDraggedWindow =
|
||||
g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
try {
|
||||
switch (std::stoi(ARGS[1])) {
|
||||
@@ -1959,8 +2144,8 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property!
|
||||
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail();
|
||||
static const auto* USECURRPOS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:insert_after_current");
|
||||
pWindowInDirection = **USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail();
|
||||
|
||||
pWindowInDirection->insertWindowToGroup(pWindow);
|
||||
pWindowInDirection->setGroupCurrent(pWindow);
|
||||
@@ -1974,7 +2159,7 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi
|
||||
}
|
||||
|
||||
void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir) {
|
||||
static auto* const BFOCUSREMOVEDWINDOW = &g_pConfigManager->getConfigValuePtr("group:focus_removed_window")->intValue;
|
||||
static auto* const BFOCUSREMOVEDWINDOW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("group:focus_removed_window");
|
||||
const auto PWINDOWPREV = pWindow->getGroupPrevious();
|
||||
eDirection direction;
|
||||
|
||||
@@ -2001,7 +2186,7 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string&
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
}
|
||||
|
||||
if (*BFOCUSREMOVEDWINDOW) {
|
||||
if (**BFOCUSREMOVEDWINDOW) {
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
g_pCompositor->warpCursorTo(pWindow->middle());
|
||||
} else {
|
||||
@@ -2013,9 +2198,9 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string&
|
||||
void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
char arg = args[0];
|
||||
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock");
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
return;
|
||||
|
||||
if (!isDirection(args)) {
|
||||
@@ -2034,19 +2219,24 @@ void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
return;
|
||||
|
||||
// Do not move window into locked group if binds:ignore_group_lock is false
|
||||
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked)))
|
||||
if (!**PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked)))
|
||||
return;
|
||||
|
||||
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock");
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
return;
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args != "active" && args.length() > 1)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow)
|
||||
return;
|
||||
@@ -2057,7 +2247,7 @@ void CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
char arg = args[0];
|
||||
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
static auto* const PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock");
|
||||
|
||||
if (!isDirection(args)) {
|
||||
Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
@@ -2068,7 +2258,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
if (!PWINDOW || PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
|
||||
if (!**PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
|
||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||
return;
|
||||
}
|
||||
@@ -2081,32 +2271,36 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
|
||||
// note: PWINDOWINDIR is not null implies !PWINDOW->m_bIsFloating
|
||||
if (PWINDOWINDIR && PWINDOWINDIR->m_sGroupData.pNextWindow) { // target is group
|
||||
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) {
|
||||
if (!**PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) {
|
||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
} else
|
||||
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
|
||||
} else if (PWINDOWINDIR) { // target is regular window
|
||||
if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) {
|
||||
if ((!**PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) {
|
||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
} else
|
||||
moveWindowOutOfGroup(PWINDOW, args);
|
||||
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) // no target window
|
||||
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
|
||||
moveWindowOutOfGroup(PWINDOW, args);
|
||||
} else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
|
||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||
g_pCompositor->warpCursorTo(PWINDOW->middle());
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
}
|
||||
|
||||
void CKeybindManager::setIgnoreGroupLock(std::string args) {
|
||||
static auto* const BIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
static auto* const BIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock");
|
||||
|
||||
if (args == "toggle")
|
||||
*BIGNOREGROUPLOCK = !*BIGNOREGROUPLOCK;
|
||||
**BIGNOREGROUPLOCK = !*BIGNOREGROUPLOCK;
|
||||
else
|
||||
*BIGNOREGROUPLOCK = args == "on";
|
||||
**BIGNOREGROUPLOCK = args == "on";
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(*BIGNOREGROUPLOCK)});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**BIGNOREGROUPLOCK)});
|
||||
}
|
||||
|
||||
void CKeybindManager::denyWindowFromGroup(std::string args) {
|
||||
|
@@ -12,7 +12,7 @@ class CPluginSystem;
|
||||
|
||||
struct SKeybind {
|
||||
std::string key = "";
|
||||
int keycode = -1;
|
||||
uint32_t keycode = 0;
|
||||
uint32_t modmask = 0;
|
||||
std::string handler = "";
|
||||
std::string arg = "";
|
||||
@@ -36,6 +36,14 @@ enum eFocusWindowMode {
|
||||
MODE_PID
|
||||
};
|
||||
|
||||
struct SPressedKeyWithMods {
|
||||
std::string keyName = "";
|
||||
xkb_keysym_t keysym = 0;
|
||||
uint32_t keycode = 0;
|
||||
uint32_t modmaskAtPressTime = 0;
|
||||
bool sent = false;
|
||||
};
|
||||
|
||||
class CKeybindManager {
|
||||
public:
|
||||
CKeybindManager();
|
||||
@@ -51,8 +59,9 @@ class CKeybindManager {
|
||||
void addKeybind(SKeybind);
|
||||
void removeKeybind(uint32_t, const std::string&);
|
||||
uint32_t stringToModMask(std::string);
|
||||
uint32_t keycodeToModifier(xkb_keycode_t);
|
||||
void clearKeybinds();
|
||||
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0);
|
||||
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0);
|
||||
|
||||
std::unordered_map<std::string, std::function<void(std::string)>> m_mDispatchers;
|
||||
|
||||
@@ -61,40 +70,40 @@ class CKeybindManager {
|
||||
bool m_bGroupsLocked = false;
|
||||
|
||||
std::list<SKeybind> m_lKeybinds;
|
||||
std::list<SShortcutInhibitor> m_lShortcutInhibitors;
|
||||
|
||||
private:
|
||||
std::deque<xkb_keysym_t> m_dPressedKeysyms;
|
||||
std::deque<int> m_dPressedKeycodes;
|
||||
std::deque<SPressedKeyWithMods> m_dPressedKeys;
|
||||
|
||||
inline static std::string m_szCurrentSelectedSubmap = "";
|
||||
inline static std::string m_szCurrentSelectedSubmap = "";
|
||||
|
||||
SKeybind* m_pActiveKeybind = nullptr;
|
||||
SKeybind* m_pActiveKeybind = nullptr;
|
||||
|
||||
uint32_t m_uTimeLastMs = 0;
|
||||
uint32_t m_uLastCode = 0;
|
||||
uint32_t m_uLastMouseCode = 0;
|
||||
uint32_t m_uTimeLastMs = 0;
|
||||
uint32_t m_uLastCode = 0;
|
||||
uint32_t m_uLastMouseCode = 0;
|
||||
|
||||
bool m_bIsMouseBindActive = false;
|
||||
std::vector<SKeybind*> m_vPressedSpecialBinds;
|
||||
bool m_bIsMouseBindActive = false;
|
||||
std::vector<SKeybind*> m_vPressedSpecialBinds;
|
||||
|
||||
int m_iPassPressed = -1; // used for pass
|
||||
int m_iPassPressed = -1; // used for pass
|
||||
|
||||
CTimer m_tScrollTimer;
|
||||
CTimer m_tScrollTimer;
|
||||
|
||||
bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t);
|
||||
bool handleKeybinds(const uint32_t, const SPressedKeyWithMods&, bool);
|
||||
|
||||
bool handleInternalKeybinds(xkb_keysym_t);
|
||||
bool handleVT(xkb_keysym_t);
|
||||
bool handleInternalKeybinds(xkb_keysym_t);
|
||||
bool handleVT(xkb_keysym_t);
|
||||
|
||||
xkb_state* m_pXKBTranslationState = nullptr;
|
||||
xkb_state* m_pXKBTranslationState = nullptr;
|
||||
|
||||
void updateXKBTranslationState();
|
||||
bool ensureMouseBindState();
|
||||
void updateXKBTranslationState();
|
||||
bool ensureMouseBindState();
|
||||
|
||||
static bool tryMoveFocusToMonitor(CMonitor* monitor);
|
||||
static void moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir = "");
|
||||
static void moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDirection);
|
||||
static void switchToWindow(CWindow* PWINDOWTOCHANGETO);
|
||||
static bool tryMoveFocusToMonitor(CMonitor* monitor);
|
||||
static void moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir = "");
|
||||
static void moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDirection);
|
||||
static void switchToWindow(CWindow* PWINDOWTOCHANGETO);
|
||||
|
||||
// -------------- Dispatchers -------------- //
|
||||
static void killActive(std::string);
|
||||
@@ -119,6 +128,7 @@ class CKeybindManager {
|
||||
static void alterSplitRatio(std::string);
|
||||
static void focusMonitor(std::string);
|
||||
static void toggleSplit(std::string);
|
||||
static void swapSplit(std::string);
|
||||
static void moveCursorToCorner(std::string);
|
||||
static void moveCursor(std::string);
|
||||
static void workspaceOpt(std::string);
|
||||
@@ -126,6 +136,7 @@ class CKeybindManager {
|
||||
static void exitHyprland(std::string);
|
||||
static void moveCurrentWorkspaceToMonitor(std::string);
|
||||
static void moveWorkspaceToMonitor(std::string);
|
||||
static void focusWorkspaceOnCurrentMonitor(std::string);
|
||||
static void toggleSpecialWorkspace(std::string);
|
||||
static void forceRendererReload(std::string);
|
||||
static void resizeActive(std::string);
|
||||
|
@@ -44,9 +44,9 @@ static void handleSurfaceDestroy(void* owner, void* data) {
|
||||
|
||||
void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
|
||||
static auto* const PALLOWRELOCK = &g_pConfigManager->getConfigValuePtr("misc:allow_session_lock_restore")->intValue;
|
||||
static auto* const PALLOWRELOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:allow_session_lock_restore");
|
||||
|
||||
if (m_sSessionLock.active && (!*PALLOWRELOCK || m_sSessionLock.pWlrLock)) {
|
||||
if (m_sSessionLock.active && (!**PALLOWRELOCK || m_sSessionLock.pWlrLock)) {
|
||||
Debug::log(LOG, "Attempted to lock a locked session!");
|
||||
wlr_session_lock_v1_destroy(pWlrLock);
|
||||
return;
|
||||
@@ -75,6 +75,8 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
PSURFACE->pWlrLockSurface = PWLRSURFACE;
|
||||
PSURFACE->iMonitorID = PMONITOR->ID;
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PSURFACE->pWlrLockSurface->surface, PMONITOR->scale);
|
||||
|
||||
wlr_session_lock_surface_v1_configure(PWLRSURFACE, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
|
||||
PSURFACE->hyprListener_map.initCallback(&PWLRSURFACE->surface->events.map, &handleSurfaceMap, PSURFACE, "SSessionLockSurface");
|
||||
|
@@ -7,9 +7,9 @@ int slowUpdate = 0;
|
||||
int handleTimer(void* data) {
|
||||
const auto PTM = (CThreadManager*)data;
|
||||
|
||||
static auto* const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
|
||||
static auto* const PDISABLECFGRELOAD = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:disable_autoreload");
|
||||
|
||||
if (*PDISABLECFGRELOAD != 1)
|
||||
if (**PDISABLECFGRELOAD != 1)
|
||||
g_pConfigManager->tick();
|
||||
|
||||
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
|
||||
@@ -18,8 +18,6 @@ int handleTimer(void* data) {
|
||||
}
|
||||
|
||||
CThreadManager::CThreadManager() {
|
||||
HyprCtl::startHyprCtlSocket();
|
||||
|
||||
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
|
||||
|
||||
wl_event_source_timer_update(m_esConfigTimer, 1000);
|
||||
|
@@ -147,17 +147,19 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
|
||||
|
||||
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool force) {
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
|
||||
|
||||
// calculate pos
|
||||
// TODO: this should be decoupled from setWindowSize IMO
|
||||
Vector2D windowPos = pWindow->m_vRealPosition.vec();
|
||||
|
||||
if (pWindow->m_bIsX11 && PMONITOR) {
|
||||
windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor
|
||||
if (*PXWLFORCESCALEZERO)
|
||||
if (**PXWLFORCESCALEZERO)
|
||||
windowPos = windowPos * PMONITOR->scale; // scale if applicable
|
||||
windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland
|
||||
}
|
||||
@@ -170,7 +172,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||
|
||||
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
||||
|
||||
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) {
|
||||
if (**PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) {
|
||||
size = size * PMONITOR->scale;
|
||||
pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale;
|
||||
}
|
||||
@@ -315,12 +317,12 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) {
|
||||
|
||||
Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) {
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
||||
|
||||
CMonitor* pMonitor = nullptr;
|
||||
double bestDistance = __FLT_MAX__;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
const auto SIZ = *PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize;
|
||||
const auto SIZ = **PXWLFORCESCALEZERO ? m->vecTransformedSize : m->vecSize;
|
||||
|
||||
double distance =
|
||||
vecToRectDistanceSquared(coord, {m->vecXWaylandPosition.x, m->vecXWaylandPosition.y}, {m->vecXWaylandPosition.x + SIZ.x - 1, m->vecXWaylandPosition.y + SIZ.y - 1});
|
||||
@@ -337,7 +339,7 @@ Vector2D CHyprXWaylandManager::xwaylandToWaylandCoords(const Vector2D& coord) {
|
||||
// get local coords
|
||||
Vector2D result = coord - pMonitor->vecXWaylandPosition;
|
||||
// if scaled, unscale
|
||||
if (*PXWLFORCESCALEZERO)
|
||||
if (**PXWLFORCESCALEZERO)
|
||||
result = result / pMonitor->scale;
|
||||
// add pos
|
||||
result = result + pMonitor->vecPosition;
|
||||
|
@@ -16,20 +16,20 @@ CInputManager::~CInputManager() {
|
||||
}
|
||||
|
||||
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||
static auto* const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
|
||||
static auto* const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
|
||||
static auto* const PSENSTORAW = &g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw")->intValue;
|
||||
static auto* const PSENS = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("general:sensitivity");
|
||||
static auto* const PNOACCEL = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:force_no_accel");
|
||||
static auto* const PSENSTORAW = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw");
|
||||
|
||||
const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||
const auto DELTA = **PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
|
||||
|
||||
if (*PSENSTORAW == 1)
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS,
|
||||
DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS);
|
||||
if (**PSENSTORAW == 1)
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * **PSENS,
|
||||
DELTA.y * **PSENS, e->unaccel_dx * **PSENS, e->unaccel_dy * **PSENS);
|
||||
else
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y,
|
||||
e->unaccel_dx, e->unaccel_dy);
|
||||
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS);
|
||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * **PSENS, DELTA.y * **PSENS);
|
||||
|
||||
mouseMoveUnified(e->time_msec);
|
||||
|
||||
@@ -73,17 +73,17 @@ void CInputManager::sendMotionEventsToFocused() {
|
||||
}
|
||||
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PMOUSEREFOCUS = &g_pConfigManager->getConfigValuePtr("input:mouse_refocus")->intValue;
|
||||
static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue;
|
||||
static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue;
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PRESIZECURSORICON = &g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border")->intValue;
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
static auto* const PMOUSEREFOCUS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:mouse_refocus");
|
||||
static auto* const PMOUSEDPMS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms");
|
||||
static auto* const PFOLLOWONDND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd");
|
||||
static auto* const PFLOATBEHAVIOR = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus");
|
||||
static auto* const PMOUSEFOCUSMON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor");
|
||||
static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border");
|
||||
static auto* const PRESIZECURSORICON = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border");
|
||||
static auto* const PZOOMFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor");
|
||||
|
||||
const auto FOLLOWMOUSE = *PFOLLOWONDND && m_sDrag.drag ? 1 : *PFOLLOWMOUSE;
|
||||
const auto FOLLOWMOUSE = **PFOLLOWONDND && m_sDrag.drag ? 1 : **PFOLLOWMOUSE;
|
||||
|
||||
m_pFoundSurfaceToFocus = nullptr;
|
||||
m_pFoundLSToFocus = nullptr;
|
||||
@@ -97,7 +97,7 @@ 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) {
|
||||
if (!g_pCompositor->m_bDPMSStateON && **PMOUSEDPMS) {
|
||||
// enable dpms
|
||||
g_pKeybindManager->dpms("on");
|
||||
}
|
||||
@@ -121,7 +121,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (PMONITOR == nullptr)
|
||||
return;
|
||||
|
||||
if (*PZOOMFACTOR != 1.f)
|
||||
if (**PZOOMFACTOR != 1.f)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0)
|
||||
@@ -220,7 +220,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal());
|
||||
|
||||
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor && (*PMOUSEFOCUSMON || refocus))
|
||||
if (PMONITOR && PMONITOR != g_pCompositor->m_pLastMonitor && (**PMOUSEFOCUSMON || refocus))
|
||||
g_pCompositor->setActiveMonitor(PMONITOR);
|
||||
|
||||
if (g_pSessionLockManager->isSessionLocked()) {
|
||||
@@ -261,7 +261,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
const auto PWINDOWIDEAL = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (PWINDOWIDEAL &&
|
||||
((PWINDOWIDEAL->m_bIsFloating && PWINDOWIDEAL->m_bCreatedOverFullscreen) /* floating over fullscreen */
|
||||
@@ -282,19 +282,19 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (pFoundWindow && !g_pCompositor->isWorkspaceSpecial(pFoundWindow->m_iWorkspaceID)) {
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
} else {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
} else {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
@@ -315,11 +315,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
foundSurface =
|
||||
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor);
|
||||
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0)
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor);
|
||||
|
||||
if (!foundSurface) {
|
||||
if (!m_bEmptyFocusCursorSet) {
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
if (**PRESIZEONBORDER && **PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
m_eBorderIconDirection = BORDERICON_NONE;
|
||||
unsetCursorImage();
|
||||
}
|
||||
@@ -389,7 +390,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
if (pFoundWindow) {
|
||||
// change cursor icon if hovering over border
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||
if (**PRESIZEONBORDER && **PRESIZECURSORICON) {
|
||||
if (!pFoundWindow->m_bIsFullscreen && !pFoundWindow->hasPopupAt(mouseCoords)) {
|
||||
setCursorIconOnBorder(pFoundWindow);
|
||||
} else if (m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
@@ -399,7 +400,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
if (FOLLOWMOUSE != 1 && !refocus) {
|
||||
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow &&
|
||||
((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) {
|
||||
((pFoundWindow->m_bIsFloating && **PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && **PFLOATBEHAVIOR != 0))) {
|
||||
// enter if change floating style
|
||||
if (FOLLOWMOUSE != 3 && allowKeyboardRefocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
@@ -421,15 +422,23 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
m_bLastFocusOnLS = false;
|
||||
return; // don't enter any new surfaces
|
||||
} else {
|
||||
if (((FOLLOWMOUSE != 3 && allowKeyboardRefocus) && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus) {
|
||||
m_pLastMouseFocus = pFoundWindow;
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
if (allowKeyboardRefocus && ((FOLLOWMOUSE != 3 && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus)) {
|
||||
if (m_pLastMouseFocus != pFoundWindow || g_pCompositor->m_pLastWindow != pFoundWindow || g_pCompositor->m_pLastFocus != foundSurface || refocus) {
|
||||
m_pLastMouseFocus = pFoundWindow;
|
||||
|
||||
// TODO: this looks wrong. When over a popup, it constantly is switching.
|
||||
// Temp fix until that's figured out. Otherwise spams windowrule lookups and other shit.
|
||||
if (m_pLastMouseFocus != pFoundWindow || g_pCompositor->m_pLastWindow != pFoundWindow)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
else
|
||||
g_pCompositor->focusSurface(foundSurface, pFoundWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bLastFocusOnLS = false;
|
||||
} else {
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
if (**PRESIZEONBORDER && **PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) {
|
||||
m_eBorderIconDirection = BORDERICON_NONE;
|
||||
unsetCursorImage();
|
||||
}
|
||||
@@ -486,11 +495,18 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
||||
if (!cursorImageUnlocked())
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "cursorImage request: surface {:x}", (uintptr_t)e->surface);
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
|
||||
if (e->surface != m_sCursorSurfaceInfo.wlSurface.wlr()) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
|
||||
if (e->surface)
|
||||
m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
|
||||
}
|
||||
|
||||
if (e->surface) {
|
||||
m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
|
||||
m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
} else {
|
||||
@@ -509,6 +525,8 @@ void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_
|
||||
if (!cursorImageUnlocked())
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "cursorImage request: shape {}", (uint32_t)e->shape);
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
m_sCursorSurfaceInfo.vHotspot = {};
|
||||
@@ -587,26 +605,26 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
|
||||
// notify the keybind manager
|
||||
static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
|
||||
static auto* const PPASSMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound");
|
||||
const auto PASS = g_pKeybindManager->onMouseEvent(e);
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
static auto* const PFOLLOWMOUSE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("input:follow_mouse");
|
||||
static auto* const PRESIZEONBORDER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:resize_on_border");
|
||||
static auto* const PBORDERSIZE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:border_size");
|
||||
static auto* const PBORDERGRABEXTEND = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area");
|
||||
const auto BORDER_GRAB_AREA = **PRESIZEONBORDER ? **PBORDERSIZE + **PBORDERGRABEXTEND : 0;
|
||||
|
||||
if (!PASS && !*PPASSMOUSE)
|
||||
if (!PASS && !**PPASSMOUSE)
|
||||
return;
|
||||
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
const auto w = g_pCompositor->vectorToWindowUnified(mouseCoords, ALLOW_FLOATING | RESERVED_EXTENTS | INPUT_EXTENTS);
|
||||
|
||||
if (w && !m_bLastFocusOnLS && w->checkInputOnDecos(INPUT_TYPE_BUTTON, mouseCoords, e))
|
||||
return;
|
||||
|
||||
// clicking on border triggers resize
|
||||
// TODO detect click on LS properly
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WLR_BUTTON_PRESSED) {
|
||||
if (**PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WLR_BUTTON_PRESSED) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA};
|
||||
@@ -620,7 +638,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
|
||||
switch (e->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
if (*PFOLLOWMOUSE == 3) // don't refocus on full loose
|
||||
if (**PFOLLOWMOUSE == 3) // don't refocus on full loose
|
||||
break;
|
||||
|
||||
if ((!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) /* No constraints */
|
||||
@@ -645,15 +663,17 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
}
|
||||
|
||||
// notify app if we didnt handle it
|
||||
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) {
|
||||
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus))
|
||||
wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state);
|
||||
}
|
||||
|
||||
if (const auto PMON = g_pCompositor->getMonitorFromVector(mouseCoords); PMON != g_pCompositor->m_pLastMonitor && PMON)
|
||||
g_pCompositor->setActiveMonitor(PMON);
|
||||
}
|
||||
|
||||
void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
||||
switch (e->state) {
|
||||
case WLR_BUTTON_PRESSED: {
|
||||
const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(getMouseCoordsInternal());
|
||||
const auto PWINDOW = g_pCompositor->vectorToWindowUnified(getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "Cannot kill invalid window!");
|
||||
@@ -673,9 +693,9 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue;
|
||||
static auto* const PSCROLLFACTOR = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor");
|
||||
|
||||
auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR);
|
||||
auto factor = (**PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : **PSCROLLFACTOR);
|
||||
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"event", e}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseAxis", EMAP);
|
||||
@@ -689,13 +709,14 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
|
||||
if (!m_bLastFocusOnLS) {
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS);
|
||||
const auto PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
|
||||
|
||||
if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e))
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source);
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source,
|
||||
WLR_AXIS_RELATIVE_DIRECTION_IDENTICAL);
|
||||
}
|
||||
|
||||
Vector2D CInputManager::getMouseCoordsInternal() {
|
||||
@@ -802,7 +823,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
const auto REPEATRATE = g_pConfigManager->getDeviceInt(devname, "repeat_rate", "input:repeat_rate");
|
||||
const auto REPEATDELAY = g_pConfigManager->getDeviceInt(devname, "repeat_delay", "input:repeat_delay");
|
||||
|
||||
const auto NUMLOCKON = g_pConfigManager->getDeviceInt(devname, "numlock_by_default", "input:numlock_by_default");
|
||||
const auto NUMLOCKON = g_pConfigManager->getDeviceInt(devname, "numlock_by_default", "input:numlock_by_default");
|
||||
const auto RESOLVEBINDSBYSYM = g_pConfigManager->getDeviceInt(devname, "resolve_binds_by_sym", "input:resolve_binds_by_sym");
|
||||
|
||||
const auto FILEPATH = g_pConfigManager->getDeviceString(devname, "kb_file", "input:kb_file");
|
||||
const auto RULES = g_pConfigManager->getDeviceString(devname, "kb_rules", "input:kb_rules");
|
||||
@@ -813,7 +835,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
|
||||
const auto ENABLED = HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "enabled") : true;
|
||||
|
||||
pKeyboard->enabled = ENABLED;
|
||||
pKeyboard->enabled = ENABLED;
|
||||
pKeyboard->resolveBindsBySym = RESOLVEBINDSBYSYM;
|
||||
|
||||
try {
|
||||
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" &&
|
||||
@@ -885,6 +908,9 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
xkb_state_unref(pKeyboard->xkbTranslationState);
|
||||
pKeyboard->xkbTranslationState = xkb_state_new(KEYMAP);
|
||||
|
||||
wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP);
|
||||
|
||||
wlr_keyboard_modifiers wlrMods = {0};
|
||||
@@ -1106,6 +1132,8 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
|
||||
pKeyboard->hyprListener_keyboardMod.removeCallback();
|
||||
pKeyboard->hyprListener_keyboardKey.removeCallback();
|
||||
|
||||
xkb_state_unref(pKeyboard->xkbTranslationState);
|
||||
|
||||
if (pKeyboard->active) {
|
||||
m_lKeyboards.remove(*pKeyboard);
|
||||
|
||||
@@ -1161,8 +1189,8 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", e}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP);
|
||||
|
||||
static auto* const PDPMS = &g_pConfigManager->getConfigValuePtr("misc:key_press_enables_dpms")->intValue;
|
||||
if (*PDPMS && !g_pCompositor->m_bDPMSStateON) {
|
||||
static auto* const PDPMS = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:key_press_enables_dpms");
|
||||
if (**PDPMS && !g_pCompositor->m_bDPMSStateON) {
|
||||
// enable dpms
|
||||
g_pKeybindManager->dpms("on");
|
||||
}
|
||||
@@ -1185,6 +1213,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
|
||||
updateKeyboardsLeds(pKeyboard->keyboard);
|
||||
}
|
||||
|
||||
if (m_bExitTriggered)
|
||||
g_pCompositor->cleanup();
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||
@@ -1457,20 +1488,37 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||
}
|
||||
|
||||
void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
|
||||
|
||||
auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void {
|
||||
if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice);
|
||||
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7);
|
||||
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "enabled", "input:touchdevice:enabled");
|
||||
const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||
if (libinput_device_config_send_events_get_mode(LIBINPUTDEV) != mode)
|
||||
libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode);
|
||||
|
||||
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7);
|
||||
Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->name);
|
||||
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
|
||||
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
|
||||
|
||||
const auto OUTPUT = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output");
|
||||
if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY)
|
||||
PTOUCHDEV->boundOutput = OUTPUT;
|
||||
else
|
||||
PTOUCHDEV->boundOutput = "";
|
||||
auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output");
|
||||
bool bound = !output.empty() && output != STRVAL_EMPTY;
|
||||
const bool AUTODETECT = output == "[[Auto]]";
|
||||
if (!bound && AUTODETECT) {
|
||||
const auto DEFAULTOUTPUT = wlr_touch_from_input_device(PTOUCHDEV->pWlrDevice)->output_name;
|
||||
if (DEFAULTOUTPUT) {
|
||||
output = DEFAULTOUTPUT;
|
||||
bound = true;
|
||||
}
|
||||
}
|
||||
PTOUCHDEV->boundOutput = bound ? output : "";
|
||||
const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr;
|
||||
if (PMONITOR) {
|
||||
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->name, PMONITOR->szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV->pWlrDevice, PMONITOR->output);
|
||||
} else if (bound)
|
||||
Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->name, output);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1501,9 +1549,12 @@ void CInputManager::setTabletConfigs() {
|
||||
const auto OUTPUT = g_pConfigManager->getDeviceString(t.name, "output", "input:tablet:output");
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromString(OUTPUT);
|
||||
if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY && PMONITOR) {
|
||||
Debug::log(LOG, "Binding tablet {} to output {}", t.name, PMONITOR->szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output);
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr);
|
||||
}
|
||||
t.boundOutput = OUTPUT;
|
||||
} else if (!PMONITOR)
|
||||
Debug::log(ERR, "Failed to bind tablet {} to output '{}': monitor not found", t.name, OUTPUT);
|
||||
|
||||
const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position");
|
||||
const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size");
|
||||
@@ -1647,17 +1698,17 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) {
|
||||
return;
|
||||
}
|
||||
|
||||
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
static const auto* PEXTENDBORDERGRAB = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
static auto* const PEXTENDBORDERGRAB = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area");
|
||||
const int BORDERSIZE = w->getRealBorderSize();
|
||||
const int ROUNDING = w->rounding();
|
||||
|
||||
// give a small leeway (10 px) for corner icon
|
||||
const auto CORNER = *PROUNDING + BORDERSIZE + 10;
|
||||
const auto CORNER = ROUNDING + BORDERSIZE + 10;
|
||||
const auto mouseCoords = getMouseCoordsInternal();
|
||||
CBox box = w->getWindowMainSurfaceBox();
|
||||
eBorderIconDirection direction = BORDERICON_NONE;
|
||||
CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
CBox boxFullGrabInput = {box.x - **PEXTENDBORDERGRAB - BORDERSIZE, box.y - **PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (**PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (**PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
|
||||
if (w->hasPopupAt(mouseCoords))
|
||||
direction = BORDERICON_NONE;
|
||||
|
@@ -142,25 +142,28 @@ class CInputManager {
|
||||
// Switches
|
||||
std::list<SSwitchDevice> m_lSwitches;
|
||||
|
||||
void newTabletTool(wlr_input_device*);
|
||||
void newTabletPad(wlr_input_device*);
|
||||
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
|
||||
void recheckIdleInhibitorStatus();
|
||||
// Exclusive layer surfaces
|
||||
std::deque<SLayerSurface*> m_dExclusiveLSes;
|
||||
|
||||
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||
void newTabletTool(wlr_input_device*);
|
||||
void newTabletPad(wlr_input_device*);
|
||||
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
|
||||
void recheckIdleInhibitorStatus();
|
||||
|
||||
SSwipeGesture m_sActiveSwipe;
|
||||
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||
|
||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||
SSwipeGesture m_sActiveSwipe;
|
||||
|
||||
CTimer m_tmrLastCursorMovement;
|
||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||
|
||||
CInputMethodRelay m_sIMERelay;
|
||||
CTimer m_tmrLastCursorMovement;
|
||||
|
||||
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
||||
CInputMethodRelay m_sIMERelay;
|
||||
|
||||
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
||||
|
||||
// for shared mods
|
||||
uint32_t accumulateModsFromAllKBs();
|
||||
@@ -243,6 +246,8 @@ class CInputManager {
|
||||
|
||||
void restoreCursorIconToApp(); // no-op if restored
|
||||
|
||||
bool m_bExitTriggered = false; // for exit dispatcher
|
||||
|
||||
friend class CKeybindManager;
|
||||
friend class CWLSurface;
|
||||
};
|
||||
|