diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..90314ef3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,65 @@ +--- +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 diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 00000000..c6bf34ed --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1 @@ +subprojects/**/* diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..db499035 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,208 @@ +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 diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 00000000..fd5797d5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,15 @@ +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 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 06fc6b5d..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Bug report -about: Found a bug? Report it here! -title: '' -labels: bug -assignees: '' - ---- - -Please consult the issue guidelines at -https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md -BEFORE submitting. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index a0a41238..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Feature request -about: Suggest a feature/change/idea -title: '' -labels: enhancement -assignees: '' - ---- - -Please consult the issue guidelines at -https://github.com/vaxerski/Hyprland/blob/main/docs/ISSUE_GUIDELINES.md -BEFORE submitting. diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml new file mode 100644 index 00000000..9fcaabfb --- /dev/null +++ b/.github/actions/setup_base/action.yml @@ -0,0 +1,123 @@ +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 diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..6b89255a --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,87 @@ +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/**" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 073333bc..75b4b7c5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,11 @@ + + + #### Describe your PR, what does it fix/add? diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 77c9c48b..2ec558ed 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,83 +3,81 @@ name: Build Hyprland on: [push, pull_request, workflow_dispatch] jobs: gcc: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: "Build Hyprland (Arch)" runs-on: ubuntu-latest container: image: archlinux steps: - - name: Get required pacman pkgs - run: | - 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: Set up user - run: | - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - - name: Build wlroots - run: | - su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots" - su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .." - - name: Fix permissions for git - run: | - git config --global --add safe.directory /__w/Hyprland/Hyprland - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 with: - submodules: recursive + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + with: + INSTALL_XORG_PKGS: true + - name: Build Hyprland run: | - git submodule sync --recursive && git submodule update --init --force --recursive - make all + CFLAGS=-Werror CXXFLAGS=-Werror make nopch + - name: Compress and package artifacts run: | mkdir x86_64-pc-linux-gnu mkdir hyprland - mkdir hyprland/example - mkdir hyprland/assets cp ./LICENSE hyprland/ cp build/Hyprland hyprland/ - cp hyprctl/hyprctl hyprland/ - cp subprojects/wlroots/build/libwlroots.so.11032 hyprland/ - cp build/Hyprland hyprland/ + cp build/hyprctl/hyprctl hyprland/ + cp build/hyprpm/hyprpm hyprland/ cp -r example/ hyprland/ cp -r assets/ hyprland/ - tar -cvf Hyprland.tar.xz hyprland + tar -cvJf Hyprland.tar.xz hyprland + - name: Release - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build archive path: Hyprland.tar.xz - meson: - name: "Build Hyprland with Meson (Arch)" + clang-format: + permissions: read-all + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork + name: "Code Style" runs-on: ubuntu-latest container: image: archlinux steps: - - name: Download dependencies + - name: Checkout repository + uses: actions/checkout@v4 + + # - name: clang-format check + # uses: jidicula/clang-format-action@v4.16.0 + # with: + # exclude-regex: ^subprojects$ + + - name: Install clang-format run: | - 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 go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd - - name: Checkout Hyprland - uses: actions/checkout@v3 - with: - submodules: true - - name: Configure + pacman --noconfirm --noprogressbar -Sy clang + + - name: clang-format check + run: .github/workflows/clang-format-check.sh "." "llvm" "^subprojects$" "" + + - name: Save PR head commit SHA + if: failure() && github.event_name == 'pull_request' + shell: bash run: | - meson obj-x86_64-pc-linux-gnu \ - -Ddefault_library=static - - name: Compile - run: ninja -C obj-x86_64-pc-linux-gnu -# - name: Compress artifacts -# run: | -# mkdir x86_64-pc-linux-gnu -# DESTDIR=$PWD/x86_64-pc-linux-gnu meson install -C obj-x86_64-pc-linux-gnu --tags runtime -# tar -cvf x86_64-pc-linux-gnu.tar.xz x86_64-pc-linux-gnu -# - name: Upload artifacts -# uses: actions/upload-artifact@v3 -# with: -# name: Build artifacts (x86_64-pc-linux-gnu) -# path: x86_64-pc-linux-gnu.tar.xz + SHA="${{ github.event.pull_request.head.sha }}" + echo "SHA=$SHA" >> $GITHUB_ENV + - name: Save latest commit SHA if not PR + if: failure() && github.event_name != 'pull_request' + shell: bash + run: echo "SHA=${{ github.sha }}" >> $GITHUB_ENV + + - name: Report failure in job summary + if: failure() + run: | + DEEPLINK="${{ github.server_url }}/${{ github.repository }}/commit/${{ env.SHA }}" + echo -e "Format check failed on commit [${GITHUB_SHA:0:8}]($DEEPLINK) with files:\n$(<$GITHUB_WORKSPACE/failing-files.txt)" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/clang-format-check.sh b/.github/workflows/clang-format-check.sh new file mode 100755 index 00000000..41237aa7 --- /dev/null +++ b/.github/workflows/clang-format-check.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# +# Adapted from https://github.com/jidicula/clang-format-action + +############################################################################### +# check.sh # +############################################################################### +# USAGE: ./entrypoint.sh [] [] +# +# Checks all C/C++/Protobuf/CUDA files (.h, .H, .hpp, .hh, .h++, .hxx and .c, +# .C, .cpp, .cc, .c++, .cxx, .proto, .cu) in the provided GitHub repository path +# (arg1) for conforming to clang-format. If no path is provided or provided path +# is not a directory, all C/C++/Protobuf/CUDA files are checked. If any files +# are incorrectly formatted, the script lists them and exits with 1. +# +# Define your own formatting rules in a .clang-format file at your repository +# root. Otherwise, the provided style guide (arg2) is used as a fallback. + +# format_diff function +# Accepts a filepath argument. The filepath passed to this function must point +# to a C/C++/Protobuf/CUDA file. +format_diff() { + local filepath="$1" + + # Invoke clang-format with dry run and formatting error output + local_format="$(clang-format \ + --dry-run \ + --Werror \ + --style=file \ + --fallback-style="$FALLBACK_STYLE" \ + "${filepath}")" + + local format_status="$?" + if [[ ${format_status} -ne 0 ]]; then + # Append Markdown-bulleted monospaced filepath of failing file to + # summary file. + echo "* \`$filepath\`" >>failing-files.txt + + echo "Failed on file: $filepath" >&2 + echo "$local_format" >&2 + exit_code=1 # flip the global exit code + return "${format_status}" + fi + return 0 +} + +CHECK_PATH="$1" +FALLBACK_STYLE="$2" +EXCLUDE_REGEX="$3" +INCLUDE_REGEX="$4" + +# Set the regex to an empty string regex if nothing was provided +if [[ -z $EXCLUDE_REGEX ]]; then + EXCLUDE_REGEX="^$" +fi + +# Set the filetype regex if nothing was provided. +# Find all C/C++/Protobuf/CUDA files: +# h, H, hpp, hh, h++, hxx +# c, C, cpp, cc, c++, cxx +# ino, pde +# proto +# cu +if [[ -z $INCLUDE_REGEX ]]; then + INCLUDE_REGEX='^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|(ino|pde|proto|cu))$' +fi + +cd "$GITHUB_WORKSPACE" || exit 2 + +if [[ ! -d $CHECK_PATH ]]; then + echo "Not a directory in the workspace, fallback to all files." >&2 + CHECK_PATH="." +fi + +# initialize exit code +exit_code=0 + +# All files improperly formatted will be printed to the output. +src_files=$(find "$CHECK_PATH" -name .git -prune -o -regextype posix-egrep -regex "$INCLUDE_REGEX" -print) + +# check formatting in each source file +IFS=$'\n' # Loop below should separate on new lines, not spaces. +for file in $src_files; do + # Only check formatting if the path doesn't match the regex + if ! [[ ${file} =~ $EXCLUDE_REGEX ]]; then + format_diff "${file}" + fi +done + +# global exit code is flipped to nonzero if any invocation of `format_diff` has +# a formatting difference. +exit "$exit_code" diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 00000000..505829e3 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,28 @@ +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 diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml new file mode 100644 index 00000000..55f4e126 --- /dev/null +++ b/.github/workflows/close-issues.yml @@ -0,0 +1,101 @@ +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}`); + } + } + } diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000..52474c6a --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,12 @@ +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 diff --git a/.github/workflows/man-update.yaml b/.github/workflows/man-update.yaml new file mode 100644 index 00000000..6c0a72f3 --- /dev/null +++ b/.github/workflows/man-update.yaml @@ -0,0 +1,30 @@ +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" diff --git a/.github/workflows/new-pr-comment.yml b/.github/workflows/new-pr-comment.yml new file mode 100644 index 00000000..36ea1909 --- /dev/null +++ b/.github/workflows/new-pr-comment.yml @@ -0,0 +1,45 @@ +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, + }); diff --git a/.github/workflows/nix-build.yaml b/.github/workflows/nix-build.yaml deleted file mode 100644 index bf388ed1..00000000 --- a/.github/workflows/nix-build.yaml +++ /dev/null @@ -1,25 +0,0 @@ -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 - with: - submodules: recursive - - name: Install nix - uses: cachix/install-nix-action@v17 - with: - install_url: https://releases.nixos.org/nix/nix-2.10.3/install - extra_nix_config: | - auto-optimise-store = true - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v10 - with: - name: hyprland - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build Hyprland with default settings - run: nix build --print-build-logs diff --git a/.github/workflows/nix-ci.yml b/.github/workflows/nix-ci.yml new file mode 100644 index 00000000..5b22e992 --- /dev/null +++ b/.github/workflows/nix-ci.yml @@ -0,0 +1,29 @@ +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 diff --git a/.github/workflows/nix-meson-ver-update.yaml b/.github/workflows/nix-meson-ver-update.yaml deleted file mode 100644 index ddeac945..00000000 --- a/.github/workflows/nix-meson-ver-update.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: "Nix & Meson: update version" - -on: [workflow_dispatch] - -jobs: - update: - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v3 - - name: Update flake and meson version - run: | - REGEX="([0-9]+(\.[0-9a-zA-Z]+)+)" - - CRT_REV=$(git show-ref --tags --head --abbrev | head -n 1 | head -c 7) - TAG_REV=$(git show-ref --tags --abbrev | tail -n 1 | head -c 7) - CRT_VER=$(sed -nEe "/$REGEX/{p;q;}" meson.build | awk -F\' '{print $2}') - VERSION=$(git show-ref --tags --abbrev | tail -n 1 | tail -c +20) - - if [[ $TAG_REV = $CRT_REV ]] || [[ $CRT_VER != $VERSION ]]; then - sed -Ei "s/$REGEX/$VERSION/g" meson.build - sed -Ei "s/$REGEX/$VERSION/g" flake.nix - fi - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[gha] bump flake and meson version" diff --git a/.github/workflows/nix-test.yml b/.github/workflows/nix-test.yml new file mode 100644 index 00000000..68357093 --- /dev/null +++ b/.github/workflows/nix-test.yml @@ -0,0 +1,47 @@ +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 diff --git a/.github/workflows/nix-update-inputs.yml b/.github/workflows/nix-update-inputs.yml new file mode 100644 index 00000000..a3084b27 --- /dev/null +++ b/.github/workflows/nix-update-inputs.yml @@ -0,0 +1,44 @@ +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" diff --git a/.github/workflows/nix-update.yaml b/.github/workflows/nix-update.yaml deleted file mode 100644 index 91a5c686..00000000 --- a/.github/workflows/nix-update.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Nix: update lockfile" - -on: [push, 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/update-inputs.sh - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[gha] bump flake inputs" diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 00000000..b46b3795 --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,41 @@ +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 }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cb32972f..09aae111 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,15 +9,41 @@ jobs: source-tarball: runs-on: ubuntu-latest steps: - - name: Checkout Hyprland - id: checkout - uses: actions/checkout@v3 + - 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: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz * + 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 diff --git a/.github/workflows/flawfinder.yml b/.github/workflows/security-checks.yml similarity index 78% rename from .github/workflows/flawfinder.yml rename to .github/workflows/security-checks.yml index e1df95dc..284500e6 100644 --- a/.github/workflows/flawfinder.yml +++ b/.github/workflows/security-checks.yml @@ -1,13 +1,10 @@ -name: Flawfinder +name: Security Checks -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] +on: [push, pull_request] jobs: flawfinder: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork name: Flawfinder Checks runs-on: ubuntu-latest permissions: @@ -16,7 +13,7 @@ jobs: security-events: write steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Scan with Flawfinder uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c diff --git a/.github/workflows/translation-ai-check.yml b/.github/workflows/translation-ai-check.yml new file mode 100644 index 00000000..d6a62a60 --- /dev/null +++ b/.github/workflows/translation-ai-check.yml @@ -0,0 +1,139 @@ +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 diff --git a/.gitignore b/.gitignore index 27b80f06..4e5c2323 100644 --- a/.gitignore +++ b/.gitignore @@ -7,21 +7,44 @@ cmake_install.cmake install_manifest.txt compile_commands.json CTestTestfile.cmake +CPackConfig.cmake +CPackSourceConfig.cmake +hyprland.pc _deps build/ -result +result* +/.pre-commit-config.yaml /.vscode/ +/.idea/ .envrc .cache +.direnv +/.cmake/ +/.worktree/ *.o -*-protocol.c -*-protocol.h +protocols/*.c* +protocols/*.h* .ccls-cache +*.so +src/render/shaders/*.inc +src/render/shaders/Shaders.hpp hyprctl/hyprctl +hyprctl/hw-protocols/*.c* +hyprctl/hw-protocols/*.h* gmon.out *.out -*.tar.gz \ No newline at end of file +*.tar.gz + +PKGBUILD + +src/version.h +hyprpm/Makefile +hyprctl/Makefile +example/hyprland.desktop + +**/.#*.* +**/#*.*# diff --git a/.gitmodules b/.gitmodules index 61cb4cef..638f8ba9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ -[submodule "wlroots"] - path = subprojects/wlroots - url = https://gitlab.freedesktop.org/wlroots/wlroots.git +[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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 06aabd2c..87574b82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,96 +1,680 @@ -cmake_minimum_required(VERSION 3.4) -project(Hyprland - DESCRIPTION "A Modern C++ Wayland Compositor" -) +cmake_minimum_required(VERSION 3.30) + +# Get version +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") -message(STATUS "Configuring Hyprland!") +message(STATUS "Gathering git info") -# Get git info -# hash and branch -execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND bash -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_MESSAGE - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND bash -c "git diff-index --quiet HEAD -- || echo \"dirty\"" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_DIRTY - OUTPUT_STRIP_TRAILING_WHITESPACE) -# -# - -include_directories(. PRIVATE "subprojects/wlroots/include/") -include_directories(. PRIVATE "subprojects/wlroots/build/include/") -add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE ) -add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing) -find_package(Threads REQUIRED) +# Make shader files includable +execute_process(COMMAND ./scripts/generateShaderIncludes.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE HYPR_SHADER_GEN_RESULT) +if(NOT HYPR_SHADER_GEN_RESULT EQUAL 0) + message( + FATAL_ERROR + "Failed to generate shader includes (scripts/generateShaderIncludes.sh), exit code: ${HYPR_SHADER_GEN_RESULT}" + ) +endif() find_package(PkgConfig REQUIRED) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves + +# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not +# provide a .pc file and won't be detected this way +pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2) + +# Find non-pkgconfig udis86, otherwise fallback to subproject +if(NOT udis_dep_FOUND) + find_library(udis_nopc udis86) + if(NOT("${udis_nopc}" MATCHES "udis_nopc-NOTFOUND")) + message(STATUS "Found udis86 at ${udis_nopc}") + 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 + -frtti + -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...") + +find_package(Threads REQUIRED) + +set(GLES_VERSION "GLES3") +find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) +find_package(glslang CONFIG REQUIRED) + +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.91) +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 + lcms2) + +find_package(hyprwayland-scanner 0.3.10 REQUIRED) 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}") -add_executable(Hyprland ${SRCFILES}) +set(TRACY_CPP_FILES "") +if(USE_TRACY) + set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp") + message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES}) +endif() -IF(LEGACY_RENDERER MATCHES true) - message(STATUS "Using the legacy GLES2 renderer!") - add_definitions( -DLEGACY_RENDERER ) -ENDIF(LEGACY_RENDERER MATCHES true) +add_library(hyprland_lib STATIC ${SRCFILES}) +add_executable(Hyprland src/main.cpp ${TRACY_CPP_FILES}) +target_link_libraries(Hyprland hyprland_lib) -IF(NO_XWAYLAND MATCHES true) - message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!") - add_definitions( -DNO_XWAYLAND ) -ENDIF(NO_XWAYLAND MATCHES true) +target_include_directories(hyprland_lib PUBLIC ${deps_INCLUDE_DIRS}) +target_include_directories(Hyprland PUBLIC ${deps_INCLUDE_DIRS}) -IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) - message(STATUS "Configuring Hyprland in Debug with CMake!") - add_definitions( -DHYPRLAND_DEBUG ) -ELSE() - add_compile_options( -O3 ) - message(STATUS "Configuring Hyprland in Release with CMake!") -ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) +set(USE_GPROF OFF) -target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"") -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(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) + message(STATUS "Setting debug flags") -target_link_libraries(Hyprland rt) + if(WITH_ASAN) + message(STATUS "Enabling ASan") + + target_link_libraries(hyprland_lib PUBLIC asan) + target_compile_options(hyprland_lib PUBLIC -fsanitize=address) + 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(USE_TRACY) + message(STATUS "Tracy is turned on") + + option(TRACY_ENABLE "" ON) + option(TRACY_ON_DEMAND "" ON) + add_subdirectory(subprojects/tracy) + + add_compile_options(-fno-omit-frame-pointer) + + 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() + +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_VERSION ${PROJECT_VERSION}) include(CPack) -target_link_libraries(Hyprland PkgConfig::deps) +if(CMAKE_DISABLE_PRECOMPILE_HEADERS) + message(STATUS "Not using precompiled headers") +else() + message(STATUS "Setting precompiled headers") + target_precompile_headers(hyprland_lib PRIVATE + $<$:src/pch/pch.hpp>) +endif() -target_link_libraries(Hyprland - ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us - pixman-1 - OpenGL - GLESv2 - pthread - ${CMAKE_THREAD_LIBS_INIT} - ${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o +message(STATUS "Setting link libraries") + +target_link_libraries( + hyprland_lib + PUBLIC + PkgConfig::aquamarine_dep + PkgConfig::hyprlang_dep + PkgConfig::hyprutils_dep + PkgConfig::hyprcursor_dep + PkgConfig::hyprgraphics_dep + PkgConfig::deps ) -IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin") -ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) \ No newline at end of file +target_link_libraries( + Hyprland + ${LIBRT} + hyprland_lib) +if(udis_dep_FOUND) + 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() + +if(TARGET OpenGL::GL) + target_link_libraries(hyprland_lib PUBLIC OpenGL::EGL OpenGL::GL glslang::glslang glslang::glslang-default-resource-limits glslang::SPIRV Threads::Threads) +else() + target_link_libraries(hyprland_lib PUBLIC OpenGL::EGL OpenGL::GLES3 glslang::glslang glslang::glslang-default-resource-limits glslang::SPIRV Threads::Threads) +endif() + +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" "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) +protocolnew("staging/ext-image-capture-source" "ext-image-capture-source-v1" false) +protocolnew("staging/ext-image-copy-capture" "ext-image-copy-capture-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 +configure_file( + ${CMAKE_SOURCE_DIR}/example/hyprland.desktop.in + ${CMAKE_SOURCE_DIR}/example/hyprland.desktop + @ONLY +) +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() diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..3c41db0e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,96 @@ +## 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. diff --git a/LICENSE b/LICENSE index 4a34d9a9..efdec21a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2022, vaxerski +Copyright (c) 2022-2026, vaxerski All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Makefile b/Makefile index 17163df4..852fcddf 100644 --- a/Makefile +++ b/Makefile @@ -1,164 +1,57 @@ -include config.mk +PREFIX = /usr/local -CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 - -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))) - -DATE=$(shell date "+%d %b %Y") - -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 - -tablet-unstable-v2-protocol.h: - $(WAYLAND_SCANNER) server-header \ - protocols/tablet-unstable-v2.xml $@ - -tablet-unstable-v2-protocol.c: - $(WAYLAND_SCANNER) private-code \ - protocols/tablet-unstable-v2.xml $@ - -tablet-unstable-v2-protocol.o: tablet-unstable-v2-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 - -wlr-output-power-management-unstable-v1-protocol.h: - $(WAYLAND_SCANNER) server-header \ - protocols/wlr-output-power-management-unstable-v1.xml $@ - -wlr-output-power-management-unstable-v1-protocol.c: - $(WAYLAND_SCANNER) private-code \ - protocols/wlr-output-power-management-unstable-v1.xml $@ - -wlr-output-power-management-unstable-v1-protocol.o: wlr-output-power-management-unstable-v1-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 $(nproc) - -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 $(nproc) +stub: + @echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland." release: - 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) + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` debug: - 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) + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DTESTS=true -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build + cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + +nopch: + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build + cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` clear: rm -rf build - rm -f *.o *-protocol.h *-protocol.c - rm -f ./hyprctl/hyprctl - rm -rf ./subprojects/wlroots/build + rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp + rm -f ./hyprctl/hw-protocols/*.cpp ./hyprctl/hw-protocols/*.hpp all: - make config - make release - cd ./hyprctl && make all && cd .. + $(MAKE) clear + $(MAKE) release install: - make clear - make fixwlr - cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../.. - make protocols - make release - cd hyprctl && make all && cd .. - - 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 + cmake --install ./build uninstall: - rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop - rm -f ${PREFIX}/bin/Hyprland - rm -f ${PREFIX}/bin/hyprctl - rm -f /usr/lib/libwlroots.so.11032 - rm -rf ${PREFIX}/share/hyprland + xargs rm < ./build/install_manifest.txt -protocols: 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 tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o +pluginenv: + @echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n" + @exit 1 -fixwlr: - sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build +installheaders: + @if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi - rm -rf ./subprojects/wlroots/build + # 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 -config: - make protocols + cmake --build ./build --config Release --target generate-protocol-headers - make fixwlr + 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 - cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release - cd subprojects/wlroots && ninja -C build/ - - cd subprojects/wlroots && ninja -C build/ install + chmod -R 755 ${PREFIX}/include/hyprland + chmod 755 ${PREFIX}/share/pkgconfig man: pandoc ./docs/Hyprland.1.rst \ @@ -167,7 +60,7 @@ man: --variable=date:"${DATE}" \ --variable=section:1 \ --from rst \ - --to man | gzip -c > /usr/share/man/man1/Hyprland.1.gz + --to man > ./docs/Hyprland.1 pandoc ./docs/hyprctl.1.rst \ --standalone \ @@ -175,4 +68,32 @@ man: --variable=date:"${DATE}" \ --variable=section:1 \ --from rst \ - --to man | gzip -c > /usr/share/man/man1/hyprctl.1.gz + --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 + 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 diff --git a/README.md b/README.md index 4735b279..bb74c4e4 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,22 @@
-banner +banner
-![Badge Workflow] +[![Badge Workflow]][Workflow] [![Badge License]][License] -![Badge Lines] ![Badge Language] [![Badge Pull Requests]][Pull Requests] [![Badge Issues]][Issues] ![Badge Hi Mom]
-[![Badge Discord]][Discord]
-Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks. +Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks. -It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, and more. +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...

@@ -33,42 +32,29 @@ It supports multiple layouts, fancy effects, has a very flexible IPC model allow
- -# Notice - -Hyprland is still in pretty early development compared to some other Wayland compositors. - -Although Hyprland is pretty stable, it may have some bugs. - -### Help Wanted - -Hyprland needs testers!
-Try it out and report bugs / suggestions! # 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 +- Fast and active development +- Not afraid to provide bleeding-edge features - Config reloaded instantly upon saving -- Custom bezier curve based animations -- `wlr_ext` workspaces protocol support -- Dual Kawase blur -- Drop shadows - Fully dynamic workspaces -- Closely follows `wlroots-git` +- Two built-in layouts and more available as plugins - Global keybinds passed to your apps of choice -- Bundled wlroots -- Window/layer fade in/out - Tiling/pseudotiling/floating/fullscreen windows -- Switching workspaces between window modes on the fly -- Special workspace (scratchpad) -- Window/monitor rules +- Special workspaces (scratchpads) +- Window groups (tabbed mode) +- Powerful window/monitor/layer rules - Socket-based IPC -- Event system for bash scripts -- Rounded corners -- Full damage tracking -- Docks support -- Drawing tablet support -- Native IME + Input panels support +- Native IME and Input Panels Support - and much more...
@@ -93,22 +79,13 @@ Try it out and report bugs / suggestions!

-# Stars Over Time - -
- -[![Stars Preview]][Stars] - -
-
- # Special Thanks
-**[wlroots]** - *For their amazing library* +**[wlroots]** - *For powering Hyprland in the past* **[tinywl]** - *For showing how 2 do stuff* @@ -123,8 +100,7 @@ Try it out and report bugs / suggestions! -[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/ -[Discord]: https://discord.gg/hQ9XvMUjjr +[Configure]: https://wiki.hypr.land/Configuring/ [Stars]: https://starchart.cc/hyprwm/Hyprland [Hypr]: https://github.com/hyprwm/Hypr @@ -132,9 +108,10 @@ Try it out and report bugs / suggestions! [Issues]: https://github.com/hyprwm/Hyprland/issues [Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta -[Contribute]: https://wiki.hyprland.org/Contributing-and-Debugging/ -[Install]: https://wiki.hyprland.org/Getting-Started/Installation/ -[Quick Start]: https://wiki.hyprland.org/Getting-Started/Quick-start/ +[Contribute]: https://wiki.hypr.land/Contributing-and-Debugging/ +[Install]: https://wiki.hypr.land/Getting-Started/Installation/ +[Quick Start]: https://wiki.hypr.land/Getting-Started/Master-Tutorial/ +[Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml [License]: LICENSE @@ -145,21 +122,19 @@ Try it out and report bugs / suggestions! [Wayfire]: https://github.com/WayfireWM/wayfire [TinyWl]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/tinywl/tinywl.c [Sway]: https://github.com/swaywm/sway -[DWL]: https://github.com/djpohly/dwl +[DWL]: https://codeberg.org/dwl/dwl -[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg -[Preview A]: https://i.imgur.com/sCafdKQ.png -[Preview B]: https://i.imgur.com/NbrTnZH.png -[Preview C]: https://i.imgur.com/ZA4Fa8R.png +[Preview A]: https://i.ibb.co/XxFY75Mk/greerggergerhtrytghjnyhjn.png +[Preview B]: https://i.ibb.co/C1yTb0r/falf.png +[Preview C]: https://i.ibb.co/2Yc4q835/hyprland-preview-b.png [Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg -[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff [Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland [Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland [Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..187165ce --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# 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` diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..524456c7 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.54.0 diff --git a/assets/header.svg b/assets/header.svg index c8cf8222..a2b32551 100644 --- a/assets/header.svg +++ b/assets/header.svg @@ -1,72 +1,64 @@ - - -
- - - -

Hyprland

-
-
-
-
+ .st4 { + fill: url(#e); + } + + .st5 { + fill: url(#f); + } + + .st6 { + fill: url(#g); + } + + .st7 { + fill: url(#h); + } + + .st8 { + fill: url(#i); + } +