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)