DEV Community

Cover image for DisplayFlowCLI multi monitor tool for windows in rust
piot5
piot5

Posted on • Edited on

DisplayFlowCLI multi monitor tool for windows in rust

displayflow

If you’ve ever tried to automate display layouts on Windows with command line tools, you know the frustration: GDI device indices are volatile. A reboot, a driver update, or simply unplugging a monitor can reassign \DISPLAY1 to a completely different physical screen.
I built displayflow, a Rust-based utility that fixes this by creating a "Synthetic ID" mapping between live GDI data and the Windows Registry.
The Problem: Why EnumDisplayDevices isn't enough
Windows provides the GDI API to manage monitors, but it has two major flaws for automation:
Volatile IDs: The names are logical, not physical.
Missing Metadata: When a monitor is disconnected, GDI forgets its existence, making it impossible to "pre-configure" layouts for specific hardware combinations.
The Solution: Synthetic Inventory Scrapping
displayflow works by bridging two worlds:
Live GDI Scan Using EnumDisplayDevicesW and EnumDisplaySettingsW to get current coordinates and refresh rates.
Registry : Parsing SYSTEM\CurrentControlSet\Enum\DISPLAY to extract EDID data (Serial Numbers, Physical Dimensions).
Key Code: The EDID Parser
To uniquely identify a monitor, we have to manually parse the EDID block from the registry.

fn parse_edid(bytes: &[u8]) -> (String, String, String) {
// We look for the Serial Number Descriptor (00 00 00 ff)
for offset in [54, 72, 90, 108] {
if offset + 18 <= bytes.len() && &bytes[offset..offset+4] == b"\x00\x00\x00\xff" {
let sn = String::from_utf16_lossy(...) //

Features:
Force Registry Commits: Instead of flickering every time a setting changes, DisplayFlow stages configurations using CDS_NORESET and commits them all at once via ChangeDisplaySettingsExW.
Daemon Mode with Hotkeys: A background listener using RegisterHotKey that triggers layout "Suites" stored in the registry. I want to include more
event triggers (like hot plug based on port) in future versions
How to use it
I designed the CLI to be "Pipe-First". You can scan your current setup, pipe it into a profile, and re-apply it later:
Save current layout as a suite named 'Gaming'
df --save Gaming --hotkey
Re-apply it anywhere
df --apply-suite Gaming

df 1:3840:2160:0:0:1:144:90:100:75:up --save Cinema --hotkey

I included Res position primary rotation hz Ddc contrast Ddc brightness and animation .the last statement is a transition Animation whos direction you choose per monitor

Why Rust?
Handling Win32 API calls (especially the DEVMODEW struct with its nested unions) is unsafe in C++. Rust’s windows-rs crate allowed me to wrap these unsafe calls in a way that ensures memory safety while dealing with raw pointers and byte-level registry parsing.

Check out the code on GitHub:

https://github.com/piot5/displayflow_cli

rust #windows #cpp #programming #automation

Top comments (0)