(Apologies if you already know much/all of this.)
When an X client app attempts to move or resize one of its
(non-override-redirect / "popup" in GDK parlance) windows, the
ConfigureRequest message that it sends to the X server gets redirected
to the window manager. The window manager has the option of sending
the request back to the server (possibly with modifications) or
ignoring it. Once the X server receives the request from the window
manager, it resizes the window, which triggers ConfigureNotify and
(only if the window gets larger, I think) expose events to be sent to
the client. After all of this is done, the client can send additional
requests to the X server to repaint the window.
But things are actually more complicated than this, at least for many
common window managers.
http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2552503
describes a scheme by which the window manager, upon resizing a
window, asks the client to notify it once it's done repainting the
resized window. This was initially done to rate-limit resizes so that
clients wouldn't fall behind, but in the case of compositing window
managers (Compiz, Mutter, KWin, etc.), it's also used to avoid drawing
the window onscreen again until it's been fully repainted.
So if you're trying to animate resizes while running under a
compositing window manager, I think that you're looking at:
- Chrome sends ConfigureRequest to server
- server sends ConfigureRequest to window manager
- window manager sends _NET_WM_SYNC_REQUEST ClientMessage to Chrome
and ConfigureRequest to server
- server sends ConfigureNotify to Chrome
- Chrome sends paint commands to server and increments sync request counter
- server sends damage event and notification that counter changed to
window manager
- window manager fetches updated window contents and paints them
onscreen using GL or whatever (avoiding additional copies, driver
willing)
If you're using override-redirect windows, the initial
ConfigureRequest redirection and the sync request stuff goes away (at
the expense of unpainted garbage probably being visible onscreen as
the window resizes itself).
If you only care about making the animation work for compositing
window managers, a better approach might be just using an RGBA window
for your panel (if you aren't already), and then resizing the window
just once to the final size and only animating its _appearance_
changing between the two sizes. That way, the resizing-related bits
only happen once and you can do your animation without any round trips
to the server.
I've found xtrace (http://xtrace.alioth.debian.org/) to be useful in
debugging performance issues in X clients. You could also try running
your code without a window manager to see if that improves things.
You're probably not seeing any performance issues with move animations
since your client doesn't need to redraw its windows' contents for
each frame of animation. In the resize case, I think that there's a
round trip between your client and the X server for each frame (as you
might not redraw until you receive notification from the server that
the window has been resized). It's possible that GDK avoids this
delay for popup windows since it knows that its resize request will be
honored. Things will still look janky since resizing and redrawing
happen non-atomically, though.
> At the moment, I don't know if this only needs to work for compositing
> window mangers. Is there a policy in Chrome with regards to what window
> managers we work well with? Can you send me some pointers to info/API for
> RGBA windows? A quick search didn't turn up much. And lastly, what does
> animating appearance mean? My specific scenario is that I'm sizing the
> window from a height of say, 400 pixels, down to 5 pixels and trying to
> animate this by resizing a few pixels every 20 seconds.
I meant that in the case of making a panel resize from 100x100 to
400x400, you could resize the window once to 400x400 and paint the
contents within the 110x110 region while leaving the rest of the
window transparent, then within 120x120, and so on. The window's
alpha channel will only be honored if there's a compositor running,
but if you don't need partial transparency, you could use the shape
extension to mask out portions of the window without using RGBA
windows (using the shape extension may have worse performance in
compositing window managers, though). I don't know of any good
resources about RGBA windows in X. :-/
It's a bit off-topic, but what's your plan for the actual
implementation of this with regard to using normal vs. popup windows?
If you use normal windows, you'll have compatibility problems with
various window managers ignoring or misinterpreting your requests to
move and resize your panels. If you use popup windows, input won't
work (the window manager will never focus your panels). To get around
this in Chrome OS, we just wrote our own window manager that knows how
to handle our panels. :-P
You're probably not seeing any performance issues with move animations
since your client doesn't need to redraw its windows' contents for
each frame of animation. In the resize case, I think that there's a
round trip between your client and the X server for each frame (as you
might not redraw until you receive notification from the server that
the window has been resized). It's possible that GDK avoids this
delay for popup windows since it knows that its resize request will be
honored. Things will still look janky since resizing and redrawing
happen non-atomically, though.
I meant that in the case of making a panel resize from 100x100 to
400x400, you could resize the window once to 400x400 and paint the
contents within the 110x110 region while leaving the rest of the
window transparent, then within 120x120, and so on. The window's
alpha channel will only be honored if there's a compositor running,
but if you don't need partial transparency, you could use the shape
extension to mask out portions of the window without using RGBA
windows (using the shape extension may have worse performance in
compositing window managers, though). I don't know of any good
resources about RGBA windows in X. :-/
It's a bit off-topic, but what's your plan for the actual
implementation of this with regard to using normal vs. popup windows?
If you use normal windows, you'll have compatibility problems with
various window managers ignoring or misinterpreting your requests to
move and resize your panels. If you use popup windows, input won't
work (the window manager will never focus your panels). To get around
this in Chrome OS, we just wrote our own window manager that knows how
to handle our panels. :-P
Whether to redraw or not is up to the toolkit, as far as I'm aware.
It could maybe be avoided in some cases where the window is getting
smaller, assuming that its bit gravity is set correctly (see
http://tronche.com/gui/x/xlib/window/attributes/gravity.html).
If you only need to animate panels sliding down off the bottom of the
screen, you may also be able to just animate them moving offscreen
instead of resizing them.
[snip]
> minimize it. Looks like I have to solve one of two problems:
> 1) Make popup windows take keyboard focus or
> 2) Figure a way to convince the window manager to honor the size and
> position requests precisely.
> I don't think we'll be writing a new window manager for chrome on Linux :-)
> Looking at the documentation option 1) doesn't seem like a good idea as I
> might run into other problems(?). I'd appreciate any ideas/thoughts in this
> regard.
Yeah, 1) isn't a great choice. It's what the Linux version of Chrome
uses for infobubbles (such as the bookmark bubble) since we ran into
issues with some window managers when using normal windows with
_NET_WM_WINDOW_TYPE_UTILITY (the window manager isn't under any
obligation to honor move or resize requests), but there are problems
with various GTK widgets' behavior when the window grabs the focus
instead of getting it assigned by the window manager, and grabbing the
keyboard is user-unfriendly (window manager shortcuts like Alt-Tab
won't work, for instance).