Compare commits
No commits in common. "main" and "v0.1.0beta" have entirely different histories.
main
...
v0.1.0beta
|
|
@ -1,65 +0,0 @@
|
||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: LLVM
|
|
||||||
|
|
||||||
AccessModifierOffset: -2
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AlignConsecutiveMacros: true
|
|
||||||
AlignConsecutiveAssignments: true
|
|
||||||
AlignEscapedNewlines: Right
|
|
||||||
AlignOperands: false
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AllowAllArgumentsOnNextLine: true
|
|
||||||
AllowAllConstructorInitializersOnNextLine: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
AllowShortBlocksOnASingleLine: true
|
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
AllowShortLambdasOnASingleLine: All
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
BreakBeforeTernaryOperators: false
|
|
||||||
BreakConstructorInitializers: AfterColon
|
|
||||||
ColumnLimit: 180
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
FixNamespaceComments: false
|
|
||||||
IncludeBlocks: Preserve
|
|
||||||
IndentCaseLabels: true
|
|
||||||
IndentWidth: 4
|
|
||||||
PointerAlignment: Left
|
|
||||||
ReflowComments: false
|
|
||||||
SortIncludes: false
|
|
||||||
SortUsingDeclarations: false
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterLogicalNot: false
|
|
||||||
SpaceAfterTemplateKeyword: true
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeInheritanceColon: true
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Standard: Auto
|
|
||||||
TabWidth: 4
|
|
||||||
UseTab: Never
|
|
||||||
|
|
||||||
AllowShortEnumsOnASingleLine: false
|
|
||||||
|
|
||||||
BraceWrapping:
|
|
||||||
AfterEnum: false
|
|
||||||
|
|
||||||
AlignConsecutiveDeclarations: AcrossEmptyLines
|
|
||||||
|
|
||||||
NamespaceIndentation: All
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
subprojects/**/*
|
|
||||||
208
.clang-tidy
|
|
@ -1,208 +0,0 @@
|
||||||
WarningsAsErrors: >
|
|
||||||
-*,
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-multi-level-implicit-pointer-conversion,
|
|
||||||
-bugprone-empty-catch,
|
|
||||||
-bugprone-unused-return-value,
|
|
||||||
-bugprone-reserved-identifier,
|
|
||||||
-bugprone-switch-missing-default-case,
|
|
||||||
-bugprone-unused-local-non-trivial-variable,
|
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-bugprone-forward-declararion-namespace,
|
|
||||||
-bugprone-forward-declararion-namespace,
|
|
||||||
-bugprone-macro-parentheses,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
-bugprone-branch-clone,
|
|
||||||
-bugprone-assignment-in-if-condition,
|
|
||||||
concurrency-*,
|
|
||||||
-concurrency-mt-unsafe,
|
|
||||||
cppcoreguidelines-*,
|
|
||||||
-cppcoreguidelines-pro-type-const-cast,
|
|
||||||
-cppcoreguidelines-owning-memory,
|
|
||||||
-cppcoreguidelines-avoid-magic-numbers,
|
|
||||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
|
||||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
|
||||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
|
||||||
-cppcoreguidelines-avoid-goto,
|
|
||||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
|
||||||
-cppcoreguidelines-avoid-do-while,
|
|
||||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
|
||||||
-cppcoreguidelines-special-member-functions,
|
|
||||||
-cppcoreguidelines-explicit-virtual-functions,
|
|
||||||
-cppcoreguidelines-avoid-c-arrays,
|
|
||||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
|
||||||
-cppcoreguidelines-narrowing-conversions,
|
|
||||||
-cppcoreguidelines-pro-type-union-access,
|
|
||||||
-cppcoreguidelines-pro-type-member-init,
|
|
||||||
-cppcoreguidelines-macro-usage,
|
|
||||||
-cppcoreguidelines-macro-to-enum,
|
|
||||||
-cppcoreguidelines-init-variables,
|
|
||||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
|
||||||
-cppcoreguidelines-pro-type-vararg,
|
|
||||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
|
||||||
-google-global-names-in-headers,
|
|
||||||
-google-readability-casting,
|
|
||||||
google-runtime-operator,
|
|
||||||
misc-*,
|
|
||||||
-misc-use-internal-linkage,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
-misc-no-recursion,
|
|
||||||
-misc-non-private-member-variables-in-classes,
|
|
||||||
-misc-include-cleaner,
|
|
||||||
-misc-use-anonymous-namespace,
|
|
||||||
-misc-const-correctness,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-use-emplace,
|
|
||||||
-modernize-redundant-void-arg,
|
|
||||||
-modernize-use-starts-ends-with,
|
|
||||||
-modernize-use-designated-initializers,
|
|
||||||
-modernize-use-std-numbers,
|
|
||||||
-modernize-return-braced-init-list,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-override,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-macro-to-enum,
|
|
||||||
-modernize-loop-convert,
|
|
||||||
-modernize-use-nodiscard,
|
|
||||||
-modernize-pass-by-value,
|
|
||||||
-modernize-use-auto,
|
|
||||||
performance-*,
|
|
||||||
-performance-inefficient-vector-operation,
|
|
||||||
-performance-inefficient-string-concatenation,
|
|
||||||
-performance-enum-size,
|
|
||||||
-performance-move-const-arg,
|
|
||||||
-performance-avoid-endl,
|
|
||||||
-performance-unnecessary-value-param,
|
|
||||||
portability-std-allocator-const,
|
|
||||||
readability-*,
|
|
||||||
-readability-identifier-naming,
|
|
||||||
-readability-use-std-min-max,
|
|
||||||
-readability-math-missing-parentheses,
|
|
||||||
-readability-simplify-boolean-expr,
|
|
||||||
-readability-static-accessed-through-instance,
|
|
||||||
-readability-use-anyofallof,
|
|
||||||
-readability-enum-initial-value,
|
|
||||||
-readability-redundant-inline-specifier,
|
|
||||||
-readability-function-cognitive-complexity,
|
|
||||||
-readability-function-size,
|
|
||||||
-readability-identifier-length,
|
|
||||||
-readability-magic-numbers,
|
|
||||||
-readability-uppercase-literal-suffix,
|
|
||||||
-readability-braces-around-statements,
|
|
||||||
-readability-redundant-access-specifiers,
|
|
||||||
-readability-else-after-return,
|
|
||||||
-readability-container-data-pointer,
|
|
||||||
-readability-implicit-bool-conversion,
|
|
||||||
-readability-avoid-nested-conditional-operator,
|
|
||||||
-readability-redundant-member-init,
|
|
||||||
-readability-redundant-string-init,
|
|
||||||
-readability-avoid-const-params-in-decls,
|
|
||||||
-readability-named-parameter,
|
|
||||||
-readability-convert-member-functions-to-static,
|
|
||||||
-readability-qualified-auto,
|
|
||||||
-readability-make-member-function-const,
|
|
||||||
-readability-isolate-declaration,
|
|
||||||
-readability-inconsistent-declaration-parameter-name,
|
|
||||||
-clang-diagnostic-error,
|
|
||||||
|
|
||||||
HeaderFilterRegex: '.*\.hpp'
|
|
||||||
FormatStyle: file
|
|
||||||
Checks: >
|
|
||||||
-*,
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-bugprone-forward-declararion-namespace,
|
|
||||||
-bugprone-forward-declararion-namespace,
|
|
||||||
-bugprone-macro-parentheses,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
-bugprone-branch-clone,
|
|
||||||
-bugprone-assignment-in-if-condition,
|
|
||||||
concurrency-*,
|
|
||||||
-concurrency-mt-unsafe,
|
|
||||||
cppcoreguidelines-*,
|
|
||||||
-cppcoreguidelines-owning-memory,
|
|
||||||
-cppcoreguidelines-avoid-magic-numbers,
|
|
||||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
|
||||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
|
||||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
|
||||||
-cppcoreguidelines-avoid-goto,
|
|
||||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
|
||||||
-cppcoreguidelines-avoid-do-while,
|
|
||||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
|
||||||
-cppcoreguidelines-special-member-functions,
|
|
||||||
-cppcoreguidelines-explicit-virtual-functions,
|
|
||||||
-cppcoreguidelines-avoid-c-arrays,
|
|
||||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
|
||||||
-cppcoreguidelines-narrowing-conversions,
|
|
||||||
-cppcoreguidelines-pro-type-union-access,
|
|
||||||
-cppcoreguidelines-pro-type-member-init,
|
|
||||||
-cppcoreguidelines-macro-usage,
|
|
||||||
-cppcoreguidelines-macro-to-enum,
|
|
||||||
-cppcoreguidelines-init-variables,
|
|
||||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
|
||||||
-cppcoreguidelines-pro-type-vararg,
|
|
||||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
|
||||||
google-global-names-in-headers,
|
|
||||||
-google-readability-casting,
|
|
||||||
google-runtime-operator,
|
|
||||||
misc-*,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
-misc-no-recursion,
|
|
||||||
-misc-non-private-member-variables-in-classes,
|
|
||||||
-misc-include-cleaner,
|
|
||||||
-misc-use-anonymous-namespace,
|
|
||||||
-misc-const-correctness,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-return-braced-init-list,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-override,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-macro-to-enum,
|
|
||||||
-modernize-loop-convert,
|
|
||||||
-modernize-use-nodiscard,
|
|
||||||
-modernize-pass-by-value,
|
|
||||||
-modernize-use-auto,
|
|
||||||
performance-*,
|
|
||||||
-performance-avoid-endl,
|
|
||||||
-performance-unnecessary-value-param,
|
|
||||||
portability-std-allocator-const,
|
|
||||||
readability-*,
|
|
||||||
-readability-function-cognitive-complexity,
|
|
||||||
-readability-function-size,
|
|
||||||
-readability-identifier-length,
|
|
||||||
-readability-magic-numbers,
|
|
||||||
-readability-uppercase-literal-suffix,
|
|
||||||
-readability-braces-around-statements,
|
|
||||||
-readability-redundant-access-specifiers,
|
|
||||||
-readability-else-after-return,
|
|
||||||
-readability-container-data-pointer,
|
|
||||||
-readability-implicit-bool-conversion,
|
|
||||||
-readability-avoid-nested-conditional-operator,
|
|
||||||
-readability-redundant-member-init,
|
|
||||||
-readability-redundant-string-init,
|
|
||||||
-readability-avoid-const-params-in-decls,
|
|
||||||
-readability-named-parameter,
|
|
||||||
-readability-convert-member-functions-to-static,
|
|
||||||
-readability-qualified-auto,
|
|
||||||
-readability-make-member-function-const,
|
|
||||||
-readability-isolate-declaration,
|
|
||||||
-readability-inconsistent-declaration-parameter-name,
|
|
||||||
-clang-diagnostic-error,
|
|
||||||
|
|
||||||
CheckOptions:
|
|
||||||
performance-for-range-copy.WarnOnAllAutoCopies: true
|
|
||||||
performance-inefficient-string-concatenation.StrictMode: true
|
|
||||||
readability-braces-around-statements.ShortStatementLines: 0
|
|
||||||
readability-identifier-naming.ClassCase: CamelCase
|
|
||||||
readability-identifier-naming.ClassIgnoredRegexp: I.*
|
|
||||||
readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!?
|
|
||||||
readability-identifier-naming.EnumCase: CamelCase
|
|
||||||
readability-identifier-naming.EnumPrefix: e
|
|
||||||
readability-identifier-naming.EnumConstantCase: UPPER_CASE
|
|
||||||
readability-identifier-naming.FunctionCase: camelBack
|
|
||||||
readability-identifier-naming.NamespaceCase: CamelCase
|
|
||||||
readability-identifier-naming.NamespacePrefix: N
|
|
||||||
readability-identifier-naming.StructPrefix: S
|
|
||||||
readability-identifier-naming.StructCase: CamelCase
|
|
||||||
1
.github/FUNDING.yml
vendored
|
|
@ -1 +0,0 @@
|
||||||
ko_fi: vaxry
|
|
||||||
15
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
name: Do not open issues, go to discussions please!
|
|
||||||
description: Do not open an issue
|
|
||||||
body:
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Please close this issue.
|
|
||||||
description: Users cannot open issues. I want my issue to be closed.
|
|
||||||
options:
|
|
||||||
- label: Yes, I want this issue to be closed.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: body
|
|
||||||
attributes:
|
|
||||||
label: Issue body
|
|
||||||
15
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Found a bug? Report it here!
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
|
||||||
|
|
||||||
|
**Images/videos/anything that would help**
|
||||||
|
|
||||||
|
|
||||||
|
Please attach a log (it's in /tmp/hypr/hyprland.log) and, if crashing, a crashdump (coredumpctl, then coredumpctl info <pid>)
|
||||||
9
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest a feature/change/idea
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe in detail your idea.**
|
||||||
123
.github/actions/setup_base/action.yml
vendored
|
|
@ -1,123 +0,0 @@
|
||||||
name: "Setup base"
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
INSTALL_XORG_PKGS:
|
|
||||||
description: 'Install xorg dependencies'
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: Get required pacman pkgs
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
|
||||||
pacman --noconfirm --noprogressbar -Sy \
|
|
||||||
base-devel \
|
|
||||||
cairo \
|
|
||||||
clang \
|
|
||||||
cmake \
|
|
||||||
git \
|
|
||||||
glaze \
|
|
||||||
glm \
|
|
||||||
glslang \
|
|
||||||
go \
|
|
||||||
gtest \
|
|
||||||
hyprlang \
|
|
||||||
hyprcursor \
|
|
||||||
jq \
|
|
||||||
libc++ \
|
|
||||||
libdisplay-info \
|
|
||||||
libdrm \
|
|
||||||
libepoxy \
|
|
||||||
libfontenc \
|
|
||||||
libglvnd \
|
|
||||||
libinput \
|
|
||||||
libjxl \
|
|
||||||
libliftoff \
|
|
||||||
libspng \
|
|
||||||
libwebp \
|
|
||||||
libxcursor \
|
|
||||||
libxcvt \
|
|
||||||
libxfont2 \
|
|
||||||
libxkbcommon \
|
|
||||||
libxkbfile \
|
|
||||||
lld \
|
|
||||||
meson \
|
|
||||||
muparser \
|
|
||||||
ninja \
|
|
||||||
pango \
|
|
||||||
pixman \
|
|
||||||
pkgconf \
|
|
||||||
pugixml \
|
|
||||||
scdoc \
|
|
||||||
seatd \
|
|
||||||
systemd \
|
|
||||||
tomlplusplus \
|
|
||||||
wayland \
|
|
||||||
wayland-protocols \
|
|
||||||
xcb-util-errors \
|
|
||||||
xcb-util-renderutil \
|
|
||||||
xcb-util-wm \
|
|
||||||
xcb-util \
|
|
||||||
xcb-util-image \
|
|
||||||
libzip \
|
|
||||||
librsvg \
|
|
||||||
re2
|
|
||||||
|
|
||||||
- name: Get hyprwayland-scanner-git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/hyprwm/hyprwayland-scanner --recursive
|
|
||||||
cd hyprwayland-scanner
|
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
|
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
|
||||||
cmake --install build
|
|
||||||
|
|
||||||
- name: Get hyprwire-git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/hyprwm/hyprwire --recursive
|
|
||||||
cd hyprwire
|
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
|
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
|
||||||
cmake --install build
|
|
||||||
|
|
||||||
- name: Get hyprutils-git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build
|
|
||||||
|
|
||||||
- name: Get hyprgraphics-git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build
|
|
||||||
|
|
||||||
- name: Get aquamarine-git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/hyprwm/aquamarine && cd aquamarine && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target aquamarine && cmake --install build
|
|
||||||
|
|
||||||
- name: Get Xorg pacman pkgs
|
|
||||||
shell: bash
|
|
||||||
if: inputs.INSTALL_XORG_PKGS == 'true'
|
|
||||||
run: |
|
|
||||||
pacman --noconfirm --noprogressbar -Sy \
|
|
||||||
xorg-fonts-encodings \
|
|
||||||
xorg-server-common \
|
|
||||||
xorg-setxkbmap \
|
|
||||||
xorg-xkbcomp \
|
|
||||||
xorg-xwayland
|
|
||||||
|
|
||||||
- name: Checkout Hyprland
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
# Fix an issue with actions/checkout where the checkout repo is not mark as safe
|
|
||||||
- name: Mark directory as safe for git
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
|
||||||
87
.github/labeler.yml
vendored
|
|
@ -1,87 +0,0 @@
|
||||||
assets:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "assets/**"
|
|
||||||
|
|
||||||
docs:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "docs/**"
|
|
||||||
|
|
||||||
hyprctl:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "hyprctl/**"
|
|
||||||
|
|
||||||
hyprpm:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "hyprpm/**"
|
|
||||||
|
|
||||||
nix:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "nix/**"
|
|
||||||
|
|
||||||
protocols:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ["protocols/**", "src/protocols/**"]
|
|
||||||
|
|
||||||
start:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "start/**"
|
|
||||||
|
|
||||||
core:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/**"
|
|
||||||
|
|
||||||
config:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/config/**"
|
|
||||||
|
|
||||||
debug:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/debug/**"
|
|
||||||
|
|
||||||
desktop:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/desktop/**"
|
|
||||||
|
|
||||||
devices:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/devices/**"
|
|
||||||
|
|
||||||
events:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/events/**"
|
|
||||||
|
|
||||||
helpers:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/helpers/**"
|
|
||||||
|
|
||||||
hyprerror:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/hyprerror/**"
|
|
||||||
|
|
||||||
init:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/init/**"
|
|
||||||
|
|
||||||
layout:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/layout/**"
|
|
||||||
|
|
||||||
managers:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/managers/**"
|
|
||||||
|
|
||||||
pch:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/pch/**"
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/plugins/**"
|
|
||||||
|
|
||||||
render:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/render/**"
|
|
||||||
|
|
||||||
xwayland:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: "src/xwayland/**"
|
|
||||||
12
.github/pull_request_template.md
vendored
|
|
@ -1,15 +1,9 @@
|
||||||
<!--
|
Describe your PR, what does it fix/add?
|
||||||
BEFORE you submit your PR, please check out the PR guidelines
|
|
||||||
on our wiki: https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
#### Describe your PR, what does it fix/add?
|
Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
|
||||||
|
|
||||||
|
|
||||||
#### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
|
Is it ready for merging, or does it need work?
|
||||||
|
|
||||||
|
|
||||||
#### Is it ready for merging, or does it need work?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
65
.github/workflows/ci.yaml
vendored
|
|
@ -3,54 +3,39 @@ name: Build Hyprland
|
||||||
on: [push, pull_request, workflow_dispatch]
|
on: [push, pull_request, workflow_dispatch]
|
||||||
jobs:
|
jobs:
|
||||||
gcc:
|
gcc:
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: "Build Hyprland (Arch)"
|
name: "Build Hyprland (Arch)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: archlinux
|
image: archlinux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository actions
|
- name: Get required pacman pkgs
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
with:
|
|
||||||
INSTALL_XORG_PKGS: true
|
|
||||||
|
|
||||||
- name: Build Hyprland
|
|
||||||
run: |
|
run: |
|
||||||
CFLAGS=-Werror CXXFLAGS=-Werror make nopch
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
|
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
|
||||||
|
|
||||||
- name: Compress and package artifacts
|
- name: Set up user
|
||||||
run: |
|
run: |
|
||||||
mkdir x86_64-pc-linux-gnu
|
useradd -m githubuser
|
||||||
mkdir hyprland
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
cp ./LICENSE hyprland/
|
|
||||||
cp build/Hyprland hyprland/
|
|
||||||
cp build/hyprctl/hyprctl hyprland/
|
|
||||||
cp build/hyprpm/hyprpm hyprland/
|
|
||||||
cp -r example/ hyprland/
|
|
||||||
cp -r assets/ hyprland/
|
|
||||||
tar -cvJf Hyprland.tar.xz hyprland
|
|
||||||
|
|
||||||
- name: Release
|
- name: Build wlroots
|
||||||
uses: actions/upload-artifact@v4
|
run: |
|
||||||
with:
|
su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots"
|
||||||
name: Build archive
|
su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .."
|
||||||
path: Hyprland.tar.xz
|
|
||||||
|
|
||||||
clang-format:
|
- name: Fix permissions for git
|
||||||
permissions: read-all
|
run: |
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
||||||
name: "Code Style"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: clang-format check
|
- name: Checkout Hyprland
|
||||||
uses: jidicula/clang-format-action@v4.16.0
|
uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
exclude-regex: ^subprojects$
|
- name: Build Hyprland With default settings
|
||||||
|
run: |
|
||||||
|
git submodule sync --recursive && git submodule update --init --force --recursive
|
||||||
|
make all
|
||||||
|
|
||||||
|
- name: Build Hyprland with LEGACY_RENDERER
|
||||||
|
run: |
|
||||||
|
make legacyrenderer
|
||||||
|
|
|
||||||
28
.github/workflows/clang-format.yml
vendored
|
|
@ -1,28 +0,0 @@
|
||||||
name: clang-format
|
|
||||||
on: pull_request_target
|
|
||||||
jobs:
|
|
||||||
clang-format:
|
|
||||||
permissions: write-all
|
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: "Code Style"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: clang-format check
|
|
||||||
uses: jidicula/clang-format-action@v4.16.0
|
|
||||||
with:
|
|
||||||
exclude-regex: ^subprojects$
|
|
||||||
|
|
||||||
- name: Create comment
|
|
||||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
|
||||||
run: |
|
|
||||||
echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style).' > clang-format.patch
|
|
||||||
|
|
||||||
- name: Post comment
|
|
||||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
|
||||||
uses: mshick/add-pr-comment@v2
|
|
||||||
with:
|
|
||||||
message-path: |
|
|
||||||
clang-format.patch
|
|
||||||
101
.github/workflows/close-issues.yml
vendored
|
|
@ -1,101 +0,0 @@
|
||||||
name: Close Unauthorized Issues
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
close-unauthorized-issues:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
steps:
|
|
||||||
# XXX: This *could* be done in Bash by abusing GitHub's own tool to interact with its API
|
|
||||||
# but that's too much of a hack, and we'll be adding a layer of abstraction. github-script
|
|
||||||
# is a workflow that eases interaction with GitHub API in the workflow run context.
|
|
||||||
- name: "Close 'unauthorized' issues"
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const ALLOWED_USERS = ['vaxerski', 'fufexan', 'NotAShelf'];
|
|
||||||
const CLOSING_COMMENT = 'Users are no longer allowed to open issues themselves, please open a discussion instead.\n\nPlease see the [wiki](https://wiki.hyprland.org/Contributing-and-Debugging/Issue-Guidelines/) on why this is the case.\n\nWe are volunteers, and we need your cooperation to make the best software we can. Thank you for understanding! ❤️\n\n[Open a discussion here](https://github.com/hyprwm/Hyprland/discussions)';
|
|
||||||
|
|
||||||
async function closeUnauthorizedIssue(issueNumber, userName) {
|
|
||||||
if (ALLOWED_USERS.includes(userName)) {
|
|
||||||
console.log(`Issue #${issueNumber} - Created by authorized user ${userName}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Issue #${issueNumber} - Unauthorized, closing`);
|
|
||||||
|
|
||||||
await github.rest.issues.update({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
state: 'closed',
|
|
||||||
state_reason: 'not_planned'
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
body: CLOSING_COMMENT
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.eventName === 'issues' && context.payload.action === 'opened') {
|
|
||||||
// Direct access to the issue that triggered the workflow
|
|
||||||
const issue = context.payload.issue;
|
|
||||||
|
|
||||||
// Skip if this is a PR
|
|
||||||
if (issue.pull_request) {
|
|
||||||
console.log(`Issue #${issue.number} - Skipping, this is a pull request`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the single issue that triggered the workflow
|
|
||||||
await closeUnauthorizedIssue(issue.number, issue.user.login);
|
|
||||||
} else {
|
|
||||||
// For manual runs, we need to handle pagination
|
|
||||||
async function* fetchAllOpenIssues() {
|
|
||||||
let page = 1;
|
|
||||||
let hasNextPage = true;
|
|
||||||
|
|
||||||
while (hasNextPage) {
|
|
||||||
const response = await github.rest.issues.listForRepo({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'open',
|
|
||||||
per_page: 100,
|
|
||||||
page: page
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.data.length === 0) {
|
|
||||||
hasNextPage = false;
|
|
||||||
} else {
|
|
||||||
for (const issue of response.data) {
|
|
||||||
yield issue;
|
|
||||||
}
|
|
||||||
page++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process issues one by one
|
|
||||||
for await (const issue of fetchAllOpenIssues()) {
|
|
||||||
try {
|
|
||||||
// Skip pull requests
|
|
||||||
if (issue.pull_request) {
|
|
||||||
console.log(`Issue #${issue.number} - Skipping, this is a pull request`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await closeUnauthorizedIssue(issue.number, issue.user.login);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error processing issue #${issue.number}: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
name: Security Checks
|
name: Flawfinder
|
||||||
|
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
flawfinder:
|
flawfinder:
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: Flawfinder Checks
|
name: Flawfinder Checks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
|
|
@ -13,7 +16,7 @@ jobs:
|
||||||
security-events: write
|
security-events: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Scan with Flawfinder
|
- name: Scan with Flawfinder
|
||||||
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
|
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
|
||||||
12
.github/workflows/labeler.yml
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
name: "Pull Request Labeler"
|
|
||||||
on:
|
|
||||||
- pull_request_target
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
labeler:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/labeler@v5
|
|
||||||
30
.github/workflows/man-update.yaml
vendored
|
|
@ -1,30 +0,0 @@
|
||||||
name: Build man pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- docs/**
|
|
||||||
branches:
|
|
||||||
- 'main'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
main:
|
|
||||||
name: Build man pages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install deps
|
|
||||||
run: sudo apt install pandoc
|
|
||||||
|
|
||||||
- name: Clone repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.PAT }}
|
|
||||||
|
|
||||||
- name: Build man pages
|
|
||||||
run: make man
|
|
||||||
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
|
||||||
name: Commit
|
|
||||||
with:
|
|
||||||
commit_message: "[gha] build man pages"
|
|
||||||
45
.github/workflows/new-pr-comment.yml
vendored
|
|
@ -1,45 +0,0 @@
|
||||||
name: "New MR welcome comment"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment:
|
|
||||||
if: >
|
|
||||||
github.event.pull_request.user.login != 'vaxerski' &&
|
|
||||||
github.event.pull_request.user.login != 'fufexan' &&
|
|
||||||
github.event.pull_request.user.login != 'gulafaran' &&
|
|
||||||
github.event.pull_request.user.login != 'ujint34' &&
|
|
||||||
github.event.pull_request.user.login != 'paideiadilemma' &&
|
|
||||||
github.event.pull_request.user.login != 'notashelf'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
PR_COMMENT: |
|
|
||||||
Hello and thank you for making a PR to Hyprland!
|
|
||||||
|
|
||||||
Please check the [PR Guidelines](https://wiki.hypr.land/Contributing-and-Debugging/PR-Guidelines/) and make sure your PR follows them.
|
|
||||||
It will make the entire review process faster. :)
|
|
||||||
|
|
||||||
If your code can be tested, please always add tests. See more [here](https://wiki.hypr.land/Contributing-and-Debugging/Tests/).
|
|
||||||
|
|
||||||
_beep boop, I'm just a bot. A real human will review your PR soon._
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Add comment to PR
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const pr = context.payload.pull_request;
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: pr.number,
|
|
||||||
body: process.env.PR_COMMENT,
|
|
||||||
});
|
|
||||||
19
.github/workflows/nix-build.yaml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
name: Build Hyprland (Nix)
|
||||||
|
|
||||||
|
on: [push, pull_request, workflow_dispatch]
|
||||||
|
jobs:
|
||||||
|
nix:
|
||||||
|
name: "Build Hyprland (Nix)"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install nix
|
||||||
|
uses: cachix/install-nix-action@v17
|
||||||
|
with:
|
||||||
|
install_url: https://releases.nixos.org/nix/nix-2.8.0/install
|
||||||
|
extra_nix_config: |
|
||||||
|
auto-optimise-store = true
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
- name: Build HyprLand with default settings
|
||||||
|
run: nix build --print-build-logs
|
||||||
29
.github/workflows/nix-ci.yml
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
name: Nix
|
|
||||||
|
|
||||||
on: [push, pull_request, workflow_dispatch]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-inputs:
|
|
||||||
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
|
||||||
uses: ./.github/workflows/nix-update-inputs.yml
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
hyprland:
|
|
||||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
|
||||||
uses: ./.github/workflows/nix.yml
|
|
||||||
secrets: inherit
|
|
||||||
with:
|
|
||||||
command: nix build 'github:${{ github.repository }}?ref=${{ github.ref }}' -L --extra-substituters "https://hyprland.cachix.org"
|
|
||||||
|
|
||||||
xdph:
|
|
||||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
|
||||||
needs: hyprland
|
|
||||||
uses: ./.github/workflows/nix.yml
|
|
||||||
secrets: inherit
|
|
||||||
with:
|
|
||||||
command: nix build 'github:${{ github.repository }}?ref=${{ github.ref }}#xdg-desktop-portal-hyprland' -L --extra-substituters "https://hyprland.cachix.org"
|
|
||||||
|
|
||||||
test:
|
|
||||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
|
|
||||||
uses: ./.github/workflows/nix-test.yml
|
|
||||||
secrets: inherit
|
|
||||||
47
.github/workflows/nix-test.yml
vendored
|
|
@ -1,47 +0,0 @@
|
||||||
name: Nix (Test)
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
secrets:
|
|
||||||
CACHIX_AUTH_TOKEN:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install Nix
|
|
||||||
uses: nixbuild/nix-quick-install-action@v31
|
|
||||||
with:
|
|
||||||
nix_conf: |
|
|
||||||
keep-env-derivations = true
|
|
||||||
keep-outputs = true
|
|
||||||
|
|
||||||
- name: Restore and save Nix store
|
|
||||||
uses: nix-community/cache-nix-action@v6
|
|
||||||
with:
|
|
||||||
# restore and save a cache using this key (per job)
|
|
||||||
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}
|
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
|
||||||
# before trying to save a new cache
|
|
||||||
gc-max-store-size-linux: 5G
|
|
||||||
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: hyprland
|
|
||||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
|
||||||
|
|
||||||
- name: Run test VM
|
|
||||||
run: nix build 'github:${{ github.repository }}?ref=${{ github.ref }}#checks.x86_64-linux.tests' -L --extra-substituters "https://hyprland.cachix.org"
|
|
||||||
|
|
||||||
- name: Check exit status
|
|
||||||
run: grep 0 result/exit_status
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: logs
|
|
||||||
path: result
|
|
||||||
44
.github/workflows/nix-update-inputs.yml
vendored
|
|
@ -1,44 +0,0 @@
|
||||||
name: Nix (Update Inputs)
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
secrets:
|
|
||||||
PAT:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update:
|
|
||||||
if: github.repository == 'hyprwm/Hyprland'
|
|
||||||
name: inputs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Clone repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.PAT }}
|
|
||||||
|
|
||||||
- name: Install Nix
|
|
||||||
uses: nixbuild/nix-quick-install-action@v31
|
|
||||||
with:
|
|
||||||
nix_conf: |
|
|
||||||
keep-env-derivations = true
|
|
||||||
keep-outputs = true
|
|
||||||
|
|
||||||
- name: Restore and save Nix store
|
|
||||||
uses: nix-community/cache-nix-action@v6
|
|
||||||
with:
|
|
||||||
# restore and save a cache using this key (per job)
|
|
||||||
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}
|
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
|
||||||
# before trying to save a new cache
|
|
||||||
gc-max-store-size-linux: 5G
|
|
||||||
|
|
||||||
- name: Update inputs
|
|
||||||
run: nix/update-inputs.sh
|
|
||||||
|
|
||||||
- name: Commit
|
|
||||||
uses: stefanzweifel/git-auto-commit-action@v5
|
|
||||||
with:
|
|
||||||
commit_message: "[gha] Nix: update inputs"
|
|
||||||
25
.github/workflows/nix-update.yaml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
name: "Nix: update lockfile"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 */14 * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install nix
|
||||||
|
uses: cachix/install-nix-action@v17
|
||||||
|
with:
|
||||||
|
install_url: https://releases.nixos.org/nix/nix-2.8.0/install
|
||||||
|
extra_nix_config: |
|
||||||
|
auto-optimise-store = true
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
- name: Update lockfile
|
||||||
|
run: nix flake update
|
||||||
|
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
with:
|
||||||
|
commit_message: "[gha] bump flake inputs"
|
||||||
41
.github/workflows/nix.yml
vendored
|
|
@ -1,41 +0,0 @@
|
||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
command:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
description: Command to run
|
|
||||||
secrets:
|
|
||||||
CACHIX_AUTH_TOKEN:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install Nix
|
|
||||||
uses: nixbuild/nix-quick-install-action@v31
|
|
||||||
with:
|
|
||||||
nix_conf: |
|
|
||||||
keep-env-derivations = true
|
|
||||||
keep-outputs = true
|
|
||||||
|
|
||||||
- name: Restore and save Nix store
|
|
||||||
uses: nix-community/cache-nix-action@v6
|
|
||||||
with:
|
|
||||||
# restore and save a cache using this key (per job)
|
|
||||||
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}
|
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
|
||||||
# before trying to save a new cache
|
|
||||||
gc-max-store-size-linux: 5G
|
|
||||||
|
|
||||||
- uses: cachix/cachix-action@v15
|
|
||||||
with:
|
|
||||||
name: hyprland
|
|
||||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
|
||||||
|
|
||||||
- run: ${{ inputs.command }}
|
|
||||||
64
.github/workflows/release.yaml
vendored
|
|
@ -1,64 +0,0 @@
|
||||||
name: Release artifacts
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
source-tarball:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Populate git info in version.h.in
|
|
||||||
run: |
|
|
||||||
git fetch --tags --unshallow || true
|
|
||||||
|
|
||||||
COMMIT_HASH=$(git rev-parse HEAD)
|
|
||||||
BRANCH="${GITHUB_REF_NAME:-$(git rev-parse --abbrev-ref HEAD)}"
|
|
||||||
COMMIT_MSG=$(git show -s --format=%s | sed 's/[&/]/\\&/g')
|
|
||||||
COMMIT_DATE=$(git show -s --format=%cd --date=local)
|
|
||||||
GIT_DIRTY=$(git diff-index --quiet HEAD -- && echo "clean" || echo "dirty")
|
|
||||||
GIT_TAG=$(git describe --tags --always || echo "unknown")
|
|
||||||
GIT_COMMITS=$(git rev-list --count HEAD)
|
|
||||||
|
|
||||||
echo "Branch: $BRANCH"
|
|
||||||
echo "Tag: $GIT_TAG"
|
|
||||||
|
|
||||||
sed -i \
|
|
||||||
-e "s|@GIT_COMMIT_HASH@|$COMMIT_HASH|" \
|
|
||||||
-e "s|@GIT_BRANCH@|$BRANCH|" \
|
|
||||||
-e "s|@GIT_COMMIT_MESSAGE@|$COMMIT_MSG|" \
|
|
||||||
-e "s|@GIT_COMMIT_DATE@|$COMMIT_DATE|" \
|
|
||||||
-e "s|@GIT_DIRTY@|$GIT_DIRTY|" \
|
|
||||||
-e "s|@GIT_TAG@|$GIT_TAG|" \
|
|
||||||
-e "s|@GIT_COMMITS@|$GIT_COMMITS|" \
|
|
||||||
src/version.h.in
|
|
||||||
|
|
||||||
- name: Create tarball with submodules
|
|
||||||
id: tar
|
|
||||||
run: |
|
|
||||||
mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
|
||||||
|
|
||||||
- id: whatrelease
|
|
||||||
name: Get latest release
|
|
||||||
uses: pozetroninc/github-action-get-latest-release@master
|
|
||||||
with:
|
|
||||||
owner: hyprwm
|
|
||||||
repo: Hyprland
|
|
||||||
excludes: prerelease, draft
|
|
||||||
|
|
||||||
- name: Upload to release
|
|
||||||
id: upload
|
|
||||||
uses: svenstaro/upload-release-action@v2
|
|
||||||
with:
|
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
file: source.tar.gz
|
|
||||||
asset_name: source-${{ steps.whatrelease.outputs.release }}.tar.gz
|
|
||||||
tag: ${{ steps.whatrelease.outputs.release }}
|
|
||||||
overwrite: true
|
|
||||||
139
.github/workflows/translation-ai-check.yml
vendored
|
|
@ -1,139 +0,0 @@
|
||||||
name: AI Translation Check
|
|
||||||
|
|
||||||
on:
|
|
||||||
# pull_request_target:
|
|
||||||
# types:
|
|
||||||
# - opened
|
|
||||||
issue_comment:
|
|
||||||
types:
|
|
||||||
- created
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
issues: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
review:
|
|
||||||
name: Review Translation
|
|
||||||
if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'issue_comment' && github.event.action == 'created' && github.event.issue.pull_request != null && github.event.comment.user.login == 'vaxerski' && github.event.comment.body == 'ai, please recheck' ) }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
OPENAI_MODEL: gpt-5-mini
|
|
||||||
SYSTEM_PROMPT: |
|
|
||||||
You are a programmer and a translator. Your job is to review the attached patch for adding translation to a piece of software and make sure the submitted translation is not malicious, and that it makes sense. If the translation is not malicious, and doesn't contain obvious grammatical mistakes, say "Translation check OK". Otherwise, say "Translation check not ok" and list bad entries.
|
|
||||||
Examples of bad translations include obvious trolling (slurs, etc) or nonsense sentences. Meaningful improvements may be suggested, but if there are only minor improvements, just reply with "Translation check OK". Do not provide anything but the result and (if applicable) the bad entries or improvements.
|
|
||||||
|
|
||||||
AI_PROMPT: Translation patch below.
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout source code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- uses: dorny/paths-filter@v3
|
|
||||||
id: changes
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
i18n:
|
|
||||||
- 'src/i18n/**'
|
|
||||||
|
|
||||||
- name: Stop if i18n not changed
|
|
||||||
if: steps.changes.outputs.i18n != 'true'
|
|
||||||
run: echo "No i18n changes in this PR; skipping." && exit 0
|
|
||||||
|
|
||||||
- name: Determine PR number
|
|
||||||
id: pr
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
|
|
||||||
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Download combined PR diff
|
|
||||||
id: get_diff
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
|
||||||
run: |
|
|
||||||
# Get the combined diff for the entire PR
|
|
||||||
curl -sSL \
|
|
||||||
-H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
-H "Accept: application/vnd.github.v3.diff" \
|
|
||||||
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" \
|
|
||||||
-o pr.diff
|
|
||||||
|
|
||||||
# Compute character length
|
|
||||||
LEN=$(wc -c < pr.diff | tr -d ' ')
|
|
||||||
echo "len=$LEN" >> "$GITHUB_OUTPUT"
|
|
||||||
if [ "$LEN" -gt 25000 ]; then
|
|
||||||
echo "too_long=true" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "too_long=false" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "got diff:"
|
|
||||||
cat pr.diff
|
|
||||||
|
|
||||||
- name: Comment when diff length exceeded
|
|
||||||
if: steps.get_diff.outputs.too_long == 'true'
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
|
||||||
run: |
|
|
||||||
jq -n --arg body "Diff length exceeded, can't query API" '{body: ("AI translation check result:\n\n" + $body)}' > body.json
|
|
||||||
curl -sS -X POST \
|
|
||||||
-H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \
|
|
||||||
--data @body.json
|
|
||||||
|
|
||||||
- name: Query OpenAI and post review
|
|
||||||
if: steps.get_diff.outputs.too_long == 'false'
|
|
||||||
env:
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
OPENAI_MODEL: ${{ env.OPENAI_MODEL }}
|
|
||||||
SYSTEM_PROMPT: ${{ env.SYSTEM_PROMPT }}
|
|
||||||
AI_PROMPT: ${{ env.AI_PROMPT }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
|
||||||
run: |
|
|
||||||
# Prepare OpenAI chat request payload (embed diff safely)
|
|
||||||
jq -n \
|
|
||||||
--arg model "$OPENAI_MODEL" \
|
|
||||||
--arg sys "$SYSTEM_PROMPT" \
|
|
||||||
--arg prompt "$AI_PROMPT" \
|
|
||||||
--rawfile diff pr.diff \
|
|
||||||
'{model:$model,
|
|
||||||
messages:[
|
|
||||||
{role:"system", content:$sys},
|
|
||||||
{role:"user", content: ($prompt + "\n\n```diff\n" + $diff + "\n```")}
|
|
||||||
]
|
|
||||||
}' > payload.json
|
|
||||||
|
|
||||||
# Call OpenAI
|
|
||||||
curl -sS https://api.openai.com/v1/chat/completions \
|
|
||||||
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d @payload.json > response.json
|
|
||||||
|
|
||||||
# Extract response text
|
|
||||||
COMMENT=$(jq -r '.choices[0].message.content // empty' response.json)
|
|
||||||
if [ -z "$COMMENT" ]; then
|
|
||||||
COMMENT="AI did not return a response."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If failed, add a note
|
|
||||||
ADDITIONAL_NOTE=""
|
|
||||||
if [[ "$COMMENT" == *"not ok"* ]]; then
|
|
||||||
ADDITIONAL_NOTE=$(echo -ne "\n\nPlease note this check is a guideline, not a hard requirement. It is here to help you translate. If you disagree with some points, just state that. Any typos should be fixed.")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Post the review as a PR comment
|
|
||||||
jq -n --arg body "$COMMENT" --arg note "$ADDITIONAL_NOTE" '{body: ("AI translation check result:\n\n" + $body + $note)}' > body.json
|
|
||||||
echo "CURLing https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments"
|
|
||||||
curl -sS -X POST \
|
|
||||||
-H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \
|
|
||||||
--data @body.json
|
|
||||||
34
.gitignore
vendored
|
|
@ -7,43 +7,15 @@ cmake_install.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
CPackConfig.cmake
|
|
||||||
CPackSourceConfig.cmake
|
|
||||||
hyprland.pc
|
|
||||||
_deps
|
_deps
|
||||||
|
|
||||||
build/
|
build/
|
||||||
result*
|
result
|
||||||
/.pre-commit-config.yaml
|
|
||||||
/.vscode/
|
/.vscode/
|
||||||
/.idea/
|
|
||||||
.envrc
|
|
||||||
.cache
|
|
||||||
.direnv
|
|
||||||
/.cmake/
|
|
||||||
/.worktree/
|
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
protocols/*.c*
|
*-protocol.c
|
||||||
protocols/*.h*
|
*-protocol.h
|
||||||
.ccls-cache
|
.ccls-cache
|
||||||
*.so
|
|
||||||
src/render/shaders/*.inc
|
|
||||||
src/render/shaders/Shaders.hpp
|
|
||||||
|
|
||||||
hyprctl/hyprctl
|
hyprctl/hyprctl
|
||||||
hyprctl/hw-protocols/*.c*
|
|
||||||
hyprctl/hw-protocols/*.h*
|
|
||||||
|
|
||||||
gmon.out
|
|
||||||
*.out
|
|
||||||
*.tar.gz
|
|
||||||
|
|
||||||
PKGBUILD
|
|
||||||
|
|
||||||
src/version.h
|
|
||||||
hyprpm/Makefile
|
|
||||||
hyprctl/Makefile
|
|
||||||
|
|
||||||
**/.#*.*
|
|
||||||
**/#*.*#
|
|
||||||
|
|
|
||||||
9
.gitmodules
vendored
|
|
@ -1,9 +0,0 @@
|
||||||
[submodule "subprojects/hyprland-protocols"]
|
|
||||||
path = subprojects/hyprland-protocols
|
|
||||||
url = https://github.com/hyprwm/hyprland-protocols
|
|
||||||
[submodule "subprojects/udis86"]
|
|
||||||
path = subprojects/udis86
|
|
||||||
url = https://github.com/canihavesomecoffee/udis86
|
|
||||||
[submodule "subprojects/tracy"]
|
|
||||||
path = subprojects/tracy
|
|
||||||
url = https://github.com/wolfpld/tracy
|
|
||||||
708
CMakeLists.txt
|
|
@ -1,666 +1,94 @@
|
||||||
cmake_minimum_required(VERSION 3.30)
|
cmake_minimum_required(VERSION 3.4)
|
||||||
|
project(Hyprland
|
||||||
# Get version
|
DESCRIPTION "A Modern C++ Wayland Compositor"
|
||||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
)
|
||||||
string(STRIP ${VER_RAW} VER)
|
|
||||||
|
|
||||||
project(
|
|
||||||
Hyprland
|
|
||||||
DESCRIPTION "A Modern C++ Wayland Compositor"
|
|
||||||
VERSION ${VER})
|
|
||||||
|
|
||||||
include(CTest)
|
|
||||||
include(CheckIncludeFile)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
|
|
||||||
set(HYPRLAND_VERSION ${VER})
|
|
||||||
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
|
||||||
set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
|
|
||||||
set(BINDIR ${CMAKE_INSTALL_BINDIR})
|
|
||||||
|
|
||||||
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
||||||
|
|
||||||
message(STATUS "Gathering git info")
|
message(STATUS "Configuring Hyprland!")
|
||||||
|
|
||||||
# Make shader files includable
|
# Get git info
|
||||||
execute_process(COMMAND ./scripts/generateShaderIncludes.sh
|
# hash and branch
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
execute_process(
|
||||||
RESULT_VARIABLE HYPR_SHADER_GEN_RESULT)
|
COMMAND git rev-parse --abbrev-ref HEAD
|
||||||
if(NOT HYPR_SHADER_GEN_RESULT EQUAL 0)
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
message(
|
OUTPUT_VARIABLE GIT_BRANCH
|
||||||
FATAL_ERROR
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
"Failed to generate shader includes (scripts/generateShaderIncludes.sh), exit code: ${HYPR_SHADER_GEN_RESULT}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
execute_process(
|
||||||
|
COMMAND git rev-parse HEAD
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not
|
execute_process(
|
||||||
# provide a .pc file and won't be detected this way
|
COMMAND bash -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
|
||||||
pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2)
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
# Find non-pkgconfig udis86, otherwise fallback to subproject
|
execute_process(
|
||||||
if(NOT udis_dep_FOUND)
|
COMMAND bash -c "git diff-index --quiet HEAD -- || echo \"dirty\""
|
||||||
find_library(udis_nopc udis86)
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
if(NOT("${udis_nopc}" MATCHES "udis_nopc-NOTFOUND"))
|
OUTPUT_VARIABLE GIT_DIRTY
|
||||||
message(STATUS "Found udis86 at ${udis_nopc}")
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
else()
|
#
|
||||||
add_subdirectory("subprojects/udis86")
|
#
|
||||||
include_directories("subprojects/udis86")
|
|
||||||
message(STATUS "udis86 dependency not found, falling back to subproject")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_library(librt rt)
|
|
||||||
if("${librt}" MATCHES "librt-NOTFOUND")
|
|
||||||
unset(LIBRT)
|
|
||||||
else()
|
|
||||||
set(LIBRT rt)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE)
|
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
|
||||||
if(BUILDTYPE_LOWER STREQUAL "release")
|
|
||||||
# Pass.
|
|
||||||
elseif(BUILDTYPE_LOWER STREQUAL "debug")
|
|
||||||
# Pass.
|
|
||||||
elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo")
|
|
||||||
set(BUILDTYPE_LOWER "debugoptimized")
|
|
||||||
elseif(BUILDTYPE_LOWER STREQUAL "minsizerel")
|
|
||||||
set(BUILDTYPE_LOWER "minsize")
|
|
||||||
elseif(BUILDTYPE_LOWER STREQUAL "none")
|
|
||||||
set(BUILDTYPE_LOWER "plain")
|
|
||||||
else()
|
|
||||||
set(BUILDTYPE_LOWER "release")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(BUILDTYPE_LOWER "release")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
|
||||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
|
||||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
|
||||||
message(
|
|
||||||
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
|
||||||
message(STATUS "Configuring Hyprland in Debug with CMake")
|
|
||||||
add_compile_definitions(HYPRLAND_DEBUG)
|
|
||||||
set(BUILD_TESTING ON)
|
|
||||||
else()
|
|
||||||
add_compile_options(-O3)
|
|
||||||
message(STATUS "Configuring Hyprland in Release with CMake")
|
|
||||||
set(BUILD_TESTING OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}")
|
|
||||||
|
|
||||||
include_directories(. "src/" "protocols/")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 26)
|
|
||||||
set(CXX_STANDARD_REQUIRED ON)
|
|
||||||
add_compile_options(
|
|
||||||
-Wall
|
|
||||||
-Wextra
|
|
||||||
-Wpedantic
|
|
||||||
-Wno-unused-parameter
|
|
||||||
-Wno-unused-value
|
|
||||||
-Wno-missing-field-initializers
|
|
||||||
-Wno-gnu-zero-variadic-macro-arguments
|
|
||||||
-Wno-narrowing
|
|
||||||
-Wno-pointer-arith
|
|
||||||
-Wno-clobbered
|
|
||||||
-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)
|
|
||||||
|
|
||||||
# disable lto as it may break plugins
|
|
||||||
add_compile_options(-fno-lto)
|
|
||||||
|
|
||||||
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
|
||||||
|
|
||||||
message(STATUS "Checking deps...")
|
|
||||||
|
|
||||||
|
include_directories(.)
|
||||||
|
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
|
||||||
|
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
set(GLES_VERSION "GLES3")
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon wlroots libinput xcb)
|
||||||
|
|
||||||
set(AQUAMARINE_MINIMUM_VERSION 0.9.3)
|
|
||||||
set(HYPRLANG_MINIMUM_VERSION 0.6.7)
|
|
||||||
set(HYPRCURSOR_MINIMUM_VERSION 0.1.7)
|
|
||||||
set(HYPRUTILS_MINIMUM_VERSION 0.11.0)
|
|
||||||
set(HYPRGRAPHICS_MINIMUM_VERSION 0.1.6)
|
|
||||||
|
|
||||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=${AQUAMARINE_MINIMUM_VERSION})
|
|
||||||
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=${HYPRLANG_MINIMUM_VERSION})
|
|
||||||
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=${HYPRCURSOR_MINIMUM_VERSION})
|
|
||||||
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=${HYPRUTILS_MINIMUM_VERSION})
|
|
||||||
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=${HYPRGRAPHICS_MINIMUM_VERSION})
|
|
||||||
|
|
||||||
string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION})
|
|
||||||
list(GET AQ_VERSION_LIST 0 AQ_VERSION_MAJOR)
|
|
||||||
list(GET AQ_VERSION_LIST 1 AQ_VERSION_MINOR)
|
|
||||||
list(GET AQ_VERSION_LIST 2 AQ_VERSION_PATCH)
|
|
||||||
|
|
||||||
set(AQUAMARINE_VERSION "${aquamarine_dep_VERSION}")
|
|
||||||
set(AQUAMARINE_VERSION_MAJOR "${AQ_VERSION_MAJOR}")
|
|
||||||
set(AQUAMARINE_VERSION_MINOR "${AQ_VERSION_MINOR}")
|
|
||||||
set(AQUAMARINE_VERSION_PATCH "${AQ_VERSION_PATCH}")
|
|
||||||
set(HYPRLANG_VERSION "${hyprlang_dep_VERSION}")
|
|
||||||
set(HYPRUTILS_VERSION "${hyprutils_dep_VERSION}")
|
|
||||||
set(HYPRCURSOR_VERSION "${hyprcursor_dep_VERSION}")
|
|
||||||
set(HYPRGRAPHICS_VERSION "${hyprgraphics_dep_VERSION}")
|
|
||||||
|
|
||||||
|
|
||||||
find_package(Git QUIET)
|
|
||||||
|
|
||||||
# Populate variables with env vars if present
|
|
||||||
set(GIT_COMMIT_HASH "$ENV{GIT_COMMIT_HASH}")
|
|
||||||
if(NOT GIT_COMMIT_HASH)
|
|
||||||
set(GIT_COMMIT_HASH "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_BRANCH "$ENV{GIT_BRANCH}")
|
|
||||||
if(NOT GIT_BRANCH)
|
|
||||||
set(GIT_BRANCH "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_COMMIT_MESSAGE "$ENV{GIT_COMMIT_MESSAGE}")
|
|
||||||
if(NOT GIT_COMMIT_MESSAGE)
|
|
||||||
set(GIT_COMMIT_MESSAGE "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_COMMIT_DATE "$ENV{GIT_COMMIT_DATE}")
|
|
||||||
if(NOT GIT_COMMIT_DATE)
|
|
||||||
set(GIT_COMMIT_DATE "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_DIRTY "$ENV{GIT_DIRTY}")
|
|
||||||
if(NOT GIT_DIRTY)
|
|
||||||
set(GIT_DIRTY "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_TAG "$ENV{GIT_TAG}")
|
|
||||||
if(NOT GIT_TAG)
|
|
||||||
set(GIT_TAG "unknown")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GIT_COMMITS "$ENV{GIT_COMMITS}")
|
|
||||||
if(NOT GIT_COMMITS)
|
|
||||||
set(GIT_COMMITS "0")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(Git_FOUND)
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${GIT_EXECUTABLE} rev-parse --show-toplevel
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
OUTPUT_VARIABLE GIT_TOPLEVEL
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
ERROR_QUIET
|
|
||||||
RESULT_VARIABLE GIT_TOPLEVEL_RESULT
|
|
||||||
)
|
|
||||||
|
|
||||||
if(GIT_TOPLEVEL_RESULT EQUAL 0)
|
|
||||||
message(STATUS "Detected git repository root: ${GIT_TOPLEVEL}")
|
|
||||||
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} branch --show-current
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND sh "-c" "${GIT_EXECUTABLE} show -s --format=%s --no-show-signature | sed \"s/\\\"/\'/g\""
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --format=%cd --date=local --no-show-signature
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
RESULT_VARIABLE GIT_DIRTY_RESULT)
|
|
||||||
if(NOT GIT_DIRTY_RESULT EQUAL 0)
|
|
||||||
set(GIT_DIRTY "dirty")
|
|
||||||
else()
|
|
||||||
set(GIT_DIRTY "clean")
|
|
||||||
endif()
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD
|
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
|
||||||
OUTPUT_VARIABLE GIT_COMMITS OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
else()
|
|
||||||
message(WARNING "No Git repository detected in ${CMAKE_SOURCE_DIR}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
configure_file(
|
|
||||||
${CMAKE_SOURCE_DIR}/src/version.h.in
|
|
||||||
${CMAKE_SOURCE_DIR}/src/version.h
|
|
||||||
@ONLY
|
|
||||||
)
|
|
||||||
|
|
||||||
set_source_files_properties(${CMAKE_SOURCE_DIR}/src/version.h PROPERTIES GENERATED TRUE)
|
|
||||||
|
|
||||||
set(XKBCOMMON_MINIMUM_VERSION 1.11.0)
|
|
||||||
set(WAYLAND_SERVER_MINIMUM_VERSION 1.22.90)
|
|
||||||
set(WAYLAND_SERVER_PROTOCOLS_MINIMUM_VERSION 1.45)
|
|
||||||
set(LIBINPUT_MINIMUM_VERSION 1.28)
|
|
||||||
|
|
||||||
pkg_check_modules(
|
|
||||||
deps
|
|
||||||
REQUIRED
|
|
||||||
IMPORTED_TARGET GLOBAL
|
|
||||||
xkbcommon>=${XKBCOMMON_MINIMUM_VERSION}
|
|
||||||
uuid
|
|
||||||
wayland-server>=${WAYLAND_SERVER_MINIMUM_VERSION}
|
|
||||||
wayland-protocols>=${WAYLAND_SERVER_PROTOCOLS_MINIMUM_VERSION}
|
|
||||||
cairo
|
|
||||||
pango
|
|
||||||
pangocairo
|
|
||||||
pixman-1
|
|
||||||
xcursor
|
|
||||||
libdrm
|
|
||||||
libinput>=${LIBINPUT_MINIMUM_VERSION}
|
|
||||||
gbm
|
|
||||||
gio-2.0
|
|
||||||
re2
|
|
||||||
muparser)
|
|
||||||
|
|
||||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||||
get_filename_component(FULL_MAIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ABSOLUTE)
|
|
||||||
list(REMOVE_ITEM SRCFILES "${FULL_MAIN_PATH}")
|
|
||||||
|
|
||||||
set(TRACY_CPP_FILES "")
|
add_executable(Hyprland ${SRCFILES})
|
||||||
if(USE_TRACY)
|
|
||||||
set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp")
|
|
||||||
message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(hyprland_lib STATIC ${SRCFILES})
|
IF(LEGACY_RENDERER MATCHES true)
|
||||||
add_executable(Hyprland src/main.cpp ${TRACY_CPP_FILES})
|
message(STATUS "Using the legacy GLES2 renderer!")
|
||||||
target_link_libraries(Hyprland hyprland_lib)
|
add_definitions( -DLEGACY_RENDERER )
|
||||||
|
ENDIF(LEGACY_RENDERER MATCHES true)
|
||||||
|
|
||||||
target_include_directories(hyprland_lib PUBLIC ${deps_INCLUDE_DIRS})
|
IF(NO_XWAYLAND MATCHES true)
|
||||||
target_include_directories(Hyprland PUBLIC ${deps_INCLUDE_DIRS})
|
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
|
||||||
|
add_definitions( -DNO_XWAYLAND )
|
||||||
|
ENDIF(NO_XWAYLAND MATCHES true)
|
||||||
|
|
||||||
set(USE_GPROF OFF)
|
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
message(STATUS "Configuring Hyprland in Debug with CMake!")
|
||||||
|
ELSE()
|
||||||
|
# add_compile_options(-O3) # may crash for some
|
||||||
|
message(STATUS "Configuring Hyprland in Release with CMake!")
|
||||||
|
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
|
||||||
message(STATUS "Setting debug flags")
|
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
|
||||||
|
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"")
|
||||||
|
target_compile_definitions(Hyprland PRIVATE "-DGIT_DIRTY=\"${GIT_DIRTY}\"")
|
||||||
|
|
||||||
if(WITH_ASAN)
|
target_link_libraries(Hyprland rt)
|
||||||
message(STATUS "Enabling ASan")
|
|
||||||
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC asan)
|
|
||||||
target_compile_options(hyprland_lib PUBLIC -fsanitize=address)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(USE_TRACY)
|
|
||||||
message(STATUS "Tracy is turned on")
|
|
||||||
|
|
||||||
option(TRACY_ENABLE "" ON)
|
|
||||||
option(TRACY_ON_DEMAND "" ON)
|
|
||||||
add_subdirectory(subprojects/tracy)
|
|
||||||
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC Tracy::TracyClient)
|
|
||||||
|
|
||||||
if(USE_TRACY_GPU)
|
|
||||||
message(STATUS "Tracy GPU Profiling is turned on")
|
|
||||||
add_compile_definitions(USE_TRACY_GPU)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_compile_options(-fno-pie -fno-builtin)
|
|
||||||
add_link_options(-no-pie -fno-builtin)
|
|
||||||
if(USE_GPROF)
|
|
||||||
add_compile_options(-pg)
|
|
||||||
add_link_options(-pg)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILT_WITH_NIX)
|
|
||||||
add_compile_definitions(BUILT_WITH_NIX)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_include_file("execinfo.h" EXECINFOH)
|
|
||||||
if(EXECINFOH)
|
|
||||||
message(STATUS "Configuration supports execinfo")
|
|
||||||
add_compile_definitions(HAS_EXECINFO)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CheckLibraryExists)
|
|
||||||
check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO)
|
|
||||||
if(HAVE_LIBEXECINFO)
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC execinfo)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_include_file("sys/timerfd.h" HAS_TIMERFD)
|
|
||||||
pkg_check_modules(epoll IMPORTED_TARGET epoll-shim)
|
|
||||||
if(NOT HAS_TIMERFD AND epoll_FOUND)
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC PkgConfig::epoll)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_include_file("sys/inotify.h" HAS_INOTIFY)
|
|
||||||
pkg_check_modules(inotify IMPORTED_TARGET libinotify)
|
|
||||||
if(NOT HAS_INOTIFY AND inotify_FOUND)
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC PkgConfig::inotify)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NO_XWAYLAND)
|
|
||||||
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
|
|
||||||
add_compile_definitions(NO_XWAYLAND)
|
|
||||||
else()
|
|
||||||
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
|
|
||||||
set(XWAYLAND_DEPENDENCIES
|
|
||||||
xcb
|
|
||||||
xcb-render
|
|
||||||
xcb-xfixes
|
|
||||||
xcb-icccm
|
|
||||||
xcb-composite
|
|
||||||
xcb-res
|
|
||||||
xcb-errors)
|
|
||||||
|
|
||||||
pkg_check_modules(
|
|
||||||
xdeps
|
|
||||||
REQUIRED
|
|
||||||
IMPORTED_TARGET
|
|
||||||
${XWAYLAND_DEPENDENCIES})
|
|
||||||
|
|
||||||
string(JOIN ", " PKGCONFIG_XWAYLAND_DEPENDENCIES ${XWAYLAND_DEPENDENCIES})
|
|
||||||
string(PREPEND PKGCONFIG_XWAYLAND_DEPENDENCIES ", ")
|
|
||||||
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC PkgConfig::xdeps)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
configure_file(hyprland.pc.in hyprland.pc @ONLY)
|
|
||||||
|
|
||||||
if(NO_SYSTEMD)
|
|
||||||
message(STATUS "SYSTEMD support is disabled...")
|
|
||||||
else()
|
|
||||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...")
|
|
||||||
add_compile_definitions(USES_SYSTEMD)
|
|
||||||
|
|
||||||
# session file -uwsm
|
|
||||||
if(NO_UWSM)
|
|
||||||
message(STATUS "UWSM support is disabled...")
|
|
||||||
else()
|
|
||||||
message(STATUS "UWSM support is enabled (NO_UWSM not defined)...")
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
if(CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
target_link_libraries(Hyprland PkgConfig::deps)
|
||||||
message(STATUS "Not using precompiled headers")
|
|
||||||
else()
|
|
||||||
message(STATUS "Setting precompiled headers")
|
|
||||||
target_precompile_headers(hyprland_lib PRIVATE
|
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Setting link libraries")
|
target_link_libraries(Hyprland
|
||||||
|
wlroots
|
||||||
target_link_libraries(
|
pixman-1
|
||||||
hyprland_lib
|
OpenGL
|
||||||
PUBLIC
|
GLESv2
|
||||||
PkgConfig::aquamarine_dep
|
pthread
|
||||||
PkgConfig::hyprlang_dep
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
PkgConfig::hyprutils_dep
|
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
|
||||||
PkgConfig::hyprcursor_dep
|
|
||||||
PkgConfig::hyprgraphics_dep
|
|
||||||
PkgConfig::deps
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
Hyprland
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin")
|
||||||
${LIBRT}
|
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
|
||||||
hyprland_lib)
|
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
|
||||||
if(udis_dep_FOUND)
|
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
target_link_libraries(hyprland_lib PUBLIC PkgConfig::udis_dep)
|
|
||||||
elseif(NOT("${udis_nopc}" MATCHES "udis_nopc-NOTFOUND"))
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC ${udis_nopc})
|
|
||||||
else()
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC libudis86)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# used by `make installheaders`, to ensure the headers are generated
|
|
||||||
add_custom_target(generate-protocol-headers)
|
|
||||||
set(PROTOCOL_SOURCES "")
|
|
||||||
|
|
||||||
function(protocolnew protoPath protoName external)
|
|
||||||
if(external)
|
|
||||||
set(path ${protoPath})
|
|
||||||
else()
|
|
||||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
|
||||||
endif()
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
|
|
||||||
COMMAND hyprwayland-scanner ${path}/${protoName}.xml
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
||||||
target_sources(hyprland_lib PRIVATE protocols/${protoName}.cpp
|
|
||||||
protocols/${protoName}.hpp)
|
|
||||||
target_sources(generate-protocol-headers
|
|
||||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp)
|
|
||||||
|
|
||||||
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp")
|
|
||||||
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
|
|
||||||
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp")
|
|
||||||
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
function(protocolWayland)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
|
||||||
COMMAND
|
|
||||||
hyprwayland-scanner --wayland-enums
|
|
||||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
|
||||||
target_sources(hyprland_lib PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
|
||||||
target_sources(generate-protocol-headers
|
|
||||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
|
||||||
|
|
||||||
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/wayland.hpp")
|
|
||||||
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
|
|
||||||
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/wayland.cpp")
|
|
||||||
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC OpenGL::EGL OpenGL::GL Threads::Threads)
|
|
||||||
|
|
||||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.4)
|
|
||||||
if(hyprland_protocols_dep_FOUND)
|
|
||||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
|
||||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
|
||||||
else()
|
|
||||||
set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols")
|
|
||||||
message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
|
|
||||||
true)
|
|
||||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1"
|
|
||||||
true)
|
|
||||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "wlr-output-power-management-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "virtual-keyboard-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "wlr-virtual-pointer-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "input-method-unstable-v2" true)
|
|
||||||
protocolnew("protocols" "wlr-output-management-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "kde-server-decoration" true)
|
|
||||||
protocolnew("protocols" "wlr-data-control-unstable-v1" true)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
|
|
||||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
|
||||||
protocolnew("protocols" "xx-color-management-v4" true)
|
|
||||||
protocolnew("protocols" "frog-color-management-v1" true)
|
|
||||||
protocolnew("protocols" "wayland-drm" true)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)
|
|
||||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-mapping-v1"
|
|
||||||
true)
|
|
||||||
|
|
||||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
|
||||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
|
||||||
protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false)
|
|
||||||
protocolnew("staging/cursor-shape" "cursor-shape-v1" false)
|
|
||||||
protocolnew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false)
|
|
||||||
protocolnew("unstable/relative-pointer" "relative-pointer-unstable-v1" false)
|
|
||||||
protocolnew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false)
|
|
||||||
protocolnew("staging/alpha-modifier" "alpha-modifier-v1" false)
|
|
||||||
protocolnew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1"
|
|
||||||
false)
|
|
||||||
protocolnew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false)
|
|
||||||
protocolnew("unstable/keyboard-shortcuts-inhibit"
|
|
||||||
"keyboard-shortcuts-inhibit-unstable-v1" false)
|
|
||||||
protocolnew("unstable/text-input" "text-input-unstable-v3" false)
|
|
||||||
protocolnew("unstable/pointer-constraints" "pointer-constraints-unstable-v1"
|
|
||||||
false)
|
|
||||||
protocolnew("staging/xdg-activation" "xdg-activation-v1" false)
|
|
||||||
protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
|
|
||||||
protocolnew("staging/ext-session-lock" "ext-session-lock-v1" false)
|
|
||||||
protocolnew("stable/tablet" "tablet-v2" false)
|
|
||||||
protocolnew("stable/presentation-time" "presentation-time" false)
|
|
||||||
protocolnew("stable/xdg-shell" "xdg-shell" false)
|
|
||||||
protocolnew("unstable/primary-selection" "primary-selection-unstable-v1" false)
|
|
||||||
protocolnew("staging/xwayland-shell" "xwayland-shell-v1" false)
|
|
||||||
protocolnew("stable/viewporter" "viewporter" false)
|
|
||||||
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
|
||||||
protocolnew("staging/drm-lease" "drm-lease-v1" false)
|
|
||||||
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
|
||||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
|
||||||
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
|
||||||
protocolnew("staging/security-context" "security-context-v1" false)
|
|
||||||
protocolnew("staging/content-type" "content-type-v1" false)
|
|
||||||
protocolnew("staging/color-management" "color-management-v1" false)
|
|
||||||
protocolnew("staging/xdg-toplevel-tag" "xdg-toplevel-tag-v1" false)
|
|
||||||
protocolnew("staging/xdg-system-bell" "xdg-system-bell-v1" false)
|
|
||||||
protocolnew("staging/ext-workspace" "ext-workspace-v1" false)
|
|
||||||
protocolnew("staging/ext-data-control" "ext-data-control-v1" false)
|
|
||||||
protocolnew("staging/pointer-warp" "pointer-warp-v1" false)
|
|
||||||
protocolnew("staging/fifo" "fifo-v1" false)
|
|
||||||
protocolnew("staging/commit-timing" "commit-timing-v1" false)
|
|
||||||
|
|
||||||
protocolwayland()
|
|
||||||
|
|
||||||
# tools
|
|
||||||
add_subdirectory(hyprctl)
|
|
||||||
add_subdirectory(start)
|
|
||||||
|
|
||||||
if(NO_HYPRPM)
|
|
||||||
message(STATUS "hyprpm is disabled")
|
|
||||||
else()
|
|
||||||
add_subdirectory(hyprpm)
|
|
||||||
message(STATUS "hyprpm is enabled (NO_HYPRPM not defined)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# binary and symlink
|
|
||||||
install(TARGETS Hyprland)
|
|
||||||
|
|
||||||
install(
|
|
||||||
CODE "execute_process( \
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
|
||||||
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
|
|
||||||
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
|
|
||||||
)")
|
|
||||||
# session file
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
|
||||||
|
|
||||||
# allow Hyprland to find assets
|
|
||||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
|
||||||
|
|
||||||
# installable assets
|
|
||||||
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
|
||||||
install(FILES ${INSTALLABLE_ASSETS}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
|
||||||
|
|
||||||
# default config
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
|
||||||
|
|
||||||
# portal config
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal)
|
|
||||||
|
|
||||||
# man pages
|
|
||||||
file(GLOB_RECURSE MANPAGES "docs/*.1")
|
|
||||||
install(FILES ${MANPAGES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
|
||||||
|
|
||||||
# pkgconfig entry
|
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
|
|
||||||
|
|
||||||
# protocol headers
|
|
||||||
set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols")
|
|
||||||
install(
|
|
||||||
DIRECTORY ${HEADERS_PROTO}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
|
||||||
FILES_MATCHING
|
|
||||||
PATTERN "*.h*")
|
|
||||||
|
|
||||||
# hyprland headers
|
|
||||||
set(HEADERS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
|
||||||
install(
|
|
||||||
DIRECTORY ${HEADERS_SRC}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
|
||||||
FILES_MATCHING
|
|
||||||
PATTERN "*.h"
|
|
||||||
PATTERN "*.hpp"
|
|
||||||
PATTERN "*.inc")
|
|
||||||
|
|
||||||
if(BUILD_TESTING OR WITH_TESTS)
|
|
||||||
message(STATUS "Building tests")
|
|
||||||
|
|
||||||
# hyprtester
|
|
||||||
add_subdirectory(hyprtester)
|
|
||||||
|
|
||||||
# GTest
|
|
||||||
find_package(GTest CONFIG REQUIRED)
|
|
||||||
include(GoogleTest)
|
|
||||||
file(GLOB_RECURSE TESTFILES "tests/*.cpp")
|
|
||||||
add_executable(hyprland_gtests ${TESTFILES})
|
|
||||||
target_compile_options(hyprland_gtests PRIVATE --coverage)
|
|
||||||
target_link_options(hyprland_gtests PRIVATE --coverage)
|
|
||||||
target_include_directories(
|
|
||||||
hyprland_gtests
|
|
||||||
PUBLIC "./include"
|
|
||||||
PRIVATE "./src" "./src/include" "./protocols" "${CMAKE_BINARY_DIR}")
|
|
||||||
|
|
||||||
target_link_libraries(hyprland_gtests hyprland_lib GTest::gtest_main)
|
|
||||||
|
|
||||||
gtest_discover_tests(hyprland_gtests)
|
|
||||||
|
|
||||||
# Enable coverage in main hyprland lib
|
|
||||||
target_compile_options(hyprland_lib PRIVATE --coverage)
|
|
||||||
target_link_options(hyprland_lib PRIVATE --coverage)
|
|
||||||
target_link_libraries(hyprland_lib PUBLIC gcov)
|
|
||||||
|
|
||||||
# Enable coverage in hyprland exe
|
|
||||||
target_compile_options(Hyprland PRIVATE --coverage)
|
|
||||||
target_link_options(Hyprland PRIVATE --coverage)
|
|
||||||
target_link_libraries(Hyprland gcov)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
|
||||||
message(STATUS "Testing is enabled")
|
|
||||||
|
|
||||||
enable_testing()
|
|
||||||
add_custom_target(tests)
|
|
||||||
|
|
||||||
add_dependencies(tests hyprland_gtests)
|
|
||||||
|
|
||||||
else()
|
|
||||||
message(STATUS "Testing is disabled")
|
|
||||||
endif()
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
## Goal
|
|
||||||
|
|
||||||
Our goal is to provide a space where it is safe for everyone to contribute to,
|
|
||||||
and get support for, open-source software in a respectful and cooperative
|
|
||||||
manner.
|
|
||||||
|
|
||||||
We value all contributions and want to make this organization and its
|
|
||||||
surrounding community a place for everyone.
|
|
||||||
|
|
||||||
As members, contributors, and everyone else who may participate in the
|
|
||||||
development, we strive to keep the entire experience civil.
|
|
||||||
|
|
||||||
## Standards
|
|
||||||
|
|
||||||
Our community standards exist in order to make sure everyone feels comfortable
|
|
||||||
contributing to the project(s) together.
|
|
||||||
|
|
||||||
Our standards are:
|
|
||||||
- Do not harass, attack, or in any other way discriminate against anyone, including
|
|
||||||
for their protected traits, including, but not limited to, sex, religion, race,
|
|
||||||
appearance, gender, identity, nationality, sexuality, etc.
|
|
||||||
- Do not go off-topic, do not post spam.
|
|
||||||
- Treat everyone with respect.
|
|
||||||
|
|
||||||
Examples of breaking each rule respectively include:
|
|
||||||
- Harassment, bullying or inappropriate jokes about another person.
|
|
||||||
- Posting distasteful imagery, trolling, or posting things unrelated to the topic at hand.
|
|
||||||
- Treating someone as worse because of their lack of understanding of an issue.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Enforcement of this CoC is done by the members of the hyprwm organization.
|
|
||||||
|
|
||||||
We, as the organization, will strive our best to keep this community civil and
|
|
||||||
following the standards outlined above.
|
|
||||||
|
|
||||||
### Reporting incidents
|
|
||||||
|
|
||||||
If you believe an incident of breaking our standards has occurred, but nobody has
|
|
||||||
taken appropriate action, you can privately contact the people responsible for dealing
|
|
||||||
with such incidents in multiple ways:
|
|
||||||
|
|
||||||
***E-Mail***
|
|
||||||
- `vaxry[at]vaxry.net`
|
|
||||||
- `mihai[at]fufexan.net`
|
|
||||||
|
|
||||||
***Discord***
|
|
||||||
- `@vaxry`
|
|
||||||
- `@fufexan`
|
|
||||||
|
|
||||||
***Matrix***
|
|
||||||
- `@vaxry:matrix.vaxry.net`
|
|
||||||
- `@fufexan:matrix.org`
|
|
||||||
|
|
||||||
We, as members, guarantee your privacy and will not share those reports with anyone.
|
|
||||||
|
|
||||||
## Enforcement Strategy
|
|
||||||
|
|
||||||
Depending on the severity of the infraction, any action from the list below may be applied.
|
|
||||||
Please keep in mind cases are reviewed on a per-case basis and members are the ultimate
|
|
||||||
deciding factor in the type of punishment.
|
|
||||||
|
|
||||||
If the matter would benefit from an outside opinion, a member might reach for more opinions
|
|
||||||
from people unrelated to the organization, however, the final decision regarding the action
|
|
||||||
to be taken is still up to the member.
|
|
||||||
|
|
||||||
For example, if the matter at hand regards a representative of a marginalized group or minority,
|
|
||||||
the member might ask for a first-hand opinion from another representative of such group.
|
|
||||||
|
|
||||||
### Correction/Edit
|
|
||||||
|
|
||||||
If your message is found to be misleading or poorly worded, a member might
|
|
||||||
edit your message.
|
|
||||||
|
|
||||||
### Warning/Deletion
|
|
||||||
|
|
||||||
If your message is found inappropriate, a member might give you a public or private warning,
|
|
||||||
and/or delete your message.
|
|
||||||
|
|
||||||
### Mute
|
|
||||||
|
|
||||||
If your message is disruptive, or you have been repeatedly violating the standards,
|
|
||||||
a member might mute (or temporarily ban) you.
|
|
||||||
|
|
||||||
### Ban
|
|
||||||
|
|
||||||
If your message is hateful, very disruptive, or other, less serious infractions are repeated
|
|
||||||
ignoring previous punishments, a member might ban you permanently.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This CoC shall apply to all projects ran under the `hyprwm` organization and all _official_ communities
|
|
||||||
outside of GitHub.
|
|
||||||
|
|
||||||
However, it is worth noting that official communities outside of GitHub might have their own,
|
|
||||||
additional sets of rules.
|
|
||||||
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2022-2025, vaxerski
|
Copyright (c) 2022, vaxerski
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
|
||||||
184
Makefile
|
|
@ -1,98 +1,116 @@
|
||||||
PREFIX = /usr/local
|
include config.mk
|
||||||
|
|
||||||
stub:
|
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99
|
||||||
@echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland."
|
|
||||||
|
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
||||||
|
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
|
||||||
|
|
||||||
|
PKGS = wlroots wayland-server xcb xkbcommon libinput
|
||||||
|
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
|
||||||
|
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
|
||||||
|
|
||||||
|
xdg-shell-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
|
||||||
|
xdg-shell-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
|
||||||
|
xdg-shell-protocol.o: xdg-shell-protocol.h
|
||||||
|
|
||||||
|
wlr-layer-shell-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
|
||||||
|
wlr-layer-shell-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
|
||||||
|
wlr-layer-shell-unstable-v1-protocol.o: wlr-layer-shell-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
wlr-screencopy-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/wlr-screencopy-unstable-v1.xml $@
|
||||||
|
|
||||||
|
wlr-screencopy-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/wlr-screencopy-unstable-v1.xml $@
|
||||||
|
|
||||||
|
wlr-screencopy-unstable-v1-protocol.o: wlr-screencopy-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
ext-workspace-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/ext-workspace-unstable-v1.xml $@
|
||||||
|
|
||||||
|
ext-workspace-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/ext-workspace-unstable-v1.xml $@
|
||||||
|
|
||||||
|
ext-workspace-unstable-v1-protocol.o: ext-workspace-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/pointer-constraints-unstable-v1.xml $@
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/pointer-constraints-unstable-v1.xml $@
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
idle-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/idle.xml $@
|
||||||
|
|
||||||
|
idle-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/idle.xml $@
|
||||||
|
|
||||||
|
idle-protocol.o: idle-protocol.h
|
||||||
|
|
||||||
|
legacyrenderer:
|
||||||
|
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
|
||||||
|
cmake --build ./build --config Release --target all -j 10
|
||||||
|
|
||||||
|
legacyrendererdebug:
|
||||||
|
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
|
||||||
|
cmake --build ./build --config Release --target all -j 10
|
||||||
|
|
||||||
release:
|
release:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -H./ -B./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Release --target all -j 10
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DTESTS=true -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
|
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -H./ -B./build -G Ninja
|
||||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
cmake --build ./build --config Debug --target all -j 10
|
||||||
|
|
||||||
nopch:
|
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build
|
|
||||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp
|
rm -f *.o *-protocol.h *-protocol.c
|
||||||
|
rm -f ./hyprctl/hyprctl
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(MAKE) clear
|
make config
|
||||||
$(MAKE) release
|
make release
|
||||||
|
cd ./hyprctl && make all && cd ..
|
||||||
|
|
||||||
install:
|
install:
|
||||||
cmake --install ./build
|
make all
|
||||||
|
mkdir -p ${PREFIX}/share/wayland-sessions
|
||||||
|
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
|
||||||
|
mkdir -p ${PREFIX}/bin
|
||||||
|
cp ./build/Hyprland ${PREFIX}/bin
|
||||||
|
cp ./hyprctl/hyprctl ${PREFIX}/bin
|
||||||
|
mkdir -p ${PREFIX}/share/hyprland
|
||||||
|
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
|
||||||
|
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
||||||
|
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
xargs rm < ./build/install_manifest.txt
|
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||||
|
rm -f ${PREFIX}/bin/Hyprland
|
||||||
|
rm -f ${PREFIX}/bin/hyprctl
|
||||||
|
rm -rf ${PREFIX}/share/hyprland
|
||||||
|
|
||||||
pluginenv:
|
config: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o
|
||||||
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
|
|
||||||
@exit 1
|
|
||||||
|
|
||||||
installheaders:
|
|
||||||
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
|
||||||
|
|
||||||
# remove previous headers from hyprpm's dir
|
|
||||||
rm -fr ${PREFIX}/include/hyprland
|
|
||||||
mkdir -p ${PREFIX}/include/hyprland
|
|
||||||
mkdir -p ${PREFIX}/include/hyprland/protocols
|
|
||||||
mkdir -p ${PREFIX}/share/pkgconfig
|
|
||||||
|
|
||||||
cmake --build ./build --config Release --target generate-protocol-headers
|
|
||||||
|
|
||||||
find src -type f \( -name '*.hpp' -o -name '*.h' -o -name '*.inc' \) -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
|
||||||
cp ./protocols/*.h* ${PREFIX}/include/hyprland/protocols
|
|
||||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
|
||||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
|
||||||
|
|
||||||
chmod -R 755 ${PREFIX}/include/hyprland
|
|
||||||
chmod 755 ${PREFIX}/share/pkgconfig
|
|
||||||
|
|
||||||
man:
|
|
||||||
pandoc ./docs/Hyprland.1.rst \
|
|
||||||
--standalone \
|
|
||||||
--variable=header:"Hyprland User Manual" \
|
|
||||||
--variable=date:"${DATE}" \
|
|
||||||
--variable=section:1 \
|
|
||||||
--from rst \
|
|
||||||
--to man > ./docs/Hyprland.1
|
|
||||||
|
|
||||||
pandoc ./docs/hyprctl.1.rst \
|
|
||||||
--standalone \
|
|
||||||
--variable=header:"hyprctl User Manual" \
|
|
||||||
--variable=date:"${DATE}" \
|
|
||||||
--variable=section:1 \
|
|
||||||
--from rst \
|
|
||||||
--to man > ./docs/hyprctl.1
|
|
||||||
|
|
||||||
asan:
|
|
||||||
@echo -en "!!WARNING!!\nOnly run this in the TTY.\n"
|
|
||||||
@pidof Hyprland > /dev/null && echo -ne "Refusing to run with Hyprland running.\n" || echo ""
|
|
||||||
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
|
||||||
|
|
||||||
rm -rf ./wayland
|
|
||||||
#git reset --hard
|
|
||||||
|
|
||||||
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
|
||||||
@read patchvar; \
|
|
||||||
if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi
|
|
||||||
|
|
||||||
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
|
|
||||||
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..
|
|
||||||
cp ./wayland/build/src/libwayland-server.a .
|
|
||||||
@echo "Wayland done"
|
|
||||||
|
|
||||||
patch -p1 < ./scripts/hyprlandStaticAsan.diff
|
|
||||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build -G Ninja
|
|
||||||
cmake --build ./build --config Debug --target all
|
|
||||||
@echo "Hyprland done"
|
|
||||||
|
|
||||||
ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.conf
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(MAKE) debug
|
|
||||||
./build/hyprtester/hyprtester -c hyprtester/test.conf -b ./build/Hyprland -p hyprtester/plugin/hyprtestplugin.so
|
|
||||||
|
|
|
||||||
107
README.md
|
|
@ -1,22 +1,24 @@
|
||||||
<div align = center>
|
<div align = center>
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/hyprwm/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
![Banner]
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
[![Badge Workflow]][Workflow]
|
![Badge Workflow]
|
||||||
[![Badge License]][License]
|
[![Badge License]][License]
|
||||||
|
![Badge Lines]
|
||||||
![Badge Language]
|
![Badge Language]
|
||||||
[![Badge Pull Requests]][Pull Requests]
|
[![Badge Pull Requests]][Pull Requests]
|
||||||
[![Badge Issues]][Issues]
|
[![Badge Issues]][Issues]
|
||||||
![Badge Hi Mom]<br>
|
![Badge Hi Mom]<br>
|
||||||
|
[![Badge Discord]][Discord]
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
||||||
|
|
||||||
|
For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
||||||
|
|
||||||
It provides the latest Wayland features, is highly customizable, has all the eyecandy, the most powerful plugins,
|
|
||||||
easy IPC, much more QoL stuff than other compositors and more...
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
@ -33,29 +35,34 @@ easy IPC, much more QoL stuff than other compositors and more...
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
# Notice
|
||||||
|
|
||||||
|
This project is still in its early development, expect bugs.
|
||||||
|
|
||||||
|
Once you get it working though, it's pretty stable.<br/>
|
||||||
|
|
||||||
|
|
||||||
|
### Help Wanted
|
||||||
|
|
||||||
|
Hyprland needs testers! <br/>
|
||||||
|
Try it out and report bugs / suggestions!
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
- All of the eyecandy: gradient borders, blur, animations, shadows and much more
|
|
||||||
- A lot of customization
|
|
||||||
- 100% independent, no wlroots, no libweston, no kwin, no mutter.
|
|
||||||
- Custom bezier curves for the best animations
|
|
||||||
- Powerful plugin support
|
|
||||||
- Built-in plugin manager
|
|
||||||
- Tearing support for better gaming performance
|
|
||||||
- Easily expandable and readable codebase
|
- Easily expandable and readable codebase
|
||||||
- Fast and active development
|
|
||||||
- Not afraid to provide bleeding-edge features
|
|
||||||
- Config reloaded instantly upon saving
|
- Config reloaded instantly upon saving
|
||||||
- Fully dynamic workspaces
|
- Bezier-curve window animations
|
||||||
- Two built-in layouts and more available as plugins
|
- Custom bezier curve based animations
|
||||||
- Global keybinds passed to your apps of choice
|
- Workspaces protocol support
|
||||||
- Tiling/pseudotiling/floating/fullscreen windows
|
- Dual Kawase blur
|
||||||
- Special workspaces (scratchpads)
|
- Window fade in / out
|
||||||
- Window groups (tabbed mode)
|
- Tiling / floating / fullscreen windows
|
||||||
- Powerful window/monitor/layer rules
|
- Window / monitor rules
|
||||||
- Socket-based IPC
|
- Socket-based IPC
|
||||||
- Native IME and Input Panels Support
|
- Rounded corners
|
||||||
- and much more...
|
- Damage tracking ( *Experimental* )
|
||||||
|
- Moving / resizing
|
||||||
|
- Docks support
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
@ -79,13 +86,22 @@ easy IPC, much more QoL stuff than other compositors and more...
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
# Stars Over Time
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
[![Stars Preview]][Stars]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
# Special Thanks
|
# Special Thanks
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
**[wlroots]** - *For powering Hyprland in the past*
|
**[wlroots]** - *For their amazing library*
|
||||||
|
|
||||||
**[tinywl]** - *For showing how 2 do stuff*
|
**[tinywl]** - *For showing how 2 do stuff*
|
||||||
|
|
||||||
|
|
@ -100,18 +116,18 @@ easy IPC, much more QoL stuff than other compositors and more...
|
||||||
|
|
||||||
<!----------------------------------------------------------------------------->
|
<!----------------------------------------------------------------------------->
|
||||||
|
|
||||||
[Configure]: https://wiki.hypr.land/Configuring/
|
[Configure]: https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland
|
||||||
[Stars]: https://starchart.cc/hyprwm/Hyprland
|
[Discord]: https://discord.gg/hQ9XvMUjjr
|
||||||
[Hypr]: https://github.com/hyprwm/Hypr
|
[Stars]: https://starchart.cc/vaxerski/Hyprland
|
||||||
|
[Hypr]: https://github.com/vaxerski/Hypr
|
||||||
|
|
||||||
[Pull Requests]: https://github.com/hyprwm/Hyprland/pulls
|
[Pull Requests]: https://github.com/vaxerski/Hyprland/pulls
|
||||||
[Issues]: https://github.com/hyprwm/Hyprland/issues
|
[Issues]: https://github.com/vaxerski/Hyprland/issues
|
||||||
[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
|
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
||||||
|
|
||||||
[Contribute]: https://wiki.hypr.land/Contributing-and-Debugging/
|
[Contribute]: docs/Contribute.md
|
||||||
[Install]: https://wiki.hypr.land/Getting-Started/Installation/
|
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
||||||
[Quick Start]: https://wiki.hypr.land/Getting-Started/Master-Tutorial/
|
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
|
||||||
[Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml
|
|
||||||
[License]: LICENSE
|
[License]: LICENSE
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -122,22 +138,25 @@ easy IPC, much more QoL stuff than other compositors and more...
|
||||||
[Wayfire]: https://github.com/WayfireWM/wayfire
|
[Wayfire]: https://github.com/WayfireWM/wayfire
|
||||||
[TinyWl]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/tinywl/tinywl.c
|
[TinyWl]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/tinywl/tinywl.c
|
||||||
[Sway]: https://github.com/swaywm/sway
|
[Sway]: https://github.com/swaywm/sway
|
||||||
[DWL]: https://codeberg.org/dwl/dwl
|
[DWL]: https://github.com/djpohly/dwl
|
||||||
|
|
||||||
<!----------------------------------{ Images }--------------------------------->
|
<!----------------------------------{ Images }--------------------------------->
|
||||||
|
|
||||||
[Preview A]: https://i.ibb.co/XxFY75Mk/greerggergerhtrytghjnyhjn.png
|
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||||
[Preview B]: https://i.ibb.co/C1yTb0r/falf.png
|
[Preview A]: https://i.imgur.com/NbrTnZH.png
|
||||||
[Preview C]: https://i.ibb.co/2Yc4q835/hyprland-preview-b.png
|
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
|
||||||
|
[Preview C]: https://i.imgur.com/BpXxM8H.png
|
||||||
|
[Banner]: https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/hyprland.png
|
||||||
|
|
||||||
|
|
||||||
<!----------------------------------{ Badges }--------------------------------->
|
<!----------------------------------{ Badges }--------------------------------->
|
||||||
|
|
||||||
[Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg
|
[Badge Workflow]: https://github.com/vaxerski/Hyprland/actions/workflows/ci.yaml/badge.svg
|
||||||
|
|
||||||
[Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
|
[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
|
||||||
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
|
[Badge Issues]: https://img.shields.io/github/issues/vaxerski/Hyprland
|
||||||
[Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
|
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/vaxerski/Hyprland
|
||||||
[Badge License]: https://img.shields.io/github/license/hyprwm/Hyprland
|
[Badge Language]: https://img.shields.io/github/languages/top/vaxerski/Hyprland
|
||||||
[Badge Lines]: https://img.shields.io/tokei/lines/github/hyprwm/Hyprland
|
[Badge License]: https://img.shields.io/github/license/vaxerski/Hyprland
|
||||||
|
[Badge Lines]: https://img.shields.io/tokei/lines/github/vaxerski/Hyprland
|
||||||
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4
|
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4
|
||||||
|
|
|
||||||
32
SECURITY.md
|
|
@ -1,32 +0,0 @@
|
||||||
# Hyprland Development Security Policy
|
|
||||||
|
|
||||||
If you have a bug that affects the security of your system, you may
|
|
||||||
want to privately disclose it instead of making it immediately public.
|
|
||||||
|
|
||||||
## Supported versions
|
|
||||||
|
|
||||||
_Only_ the most recent release on Github is supported. There are no LTS releases.
|
|
||||||
|
|
||||||
## What is not a security issue
|
|
||||||
|
|
||||||
Some examples of issues that should not be reported as security issues:
|
|
||||||
|
|
||||||
- An app can execute a command when ran outside of a sandbox
|
|
||||||
- An app can write / read hyprland sockets when ran outside of a sandbox
|
|
||||||
- Crashes
|
|
||||||
- Things that are protected via permissions when the permission system is disabled
|
|
||||||
|
|
||||||
## What is a security issue
|
|
||||||
|
|
||||||
Some examples of issues that should be reported as security issues:
|
|
||||||
|
|
||||||
- Sandboxed application executing arbitrary code via Hyprland
|
|
||||||
- Application being able to modify Hyprland's code on the fly
|
|
||||||
- Application being able to keylog / track user's activity beyond what the wayland protocols allow
|
|
||||||
|
|
||||||
## How to report security issues
|
|
||||||
|
|
||||||
Please report your security issues via either of these channels:
|
|
||||||
- Mail: `vaxry [at] vaxry [dot] net`
|
|
||||||
- Matrix: `@vaxry:matrix.vaxry.net`
|
|
||||||
- Discord: `@vaxry`
|
|
||||||
1
VERSION
|
|
@ -1 +0,0 @@
|
||||||
0.52.0
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
<svg viewBox="0 330 1006.49 347.4685344827586" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="1006.49" height="347.4685344827586">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.st0 {
|
|
||||||
fill: url(#a);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st1 {
|
|
||||||
fill: url(#b);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st2 {
|
|
||||||
fill: url(#c);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st3 {
|
|
||||||
fill: url(#d);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st4 {
|
|
||||||
fill: url(#e);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st5 {
|
|
||||||
fill: url(#f);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st6 {
|
|
||||||
fill: url(#g);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st7 {
|
|
||||||
fill: url(#h);
|
|
||||||
}
|
|
||||||
|
|
||||||
.st8 {
|
|
||||||
fill: url(#i);
|
|
||||||
}
|
|
||||||
</style><style class="darkreader darkreader--sync" media="screen"/>
|
|
||||||
<linearGradient gradientUnits="userSpaceOnUse" y2="491.29" x2="561.93" y1="593.85" x1="561.93" id="i">
|
|
||||||
<stop stop-color="#00a8f4" offset="0" style="--darkreader-inline-stopcolor: var(--darkreader-background-00a8f4, #0086c3);" data-darkreader-inline-stopcolor=""/>
|
|
||||||
<stop stop-color="#00e5d0" offset="1" style="--darkreader-inline-stopcolor: var(--darkreader-background-00e5d0, #00b7a6);" data-darkreader-inline-stopcolor=""/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient xlink:href="#i" y2="491.58" x2="630.69" y1="567.48" x1="630.69" id="c"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="493.77" x2="480.34" y1="596.04" x1="480.34" id="a"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="470.31" x2="392.86" y1="567.48" x1="392.86" id="b"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="491.73" x2="804.79" y1="567.48" x1="804.79" id="f"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="463.46" x2="883.97" y1="569.67" x1="883.97" id="g"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="465.94" x2="671.56" y1="567.48" x1="671.56" id="d"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="491.58" x2="724.23" y1="569.67" x1="724.23" id="e"/>
|
|
||||||
<linearGradient xlink:href="#i" y2="346.78" x2="202.09" y1="659.7" x1="202.09" id="h"/>
|
|
||||||
</defs>
|
|
||||||
<g>
|
|
||||||
<path d="M580.29,495c-5.59-2.48-12.07-3.71-19.45-3.71-4.86,0-9.4.36-13.62,1.09-4.22.73-7.94,1.82-11.15,3.28-3.2,1.46-5.73,3.3-7.58,5.54-1.85,2.24-2.77,4.95-2.77,8.16v84.5h21.27v-28.09c1.05.58,2.16,1.1,3.35,1.5,3.01,1.02,5.92,1.67,8.74,1.97,2.82.29,4.95.44,6.41.44,6.9,0,12.75-1.6,17.56-4.81,4.81-3.21,8.52-7.7,11.15-13.48,2.62-5.78,3.93-12.46,3.93-20.03,0-10.1-1.58-18.07-4.73-23.89-3.16-5.83-7.53-9.98-13.11-12.46ZM574.46,543.37c-1.31,3.16-3.23,5.42-5.75,6.77-2.53,1.36-5.73,2.04-9.62,2.04-1.75,0-3.74-.24-5.97-.73-2.24-.48-4.28-1.26-6.12-2.33v-34.67c0-1.46.99-2.64,2.99-3.57,1.99-.92,5.32-1.38,9.98-1.38,4.27,0,7.6.85,9.98,2.55,2.38,1.7,4.05,4.1,5.03,7.21.97,3.11,1.46,6.9,1.46,11.36,0,5.34-.66,9.59-1.97,12.75Z" class="st8"/>
|
|
||||||
<path d="M638.78,491.58c-4.57,0-9.11.61-13.62,1.82-4.52,1.22-8.52,2.57-12.02,4.08-3.5,1.51-5.93,2.84-7.28,4.01v66h21.71v-56.96c1.65-.29,3.69-.48,6.12-.58,2.43-.1,5-.12,7.72-.07,2.72.05,5.34.17,7.87.36,2.52.2,4.61.49,6.26.87v-15.88c-1.36-1.07-3.35-1.94-5.97-2.62-2.62-.68-6.22-1.02-10.78-1.02Z" class="st2"/>
|
|
||||||
<path d="M481.21,542.1l-15.66-48.33h-24.91l29.61,72.88c-.37,1.26-.77,2.39-1.21,3.39-1.17,2.67-2.65,4.56-4.44,5.68-1.8,1.12-3.91,1.68-6.34,1.68-1.46,0-2.87-.12-4.22-.36-1.36-.24-2.82-.66-4.37-1.24v17.63c1.65.78,3.64,1.41,5.97,1.89,2.33.48,4.71.73,7.14.73,3.5,0,6.9-.87,10.2-2.62,3.3-1.75,6.48-4.61,9.54-8.6,3.06-3.98,5.9-9.37,8.52-16.17l28.99-74.89h-23.31l-15.52,48.33Z" class="st0"/>
|
|
||||||
<polygon points="410.78 509.65 375.08 509.65 375.08 470.31 351.48 470.31 351.48 567.48 375.08 567.48 375.08 528.88 410.78 528.88 410.78 567.48 434.23 567.48 434.23 470.31 410.78 470.31 410.78 509.65" class="st1"/>
|
|
||||||
<path d="M825.12,494.28c-4.66-1.7-10.3-2.55-16.9-2.55-3.11,0-6.48.24-10.13.73-3.64.49-7.26,1.12-10.85,1.89-3.59.78-6.9,1.68-9.91,2.7-3.01,1.02-5.44,2.02-7.28,2.99v67.45h21.71v-55.36c1.17-.58,2.86-1.14,5.1-1.67,2.23-.53,4.47-.8,6.7-.8,2.62,0,4.86.32,6.7.95,1.84.63,3.3,1.51,4.37,2.62,1.07,1.12,1.87,2.45,2.4,4.01.53,1.56.8,3.26.8,5.1v45.16h21.71v-49.54c0-6.51-1.24-11.65-3.71-15.44-2.48-3.79-6.05-6.53-10.71-8.23Z" class="st5"/>
|
|
||||||
<path d="M899.27,463.46v31.53c-.93-.55-1.9-1.01-2.91-1.37-2.72-.97-5.34-1.58-7.87-1.82-2.53-.24-4.57-.36-6.12-.36-11.75,0-20.57,3.45-26.44,10.34-5.88,6.9-8.81,16.32-8.81,28.26,0,7.67.99,14.08,2.99,19.23,1.99,5.15,4.73,9.2,8.23,12.17,3.5,2.96,7.65,5.08,12.46,6.34,4.81,1.26,10.08,1.89,15.81,1.89,4.27,0,8.45-.46,12.53-1.38,4.08-.92,7.74-2.26,11-4.01,3.25-1.75,5.85-3.96,7.79-6.63,1.94-2.67,2.91-5.8,2.91-9.4v-84.79h-21.56ZM899.27,545.92c0,1.85-1.09,3.23-3.28,4.15-2.19.92-5.03,1.38-8.52,1.38-4.57,0-8.18-.85-10.85-2.55-2.67-1.7-4.59-4.08-5.75-7.14-1.17-3.06-1.75-6.72-1.75-11,0-5.44.7-9.76,2.11-12.97,1.41-3.2,3.52-5.49,6.34-6.85,2.82-1.36,6.26-2.04,10.34-2.04,1.84,0,3.76.27,5.75.8,1.99.54,3.86,1.29,5.61,2.26v33.95Z" class="st6"/>
|
|
||||||
<rect height="101.55" width="21.56" y="465.94" x="660.78" class="st3"/>
|
|
||||||
<path d="M750.3,498.72c-2.38-1.94-4.98-3.42-7.79-4.44-2.82-1.02-5.63-1.72-8.45-2.11-2.82-.39-5.39-.58-7.72-.58-6.61,0-12.55.68-17.85,2.04-5.3,1.36-9.2,2.82-11.73,4.37v19.23c2.72-2.14,6.24-3.96,10.56-5.46,4.32-1.5,8.62-2.26,12.89-2.26,5.24,0,9.3,1,12.17,2.99,2.86,1.99,4.3,5.22,4.3,9.69v4.68c-.7-.4-1.44-.8-2.26-1.19-2.48-1.17-5.27-2.09-8.38-2.77-3.11-.68-6.32-1.02-9.62-1.02-5.93,0-10.83.92-14.71,2.77-3.89,1.85-6.77,4.47-8.67,7.87-1.89,3.4-2.84,7.38-2.84,11.95,0,4.86.82,8.91,2.48,12.16,1.65,3.26,3.96,5.83,6.92,7.72,2.96,1.89,6.41,3.25,10.34,4.08,3.93.82,8.13,1.24,12.6,1.24,7.48,0,13.86-.58,19.16-1.75,5.29-1.17,9.35-3.03,12.16-5.61,2.82-2.57,4.23-5.95,4.23-10.13l.15-34.82c0-4.47-.73-8.21-2.19-11.22-1.46-3.01-3.38-5.49-5.75-7.43ZM733.7,553.35c-1.99.68-5.46,1.02-10.42,1.02-1.94,0-3.81-.39-5.61-1.17-1.8-.78-3.23-1.89-4.3-3.35-1.07-1.46-1.6-3.11-1.6-4.95,0-3.01,1.09-5.22,3.28-6.63,2.19-1.41,5.66-2.11,10.42-2.11,3.11,0,6.02.34,8.74,1.02.87.22,1.69.47,2.48.74v11.36c0,2.04-1,3.4-2.99,4.08Z" class="st4"/>
|
|
||||||
</g>
|
|
||||||
<path d="M311.03,491.55c-9.09-20.56-22.42-39.71-35.29-58.22-2.38-3.41-4.62-6.64-6.84-9.87-3.15-4.6-7.42-10.49-12.36-17.31-11.29-15.59-28.92-39.62-40.84-59.36v49.42c12.28,17.62,24.2,33.49,30.57,42.78,13.94,20.33,30.09,42,39.67,63.66,28.78,65.13-11.7,128.85-82.05,129.61h-1.26c-.18,0-.35,0-.53,0-.18,0-.35,0-.53,0h-1.26c-70.35-.76-110.84-64.48-82.05-129.61,9.58-21.67,25.72-43.33,39.67-63.66,6.36-9.28,18.28-25.16,30.57-42.78v-49.42c-11.92,19.75-29.55,43.78-40.84,59.36-4.94,6.81-9.21,12.7-12.36,17.31-2.22,3.23-4.46,6.45-6.84,9.87-12.88,18.52-26.21,37.67-35.29,58.22-8.83,19.97-12.7,40.38-11.49,60.65,1.16,19.65,7.28,38.57,17.68,54.73,10.28,15.97,24.74,29.21,41.81,38.29,17.64,9.37,37.44,14.25,58.87,14.48.52,0,1.03,0,1.56,0,.18,0,.35,0,.53,0,.18,0,.35,0,.53,0,.52,0,1.03,0,1.56,0,21.43-.23,41.23-5.1,58.87-14.48,17.07-9.08,31.52-22.32,41.81-38.29,10.4-16.16,16.52-35.08,17.68-54.73,1.2-20.27-2.67-40.68-11.49-60.65Z" class="st7"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 6.6 KiB |
|
|
@ -1,2 +0,0 @@
|
||||||
[preferred]
|
|
||||||
default=hyprland;gtk
|
|
||||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 14 MiB |
|
Before Width: | Height: | Size: 5.9 MiB |
|
Before Width: | Height: | Size: 27 MiB |
BIN
assets/wall_2K.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
assets/wall_4K.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
assets/wall_8K.png
Normal file
|
After Width: | Height: | Size: 231 KiB |
40
aur/PKGBUILD-git
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Maintainer: Sander van Kasteel <info@sandervankasteel.nl>, ThatOneCalculator <kainoa@t1c.dev>
|
||||||
|
|
||||||
|
_pkgname="hyprland"
|
||||||
|
pkgname="${_pkgname}-git"
|
||||||
|
pkgver=r461.96cdf8f
|
||||||
|
pkgrel=5
|
||||||
|
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||||
|
arch=(any)
|
||||||
|
url="https://github.com/vaxerski/Hyprland"
|
||||||
|
license=('BSD')
|
||||||
|
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango)
|
||||||
|
makedepends=(git cmake ninja gcc gdb)
|
||||||
|
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
|
||||||
|
sha256sums=('SKIP')
|
||||||
|
options=(!makeflags !buildflags)
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
cd "$_pkgname"
|
||||||
|
( set -o pipefail
|
||||||
|
git describe --long 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
|
||||||
|
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "${srcdir}/${_pkgname}"
|
||||||
|
make all
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}/${_pkgname}"
|
||||||
|
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
||||||
|
mkdir -p "${pkgdir}/usr/share/hyprland"
|
||||||
|
install -Dm755 build/Hyprland -t "${pkgdir}/usr/bin"
|
||||||
|
install -Dm755 hyprctl/hyprctl -t "${pkgdir}/usr/bin"
|
||||||
|
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
||||||
|
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
||||||
|
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
||||||
|
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
||||||
|
}
|
||||||
4
config.mk
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
PREFIX = /usr/local
|
||||||
|
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement
|
||||||
|
CFLAGS += -DXWAYLAND
|
||||||
|
|
||||||
84
default.nix
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
fetchFromGitHub,
|
||||||
|
pkg-config,
|
||||||
|
cmake,
|
||||||
|
ninja,
|
||||||
|
libdrm,
|
||||||
|
libinput,
|
||||||
|
libxcb,
|
||||||
|
libxkbcommon,
|
||||||
|
mesa,
|
||||||
|
mount,
|
||||||
|
pango,
|
||||||
|
wayland,
|
||||||
|
wayland-protocols,
|
||||||
|
wayland-scanner,
|
||||||
|
wlroots,
|
||||||
|
xcbutilwm,
|
||||||
|
xwayland,
|
||||||
|
enableXWayland ? true,
|
||||||
|
version ? "git",
|
||||||
|
}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "hyprland";
|
||||||
|
inherit version;
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cmake
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs =
|
||||||
|
[
|
||||||
|
libdrm
|
||||||
|
libinput
|
||||||
|
libxcb
|
||||||
|
libxkbcommon
|
||||||
|
mesa
|
||||||
|
pango
|
||||||
|
wayland
|
||||||
|
wayland-protocols
|
||||||
|
wayland-scanner
|
||||||
|
(wlroots.override {inherit enableXWayland;})
|
||||||
|
xcbutilwm
|
||||||
|
]
|
||||||
|
++ lib.optional enableXWayland xwayland;
|
||||||
|
|
||||||
|
cmakeFlags =
|
||||||
|
["-DCMAKE_BUILD_TYPE=Release"]
|
||||||
|
++ lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
||||||
|
|
||||||
|
prePatch = ''
|
||||||
|
make config
|
||||||
|
'';
|
||||||
|
|
||||||
|
postBuild = ''
|
||||||
|
pushd ../hyprctl
|
||||||
|
make all
|
||||||
|
popd
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
pushd ..
|
||||||
|
install -Dm644 ./example/hyprland.desktop -t $out/share/wayland-sessions
|
||||||
|
install -Dm755 ./build/Hyprland -t $out/bin
|
||||||
|
install -Dm755 ./hyprctl/hyprctl -t $out/bin
|
||||||
|
install -Dm644 ./assets/* -t $out/share/hyprland
|
||||||
|
install -Dm644 ./example/hyprland.conf -t $out/share/hyprland
|
||||||
|
popd
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru.providedSessions = ["hyprland"];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://github.com/vaxerski/Hyprland";
|
||||||
|
description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||||
|
license = licenses.bsd3;
|
||||||
|
platforms = platforms.linux;
|
||||||
|
mainProgram = "Hyprland";
|
||||||
|
};
|
||||||
|
}
|
||||||
32
docs/Contribute.md
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
*Thank you for considering contributing to Hyprland.*
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Check the [Wiki] for debugging instructions.
|
||||||
|
|
||||||
|
Afterwards, pick yourself an [Issue] or implement your own suggestion.
|
||||||
|
|
||||||
|
An good place to search for things to contribute is the [Projects Page]
|
||||||
|
|
||||||
|
*As Hyprland is still in its early stages of development, I'd recommend you stick to bug fixes first.*
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
|
||||||
|
- Please follow the code style
|
||||||
|
|
||||||
|
- Code must be readable
|
||||||
|
|
||||||
|
- Features should be useful
|
||||||
|
|
||||||
|
- Test your changes!
|
||||||
|
|
||||||
|
*Run it on bare metal and check if everything works.*
|
||||||
|
|
||||||
|
<!----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
[Issue]: https://github.com/vaxerski/Hyprland/issues
|
||||||
|
[Wiki]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
|
||||||
|
[Projects page]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
.\" Automatically generated by Pandoc 3.1.3
|
|
||||||
.\"
|
|
||||||
.\" Define V font for inline verbatim, using C font in formats
|
|
||||||
.\" that render this, and otherwise B font.
|
|
||||||
.ie "\f[CB]x\f[]"x" \{\
|
|
||||||
. ftr V B
|
|
||||||
. ftr VI BI
|
|
||||||
. ftr VB B
|
|
||||||
. ftr VBI BI
|
|
||||||
.\}
|
|
||||||
.el \{\
|
|
||||||
. ftr V CR
|
|
||||||
. ftr VI CI
|
|
||||||
. ftr VB CB
|
|
||||||
. ftr VBI CBI
|
|
||||||
.\}
|
|
||||||
.TH "Hyprland" "1" "" "" "Hyprland User Manual"
|
|
||||||
.hy
|
|
||||||
.SH NAME
|
|
||||||
.PP
|
|
||||||
Hyprland - Dynamic tiling Wayland compositor
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.PP
|
|
||||||
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic
|
|
||||||
tiling Wayland compositor that doesn\[aq]t sacrifice on its looks.
|
|
||||||
.PP
|
|
||||||
You can launch Hyprland by either going into a TTY and executing
|
|
||||||
\f[B]Hyprland\f[R], or with a login manager.
|
|
||||||
.SH NOTICE
|
|
||||||
.PP
|
|
||||||
Hyprland is still in pretty early development compared to some other
|
|
||||||
Wayland compositors.
|
|
||||||
.PP
|
|
||||||
Although Hyprland is pretty stable, it may have some bugs.
|
|
||||||
.SH CONFIGURATION
|
|
||||||
.PP
|
|
||||||
For configuration information please see
|
|
||||||
<\f[I]https://github.com/hyprwm/Hyprland/wiki\f[R]>.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
\f[B]-h\f[R], \f[B]--help\f[R]
|
|
||||||
Show command usage.
|
|
||||||
.TP
|
|
||||||
\f[B]-c\f[R], \f[B]--config\f[R]
|
|
||||||
Specify config file to use.
|
|
||||||
.TP
|
|
||||||
\f[B]--socket\f[R]
|
|
||||||
Sets the Wayland socket name (for Wayland socket handover)
|
|
||||||
.TP
|
|
||||||
\f[B]--wayland-fd\f[R]
|
|
||||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
|
||||||
.SH BUGS
|
|
||||||
.TP
|
|
||||||
Submit bug reports and request features online at:
|
|
||||||
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
|
||||||
.SH SEE ALSO
|
|
||||||
.PP
|
|
||||||
Sources at: <\f[I]https://github.com/hyprwm/Hyprland\f[R]>
|
|
||||||
.SH COPYRIGHT
|
|
||||||
.PP
|
|
||||||
Copyright (c) 2022, vaxerski
|
|
||||||
.SH AUTHORS
|
|
||||||
Vaxerski <\f[I]https://github.com/vaxerski\f[R]>.
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
:title: Hyprland
|
|
||||||
:author: Vaxerski <*https://github.com/vaxerski*>
|
|
||||||
|
|
||||||
NAME
|
|
||||||
====
|
|
||||||
|
|
||||||
Hyprland - Dynamic tiling Wayland compositor
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
========
|
|
||||||
|
|
||||||
**Hyprland** [*arg [...]*].
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
===========
|
|
||||||
|
|
||||||
**Hyprland** is an independent, highly customizable,
|
|
||||||
dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
|
||||||
|
|
||||||
You can launch Hyprland by either going into a TTY and
|
|
||||||
executing **Hyprland**, or with a login manager.
|
|
||||||
|
|
||||||
NOTICE
|
|
||||||
======
|
|
||||||
|
|
||||||
Hyprland is still in pretty early development compared to some other Wayland compositors.
|
|
||||||
|
|
||||||
Although Hyprland is pretty stable, it may have some bugs.
|
|
||||||
|
|
||||||
CONFIGURATION
|
|
||||||
=============
|
|
||||||
|
|
||||||
For configuration information please see <*https://github.com/hyprwm/Hyprland/wiki*>.
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
=======
|
|
||||||
|
|
||||||
**-h**, **--help**
|
|
||||||
Show command usage.
|
|
||||||
|
|
||||||
**-c**, **--config**
|
|
||||||
Specify config file to use.
|
|
||||||
|
|
||||||
**--socket**
|
|
||||||
Sets the Wayland socket name (for Wayland socket handover)
|
|
||||||
|
|
||||||
**--wayland-fd**
|
|
||||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
|
||||||
|
|
||||||
BUGS
|
|
||||||
====
|
|
||||||
|
|
||||||
Submit bug reports and request features online at:
|
|
||||||
<*https://github.com/hyprwm/Hyprland/issues*>
|
|
||||||
|
|
||||||
SEE ALSO
|
|
||||||
========
|
|
||||||
|
|
||||||
Sources at: <*https://github.com/hyprwm/Hyprland*>
|
|
||||||
|
|
||||||
COPYRIGHT
|
|
||||||
=========
|
|
||||||
|
|
||||||
Copyright (c) 2022, vaxerski
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
# Issue Guidelines
|
|
||||||
|
|
||||||
First of all, please remember to:
|
|
||||||
- Check that your issue is not a duplicate
|
|
||||||
- Read the [FAQ](https://wiki.hypr.land/FAQ/)
|
|
||||||
- Read the [Configuring Page](https://wiki.hypr.land/Configuring/)
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
# Reporting suggestions
|
|
||||||
Suggestions are welcome.
|
|
||||||
|
|
||||||
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://wiki.hypr.land/IPC). Please do not suggest features that can be implemented as such.
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
# Reporting bugs
|
|
||||||
|
|
||||||
All bug reports should have the following:
|
|
||||||
- Steps to reproduce
|
|
||||||
- Expected outcome
|
|
||||||
- Noted outcome
|
|
||||||
|
|
||||||
If your bug is one that doesn't crash Hyprland, but feels like invalid behavior, that's all you need to say.
|
|
||||||
|
|
||||||
If your bug crashes Hyprland, append additionally:
|
|
||||||
- The Hyprland log
|
|
||||||
- Your config
|
|
||||||
- (v0.22.0beta and up) The Hyprland Crash Report
|
|
||||||
- (v0.21.0beta and below) Coredump / Coredump analysis (with a stacktrace)
|
|
||||||
|
|
||||||
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
|
|
||||||
|
|
||||||
## Obtaining the Hyprland log
|
|
||||||
If you are in a TTY, and the hyprland session that crashed was the last one you launched, the log will be printed with
|
|
||||||
```
|
|
||||||
cat $XDG_RUNTIME_DIR/hypr/$(ls -t $XDG_RUNTIME_DIR/hypr | head -n 1)/hyprland.log
|
|
||||||
```
|
|
||||||
feel free to send it to a file, save, copy, etc.
|
|
||||||
|
|
||||||
if you are in a Hyprland session, and you want the log of the last session, use
|
|
||||||
```
|
|
||||||
cat $XDG_RUNTIME_DIR/hypr/$(ls -t $XDG_RUNTIME_DIR/hypr | head -n 2 | tail -n 1)/hyprland.log
|
|
||||||
```
|
|
||||||
|
|
||||||
basically, directories in $XDG_RUNTIME_DIR/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 `$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.
|
|
||||||
|
|
||||||
Attach that file to your issue.
|
|
||||||
## Obtaining the Hyprland coredump (v0.21.0beta and below)
|
|
||||||
If you are on systemd, you can simply use
|
|
||||||
```
|
|
||||||
coredumpctl
|
|
||||||
```
|
|
||||||
then go to the end (press END on your keyboard) and remember the PID of the last `Hyprland` occurrence. It's the first number after the time, for example `2891`.
|
|
||||||
|
|
||||||
exit coredumpctl (ctrl+c) and use
|
|
||||||
```
|
|
||||||
coredumpctl info [PID]
|
|
||||||
```
|
|
||||||
where `[PID]` is the PID you remembered.
|
|
||||||
|
|
||||||
## Obtaining the debug Hyprland coredump
|
|
||||||
A debug coredump provides more information for debugging and may speed up the process of fixing the bug.
|
|
||||||
|
|
||||||
Make sure you're on latest git. Run `git pull --recurse-submodules` to sync everything.
|
|
||||||
|
|
||||||
1. [Compile Hyprland with debug mode](http://wiki.hypr.land/Contributing-and-Debugging/#build-in-debug-mode)
|
|
||||||
> Note: The config file used will be `hyprlandd.conf` instead of `hyprland.conf`
|
|
||||||
|
|
||||||
2. `cd ~`
|
|
||||||
3. For your own convenience, launch Hyprland from a tty with the envvar `ASAN_OPTIONS="log_path=asan.log" ~/path/to/Hyprland`
|
|
||||||
4. Reproduce the crash. Hyprland should instantly close.
|
|
||||||
5. Check out your `~` and find a file called `asan.log.XXXXX` where `XXXXX` will be a number corresponding to the PID of the Hyprland instance that crashed.
|
|
||||||
6. That is your coredump. Attach it to your issue.
|
|
||||||
35
docs/Install.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
*I do not maintain any packages, but some kind people have made them for me.*
|
||||||
|
|
||||||
|
**If I missed any, please let me know.**
|
||||||
|
|
||||||
|
## Notice
|
||||||
|
|
||||||
|
Since I am not the maintainer, I cannot guarantee that those packages will always work and be up to date.
|
||||||
|
|
||||||
|
***Use at your own disclosure.*** <br>
|
||||||
|
*If they don't work, try building manually.*
|
||||||
|
|
||||||
|
#### Arch ( AUR / -git )
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yay -S hyprland-git
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Building / No XWayland / other
|
||||||
|
|
||||||
|
If your distro doesn't have **Hyprland** in its repositories, you want to modify it, or use custom build flags, please refer to the **[Wiki Page][Install]** for the installation instructions.
|
||||||
|
|
||||||
|
|
||||||
|
<!----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
||||||
|
|
||||||
|
|
||||||
159
docs/hyprctl.1
|
|
@ -1,159 +0,0 @@
|
||||||
.\" Automatically generated by Pandoc 3.1.3
|
|
||||||
.\"
|
|
||||||
.\" Define V font for inline verbatim, using C font in formats
|
|
||||||
.\" that render this, and otherwise B font.
|
|
||||||
.ie "\f[CB]x\f[]"x" \{\
|
|
||||||
. ftr V B
|
|
||||||
. ftr VI BI
|
|
||||||
. ftr VB B
|
|
||||||
. ftr VBI BI
|
|
||||||
.\}
|
|
||||||
.el \{\
|
|
||||||
. ftr V CR
|
|
||||||
. ftr VI CI
|
|
||||||
. ftr VB CB
|
|
||||||
. ftr VBI CBI
|
|
||||||
.\}
|
|
||||||
.TH "hyprctl" "1" "" "" "hyprctl User Manual"
|
|
||||||
.hy
|
|
||||||
.SH NAME
|
|
||||||
.PP
|
|
||||||
hyprctl - Utility for controlling parts of Hyprland from a CLI or a
|
|
||||||
script
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.PP
|
|
||||||
\f[B]hyprctl\f[R] [\f[I](opt)flags\f[R]] [\f[B]command\f[R]]
|
|
||||||
[\f[I](opt)args\f[R]]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
\f[B]hyprctl\f[R] is a utility for controlling some parts of the
|
|
||||||
compositor from a CLI or a script.
|
|
||||||
.SH CONTROL COMMANDS
|
|
||||||
.PP
|
|
||||||
\f[B]dispatch\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Call a dispatcher with an argument.
|
|
||||||
.PP
|
|
||||||
An argument must be present.
|
|
||||||
For dispatchers without parameters it can be anything.
|
|
||||||
.PP
|
|
||||||
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
|
||||||
.TP
|
|
||||||
Examples:
|
|
||||||
\f[B]hyprctl\f[R] \f[I]dispatch exec kitty\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
\f[B]hyprctl\f[R] \f[I]dispatch pseudo x\f[R]
|
|
||||||
.RE
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]keyword\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Set a config keyword dynamically.
|
|
||||||
.PP
|
|
||||||
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
|
||||||
.TP
|
|
||||||
Examples:
|
|
||||||
\f[B]hyprctl\f[R] \f[I]keyword bind SUPER,0,pseudo\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
\f[B]hyprctl\f[R] \f[I]keyword general:border_size 10\f[R]
|
|
||||||
.RE
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]reload\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Force a reload of the config file.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]kill\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Enter kill mode, where you can kill an app by clicking on it.
|
|
||||||
You can exit by pressing ESCAPE.
|
|
||||||
.RE
|
|
||||||
.SH INFO COMMANDS
|
|
||||||
.PP
|
|
||||||
\f[B]version\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Prints the Hyprland version, flags, commit and branch of build.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]monitors\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Lists all the outputs with their properties.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]workspaces\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Lists all workspaces with their properties.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]clients\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Lists all windows with their properties.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]devices\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Lists all connected input devices.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]activewindow\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Returns the active window name.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]layers\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Lists all the layers.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]splash\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Returns the current random splash.
|
|
||||||
.RE
|
|
||||||
.SH OPTIONS
|
|
||||||
.PP
|
|
||||||
\f[B]--batch\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Specify a batch of commands to execute.
|
|
||||||
.TP
|
|
||||||
Example:
|
|
||||||
\f[B]hyprctl\f[R] \f[I]--batch \[dq]keyword general:border_size 2 ;
|
|
||||||
keyword general:gaps_out 20\[dq]\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
\f[I];\f[R] separates the commands.
|
|
||||||
.RE
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\f[B]-j\f[R]
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Outputs information in JSON.
|
|
||||||
.RE
|
|
||||||
.SH BUGS
|
|
||||||
.TP
|
|
||||||
Submit bug reports and request features online at:
|
|
||||||
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
|
||||||
.SH SEE ALSO
|
|
||||||
.PP
|
|
||||||
Sources at: <\f[I]https://github.com/hyprwm/Hyprland\f[R]>
|
|
||||||
.SH COPYRIGHT
|
|
||||||
.PP
|
|
||||||
Copyright (c) 2022, vaxerski
|
|
||||||
.SH AUTHORS
|
|
||||||
Vaxerski <\f[I]https://github.com/vaxerski\f[R]>.
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
:title: hyprctl(1)
|
|
||||||
:author: Vaxerski <*https://github.com/vaxerski*>
|
|
||||||
|
|
||||||
NAME
|
|
||||||
====
|
|
||||||
|
|
||||||
hyprctl - Utility for controlling parts of Hyprland from a CLI or a script
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
========
|
|
||||||
|
|
||||||
**hyprctl** [*(opt)flags*] [**command**] [*(opt)args*]
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
===========
|
|
||||||
|
|
||||||
**hyprctl** is a utility for controlling some parts of the compositor from a CLI or a script.
|
|
||||||
|
|
||||||
CONTROL COMMANDS
|
|
||||||
================
|
|
||||||
|
|
||||||
**dispatch**
|
|
||||||
|
|
||||||
Call a dispatcher with an argument.
|
|
||||||
|
|
||||||
An argument must be present.
|
|
||||||
For dispatchers without parameters it can be anything.
|
|
||||||
|
|
||||||
Returns: *ok* on success, and an error message on failure.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
**hyprctl** *dispatch exec kitty*
|
|
||||||
|
|
||||||
**hyprctl** *dispatch pseudo x*
|
|
||||||
|
|
||||||
**keyword**
|
|
||||||
|
|
||||||
Set a config keyword dynamically.
|
|
||||||
|
|
||||||
Returns: *ok* on success, and an error message on failure.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
**hyprctl** *keyword bind SUPER,0,pseudo*
|
|
||||||
|
|
||||||
**hyprctl** *keyword general:border_size 10*
|
|
||||||
|
|
||||||
**reload**
|
|
||||||
|
|
||||||
Force a reload of the config file.
|
|
||||||
|
|
||||||
**kill**
|
|
||||||
|
|
||||||
Enter kill mode, where you can kill an app by clicking on it.
|
|
||||||
You can exit by pressing ESCAPE.
|
|
||||||
|
|
||||||
INFO COMMANDS
|
|
||||||
=============
|
|
||||||
|
|
||||||
**version**
|
|
||||||
|
|
||||||
Prints the Hyprland version, flags, commit and branch of build.
|
|
||||||
|
|
||||||
**monitors**
|
|
||||||
|
|
||||||
Lists all the outputs with their properties.
|
|
||||||
|
|
||||||
**workspaces**
|
|
||||||
|
|
||||||
Lists all workspaces with their properties.
|
|
||||||
|
|
||||||
**clients**
|
|
||||||
|
|
||||||
Lists all windows with their properties.
|
|
||||||
|
|
||||||
**devices**
|
|
||||||
|
|
||||||
Lists all connected input devices.
|
|
||||||
|
|
||||||
**activewindow**
|
|
||||||
|
|
||||||
Returns the active window name.
|
|
||||||
|
|
||||||
**layers**
|
|
||||||
|
|
||||||
Lists all the layers.
|
|
||||||
|
|
||||||
**splash**
|
|
||||||
|
|
||||||
Returns the current random splash.
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
=======
|
|
||||||
|
|
||||||
**--batch**
|
|
||||||
|
|
||||||
Specify a batch of commands to execute.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
**hyprctl** *--batch "keyword general:border_size 2 ; keyword general:gaps_out 20"*
|
|
||||||
|
|
||||||
*;* separates the commands.
|
|
||||||
|
|
||||||
**-j**
|
|
||||||
|
|
||||||
Outputs information in JSON.
|
|
||||||
|
|
||||||
BUGS
|
|
||||||
====
|
|
||||||
|
|
||||||
Submit bug reports and request features online at:
|
|
||||||
<*https://github.com/hyprwm/Hyprland/issues*>
|
|
||||||
|
|
||||||
SEE ALSO
|
|
||||||
========
|
|
||||||
|
|
||||||
Sources at: <*https://github.com/hyprwm/Hyprland*>
|
|
||||||
|
|
||||||
COPYRIGHT
|
|
||||||
=========
|
|
||||||
|
|
||||||
Copyright (c) 2022, vaxerski
|
|
||||||
|
|
@ -1,341 +1,98 @@
|
||||||
# This is an example Hyprland config file.
|
# This is an example Hyprland config file.
|
||||||
|
# Syntax is the same as in Hypr, but settings might differ.
|
||||||
|
#
|
||||||
# Refer to the wiki for more information.
|
# Refer to the wiki for more information.
|
||||||
# https://wiki.hypr.land/Configuring/
|
|
||||||
|
|
||||||
# Please note not all available settings / options are set here.
|
monitor=,1280x720@60,0x0,1
|
||||||
# For a full list, see the wiki
|
workspace=DP-1,1
|
||||||
|
|
||||||
# You can split this configuration into multiple files
|
|
||||||
# Create your files separately and then link them to this file like this:
|
|
||||||
# source = ~/.config/hypr/myColors.conf
|
|
||||||
|
|
||||||
|
|
||||||
################
|
|
||||||
### MONITORS ###
|
|
||||||
################
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Monitors/
|
|
||||||
monitor=,preferred,auto,auto
|
|
||||||
|
|
||||||
|
|
||||||
###################
|
|
||||||
### MY PROGRAMS ###
|
|
||||||
###################
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Keywords/
|
|
||||||
|
|
||||||
# Set programs that you use
|
|
||||||
$terminal = kitty
|
|
||||||
$fileManager = dolphin
|
|
||||||
$menu = hyprlauncher
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
### AUTOSTART ###
|
|
||||||
#################
|
|
||||||
|
|
||||||
# Autostart necessary processes (like notifications daemons, status bars, etc.)
|
|
||||||
# Or execute your favorite apps at launch like this:
|
|
||||||
|
|
||||||
# exec-once = $terminal
|
|
||||||
# exec-once = nm-applet &
|
|
||||||
# exec-once = waybar & hyprpaper & firefox
|
|
||||||
|
|
||||||
|
|
||||||
#############################
|
|
||||||
### ENVIRONMENT VARIABLES ###
|
|
||||||
#############################
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Environment-variables/
|
|
||||||
|
|
||||||
env = XCURSOR_SIZE,24
|
|
||||||
env = HYPRCURSOR_SIZE,24
|
|
||||||
|
|
||||||
|
|
||||||
###################
|
|
||||||
### PERMISSIONS ###
|
|
||||||
###################
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Permissions/
|
|
||||||
# Please note permission changes here require a Hyprland restart and are not applied on-the-fly
|
|
||||||
# for security reasons
|
|
||||||
|
|
||||||
# ecosystem {
|
|
||||||
# enforce_permissions = 1
|
|
||||||
# }
|
|
||||||
|
|
||||||
# permission = /usr/(bin|local/bin)/grim, screencopy, allow
|
|
||||||
# permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow
|
|
||||||
# permission = /usr/(bin|local/bin)/hyprpm, plugin, allow
|
|
||||||
|
|
||||||
|
|
||||||
#####################
|
|
||||||
### LOOK AND FEEL ###
|
|
||||||
#####################
|
|
||||||
|
|
||||||
# Refer to https://wiki.hypr.land/Configuring/Variables/
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#general
|
|
||||||
general {
|
|
||||||
gaps_in = 5
|
|
||||||
gaps_out = 20
|
|
||||||
|
|
||||||
border_size = 2
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#variable-types for info about colors
|
|
||||||
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
|
||||||
col.inactive_border = rgba(595959aa)
|
|
||||||
|
|
||||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
|
||||||
resize_on_border = false
|
|
||||||
|
|
||||||
# Please see https://wiki.hypr.land/Configuring/Tearing/ before you turn this on
|
|
||||||
allow_tearing = false
|
|
||||||
|
|
||||||
layout = dwindle
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#decoration
|
|
||||||
decoration {
|
|
||||||
rounding = 10
|
|
||||||
rounding_power = 2
|
|
||||||
|
|
||||||
# Change transparency of focused and unfocused windows
|
|
||||||
active_opacity = 1.0
|
|
||||||
inactive_opacity = 1.0
|
|
||||||
|
|
||||||
shadow {
|
|
||||||
enabled = true
|
|
||||||
range = 4
|
|
||||||
render_power = 3
|
|
||||||
color = rgba(1a1a1aee)
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#blur
|
|
||||||
blur {
|
|
||||||
enabled = true
|
|
||||||
size = 3
|
|
||||||
passes = 1
|
|
||||||
|
|
||||||
vibrancy = 0.1696
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#animations
|
|
||||||
animations {
|
|
||||||
enabled = yes, please :)
|
|
||||||
|
|
||||||
# Default curves, see https://wiki.hypr.land/Configuring/Animations/#curves
|
|
||||||
# NAME, X0, Y0, X1, Y1
|
|
||||||
bezier = easeOutQuint, 0.23, 1, 0.32, 1
|
|
||||||
bezier = easeInOutCubic, 0.65, 0.05, 0.36, 1
|
|
||||||
bezier = linear, 0, 0, 1, 1
|
|
||||||
bezier = almostLinear, 0.5, 0.5, 0.75, 1
|
|
||||||
bezier = quick, 0.15, 0, 0.1, 1
|
|
||||||
|
|
||||||
# Default animations, see https://wiki.hypr.land/Configuring/Animations/
|
|
||||||
# NAME, ONOFF, SPEED, CURVE, [STYLE]
|
|
||||||
animation = global, 1, 10, default
|
|
||||||
animation = border, 1, 5.39, easeOutQuint
|
|
||||||
animation = windows, 1, 4.79, easeOutQuint
|
|
||||||
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
|
|
||||||
animation = windowsOut, 1, 1.49, linear, popin 87%
|
|
||||||
animation = fadeIn, 1, 1.73, almostLinear
|
|
||||||
animation = fadeOut, 1, 1.46, almostLinear
|
|
||||||
animation = fade, 1, 3.03, quick
|
|
||||||
animation = layers, 1, 3.81, easeOutQuint
|
|
||||||
animation = layersIn, 1, 4, easeOutQuint, fade
|
|
||||||
animation = layersOut, 1, 1.5, linear, fade
|
|
||||||
animation = fadeLayersIn, 1, 1.79, almostLinear
|
|
||||||
animation = fadeLayersOut, 1, 1.39, almostLinear
|
|
||||||
animation = workspaces, 1, 1.94, almostLinear, fade
|
|
||||||
animation = workspacesIn, 1, 1.21, almostLinear, fade
|
|
||||||
animation = workspacesOut, 1, 1.94, almostLinear, fade
|
|
||||||
animation = zoomFactor, 1, 7, quick
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ref https://wiki.hypr.land/Configuring/Workspace-Rules/
|
|
||||||
# "Smart gaps" / "No gaps when only"
|
|
||||||
# uncomment all if you wish to use that.
|
|
||||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
|
||||||
# workspace = f[1], gapsout:0, gapsin:0
|
|
||||||
# windowrule {
|
|
||||||
# name = no-gaps-wtv1
|
|
||||||
# match:float = false
|
|
||||||
# match:workspace = w[tv1]
|
|
||||||
#
|
|
||||||
# border_size = 0
|
|
||||||
# rounding = 0
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# windowrule {
|
|
||||||
# name = no-gaps-f1
|
|
||||||
# match:float = false
|
|
||||||
# match:workspace = f[1]
|
|
||||||
#
|
|
||||||
# border_size = 0
|
|
||||||
# rounding = 0
|
|
||||||
# }
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
|
|
||||||
dwindle {
|
|
||||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
|
||||||
preserve_split = true # You probably want this
|
|
||||||
}
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Master-Layout/ for more
|
|
||||||
master {
|
|
||||||
new_status = master
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#misc
|
|
||||||
misc {
|
|
||||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
|
||||||
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#############
|
|
||||||
### INPUT ###
|
|
||||||
#############
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#input
|
|
||||||
input {
|
input {
|
||||||
kb_layout = us
|
kb_layout=
|
||||||
kb_variant =
|
kb_variant=
|
||||||
kb_model =
|
kb_model=
|
||||||
kb_options =
|
kb_options=
|
||||||
kb_rules =
|
kb_rules=
|
||||||
|
|
||||||
follow_mouse = 1
|
follow_mouse=1
|
||||||
|
|
||||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
|
||||||
|
|
||||||
touchpad {
|
|
||||||
natural_scroll = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Gestures
|
general {
|
||||||
gesture = 3, horizontal, workspace
|
max_fps=60 # deprecated, unused
|
||||||
|
sensitivity=0.25
|
||||||
|
main_mod=SUPER
|
||||||
|
|
||||||
# Example per-device config
|
gaps_in=5
|
||||||
# See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more
|
gaps_out=20
|
||||||
device {
|
border_size=2
|
||||||
name = epic-mouse-v1
|
col.active_border=0x66ee1111
|
||||||
sensitivity = -0.5
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
|
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decoration {
|
||||||
###################
|
rounding=10
|
||||||
### KEYBINDINGS ###
|
blur=1
|
||||||
###################
|
blur_size=3 # minimum 1
|
||||||
|
blur_passes=1 # minimum 1, more passes = more resource intensive.
|
||||||
# See https://wiki.hypr.land/Configuring/Keywords/
|
# Your blur "amount" is blur_size * blur_passes, but high blur_size (over around 5-ish) will produce artifacts.
|
||||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
# if you want heavy blur, you need to up the blur_passes.
|
||||||
|
# the more passes, the more you can up the blur_size without noticing artifacts.
|
||||||
# Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more
|
|
||||||
bind = $mainMod, Q, exec, $terminal
|
|
||||||
bind = $mainMod, C, killactive,
|
|
||||||
bind = $mainMod, M, exec, command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch exit
|
|
||||||
bind = $mainMod, E, exec, $fileManager
|
|
||||||
bind = $mainMod, V, togglefloating,
|
|
||||||
bind = $mainMod, R, exec, $menu
|
|
||||||
bind = $mainMod, P, pseudo, # dwindle
|
|
||||||
bind = $mainMod, J, togglesplit, # dwindle
|
|
||||||
|
|
||||||
# Move focus with mainMod + arrow keys
|
|
||||||
bind = $mainMod, left, movefocus, l
|
|
||||||
bind = $mainMod, right, movefocus, r
|
|
||||||
bind = $mainMod, up, movefocus, u
|
|
||||||
bind = $mainMod, down, movefocus, d
|
|
||||||
|
|
||||||
# Switch workspaces with mainMod + [0-9]
|
|
||||||
bind = $mainMod, 1, workspace, 1
|
|
||||||
bind = $mainMod, 2, workspace, 2
|
|
||||||
bind = $mainMod, 3, workspace, 3
|
|
||||||
bind = $mainMod, 4, workspace, 4
|
|
||||||
bind = $mainMod, 5, workspace, 5
|
|
||||||
bind = $mainMod, 6, workspace, 6
|
|
||||||
bind = $mainMod, 7, workspace, 7
|
|
||||||
bind = $mainMod, 8, workspace, 8
|
|
||||||
bind = $mainMod, 9, workspace, 9
|
|
||||||
bind = $mainMod, 0, workspace, 10
|
|
||||||
|
|
||||||
# Move active window to a workspace with mainMod + SHIFT + [0-9]
|
|
||||||
bind = $mainMod SHIFT, 1, movetoworkspace, 1
|
|
||||||
bind = $mainMod SHIFT, 2, movetoworkspace, 2
|
|
||||||
bind = $mainMod SHIFT, 3, movetoworkspace, 3
|
|
||||||
bind = $mainMod SHIFT, 4, movetoworkspace, 4
|
|
||||||
bind = $mainMod SHIFT, 5, movetoworkspace, 5
|
|
||||||
bind = $mainMod SHIFT, 6, movetoworkspace, 6
|
|
||||||
bind = $mainMod SHIFT, 7, movetoworkspace, 7
|
|
||||||
bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
|
||||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
|
||||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
|
||||||
|
|
||||||
# Example special workspace (scratchpad)
|
|
||||||
bind = $mainMod, S, togglespecialworkspace, magic
|
|
||||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
|
||||||
|
|
||||||
# Scroll through existing workspaces with mainMod + scroll
|
|
||||||
bind = $mainMod, mouse_down, workspace, e+1
|
|
||||||
bind = $mainMod, mouse_up, workspace, e-1
|
|
||||||
|
|
||||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
|
||||||
bindm = $mainMod, mouse:272, movewindow
|
|
||||||
bindm = $mainMod, mouse:273, resizewindow
|
|
||||||
|
|
||||||
# Laptop multimedia keys for volume and LCD brightness
|
|
||||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
|
|
||||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
|
||||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
|
||||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
|
||||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+
|
|
||||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-
|
|
||||||
|
|
||||||
# Requires playerctl
|
|
||||||
bindl = , XF86AudioNext, exec, playerctl next
|
|
||||||
bindl = , XF86AudioPause, exec, playerctl play-pause
|
|
||||||
bindl = , XF86AudioPlay, exec, playerctl play-pause
|
|
||||||
bindl = , XF86AudioPrev, exec, playerctl previous
|
|
||||||
|
|
||||||
##############################
|
|
||||||
### WINDOWS AND WORKSPACES ###
|
|
||||||
##############################
|
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Window-Rules/ for more
|
|
||||||
# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
|
|
||||||
|
|
||||||
# Example windowrules that are useful
|
|
||||||
|
|
||||||
windowrule {
|
|
||||||
# Ignore maximize requests from all apps. You'll probably like this.
|
|
||||||
name = suppress-maximize-events
|
|
||||||
match:class = .*
|
|
||||||
|
|
||||||
suppress_event = maximize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
windowrule {
|
animations {
|
||||||
# Fix some dragging issues with XWayland
|
enabled=1
|
||||||
name = fix-xwayland-drags
|
animation=windows,1,7,default
|
||||||
match:class = ^$
|
animation=borders,1,10,default
|
||||||
match:title = ^$
|
animation=fadein,1,10,default
|
||||||
match:xwayland = true
|
animation=workspaces,1,6,default
|
||||||
match:float = true
|
|
||||||
match:fullscreen = false
|
|
||||||
match:pin = false
|
|
||||||
|
|
||||||
no_focus = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Hyprland-run windowrule
|
dwindle {
|
||||||
windowrule {
|
pseudotile=0 # enable pseudotiling on dwindle
|
||||||
name = move-hyprland-run
|
|
||||||
|
|
||||||
match:class = hyprland-run
|
|
||||||
|
|
||||||
move = 20 monitor_h-120
|
|
||||||
float = yes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# example window rules
|
||||||
|
# for windows named/classed as abc and xyz
|
||||||
|
#windowrule=move 69 420,abc
|
||||||
|
#windowrule=size 420 69,abc
|
||||||
|
#windowrule=tile,xyz
|
||||||
|
#windowrule=float,abc
|
||||||
|
#windowrule=pseudo,abc
|
||||||
|
#windowrule=monitor 0,xyz
|
||||||
|
|
||||||
|
# example binds
|
||||||
|
bind=SUPER,Q,exec,kitty
|
||||||
|
bind=SUPER,C,killactive,
|
||||||
|
bind=SUPER,M,exec,pkill Hyprland
|
||||||
|
bind=SUPER,E,exec,dolphin
|
||||||
|
bind=SUPER,V,togglefloating,
|
||||||
|
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
||||||
|
bind=SUPER,P,pseudo,
|
||||||
|
|
||||||
|
bind=SUPER,left,movefocus,l
|
||||||
|
bind=SUPER,right,movefocus,r
|
||||||
|
bind=SUPER,up,movefocus,u
|
||||||
|
bind=SUPER,down,movefocus,d
|
||||||
|
|
||||||
|
bind=SUPER,1,workspace,1
|
||||||
|
bind=SUPER,2,workspace,2
|
||||||
|
bind=SUPER,3,workspace,3
|
||||||
|
bind=SUPER,4,workspace,4
|
||||||
|
bind=SUPER,5,workspace,5
|
||||||
|
bind=SUPER,6,workspace,6
|
||||||
|
bind=SUPER,7,workspace,7
|
||||||
|
bind=SUPER,8,workspace,8
|
||||||
|
bind=SUPER,9,workspace,9
|
||||||
|
bind=SUPER,0,workspace,10
|
||||||
|
|
||||||
|
bind=ALT,1,movetoworkspace,1
|
||||||
|
bind=ALT,2,movetoworkspace,2
|
||||||
|
bind=ALT,3,movetoworkspace,3
|
||||||
|
bind=ALT,4,movetoworkspace,4
|
||||||
|
bind=ALT,5,movetoworkspace,5
|
||||||
|
bind=ALT,6,movetoworkspace,6
|
||||||
|
bind=ALT,7,movetoworkspace,7
|
||||||
|
bind=ALT,8,movetoworkspace,8
|
||||||
|
bind=ALT,9,movetoworkspace,9
|
||||||
|
bind=ALT,0,movetoworkspace,10
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Hyprland
|
Name=Hyprland
|
||||||
Comment=An intelligent dynamic tiling Wayland compositor
|
Comment=An intelligent dynamic tiling Wayland compositor
|
||||||
Exec=start-hyprland
|
Exec=Hyprland
|
||||||
Type=Application
|
Type=Application
|
||||||
DesktopNames=Hyprland
|
|
||||||
Keywords=tiling;wayland;compositor;
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
; a primitive systemd --user example
|
|
||||||
[Unit]
|
|
||||||
Description = %p
|
|
||||||
BindsTo = graphical-session.target
|
|
||||||
Upholds = swaybg@333333.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type = notify
|
|
||||||
ExecStart = /usr/bin/Hyprland
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy = default.target
|
|
||||||
|
|
@ -22,6 +22,5 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
//
|
|
||||||
// Example blue light filter shader.
|
|
||||||
//
|
|
||||||
|
|
||||||
#version 300 es
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
in vec2 v_texcoord;
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
vec4 pixColor = texture(tex, v_texcoord);
|
|
||||||
|
|
||||||
pixColor[2] *= 0.8;
|
|
||||||
|
|
||||||
fragColor = pixColor;
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
; a primitive systemd --user example
|
|
||||||
; see example/hyprland.service for more details
|
|
||||||
[Unit]
|
|
||||||
Description = %p
|
|
||||||
BindsTo = hyprland.service
|
|
||||||
Wants = hyprland.service
|
|
||||||
After = hyprland.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart = /usr/bin/swaybg --color #%i
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy = default.target
|
|
||||||
422
flake.lock
generated
|
|
@ -1,335 +1,12 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"aquamarine": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"hyprwayland-scanner": [
|
|
||||||
"hyprwayland-scanner"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765900596,
|
|
||||||
"narHash": "sha256-+hn8v9jkkLP9m+o0Nm5SiEq10W0iWDSotH2XfjU45fA=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "aquamarine",
|
|
||||||
"rev": "d83c97f8f5c0aae553c1489c7d9eff3eadcadace",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "aquamarine",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1761588595,
|
|
||||||
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gitignore": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"pre-commit-hooks",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1709087332,
|
|
||||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprcursor": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprlang": [
|
|
||||||
"hyprlang"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1753964049,
|
|
||||||
"narHash": "sha256-lIqabfBY7z/OANxHoPeIrDJrFyYy9jAM4GQLzZ2feCM=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprcursor",
|
|
||||||
"rev": "44e91d467bdad8dcf8bbd2ac7cf49972540980a5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprcursor",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprgraphics": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1763733840,
|
|
||||||
"narHash": "sha256-JnET78yl5RvpGuDQy3rCycOCkiKoLr5DN1fPhRNNMco=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprgraphics",
|
|
||||||
"rev": "8f1bec691b2d198c60cccabca7a94add2df4ed1a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprgraphics",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprland-guiutils": {
|
|
||||||
"inputs": {
|
|
||||||
"aquamarine": [
|
|
||||||
"aquamarine"
|
|
||||||
],
|
|
||||||
"hyprgraphics": [
|
|
||||||
"hyprgraphics"
|
|
||||||
],
|
|
||||||
"hyprlang": [
|
|
||||||
"hyprlang"
|
|
||||||
],
|
|
||||||
"hyprtoolkit": "hyprtoolkit",
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"hyprwayland-scanner": [
|
|
||||||
"hyprwayland-scanner"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765643131,
|
|
||||||
"narHash": "sha256-CCGohW5EBIRy4B7vTyBMqPgsNcaNenVad/wszfddET0=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-guiutils",
|
|
||||||
"rev": "e50ae912813bdfa8372d62daf454f48d6df02297",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-guiutils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprland-protocols": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765214753,
|
|
||||||
"narHash": "sha256-P9zdGXOzToJJgu5sVjv7oeOGPIIwrd9hAUAP3PsmBBs=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-protocols",
|
|
||||||
"rev": "3f3860b869014c00e8b9e0528c7b4ddc335c21ab",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprland-protocols",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprlang": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1764612430,
|
|
||||||
"narHash": "sha256-54ltTSbI6W+qYGMchAgCR6QnC1kOdKXN6X6pJhOWxFg=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprlang",
|
|
||||||
"rev": "0d00dc118981531aa731150b6ea551ef037acddd",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprlang",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprtoolkit": {
|
|
||||||
"inputs": {
|
|
||||||
"aquamarine": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"aquamarine"
|
|
||||||
],
|
|
||||||
"hyprgraphics": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"hyprgraphics"
|
|
||||||
],
|
|
||||||
"hyprlang": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"hyprlang"
|
|
||||||
],
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"hyprwayland-scanner": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"hyprwayland-scanner"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"hyprland-guiutils",
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1764592794,
|
|
||||||
"narHash": "sha256-7CcO+wbTJ1L1NBQHierHzheQGPWwkIQug/w+fhTAVuU=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprtoolkit",
|
|
||||||
"rev": "5cfe0743f0e608e1462972303778d8a0859ee63e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprtoolkit",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprutils": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1766160771,
|
|
||||||
"narHash": "sha256-roINUGikWRqqgKrD4iotKbGj3ZKJl3hjMz5l/SyKrHw=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprutils",
|
|
||||||
"rev": "5ac060bfcf2f12b3a6381156ebbc13826a05b09f",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprutils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprwayland-scanner": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1763640274,
|
|
||||||
"narHash": "sha256-Uan1Nl9i4TF/kyFoHnTq1bd/rsWh4GAK/9/jDqLbY5A=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwayland-scanner",
|
|
||||||
"rev": "f6cf414ca0e16a4d30198fd670ec86df3c89f671",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwayland-scanner",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hyprwire": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1766253200,
|
|
||||||
"narHash": "sha256-26qPwrd3od+xoYVywSB7hC2cz9ivN46VPLlrsXyGxvE=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwire",
|
|
||||||
"rev": "1079777525b30a947c8d657fac158e00ae85de9d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "hyprwire",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766070988,
|
"lastModified": 1653407748,
|
||||||
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=",
|
"narHash": "sha256-g9puJaILRTb9ttlLQ7IehpV7Wcy0n+vs8LOFu6ylQcM=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8",
|
"rev": "5ce6597eca7d7b518c03ecda57d45f9404b5e060",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -339,93 +16,28 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765911976,
|
|
||||||
"narHash": "sha256-t3T/xm8zstHRLx+pIHxVpQTiySbKqcQbK+r+01XVKc0=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "git-hooks.nix",
|
|
||||||
"rev": "b68b780b69702a090c8bb1b973bab13756cc7a27",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "git-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"aquamarine": "aquamarine",
|
|
||||||
"hyprcursor": "hyprcursor",
|
|
||||||
"hyprgraphics": "hyprgraphics",
|
|
||||||
"hyprland-guiutils": "hyprland-guiutils",
|
|
||||||
"hyprland-protocols": "hyprland-protocols",
|
|
||||||
"hyprlang": "hyprlang",
|
|
||||||
"hyprutils": "hyprutils",
|
|
||||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
|
||||||
"hyprwire": "hyprwire",
|
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"pre-commit-hooks": "pre-commit-hooks",
|
"wlroots": "wlroots"
|
||||||
"systems": "systems",
|
|
||||||
"xdph": "xdph"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"wlroots": {
|
||||||
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689347949,
|
"host": "gitlab.freedesktop.org",
|
||||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
"lastModified": 1653658290,
|
||||||
"owner": "nix-systems",
|
"narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
|
||||||
"repo": "default-linux",
|
"owner": "wlroots",
|
||||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
"repo": "wlroots",
|
||||||
"type": "github"
|
"rev": "75d31509db8c28e8379fe9570118ef8c82284581",
|
||||||
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-systems",
|
"host": "gitlab.freedesktop.org",
|
||||||
"repo": "default-linux",
|
"owner": "wlroots",
|
||||||
"type": "github"
|
"repo": "wlroots",
|
||||||
}
|
"type": "gitlab"
|
||||||
},
|
|
||||||
"xdph": {
|
|
||||||
"inputs": {
|
|
||||||
"hyprland-protocols": [
|
|
||||||
"hyprland-protocols"
|
|
||||||
],
|
|
||||||
"hyprlang": [
|
|
||||||
"hyprlang"
|
|
||||||
],
|
|
||||||
"hyprutils": [
|
|
||||||
"hyprutils"
|
|
||||||
],
|
|
||||||
"hyprwayland-scanner": [
|
|
||||||
"hyprwayland-scanner"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1761431178,
|
|
||||||
"narHash": "sha256-xzjC1CV3+wpUQKNF+GnadnkeGUCJX+vgaWIZsnz9tzI=",
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
|
||||||
"rev": "4b8801228ff958d028f588f0c2b911dbf32297f9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hyprwm",
|
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
208
flake.nix
|
|
@ -3,193 +3,53 @@
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
wlroots = {
|
||||||
# <https://github.com/nix-systems/nix-systems>
|
url = "gitlab:wlroots/wlroots?host=gitlab.freedesktop.org";
|
||||||
systems.url = "github:nix-systems/default-linux";
|
flake = false;
|
||||||
|
|
||||||
aquamarine = {
|
|
||||||
url = "github:hyprwm/aquamarine";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprcursor = {
|
|
||||||
url = "github:hyprwm/hyprcursor";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.hyprlang.follows = "hyprlang";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprgraphics = {
|
|
||||||
url = "github:hyprwm/hyprgraphics";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprland-protocols = {
|
|
||||||
url = "github:hyprwm/hyprland-protocols";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprland-guiutils = {
|
|
||||||
url = "github:hyprwm/hyprland-guiutils";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.aquamarine.follows = "aquamarine";
|
|
||||||
inputs.hyprgraphics.follows = "hyprgraphics";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
inputs.hyprlang.follows = "hyprlang";
|
|
||||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprlang = {
|
|
||||||
url = "github:hyprwm/hyprlang";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprutils = {
|
|
||||||
url = "github:hyprwm/hyprutils";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprwayland-scanner = {
|
|
||||||
url = "github:hyprwm/hyprwayland-scanner";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprwire = {
|
|
||||||
url = "github:hyprwm/hyprwire";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
inputs.systems.follows = "systems";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
};
|
|
||||||
|
|
||||||
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";
|
|
||||||
inputs.hyprutils.follows = "hyprutils";
|
|
||||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
|
||||||
};
|
|
||||||
|
|
||||||
pre-commit-hooks = {
|
|
||||||
url = "github:cachix/git-hooks.nix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs @ {
|
outputs = inputs @ {
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
systems,
|
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
eachSystem = lib.genAttrs (import systems);
|
genSystems = lib.genAttrs [
|
||||||
pkgsFor = eachSystem (system:
|
"x86_64-linux"
|
||||||
import nixpkgs {
|
];
|
||||||
localSystem = system;
|
pkgsFor = nixpkgs.legacyPackages;
|
||||||
overlays = with self.overlays; [
|
# https://github.com/NixOS/rfcs/pull/107
|
||||||
hyprland-packages
|
mkVersion = longDate:
|
||||||
hyprland-extras
|
lib.concatStrings [
|
||||||
];
|
"0.pre"
|
||||||
});
|
"+date="
|
||||||
pkgsCrossFor = eachSystem (system: crossSystem:
|
(lib.concatStringsSep "-" [
|
||||||
import nixpkgs {
|
(__substring 0 4 longDate)
|
||||||
localSystem = system;
|
(__substring 4 2 longDate)
|
||||||
inherit crossSystem;
|
(__substring 6 2 longDate)
|
||||||
overlays = with self.overlays; [
|
])
|
||||||
hyprland-packages
|
];
|
||||||
hyprland-extras
|
|
||||||
];
|
|
||||||
});
|
|
||||||
pkgsDebugFor = eachSystem (system:
|
|
||||||
import nixpkgs {
|
|
||||||
localSystem = system;
|
|
||||||
overlays = with self.overlays; [
|
|
||||||
hyprland-debug
|
|
||||||
];
|
|
||||||
});
|
|
||||||
pkgsDebugCrossFor = eachSystem (system: crossSystem:
|
|
||||||
import nixpkgs {
|
|
||||||
localSystem = system;
|
|
||||||
inherit crossSystem;
|
|
||||||
overlays = with self.overlays; [
|
|
||||||
hyprland-debug
|
|
||||||
];
|
|
||||||
});
|
|
||||||
in {
|
in {
|
||||||
overlays = import ./nix/overlays.nix {inherit self lib inputs;};
|
packages = genSystems (system: {
|
||||||
|
wlroots = pkgsFor.${system}.wlroots.overrideAttrs (prev: {
|
||||||
checks = eachSystem (system:
|
version = mkVersion inputs.wlroots.lastModifiedDate;
|
||||||
(lib.filterAttrs
|
src = inputs.wlroots;
|
||||||
(n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n))
|
});
|
||||||
self.packages.${system})
|
default = pkgsFor.${system}.callPackage ./default.nix {
|
||||||
// {
|
version = mkVersion self.lastModifiedDate;
|
||||||
inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
|
inherit (self.packages.${system}) wlroots;
|
||||||
pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
|
};
|
||||||
src = ./.;
|
|
||||||
hooks = {
|
|
||||||
hyprland-treewide-formatter = {
|
|
||||||
enable = true;
|
|
||||||
entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter";
|
|
||||||
pass_filenames = false;
|
|
||||||
excludes = ["subprojects"];
|
|
||||||
always_run = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// (import ./nix/tests inputs pkgsFor.${system}));
|
|
||||||
|
|
||||||
packages = eachSystem (system: {
|
|
||||||
default = self.packages.${system}.hyprland;
|
|
||||||
inherit
|
|
||||||
(pkgsFor.${system})
|
|
||||||
# hyprland-packages
|
|
||||||
hyprland
|
|
||||||
hyprland-unwrapped
|
|
||||||
hyprland-with-tests
|
|
||||||
# hyprland-extras
|
|
||||||
xdg-desktop-portal-hyprland
|
|
||||||
;
|
|
||||||
inherit (pkgsDebugFor.${system}) hyprland-debug;
|
|
||||||
hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland;
|
|
||||||
hyprland-debug-cross = (pkgsDebugCrossFor.${system} "aarch64-linux").hyprland-debug;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
devShells = eachSystem (system: {
|
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||||
default =
|
|
||||||
pkgsFor.${system}.mkShell.override {
|
|
||||||
inherit (self.packages.${system}.default) stdenv;
|
|
||||||
} {
|
|
||||||
name = "hyprland-shell";
|
|
||||||
hardeningDisable = ["fortify"];
|
|
||||||
inputsFrom = [pkgsFor.${system}.hyprland];
|
|
||||||
packages = [pkgsFor.${system}.clang-tools];
|
|
||||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {});
|
nixosModules.default = import ./module.nix self;
|
||||||
|
|
||||||
nixosModules.default = import ./nix/module.nix inputs;
|
# Deprecated
|
||||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
overlays.default = _: prev: {
|
||||||
|
hyprland = self.packages.${prev.system}.default;
|
||||||
# Hydra build jobs
|
};
|
||||||
# Recent versions of Hydra can aggregate jobsets from 'hydraJobs' instead of a release.nix
|
overlay = self.overlays.default;
|
||||||
# or similar. Remember to filter large or incompatible attributes here. More eval jobs can
|
|
||||||
# be added by merging, e.g., self.packages // self.devShells.
|
|
||||||
hydraJobs = self.packages;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.19)
|
|
||||||
|
|
||||||
project(
|
|
||||||
hyprctl
|
|
||||||
DESCRIPTION "Control utility for Hyprland"
|
|
||||||
)
|
|
||||||
|
|
||||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4 hyprwire re2)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE HYPRCTL_SRCFILES CONFIGURE_DEPENDS "src/*.cpp" "hw-protocols/*.cpp" "include/*.hpp")
|
|
||||||
|
|
||||||
add_executable(hyprctl ${HYPRCTL_SRCFILES})
|
|
||||||
|
|
||||||
target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps)
|
|
||||||
target_include_directories(hyprctl PRIVATE "hw-protocols")
|
|
||||||
|
|
||||||
# Hyprwire
|
|
||||||
|
|
||||||
function(hyprprotocol protoPath protoName)
|
|
||||||
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${protoPath})
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/hw-protocols/${protoName}-client.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hw-protocols/${protoName}-client.hpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hw-protocols/${protoName}-spec.hpp
|
|
||||||
COMMAND hyprwire-scanner --client ${path}/${protoName}.xml
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hw-protocols/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_sources(hyprctl PRIVATE hw-protocols/${protoName}-client.cpp
|
|
||||||
hw-protocols/${protoName}-client.hpp
|
|
||||||
hw-protocols/${protoName}-spec.hpp)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
hyprprotocol(hw-protocols hyprpaper_core)
|
|
||||||
|
|
||||||
# binary
|
|
||||||
install(TARGETS hyprctl)
|
|
||||||
|
|
||||||
# shell completions
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.bash
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions
|
|
||||||
RENAME hyprctl)
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.fish
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/fish/vendor_completions.d)
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.zsh
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions
|
|
||||||
RENAME _hyprctl)
|
|
||||||
4
hyprctl/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
clean:
|
||||||
|
rm -rf ./hyprctl ./hyprctl
|
||||||
|
all:
|
||||||
|
g++ -std=c++20 ./main.cpp -o ./hyprctl
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<protocol name="hyprpaper_core" version="1">
|
|
||||||
<copyright>
|
|
||||||
BSD 3-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2025, Hypr Development
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
</copyright>
|
|
||||||
|
|
||||||
<object name="hyprpaper_core_manager" version="1">
|
|
||||||
<description summary="manager object">
|
|
||||||
This is the core manager object for hyprpaper operations
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<c2s name="get_wallpaper_object">
|
|
||||||
<description summary="Get a wallpaper object">
|
|
||||||
Creates a wallpaper object
|
|
||||||
</description>
|
|
||||||
<returns iface="hyprpaper_wallpaper"/>
|
|
||||||
</c2s>
|
|
||||||
|
|
||||||
<s2c name="add_monitor">
|
|
||||||
<description summary="New monitor added">
|
|
||||||
Emitted when a new monitor is added.
|
|
||||||
</description>
|
|
||||||
<arg name="monitor_name" type="varchar" summary="the monitor's name"/>
|
|
||||||
</s2c>
|
|
||||||
|
|
||||||
<s2c name="remove_monitor">
|
|
||||||
<description summary="A monitor was removed">
|
|
||||||
Emitted when a monitor is removed.
|
|
||||||
</description>
|
|
||||||
<arg name="monitor_name" type="varchar" summary="the monitor's name"/>
|
|
||||||
</s2c>
|
|
||||||
|
|
||||||
<c2s name="destroy" destructor="true">
|
|
||||||
<description summary="Destroy this object">
|
|
||||||
Destroys this object. Children remain alive until destroyed.
|
|
||||||
</description>
|
|
||||||
</c2s>
|
|
||||||
</object>
|
|
||||||
|
|
||||||
<enum name="wallpaper_fit_mode">
|
|
||||||
<value idx="0" name="stretch"/>
|
|
||||||
<value idx="1" name="cover"/>
|
|
||||||
<value idx="2" name="contain"/>
|
|
||||||
<value idx="3" name="tile"/>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<enum name="wallpaper_errors">
|
|
||||||
<value idx="0" name="inert_wallpaper_object" description="attempted to use an inert wallpaper object"/>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<enum name="applying_error">
|
|
||||||
<value idx="0" name="invalid_path" description="path provided was invalid"/>
|
|
||||||
<value idx="1" name="invalid_monitor" description="monitor provided was invalid"/>
|
|
||||||
<value idx="2" name="unknown_error" description="unknown error"/>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<object name="hyprpaper_wallpaper" version="1">
|
|
||||||
<description summary="wallpaper object">
|
|
||||||
This is an object describing a wallpaper
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<c2s name="path">
|
|
||||||
<description summary="Set a path">
|
|
||||||
Set a file path for the wallpaper. This has to be an absolute path from the fs root.
|
|
||||||
This is required.
|
|
||||||
</description>
|
|
||||||
<arg name="wallpaper" type="varchar" summary="path"/>
|
|
||||||
</c2s>
|
|
||||||
|
|
||||||
<c2s name="fit_mode">
|
|
||||||
<description summary="Set a fit mode">
|
|
||||||
Set a fit mode for the wallpaper. This is set to cover by default.
|
|
||||||
</description>
|
|
||||||
<arg name="fit_mode" type="enum" interface="wallpaper_fit_mode" summary="path"/>
|
|
||||||
</c2s>
|
|
||||||
|
|
||||||
<c2s name="monitor_name">
|
|
||||||
<description summary="Set the monitor name">
|
|
||||||
Set a monitor for the wallpaper. Setting this to empty (or not setting at all) will
|
|
||||||
treat this as a wildcard fallback.
|
|
||||||
|
|
||||||
See hyprpaper_core_manager.add_monitor and hyprpaper_core_manager.remove_monitor
|
|
||||||
for tracking monitor names.
|
|
||||||
</description>
|
|
||||||
<arg name="monitor_name" type="varchar" summary="monitor name"/>
|
|
||||||
</c2s>
|
|
||||||
|
|
||||||
<c2s name="apply">
|
|
||||||
<description summary="Apply this wallpaper">
|
|
||||||
Applies this object's state to the wallpaper state. Will emit .success on success,
|
|
||||||
and .failed on failure.
|
|
||||||
|
|
||||||
This object becomes inert after .succeess or .failed, the only valid operation
|
|
||||||
is to destroy it afterwards.
|
|
||||||
</description>
|
|
||||||
</c2s>
|
|
||||||
|
|
||||||
<s2c name="success">
|
|
||||||
<description summary="Operation succeeded">
|
|
||||||
Wallpaper was applied successfully.
|
|
||||||
</description>
|
|
||||||
</s2c>
|
|
||||||
|
|
||||||
<s2c name="failed">
|
|
||||||
<description summary="Operation failed">
|
|
||||||
Wallpaper was not applied. See the error field for more information.
|
|
||||||
</description>
|
|
||||||
<arg name="error" type="enum" interface="hyprpaper_wallpaper_application_error" summary="path"/>
|
|
||||||
</s2c>
|
|
||||||
|
|
||||||
<c2s name="destroy" destructor="true">
|
|
||||||
<description summary="Destroy this object">
|
|
||||||
Destroys this object.
|
|
||||||
</description>
|
|
||||||
</c2s>
|
|
||||||
</object>
|
|
||||||
</protocol>
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
_hyprctl_cmd_1 () {
|
|
||||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_3 () {
|
|
||||||
hyprctl clients | awk '/class/{print $2}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_2 () {
|
|
||||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_0 () {
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl () {
|
|
||||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
|
||||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local words cword
|
|
||||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
|
||||||
|
|
||||||
declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize sendkeystate)
|
|
||||||
declare -A literal_transitions
|
|
||||||
literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)"
|
|
||||||
literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)"
|
|
||||||
literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)"
|
|
||||||
literal_transitions[6]="([126]=2)"
|
|
||||||
literal_transitions[10]="([56]=2)"
|
|
||||||
literal_transitions[11]="([9]=2)"
|
|
||||||
literal_transitions[12]="([14]=19 [80]=22)"
|
|
||||||
literal_transitions[13]="([142]=2)"
|
|
||||||
literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)"
|
|
||||||
literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)"
|
|
||||||
literal_transitions[16]="([40]=2 [44]=2)"
|
|
||||||
literal_transitions[17]="([7]=23)"
|
|
||||||
literal_transitions[18]="([31]=2 [149]=2)"
|
|
||||||
literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)"
|
|
||||||
literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)"
|
|
||||||
literal_transitions[23]="([57]=21 [110]=21)"
|
|
||||||
declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1)
|
|
||||||
declare -A subword_transitions
|
|
||||||
|
|
||||||
local state=0
|
|
||||||
local word_index=1
|
|
||||||
while [[ $word_index -lt $cword ]]; do
|
|
||||||
local word=${words[$word_index]}
|
|
||||||
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
declare -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
local word_matched=0
|
|
||||||
for literal_id in $(seq 0 $((${#literals[@]} - 1))); do
|
|
||||||
if [[ ${literals[$literal_id]} = "$word" ]]; then
|
|
||||||
if [[ -v "state_transitions[$literal_id]" ]]; then
|
|
||||||
state=${state_transitions[$literal_id]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
word_matched=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ $word_matched -ne 0 ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v "match_anything_transitions[$state]" ]]; then
|
|
||||||
state=${match_anything_transitions[$state]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
local -a matches=()
|
|
||||||
|
|
||||||
local prefix="${words[$cword]}"
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local state_transitions_initializer=${literal_transitions[$state]}
|
|
||||||
declare -A state_transitions
|
|
||||||
eval "state_transitions=$state_transitions_initializer"
|
|
||||||
|
|
||||||
for literal_id in "${!state_transitions[@]}"; do
|
|
||||||
local literal="${literals[$literal_id]}"
|
|
||||||
if [[ $literal = "${prefix}"* ]]; then
|
|
||||||
matches+=("$literal ")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
declare -A commands
|
|
||||||
commands=([7]=0 [22]=1 [8]=3 [5]=2)
|
|
||||||
if [[ -v "commands[$state]" ]]; then
|
|
||||||
local command_id=${commands[$state]}
|
|
||||||
local completions=()
|
|
||||||
readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
|
||||||
for item in "${completions[@]}"; do
|
|
||||||
if [[ $item = "${prefix}"* ]]; then
|
|
||||||
matches+=("$item")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
local shortest_suffix="$prefix"
|
|
||||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
|
||||||
local char="${COMP_WORDBREAKS:$i:1}"
|
|
||||||
local candidate=${prefix##*$char}
|
|
||||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
|
||||||
shortest_suffix=$candidate
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
local superfluous_prefix=""
|
|
||||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
|
||||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
|
||||||
fi
|
|
||||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -o nospace -F _hyprctl hyprctl
|
|
||||||
|
|
@ -1,235 +0,0 @@
|
||||||
function _hyprctl_2
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprctl_4
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprctl clients | awk '/class/{print $2}'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprctl_3
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprctl_1
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprctl
|
|
||||||
set COMP_LINE (commandline --cut-at-cursor)
|
|
||||||
|
|
||||||
set COMP_WORDS
|
|
||||||
echo $COMP_LINE | read --tokenize --array COMP_WORDS
|
|
||||||
if string match --quiet --regex '.*\s$' $COMP_LINE
|
|
||||||
set COMP_CWORD (math (count $COMP_WORDS) + 1)
|
|
||||||
else
|
|
||||||
set COMP_CWORD (count $COMP_WORDS)
|
|
||||||
end
|
|
||||||
|
|
||||||
set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize" "sendkeystate"
|
|
||||||
|
|
||||||
set descriptions
|
|
||||||
set descriptions[1] "Resize the active window"
|
|
||||||
set descriptions[2] "Fullscreen"
|
|
||||||
set descriptions[3] "Switch to the next window in a group"
|
|
||||||
set descriptions[4] "Refresh state after issuing the command"
|
|
||||||
set descriptions[5] "Move the active window into a group"
|
|
||||||
set descriptions[7] "CONFUSED"
|
|
||||||
set descriptions[9] "Print system info"
|
|
||||||
set descriptions[11] "List all layouts available (including plugin ones)"
|
|
||||||
set descriptions[12] "Set a property of a window"
|
|
||||||
set descriptions[14] "Set the xkb layout index for a keyboard"
|
|
||||||
set descriptions[16] "Prohibit the active window from becoming or being inserted into group"
|
|
||||||
set descriptions[19] "Execute a shell command"
|
|
||||||
set descriptions[20] "Set the cursor theme and reloads the cursor manager"
|
|
||||||
set descriptions[22] "Focus the urgent window or the last window"
|
|
||||||
set descriptions[23] "Get the list of defined workspace rules"
|
|
||||||
set descriptions[24] "Move the active workspace to a monitor"
|
|
||||||
set descriptions[25] "Move window doesn't switch to the workspace"
|
|
||||||
set descriptions[26] "Interact with hyprpaper if present"
|
|
||||||
set descriptions[29] "Swap the active window with the next or previous in a group"
|
|
||||||
set descriptions[30] "Move the cursor to the corner of the active window"
|
|
||||||
set descriptions[31] "Move a selected window"
|
|
||||||
set descriptions[33] "Move the active window in a direction or to a monitor"
|
|
||||||
set descriptions[34] "Lists all global shortcuts"
|
|
||||||
set descriptions[35] "List all windows with their properties"
|
|
||||||
set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock"
|
|
||||||
set descriptions[38] "Print the current random splash"
|
|
||||||
set descriptions[39] "Execute a raw shell command"
|
|
||||||
set descriptions[40] "List active outputs with their properties"
|
|
||||||
set descriptions[43] "Disable output"
|
|
||||||
set descriptions[44] "Gets the current config info about animations and beziers"
|
|
||||||
set descriptions[47] "Change the split ratio"
|
|
||||||
set descriptions[48] "Move the active window"
|
|
||||||
set descriptions[49] "Pass the key to a specified window"
|
|
||||||
set descriptions[50] "Swap the focused window with the next window"
|
|
||||||
set descriptions[51] "List all connected keyboards and mice"
|
|
||||||
set descriptions[52] "List the layers"
|
|
||||||
set descriptions[54] "Lock the focused group"
|
|
||||||
set descriptions[55] "OK"
|
|
||||||
set descriptions[56] "Move a workspace to a monitor"
|
|
||||||
set descriptions[58] "Specify the Hyprland instance"
|
|
||||||
set descriptions[59] "Disable output"
|
|
||||||
set descriptions[61] "Pin a window"
|
|
||||||
set descriptions[62] "WARNING"
|
|
||||||
set descriptions[63] "INFO"
|
|
||||||
set descriptions[66] "Set the current window's floating state to true"
|
|
||||||
set descriptions[69] "On shortcut X sends shortcut Y to a specified window"
|
|
||||||
set descriptions[70] "List all workspaces with their properties"
|
|
||||||
set descriptions[71] "Focus the next window on a workspace"
|
|
||||||
set descriptions[72] "Modify the window stack order of the active or specified window"
|
|
||||||
set descriptions[73] "Toggle the current active window into a group"
|
|
||||||
set descriptions[74] "Lock the groups"
|
|
||||||
set descriptions[76] "Set all monitors' DPMS status"
|
|
||||||
set descriptions[77] "Switch focus from current to previously focused window"
|
|
||||||
set descriptions[78] "No Icon"
|
|
||||||
set descriptions[79] "Execute a batch of commands separated by ;"
|
|
||||||
set descriptions[80] "Send a notification using the built-in Hyprland notification system"
|
|
||||||
set descriptions[82] "List all running Hyprland instances and their info"
|
|
||||||
set descriptions[83] "Maximize no fullscreen"
|
|
||||||
set descriptions[84] "Maximize and fullscreen"
|
|
||||||
set descriptions[85] "Move the active window out of a group"
|
|
||||||
set descriptions[86] "Close the active window"
|
|
||||||
set descriptions[87] "HINT"
|
|
||||||
set descriptions[88] "Move the focused window to a workspace"
|
|
||||||
set descriptions[89] "Move the cursor to a specified position"
|
|
||||||
set descriptions[90] "List all current config parsing errors"
|
|
||||||
set descriptions[91] "Close a specified window"
|
|
||||||
set descriptions[92] "Swap the active window with another window"
|
|
||||||
set descriptions[93] "Apply a tag to the window"
|
|
||||||
set descriptions[94] "Force the renderer to reload all resources and outputs"
|
|
||||||
set descriptions[95] "Center the active window"
|
|
||||||
set descriptions[97] "Focus the first window matching"
|
|
||||||
set descriptions[98] "Set the hyprctl error string"
|
|
||||||
set descriptions[101] "List all registered binds"
|
|
||||||
set descriptions[102] "Print the Hyprland version: flags, commit and branch of build"
|
|
||||||
set descriptions[103] "Prints the help message"
|
|
||||||
set descriptions[104] "Toggle a special workspace on/off"
|
|
||||||
set descriptions[105] "Toggle the focused window's fullscreen state"
|
|
||||||
set descriptions[107] "None"
|
|
||||||
set descriptions[108] "Issue a keyword to call a config keyword dynamically"
|
|
||||||
set descriptions[109] "Toggle the current window to always be opaque"
|
|
||||||
set descriptions[110] "ERROR"
|
|
||||||
set descriptions[111] "Specify the Hyprland instance"
|
|
||||||
set descriptions[112] "Toggle the current window's floating state"
|
|
||||||
set descriptions[113] "Rename a workspace"
|
|
||||||
set descriptions[115] "Get the active workspace name and its properties"
|
|
||||||
set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it"
|
|
||||||
set descriptions[119] "Allows adding/removing fake outputs to a specific backend"
|
|
||||||
set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
|
||||||
set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg"
|
|
||||||
set descriptions[122] "Force reload the config"
|
|
||||||
set descriptions[124] "Output in JSON format"
|
|
||||||
set descriptions[125] "Emits a custom event to socket2"
|
|
||||||
set descriptions[126] "Prints the help message"
|
|
||||||
set descriptions[128] "Current"
|
|
||||||
set descriptions[129] "Get the active window name and its properties"
|
|
||||||
set descriptions[131] "Dismiss all or up to amount of notifications"
|
|
||||||
set descriptions[132] "Focus a monitor"
|
|
||||||
set descriptions[133] "Move the focus in a direction"
|
|
||||||
set descriptions[134] "Interact with a plugin"
|
|
||||||
set descriptions[135] "Exit the compositor with no questions asked"
|
|
||||||
set descriptions[136] "Change the workspace"
|
|
||||||
set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client"
|
|
||||||
set descriptions[138] "Get the config option status (values)"
|
|
||||||
set descriptions[141] "List all decorations and their info"
|
|
||||||
set descriptions[142] "Set the current window's floating state to false"
|
|
||||||
set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
|
||||||
set descriptions[145] "Resize a selected window"
|
|
||||||
set descriptions[146] "Toggle the focused window's internal fullscreen state"
|
|
||||||
set descriptions[147] "Print tail of the log"
|
|
||||||
set descriptions[148] "Swap the active workspaces between two monitors"
|
|
||||||
set descriptions[149] "Change the current mapping group"
|
|
||||||
set descriptions[151] "Behave as moveintogroup"
|
|
||||||
set descriptions[152] "Get the current cursor pos in global layout coordinates"
|
|
||||||
set descriptions[154] "Focus the requested workspace"
|
|
||||||
|
|
||||||
set literal_transitions
|
|
||||||
set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13"
|
|
||||||
set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3"
|
|
||||||
set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17"
|
|
||||||
set literal_transitions[7] "set inputs 127; set tos 3"
|
|
||||||
set literal_transitions[11] "set inputs 57; set tos 3"
|
|
||||||
set literal_transitions[12] "set inputs 10; set tos 3"
|
|
||||||
set literal_transitions[13] "set inputs 15 81; set tos 20 23"
|
|
||||||
set literal_transitions[14] "set inputs 143; set tos 3"
|
|
||||||
set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
|
||||||
set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5"
|
|
||||||
set literal_transitions[17] "set inputs 41 45; set tos 3 3"
|
|
||||||
set literal_transitions[18] "set inputs 8; set tos 24"
|
|
||||||
set literal_transitions[19] "set inputs 32 150; set tos 3 3"
|
|
||||||
set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3"
|
|
||||||
set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3"
|
|
||||||
set literal_transitions[24] "set inputs 58 111; set tos 22 22"
|
|
||||||
|
|
||||||
set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2
|
|
||||||
set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2
|
|
||||||
|
|
||||||
set state 1
|
|
||||||
set word_index 2
|
|
||||||
while test $word_index -lt $COMP_CWORD
|
|
||||||
set -- word $COMP_WORDS[$word_index]
|
|
||||||
|
|
||||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
eval $literal_transitions[$state]
|
|
||||||
|
|
||||||
if contains -- $word $literals
|
|
||||||
set literal_matched 0
|
|
||||||
for literal_id in (seq 1 (count $literals))
|
|
||||||
if test $literals[$literal_id] = $word
|
|
||||||
set index (contains --index -- $literal_id $inputs)
|
|
||||||
set state $tos[$index]
|
|
||||||
set word_index (math $word_index + 1)
|
|
||||||
set literal_matched 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if test $literal_matched -ne 0
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
|
||||||
set index (contains --index -- $state $match_anything_transitions_from)
|
|
||||||
set state $match_anything_transitions_to[$index]
|
|
||||||
set word_index (math $word_index + 1)
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
eval $literal_transitions[$state]
|
|
||||||
for literal_id in $inputs
|
|
||||||
if test -n $descriptions[$literal_id]
|
|
||||||
printf '%s\t%s\n' $literals[$literal_id] $descriptions[$literal_id]
|
|
||||||
else
|
|
||||||
printf '%s\n' $literals[$literal_id]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
set command_states 8 23 9 6
|
|
||||||
set command_ids 1 2 4 3
|
|
||||||
if contains $state $command_states
|
|
||||||
set index (contains --index $state $command_states)
|
|
||||||
set function_id $command_ids[$index]
|
|
||||||
set function_name _hyprctl_$function_id
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
|
||||||
end
|
|
||||||
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
complete --command hyprctl --no-files --arguments "(_hyprctl)"
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
# This is a file fed to complgen to generate bash/fish/zsh completions
|
|
||||||
# Repo: https://github.com/adaszko/complgen
|
|
||||||
# Generate completion scripts: "complgen aot --bash-script hyprctl.bash --fish-script hyprctl.fish --zsh-script hyprctl.zsh ./hyprctl.usage"
|
|
||||||
|
|
||||||
hyprctl [<OPTIONS>]... <ARGUMENTS>
|
|
||||||
|
|
||||||
<OPTIONS> ::= (-i | --instance) "Specify the Hyprland instance"
|
|
||||||
| (-j) "Output in JSON format"
|
|
||||||
| (-r) "Refresh state after issuing the command"
|
|
||||||
| (--batch) "Execute a batch of commands separated by ;"
|
|
||||||
| (-q | --quiet) "Disable output"
|
|
||||||
| (-h | --help) "Prints the help message"
|
|
||||||
;
|
|
||||||
|
|
||||||
<WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}};
|
|
||||||
|
|
||||||
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
|
||||||
|
|
||||||
<MONITORS> ::= {{{ hyprctl monitors | awk '/Monitor/{ print $2 }' }}};
|
|
||||||
|
|
||||||
<KEYBOARDS> ::= {{{ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' }}};
|
|
||||||
|
|
||||||
<NOTIFICATION_TYPES> ::= (0) "WARNING"
|
|
||||||
| (1) "INFO"
|
|
||||||
| (2) "HINT"
|
|
||||||
| (3) "ERROR"
|
|
||||||
| (4) "CONFUSED"
|
|
||||||
| (5) "OK"
|
|
||||||
| (-1) "No Icon"
|
|
||||||
;
|
|
||||||
|
|
||||||
<PROPS> ::= (animationstyle)
|
|
||||||
| (rounding <NUM>)
|
|
||||||
| (bordersize <NUM>)
|
|
||||||
| (forcenoblur (0 | 1))
|
|
||||||
| (forceopaque (0 | 1))
|
|
||||||
| (forceopaqueoverriden (0 | 1))
|
|
||||||
| (forceallowsinput (0 | 1))
|
|
||||||
| (forcenoanims (0 | 1))
|
|
||||||
| (forcenoborder (0 | 1))
|
|
||||||
| (forcenodim (0 | 1))
|
|
||||||
| (forcenoshadow (0 | 1))
|
|
||||||
| (nofocus (0 | 1))
|
|
||||||
| (windowdancecompat (0 | 1))
|
|
||||||
| (nomaxsize (0 | 1))
|
|
||||||
| (minsize)
|
|
||||||
| (maxsize)
|
|
||||||
| (dimaround (0 | 1))
|
|
||||||
| (keepaspectratio (0 | 1))
|
|
||||||
| (alphaoverride (0 | 1))
|
|
||||||
| (alpha)
|
|
||||||
| (alphainactiveoverride (0 | 1))
|
|
||||||
| (alphainactive)
|
|
||||||
| (alphafullscreenoverride (0 | 1))
|
|
||||||
| (alphafullscreen)
|
|
||||||
| (activebordercolor)
|
|
||||||
| (inactivebordercolor)
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
|
|
||||||
| (activeworkspace) "Get the active workspace name and its properties"
|
|
||||||
| (animations) "Gets the current config info about animations and beziers"
|
|
||||||
| (binds) "List all registered binds"
|
|
||||||
| (clients) "List all windows with their properties"
|
|
||||||
| (configerrors) "List all current config parsing errors"
|
|
||||||
| (cursorpos) "Get the current cursor pos in global layout coordinates"
|
|
||||||
| (decorations <WINDOWS>) "List all decorations and their info"
|
|
||||||
| (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
|
||||||
| (devices) "List all connected keyboards and mice"
|
|
||||||
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
|
|
||||||
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
|
|
||||||
| (getoption) "Get the config option status (values)"
|
|
||||||
| (globalshortcuts) "Lists all global shortcuts"
|
|
||||||
| (hyprpaper) "Interact with hyprpaper if present"
|
|
||||||
| (instances) "List all running Hyprland instances and their info"
|
|
||||||
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
|
|
||||||
| (kill) "Get into a kill mode, where you can kill an app by clicking on it"
|
|
||||||
| (layers) "List the layers"
|
|
||||||
| (layouts) "List all layouts available (including plugin ones)"
|
|
||||||
| (monitors [all]) "List active outputs with their properties"
|
|
||||||
| (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system"
|
|
||||||
| (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend"
|
|
||||||
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
|
|
||||||
| (reload [config-only]) "Force reload the config"
|
|
||||||
| (rollinglog [-f]) "Print tail of the log"
|
|
||||||
| (setcursor) "Set the cursor theme and reloads the cursor manager"
|
|
||||||
| (seterror [disable]) "Set the hyprctl error string"
|
|
||||||
| (setprop <PROPS>) "Set a property of a window"
|
|
||||||
| (splash) "Print the current random splash"
|
|
||||||
| (switchxkblayout <KEYBOARDS> (next | prev | <NUM>)) "Set the xkb layout index for a keyboard"
|
|
||||||
| (systeminfo) "Print system info"
|
|
||||||
| (version) "Print the Hyprland version: flags, commit and branch of build"
|
|
||||||
| (workspacerules) "Get the list of defined workspace rules"
|
|
||||||
| (workspaces) "List all workspaces with their properties"
|
|
||||||
;
|
|
||||||
|
|
||||||
<WINDOW_STATE> ::= (-1) "Current"
|
|
||||||
| (0) "None"
|
|
||||||
| (1) "Maximize no fullscreen"
|
|
||||||
| (2) "Fullscreen"
|
|
||||||
| (3) "Maximize and fullscreen"
|
|
||||||
;
|
|
||||||
|
|
||||||
<DISPATCHERS> ::= (exec) "Execute a shell command"
|
|
||||||
| (execr) "Execute a raw shell command"
|
|
||||||
| (pass) "Pass the key to a specified window"
|
|
||||||
| (sendshortcut) "On shortcut X sends shortcut Y to a specified window"
|
|
||||||
| (sendkeystate) "Send a key with specific state (down/repeat/up) to a specified window (window must keep focus for events to continue)"
|
|
||||||
| (killactive) "Close the active window"
|
|
||||||
| (closewindow) "Close a specified window"
|
|
||||||
| (workspace) "Change the workspace"
|
|
||||||
| (movetoworkspace) "Move the focused window to a workspace"
|
|
||||||
| (movetoworkspacesilent) "Move window doesn't switch to the workspace"
|
|
||||||
| (togglefloating) "Toggle the current window's floating state"
|
|
||||||
| (setfloating) "Set the current window's floating state to true"
|
|
||||||
| (settiled) "Set the current window's floating state to false"
|
|
||||||
| (fullscreen) "Toggle the focused window's fullscreen state"
|
|
||||||
| (fakefullscreen) "Toggle the focused window's internal fullscreen state"
|
|
||||||
| (fullscreenstate <WINDOW_STATE>) "Sets the focused window’s fullscreen mode and the one sent to the client"
|
|
||||||
| (dpms) "Set all monitors' DPMS status"
|
|
||||||
| (pin) "Pin a window"
|
|
||||||
| (movefocus) "Move the focus in a direction"
|
|
||||||
| (movewindow) "Move the active window in a direction or to a monitor"
|
|
||||||
| (swapwindow) "Swap the active window with another window"
|
|
||||||
| (centerwindow) "Center the active window"
|
|
||||||
| (resizeactive) "Resize the active window"
|
|
||||||
| (moveactive) "Move the active window"
|
|
||||||
| (resizewindowpixel) "Resize a selected window"
|
|
||||||
| (movewindowpixel) "Move a selected window"
|
|
||||||
| (cyclenext) "Focus the next window on a workspace"
|
|
||||||
| (swapnext) "Swap the focused window with the next window"
|
|
||||||
| (tagwindow) "Apply a tag to the window"
|
|
||||||
| (focuswindow) "Focus the first window matching"
|
|
||||||
| (focusmonitor) "Focus a monitor"
|
|
||||||
| (splitratio) "Change the split ratio"
|
|
||||||
| (toggleopaque) "Toggle the current window to always be opaque"
|
|
||||||
| (movecursortocorner) "Move the cursor to the corner of the active window"
|
|
||||||
| (movecursor) "Move the cursor to a specified position"
|
|
||||||
| (renameworkspace) "Rename a workspace"
|
|
||||||
| (exit) "Exit the compositor with no questions asked"
|
|
||||||
| (forcerendererreload) "Force the renderer to reload all resources and outputs"
|
|
||||||
| (movecurrentworkspacetomonitor) "Move the active workspace to a monitor"
|
|
||||||
| (focusworkspaceoncurrentmonitor) "Focus the requested workspace"
|
|
||||||
| (moveworkspacetomonitor) "Move a workspace to a monitor"
|
|
||||||
| (swapactiveworkspaces) "Swap the active workspaces between two monitors"
|
|
||||||
| (alterzorder) "Modify the window stack order of the active or specified window"
|
|
||||||
| (togglespecialworkspace) "Toggle a special workspace on/off"
|
|
||||||
| (focusurgentorlast) "Focus the urgent window or the last window"
|
|
||||||
| (togglegroup) "Toggle the current active window into a group"
|
|
||||||
| (changegroupactive) "Switch to the next window in a group"
|
|
||||||
| (focuscurrentorlast) "Switch focus from current to previously focused window"
|
|
||||||
| (lockgroups) "Lock the groups"
|
|
||||||
| (lockactivegroup) "Lock the focused group"
|
|
||||||
| (moveintogroup) "Move the active window into a group"
|
|
||||||
| (moveoutofgroup) "Move the active window out of a group"
|
|
||||||
| (movewindoworgroup) "Behave as moveintogroup"
|
|
||||||
| (movegroupwindow) "Swap the active window with the next or previous in a group"
|
|
||||||
| (denywindowfromgroup) "Prohibit the active window from becoming or being inserted into group"
|
|
||||||
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
|
|
||||||
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
|
|
||||||
| (submap) "Change the current mapping group"
|
|
||||||
| (event) "Emits a custom event to socket2"
|
|
||||||
;
|
|
||||||
|
|
@ -1,274 +0,0 @@
|
||||||
#compdef hyprctl
|
|
||||||
|
|
||||||
_hyprctl_cmd_1 () {
|
|
||||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_3 () {
|
|
||||||
hyprctl clients | awk '/class/{print $2}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_2 () {
|
|
||||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl_cmd_0 () {
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprctl () {
|
|
||||||
local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize" "sendkeystate")
|
|
||||||
|
|
||||||
local -A descriptions
|
|
||||||
descriptions[1]="Resize the active window"
|
|
||||||
descriptions[2]="Fullscreen"
|
|
||||||
descriptions[3]="Switch to the next window in a group"
|
|
||||||
descriptions[4]="Refresh state after issuing the command"
|
|
||||||
descriptions[5]="Move the active window into a group"
|
|
||||||
descriptions[7]="CONFUSED"
|
|
||||||
descriptions[9]="Print system info"
|
|
||||||
descriptions[11]="List all layouts available (including plugin ones)"
|
|
||||||
descriptions[12]="Set a property of a window"
|
|
||||||
descriptions[14]="Set the xkb layout index for a keyboard"
|
|
||||||
descriptions[16]="Prohibit the active window from becoming or being inserted into group"
|
|
||||||
descriptions[19]="Execute a shell command"
|
|
||||||
descriptions[20]="Set the cursor theme and reloads the cursor manager"
|
|
||||||
descriptions[22]="Focus the urgent window or the last window"
|
|
||||||
descriptions[23]="Get the list of defined workspace rules"
|
|
||||||
descriptions[24]="Move the active workspace to a monitor"
|
|
||||||
descriptions[25]="Move window doesn't switch to the workspace"
|
|
||||||
descriptions[26]="Interact with hyprpaper if present"
|
|
||||||
descriptions[29]="Swap the active window with the next or previous in a group"
|
|
||||||
descriptions[30]="Move the cursor to the corner of the active window"
|
|
||||||
descriptions[31]="Move a selected window"
|
|
||||||
descriptions[33]="Move the active window in a direction or to a monitor"
|
|
||||||
descriptions[34]="Lists all global shortcuts"
|
|
||||||
descriptions[35]="List all windows with their properties"
|
|
||||||
descriptions[37]="Temporarily enable or disable binds:ignore_group_lock"
|
|
||||||
descriptions[38]="Print the current random splash"
|
|
||||||
descriptions[39]="Execute a raw shell command"
|
|
||||||
descriptions[40]="List active outputs with their properties"
|
|
||||||
descriptions[43]="Disable output"
|
|
||||||
descriptions[44]="Gets the current config info about animations and beziers"
|
|
||||||
descriptions[47]="Change the split ratio"
|
|
||||||
descriptions[48]="Move the active window"
|
|
||||||
descriptions[49]="Pass the key to a specified window"
|
|
||||||
descriptions[50]="Swap the focused window with the next window"
|
|
||||||
descriptions[51]="List all connected keyboards and mice"
|
|
||||||
descriptions[52]="List the layers"
|
|
||||||
descriptions[54]="Lock the focused group"
|
|
||||||
descriptions[55]="OK"
|
|
||||||
descriptions[56]="Move a workspace to a monitor"
|
|
||||||
descriptions[58]="Specify the Hyprland instance"
|
|
||||||
descriptions[59]="Disable output"
|
|
||||||
descriptions[61]="Pin a window"
|
|
||||||
descriptions[62]="WARNING"
|
|
||||||
descriptions[63]="INFO"
|
|
||||||
descriptions[66]="Set the current window's floating state to true"
|
|
||||||
descriptions[69]="On shortcut X sends shortcut Y to a specified window"
|
|
||||||
descriptions[70]="List all workspaces with their properties"
|
|
||||||
descriptions[71]="Focus the next window on a workspace"
|
|
||||||
descriptions[72]="Modify the window stack order of the active or specified window"
|
|
||||||
descriptions[73]="Toggle the current active window into a group"
|
|
||||||
descriptions[74]="Lock the groups"
|
|
||||||
descriptions[76]="Set all monitors' DPMS status"
|
|
||||||
descriptions[77]="Switch focus from current to previously focused window"
|
|
||||||
descriptions[78]="No Icon"
|
|
||||||
descriptions[79]="Execute a batch of commands separated by ;"
|
|
||||||
descriptions[80]="Send a notification using the built-in Hyprland notification system"
|
|
||||||
descriptions[82]="List all running Hyprland instances and their info"
|
|
||||||
descriptions[83]="Maximize no fullscreen"
|
|
||||||
descriptions[84]="Maximize and fullscreen"
|
|
||||||
descriptions[85]="Move the active window out of a group"
|
|
||||||
descriptions[86]="Close the active window"
|
|
||||||
descriptions[87]="HINT"
|
|
||||||
descriptions[88]="Move the focused window to a workspace"
|
|
||||||
descriptions[89]="Move the cursor to a specified position"
|
|
||||||
descriptions[90]="List all current config parsing errors"
|
|
||||||
descriptions[91]="Close a specified window"
|
|
||||||
descriptions[92]="Swap the active window with another window"
|
|
||||||
descriptions[93]="Apply a tag to the window"
|
|
||||||
descriptions[94]="Force the renderer to reload all resources and outputs"
|
|
||||||
descriptions[95]="Center the active window"
|
|
||||||
descriptions[97]="Focus the first window matching"
|
|
||||||
descriptions[98]="Set the hyprctl error string"
|
|
||||||
descriptions[101]="List all registered binds"
|
|
||||||
descriptions[102]="Print the Hyprland version: flags, commit and branch of build"
|
|
||||||
descriptions[103]="Prints the help message"
|
|
||||||
descriptions[104]="Toggle a special workspace on/off"
|
|
||||||
descriptions[105]="Toggle the focused window's fullscreen state"
|
|
||||||
descriptions[107]="None"
|
|
||||||
descriptions[108]="Issue a keyword to call a config keyword dynamically"
|
|
||||||
descriptions[109]="Toggle the current window to always be opaque"
|
|
||||||
descriptions[110]="ERROR"
|
|
||||||
descriptions[111]="Specify the Hyprland instance"
|
|
||||||
descriptions[112]="Toggle the current window's floating state"
|
|
||||||
descriptions[113]="Rename a workspace"
|
|
||||||
descriptions[115]="Get the active workspace name and its properties"
|
|
||||||
descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it"
|
|
||||||
descriptions[119]="Allows adding/removing fake outputs to a specific backend"
|
|
||||||
descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
|
||||||
descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg"
|
|
||||||
descriptions[122]="Force reload the config"
|
|
||||||
descriptions[124]="Output in JSON format"
|
|
||||||
descriptions[125]="Emits a custom event to socket2"
|
|
||||||
descriptions[126]="Prints the help message"
|
|
||||||
descriptions[128]="Current"
|
|
||||||
descriptions[129]="Get the active window name and its properties"
|
|
||||||
descriptions[131]="Dismiss all or up to amount of notifications"
|
|
||||||
descriptions[132]="Focus a monitor"
|
|
||||||
descriptions[133]="Move the focus in a direction"
|
|
||||||
descriptions[134]="Interact with a plugin"
|
|
||||||
descriptions[135]="Exit the compositor with no questions asked"
|
|
||||||
descriptions[136]="Change the workspace"
|
|
||||||
descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client"
|
|
||||||
descriptions[138]="Get the config option status (values)"
|
|
||||||
descriptions[141]="List all decorations and their info"
|
|
||||||
descriptions[142]="Set the current window's floating state to false"
|
|
||||||
descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
|
||||||
descriptions[145]="Resize a selected window"
|
|
||||||
descriptions[146]="Toggle the focused window's internal fullscreen state"
|
|
||||||
descriptions[147]="Print tail of the log"
|
|
||||||
descriptions[148]="Swap the active workspaces between two monitors"
|
|
||||||
descriptions[149]="Change the current mapping group"
|
|
||||||
descriptions[151]="Behave as moveintogroup"
|
|
||||||
descriptions[152]="Get the current cursor pos in global layout coordinates"
|
|
||||||
descriptions[154]="Focus the requested workspace"
|
|
||||||
|
|
||||||
local -A literal_transitions
|
|
||||||
literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)"
|
|
||||||
literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)"
|
|
||||||
literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)"
|
|
||||||
literal_transitions[7]="([127]=3)"
|
|
||||||
literal_transitions[11]="([57]=3)"
|
|
||||||
literal_transitions[12]="([10]=3)"
|
|
||||||
literal_transitions[13]="([15]=20 [81]=23)"
|
|
||||||
literal_transitions[14]="([143]=3)"
|
|
||||||
literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)"
|
|
||||||
literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)"
|
|
||||||
literal_transitions[17]="([41]=3 [45]=3)"
|
|
||||||
literal_transitions[18]="([8]=24)"
|
|
||||||
literal_transitions[19]="([32]=3 [150]=3)"
|
|
||||||
literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)"
|
|
||||||
literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)"
|
|
||||||
literal_transitions[24]="([58]=22 [111]=22)"
|
|
||||||
|
|
||||||
local -A match_anything_transitions
|
|
||||||
match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2)
|
|
||||||
|
|
||||||
declare -A subword_transitions
|
|
||||||
|
|
||||||
local state=1
|
|
||||||
local word_index=2
|
|
||||||
while [[ $word_index -lt $CURRENT ]]; do
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
local word=${words[$word_index]}
|
|
||||||
local word_matched=0
|
|
||||||
for ((literal_id = 1; literal_id <= $#literals; literal_id++)); do
|
|
||||||
if [[ ${literals[$literal_id]} = "$word" ]]; then
|
|
||||||
if [[ -v "state_transitions[$literal_id]" ]]; then
|
|
||||||
state=${state_transitions[$literal_id]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
word_matched=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ $word_matched -ne 0 ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v "match_anything_transitions[$state]" ]]; then
|
|
||||||
state=${match_anything_transitions[$state]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
done
|
|
||||||
|
|
||||||
completions_no_description_trailing_space=()
|
|
||||||
completions_no_description_no_trailing_space=()
|
|
||||||
completions_trailing_space=()
|
|
||||||
suffixes_trailing_space=()
|
|
||||||
descriptions_trailing_space=()
|
|
||||||
completions_no_trailing_space=()
|
|
||||||
suffixes_no_trailing_space=()
|
|
||||||
descriptions_no_trailing_space=()
|
|
||||||
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
for literal_id in ${(k)state_transitions}; do
|
|
||||||
if [[ -v "descriptions[$literal_id]" ]]; then
|
|
||||||
completions_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
suffixes_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
descriptions_trailing_space+=("${descriptions[$literal_id]}")
|
|
||||||
else
|
|
||||||
completions_no_description_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
local -A commands=([8]=0 [23]=1 [9]=3 [6]=2)
|
|
||||||
|
|
||||||
if [[ -v "commands[$state]" ]]; then
|
|
||||||
local command_id=${commands[$state]}
|
|
||||||
local output=$(_hyprctl_cmd_${command_id} "${words[$CURRENT]}")
|
|
||||||
local -a command_completions=("${(@f)output}")
|
|
||||||
for line in ${command_completions[@]}; do
|
|
||||||
local parts=(${(@s: :)line})
|
|
||||||
if [[ -v "parts[2]" ]]; then
|
|
||||||
completions_trailing_space+=("${parts[1]}")
|
|
||||||
suffixes_trailing_space+=("${parts[1]}")
|
|
||||||
descriptions_trailing_space+=("${parts[2]}")
|
|
||||||
else
|
|
||||||
completions_no_description_trailing_space+=("${parts[1]}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
local maxlen=0
|
|
||||||
for suffix in ${suffixes_trailing_space[@]}; do
|
|
||||||
if [[ ${#suffix} -gt $maxlen ]]; then
|
|
||||||
maxlen=${#suffix}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
for suffix in ${suffixes_no_trailing_space[@]}; do
|
|
||||||
if [[ ${#suffix} -gt $maxlen ]]; then
|
|
||||||
maxlen=${#suffix}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for ((i = 1; i <= $#suffixes_trailing_space; i++)); do
|
|
||||||
if [[ -z ${descriptions_trailing_space[$i]} ]]; then
|
|
||||||
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}}"
|
|
||||||
else
|
|
||||||
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}} -- ${descriptions_trailing_space[$i]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for ((i = 1; i <= $#suffixes_no_trailing_space; i++)); do
|
|
||||||
if [[ -z ${descriptions_no_trailing_space[$i]} ]]; then
|
|
||||||
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}}"
|
|
||||||
else
|
|
||||||
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}} -- ${descriptions_no_trailing_space[$i]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
compadd -Q -a completions_no_description_trailing_space
|
|
||||||
compadd -Q -S ' ' -a completions_no_description_no_trailing_space
|
|
||||||
compadd -l -Q -a -d descriptions_trailing_space completions_trailing_space
|
|
||||||
compadd -l -Q -S '' -a -d descriptions_no_trailing_space completions_no_trailing_space
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
|
||||||
compdef _hyprctl hyprctl
|
|
||||||
else
|
|
||||||
_hyprctl
|
|
||||||
fi
|
|
||||||
130
hyprctl/main.cpp
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
const std::string USAGE = R"#(
|
||||||
|
usage: hyprctl [command] [(opt)args]
|
||||||
|
|
||||||
|
monitors
|
||||||
|
workspaces
|
||||||
|
clients
|
||||||
|
activewindow
|
||||||
|
layers
|
||||||
|
dispatch
|
||||||
|
keyword
|
||||||
|
version
|
||||||
|
reload
|
||||||
|
)#";
|
||||||
|
|
||||||
|
void request(std::string arg) {
|
||||||
|
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (SERVERSOCKET < 0) {
|
||||||
|
std::cout << "Couldn't open a socket (1)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto SERVER = gethostbyname("localhost");
|
||||||
|
|
||||||
|
if (!SERVER) {
|
||||||
|
std::cout << "Couldn't get host (2)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_un serverAddress = {0};
|
||||||
|
serverAddress.sun_family = AF_UNIX;
|
||||||
|
strcpy(serverAddress.sun_path, "/tmp/hypr/.socket.sock");
|
||||||
|
|
||||||
|
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||||
|
std::cout << "Couldn't connect to /tmp/hypr/.socket.sock. (3) Is Hyprland running?";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
|
||||||
|
|
||||||
|
if (sizeWritten < 0) {
|
||||||
|
std::cout << "Couldn't write (4)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[8192] = {0};
|
||||||
|
|
||||||
|
sizeWritten = read(SERVERSOCKET,buffer, 8192);
|
||||||
|
|
||||||
|
if (sizeWritten < 0) {
|
||||||
|
std::cout << "Couldn't read (5)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(SERVERSOCKET);
|
||||||
|
|
||||||
|
std::cout << std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispatchRequest(int argc, char** argv) {
|
||||||
|
|
||||||
|
if (argc < 4) {
|
||||||
|
std::cout << "dispatch requires 2 params";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rq = "dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||||
|
|
||||||
|
request(rq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keywordRequest(int argc, char** argv) {
|
||||||
|
if (argc < 4) {
|
||||||
|
std::cout << "keyword requires 2 params";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rq = "keyword " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||||
|
|
||||||
|
request(rq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void batchRequest(int argc, char** argv) {
|
||||||
|
std::string rq = "[[BATCH]]" + std::string(argv[2]);
|
||||||
|
|
||||||
|
request(rq);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int bflag = 0, sflag = 0, index, c;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("%s", USAGE.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "monitors")) request("monitors");
|
||||||
|
else if (!strcmp(argv[1], "clients")) request("clients");
|
||||||
|
else if (!strcmp(argv[1], "workspaces")) request("workspaces");
|
||||||
|
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
|
||||||
|
else if (!strcmp(argv[1], "layers")) request("layers");
|
||||||
|
else if (!strcmp(argv[1], "version")) request("version");
|
||||||
|
else if (!strcmp(argv[1], "reload")) request("reload");
|
||||||
|
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
|
||||||
|
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
|
||||||
|
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
|
||||||
|
else {
|
||||||
|
printf("%s", USAGE.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help]
|
|
||||||
|
|
||||||
commands:
|
|
||||||
activewindow → Gets the active window name and its properties
|
|
||||||
activeworkspace → Gets the active workspace and its properties
|
|
||||||
animations → Gets the current config'd info about animations
|
|
||||||
and beziers
|
|
||||||
binds → Lists all registered binds
|
|
||||||
clients → Lists all windows with their properties
|
|
||||||
configerrors → Lists all current config parsing errors
|
|
||||||
cursorpos → Gets the current cursor position in global layout
|
|
||||||
coordinates
|
|
||||||
decorations <window_regex> → Lists all decorations and their info
|
|
||||||
devices → Lists all connected keyboards and mice
|
|
||||||
dismissnotify [amount] → Dismisses all or up to AMOUNT notifications
|
|
||||||
dispatch <dispatcher> [args] → Issue a dispatch to call a keybind
|
|
||||||
dispatcher with arguments
|
|
||||||
getoption <option> → Gets the config option status (values)
|
|
||||||
globalshortcuts → Lists all global shortcuts
|
|
||||||
hyprpaper ... → Issue a hyprpaper request
|
|
||||||
hyprsunset ... → Issue a hyprsunset request
|
|
||||||
instances → Lists all running instances of Hyprland with
|
|
||||||
their info
|
|
||||||
keyword <name> <value> → Issue a keyword to call a config keyword
|
|
||||||
dynamically
|
|
||||||
kill → Issue a kill to get into a kill mode, where you can
|
|
||||||
kill an app by clicking on it. You can exit it
|
|
||||||
with ESCAPE
|
|
||||||
layers → Lists all the surface layers
|
|
||||||
layouts → Lists all layouts available (including plugin'd ones)
|
|
||||||
monitors → Lists active outputs with their properties,
|
|
||||||
'monitors all' lists active and inactive outputs
|
|
||||||
notify ... → Sends a notification using the built-in Hyprland
|
|
||||||
notification system
|
|
||||||
output ... → Allows you to add and remove fake outputs to your
|
|
||||||
preferred backend
|
|
||||||
plugin ... → Issue a plugin request
|
|
||||||
reload [config-only] → Issue a reload to force reload the config. Pass
|
|
||||||
'config-only' to disable monitor reload
|
|
||||||
rollinglog → Prints tail of the log. Also supports -f/--follow
|
|
||||||
option
|
|
||||||
setcursor <theme> <size> → Sets the cursor theme and reloads the cursor
|
|
||||||
manager
|
|
||||||
seterror <color> <message...> → Sets the hyprctl error string. Color has
|
|
||||||
the same format as in colors in config. Will reset
|
|
||||||
when Hyprland's config is reloaded
|
|
||||||
setprop ... → Sets a window property
|
|
||||||
getprop ... → Gets a window property
|
|
||||||
splash → Get the current splash
|
|
||||||
switchxkblayout ... → Sets the xkb layout index for a keyboard
|
|
||||||
systeminfo → Get system info
|
|
||||||
version → Prints the hyprland version, meaning flags, commit
|
|
||||||
and branch of build.
|
|
||||||
workspacerules → Lists all workspace rules
|
|
||||||
workspaces → Lists all workspaces with their properties
|
|
||||||
|
|
||||||
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)
|
|
||||||
--quiet (-q) → Disable the output of hyprctl
|
|
||||||
|
|
||||||
--help:
|
|
||||||
Can be used to print command's arguments that did not fit into this page
|
|
||||||
(three dots))#";
|
|
||||||
|
|
||||||
const std::string_view HYPRPAPER_HELP = R"#(usage: hyprctl [flags] hyprpaper <request>
|
|
||||||
|
|
||||||
requests:
|
|
||||||
wallpaper → Issue a wallpaper to call a config wallpaper dynamically.
|
|
||||||
Arguments are [mon],[path],[fit_mode]. Fit mode is optional.
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view HYPRSUNSET_HELP = R"#(usage: hyprctl [flags] hyprsunset <request>
|
|
||||||
|
|
||||||
requests:
|
|
||||||
temperature <temp> → Enable blue-light filter
|
|
||||||
identity → Disable blue-light filter
|
|
||||||
gamma <gamma> → Enable gamma filter
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view NOTIFY_HELP = R"#(usage: hyprctl [flags] notify <icon> <time_ms> <color> <message...>
|
|
||||||
|
|
||||||
icon:
|
|
||||||
Integer of value:
|
|
||||||
0 → Warning
|
|
||||||
1 → Info
|
|
||||||
2 → Hint
|
|
||||||
3 → Error
|
|
||||||
4 → Confused
|
|
||||||
5 → Ok
|
|
||||||
6 or -1 → No icon
|
|
||||||
|
|
||||||
time_ms:
|
|
||||||
Time to display notification in milliseconds
|
|
||||||
|
|
||||||
color:
|
|
||||||
Notification color. Format is the same as for colors in hyprland.conf. Use
|
|
||||||
0 for default color for icon
|
|
||||||
|
|
||||||
message:
|
|
||||||
Notification message
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view OUTPUT_HELP = R"#(usage: hyprctl [flags] output <create <backend> | remove <name>>
|
|
||||||
|
|
||||||
create <backend>:
|
|
||||||
Creates new virtual output. Possible values for backend: wayland, x11,
|
|
||||||
headless or auto.
|
|
||||||
|
|
||||||
remove <name>:
|
|
||||||
Removes virtual output. Pass the output's name, as found in
|
|
||||||
'hyprctl monitors'
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view PLUGIN_HELP = R"#(usage: hyprctl [flags] plugin <request>
|
|
||||||
|
|
||||||
requests:
|
|
||||||
load <path> → Loads a plugin. Path must be absolute
|
|
||||||
unload <path> → Unloads a plugin. Path must be absolute
|
|
||||||
list → Lists all loaded plugins
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view SETPROP_HELP = R"#(usage: hyprctl [flags] setprop <regex> <property> <value> [lock]
|
|
||||||
|
|
||||||
regex:
|
|
||||||
Regular expression by which a window will be searched
|
|
||||||
|
|
||||||
property:
|
|
||||||
See https://wiki.hypr.land/Configuring/Using-hyprctl/#setprop for list
|
|
||||||
of properties
|
|
||||||
|
|
||||||
value:
|
|
||||||
Property value
|
|
||||||
|
|
||||||
lock:
|
|
||||||
Optional argument. If lock is not added, will be unlocked. Locking means a
|
|
||||||
dynamic windowrule cannot override this setting.
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view GETPROP_HELP = R"#(usage: hyprctl [flags] getprop <regex> <property>
|
|
||||||
|
|
||||||
regex:
|
|
||||||
Regular expression by which a window will be searched
|
|
||||||
|
|
||||||
property:
|
|
||||||
See https://wiki.hypr.land/Configuring/Using-hyprctl/#setprop for list
|
|
||||||
of properties
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
||||||
const std::string_view SWITCHXKBLAYOUT_HELP = R"#(usage: [flags] switchxkblayout <device> <cmd>
|
|
||||||
|
|
||||||
device:
|
|
||||||
You can find the device using 'hyprctl devices' command
|
|
||||||
|
|
||||||
cmd:
|
|
||||||
'next' for next, 'prev' for previous, or ID for a specific one. IDs are
|
|
||||||
assigned based on their order in config file (keyboard_layout),
|
|
||||||
starting from 0
|
|
||||||
|
|
||||||
flags:
|
|
||||||
See 'hyprctl --help')#";
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <hyprutils/memory/SharedPtr.hpp>
|
|
||||||
#include <hyprutils/memory/UniquePtr.hpp>
|
|
||||||
#include <hyprutils/memory/Atomic.hpp>
|
|
||||||
|
|
||||||
using namespace Hyprutils::Memory;
|
|
||||||
|
|
||||||
#define SP CSharedPointer
|
|
||||||
#define WP CWeakPointer
|
|
||||||
#define UP CUniquePointer
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
#include "Hyprpaper.hpp"
|
|
||||||
#include "../helpers/Memory.hpp"
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <format>
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
#include <hyprpaper_core-client.hpp>
|
|
||||||
|
|
||||||
#include <hyprutils/string/VarList2.hpp>
|
|
||||||
using namespace Hyprutils::String;
|
|
||||||
|
|
||||||
using namespace std::string_literals;
|
|
||||||
|
|
||||||
constexpr const char* SOCKET_NAME = ".hyprpaper.sock";
|
|
||||||
static SP<CCHyprpaperCoreImpl> g_coreImpl;
|
|
||||||
|
|
||||||
constexpr const uint32_t PROTOCOL_VERSION_SUPPORTED = 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
static hyprpaperCoreWallpaperFitMode fitFromString(const std::string_view& sv) {
|
|
||||||
if (sv == "contain")
|
|
||||||
return HYPRPAPER_CORE_WALLPAPER_FIT_MODE_CONTAIN;
|
|
||||||
if (sv == "fit" || sv == "stretch")
|
|
||||||
return HYPRPAPER_CORE_WALLPAPER_FIT_MODE_STRETCH;
|
|
||||||
if (sv == "tile")
|
|
||||||
return HYPRPAPER_CORE_WALLPAPER_FIT_MODE_TILE;
|
|
||||||
return HYPRPAPER_CORE_WALLPAPER_FIT_MODE_COVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::expected<std::string, std::string> resolvePath(const std::string_view& sv) {
|
|
||||||
std::error_code ec;
|
|
||||||
auto can = std::filesystem::canonical(sv, ec);
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
return std::unexpected(std::format("invalid path: {}", ec.message()));
|
|
||||||
|
|
||||||
return can;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::expected<std::string, std::string> getFullPath(const std::string_view& sv) {
|
|
||||||
if (sv.empty())
|
|
||||||
return std::unexpected("empty path");
|
|
||||||
|
|
||||||
if (sv[0] == '~') {
|
|
||||||
static auto HOME = getenv("HOME");
|
|
||||||
if (!HOME || HOME[0] == '\0')
|
|
||||||
return std::unexpected("home path but no $HOME");
|
|
||||||
|
|
||||||
return resolvePath(std::string{HOME} + "/"s + std::string{sv.substr(1)});
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolvePath(sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::expected<void, std::string> Hyprpaper::makeHyprpaperRequest(const std::string_view& rq) {
|
|
||||||
if (!rq.contains(' '))
|
|
||||||
return std::unexpected("Invalid request");
|
|
||||||
|
|
||||||
if (!rq.starts_with("/hyprpaper "))
|
|
||||||
return std::unexpected("Invalid request");
|
|
||||||
|
|
||||||
std::string_view LHS, RHS;
|
|
||||||
auto spacePos = rq.find(' ', 12);
|
|
||||||
LHS = rq.substr(11, spacePos - 11);
|
|
||||||
RHS = rq.substr(spacePos + 1);
|
|
||||||
|
|
||||||
if (LHS != "wallpaper")
|
|
||||||
return std::unexpected("Unknown hyprpaper request");
|
|
||||||
|
|
||||||
CVarList2 args(std::string{RHS}, 0, ',');
|
|
||||||
|
|
||||||
const std::string MONITOR = std::string{args[0]};
|
|
||||||
const auto& PATH_RAW = args[1];
|
|
||||||
const auto& FIT = args[2];
|
|
||||||
|
|
||||||
if (PATH_RAW.empty())
|
|
||||||
return std::unexpected("not enough args");
|
|
||||||
|
|
||||||
const auto RTDIR = getenv("XDG_RUNTIME_DIR");
|
|
||||||
|
|
||||||
if (!RTDIR || RTDIR[0] == '\0')
|
|
||||||
return std::unexpected("can't send: no XDG_RUNTIME_DIR");
|
|
||||||
|
|
||||||
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
|
||||||
|
|
||||||
if (!HIS || HIS[0] == '\0')
|
|
||||||
return std::unexpected("can't send: no HYPRLAND_INSTANCE_SIGNATURE (not running under hyprland)");
|
|
||||||
|
|
||||||
const auto PATH = getFullPath(PATH_RAW);
|
|
||||||
|
|
||||||
if (!PATH)
|
|
||||||
return std::unexpected(std::format("bad path: {}", PATH_RAW));
|
|
||||||
|
|
||||||
auto socketPath = RTDIR + "/hypr/"s + HIS + "/"s + SOCKET_NAME;
|
|
||||||
|
|
||||||
auto socket = Hyprwire::IClientSocket::open(socketPath);
|
|
||||||
|
|
||||||
if (!socket)
|
|
||||||
return std::unexpected("can't send: failed to connect to hyprpaper (is it running?)");
|
|
||||||
|
|
||||||
g_coreImpl = makeShared<CCHyprpaperCoreImpl>(1);
|
|
||||||
|
|
||||||
socket->addImplementation(g_coreImpl);
|
|
||||||
|
|
||||||
if (!socket->waitForHandshake())
|
|
||||||
return std::unexpected("can't send: wire handshake failed");
|
|
||||||
|
|
||||||
auto spec = socket->getSpec(g_coreImpl->protocol()->specName());
|
|
||||||
|
|
||||||
if (!spec)
|
|
||||||
return std::unexpected("can't send: hyprpaper doesn't have the spec?!");
|
|
||||||
|
|
||||||
auto manager = makeShared<CCHyprpaperCoreManagerObject>(socket->bindProtocol(g_coreImpl->protocol(), PROTOCOL_VERSION_SUPPORTED));
|
|
||||||
|
|
||||||
if (!manager)
|
|
||||||
return std::unexpected("wire error: couldn't create manager");
|
|
||||||
|
|
||||||
auto wallpaper = makeShared<CCHyprpaperWallpaperObject>(manager->sendGetWallpaperObject());
|
|
||||||
|
|
||||||
if (!wallpaper)
|
|
||||||
return std::unexpected("wire error: couldn't create wallpaper object");
|
|
||||||
|
|
||||||
bool canExit = false;
|
|
||||||
std::optional<std::string> err;
|
|
||||||
|
|
||||||
wallpaper->setFailed([&canExit, &err](uint32_t code) {
|
|
||||||
canExit = true;
|
|
||||||
err = std::format("failed to set wallpaper, code {}", code);
|
|
||||||
});
|
|
||||||
wallpaper->setSuccess([&canExit]() { canExit = true; });
|
|
||||||
|
|
||||||
wallpaper->sendPath(PATH->c_str());
|
|
||||||
wallpaper->sendMonitorName(MONITOR.c_str());
|
|
||||||
if (!FIT.empty())
|
|
||||||
wallpaper->sendFitMode(fitFromString(FIT));
|
|
||||||
|
|
||||||
wallpaper->sendApply();
|
|
||||||
|
|
||||||
while (!canExit) {
|
|
||||||
socket->dispatchEvents(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
return std::unexpected(*err);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <expected>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Hyprpaper {
|
|
||||||
std::expected<void, std::string> makeHyprpaperRequest(const std::string_view& rq);
|
|
||||||
};
|
|
||||||
|
|
@ -1,539 +0,0 @@
|
||||||
#include <re2/re2.h>
|
|
||||||
|
|
||||||
#include <cctype>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <csignal>
|
|
||||||
#include <ranges>
|
|
||||||
#include <optional>
|
|
||||||
#include <charconv>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <print>
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <hyprutils/string/String.hpp>
|
|
||||||
#include <hyprutils/memory/Casts.hpp>
|
|
||||||
using namespace Hyprutils::String;
|
|
||||||
using namespace Hyprutils::Memory;
|
|
||||||
|
|
||||||
#include "Strings.hpp"
|
|
||||||
#include "hyprpaper/Hyprpaper.hpp"
|
|
||||||
|
|
||||||
std::string instanceSignature;
|
|
||||||
bool quiet = false;
|
|
||||||
|
|
||||||
struct SInstanceData {
|
|
||||||
std::string id;
|
|
||||||
uint64_t time;
|
|
||||||
uint64_t pid;
|
|
||||||
std::string wlSocket;
|
|
||||||
};
|
|
||||||
|
|
||||||
void log(const std::string_view str) {
|
|
||||||
if (quiet)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::println("{}", str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getUID() {
|
|
||||||
const auto UID = getuid();
|
|
||||||
const auto PWUID = getpwuid(UID);
|
|
||||||
return PWUID ? PWUID->pw_uid : UID;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getRuntimeDir() {
|
|
||||||
const auto XDG = getenv("XDG_RUNTIME_DIR");
|
|
||||||
|
|
||||||
if (!XDG) {
|
|
||||||
const std::string USERID = std::to_string(getUID());
|
|
||||||
return "/run/user/" + USERID + "/hypr";
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string{XDG} + "/hypr";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<uint64_t> toUInt64(const std::string_view str) {
|
|
||||||
uint64_t value = 0;
|
|
||||||
const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
|
|
||||||
if (ec != std::errc() || ptr != str.data() + str.size())
|
|
||||||
return std::nullopt;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<SInstanceData> parseInstance(const std::filesystem::directory_entry& entry) {
|
|
||||||
if (!entry.is_directory())
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
const auto lockPath = entry.path() / "hyprland.lock";
|
|
||||||
std::ifstream ifs(lockPath);
|
|
||||||
if (!ifs.is_open())
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
SInstanceData data;
|
|
||||||
data.id = entry.path().filename().string();
|
|
||||||
|
|
||||||
const auto first = std::string_view{data.id}.find_first_of('_');
|
|
||||||
const auto last = std::string_view{data.id}.find_last_of('_');
|
|
||||||
if (first == std::string_view::npos || last == std::string_view::npos || last <= first)
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
auto time = toUInt64(std::string_view{data.id}.substr(first + 1, last - first - 1));
|
|
||||||
if (!time)
|
|
||||||
return std::nullopt;
|
|
||||||
data.time = *time;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
if (!std::getline(ifs, line))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
auto pid = toUInt64(std::string_view{line});
|
|
||||||
if (!pid)
|
|
||||||
return std::nullopt;
|
|
||||||
data.pid = *pid;
|
|
||||||
|
|
||||||
if (!std::getline(ifs, data.wlSocket))
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
if (std::getline(ifs, line) && !line.empty())
|
|
||||||
return std::nullopt; // more lines than expected
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SInstanceData> instances() {
|
|
||||||
std::vector<SInstanceData> result;
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
const auto runtimeDir = getRuntimeDir();
|
|
||||||
if (!std::filesystem::exists(runtimeDir, ec) || ec)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
std::filesystem::directory_iterator it(runtimeDir, std::filesystem::directory_options::skip_permission_denied, ec);
|
|
||||||
if (ec)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
for (const auto& el : it) {
|
|
||||||
if (auto instance = parseInstance(el))
|
|
||||||
result.emplace_back(std::move(*instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::erase_if(result, [](const auto& el) { return kill(el.pid, 0) != 0 && errno == ESRCH; });
|
|
||||||
|
|
||||||
std::ranges::sort(result, {}, &SInstanceData::time);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static volatile bool sigintReceived = false;
|
|
||||||
void intHandler(int sig) {
|
|
||||||
sigintReceived = true;
|
|
||||||
std::println("[hyprctl] SIGINT received, closing connection");
|
|
||||||
}
|
|
||||||
|
|
||||||
int rollingRead(const int socket) {
|
|
||||||
sigintReceived = false;
|
|
||||||
signal(SIGINT, intHandler);
|
|
||||||
|
|
||||||
constexpr size_t BUFFER_SIZE = 8192;
|
|
||||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
|
||||||
long sizeWritten = 0;
|
|
||||||
std::println("[hyprctl] reading from socket following up log:");
|
|
||||||
while (!sigintReceived) {
|
|
||||||
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
|
||||||
if (sizeWritten < 0 && errno != EAGAIN) {
|
|
||||||
if (errno != EINTR)
|
|
||||||
std::println("Couldn't read (5): {}: {}", strerror(errno), errno);
|
|
||||||
close(socket);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizeWritten == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sizeWritten > 0) {
|
|
||||||
std::println("{}", std::string(buffer.data(), sizeWritten));
|
|
||||||
buffer.fill('\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(100000);
|
|
||||||
}
|
|
||||||
close(socket);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int request(std::string_view arg, int minArgs = 0, bool needRoll = false) {
|
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if (SERVERSOCKET < 0) {
|
|
||||||
log("Couldn't open a socket (1)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
|
||||||
if (setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0) {
|
|
||||||
log("Couldn't set socket timeout (2)");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
|
||||||
|
|
||||||
if (ARGS < minArgs) {
|
|
||||||
log(std::format("Not enough arguments in '{}', expected at least {}", arg, minArgs));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instanceSignature.empty()) {
|
|
||||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?) (3)");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
|
||||||
serverAddress.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.socket.sock";
|
|
||||||
|
|
||||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, rc<sockaddr*>(&serverAddress), SUN_LEN(&serverAddress)) < 0) {
|
|
||||||
log("Couldn't connect to " + socketPath + ". (4)");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto sizeWritten = write(SERVERSOCKET, arg.data(), arg.size());
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
log("Couldn't write (5)");
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needRoll)
|
|
||||||
return rollingRead(SERVERSOCKET);
|
|
||||||
|
|
||||||
std::string reply = "";
|
|
||||||
constexpr size_t BUFFER_SIZE = 8192;
|
|
||||||
char buffer[BUFFER_SIZE] = {0};
|
|
||||||
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
if (errno == EWOULDBLOCK)
|
|
||||||
log("Hyprland IPC didn't respond in time\n");
|
|
||||||
log("Couldn't read (6)");
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply += std::string(buffer, sizeWritten);
|
|
||||||
|
|
||||||
while (sizeWritten == BUFFER_SIZE) {
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
log("Couldn't read (6)");
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
reply += std::string(buffer, sizeWritten);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(SERVERSOCKET);
|
|
||||||
|
|
||||||
log(reply);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int requestIPC(std::string_view filename, std::string_view arg) {
|
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if (SERVERSOCKET < 0) {
|
|
||||||
log("Couldn't open a socket (1)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instanceSignature.empty()) {
|
|
||||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
|
||||||
serverAddress.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/" + filename;
|
|
||||||
|
|
||||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, rc<sockaddr*>(&serverAddress), SUN_LEN(&serverAddress)) < 0) {
|
|
||||||
log("Couldn't connect to " + socketPath + ". (3)");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = arg.substr(arg.find_first_of('/') + 1); // strip flags
|
|
||||||
arg = arg.substr(arg.find_first_of(' ') + 1); // strip "hyprpaper"
|
|
||||||
|
|
||||||
auto sizeWritten = write(SERVERSOCKET, arg.data(), arg.size());
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
log("Couldn't write (4)");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
constexpr size_t BUFFER_SIZE = 8192;
|
|
||||||
char buffer[BUFFER_SIZE] = {0};
|
|
||||||
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
log("Couldn't read (5)");
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(SERVERSOCKET);
|
|
||||||
|
|
||||||
log(std::string(buffer));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int requestHyprsunset(std::string_view arg) {
|
|
||||||
return requestIPC(".hyprsunset.sock", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void batchRequest(std::string_view arg, bool json) {
|
|
||||||
std::string commands(arg.substr(arg.find_first_of(' ') + 1));
|
|
||||||
|
|
||||||
if (json) {
|
|
||||||
RE2::GlobalReplace(&commands, ";\\s*", ";j/");
|
|
||||||
commands.insert(0, "j/");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string rq = "[[BATCH]]" + commands;
|
|
||||||
request(rq);
|
|
||||||
}
|
|
||||||
|
|
||||||
void instancesRequest(bool json) {
|
|
||||||
std::string result = "";
|
|
||||||
|
|
||||||
// gather instance data
|
|
||||||
std::vector<SInstanceData> inst = instances();
|
|
||||||
|
|
||||||
if (!json) {
|
|
||||||
for (auto const& el : inst) {
|
|
||||||
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result += '[';
|
|
||||||
for (auto const& el : inst) {
|
|
||||||
result += std::format(R"#(
|
|
||||||
{{
|
|
||||||
"instance": "{}",
|
|
||||||
"time": {},
|
|
||||||
"pid": {},
|
|
||||||
"wl_socket": "{}"
|
|
||||||
}},)#",
|
|
||||||
el.id, el.time, el.pid, el.wlSocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.pop_back();
|
|
||||||
result += "\n]";
|
|
||||||
}
|
|
||||||
|
|
||||||
log(result + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> splitArgs(int argc, char** argv) {
|
|
||||||
std::vector<std::string> result;
|
|
||||||
|
|
||||||
for (auto i = 1 /* skip the executable */; i < argc; ++i)
|
|
||||||
result.emplace_back(argv[i]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
bool parseArgs = true;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fullRequest = "";
|
|
||||||
std::string fullArgs = "";
|
|
||||||
const auto ARGS = splitArgs(argc, argv);
|
|
||||||
bool json = false;
|
|
||||||
bool needRoll = false;
|
|
||||||
std::string overrideInstance = "";
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
|
||||||
if (ARGS[i] == "--") {
|
|
||||||
// Stop parsing arguments after --
|
|
||||||
parseArgs = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parseArgs && (ARGS[i][0] == '-') && !(isNumber(ARGS[i], true) || isNumber(ARGS[i].substr(0, ARGS[i].length() - 1), true)) /* For stuff like -2 or -2, */) {
|
|
||||||
// parse
|
|
||||||
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] == "-a" && !fullArgs.contains("a")) {
|
|
||||||
fullArgs += "a";
|
|
||||||
} else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) {
|
|
||||||
fullArgs += "c";
|
|
||||||
} else if ((ARGS[i] == "-f" || ARGS[i] == "--follow") && !fullArgs.contains("f")) {
|
|
||||||
fullArgs += "f";
|
|
||||||
needRoll = true;
|
|
||||||
} else if (ARGS[i] == "--batch") {
|
|
||||||
fullRequest = "--batch ";
|
|
||||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
|
||||||
++i;
|
|
||||||
|
|
||||||
if (i >= ARGS.size()) {
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
overrideInstance = ARGS[i];
|
|
||||||
} else if (ARGS[i] == "-q" || ARGS[i] == "--quiet") {
|
|
||||||
quiet = true;
|
|
||||||
} else if (ARGS[i] == "--help") {
|
|
||||||
const std::string& cmd = ARGS[0];
|
|
||||||
|
|
||||||
if (cmd == "hyprpaper") {
|
|
||||||
std::println("{}", HYPRPAPER_HELP);
|
|
||||||
} else if (cmd == "hyprsunset") {
|
|
||||||
std::println("{}", HYPRSUNSET_HELP);
|
|
||||||
} else if (cmd == "notify") {
|
|
||||||
std::println("{}", NOTIFY_HELP);
|
|
||||||
} else if (cmd == "output") {
|
|
||||||
std::println("{}", OUTPUT_HELP);
|
|
||||||
} else if (cmd == "plugin") {
|
|
||||||
std::println("{}", PLUGIN_HELP);
|
|
||||||
} else if (cmd == "setprop") {
|
|
||||||
std::println("{}", SETPROP_HELP);
|
|
||||||
} else if (cmd == "getprop") {
|
|
||||||
std::println("{}", GETPROP_HELP);
|
|
||||||
} else if (cmd == "switchxkblayout") {
|
|
||||||
std::println("{}", SWITCHXKBLAYOUT_HELP);
|
|
||||||
} else {
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullRequest += ARGS[i] + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullRequest.empty()) {
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullRequest.pop_back(); // remove trailing space
|
|
||||||
|
|
||||||
fullRequest = fullArgs + "/" + fullRequest;
|
|
||||||
|
|
||||||
// instances is HIS-independent
|
|
||||||
if (fullRequest.contains("/instances")) {
|
|
||||||
instancesRequest(json);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needRoll && !fullRequest.contains("/rollinglog")) {
|
|
||||||
log("only 'rollinglog' command supports '--follow' option");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overrideInstance.contains("_"))
|
|
||||||
instanceSignature = overrideInstance;
|
|
||||||
else if (!overrideInstance.empty()) {
|
|
||||||
if (!isNumber(overrideInstance, false)) {
|
|
||||||
log("instance invalid\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto INSTANCENO = std::stoi(overrideInstance);
|
|
||||||
|
|
||||||
const auto INSTANCES = instances();
|
|
||||||
|
|
||||||
if (INSTANCENO < 0 || sc<std::size_t>(INSTANCENO) >= INSTANCES.size()) {
|
|
||||||
log("no such instance\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceSignature = INSTANCES[INSTANCENO].id;
|
|
||||||
} else {
|
|
||||||
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
|
||||||
|
|
||||||
if (!ISIG) {
|
|
||||||
log("HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceSignature = ISIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exitStatus = 0;
|
|
||||||
|
|
||||||
if (fullRequest.contains("/--batch"))
|
|
||||||
batchRequest(fullRequest, json);
|
|
||||||
else if (fullRequest.contains("/hyprpaper")) {
|
|
||||||
auto result = Hyprpaper::makeHyprpaperRequest(fullRequest);
|
|
||||||
if (!result)
|
|
||||||
log(std::format("error: {}", result.error()));
|
|
||||||
exitStatus = !result;
|
|
||||||
} else if (fullRequest.contains("/hyprsunset"))
|
|
||||||
exitStatus = requestHyprsunset(fullRequest);
|
|
||||||
else if (fullRequest.contains("/switchxkblayout"))
|
|
||||||
exitStatus = request(fullRequest, 2);
|
|
||||||
else if (fullRequest.contains("/seterror"))
|
|
||||||
exitStatus = request(fullRequest, 1);
|
|
||||||
else if (fullRequest.contains("/setprop"))
|
|
||||||
exitStatus = request(fullRequest, 3);
|
|
||||||
else if (fullRequest.contains("/plugin"))
|
|
||||||
exitStatus = request(fullRequest, 1);
|
|
||||||
else if (fullRequest.contains("/dismissnotify"))
|
|
||||||
exitStatus = request(fullRequest, 0);
|
|
||||||
else if (fullRequest.contains("/notify"))
|
|
||||||
exitStatus = request(fullRequest, 2);
|
|
||||||
else if (fullRequest.contains("/output"))
|
|
||||||
exitStatus = request(fullRequest, 2);
|
|
||||||
else if (fullRequest.contains("/setcursor"))
|
|
||||||
exitStatus = request(fullRequest, 1);
|
|
||||||
else if (fullRequest.contains("/dispatch"))
|
|
||||||
exitStatus = request(fullRequest, 1);
|
|
||||||
else if (fullRequest.contains("/keyword"))
|
|
||||||
exitStatus = request(fullRequest, 2);
|
|
||||||
else if (fullRequest.contains("/decorations"))
|
|
||||||
exitStatus = request(fullRequest, 1);
|
|
||||||
else if (fullRequest.contains("/--help"))
|
|
||||||
std::println("{}", USAGE);
|
|
||||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
|
||||||
exitStatus = request(fullRequest, 0, true);
|
|
||||||
else {
|
|
||||||
exitStatus = request(fullRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::flush;
|
|
||||||
return exitStatus;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
prefix=@PREFIX@/@INCLUDEDIR@
|
|
||||||
|
|
||||||
Name: Hyprland
|
|
||||||
URL: https://github.com/hyprwm/Hyprland
|
|
||||||
Description: Hyprland header files
|
|
||||||
Version: @HYPRLAND_VERSION@
|
|
||||||
Requires: aquamarine >= @AQUAMARINE_MINIMUM_VERSION@, hyprcursor >= @HYPRCURSOR_MINIMUM_VERSION@, hyprgraphics >= @HYPRGRAPHICS_MINIMUM_VERSION@, hyprlang >= @HYPRLANG_MINIMUM_VERSION@, hyprutils >= @HYPRUTILS_MINIMUM_VERSION@, libdrm, egl, cairo, xkbcommon >= @XKBCOMMON_MINIMUM_VERSION@, libinput >= @LIBINPUT_MINIMUM_VERSION@, wayland-server >= @WAYLAND_SERVER_MINIMUM_VERSION@@PKGCONFIG_XWAYLAND_DEPENDENCIES@
|
|
||||||
Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.19)
|
|
||||||
|
|
||||||
project(
|
|
||||||
hyprpm
|
|
||||||
DESCRIPTION "A Hyprland Plugin Manager"
|
|
||||||
)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
|
|
||||||
pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.7.0)
|
|
||||||
|
|
||||||
find_package(glaze 6.0.0 QUIET)
|
|
||||||
if (NOT glaze_FOUND)
|
|
||||||
set(GLAZE_VERSION v6.1.0)
|
|
||||||
message(STATUS "glaze dependency not found, retrieving ${GLAZE_VERSION} with FetchContent")
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
glaze
|
|
||||||
GIT_REPOSITORY https://github.com/stephenberry/glaze.git
|
|
||||||
GIT_TAG ${GLAZE_VERSION}
|
|
||||||
GIT_SHALLOW TRUE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(glaze)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(hyprpm ${SRCFILES})
|
|
||||||
|
|
||||||
target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps glaze::glaze)
|
|
||||||
|
|
||||||
# binary
|
|
||||||
install(TARGETS hyprpm)
|
|
||||||
|
|
||||||
# shell completions
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.bash
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions
|
|
||||||
RENAME hyprpm)
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.fish
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/fish/vendor_completions.d)
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.zsh
|
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions
|
|
||||||
RENAME _hyprpm)
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
_hyprpm_cmd_0 () {
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprpm_cmd_1 () {
|
|
||||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprpm () {
|
|
||||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
|
||||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local words cword
|
|
||||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
|
||||||
|
|
||||||
declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f)
|
|
||||||
declare -A literal_transitions
|
|
||||||
literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)"
|
|
||||||
literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)"
|
|
||||||
literal_transitions[5]="([2]=6)"
|
|
||||||
literal_transitions[6]="([1]=7 [14]=7)"
|
|
||||||
declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1)
|
|
||||||
declare -A subword_transitions
|
|
||||||
|
|
||||||
local state=0
|
|
||||||
local word_index=1
|
|
||||||
while [[ $word_index -lt $cword ]]; do
|
|
||||||
local word=${words[$word_index]}
|
|
||||||
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
declare -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
local word_matched=0
|
|
||||||
for literal_id in $(seq 0 $((${#literals[@]} - 1))); do
|
|
||||||
if [[ ${literals[$literal_id]} = "$word" ]]; then
|
|
||||||
if [[ -v "state_transitions[$literal_id]" ]]; then
|
|
||||||
state=${state_transitions[$literal_id]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
word_matched=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ $word_matched -ne 0 ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v "match_anything_transitions[$state]" ]]; then
|
|
||||||
state=${match_anything_transitions[$state]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
local -a matches=()
|
|
||||||
|
|
||||||
local prefix="${words[$cword]}"
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local state_transitions_initializer=${literal_transitions[$state]}
|
|
||||||
declare -A state_transitions
|
|
||||||
eval "state_transitions=$state_transitions_initializer"
|
|
||||||
|
|
||||||
for literal_id in "${!state_transitions[@]}"; do
|
|
||||||
local literal="${literals[$literal_id]}"
|
|
||||||
if [[ $literal = "${prefix}"* ]]; then
|
|
||||||
matches+=("$literal ")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
declare -A commands
|
|
||||||
commands=([3]=0 [2]=1)
|
|
||||||
if [[ -v "commands[$state]" ]]; then
|
|
||||||
local command_id=${commands[$state]}
|
|
||||||
local completions=()
|
|
||||||
readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
|
||||||
for item in "${completions[@]}"; do
|
|
||||||
if [[ $item = "${prefix}"* ]]; then
|
|
||||||
matches+=("$item")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
local shortest_suffix="$prefix"
|
|
||||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
|
||||||
local char="${COMP_WORDBREAKS:$i:1}"
|
|
||||||
local candidate=${prefix##*$char}
|
|
||||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
|
||||||
shortest_suffix=$candidate
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
local superfluous_prefix=""
|
|
||||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
|
||||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
|
||||||
fi
|
|
||||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -o nospace -F _hyprpm hyprpm
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
function _hyprpm_1
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprpm_2
|
|
||||||
set 1 $argv[1]
|
|
||||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
|
||||||
end
|
|
||||||
|
|
||||||
function _hyprpm
|
|
||||||
set COMP_LINE (commandline --cut-at-cursor)
|
|
||||||
|
|
||||||
set COMP_WORDS
|
|
||||||
echo $COMP_LINE | read --tokenize --array COMP_WORDS
|
|
||||||
if string match --quiet --regex '.*\s$' $COMP_LINE
|
|
||||||
set COMP_CWORD (math (count $COMP_WORDS) + 1)
|
|
||||||
else
|
|
||||||
set COMP_CWORD (count $COMP_WORDS)
|
|
||||||
end
|
|
||||||
|
|
||||||
set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f"
|
|
||||||
|
|
||||||
set descriptions
|
|
||||||
set descriptions[1] "Disable shallow cloning of Hyprland sources"
|
|
||||||
set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)"
|
|
||||||
set descriptions[4] "Unload a plugin"
|
|
||||||
set descriptions[5] "List all installed plugins"
|
|
||||||
set descriptions[6] "Show help menu"
|
|
||||||
set descriptions[7] "Check and update all plugins if needed"
|
|
||||||
set descriptions[8] "Install a new plugin repository from git"
|
|
||||||
set descriptions[9] "Enable too much logging"
|
|
||||||
set descriptions[10] "Enable too much logging"
|
|
||||||
set descriptions[11] "Force an operation ignoring checks (e.g. update -f)"
|
|
||||||
set descriptions[12] "Disable shallow cloning of Hyprland sources"
|
|
||||||
set descriptions[13] "Remove a plugin repository"
|
|
||||||
set descriptions[14] "Load a plugin"
|
|
||||||
set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)"
|
|
||||||
set descriptions[16] "Show help menu"
|
|
||||||
set descriptions[17] "Reload all plugins"
|
|
||||||
set descriptions[18] "Force an operation ignoring checks (e.g. update -f)"
|
|
||||||
|
|
||||||
set literal_transitions
|
|
||||||
set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8"
|
|
||||||
set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5"
|
|
||||||
set literal_transitions[6] "set inputs 3; set tos 7"
|
|
||||||
set literal_transitions[7] "set inputs 2 15; set tos 8 8"
|
|
||||||
|
|
||||||
set match_anything_transitions_from 2 5 4 3 1
|
|
||||||
set match_anything_transitions_to 2 6 5 5 2
|
|
||||||
|
|
||||||
set state 1
|
|
||||||
set word_index 2
|
|
||||||
while test $word_index -lt $COMP_CWORD
|
|
||||||
set -- word $COMP_WORDS[$word_index]
|
|
||||||
|
|
||||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
eval $literal_transitions[$state]
|
|
||||||
|
|
||||||
if contains -- $word $literals
|
|
||||||
set literal_matched 0
|
|
||||||
for literal_id in (seq 1 (count $literals))
|
|
||||||
if test $literals[$literal_id] = $word
|
|
||||||
set index (contains --index -- $literal_id $inputs)
|
|
||||||
set state $tos[$index]
|
|
||||||
set word_index (math $word_index + 1)
|
|
||||||
set literal_matched 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if test $literal_matched -ne 0
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
|
||||||
set index (contains --index -- $state $match_anything_transitions_from)
|
|
||||||
set state $match_anything_transitions_to[$index]
|
|
||||||
set word_index (math $word_index + 1)
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
eval $literal_transitions[$state]
|
|
||||||
for literal_id in $inputs
|
|
||||||
if test -n $descriptions[$literal_id]
|
|
||||||
printf '%s\t%s\n' $literals[$literal_id] $descriptions[$literal_id]
|
|
||||||
else
|
|
||||||
printf '%s\n' $literals[$literal_id]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
set command_states 4 3
|
|
||||||
set command_ids 1 2
|
|
||||||
if contains $state $command_states
|
|
||||||
set index (contains --index $state $command_states)
|
|
||||||
set function_id $command_ids[$index]
|
|
||||||
set function_name _hyprpm_$function_id
|
|
||||||
set --erase inputs
|
|
||||||
set --erase tos
|
|
||||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
|
||||||
end
|
|
||||||
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
complete --command hyprpm --no-files --arguments "(_hyprpm)"
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
hyprpm [<FLAGS>]... <ARGUMENT>
|
|
||||||
|
|
||||||
|
|
||||||
<FLAGS> ::= (--notify | -n) "Send a hyprland notification for important events (e.g. load fail)"
|
|
||||||
| (--help | -h) "Show help menu"
|
|
||||||
| (--verbose | -v) "Enable too much logging"
|
|
||||||
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
|
|
||||||
| (--no-shallow | -s) "Disable shallow cloning of Hyprland sources"
|
|
||||||
;
|
|
||||||
|
|
||||||
<ARGUMENT> ::= (add) "Install a new plugin repository from git"
|
|
||||||
| (remove <PLUGIN_REPOS>) "Remove a plugin repository"
|
|
||||||
| (update) "Check and update all plugins if needed"
|
|
||||||
| (list) "List all installed plugins"
|
|
||||||
| (enable <PLUGINS>) "Load a plugin"
|
|
||||||
| (disable <PLUGINS>) "Unload a plugin"
|
|
||||||
| (reload) "Reload plugins to match the enabled/disabled state. Use -f to force reload."
|
|
||||||
;
|
|
||||||
|
|
||||||
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
|
||||||
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
#compdef hyprpm
|
|
||||||
|
|
||||||
_hyprpm_cmd_0 () {
|
|
||||||
hyprpm list | awk '/Plugin/{print $4}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprpm_cmd_1 () {
|
|
||||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
|
||||||
}
|
|
||||||
|
|
||||||
_hyprpm () {
|
|
||||||
local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f")
|
|
||||||
|
|
||||||
local -A descriptions
|
|
||||||
descriptions[1]="Disable shallow cloning of Hyprland sources"
|
|
||||||
descriptions[2]="Send a hyprland notification for important events (e.g. load fail)"
|
|
||||||
descriptions[4]="Unload a plugin"
|
|
||||||
descriptions[5]="List all installed plugins"
|
|
||||||
descriptions[6]="Show help menu"
|
|
||||||
descriptions[7]="Check and update all plugins if needed"
|
|
||||||
descriptions[8]="Install a new plugin repository from git"
|
|
||||||
descriptions[9]="Enable too much logging"
|
|
||||||
descriptions[10]="Enable too much logging"
|
|
||||||
descriptions[11]="Force an operation ignoring checks (e.g. update -f)"
|
|
||||||
descriptions[12]="Disable shallow cloning of Hyprland sources"
|
|
||||||
descriptions[13]="Remove a plugin repository"
|
|
||||||
descriptions[14]="Load a plugin"
|
|
||||||
descriptions[15]="Send a hyprland notification for important events (e.g. load fail)"
|
|
||||||
descriptions[16]="Show help menu"
|
|
||||||
descriptions[17]="Reload all plugins"
|
|
||||||
descriptions[18]="Force an operation ignoring checks (e.g. update -f)"
|
|
||||||
|
|
||||||
local -A literal_transitions
|
|
||||||
literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)"
|
|
||||||
literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)"
|
|
||||||
literal_transitions[6]="([3]=7)"
|
|
||||||
literal_transitions[7]="([2]=8 [15]=8)"
|
|
||||||
|
|
||||||
local -A match_anything_transitions
|
|
||||||
match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2)
|
|
||||||
|
|
||||||
declare -A subword_transitions
|
|
||||||
|
|
||||||
local state=1
|
|
||||||
local word_index=2
|
|
||||||
while [[ $word_index -lt $CURRENT ]]; do
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
local word=${words[$word_index]}
|
|
||||||
local word_matched=0
|
|
||||||
for ((literal_id = 1; literal_id <= $#literals; literal_id++)); do
|
|
||||||
if [[ ${literals[$literal_id]} = "$word" ]]; then
|
|
||||||
if [[ -v "state_transitions[$literal_id]" ]]; then
|
|
||||||
state=${state_transitions[$literal_id]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
word_matched=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ $word_matched -ne 0 ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v "match_anything_transitions[$state]" ]]; then
|
|
||||||
state=${match_anything_transitions[$state]}
|
|
||||||
word_index=$((word_index + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
done
|
|
||||||
|
|
||||||
completions_no_description_trailing_space=()
|
|
||||||
completions_no_description_no_trailing_space=()
|
|
||||||
completions_trailing_space=()
|
|
||||||
suffixes_trailing_space=()
|
|
||||||
descriptions_trailing_space=()
|
|
||||||
completions_no_trailing_space=()
|
|
||||||
suffixes_no_trailing_space=()
|
|
||||||
descriptions_no_trailing_space=()
|
|
||||||
|
|
||||||
if [[ -v "literal_transitions[$state]" ]]; then
|
|
||||||
local -A state_transitions
|
|
||||||
eval "state_transitions=${literal_transitions[$state]}"
|
|
||||||
|
|
||||||
for literal_id in ${(k)state_transitions}; do
|
|
||||||
if [[ -v "descriptions[$literal_id]" ]]; then
|
|
||||||
completions_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
suffixes_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
descriptions_trailing_space+=("${descriptions[$literal_id]}")
|
|
||||||
else
|
|
||||||
completions_no_description_trailing_space+=("${literals[$literal_id]}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
local -A commands=([4]=0 [3]=1)
|
|
||||||
|
|
||||||
if [[ -v "commands[$state]" ]]; then
|
|
||||||
local command_id=${commands[$state]}
|
|
||||||
local output=$(_hyprpm_cmd_${command_id} "${words[$CURRENT]}")
|
|
||||||
local -a command_completions=("${(@f)output}")
|
|
||||||
for line in ${command_completions[@]}; do
|
|
||||||
local parts=(${(@s: :)line})
|
|
||||||
if [[ -v "parts[2]" ]]; then
|
|
||||||
completions_trailing_space+=("${parts[1]}")
|
|
||||||
suffixes_trailing_space+=("${parts[1]}")
|
|
||||||
descriptions_trailing_space+=("${parts[2]}")
|
|
||||||
else
|
|
||||||
completions_no_description_trailing_space+=("${parts[1]}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
local maxlen=0
|
|
||||||
for suffix in ${suffixes_trailing_space[@]}; do
|
|
||||||
if [[ ${#suffix} -gt $maxlen ]]; then
|
|
||||||
maxlen=${#suffix}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
for suffix in ${suffixes_no_trailing_space[@]}; do
|
|
||||||
if [[ ${#suffix} -gt $maxlen ]]; then
|
|
||||||
maxlen=${#suffix}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for ((i = 1; i <= $#suffixes_trailing_space; i++)); do
|
|
||||||
if [[ -z ${descriptions_trailing_space[$i]} ]]; then
|
|
||||||
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}}"
|
|
||||||
else
|
|
||||||
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}} -- ${descriptions_trailing_space[$i]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for ((i = 1; i <= $#suffixes_no_trailing_space; i++)); do
|
|
||||||
if [[ -z ${descriptions_no_trailing_space[$i]} ]]; then
|
|
||||||
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}}"
|
|
||||||
else
|
|
||||||
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}} -- ${descriptions_no_trailing_space[$i]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
compadd -Q -a completions_no_description_trailing_space
|
|
||||||
compadd -Q -S ' ' -a completions_no_description_no_trailing_space
|
|
||||||
compadd -l -Q -a -d descriptions_trailing_space completions_trailing_space
|
|
||||||
compadd -l -Q -S '' -a -d descriptions_no_trailing_space completions_no_trailing_space
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
|
||||||
compdef _hyprpm hyprpm
|
|
||||||
else
|
|
||||||
_hyprpm
|
|
||||||
fi
|
|
||||||
|
|
@ -1,309 +0,0 @@
|
||||||
#include "DataState.hpp"
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <toml++/toml.hpp>
|
|
||||||
#include <print>
|
|
||||||
#include <sstream>
|
|
||||||
#include <fstream>
|
|
||||||
#include "PluginManager.hpp"
|
|
||||||
#include "../helpers/Die.hpp"
|
|
||||||
#include "../helpers/Sys.hpp"
|
|
||||||
#include "../helpers/StringUtils.hpp"
|
|
||||||
|
|
||||||
static std::string getTempRoot() {
|
|
||||||
static auto ENV = getenv("XDG_RUNTIME_DIR");
|
|
||||||
if (!ENV) {
|
|
||||||
std::cerr << "\nERROR: XDG_RUNTIME_DIR not set!\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto STR = ENV + std::string{"/hyprpm/"};
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(STR))
|
|
||||||
mkdir(STR.c_str(), S_IRWXU);
|
|
||||||
|
|
||||||
return STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the state to a file
|
|
||||||
static bool writeState(const std::string& str, const std::string& to) {
|
|
||||||
// create temp file in a safe temp root
|
|
||||||
std::ofstream of(getTempRoot() + ".temp-state", std::ios::trunc);
|
|
||||||
if (!of.good())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
of << str;
|
|
||||||
of.close();
|
|
||||||
|
|
||||||
return NSys::root::install(getTempRoot() + ".temp-state", to, "644");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path DataState::getDataStatePath() {
|
|
||||||
return std::filesystem::path("/var/cache/hyprpm/" + g_pPluginManager->m_szUsername);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DataState::getHeadersPath() {
|
|
||||||
return getDataStatePath() / "headersRoot";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::filesystem::path> DataState::getPluginStates() {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
std::vector<std::filesystem::path> states;
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(getDataStatePath())) {
|
|
||||||
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto stateFile = entry.path() / "state.toml";
|
|
||||||
if (!std::filesystem::exists(stateFile))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
states.emplace_back(stateFile);
|
|
||||||
}
|
|
||||||
return states;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataState::ensureStateStoreExists() {
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::exists(getHeadersPath(), ec) || ec) {
|
|
||||||
std::println("{}", infoString("The hyprpm state store doesn't exist. Creating now..."));
|
|
||||||
if (!std::filesystem::exists("/var/cache/hyprpm/", ec) || ec) {
|
|
||||||
if (!NSys::root::createDirectory("/var/cache/hyprpm", "755"))
|
|
||||||
Debug::die("ensureStateStoreExists: Failed to run a superuser cmd");
|
|
||||||
}
|
|
||||||
if (!std::filesystem::exists(getDataStatePath(), ec) || ec) {
|
|
||||||
if (!NSys::root::createDirectory(getDataStatePath().string(), "755"))
|
|
||||||
Debug::die("ensureStateStoreExists: Failed to run a superuser cmd");
|
|
||||||
}
|
|
||||||
if (!NSys::root::createDirectory(getHeadersPath(), "755"))
|
|
||||||
Debug::die("ensureStateStoreExists: Failed to run a superuser cmd");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
const auto PATH = getDataStatePath() / repo.name;
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::exists(PATH, ec) || ec) {
|
|
||||||
if (!NSys::root::createDirectory(PATH.string(), "755"))
|
|
||||||
Debug::die("addNewPluginRepo: failed to create cache dir");
|
|
||||||
}
|
|
||||||
// clang-format off
|
|
||||||
auto DATA = toml::table{
|
|
||||||
{"repository", toml::table{
|
|
||||||
{"name", repo.name},
|
|
||||||
{"author", repo.author},
|
|
||||||
{"hash", repo.hash},
|
|
||||||
{"url", repo.url},
|
|
||||||
{"rev", repo.rev}
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
for (auto const& p : repo.plugins) {
|
|
||||||
const auto filename = p.name + ".so";
|
|
||||||
|
|
||||||
// copy .so to the good place and chmod 755
|
|
||||||
if (std::filesystem::exists(p.filename)) {
|
|
||||||
if (!NSys::root::install(p.filename, (PATH / filename).string(), "0755"))
|
|
||||||
Debug::die("addNewPluginRepo: failed to install so file");
|
|
||||||
}
|
|
||||||
|
|
||||||
DATA.emplace(p.name, toml::table{
|
|
||||||
{"filename", filename},
|
|
||||||
{"enabled", p.enabled},
|
|
||||||
{"failed", p.failed}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << DATA;
|
|
||||||
|
|
||||||
if (!writeState(ss.str(), (PATH / "state.toml").string()))
|
|
||||||
Debug::die("{}", failureString("Failed to write plugin state"));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataState::pluginRepoExists(const SPluginRepoIdentifier identifier) {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
for (const auto& stateFile : getPluginStates()) {
|
|
||||||
const auto STATE = toml::parse_file(stateFile.c_str());
|
|
||||||
const auto NAME = STATE["repository"]["name"].value_or("");
|
|
||||||
const auto AUTHOR = STATE["repository"]["author"].value_or("");
|
|
||||||
const auto URL = STATE["repository"]["url"].value_or("");
|
|
||||||
|
|
||||||
if (identifier.matches(URL, NAME, AUTHOR))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataState::removePluginRepo(const SPluginRepoIdentifier identifier) {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
for (const auto& stateFile : getPluginStates()) {
|
|
||||||
const auto STATE = toml::parse_file(stateFile.c_str());
|
|
||||||
const auto NAME = STATE["repository"]["name"].value_or("");
|
|
||||||
const auto AUTHOR = STATE["repository"]["author"].value_or("");
|
|
||||||
const auto URL = STATE["repository"]["url"].value_or("");
|
|
||||||
|
|
||||||
if (identifier.matches(URL, NAME, AUTHOR)) {
|
|
||||||
// unload the plugins!!
|
|
||||||
for (const auto& file : std::filesystem::directory_iterator(stateFile.parent_path())) {
|
|
||||||
if (!file.path().string().ends_with(".so"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
g_pPluginManager->loadUnloadPlugin(std::filesystem::absolute(file.path()), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PATH = stateFile.parent_path().string();
|
|
||||||
|
|
||||||
if (!PATH.starts_with("/var/cache/hyprpm") || PATH.contains('\''))
|
|
||||||
return; // WTF?
|
|
||||||
|
|
||||||
// scary!
|
|
||||||
if (!NSys::root::removeRecursive(PATH))
|
|
||||||
Debug::die("removePluginRepo: failed to remove dir");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataState::updateGlobalState(const SGlobalState& state) {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
const auto PATH = getDataStatePath();
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::exists(PATH, ec) || ec) {
|
|
||||||
if (!NSys::root::createDirectory(PATH.string(), "755"))
|
|
||||||
Debug::die("updateGlobalState: failed to create dir");
|
|
||||||
}
|
|
||||||
// clang-format off
|
|
||||||
auto DATA = toml::table{
|
|
||||||
{"state", toml::table{
|
|
||||||
{"hash", state.headersAbiCompiled},
|
|
||||||
{"dont_warn_install", state.dontWarnInstall}
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << DATA;
|
|
||||||
|
|
||||||
if (!writeState(ss.str(), (PATH / "state.toml").string()))
|
|
||||||
Debug::die("{}", failureString("Failed to write plugin state"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SGlobalState DataState::getGlobalState() {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
const auto stateFile = getDataStatePath() / "state.toml";
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::exists(stateFile, ec) || ec)
|
|
||||||
return SGlobalState{};
|
|
||||||
|
|
||||||
auto DATA = toml::parse_file(stateFile.c_str());
|
|
||||||
|
|
||||||
SGlobalState state;
|
|
||||||
state.headersAbiCompiled = DATA["state"]["hash"].value_or("");
|
|
||||||
state.dontWarnInstall = DATA["state"]["dont_warn_install"].value_or(false);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SPluginRepository> DataState::getAllRepositories() {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
std::vector<SPluginRepository> repos;
|
|
||||||
for (const auto& stateFile : getPluginStates()) {
|
|
||||||
const auto STATE = toml::parse_file(stateFile.c_str());
|
|
||||||
|
|
||||||
const auto NAME = STATE["repository"]["name"].value_or("");
|
|
||||||
const auto AUTHOR = STATE["repository"]["author"].value_or("");
|
|
||||||
const auto URL = STATE["repository"]["url"].value_or("");
|
|
||||||
const auto REV = STATE["repository"]["rev"].value_or("");
|
|
||||||
const auto HASH = STATE["repository"]["hash"].value_or("");
|
|
||||||
|
|
||||||
SPluginRepository repo;
|
|
||||||
repo.hash = HASH;
|
|
||||||
repo.name = NAME;
|
|
||||||
repo.author = AUTHOR;
|
|
||||||
repo.url = URL;
|
|
||||||
repo.rev = REV;
|
|
||||||
|
|
||||||
for (const auto& [key, val] : STATE) {
|
|
||||||
if (key == "repository")
|
|
||||||
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, FAILED});
|
|
||||||
}
|
|
||||||
|
|
||||||
repos.push_back(repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return repos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataState::setPluginEnabled(const SPluginRepoIdentifier identifier, bool enabled) {
|
|
||||||
ensureStateStoreExists();
|
|
||||||
|
|
||||||
for (const auto& stateFile : getPluginStates()) {
|
|
||||||
const auto STATE = toml::parse_file(stateFile.c_str());
|
|
||||||
for (const auto& [key, val] : STATE) {
|
|
||||||
if (key == "repository")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (identifier.type) {
|
|
||||||
case IDENTIFIER_NAME:
|
|
||||||
if (key.str() != identifier.name)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case IDENTIFIER_AUTHOR_NAME:
|
|
||||||
if (STATE["repository"]["author"] != identifier.author || key.str() != identifier.name)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto FAILED = STATE[key]["failed"].value_or(false);
|
|
||||||
|
|
||||||
if (FAILED)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto modifiedState = STATE;
|
|
||||||
(*modifiedState[key].as_table()).insert_or_assign("enabled", enabled);
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << modifiedState;
|
|
||||||
|
|
||||||
if (!writeState(ss.str(), stateFile.string()))
|
|
||||||
Debug::die("{}", failureString("Failed to write plugin state"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataState::purgeAllCache() {
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::exists(getDataStatePath()) && !ec) {
|
|
||||||
std::println("{}", infoString("Nothing to do"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PATH = getDataStatePath().string();
|
|
||||||
if (PATH.contains('\''))
|
|
||||||
return;
|
|
||||||
// scary!
|
|
||||||
if (!NSys::root::removeRecursive(PATH))
|
|
||||||
Debug::die("Failed to run a superuser cmd");
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "Plugin.hpp"
|
|
||||||
|
|
||||||
struct SGlobalState {
|
|
||||||
std::string headersAbiCompiled = "";
|
|
||||||
bool dontWarnInstall = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace DataState {
|
|
||||||
std::filesystem::path getDataStatePath();
|
|
||||||
std::string getHeadersPath();
|
|
||||||
std::vector<std::filesystem::path> getPluginStates();
|
|
||||||
void ensureStateStoreExists();
|
|
||||||
void addNewPluginRepo(const SPluginRepository& repo);
|
|
||||||
void removePluginRepo(const SPluginRepoIdentifier identifier);
|
|
||||||
bool pluginRepoExists(const SPluginRepoIdentifier identifier);
|
|
||||||
void updateGlobalState(const SGlobalState& state);
|
|
||||||
void purgeAllCache();
|
|
||||||
SGlobalState getGlobalState();
|
|
||||||
bool setPluginEnabled(const SPluginRepoIdentifier identifier, bool enabled);
|
|
||||||
std::vector<SPluginRepository> getAllRepositories();
|
|
||||||
};
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#include "HyprlandSocket.hpp"
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include "../helpers/StringUtils.hpp"
|
|
||||||
#include <print>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <hyprutils/memory/Casts.hpp>
|
|
||||||
|
|
||||||
using namespace Hyprutils::Memory;
|
|
||||||
|
|
||||||
static int getUID() {
|
|
||||||
const auto UID = getuid();
|
|
||||||
const auto PWUID = getpwuid(UID);
|
|
||||||
return PWUID ? PWUID->pw_uid : UID;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getRuntimeDir() {
|
|
||||||
const auto XDG = getenv("XDG_RUNTIME_DIR");
|
|
||||||
|
|
||||||
if (!XDG) {
|
|
||||||
const std::string USERID = std::to_string(getUID());
|
|
||||||
return "/run/user/" + USERID + "/hypr";
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string{XDG} + "/hypr";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NHyprlandSocket::send(const std::string& cmd) {
|
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if (SERVERSOCKET < 0) {
|
|
||||||
std::println("{}", failureString("Couldn't open a socket (1)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
|
||||||
|
|
||||||
if (!HIS) {
|
|
||||||
std::println("{}", failureString("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?) (3)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
|
||||||
serverAddress.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
std::string socketPath = getRuntimeDir() + "/" + HIS + "/.socket.sock";
|
|
||||||
|
|
||||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, rc<sockaddr*>(&serverAddress), SUN_LEN(&serverAddress)) < 0) {
|
|
||||||
std::println("{}", failureString("Couldn't connect to " + socketPath + ". (4)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto sizeWritten = write(SERVERSOCKET, cmd.c_str(), cmd.length());
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
std::println("{}", failureString("Couldn't write (5)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string reply = "";
|
|
||||||
constexpr size_t BUFFER_SIZE = 8192;
|
|
||||||
char buffer[BUFFER_SIZE] = {0};
|
|
||||||
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
|
||||||
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
std::println("{}", failureString("Couldn't read (6)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
reply += std::string(buffer, sizeWritten);
|
|
||||||
|
|
||||||
while (sizeWritten == BUFFER_SIZE) {
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, BUFFER_SIZE);
|
|
||||||
if (sizeWritten < 0) {
|
|
||||||
std::println("{}", failureString("Couldn't read (7)"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
reply += std::string(buffer, sizeWritten);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(SERVERSOCKET);
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace NHyprlandSocket {
|
|
||||||
std::string send(const std::string& cmd);
|
|
||||||
};
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
#include "Manifest.hpp"
|
|
||||||
#include <toml++/toml.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
// Alphanumerics and -_ allowed for plugin names. No magic names.
|
|
||||||
// [A-Za-z0-9\-_]*
|
|
||||||
static bool validManifestName(const std::string_view& n) {
|
|
||||||
return std::ranges::all_of(n, [](const char& c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '-' || c == '_' || c == '=' || (c >= '0' && c <= '9'); });
|
|
||||||
}
|
|
||||||
|
|
||||||
CManifest::CManifest(const eManifestType type, const std::string& path) {
|
|
||||||
auto manifest = toml::parse_file(path);
|
|
||||||
|
|
||||||
if (type == MANIFEST_HYPRLOAD) {
|
|
||||||
for (auto const& [key, val] : manifest) {
|
|
||||||
if (key.str().ends_with(".build"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CManifest::SManifestPlugin plugin;
|
|
||||||
|
|
||||||
if (!validManifestName(key.str())) {
|
|
||||||
m_good = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.name = key;
|
|
||||||
m_plugins.push_back(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& plugin : m_plugins) {
|
|
||||||
plugin.description = manifest[plugin.name]["description"].value_or("?");
|
|
||||||
plugin.version = manifest[plugin.name]["version"].value_or("?");
|
|
||||||
plugin.output = manifest[plugin.name]["build"]["output"].value_or("?");
|
|
||||||
auto authors = manifest[plugin.name]["authors"].as_array();
|
|
||||||
if (authors) {
|
|
||||||
for (auto&& a : *authors) {
|
|
||||||
plugin.authors.push_back(a.as_string()->value_or("?"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto author = manifest[plugin.name]["author"].value_or("");
|
|
||||||
if (!std::string{author}.empty())
|
|
||||||
plugin.authors.push_back(author);
|
|
||||||
}
|
|
||||||
auto buildSteps = manifest[plugin.name]["build"]["steps"].as_array();
|
|
||||||
if (buildSteps) {
|
|
||||||
for (auto&& s : *buildSteps) {
|
|
||||||
plugin.buildSteps.push_back(s.as_string()->value_or("?"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.output.empty() || plugin.buildSteps.empty()) {
|
|
||||||
m_good = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == MANIFEST_HYPRPM) {
|
|
||||||
m_repository.name = manifest["repository"]["name"].value_or("");
|
|
||||||
auto authors = manifest["repository"]["authors"].as_array();
|
|
||||||
if (authors) {
|
|
||||||
for (auto&& a : *authors) {
|
|
||||||
m_repository.authors.push_back(a.as_string()->value_or("?"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto author = manifest["repository"]["author"].value_or("");
|
|
||||||
if (!std::string{author}.empty())
|
|
||||||
m_repository.authors.push_back(author);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pins = manifest["repository"]["commit_pins"].as_array();
|
|
||||||
if (pins) {
|
|
||||||
for (auto&& pin : *pins) {
|
|
||||||
auto pinArr = pin.as_array();
|
|
||||||
if (pinArr && pinArr->get(1))
|
|
||||||
m_repository.commitPins.push_back(std::make_pair<>(pinArr->get(0)->as_string()->get(), pinArr->get(1)->as_string()->get()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& [key, val] : manifest) {
|
|
||||||
if (key.str() == "repository")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CManifest::SManifestPlugin plugin;
|
|
||||||
|
|
||||||
if (!validManifestName(key.str())) {
|
|
||||||
m_good = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.name = key;
|
|
||||||
m_plugins.push_back(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& plugin : m_plugins) {
|
|
||||||
plugin.description = manifest[plugin.name]["description"].value_or("?");
|
|
||||||
plugin.output = manifest[plugin.name]["output"].value_or("?");
|
|
||||||
plugin.since = manifest[plugin.name]["since_hyprland"].value_or(0);
|
|
||||||
auto authors = manifest[plugin.name]["authors"].as_array();
|
|
||||||
if (authors) {
|
|
||||||
for (auto&& a : *authors) {
|
|
||||||
plugin.authors.push_back(a.as_string()->value_or("?"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto author = manifest[plugin.name]["author"].value_or("");
|
|
||||||
if (!std::string{author}.empty())
|
|
||||||
plugin.authors.push_back(author);
|
|
||||||
}
|
|
||||||
auto buildSteps = manifest[plugin.name]["build"].as_array();
|
|
||||||
if (buildSteps) {
|
|
||||||
for (auto&& s : *buildSteps) {
|
|
||||||
plugin.buildSteps.push_back(s.as_string()->value_or("?"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.output.empty() || plugin.buildSteps.empty()) {
|
|
||||||
m_good = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ???
|
|
||||||
m_good = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
enum eManifestType {
|
|
||||||
MANIFEST_HYPRLOAD,
|
|
||||||
MANIFEST_HYPRPM
|
|
||||||
};
|
|
||||||
|
|
||||||
class CManifest {
|
|
||||||
public:
|
|
||||||
CManifest(const eManifestType type, const std::string& path);
|
|
||||||
|
|
||||||
struct SManifestPlugin {
|
|
||||||
std::string name;
|
|
||||||
std::string description;
|
|
||||||
std::string version;
|
|
||||||
std::vector<std::string> authors;
|
|
||||||
std::vector<std::string> buildSteps;
|
|
||||||
std::string output;
|
|
||||||
int since = 0;
|
|
||||||
bool failed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {
|
|
||||||
std::string name;
|
|
||||||
std::vector<std::string> authors;
|
|
||||||
std::vector<std::pair<std::string, std::string>> commitPins;
|
|
||||||
} m_repository;
|
|
||||||
|
|
||||||
std::vector<SManifestPlugin> m_plugins;
|
|
||||||
bool m_good = true;
|
|
||||||
};
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#include "Plugin.hpp"
|
|
||||||
|
|
||||||
SPluginRepoIdentifier SPluginRepoIdentifier::fromUrl(const std::string& url) {
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_URL, .url = url};
|
|
||||||
}
|
|
||||||
|
|
||||||
SPluginRepoIdentifier SPluginRepoIdentifier::fromName(const std::string& name) {
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_NAME, .name = name};
|
|
||||||
}
|
|
||||||
|
|
||||||
SPluginRepoIdentifier SPluginRepoIdentifier::fromAuthorName(const std::string& author, const std::string& name) {
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_AUTHOR_NAME, .name = name, .author = author};
|
|
||||||
}
|
|
||||||
|
|
||||||
SPluginRepoIdentifier SPluginRepoIdentifier::fromString(const std::string& string) {
|
|
||||||
if (string.find(':') != std::string::npos) {
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_URL, .url = string};
|
|
||||||
} else {
|
|
||||||
auto slashPos = string.find('/');
|
|
||||||
if (slashPos != std::string::npos) {
|
|
||||||
std::string author = string.substr(0, slashPos);
|
|
||||||
std::string name = string.substr(slashPos + 1, string.size() - slashPos - 1);
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_AUTHOR_NAME, .name = name, .author = author};
|
|
||||||
} else {
|
|
||||||
return SPluginRepoIdentifier{.type = IDENTIFIER_NAME, .name = string};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SPluginRepoIdentifier::toString() const {
|
|
||||||
switch (type) {
|
|
||||||
case IDENTIFIER_NAME: return name;
|
|
||||||
case IDENTIFIER_AUTHOR_NAME: return author + '/' + name;
|
|
||||||
case IDENTIFIER_URL: return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SPluginRepoIdentifier::matches(const std::string& url, const std::string& name, const std::string& author) const {
|
|
||||||
switch (type) {
|
|
||||||
case IDENTIFIER_URL: return this->url == url;
|
|
||||||
case IDENTIFIER_NAME: return this->name == name;
|
|
||||||
case IDENTIFIER_AUTHOR_NAME: return this->author == author && this->name == name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct SPlugin {
|
|
||||||
std::string name;
|
|
||||||
std::string filename;
|
|
||||||
bool enabled = false;
|
|
||||||
bool failed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SPluginRepository {
|
|
||||||
std::string url;
|
|
||||||
std::string rev;
|
|
||||||
std::string name;
|
|
||||||
std::string author;
|
|
||||||
std::vector<SPlugin> plugins;
|
|
||||||
std::string hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ePluginRepoIdentifierType {
|
|
||||||
IDENTIFIER_URL,
|
|
||||||
IDENTIFIER_NAME,
|
|
||||||
IDENTIFIER_AUTHOR_NAME
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SPluginRepoIdentifier {
|
|
||||||
ePluginRepoIdentifierType type;
|
|
||||||
std::string url = "";
|
|
||||||
std::string name = "";
|
|
||||||
std::string author = "";
|
|
||||||
|
|
||||||
static SPluginRepoIdentifier fromString(const std::string& string);
|
|
||||||
static SPluginRepoIdentifier fromUrl(const std::string& Url);
|
|
||||||
static SPluginRepoIdentifier fromName(const std::string& name);
|
|
||||||
static SPluginRepoIdentifier fromAuthorName(const std::string& author, const std::string& name);
|
|
||||||
std::string toString() const;
|
|
||||||
bool matches(const std::string& url, const std::string& name, const std::string& author) const;
|
|
||||||
};
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include "Plugin.hpp"
|
|
||||||
|
|
||||||
enum eHeadersErrors {
|
|
||||||
HEADERS_OK = 0,
|
|
||||||
HEADERS_NOT_HYPRLAND,
|
|
||||||
HEADERS_MISSING,
|
|
||||||
HEADERS_CORRUPTED,
|
|
||||||
HEADERS_MISMATCHED,
|
|
||||||
HEADERS_ABI_MISMATCH,
|
|
||||||
HEADERS_DUPLICATED
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eNotifyIcons {
|
|
||||||
ICON_WARNING = 0,
|
|
||||||
ICON_INFO,
|
|
||||||
ICON_HINT,
|
|
||||||
ICON_ERROR,
|
|
||||||
ICON_CONFUSED,
|
|
||||||
ICON_OK,
|
|
||||||
ICON_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ePluginLoadStateReturn {
|
|
||||||
LOADSTATE_OK = 0,
|
|
||||||
LOADSTATE_FAIL,
|
|
||||||
LOADSTATE_PARTIAL_FAIL,
|
|
||||||
LOADSTATE_HEADERS_OUTDATED,
|
|
||||||
LOADSTATE_HYPRLAND_UPDATED
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHyprlandVersion {
|
|
||||||
std::string branch;
|
|
||||||
std::string hash;
|
|
||||||
std::string date;
|
|
||||||
std::string abiHash;
|
|
||||||
int commits = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPluginManager {
|
|
||||||
public:
|
|
||||||
CPluginManager();
|
|
||||||
|
|
||||||
bool addNewPluginRepo(const std::string& url, const std::string& rev);
|
|
||||||
bool removePluginRepo(const SPluginRepoIdentifier identifier);
|
|
||||||
|
|
||||||
eHeadersErrors headersValid();
|
|
||||||
bool updateHeaders(bool force = false);
|
|
||||||
bool updatePlugins(bool forceUpdateAll);
|
|
||||||
|
|
||||||
void listAllPlugins();
|
|
||||||
|
|
||||||
bool enablePlugin(const SPluginRepoIdentifier identifier);
|
|
||||||
bool disablePlugin(const SPluginRepoIdentifier identifier);
|
|
||||||
ePluginLoadStateReturn ensurePluginsLoadState(bool forceReload = false);
|
|
||||||
|
|
||||||
bool loadUnloadPlugin(const std::string& path, bool load);
|
|
||||||
SHyprlandVersion getHyprlandVersion(bool running = true);
|
|
||||||
|
|
||||||
void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message);
|
|
||||||
|
|
||||||
bool hasDeps();
|
|
||||||
|
|
||||||
bool m_bVerbose = false;
|
|
||||||
bool m_bNoShallow = false;
|
|
||||||
std::string m_szCustomHlUrl, m_szUsername;
|
|
||||||
|
|
||||||
// will delete recursively if exists!!
|
|
||||||
bool createSafeDirectory(const std::string& path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string headerError(const eHeadersErrors err);
|
|
||||||
std::string headerErrorShort(const eHeadersErrors err);
|
|
||||||
|
|
||||||
std::string m_szWorkingPluginDirectory;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::unique_ptr<CPluginManager> g_pPluginManager;
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Colors {
|
|
||||||
constexpr const char* RED = "\x1b[31m";
|
|
||||||
constexpr const char* GREEN = "\x1b[32m";
|
|
||||||
constexpr const char* YELLOW = "\x1b[33m";
|
|
||||||
constexpr const char* BLUE = "\x1b[34m";
|
|
||||||
constexpr const char* MAGENTA = "\x1b[35m";
|
|
||||||
constexpr const char* CYAN = "\x1b[36m";
|
|
||||||
constexpr const char* RESET = "\x1b[0m";
|
|
||||||
};
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
namespace Debug {
|
|
||||||
template <typename... Args>
|
|
||||||
void die(std::format_string<Args...> fmt, Args&&... args) {
|
|
||||||
const std::string logMsg = std::vformat(fmt.get(), std::make_format_args(args...));
|
|
||||||
|
|
||||||
std::cout << "\n[ERR] " << logMsg << "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <string>
|
|
||||||
#include "Colors.hpp"
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) {
|
|
||||||
std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET);
|
|
||||||
ret += std::vformat(fmt, std::make_format_args(args...));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string successString(const std::string_view fmt, Args&&... args) {
|
|
||||||
return statusString("✔", Colors::GREEN, fmt, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string failureString(const std::string_view fmt, Args&&... args) {
|
|
||||||
return statusString("✖", Colors::RED, fmt, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string verboseString(const std::string_view fmt, Args&&... args) {
|
|
||||||
return statusString("[v]", Colors::BLUE, fmt, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string infoString(const std::string_view fmt, Args&&... args) {
|
|
||||||
return statusString("→", Colors::RESET, fmt, args...);
|
|
||||||
}
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
||||||
#include "Sys.hpp"
|
|
||||||
#include "Die.hpp"
|
|
||||||
#include "StringUtils.hpp"
|
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include <print>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <hyprutils/os/Process.hpp>
|
|
||||||
#include <hyprutils/string/VarList.hpp>
|
|
||||||
|
|
||||||
using namespace Hyprutils::OS;
|
|
||||||
using namespace Hyprutils::String;
|
|
||||||
|
|
||||||
inline constexpr std::array<std::string_view, 3> SUPERUSER_BINARIES = {
|
|
||||||
"sudo",
|
|
||||||
"doas",
|
|
||||||
"run0",
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string validSubinsAsStr() {
|
|
||||||
std::ostringstream oss;
|
|
||||||
auto it = SUPERUSER_BINARIES.begin();
|
|
||||||
if (it != SUPERUSER_BINARIES.end()) {
|
|
||||||
oss << *it++;
|
|
||||||
for (; it != SUPERUSER_BINARIES.end(); ++it)
|
|
||||||
oss << ", " << *it;
|
|
||||||
}
|
|
||||||
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool executableExistsInPath(const std::string& exe) {
|
|
||||||
const char* PATHENV = std::getenv("PATH");
|
|
||||||
if (!PATHENV)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CVarList paths(PATHENV, 0, ':', true);
|
|
||||||
std::error_code ec;
|
|
||||||
|
|
||||||
for (const auto& PATH : paths) {
|
|
||||||
std::filesystem::path candidate = std::filesystem::path(PATH) / exe;
|
|
||||||
if (!std::filesystem::exists(candidate, ec) || ec)
|
|
||||||
continue;
|
|
||||||
if (!std::filesystem::is_regular_file(candidate, ec) || ec)
|
|
||||||
continue;
|
|
||||||
auto perms = std::filesystem::status(candidate, ec).permissions();
|
|
||||||
if (ec)
|
|
||||||
continue;
|
|
||||||
if ((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string subin() {
|
|
||||||
static std::string bin;
|
|
||||||
static bool once = true;
|
|
||||||
if (!once)
|
|
||||||
return bin;
|
|
||||||
|
|
||||||
for (const auto& BIN : SUPERUSER_BINARIES) {
|
|
||||||
if (!executableExistsInPath(std::string{BIN}))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bin = BIN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
once = false;
|
|
||||||
|
|
||||||
if (bin.empty())
|
|
||||||
Debug::die("{}", failureString("No valid superuser binary present. Supported: {}", validSubinsAsStr()));
|
|
||||||
|
|
||||||
return bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool verifyStringValid(const std::string& s) {
|
|
||||||
return std::ranges::none_of(s, [](const char& c) { return c == '`' || c == '$' || c == '(' || c == ')' || c == '\'' || c == '"'; });
|
|
||||||
}
|
|
||||||
|
|
||||||
int NSys::getUID() {
|
|
||||||
const auto UID = getuid();
|
|
||||||
const auto PWUID = getpwuid(UID);
|
|
||||||
return PWUID ? PWUID->pw_uid : UID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NSys::getEUID() {
|
|
||||||
const auto UID = geteuid();
|
|
||||||
const auto PWUID = getpwuid(UID);
|
|
||||||
return PWUID ? PWUID->pw_uid : UID;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NSys::isSuperuser() {
|
|
||||||
return getuid() != geteuid() || geteuid() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NSys::root::cacheSudo() {
|
|
||||||
// "caches" the sudo so that the prompt later doesn't pop up in a weird spot
|
|
||||||
// sudo will not ask us again for a moment
|
|
||||||
CProcess proc(subin(), {"echo", "hyprland"});
|
|
||||||
proc.runSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NSys::root::dropSudo() {
|
|
||||||
if (subin() != "sudo") {
|
|
||||||
std::println("{}", infoString("Don't know how to drop timestamp for '{}', ignoring.", subin()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CProcess proc(subin(), {"-k"});
|
|
||||||
proc.runSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NSys::root::createDirectory(const std::string& path, const std::string& mode) {
|
|
||||||
if (!verifyStringValid(path))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; }))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CProcess proc(subin(), {"mkdir", "-p", "-m", mode, path});
|
|
||||||
|
|
||||||
return proc.runSync() && proc.exitCode() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NSys::root::removeRecursive(const std::string& path) {
|
|
||||||
if (!verifyStringValid(path))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
const std::string PATH_ABSOLUTE = std::filesystem::canonical(path, ec);
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!PATH_ABSOLUTE.starts_with("/var/cache/hyprpm"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CProcess proc(subin(), {"rm", "-fr", PATH_ABSOLUTE});
|
|
||||||
|
|
||||||
return proc.runSync() && proc.exitCode() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NSys::root::install(const std::string& what, const std::string& where, const std::string& mode) {
|
|
||||||
if (!verifyStringValid(what) || !verifyStringValid(where))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; }))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CProcess proc(subin(), {"install", "-m" + mode, "-o", "0", "-g", "0", what, where});
|
|
||||||
|
|
||||||
return proc.runSync() && proc.exitCode() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NSys::root::runAsSuperuserUnsafe(const std::string& cmd) {
|
|
||||||
CProcess proc(subin(), {"/bin/sh", "-c", cmd});
|
|
||||||
|
|
||||||
if (!proc.runSync())
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return proc.stdOut();
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace NSys {
|
|
||||||
bool isSuperuser();
|
|
||||||
int getUID();
|
|
||||||
int getEUID();
|
|
||||||
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
namespace root {
|
|
||||||
void cacheSudo();
|
|
||||||
void dropSudo();
|
|
||||||
|
|
||||||
//
|
|
||||||
[[nodiscard("Discarding could lead to vulnerabilities and bugs")]] bool createDirectory(const std::string& path, const std::string& mode);
|
|
||||||
[[nodiscard("Discarding could lead to vulnerabilities and bugs")]] bool removeRecursive(const std::string& path);
|
|
||||||
[[nodiscard("Discarding could lead to vulnerabilities and bugs")]] bool install(const std::string& what, const std::string& where, const std::string& mode);
|
|
||||||
|
|
||||||
// Do not use this unless absolutely necessary!
|
|
||||||
std::string runAsSuperuserUnsafe(const std::string& cmd);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
#include "helpers/Colors.hpp"
|
|
||||||
#include "helpers/StringUtils.hpp"
|
|
||||||
#include "core/PluginManager.hpp"
|
|
||||||
#include "core/DataState.hpp"
|
|
||||||
#include "helpers/Sys.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <print>
|
|
||||||
|
|
||||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
|
||||||
using namespace Hyprutils::Utils;
|
|
||||||
|
|
||||||
constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
|
||||||
┃
|
|
||||||
┣ add <url> [git rev] → Install a new plugin repository from git. Git revision
|
|
||||||
┃ is optional, when set, commit locks are ignored.
|
|
||||||
┣ remove <url|name|author/name> → Remove an installed plugin repository.
|
|
||||||
┣ enable <name|author/name> → Enable a plugin.
|
|
||||||
┣ disable <name|author/name> → Disable a plugin.
|
|
||||||
┣ update → Check and update all plugins if needed.
|
|
||||||
┣ reload → Reload hyprpm state. Ensure all enabled plugins are loaded.
|
|
||||||
┣ list → List all installed plugins.
|
|
||||||
┣ purge-cache → Remove the entire hyprpm cache, built plugins, hyprpm settings and headers.
|
|
||||||
┃
|
|
||||||
┣ Flags:
|
|
||||||
┃
|
|
||||||
┣ --notify | -n → Send a hyprland notification confirming successful plugin load.
|
|
||||||
┃ Warnings/Errors trigger notifications regardless of this flag.
|
|
||||||
┣ --help | -h → Show this menu.
|
|
||||||
┣ --verbose | -v → Enable too much logging.
|
|
||||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f).
|
|
||||||
┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources.
|
|
||||||
┣ --hl-url | → Pass a custom hyprland source url.
|
|
||||||
┗
|
|
||||||
)#";
|
|
||||||
|
|
||||||
int main(int argc, char** argv, char** envp) {
|
|
||||||
std::vector<std::string> ARGS{argc};
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
ARGS[i] = std::string{argv[i]};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.size() < 2) {
|
|
||||||
std::println(stderr, "{}", HELP);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> command;
|
|
||||||
bool notify = false, verbose = false, force = false, noShallow = false;
|
|
||||||
std::string customHlUrl;
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
if (ARGS[i].starts_with("-")) {
|
|
||||||
if (ARGS[i] == "--help" || ARGS[i] == "-h") {
|
|
||||||
std::println("{}", HELP);
|
|
||||||
return 0;
|
|
||||||
} else if (ARGS[i] == "--notify" || ARGS[i] == "-n") {
|
|
||||||
notify = true;
|
|
||||||
} else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") {
|
|
||||||
// TODO: Deprecated since v.053.0. Remove in version>0.56.0
|
|
||||||
std::println(stderr, "{}", failureString("Deprececated flag."));
|
|
||||||
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] -n flag is deprecated, see hyprpm --help.");
|
|
||||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
|
||||||
verbose = true;
|
|
||||||
} else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") {
|
|
||||||
noShallow = true;
|
|
||||||
} else if (ARGS[i] == "--hl-url") {
|
|
||||||
if (i + 1 >= argc) {
|
|
||||||
std::println(stderr, "Missing argument for --hl-url");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
customHlUrl = ARGS[i + 1];
|
|
||||||
i++;
|
|
||||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
|
||||||
force = true;
|
|
||||||
std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing."));
|
|
||||||
} else {
|
|
||||||
std::println(stderr, "Unrecognized option {}", ARGS[i]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
command.push_back(ARGS[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.empty()) {
|
|
||||||
std::println(stderr, "{}", HELP);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
|
||||||
g_pPluginManager->m_bVerbose = verbose;
|
|
||||||
g_pPluginManager->m_bNoShallow = noShallow;
|
|
||||||
g_pPluginManager->m_szCustomHlUrl = customHlUrl;
|
|
||||||
|
|
||||||
if (command[0] == "add") {
|
|
||||||
if (command.size() < 2) {
|
|
||||||
std::println(stderr, "{}", failureString("Not enough args for add."));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string rev = "";
|
|
||||||
if (command.size() >= 3)
|
|
||||||
rev = command[2];
|
|
||||||
|
|
||||||
const auto HLVER = g_pPluginManager->getHyprlandVersion();
|
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
|
|
||||||
if (GLOBALSTATE.headersAbiCompiled != HLVER.abiHash) {
|
|
||||||
std::println(stderr, "{}", failureString("Headers outdated, please run hyprpm update."));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
|
|
||||||
g_pPluginManager->updateHeaders(false);
|
|
||||||
|
|
||||||
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
|
|
||||||
} else if (command[0] == "remove") {
|
|
||||||
if (command.size() < 2) {
|
|
||||||
std::println(stderr, "{}", failureString("Not enough args for remove."));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
|
|
||||||
return g_pPluginManager->removePluginRepo(SPluginRepoIdentifier::fromString(command[1])) ? 0 : 1;
|
|
||||||
} else if (command[0] == "update") {
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
|
|
||||||
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
|
|
||||||
bool headers = g_pPluginManager->updateHeaders(force);
|
|
||||||
|
|
||||||
if (headers) {
|
|
||||||
const auto HLVER = g_pPluginManager->getHyprlandVersion(false);
|
|
||||||
auto GLOBALSTATE = DataState::getGlobalState();
|
|
||||||
const auto COMPILEDOUTDATED = HLVER.abiHash != GLOBALSTATE.headersAbiCompiled;
|
|
||||||
|
|
||||||
bool ret1 = g_pPluginManager->updatePlugins(!headersValid || force || COMPILEDOUTDATED);
|
|
||||||
|
|
||||||
if (!ret1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
auto ret2 = g_pPluginManager->ensurePluginsLoadState();
|
|
||||||
|
|
||||||
if (ret2 == LOADSTATE_HYPRLAND_UPDATED)
|
|
||||||
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Updated plugins, but Hyprland was updated. Please restart Hyprland.");
|
|
||||||
|
|
||||||
if (ret2 != LOADSTATE_OK)
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
|
|
||||||
}
|
|
||||||
} else if (command[0] == "enable") {
|
|
||||||
if (command.size() < 2) {
|
|
||||||
std::println(stderr, "{}", failureString("Not enough args for enable."));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_pPluginManager->enablePlugin(SPluginRepoIdentifier::fromString(command[1]))) {
|
|
||||||
std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)"));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
|
|
||||||
auto ret = g_pPluginManager->ensurePluginsLoadState();
|
|
||||||
|
|
||||||
if (ret == LOADSTATE_HYPRLAND_UPDATED)
|
|
||||||
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Enabled plugin, but Hyprland was updated. Please restart Hyprland.");
|
|
||||||
|
|
||||||
if (ret != LOADSTATE_OK)
|
|
||||||
return 1;
|
|
||||||
} else if (command[0] == "disable") {
|
|
||||||
if (command.size() < 2) {
|
|
||||||
std::println(stderr, "{}", failureString("Not enough args for disable."));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_pPluginManager->disablePlugin(SPluginRepoIdentifier::fromString(command[1]))) {
|
|
||||||
std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)"));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
|
|
||||||
auto ret = g_pPluginManager->ensurePluginsLoadState();
|
|
||||||
|
|
||||||
if (ret != LOADSTATE_OK)
|
|
||||||
return 1;
|
|
||||||
} else if (command[0] == "reload") {
|
|
||||||
auto ret = g_pPluginManager->ensurePluginsLoadState(force);
|
|
||||||
|
|
||||||
if (ret != LOADSTATE_OK) {
|
|
||||||
switch (ret) {
|
|
||||||
case LOADSTATE_FAIL:
|
|
||||||
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
|
|
||||||
case LOADSTATE_HEADERS_OUTDATED:
|
|
||||||
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins: Outdated headers. Please run hyprpm update manually.");
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} else if (notify) {
|
|
||||||
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
|
||||||
}
|
|
||||||
} else if (command[0] == "purge-cache") {
|
|
||||||
NSys::root::cacheSudo();
|
|
||||||
CScopeGuard x([] { NSys::root::dropSudo(); });
|
|
||||||
DataState::purgeAllCache();
|
|
||||||
} else if (command[0] == "list") {
|
|
||||||
g_pPluginManager->listAllPlugins();
|
|
||||||
} else {
|
|
||||||
std::println(stderr, "{}", HELP);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
#include "CProgressBar.hpp"
|
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <cmath>
|
|
||||||
#include <format>
|
|
||||||
#include <print>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <sstream>
|
|
||||||
#include <hyprutils/memory/Casts.hpp>
|
|
||||||
#include "../helpers/Colors.hpp"
|
|
||||||
|
|
||||||
using namespace Hyprutils::Memory;
|
|
||||||
|
|
||||||
static winsize getTerminalSize() {
|
|
||||||
winsize w{};
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clearCurrentLine() {
|
|
||||||
std::print("\r\33[2K"); // ansi escape sequence to clear entire line
|
|
||||||
}
|
|
||||||
|
|
||||||
void CProgressBar::printMessageAbove(const std::string& msg) {
|
|
||||||
clearCurrentLine();
|
|
||||||
std::print("\r{}\n", msg);
|
|
||||||
|
|
||||||
print(); // reprint bar underneath
|
|
||||||
}
|
|
||||||
|
|
||||||
void CProgressBar::print() {
|
|
||||||
const auto w = getTerminalSize();
|
|
||||||
|
|
||||||
if (m_bFirstPrint) {
|
|
||||||
std::print("\n");
|
|
||||||
m_bFirstPrint = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCurrentLine();
|
|
||||||
|
|
||||||
float percentDone = 0.0f;
|
|
||||||
if (m_fPercentage >= 0.0f)
|
|
||||||
percentDone = m_fPercentage;
|
|
||||||
else {
|
|
||||||
// check for divide-by-zero
|
|
||||||
percentDone = m_iMaxSteps > 0 ? sc<float>(m_iSteps) / m_iMaxSteps : 0.0f;
|
|
||||||
}
|
|
||||||
// clamp to ensure no overflows (sanity check)
|
|
||||||
percentDone = std::clamp(percentDone, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
const size_t BARWIDTH = std::clamp<size_t>(w.ws_col - m_szCurrentMessage.length() - 2, 0, 50);
|
|
||||||
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << ' ' << Colors::GREEN;
|
|
||||||
|
|
||||||
size_t filled = std::floor(percentDone * BARWIDTH);
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
for (; i < filled; ++i)
|
|
||||||
oss << "━";
|
|
||||||
|
|
||||||
if (i < BARWIDTH) {
|
|
||||||
oss << "╍" << Colors::RESET;
|
|
||||||
++i;
|
|
||||||
for (; i < BARWIDTH; ++i)
|
|
||||||
oss << "━";
|
|
||||||
} else
|
|
||||||
oss << Colors::RESET;
|
|
||||||
|
|
||||||
if (m_fPercentage >= 0.0f)
|
|
||||||
oss << " " << std::format("{}%", sc<int>(percentDone * 100.0)) << ' ';
|
|
||||||
else
|
|
||||||
oss << " " << std::format("{} / {}", m_iSteps, m_iMaxSteps) << ' ';
|
|
||||||
|
|
||||||
std::print("{} {}", oss.str(), m_szCurrentMessage);
|
|
||||||
std::fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class CProgressBar {
|
|
||||||
public:
|
|
||||||
void print();
|
|
||||||
void printMessageAbove(const std::string& msg);
|
|
||||||
|
|
||||||
std::string m_szCurrentMessage = "";
|
|
||||||
size_t m_iSteps = 0;
|
|
||||||
size_t m_iMaxSteps = 0;
|
|
||||||
float m_fPercentage = -1; // if != -1, use percentage
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_bFirstPrint = true;
|
|
||||||
};
|
|
||||||