Skip to content

gwl: Add overflow support through slide/scroll list#13352

Open
anaximeno wants to merge 31 commits intolinuxmint:masterfrom
anaximeno:gwl/add-support-for-slide-on-overflow
Open

gwl: Add overflow support through slide/scroll list#13352
anaximeno wants to merge 31 commits intolinuxmint:masterfrom
anaximeno:gwl/add-support-for-slide-on-overflow

Conversation

@anaximeno
Copy link
Contributor

@anaximeno anaximeno commented Jan 10, 2026

closes #11540
solves https://github.com/orgs/linuxmint/discussions/82

Example of how it should work

output.mp4

@Initu-Castilhos
Copy link

This feature is great, it's similar to dash to dock and dash to panel. Hopefully it will be implemented in the stable version.

@JosephMcc
Copy link
Contributor

Didn't actually try it yet, but it looks pretty slick. Wonder if you could use vfade when the slider button shows up as a bit more of a visual cue.

@anaximeno anaximeno force-pushed the gwl/add-support-for-slide-on-overflow branch 2 times, most recently from 21564ff to 5da320c Compare January 11, 2026 03:54
@anaximeno
Copy link
Contributor Author

Wonder if you could use vfade when the slider button shows up as a bit more of a visual cue.

I'll give it a try and see if I can get it to work with it.

@anaximeno anaximeno marked this pull request as ready for review January 11, 2026 20:34
@anaximeno anaximeno changed the title [WIP] gwl: Add overflow support through sliding gwl: Add overflow support through sliding Jan 21, 2026
@anaximeno anaximeno changed the title gwl: Add overflow support through sliding [NEXT] gwl: Add overflow support through sliding Jan 21, 2026
@anaximeno
Copy link
Contributor Author

@JosephMcc I've updated the implementation to use the native St.ScrollView instead of a direct container translation to handle the scroll, which goes with how scroll is being implemented accross Cinnamon. I wanted to use it initially as well but was having some issues with the scroll not taking effect in the gwl and instead the same stretch behavior was persisting, however I found the reason for it and it seems it was that since there was no overflow method before, a change was introduced to set the min_size of the AppGroup.actor around 1 (which meant instead of the container knowing what's the proper size to represent the full content it was considering that it should just stretch almost indefinetely, so I reverted that behavior in https://github.com/linuxmint/cinnamon/pull/13352/changes#diff-ff87e15fbe5d4a462aeef966bf403d5543648b31289a55f4b835cdcfcb32f362.

Thanks to that and getting St.ScrollView to work, I can also use the vfade/hfade in the edges instead of the slider buttons (as you suggested), I've updated the video demonstration above to represent that.

In general I think this PR is ready for testing and consideration, and I'll be continuing to test and it sending adjustments if necessary until the next merge window.

Regards.

@anaximeno anaximeno changed the title [NEXT] gwl: Add overflow support through sliding [NEXT] gwl: Add overflow support through scroll Jan 21, 2026
@clefebvre clefebvre changed the title [NEXT] gwl: Add overflow support through scroll gwl: Add overflow support through scroll Jan 22, 2026
…orkspaces

To find the new app position in the container instead of using actor.x we are summing the size of each preceding appGroup until the current app to focus because actor.x would report 0 some times.
This was triggering GLib Critical error in the logs.
…uttons visibility

This avoids issues with improper representation of the current allocation after the buttons are hidden.
…to debounce setting scrollActive state as inactive to avoid triggering the menu during the scroll animation
@anaximeno anaximeno force-pushed the gwl/add-support-for-slide-on-overflow branch from 93b827c to f70951b Compare February 9, 2026 21:13
This avoids an issue where during workspace switching some times a minimized window would visually have the focused window style when it shouldn't.
@anaximeno anaximeno force-pushed the gwl/add-support-for-slide-on-overflow branch from 1f0031b to 8198512 Compare February 16, 2026 04:22
This is useful when switching to a new workspace or the applet is reloaded so it guarantees user will at least be aware of opened windows that could otherwise be hidden if the scroll state is mantained.
If there's no opened windows just keep the current scroll state.
I've also decided to change the scroll key name, this with the goal of guaranteeing that the scroll app window list will be set as default for all users, those that want other options, or none, can switch back.
@kneekoo
Copy link

kneekoo commented Mar 3, 2026

Thanks for working on this! There's one thing that would be useful, and that's indicators that more buttons exist in either direction of the panel. Without a visual cue, the user may be unaware that more windows are open.

@anaximeno
Copy link
Contributor Author

Thanks for working on this! There's one thing that I would be useful, and that's indicators that more buttons exist in either direction of the panel. Without a visual cue, the user may be unaware that more windows are open.

Uhm, I'll consider bringing back the slider buttons that I had previously then, and use them along the fade, since the fade can be less perceptible in some cases, and seems to not be used even in some themes.

@anaximeno anaximeno force-pushed the gwl/add-support-for-slide-on-overflow branch from 9dad14c to 0d4affe Compare March 7, 2026 06:35
@anaximeno anaximeno force-pushed the gwl/add-support-for-slide-on-overflow branch from 0d4affe to 1b0f268 Compare March 7, 2026 06:50
@anaximeno anaximeno changed the title gwl: Add overflow support through scroll gwl: Add overflow support through slide/scroll list Mar 7, 2026
@mtwebster
Copy link
Member

I get really weird behavior when scrolling, if 'group windows' is disabled, and I have 'cycle apps' or 'cycle windows' as the scroll action... this may be pre-existing, I don't normally use this applet.

I also get a lot of 'access-after-disposed' warnings if I close a workspace that had windows on it.

This works well, but:

  • There's no way to disable it - some users might prefer a static, if compressed list.
  • I'm also not sure about the auto-scrolling - it's very easy to accidentally trigger it. You can already use the mousewheel or click the arrows to navigate.

Claude review fwiw:

● PR #13352 Review Summary

  "gwl: Add overflow support through slide/scroll list" — 536 additions, 40 deletions, 6 files, 27 commits

  Critical Issues (3)

  1. Double-handling of scroll events when scrollBehavior !== 4

  File: scrollBox.js:557-559

  When the scroll behavior is set to anything other than "Slide app list", the scrollBox does:
  if (this.state.settings.scrollBehavior !== 4) {
      this.state.trigger('handleScroll', event);
      return;  // returns undefined = EVENT_PROPAGATE
  }

  This triggers handleScroll on the applet via state, then the event bubbles up to the applet actor's own
  scroll-event handler (applet.js:284), calling handleScroll a second time. For "Cycle apps" or "Cycle
  windows", this means every scroll tick cycles twice.

  Fix: return Clutter.EVENT_STOP; after the trigger.

  2. Destroy order causes operations on destroyed actors

  File: workspace.js new destroy() method

  destroy() {
      this.scrollBox.destroy();  // Destroys entire actor tree including appGroup actors
      // ...
      this.appGroups.forEach( appGroup => appGroup.destroy() ); // Actors already destroyed!

  scrollBox.destroy() calls this.actor.destroy() which recursively destroys all children. Then
  appGroup.destroy() tries to container.remove_child() on a destroyed container and this.actor.destroy() on
  already-destroyed actors.

  The willUnmount guard only protects during on_applet_removed_from_panel, not during normal workspace
  removal (onWorkspaceRemoved at applet.js:972). So closing a virtual desktop will trigger operations on
  finalized GObjects.

  The old code destroyed appGroups before the container actor. Fix: restore that ordering — move
  this.scrollBox.destroy() to after the appGroup iteration.

  3. Setting key rename loses existing user preferences

  File: settings-schema.json:99-108

  scroll-behavior is renamed to list-scroll-behavior with a new default of 4. Cinnamon applet settings have
  no migration mechanism — the old key value in ~/.cinnamon/configs/ is orphaned. All existing users who
  chose "None", "Cycle apps", or "Cycle windows" will silently get "Slide app list" instead.

  Fix: Either keep the old key name (just add option 4), or accept this as an intentional UX decision with
  the understanding that existing preferences are lost.

  Important Issues (2)

  4. Stray semicolon after return in updateFocusState

  File: workspace.js:53 (PR diff)

      this.scrollToAppGroup(appGroup);
      return;
  };  // <-- stray semicolon after closing brace

  Harmless but incorrect syntax.

  5. Inline styles duplicate/override theme CSS

  File: scrollBox.js:224

  const buttonStyle = 'min-width: 15px; min-height: 20px; margin: 0px; padding: 0px;';

  The SCSS already sets margin: 0; padding: 0; for these classes. The inline style overrides theme CSS,
  preventing theme customization. The min-width/height should move to SCSS too.

  Suggestions (3)

  6. scrollToChild doesn't verify allocation validity

  File: scrollBox.js:375-416

  get_allocation_box() returns zeros for unallocated actors. The 100ms debounce makes this unlikely in
  practice but a has_allocation() check would be defensive.

  7. Edge scroll zone not scaled by ui_scale

  File: scrollBox.js:196

  EDGE_SCROLL_ZONE_SIZE = 48 is unscaled, unlike the slide speed which uses global.ui_scale. On HiDPI, 48px
  is physically smaller.

  8. Vertical panel scroll with behavior 4

  File: scrollBox.js:563-598

  The vertical-wheel-to-horizontal-scroll mapping only works in horizontal mode. Vertical panels fall
  through to EVENT_PROPAGATE, relying on native ScrollView handling. Works but isn't explicit.

  Confirmed Non-Issues

  - actor → container references: The PR correctly changes all child operation call sites (removeChild,
  get_children, insert_child_at_index, add_child, set_child_at_index) in both workspace.js and applet.js. No
   missed references.
  - scrollToLastFocusedApp fallback logic: Priority chain is correct — the metaWindows.length === 0 guard
  properly handles windowless matches.
  - onEnter suppression during scroll: Intentional — prevents distracting hover menus/tooltips while
  sliding.
  - Rapid _stopSlide calls: The slideDirection === 0 check in the timeout callback correctly prevents
  premature scrollActive clearing when a new slide starts.
  - _startSlide timer boundary stop: scrollActive stays true until leave-event triggers _stopSlide, which is
   correct since the user must move away to interact.

  Strengths

  - Clean ScrollBox architecture with proper SignalManager usage and signal cleanup
  - Debounced scrollToAppGroup prevents excessive scrolling during rapid focus changes
  - Edge scroll zones via motion events work well for drag operations
  - scrollToChild accounts for fade offsets to keep items visible
  - Adjustment signal tracking with proper connect/disconnect on orientation change
  - Timer-based slide at 16ms interval for smooth ~60fps animation
  - Scroll button visibility updates via both adjustment value and content size changes

@anaximeno
Copy link
Contributor Author

I'll take a look.

@anaximeno
Copy link
Contributor Author

anaximeno commented Mar 12, 2026

I get really weird behavior when scrolling, if 'group windows' is disabled, and I have 'cycle apps' or 'cycle windows' as the scroll action... this may be pre-existing, I don't normally use this applet.

Might've been related to the point 1. suggested by Claude, should be already fixed now.

I also get a lot of 'access-after-disposed' warnings if I close a workspace that had windows on it.

Related to the point 2. suggested by Claude, should be fixed now as well.

This works well, but:

There's no way to disable it - some users might prefer a static, if compressed list.

Uhm, I think it could be put as a settings option; however, I'm unsure if it would be worth increasing complexity here versus anyone actually missing the previous behavior (I might be wrong though), especially considering the previous behaviour would lead to situations like in the image below:

image

I'm also not sure about the auto-scrolling - it's very easy to accidentally trigger it. You can already use the mousewheel or click the arrows to navigate.

Added a settings option to disable the autofocus to the focused app button, which is triggered on focus change and on workspace switched.

Now on the Claude review

  1. Double-handling of scroll events when scrollBehavior !== 4

Fixed.

  1. Destroy order causes operations on destroyed actors

Fixed.

  1. Setting key rename loses existing user preferences

Intentional, while this could reset options some users had before the update, they can set it back. The reason for this is that most users would have it set to None, considering that was the previous default, but ideally for them, this should be defaulted to the slide-on-scroll option for when they find themselves in a case where they need to use this to already be enabled. (I'm open to using the previous key if deemed better)

  1. Stray semicolon after return in updateFocusState

Minor issue, fixed.

  1. Inline styles duplicate/override theme CSS

Fixed.

  1. scrollToChild doesn't verify allocation validity

Fixed.

  1. Edge scroll zone not scaled by ui_scale

Fixed.

  1. Vertical panel scroll with behavior 4

This is regarding the handling of opposite-direction scroll not being handled in vertical scrolls as horizontal, but it is intentional, and is a standard behavior for desktop scroll, afaik.

Looks better and is consistent with what is used in the alt-tab window switcher for example when it reaches the limits of the screen.
@anaximeno
Copy link
Contributor Author

@mtwebster there's one thing I noticed, I'm not sure what causes it, but it seems that for some reason, when a horizontal fade is active on either side of the scroll view in gwl, it triggers some hfade on the same side on scrollviews in popup menus, which makes the handle in the popup menu not (or less) visible due to the fade over it:

Before having hfade active in gwl

image

After having hfade active in gwl

image

I wonder if it is some sort of rendering issue? I don't see why the scrollview from here should affect the other one in the popup menu.

@kneekoo
Copy link

kneekoo commented Mar 13, 2026

An interesting issue: since 22.3 came out, I noticed that the language/keyboard indicator also gets contracted when a lot of apps push the system tray out of the screen, but only if the indicator consists of letters - the flag is displayed properly.

While the keyboard indicator is not part of the Window list applet, I'm not sure if it can be solved here. But since a growing number of apps in the list can push the keyboard indicator, it would be nice to take a look at this as well, even if only to confirm that it's off-scope here.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Better approach when running out of space in the panel

5 participants