hyprland-wiki/content/Contributing and Debugging/PR-Guidelines.md
2025-07-24 19:24:27 +03:00

4.6 KiB

title
PR Guidelines

PR Requirements

  • Clean, not hacky code
  • Described changes and why they were there
  • Following the style (see below)

Code Style

Please read this if you are submitting a PR, in order to minimize the amount of style nits received, and save the time for the maintainers.

Before you submit

Make sure you ran clang-format: clang-format -i src/**/*{cpp,hpp}

Check if your changes don't violate clang-tidy. Usually this is built into your IDE.

Clang-format

This is non-negotiable. Your code must be formatted.

Clang-tidy

Clang-tidy violations are not hard requirements, but please try to minimize them, and only ignore them if it's absolutely necessary.

I've tweaked it so that in 99% of cases you absolutely should fix it.

Other

Some stuff clang-tidy / clang-format won't catch:

  • No uninitialized primitives (int, float, double, size_t, etc.)
  • No short ifs. if your if/else body contains 1 line (not 1 statement) do not put {} around it.
  • The above rule does not apply to loops / etc
  • Consider adding a ; inside of empty function bodies
  • Whenever you're initializing vectors arrays or maps with a lot of elements, add a , after the last element to make the styling nicer
  • Consider forward-declaring things in headers if possible instead of including. Speeds up compile times.
  • no using namespace std;, and using namespace (anything else) is only allowed in source files, not headers.
  • prefer guards rather than nesting. if(!valid) return; is much better than if (valid) { /* a billion things */ }

Naming conventions

Although we've used hungarian notation in the past, we are moving away from it. The current, and new code, should use camelCase with an m_ prefix if the variable is a member of a class. (not a struct)

Additionally:

  • classes have a prefix of C: CMyClass
  • structs have a prefix of S: SMyStruct
  • namespaces have a prefix of N: NMyNamespace
  • interfaces have a prefix of I: IMyInterface
  • global pointers for singletons have a prefix of g_: g_someManager
  • constant variables are in CAPS: const auto MYVARIABLE = ...

General code requirements

No raw pointers

This is a simple rule - don't use raw pointers (e.g. CMyClass*) unless absolutely necessary. You have UP, SP and WP at your disposal. These are unique, shared and weak pointers respectively.

No malloc

Unless absolutely necessary, do not use malloc / free. You will forget to free the memory.

Avoid dubious cleanups

If a function is a C-style allocator, e.g. some_c_call_make_new(), it will likely require a some_c_call_free(). In these cases, either:

  • wrap the thing in a C++ class, or
  • if used only within one function, use a CScopeGuard to always free it when the function exits.

Use the STL

Generally, use the STL instead of trying to reinvent the wheel.

Use hyprutils

Hyprutils provides a lot of utilities that are well-suited for hyprland (and other hypr* projects) specifically. Use them.

No absolute includes from /src

Imagine this scenario:

src/
   a/
      a.hpp
   b/
      b.hpp

If you are in a.hpp and want to include b.hpp, you must use ../b/b.hpp, and cannot use b/b.hpp. The latter will break plugins.

One exception you might notice in the code is absolute paths from the root are allowed, e.g. protocols/some-protocol.hpp.

Test your changes

Run and test your changes to make sure they work!

Testing and CI

Since #9297, we require each MR that fixes an issue or adds a new feature to include test(s) for the feature, if possible.

The testing framework is incapable of testing visual changes (e.g. graphical effects), and some very niche parts (real HID devices, etc). However, if your change is related to: binds, layouts, config options, window management, hyprctl, dispatchers, keywords, etc. your MR needs tests.

How to run tests locally

In order to run tests locally, build Hyprland, then:

cd hyprtester
../build/hyprtester/hyprtester --plugin ./plugin/hyprtestplugin.so

How to add tests

In order to add a new test, you can either make a new test file, or add a test to an existing file. If you are adding a new test file, remember to end on a clean state: close all windows you've opened, and go back to workspace 1.

If you are adding to an existing test file, find a file that's appropriate for the category of your test.

Tests are done by having a hyprland process active, issuing hyprctl commands, and checking the result with hyprctl queries.

Check the hyprtester/ directory of the source repo for more.