Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.

Inbox
ReportR-5076GitHub issuePublicReceived

50-omarchy.conf accepts Noto Color Emoji ahead of Noto Sans Symbols 2, so text-presentation glyphs (✔ U+2714, ☑ U+2611) render as color emoji

Reported by sttwister · filed Sep 14, 2026Closed upstream on 2026-09-14 by its own reporter sttwister, as not planned. Closed by its own reporter — not by itself evidence of a fix.

Received and recorded verbatim. Nothing has been checked yet.

At a glance

1 · What is claimed?
Only the report text below — no validator has restated it as checkable claims yet.
2 · What does it affect?
Not yet mapped to any requirement or component.
3 · Is it reproducible?
No validation has been run yet.
4 · What remains unclear?
  • Not validated yet: no claims, no reproducer.
5 · What happens next?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

50-omarchy.conf accepts Noto Color Emoji ahead of Noto Sans Symbols 2, so text-presentation glyphs (✔ U+2714, ☑ U+2611) render as color emojirevision 1 · captured 2026-10-04 12:10 UTC via poll

What happens

/etc/fonts/conf.d/50-omarchy.conf (from omarchy-settings) accepts Noto Color Emoji into the generic families:

<alias>
  <family>sans-serif</family>
  <accept>
    <family>JetBrainsMono Nerd Font</family>
    <family>Noto Color Emoji</family>
  </accept>
</alias>

At priority 50 this lands ahead of the stock Noto fallback chains (66-noto-sans.conf) and therefore ahead of Noto Sans Symbols 2. As a result, every codepoint that Noto Color Emoji happens to cover is rendered as a color emoji — including the ones whose Unicode default is text presentation (Emoji_Presentation=No), which should only become emoji when followed by VS16 (U+FE0F).

The most visible casualties are the check marks and checkboxes:

CodepointCharEmoji_PresentationResolves to on OmarchyShould be
U+2714✔NoNoto Color EmojiNoto Sans Symbols 2
U+2611☑NoNoto Color EmojiNoto Sans Symbols 2
U+2610☐n/aNoto Sans Symbols 2Noto Sans Symbols 2

Note the inconsistency in that table: U+2610 ☐ renders correctly only because Noto Color Emoji has no glyph for it. So a plain ☐ → ☑ sequence in a web page renders as a black outline box followed by a blue-and-white emoji checkbox — two glyphs from two different design languages, side by side.

This affects anything going through fontconfig, not just browsers. It is not Chromium-specific; the same pages render correctly in Chrome on Ubuntu and Windows, where the emoji font sits at the end of the fallback chain.

Steps to reproduce

for c in 2714 2611 2610; do printf 'U+%s -> ' $c; fc-match "sans-serif:charset=$c"; done

Output on a stock Omarchy 4.0.3 install:

U+2714 -> NotoColorEmoji.ttf: "Noto Color Emoji" "Regular"
U+2611 -> NotoColorEmoji.ttf: "Noto Color Emoji" "Regular"
U+2610 -> NotoSansSymbols2-Regular.ttf: "Noto Sans Symbols 2" "Regular"

Or open any page containing a bare ✔ / ☑ (no VS16) in a browser — they come out as color emoji.

Expected

✔ and ☑ without VS16 resolve to a text-presentation font (Noto Sans Symbols 2), matching Unicode's default presentation and matching what the same page renders as on other distributions. Real emoji (😀, ✅ U+2705, which is Emoji_Presentation=Yes) should keep resolving to Noto Color Emoji.

Workaround

Subtracting the two codepoints from the emoji font's charset, in ~/.config/fontconfig/conf.d/60-symbols-text-presentation.conf:

<match target="scan">
  <test name="family">
    <string>Noto Color Emoji</string>
  </test>
  <edit name="charset" mode="assign">
    <minus>
      <name>charset</name>
      <charset>
        <int>0x2714</int>
        <int>0x2611</int>
      </charset>
    </minus>
  </edit>
</match>

Requires fc-cache -f -r (a scan edit is baked in at cache build time) and a full browser restart.

It has to subtract from the emoji font, not prepend a symbol font. The obvious-looking fix —

<!-- DOES NOT WORK -->
<match target="pattern">
  <edit name="family" mode="prepend" binding="weak">
    <string>Noto Sans Symbols 2</string>
  </edit>
</match>

— breaks ASCII digits. Noto Sans Symbols 2 carries U+0020, U+0023, U+002A and U+0030..U+0039 as enclosing-keycap bases (note U+20E2..U+20E3 in its charset), and those glyphs have keycap-width advances. Chromium asks fontconfig only for the family list and then reads the real font file's cmap, so a prepended family wins for every glyph it actually contains: !548 renders as ! 5 4 8. Editing that font's charset does not help either, for the same reason — the charset only prunes fontconfig's own matching, which Chromium has already bypassed by that point.

That also means fc-match is not a sufficient check here: it prunes by the edited charset and will report a clean result while Chromium still renders the wrong font. Verified instead with CSS.getPlatformFontsForNode over CDP, which reports the fonts actually used, headless on this machine:

samplestockwith the fix
!548 0123456789 #*Liberation Sans(18)Liberation Sans(18)
✔ ☑ ☐ ✓ ✗Liberation Sans(4), Noto Color Emoji(2), Adwaita Mono(3)Liberation Sans(4), Adwaita Mono(5)
😀 ✅ ❤️ 🎉 ⚠️Liberation Sans(4), Noto Color Emoji(5)Liberation Sans(4), Noto Color Emoji(5)
→ ← ↑ • — …Liberation Sans(11)Liberation Sans(11)
monospace digitsJetBrainsMono NF(10)JetBrainsMono NF(10)
Nerd Font PUA U+E0A0JetBrainsMono NF(5)JetBrainsMono NF(5)

Exactly one row changes, and the emoji font drops out of it entirely. Real emoji, digits, arrows, and Nerd Font glyphs are untouched.

The file has to go in ~/.config/fontconfig/conf.d/ rather than fonts.conf, because omarchy font set regenerates ~/.config/fontconfig/fonts.conf from scratch and would discard it.

A fix in 50-omarchy.conf could take the same shape. U+2714 and U+2611 are the two that show up in practice; the general set is every codepoint Noto Color Emoji covers with Emoji_Presentation=No.

System

  • Omarchy 4.0.3-1 (omarchy-settings 4.0.3-1)
  • fontconfig 2:2.18.3-2, noto-fonts 1:2026.09.01-1, noto-fonts-emoji 1:2.051-1
  • Google Chrome 153.0.8010.36
  • AMD RYZEN AI MAX+ 395 w/ Radeon 8060S
View raw text
## What happens

`/etc/fonts/conf.d/50-omarchy.conf` (from `omarchy-settings`) accepts `Noto Color Emoji` into the generic families:

```xml
<alias>
  <family>sans-serif</family>
  <accept>
    <family>JetBrainsMono Nerd Font</family>
    <family>Noto Color Emoji</family>
  </accept>
</alias>
```

At priority 50 this lands ahead of the stock Noto fallback chains (`66-noto-sans.conf`) and therefore ahead of **Noto Sans Symbols 2**. As a result, every codepoint that Noto Color Emoji happens to cover is rendered as a color emoji — including the ones whose Unicode default is *text* presentation (`Emoji_Presentation=No`), which should only become emoji when followed by VS16 (U+FE0F).

The most visible casualties are the check marks and checkboxes:

| Codepoint | Char | Emoji_Presentation | Resolves to on Omarchy | Should be |
|---|---|---|---|---|
| U+2714 | ✔ | No | Noto Color Emoji | Noto Sans Symbols 2 |
| U+2611 | ☑ | No | Noto Color Emoji | Noto Sans Symbols 2 |
| U+2610 | ☐ | n/a | Noto Sans Symbols 2 | Noto Sans Symbols 2 |

Note the inconsistency in that table: U+2610 ☐ renders correctly only because Noto Color Emoji has no glyph for it. So a plain `☐ → ☑` sequence in a web page renders as a *black outline box* followed by a *blue-and-white emoji checkbox* — two glyphs from two different design languages, side by side.

This affects anything going through fontconfig, not just browsers. It is not Chromium-specific; the same pages render correctly in Chrome on Ubuntu and Windows, where the emoji font sits at the end of the fallback chain.

## Steps to reproduce

```bash
for c in 2714 2611 2610; do printf 'U+%s -> ' $c; fc-match "sans-serif:charset=$c"; done
```

Output on a stock Omarchy 4.0.3 install:

```
U+2714 -> NotoColorEmoji.ttf: "Noto Color Emoji" "Regular"
U+2611 -> NotoColorEmoji.ttf: "Noto Color Emoji" "Regular"
U+2610 -> NotoSansSymbols2-Regular.ttf: "Noto Sans Symbols 2" "Regular"
```

Or open any page containing a bare `✔` / `☑` (no VS16) in a browser — they come out as color emoji.

## Expected

`✔` and `☑` without VS16 resolve to a text-presentation font (Noto Sans Symbols 2), matching Unicode's default presentation and matching what the same page renders as on other distributions. Real emoji (`😀`, `✅` U+2705, which *is* `Emoji_Presentation=Yes`) should keep resolving to Noto Color Emoji.

## Workaround

Subtracting the two codepoints from the emoji font's charset, in `~/.config/fontconfig/conf.d/60-symbols-text-presentation.conf`:

```xml
<match target="scan">
  <test name="family">
    <string>Noto Color Emoji</string>
  </test>
  <edit name="charset" mode="assign">
    <minus>
      <name>charset</name>
      <charset>
        <int>0x2714</int>
        <int>0x2611</int>
      </charset>
    </minus>
  </edit>
</match>
```

Requires `fc-cache -f -r` (a scan edit is baked in at cache build time) and a full browser restart.

**It has to subtract from the emoji font, not prepend a symbol font.** The obvious-looking fix —

```xml
<!-- DOES NOT WORK -->
<match target="pattern">
  <edit name="family" mode="prepend" binding="weak">
    <string>Noto Sans Symbols 2</string>
  </edit>
</match>
```

— breaks ASCII digits. Noto Sans Symbols 2 carries U+0020, U+0023, U+002A and U+0030..U+0039 as enclosing-keycap bases (note U+20E2..U+20E3 in its charset), and those glyphs have keycap-width advances. Chromium asks fontconfig only for the *family list* and then reads the real font file's cmap, so a prepended family wins for every glyph it actually contains: `!548` renders as `! 5 4 8`. Editing that font's charset does not help either, for the same reason — the charset only prunes fontconfig's own matching, which Chromium has already bypassed by that point.

That also means `fc-match` is not a sufficient check here: it prunes by the edited charset and will report a clean result while Chromium still renders the wrong font. Verified instead with `CSS.getPlatformFontsForNode` over CDP, which reports the fonts actually used, headless on this machine:

| sample | stock | with the fix |
|---|---|---|
| `!548 0123456789 #*` | Liberation Sans(18) | Liberation Sans(18) |
| `✔ ☑ ☐ ✓ ✗` | Liberation Sans(4), **Noto Color Emoji(2)**, Adwaita Mono(3) | Liberation Sans(4), Adwaita Mono(5) |
| `😀 ✅ ❤️ 🎉 ⚠️` | Liberation Sans(4), Noto Color Emoji(5) | Liberation Sans(4), Noto Color Emoji(5) |
| `→ ← ↑ • — …` | Liberation Sans(11) | Liberation Sans(11) |
| monospace digits | JetBrainsMono NF(10) | JetBrainsMono NF(10) |
| Nerd Font PUA U+E0A0 | JetBrainsMono NF(5) | JetBrainsMono NF(5) |

Exactly one row changes, and the emoji font drops out of it entirely. Real emoji, digits, arrows, and Nerd Font glyphs are untouched.

The file has to go in `~/.config/fontconfig/conf.d/` rather than `fonts.conf`, because `omarchy font set` regenerates `~/.config/fontconfig/fonts.conf` from scratch and would discard it.

A fix in `50-omarchy.conf` could take the same shape. U+2714 and U+2611 are the two that show up in practice; the general set is every codepoint Noto Color Emoji covers with `Emoji_Presentation=No`.

## System

- Omarchy 4.0.3-1 (`omarchy-settings` 4.0.3-1)
- fontconfig 2:2.18.3-2, noto-fonts 1:2026.09.01-1, noto-fonts-emoji 1:2.051-1
- Google Chrome 153.0.8010.36
- AMD RYZEN AI MAX+ 395 w/ Radeon 8060S


Validation

Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.

Linked

Not linked to any known issue, other report or change yet.

Decision

Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.

No decision has been recorded yet.