Well, I missed my self-imposed deadline on the constraints experiments work I’ve been doing on Metacity. I really need to help Olav out with bugzilla, though, so it’ll have to kind of be on the backburner for a little while. It’s kind of painful to do it that way since I like the branch version so much better (since the couple major regressions don’t affect my usage scenarios). Anyway, for the curious, I thought I’d list the bugs that got fixed on the branch in the process of trying to rewrite constraints.c to make it human readable and ensure that it was flexible enough to handle everything we needed.
FIXED:
- unfiled – constraints.c is overly complicated[1]
- unfiled – constraints.c is not robust when all constraints cannot simultaneously be met (constraints need to be prioritized)
- unfiled – keep-titlebar-onscreen constraint is decoration unaware (since get_outermost_onscreen_positions() forgets to include decorations)
- 109553 – gravity w/ simultaneous move & resize doesn’t work
- 113601 – maximize vertical and horizontal should toggle and be constrained
- 122196 – windows show up under vertical panels
- 122670 – jerky/random resizing of window via keyboard[2]
- 124582 – keyboard and mouse snap-resizing and snap-moving erroneously moves the window multidimensionally[3]
- 136307 – don’t allow apps to resize themselves off the screen (*cough* filechooser *cough*)
- 142016, 143784 – windows should not span multiple xineramas unless placed there by the user
- 143145 – clamp new windows to screensize and force them onscreen, if they’ll fit
- 144126 – Handle pathological strut lists sanely[4]
- 149867 – fixed aspect ratio windows are difficult to resize[5]
- 154706 – bouncing weirdness at screen edge with keyboard moving or resizing
- 156699 – avoid struts when placing windows, if possible (nasty a11y blocker)
- 302456 – dragging offscreen too restrictive[6]
- 308521 – make uni-directional resizing easier with alt-middle-drag and prevent the occasional super annoying resize-the-wrong-side(s) behavior
- 312007 – snap-resize moves windows with a minimum size constraint
- 312104 – resizing the top of a window can cause the bottom to grow
So what’s left?
- The “force new windows onscreen” and “don’t allow apps to become partially offscreen due to a resize unless already partially offscreen” behaviors make edges seem special and make it weird to not have edge resistance at screen edges when the user moves windows around. So, the long requested edge-resistance feature request needs to be written[7]. This has been started.
- Fix the regressions (shouldn’t be hard, but I’m waiting off on this due to the infrastructure that needs to be added for the edge resistance stuff)
- I need to write up some documentation about the structure of the framework and changes made; I started that over a month ago but it’s actually misleading now as I’ve had to modify the framework a fair amount. Should be relatively easy; just need a couple hours to write everything up and carefully check that it’s easy to understand.
- (Optional) Fix the extra issues related to fixed bugs (or almost fixed ones) pointed out in the notes below
NOTES:
[1] Well, at least I hope so. constraints.c is much easier for me to read, though largely due to the fact that much of the complexity has been moved to boxes.c. However, there is an extremely thorough set of testcases for boxes.c in testboxes.c, and those testcases are automatically compiled into a simple test program named testboxes. I think this separation helps a lot for managing the complexity and for ensuring that things work correctly.
[2] Actually, not totally fixed (just annoying instead of almost completely unusable). Matthias had a suggestion that may fix the remainder of the problems.
[3] There are two closely related bugs remaining though. Trying to mouse snap uni-directionally is still difficult because we only provide a threshold of 1 pixel movement before snapping. Also, there’s a related issue in that if the user stops pressing shift before letting go of the mouse button, then the ButtonRelease triggers a non-snapped movement causing the window to “un-snap” from where it was to somewhere potentially far away. Neither of these should be too difficult to fix, I’ve just run out of time for now.
[4] This bug was originally about not-quite-so-pathological cases but was left open for the worse cases. The code on the branch handles the remainder of the cases mentioned in this bug.
[5] There’s still some bugs with it, namely (A) a slight drift that’s only noticeable after lots of resizing, and (B) nasty interaction with onscreen constraints. Neither of those are quite so common, though, so I’ve punted handling those, and in any event things are *way* nicer on the branch.
[6] Though I’ve done virtually no testing so I’m not sure if my new simple formula is too lenient or still too strict. However, any further adjustment to get it in the right range should be trivial.
[7] The patches in bug 81704 are nice and helpful for testing and perhaps for getting started (though it appears they only apply to moving windows and not resizing them), but much more needs to be done:
- We should not have edge resistance at the edge of the “workarea”; with panels that only extend part of the length of the screen, we don’t want to snap to the “missing” part of the panel–we want to have edge resistance on the actual screen edges. Therefore, the correct patch can not make use of the meta_window_find_(next|nearest)_(horizontal|vertical)_edge functions.
- Edges of the screen (including between monitors for xinerama setups) and edges of windows should be treated differently by edge resistance because we should facilitate users “throwing” their window against the screen edge. Using pixel-distance for resistance is not sufficient for this. We need to include timeouts too.
- Magnetism sucks (haha, I’m so punny), resistance is good (Commander Riker proved The Borg were wrong). We do want to allow windows to kind of “stick” when they are already next to each other, and I’m of the opinion that magnetism was just a simple attempt to implement that (it’s probably much easier to implement windows getting sucked to each other when within a certain distance than to implement only allowing adjacent windows to move apart with a sufficiently strong move). I really hate having windows getting “pulled away from me”. I guess, in effect, I’m advocating something that could be called 0-distance magnetism to go along with resistance.
- We should not have edge resistance/magnetism due to unseen edges. If you have some small window buried under a bunch of large firefox/gedit/openoffice/emacs windows, the current patches blindly snap to them. Again, that’s a shortcoming of the the meta_window_find_(next|nearest)_(horizontal|vertical)_edge functions in place.c and is another reason to not use them.
- We shouldn’t be searching for edges more than we need to, we ought to just cache them when they aren’t going to change (i.e. create and cache them at the beginning of the move/resize op instead of recomputing them every time the window moves or resizes slightly during the move/resize operation. Also the screen edges can be found and cached when determining the workarea in workspace.c so that they don’t need to be recomputed with every move/resize-grab-op).
- The keyboard snap moving/resizing needs to be fixed according to the relevant parts of the above criteria as well (including the fact that resistance should be strong enough to require several keypresses to move past the screen edge instead of just one). And instead of having the code duplicated in the keyboard resize function, the keyboard move function, and both the resize and move mouse functions once this gets implemented, we should factor this all out into one common place.