The plan is to make plugin widgets children of the top-level window; in
the interregnum until Compositor is completed, that means children of
the widget for the root nsView for the root nsViewManager (in Firefox
there is usually one root nsViewManager for each document in a
<browser>). After each reflow or scroll we will recompute the desired
clip region for each plugin and apply it directly to the plugin's widget
using a platform-specific method.
This will be done by building a display list for the visible area of the
top-level window and examining it. Using display lists will avoid
duplicating clipping setup code and also allow us to exclude areas from
a plugin that are covered by opaque regular content. We can optimize
this by keeping a list of plugins and skipping this step if there are no
relevant plugins. We can also limit the display list construction to the
union of the plugin rects.
To actually clip the plugins, on Windows we'll use SetWindowRgn. On GTK
I plan to use gdk_window_shape_combine_region.
We can't reshape and move the plugin widget atomically, but we should
avoid the plugin widget ever sticking outside the clip area. One way is
to compute the intersection of the desired new clip area and the current
clip area with the plugin moved to its new position, clip the plugin to
that intersection before we move it, move it, then set the clip area to
the new area. I've done some experiments with a simple test program and
it works great on Windows.
Scrolling's a bit of a pain. We would like to be able to do a
blit-scroll and move and reshape plugins atomically. On Windows, the
best approach I know of is ScrollWindowEx on the top-level window with
SW_SCROLLCHILDREN, but that won't work until all child content widgets
are removed, because otherwise they'll be moved by the scroll when they
shouldn't. So on Windows we'd call SetWindowRgn on the plugins (passing
FALSE for the redraw flag) with the intersection of the old and new clip
areas, call ScrollWindowEx(SW_SCROLLCHILDREN), then call SetWindowRgn on
the plugins again with the new clip areas (with TRUE for the redraw
flag). In my test program this works well.
That approach requires removing all non-root content widgets, otherwise
they'd be incorectly scrolled by this method. If we don't use this
approach, and just manually move the widgets before or after calling
ScrollWindow, we get a dirty area behind the trailing edges of plugins.
We have to follow up by manually repainting these areas, and if that
repaint takes any significant time, we get a nasty effect where the
trailing edge of the plugin leaves rubbish behind temporarily. To avoid
that, we could create temporary backing store for the scrolled area,
paint into it all the areas that will be invalidated by the scroll
operation, including the areas behind trailing plugin edges (in the
"after scroll" state), then do our scroll stuff, then blit the invalid
areas from the backing store onto the screen and validate them so they
don't get painted again.
That's quite complex so I'd like to avoid doing it. But the
trailing-plugin-edge problem is significant enough that I wouldn't want
to take it as a regression on trunk. So for now I plan to keep all this
work off the trunk until all non-root content widgets are removed.
AFAIK GTK/X doesn't have anything equivalent to
ScrollWindowEx(SW_SCROLLCHILDREN); scrolling in X is generally rotten.
We have to call gdk_window_move_region to scroll the pixels and
gdk_window_move and gdk_window_shape_combine_region to move and shape
the plugins. We may end up needing temporary backing store for GTK in
the end. Or, we may consider using Jeff's composited plugin window patch.
Comments appreciated.
Rob
My current best thought is to add a couple of scriptable methods to the
native test plugin, say getScreenEdge(e) and getClipScreenEdge(n,e),
where e=0,1,2,3 to get left,top,right,bottom and n iterates over the
rectangles that make up a complex clip region. When n is greater than
the number of rectangles we'd throw an error. When Kinda lame but
simpler than exposing rectangle and rectangle list objects from the plugin.
There is a problem that on Mac we won't be setting precise clip regions,
only a bounds rectangle. I think the tests will just have to deal.
Rob