One feature that I've really been wanting from compiz is to give windows a bit of momentum when I'm moving them around. In other words, if I flick a window with the pointer and then let go, I want it to continue moving, so that it can be "thrown" across the screen. Thankfully, someone involved in compiz wrote such a plugin, found on his blog here. Unfortunately, the strategy that he uses doesn't work well for me. There are essentially three problems with it:
- In order to calculate the velocity of the window after it is released, he compares the window position at the time it is released to the window position at the time it was grabbed, and calculates the delta. This leads to weird behavior when the users is indecisive and moving the window around sporadically before releasing it.
- The velocity of the window has an unnatural association to the actual "velocity" that the user was moving it with.
- The velocity appears to be zero when using a pen-tablet (wacom) input because my hand generally stops before the pen moves out of range of the tablet.
While the compiz API documentation is in a very sad state, Sam's plugin showed me all the parts of the API that I needed. I rewrote the plugin to essentially low-pass the velocity of the window, sampled at the compiz frame rate. At each "movement" event, I update the delta in the x direction and the y direction. At each "frame" of compiz, I bake the accumulated deltas, along with the time (in ms) since the last sample. The accumulated deltas and the number of milliseconds are stored in a ring buffer. When the window is released, the buffer is averaged to get a window velocity in pixels-per-millisecond.
I also augmented the window structure to store a floating point representation of the window location. Together with the low-pass on the velocity, the outcome seems to be a lot smoother.
The window velocity exactly matches what I "feel" like the velocity of the window is when I let go of it. Also, the filter only has enough history for a couple of frames so weird movement of the window prior to release is "forgotten", and only the "most recent velocity" is used.
The code for the plugin can be found in my github