The Architecture for Detecting Keyboard Layouts and Input Methods in Fastfetch

Fastfetch implements a strict separation between platform-specific detection logic in src/detection/keyboard/ and the presentation module in src/modules/keyboard/, but it currently enumerates physical keyboard devices only and does not expose keyboard layouts or input method editor (IME) information.

The fastfetch-cli/fastfetch repository organizes hardware detection into a layered architecture where raw data gathering remains isolated from formatting and output logic. While the project reliably identifies connected keyboards across Linux, Windows, BSD, macOS, and Haiku, the detection framework intentionally stops at device enumeration and does not query desktop environment APIs for layout or input method data.

How Fastfetch Detects Keyboard Devices

Fastfetch’s keyboard detection follows a three-tier architecture: platform-specific detectors, a common detection API, and the module presentation layer.

Platform-Specific Detection Layer

Each supported operating system implements its own detector under src/detection/keyboard/ that queries the kernel or system APIs for connected HID devices:

The Detection API

All platform implementations expose a unified entry point declared in src/detection/keyboard/keyboard.h:

const char* ffDetectKeyboard(FFlist* devices);

This function populates an FFlist of FFKeyboardDevice structures containing name and serial fields. The return value is NULL on success or an error string on failure, allowing the module layer to handle diagnostics consistently across platforms.

Module Presentation Layer

The src/modules/keyboard/keyboard.c file defines ffPrintKeyboard(), which orchestrates the output flow:

  1. Allocates a result list and calls ffDetectKeyboard().
  2. Applies user-supplied filters from --ignores options defined in src/modules/keyboard/option.h.
  3. Formats output as plain text, custom strings, or JSON via helpers in the module.

This separation ensures that adding a new platform requires only implementing the detection interface, while the formatting, filtering, and JSON serialization logic remains portable.

Linux Detection Deep Dive

On Linux, src/detection/keyboard/keyboard_linux.c implements a finite-state parser for the /proc/bus/input/devices pseudo-file. The kernel exports one device per block, with lines prefixed by single-letter identifiers:

/* src/detection/keyboard/keyboard_linux.c */
const char* ffDetectKeyboard(FFlist* devices)
{
    FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
    if (!ffAppendFileBuffer("/proc/bus/input/devices", &content))
        return "Unable to read /proc/bus/input/devices";

    // Walk line-by-line parsing device blocks
    while (ffStrbufGetline(&line, &len, &content)) {
        switch (line[0]) {
            case 'N':   // "N: Name=..." — extract device name
                // Parse and trim the quoted name string
                break;

            case 'H':   // "H: Handlers=..." — verify kbd handler exists
                if (!ffStrbufMatchSeparatedNS(&kbd, handlersLen, handlers, ' '))
                    goto skipDevice;  // Not a keyboard if no "kbd" handler
                break;

            case 'B':   // "B: ..." — filter by capabilities bitmask
                // Skip pseudo-devices like Power buttons
                break;

            case 'U':   // "U: Uniq=..." — capture serial number
                break;

            case '\0':  // Empty line marks end of device block
                if (device.name.length > 0) {
                    FFKeyboardDevice* added = ffListAdd(devices);
                    ffStrbufInitMove(&added->name, &device.name);
                    ffStrbufInitMove(&added->serial, &device.serial);
                }
                break;
        }
    }
    return NULL;
}

The parser specifically looks for the kbd handler token in the H: line to distinguish actual keyboards from mice, touchpads, or power buttons that share the input subsystem.

Why Fastfetch Does Not Report Layouts or IMEs

Despite the architecture supporting keyboard detection, fastfetch does not expose keyboard layouts (e.g., XKB layout/variant) or input method editors (ibus, fcitx, macOS Input Sources, Windows IME).

This limitation stems from three design constraints:

  1. Desktop Environment Fragmentation — Layout and IME data resides in DE-specific APIs (X11 XKB, Wayland zwp_input_method, macOS Text Input Sources, Windows TSF) rather than kernel interfaces.
  2. Dependency Weight — Querying these APIs requires linking against heavy GUI libraries (libX11, libwayland-client, Cocoa, COM) that conflict with fastfetch’s goal of remaining lightweight and dependency-minimal.
  3. Scope Definition — The current keyboard module is strictly a hardware enumerator, not a configuration inspector.

Extending fastfetch to include layout or IME detection would require creating new detector files (e.g., src/detection/keyboardlayout/) that query the respective DE APIs and a corresponding module to expose the data.

Practical Usage Examples

Display Connected Keyboards

Run fastfetch with the keyboard module enabled (included in most presets by default):

fastfetch

Sample output:


 Keyboard
    Apple Keyboard
    Dell Wired Keyboard

Custom Formatting

Output only device names using the format string option:

fastfetch --module keyboard --format "{name}"

Result:


Apple Keyboard
Dell Wired Keyboard

Filter Out Specific Devices

Use the --ignore flag to exclude built-in or unwanted keyboards using substring matching:

fastfetch --module keyboard --ignore "Apple "

JSON Output for Scripting

Extract structured data for further processing:

fastfetch --module keyboard --output json

Example JSON fragment:

{
  "keyboard": {
    "result": [
      { "name": "Apple Keyboard", "serial": "12345678", "ignored": false },
      { "name": "Dell Wired Keyboard", "serial": "", "ignored": false }
    ]
  }
}

Summary

  • Fastfetch separates keyboard detection (src/detection/keyboard/) from presentation (src/modules/keyboard/) to maintain portable formatting logic across platforms.
  • Platform detectors parse OS-specific APIs: /proc/bus/input/devices on Linux, Raw Input on Windows, IOKit on macOS, and sysctl on BSD.
  • Device enumeration captures hardware names and serial numbers, but does not include active keyboard layouts or input methods.
  • Extending fastfetch to support layouts would require new DE-specific detectors for XKB, ibus, fcitx, or platform IME APIs.
  • Users can filter, format, or export keyboard data via the module’s command-line options and JSON output mode.

Frequently Asked Questions

Does fastfetch show my current keyboard layout?

No. According to the fastfetch source code, the detection framework in src/detection/keyboard/ only enumerates physical hardware devices. It does not query XKB, Wayland input methods, or OS-specific layout registries. You would need to extend the codebase with a new detector module to capture layout information.

How does fastfetch identify keyboards on Linux?

The Linux detector in src/detection/keyboard/keyboard_linux.c reads /proc/bus/input/devices and parses device blocks looking for the kbd handler token. It extracts the N: (Name) and U: (Uniq/serial) fields, filtering out non-keyboard pseudo-devices by their capability bitmasks.

Can I filter out specific keyboards from the output?

Yes. The keyboard module supports the --ignore option defined in src/modules/keyboard/option.h. Pass a substring to exclude matching devices: fastfetch --module keyboard --ignore "Internal". The filter runs in src/modules/keyboard/keyboard.c after detection but before printing.

Where is the keyboard detection code located?

All keyboard-related source files live under two directories: src/detection/keyboard/ contains platform-specific implementations (Linux, Windows, BSD, macOS, Haiku) and the common header keyboard.h declaring ffDetectKeyboard(). The presentation layer resides in src/modules/keyboard/ and includes keyboard.c, option.h, and formatting helpers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →