Chrome window naming is a small feature with an outsized effect on how it feels to use PageSets: launch a workspace, and Chrome's window title actually says what the window is — "Client Project" instead of a generic "Google Chrome." Once you've had Chrome windows named, going back to unnamed ones feels like losing a limb.
It shipped for macOS first, and stayed that way for longer than I would have liked. Not because Windows support wasn't planned — because Windows genuinely doesn't give you an easy way to do this.
Why macOS was the easy version
macOS provides a mature Accessibility framework that makes it possible for a native companion application to inspect and interact with another application's user interface in a relatively structured way.
That doesn't make window naming trivial, but it provides a predictable path for locating the appropriate browser controls and performing the operation.
Windows presented a different problem.
Windows has its own accessibility and UI Automation technologies, but Chrome's window-naming functionality isn't exposed in a way that gave PageSets a simple, direct command for changing a window name from outside the browser.
The Windows implementation therefore needed to combine native Windows behavior with UI automation while still behaving like a normal user action.
That is considerably less forgiving.
What didn't work
Several approaches looked reasonable during development but proved unreliable once tested across real world Windows 11 environments.
One early approach attempted to invoke the browser's window controls through standard Windows messaging.
Sending a raw WM_SYSCOMMAND/SC_KEYMENU message to open Chrome's system menu looked like the clean, "proper Windows API" way to do it. In practice it didn't reliably open the menu we needed — Chrome's own window-menu implementation doesn't respond to it the way the documentation implies.
Conceptually, this was attractive: use the operating system's own window-management mechanisms rather than simulate user interaction.
In practice, Chrome's implementation does not always behave like a conventional Win32 application in this area. Commands that appeared valid at the Windows API level did not consistently produce the browser behavior PageSets needed.
Calculate where the menu item should be, simulate a click there. Fragile by construction — it breaks the moment DPI scaling, window position, or a Windows theme update shifts anything by a few pixels. Not something I was willing to ship.
Another possible solution was to locate the appropriate interface element visually and interact with it based on screen position.
That approach was rejected quickly.
Display scaling, window size, DPI settings, theme changes, browser revisions, and even minor layout differences can move interface elements enough to make coordinate-driven automation unreliable.
A feature PageSets depends on every time a workspace launches cannot be built around assumptions about where a button happens to appear on a screen.
The recurring lesson was that an implementation could look perfectly reasonable in isolation and still fail under real Windows conditions.
Testing on actual Windows 11 hardware became an essential part of the development process.
Both failed in ways that were only visible on real hardware — nothing about them looked wrong in isolation. That turned out to be a pattern for this entire effort: the debugging that actually mattered happened on an actual Windows 11 box, not by reasoning about the APIs from a cross-development distance.
What actually worked
The production implementation uses a layered native approach.
PageSets first attempts to interact with the browser through the Windows mechanisms available to it. When the required browser command isn't immediately available through that path, the native helper falls back to controlled keyboard interaction and Windows UI Automation to complete the operation.
That proved considerably more reliable than depending on a single Windows API or attempting to predict browser behavior.
Timing was equally important. Originally, window naming could occur after a predetermined delay. That worked most of the time, but "most of the time" isn't acceptable for a feature that runs automatically.
The final implementation is event-driven instead.
PageSets waits until its workspace-launch sequence has genuinely completed before requesting the rename operation. The Windows helper therefore works from an actual application state rather than an arbitrary timer.
That change made a substantial difference in reliability.
Then came the installer
Adding a native Windows component also meant PageSets needed a proper Windows installer.
I didn't want users downloading a utility, copying files manually, editing configuration settings, or following a page of installation instructions. The Windows component needed to install and maintain itself like any other part of a commercial desktop application.
That meant building an MSI-based installation system.
PageSets' development and release workflow originates on macOS, which introduced another complication: many of the conventional Windows installer tools assume the build itself is running on Windows.
The solution was a cross-platform MSI toolchain that could be incorporated into the existing Mac-based release process.
Getting the package produced was only part of the work. Installation scope, application registration, branding, upgrades, repair behavior, signing, and removal all had to behave correctly as well.
The bug that nearly ruined a clean install
One of the most frustrating problems appeared after the installer was already functioning correctly.
A freshly built and properly signed PageSets installer would occasionally trigger an unexpected Windows UAC prompt.
That should not have happened. PageSets uses a per-user installation model, so administrative privileges are not normally required.
The cause turned out not to be the new installer at all.
Earlier development builds had left behind stale Windows Installer registration information on the test system. Some of those registrations referred to installation resources that no longer existed.
When Windows detected them during an upgrade, its own installer infrastructure attempted to reconcile the old installation state before continuing. That cleanup operation could require elevation even though the new PageSets installation itself did not.
In other words, a perfectly valid current installer was being affected by remnants of much older test builds.
Solving the problem required adding recovery logic capable of identifying incomplete or orphaned previous installations and safely normalizing that state before the current installation proceeds.
It was a particularly deep Windows Installer rabbit hole for what initially looked like a simple UAC problem.
It was also necessary.
Where it landed
The result is the Windows implementation I wanted PageSets to have from the beginning.
PageSets now includes a signed Windows installer that:
- Installs the native component without requiring administrative privileges under normal conditions.
- Supports automatic window naming in both Chrome and Microsoft Edge.
- Synchronizes naming with the actual PageSets workspace-launch sequence rather than arbitrary delays.
- Detects and handles several Windows and browser edge cases internally.
- Can repair its integration if local configuration or security software disrupts it.
There is no command line to configure and no separate utility the user needs to understand.
Install PageSets, launch a workspace, and the windows get their names.
Window naming on Windows is no longer an experimental or "works most of the time" feature. It is now part of the same production PageSets workflow as the macOS implementation — built, signed, packaged, and tested as a native part of the product.
— Rob Veal · Founder, LumiCore Software
Questions or feedback: support@pagesets.co