rust-windowing / rust-windowing/winit

Claude Code Review Report

Open
#4,569 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
6.2k
Forks
1.3k
Avg merge
2d 19h
Merged PRs (30d)
9

Description

Recently, I ran Claude Code across several projects to look for potential issues.

In previous runs, a significant portion of reported findings turned out to be incorrect or minor false positives, but a non-trivial subset was valid and included real issues ranging from incorrect comments to actual logic bugs. As a result, the findings generally require manual validation to separate noise from actionable problems.

Example findings:

C-1. MainRunLoop::remove_observer adds the observer instead of removing it

File: winit-common/src/core_foundation/main_run_loop.rs:132-135
Severity: Critical (resource leak / behaviour bug, affects macOS/iOS)

pub fn remove_observer(&self, observer: &MainRunLoopObserver, mode: &CFRunLoopMode) {
    // Same as in `add_observer`, accessing the main loop's observer is fine.
    self.main_run_loop.add_observer(Some(&observer.observer), Some(mode));
}

Clear copy-paste bug: the function is named remove_observer and is documented as removing the observer, but it calls add_observer. Any code path that calls this will accumulate duplicate registrations of the same observer on the main run loop, causing increasing CPU work over the lifetime of the program.

Fix: call self.main_run_loop.remove_observer(Some(&observer.observer), Some(mode)) (CFRunLoopRemoveObserver).

C-2. Android ConfigChanged never fires ScaleFactorChanged

File: winit-android/src/event_loop.rs:209-223
Severity: Critical (event correctness — Android)

MainEvent::ConfigChanged { .. } => {
    let old_scale_factor = scale_factor(&self.android_app);
    let scale_factor = scale_factor(&self.android_app);
    if (scale_factor - old_scale_factor).abs() < f64::EPSILON {
        // ... emit ScaleFactorChanged ...
    }
},

Two distinct bugs in one block:

  1. old_scale_factor and the new scale_factor are computed by the same call, so they are always identical.
  2. Even ignoring that, the conditional is inverted: it only fires when the scale factor has not changed (abs() < EPSILON).

Net effect: Android applications will never receive ScaleFactorChanged even when the OS actually changes DPI / configuration. Suggested fix: store the previously-seen scale factor in self, compute the new one once per event, and fire when they differ.

C-6. Linux backend selection: error messages are swapped

File: winit/src/platform_impl/linux/mod.rs:106-115
Severity: Medium (user-facing error message — easy to confuse users)

(_, wayland_display, x11_display) => {
    let msg = if wayland_display && !cfg!(wayland_platform) {
        "DISPLAY is not set; note: enable the `winit/wayland` feature to support \
         Wayland"
    } else if x11_display && !cfg!(x11_platform) {
        "neither WAYLAND_DISPLAY nor WAYLAND_SOCKET is set; note: enable the \
         `winit/x11` feature to support X11"
    } else {
        ...
    };

The first branch says "DISPLAY is not set" when in fact WAYLAND_DISPLAY is set (just not compiled in). The second branch says "WAYLAND_DISPLAY not set" but the condition that triggers it is x11_display && !cfg!(x11_platform). The two strings are essentially swapped. They should describe the variable that is set but whose backend isn't available.

D-3. Conversion-direction docstrings for MIN are wrong

Files: dpi/src/lib.rs:137-138, 231-232, 326-327
Severity: Nit

/// Represents a minimum logical unit of [`f64::MAX`].
pub const MIN: LogicalUnit<f64> = LogicalUnit::new(f64::MIN);

The doc string says "of f64::MAX" — should say f64::MIN. Appears three times: LogicalUnit, PhysicalUnit, PixelUnit.

Full report - findings.md

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the reported locations in winit-common/src/core_foundation/main_run_loop.rs, winit-android/src/event_loop.rs, winit/src/platform_impl/linux/mod.rs, and dpi/src/lib.rs, along with findings.md. Validate each finding against the surrounding platform code and existing tests. Done means the confirmed observer, Android scale-factor, Linux message, and documentation issues are corrected and relevant checks pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, ios, linux, macos, rust
Domain
backend, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.