Skip to content

Add Window icons to workspace visuals - #248

Open
craigloewen-msft wants to merge 21 commits into
glzr-io:mainfrom
craigloewen-msft:main
Open

Add Window icons to workspace visuals#248
craigloewen-msft wants to merge 21 commits into
glzr-io:mainfrom
craigloewen-msft:main

Conversation

@craigloewen-msft

Copy link
Copy Markdown

Overview

This PR adds icons for open applications to the workspace information at the top of the Window.

image

Please also see this PR in Glazewm glzr-io/glazewm#1224 which has required changes as well.

Changes

  • Interpret incoming icon images from Glazewm
  • Change them to grayscale and display them within the workspace element

Related issues

(Self filed): glzr-io/glazewm#1223

* Initial plan

* Add window display to workspace buttons in GlazeWM widget

Co-authored-by: craigloewen-msft <42221804+craigloewen-msft@users.noreply.github.com>

* Apply prettier formatting

* Address code review feedback: extract helper functions and improve fallback

Co-authored-by: craigloewen-msft <42221804+craigloewen-msft@users.noreply.github.com>

* Working update

* Updated!!

* Better CSS

* Ready for PR
@github-project-automation github-project-automation Bot moved this to 📬 Needs triage in zebar Dec 8, 2025
craigloewen-msft and others added 20 commits December 12, 2025 13:09
A small PR that adds permissions for the frontend to use.

Specifically, adds ability to use window effects from the frontend
itself rather than the settings menu (still waiting for
glzr-io#133), and the ability to make the
bar click-through.

I personally use these features in my Zebar configuration with a custom
Zebar build. I'd love to see these get added so there will be no need to
recompile Zebar to use my configuration.

<!--
Before submitting a PR, follow this checklist:

1. Give the PR a descriptive title.

  Examples of good titles:
    - fix: fix race condition in message loop
    - docs: update readme with new demo gif
    - feat: add new `general.focus_follows_mouse` config option

  Examples of bad titles:
    - fix #7123
    - update docs
    - fix bugs

2. If there is a related issue, reference it in the PR description, e.g.
closes glzr-io#123.
3. Propose your changes as a draft PR if your work is still in progress.
-->
The systray-util crate in the zebar project had no support for
double-clicking a system tray icon. The existing SystrayIconAction enum
only covered single left click, right click, middle click, and hover
actions. This meant that applications relying on double-click behavior
for their tray icons (which is common for actions like opening an
application's main window) could not be triggered through the zebar
systray provider.

To solve this, a LeftDoubleClick variant was added to the
SystrayIconAction enum in the core systray-util crate. Its
implementation sends the WM_LBUTTONDBLCLK and WM_LBUTTONUP Win32
messages to the target icon's window, which is the standard Windows
message sequence for a double-click event. It also calls
AllowSetForegroundWindow before sending the messages, matching the
behavior of the other click actions, and sends NIN_SELECT as a follow-up
notification for icons using version 3 or above of the shell notify API,
consistent with how Windows Explorer handles double-clicks.

The change was then propagated through the full stack. An
IconLeftDoubleClick variant was added to the SystrayFunction enum in the
desktop provider layer, with a corresponding match arm in the systray
provider's function handler to route it to the new action. On the
TypeScript side, an onLeftDoubleClick callback was added to the
SystrayOutput interface and wired up in the client provider to invoke
the icon_left_double_click provider function via Tauri commands. This
gives frontend widget authors a new onLeftDoubleClick(iconId) method
they can bind to DOM double-click events.
Now that the [macOS version of
Komorebi](https://github.com/LGUG2Z/komorebi-for-mac) is publicly
available and works mostly the same, I removed the restriction on
limiting it to the Windows version only.

There are some key differences in the schema. It's not clear to me if
these schema changes are going to be updated to be consistent between
macOS and Windows, so for now I've made the parsing logic allow both
formats while keeping platform-specific fields nullable:
* For monitors, `device_id` and `name` can be null. There's a new
`device` field.
* For windows, `hwnd` can be null as macOS doesn't use hwnds.
* The `title`, `exe`, `role`, `subrole`, `icon_path` elements are now
nested under a `details` element. For compatibility, I attempt to parse
these directly from the windows json object if it exists, and under each
respective nested `details` child element if not. This is my first time
working with Rust, so pardon the parsing logic.

---------

Co-authored-by: Lars Berger <lars.berger@yahoo.com>
glzr-io#262)

## Summary

- **Battery provider:** Cache `Manager` and `Battery` instances at
startup, use `Manager::refresh()` each poll instead of `Manager::new()`
every interval
- **Media provider:** Reuse the `GsmtcManager` created at startup
instead of calling `GsmtcManager::RequestAsync()` on every session
change event

Closes glzr-io#261

## Context

These providers were re-initializing expensive OS handles (battery API
handles, WinRT COM objects) on every poll cycle. Over extended uptime
(~24 hours), the accumulated handle churn causes system-wide stutter —
most noticeably when the cursor type changes or UAC dialogs appear.

## Test plan

- [x] Verify battery provider still reports correct values after the
change
- [x] Verify media controls (play/pause/next/previous) still work
- [ ] Run Zebar for 24+ hours and confirm no progressive stutter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Lars Berger <lars.berger@yahoo.com>
…lzr-io#269)

Causes a crash when multiple widget windows with `kCGBackstopMenuLevel`
are set to the same coordinates.
…o#278)

## Summary
- Closes glzr-io#188
- Added `isNextEnabled` and `isPreviousEnabled` boolean fields to
`MediaSession`
- Extracts values from Windows
`GlobalSystemMediaTransportControlsSessionPlaybackControls` API
## Motivation
Not all playback sessions support skip next/previous. Users need this
information to conditionally render skip buttons in their UI.
## Changes
- `packages/desktop/src/providers/media/media_provider.rs`: Added fields
to `MediaSession` struct and updated `update_playback_info()` to
populate them
- `packages/client-api/src/providers/media/media-provider-types.ts`:
Added TypeScript type definitions for the new fields
## Testing
Tested with Spotify & Youtube playing - fields correctly reflect whether
next/previous controls are available.
* Initial plan

* Add window display to workspace buttons in GlazeWM widget

Co-authored-by: craigloewen-msft <42221804+craigloewen-msft@users.noreply.github.com>

* Apply prettier formatting

* Address code review feedback: extract helper functions and improve fallback

Co-authored-by: craigloewen-msft <42221804+craigloewen-msft@users.noreply.github.com>

* Working update

* Updated!!

* Better CSS

* Ready for PR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 📬 Needs triage

Development

Successfully merging this pull request may close these issues.

8 participants