Contributing to Open Source (Sway, wlroots, Chromium)¶
The Warmwind job posting explicitly requires "upstream development, pull requests, and engaging in public review processes." This article covers the contribution workflows for the three codebases Warmwind patches daily -- wlroots/Sway, Chromium, and the Linux kernel -- with real examples, coding conventions, and practical advice for maintaining a downstream fork.
Overview of the Three Workflows¶
graph LR
wlr["wlroots/Sway"] -- "GitHub PR" --> GH["GitHub Review"]
Chrome["Chromium"] -- "git cl upload" --> Gerrit["Gerrit CQ"]
Kernel["Linux Kernel"] -- "git format-patch" --> ML["Mailing List"]
| Project | Repo | Review Tool | CI/CD | Language |
|---|---|---|---|---|
| wlroots | github.com/swaywm/wlroots | GitHub PRs | GitLab CI (freedesktop) | C11 |
| Sway | github.com/swaywm/sway | GitHub PRs | GitLab CI (freedesktop) | C11 |
| Chromium | chromium.googlesource.com | Gerrit | Commit Queue (CQ) | C++, Rust (emerging) |
wlroots / Sway Contribution Workflow¶
Repository and Tooling¶
wlroots and Sway live on GitHub. The canonical contribution method is a GitHub
pull request, though historically the projects used sourcehut
(git.sr.ht/~sircmpwn/) with email patches. The migration to GitHub happened
after Drew DeVault stepped back from active development.
# Clone and set up
git clone https://github.com/swaywm/wlroots.git
cd wlroots
meson setup build
ninja -C build
# Run tests
ninja -C build test
# For Sway, clone separately (depends on system-installed wlroots)
git clone https://github.com/swaywm/sway.git
Reference: wlroots CONTRIBUTING.md
Coding Style¶
wlroots uses a kernel-like C style with specific conventions:
// Correct wlroots style:
// - Brackets on same line (including functions, unlike kernel style)
// - C11, POSIX, no GNU extensions
// - Tabs for indentation
// - snake_case for everything
// - wlr_ prefix for public API, no prefix for static functions
static void handle_new_output(struct wl_listener *listener, void *data) {
struct wlr_output *output = data;
struct server *server = wl_container_of(listener, server, new_output);
if (!wlr_output_init_render(output, server->allocator,
server->renderer)) {
wlr_log(WLR_ERROR, "Failed to init output render");
return;
}
struct wlr_output_state state;
wlr_output_state_init(&state);
wlr_output_state_set_enabled(&state, true);
// NOTE: Always check return values
if (!wlr_output_commit_state(output, &state)) {
wlr_output_state_finish(&state);
return;
}
wlr_output_state_finish(&state);
}
Key rules from CONTRIBUTING.md:
- C11 + POSIX -- no GNU extensions (
-std=c11 -D_POSIX_C_SOURCE=200809L). - Brackets always on the same line, including function definitions.
- Always include brackets for single-statement
if/for/while. - Linear history -- every commit must be small, stand-alone, and functional. No "fixup" commits.
- No merge commits -- rebase your branch before submission.
Commit Message Format¶
subsystem: short summary (max 50 chars)
Optional longer description explaining the why, not the what.
Reference GitHub issues with #123. Wrap at 72 characters.
The first line completes the sentence: "When applied, this commit will..."
Good: "output: fix damage tracking for rotated outputs"
Bad: "Fixed bug" or "Updated code"
Real wlroots commit message examples:
render/vulkan: fix format feature detection
The previous code checked for optimal tiling features even when
using linear tiling. This caused some formats to be incorrectly
rejected on drivers that only support linear tiling for those formats.
Fixes #3891
types/output: add wlr_output_state_copy()
This is needed for compositors that want to modify an output state
before committing it, without re-creating the entire state from scratch.
Review Culture¶
- Discuss first: Visit
#sway-develon Libera Chat before starting significant work. The maintainers may redirect your approach or tell you a feature is unwanted. - Small PRs: Large changes should be split into a series of small, reviewable commits. Each commit must compile and pass tests independently.
- Be patient: The project has few maintainers (primarily Simon Ser / emersion). Review cycles can take weeks.
- Respond to feedback gracefully: Force-push updated commits (rebased, not amended with fixups).
Chromium Contribution Workflow¶
Account Setup¶
- Sign in at chromium-review.googlesource.com to create your Gerrit account.
- Set your real name at
chromium-review.googlesource.com/#/settings/. - Complete the Individual Contributor License Agreement.
- Join the
chromium-dev@chromium.orgmailing list for announcements.
Reference: Contributing to Chromium
Checkout and Build¶
# Install depot_tools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PWD/depot_tools:$PATH"
# Fetch source (~30 GB, ~1 hour)
mkdir chromium && cd chromium
fetch --nohooks chromium
cd src
gclient sync
# Configure build
gn gen out/Default --args='is_debug=true is_component_build=true'
# Build chrome target (~4 hours first time, ~16000 targets)
autoninja -C out/Default chrome
The Gerrit / CQ Workflow¶
graph LR
Local["Local Branch"] -- "git cl upload" --> CL["Gerrit CL"]
CL -- "Code Review" --> CR["+2 from OWNER"]
CR -- "CQ +2" --> CQ["Commit Queue"]
CQ -- "tests pass" --> Land["Landed"]
Step by step:
# 1. Create a branch
git new-branch my-feature
# 2. Make changes, commit locally
git commit -am "component: short description
Longer description of the change.
Bug: 123456
Change-Id: Iabcdef1234567890"
# 3. Upload to Gerrit for review
git cl upload
# 4. Address review comments, amend, re-upload
git commit --amend
git cl upload
# 5. When approved: reviewer sets CQ+2 or you set it yourself
# The CQ runs all tests and lands the CL if green
Understanding the Chromium Codebase¶
Chromium has 30M+ lines of code. Navigation strategy:
# Find owners for a directory
cat chrome/browser/ui/views/OWNERS
# Search code (use Chromium's Code Search, faster than local grep)
# https://source.chromium.org/chromium
# Understand component structure
# chrome/ → Browser UI, profiles, extensions
# content/ → Multi-process architecture, renderer, GPU
# components/ → Shared code across Chrome products
# ui/ → Toolkit abstraction (views, aura, ozone)
# third_party/ → Dependencies (Skia, V8, ICU, etc.)
# gpu/ → GPU command buffer, ANGLE
OWNERS Files¶
Every directory has an OWNERS file listing who can approve changes:
# chrome/browser/ui/views/OWNERS
pkasting@chromium.org
sky@chromium.org
# per-file overrides
per-file browser_view.cc=anyone@chromium.org
For your CL to land:
- Code-Review +2 from at least one person listed in the relevant OWNERS file (or a parent directory's OWNERS).
- Verified +1 from anyone (including yourself).
- Commit-Queue +2 to submit. The CQ runs:
- Presubmit checks (OWNERS, formatting, license headers)
- ~500 test suites across Linux, Windows, macOS, Android, ChromeOS
- If all green, the CL lands automatically.
Reference: Gerrit Guide
Chromium CL Footer Syntax¶
Bug: 123456 # Link to crbug.com issue
Fixed: 123456 # Auto-closes the bug on landing
Change-Id: Iabcdef... # Gerrit tracking (auto-generated)
Reviewed-on: https://... # Auto-populated by Gerrit
Cr-Commit-Position: ... # Auto-populated on landing
Finding Good First Issues¶
wlroots / Sway¶
- Look for issues labeled "good first issue" on GitHub.
- Protocol implementation bugs are often self-contained: "implement
ext-foo-v1protocol" involves adding a C file, wiring up the protocol XML, and handling the requests. - Documentation improvements (man pages, protocol descriptions) are always welcome and low-risk.
- Check the wayland-protocols issue tracker for protocol-level discussions that lead to implementation work.
Chromium¶
- Use crbug.com and filter
by
Hotlist-GoodFirstBug. - The Ozone/Wayland component (
Internals>Ozone>Wayland) has issues directly relevant to Warmwind's stack. - Look for bugs labeled
Available-- these have been triaged and are ready for someone to pick up. - Typo fixes and small refactors build CQ familiarity without risk.
Linux Kernel¶
- kernelnewbies.org maintains a list of first-patch-friendly tasks.
- The DRM subsystem has
TODOfiles indrivers/gpu/drm/listing cleanup tasks. - Run
checkpatch.plon existing code to find style violations worth fixing.
The Patch Lifecycle¶
wlroots/Sway (GitHub PR)¶
# 1. Fork on GitHub, clone your fork
git clone https://github.com/YOUR_USER/wlroots.git
cd wlroots
git remote add upstream https://github.com/swaywm/wlroots.git
# 2. Create feature branch from latest master
git fetch upstream
git checkout -b my-feature upstream/master
# 3. Make changes, commit with proper message
git add types/wlr_output.c
git commit -m "output: add support for adaptive sync toggle
Allow compositors to enable or disable adaptive sync on a per-output
basis through the output state API. This is needed for VRR support
in headless backends where adaptive sync has no meaning.
Closes #4567"
# 4. Push and open PR
git push origin my-feature
# Open PR on GitHub
# 5. Address review feedback: amend + force-push
git rebase -onto upstream/master HEAD~1
# Make changes
git add -u
git commit --amend
git push --force origin my-feature
# 6. Maintainer merges (rebase, not squash)
Chromium (Gerrit CL)¶
# 1. Branch from main
git new-branch fix-ozone-wayland
# 2. Edit, commit
git commit -am "ozone/wayland: fix buffer scale for fractional scaling
The previous code truncated the fractional scale to an integer before
passing it to wl_surface.set_buffer_scale. This caused blurry rendering
on outputs with non-integer scale factors (e.g. 1.25, 1.5).
Bug: 1234567
Change-Id: I$(git log -1 --format=%H | head -c 40)"
# 3. Upload
git cl upload
# 4. Review feedback → amend → re-upload
# (unlike wlroots, Gerrit tracks patchsets natively)
git commit --amend
git cl upload
# 5. CQ lands it
Writing Good Commit Messages¶
The 50/72 Rule¶
- First line: Max 50 characters. Imperative mood. Completes "When applied, this commit will ..."
- Blank line after the first line.
- Body: Wrapped at 72 characters. Explains why, not what (the diff shows the what).
Project-Specific Conventions¶
| Project | Prefix | Sign-off | Issue Reference |
|---|---|---|---|
| wlroots | subsystem: (e.g. render/vulkan:) |
Not required | Fixes #123 or Closes #123 |
| Sway | subsystem: (e.g. commands:) |
Not required | Fixes #123 |
| Chromium | component: (e.g. ozone/wayland:) |
CLA required | Bug: 123456 or Fixed: 123456 |
| Linux kernel | subsystem: (e.g. drm/sway:) |
Signed-off-by: required |
Fixes: <commit hash> ("commit title") |
Real Examples from wlroots (2025--2026)¶
Example 1: Protocol implementation
types: implement ext-workspace-v1
Add server-side implementation of the ext-workspace-v1 protocol.
This allows compositors to advertise workspaces and their state
to clients like taskbars and workspace switchers.
The implementation follows the pattern established by
wlr_foreign_toplevel_manager: a manager object that emits events
when workspaces are created/destroyed, and per-workspace objects
for state changes.
Ref: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
Example 2: Bug fix
output: fix crash when disabling output during commit
If wlr_output_commit_state() was called with enabled=false while
a pageflip was pending, the backend would attempt to access the
already-freed output state. Add a check for pending pageflips
before processing the disable request.
Fixes #4102
Example 3: Renderer improvement
render/vulkan: add support for color-management-v1
Implement the wp-color-management-v1 protocol in the Vulkan
renderer. This enables ICC profile-aware compositing when both
the output and client surfaces have attached color descriptions.
The implementation uses Vulkan's VK_EXT_swapchain_colorspace
extension to set the output color space, and performs color
space conversion in the fragment shader.
Example 4: wlroots 0.20 -- color representation support
render: add color-representation-v1 protocol support
Implement color range and color encoding negotiation using the
new wp-color-representation-v1 protocol. This enables clients
to declare whether their buffers use full-range or limited-range
color, and which transfer function applies.
Example 5: Scene graph optimization
scene: skip composition when direct scanout is possible
When a single surface covers the entire output and no other
scene nodes are visible, bypass the renderer and present the
client buffer directly via DRM pageflip. This eliminates one
GPU copy per frame for fullscreen applications.
Measured: ~0.5ms reduction in frame time on Intel UHD 630.
How This Applies to Warmwind¶
Warmwind maintains downstream patches on top of Sway and Chromium. Understanding upstream contribution is essential for maintaining a fork.
graph LR
Upstream["Upstream Sway/Chromium"] -- "release tag" --> Rebase["Rebase"]
Patches["Warmwind Patches"] --> Rebase
Rebase --> Build["CI Build"]
Build --> Deploy["Deploy to Agents"]
Maintaining a Fork¶
# Warmwind's workflow (conceptual)
# 1. Track upstream
git remote add upstream https://github.com/swaywm/sway.git
git fetch upstream
# 2. Maintain a patch branch
git checkout warmwind-patches
git rebase upstream/master
# 3. Resolve conflicts (this is where upstream knowledge pays off)
# Understanding WHY upstream made a change makes conflict resolution
# 10x easier than just looking at the diff.
# 4. Build and test
meson setup build --prefix=/opt/warmwind
ninja -C build
ninja -C build test
# 5. Tag and deploy
git tag warmwind-$(date +%Y%m%d)
Why Upstream Contributions Help Fork Maintenance¶
| Practice | Benefit for fork maintenance |
|---|---|
| Reading upstream commits daily | Early warning of breaking changes |
| Contributing fixes upstream | Fewer patches to carry downstream |
| Understanding coding conventions | Patches that rebase cleanly |
| Building relationships with maintainers | Faster review of critical fixes |
| Following protocol discussions | Anticipate API changes months ahead |
The Best Patch is No Patch¶
Every downstream patch is a maintenance burden. The ideal workflow:
- Need a feature? Propose it upstream first.
- Fix a bug? Submit upstream, carry the backport temporarily.
- Custom behavior? Design it as a configuration option upstream if possible, not a hard fork.
- Protocol extension? Propose it to wayland-protocols. If accepted, every compositor benefits and Warmwind stops carrying the patch.
What's new (2025--2026)
- wlroots 0.20 RC (Feb 2026) brings
ext-workspace-v1,color-management-v1v2, enhanced Vulkan renderer, andxdg-toplevel-tag-v1. - Chromium Rust integration continues:
crabbyavif(AVIF decoder) and QR code generator ship in production Chrome builds. - Sway remains on evolutionary releases (1.10, 1.11) with no Sway 2.0 planned. The project stays atop wlroots 0.18+.
- wlroots migrated primary development to GitHub, with legacy sourcehut and freedesktop GitLab instances now mirrors.
Glossary
- CL (Changelist)
- Chromium's term for a code review unit. Equivalent to a pull request. Uploaded to Gerrit via
git cl upload. - CQ (Commit Queue)
- Chromium's automated testing and landing system. Runs ~500 test suites across all platforms before merging a CL.
- OWNERS file
- Chromium file listing who can approve changes in a directory. At least one OWNER must give Code-Review +2 for a CL to land.
- Gerrit
- Google's code review tool used by Chromium. Supports patchset tracking, inline comments, and automated CI integration.
- depot_tools
- Google's CLI toolkit for Chromium development. Includes
gclient,gn,git cl,autoninja. - Linear history
- wlroots requirement that every commit be independently functional. No merge commits, no fixup commits. Rebase before merge.
- Signed-off-by
- Git trailer required by the Linux kernel (and some other projects) certifying the contributor has the right to submit the patch under the project's license (DCO).
- Format-patch
- Git command generating email-ready patch files. Used for kernel mailing list submissions and historically for wlroots.
- Downstream patch
- A modification carried on top of upstream code. Must be rebased on each upstream release. Warmwind carries patches on Sway and Chromium.
- chromium_src override
- Brave's technique: place a file in
brave/chromium_src/to compile it instead of the upstream equivalent, minimizing merge conflicts.