Skip to content

Fix window centering, windowless commands, and add cascade/tile-all#158

Open
gmarthews wants to merge 3 commits into
ssokolow:masterfrom
gmarthews:fix-center-windowless-cascade-tile
Open

Fix window centering, windowless commands, and add cascade/tile-all#158
gmarthews wants to merge 3 commits into
ssokolow:masterfrom
gmarthews:fix-center-windowless-cascade-tile

Conversation

@gmarthews
Copy link
Copy Markdown

Bug fixes:

  • Fix move-to-center positioning window slightly above center due to incorrect application of from_gravity for CENTER gravity. Added Rectangle.center_in() method for proper centering math.
  • Fix windowless commands (show-desktop, workspace-go-*) silently breaking after first invocation by extracting windowless flag at decoration time rather than inside the wrapper loop.
  • Fix GravityLayout treating explicit x=0.0 as unset (falsy check) by using 'is None' comparison.

New features:

  • Add 'cascade' command to arrange all workspace windows in diagonal stair-step pattern.
  • Add 'tile-all' command to tile all workspace windows in optimal grid layout respecting screen aspect ratio.
  • Add Rectangle.center_in() utility method.
  • Add _calculate_optimal_grid() for grid dimension calculation.

Bug fixes:
- Fix move-to-center positioning window slightly above center due to
  incorrect application of from_gravity for CENTER gravity. Added
  Rectangle.center_in() method for proper centering math.
- Fix windowless commands (show-desktop, workspace-go-*) silently breaking
  after first invocation by extracting windowless flag at decoration time
  rather than inside the wrapper loop.
- Fix GravityLayout treating explicit x=0.0 as unset (falsy check) by using
  'is None' comparison.

New features:
- Add 'cascade' command to arrange all workspace windows in diagonal
  stair-step pattern.
- Add 'tile-all' command to tile all workspace windows in optimal grid
  layout respecting screen aspect ratio.
- Add Rectangle.center_in() utility method.
- Add _calculate_optimal_grid() for grid dimension calculation.
@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented Apr 27, 2026

Wow. Thanks. I'll try to make time to start evaluating your changes today.

I do notice a couple of non-code oversights though (probably my bad for not getting around to writing a better contributing doc):

  1. Please add yourself to docs/authors/index.rst and run docs/update_authors.sh. (I give credit for even the smallest contributions and yours is anything but small.)
  2. Please add the notes from your commit message to ChangeLog and, since I haven't had time to work on my big 0.5.0 feature, please rename 0.5.0 to 0.4.2 in ChangeLog and quicktile/VERSION.

EDIT: I've added a PR template to make sure those are clear to future contributors.

@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented Apr 29, 2026

Testing still in progress, but I've found that cascade currently rips Yakuake away from its normal position, at which point Yakuake assumes the user wanted to switch which monitor it's bound to and requires fiddling with its config to get it fixed.

Given this is likely to also affect some desktop sticky note utilities, I'm thinking the most generally applicable solution is probably to exclude windows where Wnck.Window.is_skip_tasklist() == True from the cascade.

The question is whether get_relevant_windows should be amended or split into two classes of relevance. (eg. Whether there any dialog boxes which use _NET_WM_STATE_SKIP_TASKBAR instead of trusting WM_TRANSIENT_FOR to keep them from showing up in the taskbar.)

I'll also want to investigate whether excluding _NET_WM_WINDOW_TYPE_UTILITY from the tiling would be over-broad or just right.

@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented Apr 29, 2026

Actually, looking through the EWMH, it looks like there's a whole class of "probably don't want this" that I forgot to address because I didn't put much thought into commands which affect windows other than the active one.

For example, I hadn't noticed that, when you tear off a toolbar in Qt, that toolbar can be focused, and it doesn't prevent QuickTile from stretching it in unnatural ways... it just snaps back into shape as soon as you move it with the mouse.

...so yeah. I should probably split the concept of "relevance". I can see the following types of windows being things people might want to reposition with QuickTile's active-window commands, but which they probably wouldn't want subject to "all windows" tiling commands:

  • _NET_WM_WINDOW_TYPE_TOOLBAR (Floating toolbars)
  • _NET_WM_WINDOW_TYPE_MENU (Torn-off menus)
  • _NET_WM_WINDOW_TYPE_UTILITY (Detached docks and things like Yakuake)
  • _NET_WM_WINDOW_TYPE_SPLASH (Splash screens)

(i.e. The things which can potentially receive focus, but which a full-blown tiling window manager would generally set "allow floating" exceptions for or have specialized handling of.)

@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented Apr 29, 2026

As for the hard-coded offset = 25, since I was never the target audience for cascading (I never used it, even on Windows 3.1), I'll ask for your opinion.

It shouldn't be hard-coded, but do you think it should be a line in quicktile.cfg for users to customize or should QuickTile attempt to match it to the height of the WM-provided titlebars?

My intuition says the latter, to ensure the window titles are visible regardless of the user's chosen font size.

@gmarthews gmarthews force-pushed the fix-center-windowless-cascade-tile branch from 12ca957 to 050d710 Compare May 9, 2026 03:10
@ssokolow
Copy link
Copy Markdown
Owner

Sorry for not replying promptly. It's been a busy week. I'll try to make time to look over the updated PR within a couple of days.

@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented May 23, 2026

Clearly things didn't go as planned. Just wanted to let you know I haven't forgotten about this... it's been difficult to make time for my hobby projects when I have the energy to review code.

- Add grid-overlay command with visual GTK overlay for selecting window
  position by clicking two corners or using arrow keys
- Add cascade command to arrange windows in diagonal stair-step pattern
- Add tile-all command to tile all workspace windows in optimal grid layout
- Fix move-to-center positioning (incorrect from_gravity for CENTER gravity)
- Fix windowless commands (show-desktop, workspace-go-*) breaking after
  first invocation
- Fix GravityLayout treating explicit x=0.0 as unset (falsy check)
- Add Rectangle.center_in() utility method
- Add _calculate_optimal_grid() for grid dimension calculation
- Add GridOverlay class in new overlay.py module
- Add GridRows/GridCols config defaults and <Super>Return keybinding
- Add author entry, update ChangeLog, bump VERSION to 0.4.2
@gmarthews gmarthews force-pushed the fix-center-windowless-cascade-tile branch from 050d710 to d67c162 Compare May 24, 2026 07:52
…urable

- Exclude TOOLBAR, MENU, UTILITY, SPLASH window types and
  is_skip_tasklist() windows from get_relevant_windows (used by
  cascade, tile-all, cycle-monitors-all)
- Add CascadeOffset config setting (default 25) replacing hardcoded
  offset in cascade command
@gmarthews
Copy link
Copy Markdown
Author

gmarthews commented May 24, 2026 via email

@ssokolow
Copy link
Copy Markdown
Owner

ssokolow commented May 25, 2026

happy to adjust if you think the exclusion list is too broad or not broad enough.

Thanks. I'll see if I can find edge cases when I test it.

Titlebar height auto-detection seemed fragile across different WMs and themes, so a config option felt like the more maintainable choice.

How are you detecting them?

Is calculating the offset between Wnck.Window.get_client_window_geometry and Wnck.Window.get_geometry not reliable? ...because I vaguely remember calculating that on GdkWindow being what I did over a decade ago when I wasn't using libwnck and needed to work around bugs.

I could understand applications with client-side window decorations (eg. GtkHeaderbar) returning the same thing for those two calls (though I think there may still be a way to query the difference under GtkHeaderbar... maybe it's exposed in an xprop?).

The grid overlay

Starting to sound closer to what I'd been meaning to rearchitect QuickTile around for #10

...though please do be careful about how far you go. I'm fine with A.I.-generated code where the only thing it could be plagiarizing is QuickTile itself, or where it's generating "glue one API to another" code so simple that it's not eligible for copyright, but I'm not yet sure how far I'm willing to go in areas where, if A.I. training is declared to be plagiarism in the future, it may be difficult to unwind QuickTile from it.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants