Shift-click Notification Groups Without Breaking Ordinary Clicks

Adding Shift-click group dismissal to Glimpse meant preserving three existing click paths and carrying modifier state across the widget boundary.

Glimpse now lets Shift-click dismiss a whole notification group, but the code change was less about deleting several IDs than about preserving every ordinary click. Group expansion, notification activation, and ungrouped notifications all shared the same gesture path.

The feature shipped in Glimpse 0.15.1 through pull request 13. The interesting part is the event boundary that made the behavior precise.

The modifier belonged to the click event

GTK's GestureClick inherits access to the modifier state associated with the current event from 1. That state had to travel with the click through Glimpse's widget message path. Reading global keyboard state later would make the result depend on timing rather than the event the user actually generated.

Once the modifier reached the notification component, the behavior could be written as a narrow decision:

  1. Grouped and Shift-clicked: emit DismissGroup with the IDs of the visible group members.
  2. Grouped and ordinarily clicked: keep the existing expand or activate behavior.
  3. Ungrouped: preserve the existing activation path, even if Shift is held.

The third case prevented a convenient shortcut from becoming a surprising global rule. Shift was a modifier for a group action, not a new meaning for every notification.

A group action still became individual protocol actions

The notification service already knew how to dismiss one notification. The UI did not need a second backend protocol for groups, so DismissGroup(Vec<u32>) remained a UI-level intent and the service sent the existing dismiss command for each ID in sequence.

That separation keeps the model honest. A group is a presentation concept created by Glimpse, while the notification server still owns individual notifications. Treating the group as an atomic server object would imply guarantees the underlying protocol does not provide.

Sequential dismissal also made failure behavior easy to reason about. There was no concurrent fan-out whose completion order could change the list while the user was looking at it. The group might change between commands if another event arrived, but every command still referred to a concrete notification ID captured by the click.

Interaction tests need the negative cases

The obvious test is that Shift-clicking a group dismisses all its members. That test alone would allow several regressions: an ordinary click could start dismissing the group, an ungrouped click could stop activating, or the group could expand before dismissal.

The implementation was checked against the full behavior table instead. The Rust CI and secret scan passed on the merged pull request, but the more important confidence came from proving that the new branch was entered only for a grouped notification with the Shift modifier present.

Small desktop interactions are often shaped like this. The visible feature is one shortcut, while the real work is defining the exact boundary around it. Carry the original event data far enough, make the new state transition explicit, and test the paths that must remain boring.