Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Currently unpredictable state cycling, suggest replace with much simpler logic, gains predictability and cognitive comfort. #119

Open
fidergo-stephane-gourichon opened this issue Aug 30, 2020 · 1 comment
Labels

Comments

@fidergo-stephane-gourichon
Copy link

Hi!

Done homework, looked existing issues before posting

This request is related with, though different from, #30 , and more remotely to #13 .

Observed situation

I've been using quicktile for a long enough time and observed I converged to always purposefully press an "unwanted" key combination then the intended combination. For example: "maximize" then "left half", when I actually mean "left half".

Why?

  • All those key combinations are not one-shot. They actually cycle through states: the "obvious" state, and others (1/3, 2/3).
  • I very rarely want the 1/3 or 2/3 state.
  • The issue is, quicktile does its best to guess which of the states is current, then switch to the next. But the logic is unpredictable.
  • The whole point of quicktile is to quickly tile windows. If pressing a key combo does what the user means without a doubt, it's a win. If the user has to press, look, press again, look, until the desired state appears, then it's a loss. From a cognitive load point-of-view, it replaces a fire-and-forget action with a act-check-loop-until, which requires different (more) cognitive resources. Like a cache miss in a modern processor.

Acknowledging the difficulty

You explained well here and IIRC in other places why it's so difficult to figure out if a window is already tiled.

Perhaps a good solution would be to look in a different direction.

Thinking aloud

What if we considered something very simple, just give up the complexity and restore the main point: predictability?

What if we replaced all "is already tiled" code with a simple time-base state machine, that just totally ignores the actual window position? Looks foolish?

Here's a suggested logic:

  • quicktile maintains a "state" variable, not even one per window, just one global
  • when quicktile is summoned, if more than 5 seconds (configurable) were elapsed since last time, reset state
  • when quicktile is summoned, if the focused window ID is different from last one, reset state
  • switch state following one step of this logic diagram: (reset)->(main)->(1/3)->(2/3)->(go back to main).
  • apply the action corresponding to reached state: "main" is the obvious one (maximize, or tile to half-side or quarter-corner), "1/3" and "2/3" are the other existing actions.

Benefits

  • No more complicated guesswork depending on window managers, special windows that snap, etc, etc.
  • Predictable!

Suggested documentation wording

Before

Usage (Typical)

  • Focus the window you want to tile
  • Hold the modifiers defined in ModMask (Ctrl+Alt by default).
  • Repeatedly press one of the defined keybindings to cycle through window sizes available at the desired location on the screen.

After

Usage (Typical)

  • Focus the window you want to tile
  • Hold the modifiers defined in ModMask (Ctrl+Alt by default).
  • Press the key combination to get the main wished effects: maximize, left half, right half, top half, bottom half or one of the four corners.
  • (optional) press once more if you actually want the 1/3 variant.
  • or twice more if you actually want the 2/3 variant.

Why is the "after" behavior simpler for the user?

  • The beginner user can just press once and not even care about the "extra" states.
  • The advanced user just has to remember: half, 1/3, 2/3, and press once, twice or thrice, get what they mean.
  • For all users: nothing to check, works all the time.

And for maintainer: simpler logic, less code, less complexity.

Conclusion

IMHO this is simpler to the user, more predictable thus less cognitive load, reduces code complexity.

What do you think?

@ssokolow
Copy link
Owner

ssokolow commented Aug 30, 2020

The issue is, quicktile does its best to guess which of the states is current, then switch to the next. But the logic is unpredictable.

Actually, it hasn't been unpredictable in the strictest sense for a while. It used to detect heuristically, but it currently sets a _QUICKTILE_CYCLE_POS property on tiled windows which stores the index of the current tiling state in the sequence.

That was my solution for things like MPlayer's fixed aspect ratio. (#20)

Most of the remaining apparent unpredictability is just a need for more code to either reset the sequence or reapply the tiling preset in cases like switching monitors (#24).

The whole point of quicktile is to quickly tile windows. If pressing a key combo does what the user means without a doubt, it's a win. If the user has to press, look, press again, look, until the desired state appears, then it's a loss. From a cognitive load point-of-view, it replaces a fire-and-forget action with a act-check-loop-until, which requires different (more) cognitive resources. Like a cache miss in a modern processor.

...but I will agree with this.

What if we replaced all "is already tiled" code with a simple time-base state machine, that just totally ignores the actual window position?

My main concern there is that it's a big change. I can certainly see the benefit, but I doubt I'm the only one to have used the current approach as envisioned and reworking muscle memory like that shouldn't be done lightly.

IMHO this is simpler to the user, more predictable thus less cognitive load, reduces code complexity.

What do you think?

I'll need to think more on it when I'm not half-dead from fighting to fix a broken sleep cycle (the core reason I haven't been working on QuickTile) and sneezing my nose off because sleep deprivation interferes with over-the-counter allergy medication, but I don't think it'll actually reduce code complexity.

Getting and setting properties on the active window is simple (and the getting code is also used for stuff like querying _NET_WM_STRUT_PARTIAL to determine the usable workspace) while QuickTile currently has no code to support timeouts.

Plus, while it's got some race conditions I need to fix, QuickTile does have a "run as a subprocess to process one command, then exit" mode which would rule out some avenues for implementing what you propose. (I'd have to store a bunch of state on the root or active window rather than in local or member variables.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants