Keep selected application windows visible as live, always-on-top previews and switch between them in one click or with a global shortcut.
Window Switcher is a cross-platform desktop application for multibox, multi-client, monitoring, and other workflows where several application windows must remain easy to see and activate. It works alongside the target applications and does not modify or inject code into them.
Inspired by EVE-O Preview, Window Switcher extends the floating-preview approach to broader use cases and to both Windows and Linux.
- Features
- Platform support
- Installation
- Quick start
- User guide
- Linux setup
- Configuration and data
- Privacy and error reporting
- Troubleshooting
- Build and contribute
- Packaging
- Demo videos
- Live, always-on-top previews for selected windows
- Click-to-focus and optional focus-on-hover behavior
- Global shortcuts for a specific client, the next or previous client, or the active client
- Case-insensitive title filters for choosing which windows appear
- Persistent and temporary blacklists
- Window renaming from the main list or a preview
- Per-window preview position and size persistence
- Fixed or individually resizable previews
- Configurable movement, startup behavior, and active-window highlight color
- Runtime, operating-system, dependency, preview-mode, and update diagnostics
- Native Windows and Linux implementations—no code injection into monitored applications
| Platform | Window discovery and control | Preview technology | Global shortcuts | Status |
|---|---|---|---|---|
| Windows | Native Windows APIs | DWM thumbnails | Low-level keyboard hook | Supported |
| Linux on X11 | Native EWMH | XComposite/XDamage | evdev + uinput; permissions required |
Supported |
| Linux on Wayland | Native EWMH; XWayland windows only | PipeWire through the XDG ScreenCast portal | evdev + uinput; permissions required |
Partially supported |
| macOS | — | — | — | Not implemented |
- Native Wayland windows cannot be discovered or switched. Applications running through XWayland, including many Wine/Proton games, can be used.
- Fullscreen applications are not supported.
- Linux global shortcuts are optional and remain unavailable until the user can read
/dev/input/event*and write to/dev/uinputor/dev/input/uinput. - Wayland preview capture may show a desktop portal selection prompt.
- Linux previews use the same 20 FPS target for every window. The active-window highlight does not change capture cadence.
The application still runs when optional preview or keyboard dependencies are unavailable. Open Help > About to see the active preview mode and dependency status.
Window Switcher is GPL-3.0 software and can always be built from source.
Official precompiled builds are not currently distributed for free. Paid, ready-to-install builds may be offered through channels such as Microsoft Store. Those packages are intended for users who prefer a managed installation and are compiled with Sentry enabled, without a runtime opt-out.
| Operating system | Recommended route |
|---|---|
| Windows | Use an official packaged build when available, or build from source. |
| Linux | Install the Linux dependencies, then build from source. |
Important
Source builds also include Sentry by default. To produce a build without Sentry or any Sentry network traffic, use the compile-time opt-out.
After installing or building the application:
- Start the applications or game clients that you want to manage.
- Launch Window Switcher.
- Open
Config > Filtersand add part of a window title under Prefixes. For example,World of Warcraftdisplays every window whose title contains that text. - Add unwanted full window titles under Blacklist, if needed.
- Click a floating preview to bring its original window to the foreground.
- Optionally open
Config > Keybindsand assign shortcuts to built-in actions or individual clients. - Use
Config > Settingsto adjust preview movement, sizing, hover focus, startup behavior, and highlight color.
The main window refreshes its matching-window list automatically. Preview windows are created and removed as matching applications open and close.
Window Switcher uses window titles to decide what appears:
- Prefixes (whitelist): a window appears when its title contains at least one configured value. Matching is case-insensitive.
- Blacklist: a window is excluded when its complete title matches a configured value. Matching is case-insensitive.
- Temporary blacklist: a window is hidden by its current window ID until Window Switcher is restarted.
Open Config > Filters to manage the persistent lists. Selecting an existing entry removes it.
You can also right-click a window in the main list or its preview to:
- add its title to the blacklist;
- add it to the temporary blacklist; or
- rename the original window.
Renaming is especially useful when several clients initially share the same title. It also gives each client a stable, recognizable preview and keybind target.
- Enable Move windows to drag previews.
- Enable Resize windows to resize previews individually.
- Enable Fixed size to use the configured width and height for every preview.
- Enable Focus on hover to activate a client by moving the pointer over its preview.
- Enable Enable previews to show live content inside floating windows.
- Choose Highlight color to change the active-preview outline.
Position and size are saved per window key and restored on a later launch. Use File > Clean config file to clear saved preview layouts without resetting every preference.
The highlight follows the client activated through a preview or global keybind, making the currently active target easy to identify.
On Wayland, use Config > Reset all previews if you need to discard existing portal capture selections and choose them again. This command is shown only when the active preview provider supports selection reset.
Open Config > Keybinds, select a target, and choose Add shortcut.
Built-in targets are:
| Target | Behavior |
|---|---|
Next client |
Cycles forward through windows currently selected by the filters. |
Previous client |
Cycles backward through the selected windows. |
Focus active client |
Brings the client currently tracked as active back to the foreground. |
You can also bind shortcuts directly to an individual client. Running windows are offered as client targets, while saved targets remain available when their window is not currently open.
The keybind editor rejects duplicate shortcuts on one target and conflicts between different targets. On Linux, it also displays setup guidance when input-device permissions are missing.
| Setting | Purpose |
|---|---|
Move windows |
Allows floating previews to be dragged. |
Focus on hover |
Focuses a client when the pointer enters its preview. |
Enable previews |
Enables live content in floating preview windows. |
Start minimized |
Starts the main window hidden in the system tray. |
Resize windows |
Allows previews to be resized individually. |
Fixed size |
Applies one width and height to all previews. |
Width / Height |
Sets the fixed preview dimensions, from 10 to 2000 pixels. |
Highlight color |
Sets the outline color for the active preview. |
Settings are persisted as they change.
| Menu | Command | Purpose |
|---|---|---|
Config |
Filters |
Manage whitelist and blacklist entries. |
Config |
Keybinds |
Configure global shortcuts. |
Config |
Settings |
Configure preview behavior and appearance. |
Config |
Reset all previews |
Reset supported capture selections, primarily on Wayland. |
File |
Open data folder |
Open the directory containing config.json. |
File |
Clean config file |
Remove saved preview positions and sizes. |
File |
Generate new config file |
Restore all settings to their defaults. |
Help |
About |
Show diagnostics, version information, and updates. |
Open Help > About to view:
- the application version and update status;
- an update action when a newer release is available;
- the operating system, .NET runtime, and process architecture;
- the active Avalonia UI backend;
- the exact configuration-file path;
- the active preview mode; and
- Linux dependency status.
On Linux, the capability diagnostic distinguishes the detected session, the selected preview
backend, and its availability. For Wayland it reports separately whether the system PipeWire
runtime (libpipewire-0.3.so.0) or the bundled Window Switcher adapter
(libwindowswitcher-pipewire.so) is missing. Diagnostics never cause an X11/Wayland backend
fallback.
Source and directly distributed builds use the GitHub release updater. Builds labelled for Microsoft Store report that updates are managed by the store instead.
Window Switcher supports Linux on x86-64 systems through the linux-x64 runtime. Linux ARM64 is not supported.
Window discovery, focus, and renaming use the X11 EWMH protocol directly. Wayland previews also require PipeWire and an XDG Desktop Portal ScreenCast backend suitable for the desktop environment.
| Distribution | Wayland preview runtime |
|---|---|
| Debian / Ubuntu | sudo apt install libpipewire-0.3-0 xdg-desktop-portal |
| Arch Linux | sudo pacman -S pipewire xdg-desktop-portal |
| Fedora | sudo dnf install pipewire-libs xdg-desktop-portal |
Package names and portal backends vary by distribution and desktop environment. KDE commonly uses xdg-desktop-portal-kde, while GNOME commonly uses xdg-desktop-portal-gnome in addition to the base portal package.
On Wayland, EWMH can enumerate only XWayland windows. Installing more portal packages does not enable native Wayland window discovery.
PipeWire previews attempt to import DMA-BUF frames directly into EGL for zero-copy GPU rendering.
This path requires Avalonia to start with its EGL/X11 renderer and a compatible EGL driver. Set
EGL_PLATFORM=x11 in the launcher or development run configuration before starting the
process. Window Switcher does not restart itself or create a child process to apply this setting.
If EGL or DMA-BUF import is unavailable, the application remains usable and automatically falls back to CPU-backed preview frames. This fallback affects the transfer path, not the uniform 20 FPS target.
Building from source on Linux additionally requires:
- .NET SDK 10;
- a C compiler with C17 support;
pkg-config; and- PipeWire development headers.
Typical development-header packages are libpipewire-0.3-dev on Debian/Ubuntu, pipewire on Arch Linux, and pipewire-devel on Fedora. The native PipeWire capture adapter is built with the application and included in published and AppImage outputs.
For global shortcuts, Window Switcher must be able to:
- read the keyboard devices under
/dev/input/event*; and - write forwarded events to
/dev/uinputor/dev/input/uinput.
The in-app keybind screen recommends the following command on distributions that use the input group:
sudo usermod -aG input "$USER"Sign out and back in after changing group membership, then restart Window Switcher. Some distributions require custom udev rules instead. The uinput kernel module must also be loaded and the device node must be writable.
These permissions grant access to low-level input devices. Review your distribution's security guidance before enabling them. Previews and click-to-focus continue to work without global-keyboard access.
The Linux listener reads evdev events and forwards them through uinput, allowing matching shortcuts to be intercepted without swallowing unrelated keyboard input.
Preferences are stored in config.json inside the application data directory:
| Platform | Default path |
|---|---|
| Windows | %APPDATA%\WindowSwitcher\config.json |
| Linux | ~/.config/WindowSwitcher/config.json in a typical desktop session |
Use File > Open data folder to open the exact directory for the current system.
The file contains:
- preview and UI preferences;
- whitelist and blacklist entries;
- saved preview positions and sizes;
- global keybind targets and shortcuts;
- an anonymous telemetry installation ID; and
- an optional Sentry DSN override for custom builds.
Prefer the in-app controls for routine changes. If you edit config.json manually, close Window Switcher first and keep a backup. Invalid or unreadable configuration is replaced with defaults so that the application can start.
Window Switcher uses Sentry for unhandled-exception reporting and one low-frequency startup metric. Sentry is enabled at compile time by default; builds that include it do not provide a runtime switch to disable it. A Sentry network failure does not prevent the application from running.
The emitted startup metric is:
window_switcher.app_started
Sentry events may contain the following limited runtime metadata:
- anonymous installation ID, used as Sentry
User.Idand astelemetry_installation_idon the startup metric; - telemetry schema version;
- operating system, process architecture, and session type;
- build channel, distribution channel, and package kind;
- application version and preview mode; and
- a sanitized capture source for unhandled exceptions.
Window Switcher does not intentionally send:
- window titles or process names from the user's session;
- local file paths;
- whitelist or blacklist contents;
- global keybind definitions;
- screenshots or window previews;
- shell commands; or
- hostnames, usernames, email addresses, or machine-derived identifiers.
The SentryDsn value in config.json can redirect events for a custom build, but it is not an opt-out. Builds compiled without Sentry ignore this setting entirely.
Use the option that matches the build entry point:
# Direct MSBuild / dotnet
dotnet build Window-Switcher.slnx -p:EnableSentryTelemetry=false# Make
make build SENTRY_TELEMETRY=false
# Nuke packaging
./build/build.sh --target AppImage --enable-sentry-telemetry falseOn Windows, the equivalent Nuke option is:
./build/build.cmd --target Installer --enable-sentry-telemetry false- Confirm that at least one non-empty entry exists under
Config > Filters > Prefixes. - Check that the window title contains that entry and is not an exact blacklist match.
- On Linux, confirm that the desktop window manager exposes the EWMH
_NET_CLIENT_LISTproperty and that the target is an X11 or XWayland window. - On Wayland, confirm that the target application is using XWayland. Native Wayland windows are not discoverable.
- Confirm that Enable previews is enabled.
- Fullscreen applications are not supported; try windowed or borderless-windowed mode.
- On X11, confirm that compositing and the XComposite/XDamage extensions are available.
- On Wayland, install PipeWire and the appropriate XDG Desktop Portal backend, then accept the portal selection prompt.
- Open
Help > Aboutand review Preview mode and Dependency status. - On Wayland, try
Config > Reset all previewsand select the capture source again.
- Open
Config > Keybindsand follow the permission banner. - Confirm read access to
/dev/input/event*and write access to/dev/uinput. - Confirm that the
uinputkernel module is loaded. - Sign out and back in after adding the user to the
inputgroup.
Use File > Clean config file to remove saved preview positions and sizes, then arrange the previews again.
Use File > Generate new config file. This restores default settings, filters, saved layouts, and keybind definitions.
When reporting a reproducible problem, include the application version and the non-sensitive diagnostic information shown under Help > About. Do not post config.json publicly without reviewing it first.
Prerequisites:
- Git
- .NET SDK 10
- the Linux build dependencies, when building on Linux
Clone and run:
git clone https://github.com/SebastienDuruz/Window-Switcher.git
cd Window-Switcher
dotnet restore Window-Switcher.slnx
dotnet run --project src/WindowSwitcher/WindowSwitcher.csprojOn Linux, launch with EGL selected before process startup to enable the PipeWire DMA-BUF zero-copy path:
EGL_PLATFORM=x11 dotnet run --project src/WindowSwitcher/WindowSwitcher.csprojFor Rider, add EGL_PLATFORM=x11 to the Environment variables field of the WindowSwitcher
Run/Debug configuration. The application uses a normal single-process startup and does not alter
the IDE diagnostics or debugger environment.
The standard source build includes Sentry. Add -p:EnableSentryTelemetry=false to the dotnet restore, build, or run command when a Sentry-free build is required.
Window-Switcher/
├── src/WindowSwitcher/ Avalonia desktop UI
├── src/WindowSwitcher.Lib/ Platform and application services
├── src/WindowSwitcher.Tests/ Unit and integration tests
├── build/ Nuke build and packaging project
├── docs/ Screenshots and documentation assets
├── Directory.Build.props Shared version and build properties
├── Makefile Common development commands
└── Window-Switcher.slnx .NET solution
The application targets net10.0 and uses Avalonia with CommunityToolkit.Mvvm. Operating-system interactions are isolated in WindowSwitcher.Lib; the UI and ViewModels must remain platform-agnostic.
Run commands from the repository root:
| Make command | Direct .NET equivalent | Purpose |
|---|---|---|
make restore |
dotnet restore Window-Switcher.slnx + dotnet tool restore |
Restore packages and local tools. |
make build |
dotnet build Window-Switcher.slnx |
Build the solution. |
make run |
dotnet run --project src/WindowSwitcher/WindowSwitcher.csproj |
Run the desktop application. |
make test |
dotnet test src/WindowSwitcher.Tests/WindowSwitcher.Tests.csproj |
Run all tests. |
make test-no-build |
dotnet test src/WindowSwitcher.Tests/WindowSwitcher.Tests.csproj --no-build |
Run tests without rebuilding. |
make clean |
dotnet clean Window-Switcher.slnx |
Clean build outputs. |
make format |
dotnet csharpier format . |
Format the repository. |
make format-check |
dotnet csharpier check . |
Check formatting without changing files. |
make artifacts |
— | Build the release artifact for the current host OS. |
make installer |
— | Build the Windows installer on Windows. |
make appimage |
— | Build the AppImage on Linux. |
The application version is defined once as WindowSwitcherVersion in Directory.Build.props.
Contributions and focused bug reports are welcome:
- Search the existing issues.
- Open an issue for significant behavioral or architectural changes before investing in a large implementation.
- Keep changes small and focused, and add tests for business logic.
- Run
dotnet build Window-Switcher.slnxanddotnet test src/WindowSwitcher.Tests/WindowSwitcher.Tests.csproj. - Run
dotnet csharpier check .before submitting a pull request.
All contributions must follow the engineering rules in AGENTS.md, including the MVVM boundaries, asynchronous-programming requirements, nullability rules, and XML documentation for public library APIs.
Nuke is the release-artifact entry point. Packaging is host-specific: build Windows installers on Windows and AppImages on Linux.
| Target | Host | Output |
|---|---|---|
Restore |
Windows or Linux | Restored project dependencies |
Compile |
Windows or Linux | Compiled application |
Installer |
Windows | build/artifacts/installer/WindowSwitcher-setup-<version>-<win-runtime>.exe |
AppImage |
Linux | build/artifacts/appimage/WindowSwitcher-<version>-<linux-runtime>.AppImage |
Artifacts |
Windows or Linux | Artifact appropriate for the current host |
# Windows installer
./build/build.cmd --target Installer
# Windows Store-labelled compile
./build/build.cmd --target Compile --distribution-channel windows_store --package-kind store# Linux AppImage
./build/build.sh --target AppImage
# Artifact for the current host
./build/build.sh --target ArtifactsUseful options:
--version <x.y.z>overridesWindowSwitcherVersionfor one build.--enable-sentry-telemetry falseexcludes Sentry.--distribution-channel <name>and--package-kind <name>label packaged builds.--makensis-path <path>selects a specific NSIS compiler.
On Windows, the installer target uses the restored NSIS NuGet package when available and otherwise requires makensis from an installed NSIS distribution. NSIS is not restored on non-Windows hosts. The AppImage target finds appimagetool on PATH or downloads it to build/artifacts/tools/.
Build-labelled windows_store packages use store-managed updates instead of the GitHub release updater. Packaging resources live under build/assets/installer/ and build/assets/packaging/linux/; generated artifacts remain under build/artifacts/.
- Five World of Warcraft clients on Arch Linux KDE Wayland (v0.8.0)
- Three World of Warcraft clients on Arch Linux KDE Wayland (v0.7.0)
- EVE Online, World of Warcraft, and Project Gorgon clients (v0.4.0)
Window Switcher is licensed under the GNU General Public License v3.0.
If the project is useful to you, you can support its continued development by buying the maintainer a coffee.





