The hierarchy handling is handled in the shell by adding stuff
directly to the uiGroup, and we have a dedicated actor for
the overview there, so we don't need this anymore.
https://bugzilla.gnome.org/show_bug.cgi?id=700735
If _NET_WM_OPAQUE_REGION is set when the window is first mapped, the
initial load_properties will happen before the window actor is created,
and we'll have a call to meta_compositor_window_shape_changed. Just
fizzle this call out instead of doing anything fancy, as we'll pick
up the opaque region when the window actor is eventually created.
https://bugzilla.gnome.org/show_bug.cgi?id=695813
Window actors might be temporarily parented to intermediate actors during
effect, but we should not require that the plugin keeps track of stacking.
Rather, assume that the intermediate groups holds a whole stack, and
applying position within it.
https://bugzilla.gnome.org/show_bug.cgi?id=695711
When windows get redirected off screen, all that gets left behind
is black. We don't want to flicker black at startup, though.
This commit maps the overlay window early, before redirecting
toplevels, so they end up getting snapshotted onto the background
pixmap of the overlay window when the overlay window is mapped.
https://bugzilla.gnome.org/show_bug.cgi?id=694321
Commit 4f2bb583bf started to use a clutter_threads_add_repaint_func_full
callback instead of connecting to the stage's paint signal.
The callback has to return TRUE if it wants to be called again, so fix that
as we want to call it for every frame (otherwise apps supporting the WM SYNC
protocol will stop drawing).
https://bugzilla.gnome.org/show_bug.cgi?id=695006
Doing so causes useless full stage redraws and breaks culling
as clutter cannot know how the signal handler affects painting.
So use clutter_threads_add_repaint_func_full with the
CLUTTER_REPAINT_FLAGS_POST_PAINT flag instead.
https://bugzilla.gnome.org/show_bug.cgi?id=694988
Background handling in GNOME is very roundabout at the moment.
gnome-settings-daemon uses gnome-desktop to read the background from
disk into a screen-sized pixmap. It then sets the XID of that pixmap
on the _XROOTPMAP_ID root window property.
mutter puts that pixmap into a texture/actor which gnome-shell then
uses.
Having the gnome-settings-daemon detour from disk to screen means we
can't easily let the compositor handle transition effects when
switching backgrounds. Also, having the background actor be
per-screen instead of per-monitor means we may have oversized
textures in certain multihead setups.
This commit changes mutter to read backgrounds from disk itself, and
it changes backgrounds to be per-monitor.
This way background handling/compositing is left to the compositor.
https://bugzilla.gnome.org/show_bug.cgi?id=682427
We do, in fact, need freezing to affect window geometry, so that
move-resize operations (such as an interactive resize from the
left, or a resize of a popup centered by the application) occur
atomically.
So to make map effects work properly, only exclude the initial
placement of a window from freezing. (In the future, we may want
to consider whether pure moves of a window being done in response
to a user drag should also be excluded from freezing.)
Rename meta_window_sync_actor_position() to
meta_window_sync_actor_geometry() for clarity.
https://bugzilla.gnome.org/show_bug.cgi?id=693922
The WM spec requires _NET_WM_FRAME_DRAWN to *always* be sent when
there is an appropriate update to the sync counter value. We were
potentially missing _NET_WM_FRAME_DRAWN when an application did a
spontaneous update during an interactive resize and during effects.
Refactor the code to always send _NET_WM_FRAME_DRAWN, even when
a window is frozen.
https://bugzilla.gnome.org/show_bug.cgi?id=693833
Put override redirect windows such as menus into a separate window group
stacked above everything else. This will allow us to visually put these
above other compositior chrome.
Based on a patch from Muffin.
https://bugzilla.gnome.org/show_bug.cgi?id=633620
We previously had timestamp information stubbed out in
_NET_WM_FRAME_DRAWN. Instead of this, add a high-resolution timestamp
in _NET_WM_FRAME_DRAWN then send a _NET_WM_FRAME_TIMINGS message
after when we have complete frame timing information, representing
the "presentation time" of the frame as an offset from the timestamp
in _NET_WM_FRAME_DRAWN.
To provide maximum space in the messages,_NET_WM_FRAME_DRAWN and
_NET_WM_FRAME_TIMINGS are not done as WM_PROTOCOLS messages but
have their own message types.
https://bugzilla.gnome.org/show_bug.cgi?id=685463
Add a function to convert from g_get_monotonic_time() to a
"high-resolution server timestamp" with microsecond precision.
These timestamps will be used when communicating frame timing
information to the client.
https://bugzilla.gnome.org/show_bug.cgi?id=685463
Using a "sync delay" where we wait for 2 ms after the vblank before
starting to draw the next frame provides for much more predictable
latency for applications. An application can know that if it completes
a frame any time between 8ms before the vblank to the vblank,
it will reliably be drawn on the following vblank period, rather than
having an unpredictable latency depending on whether the compositor
is currently busy drawing a frame or not.
https://bugzilla.gnome.org/show_bug.cgi?id=685463
When the application provides the extended second counter for
_NET_WM_SYNC_REQUEST, send a client message with completion
information after the next redraw after each counter update
by the application.
https://bugzilla.gnome.org/show_bug.cgi?id=685463
Replace the unused meta_compositor_set_updates() with
a reversed-meaning meta_compositor_set_updates_frozen(), and use
it to implement freezing application window updates during
interactive resizing. This avoids drawing new areas of the window
with blank content before the application has a chance to repaint.
https://bugzilla.gnome.org/show_bug.cgi?id=685463
Some windows may already have event masks on them that we've selected
for, especially if we're using GTK+ windows. In particular, this fixes
window menus in the XI2 port.
https://bugzilla.gnome.org/show_bug.cgi?id=690581
In random places that are not grabs, we selected for events on
things like the root window, stage window, COW and more. Switch
these over to using the proper XI2 APIs.
https://bugzilla.gnome.org/show_bug.cgi?id=688779
Currently keybindings are blocked while the compositor holds a grab; if
we want a keybinding to be available anyway, we use captured ClutterEvents
to determine the KeyBindingAction the event would have triggered and
run our own handlers (ugh).
Instead, provide a hook to allow the compositor to filter out keybindings
before processing them normally, regardless of whether the compositor
holds a grab or not.
https://bugzilla.gnome.org/show_bug.cgi?id=688202
The "multiple plugins loaded at once" strategy was always a big fiction:
while it may be viable if you're super careful, it's fragile and requires
a bit of infrastructure that we would be better off without.
Note that for simplicity, we're keeping the MetaPluginManager, but it only
manages one plugin. A possible future cleanup would be to remove it entirely.
https://bugzilla.gnome.org/show_bug.cgi?id=676855
If we get two configure events on the root window in close
sequence, then we could get the sequence:
ConfigureNotify on the root window w1xh1
Processed by Mutter
clutter_actor_set_size(stage, w1, h1)
<relayout happens, stage window resized by clutter>
ConfigureNotify on the root window, w2xh2
Processed by Mutter
clutter_actor_set_size(stage, w2, h2)
ConfigureNotify on the stage window, w1, h1)
Processed by Clutter
clutter_actor_set_size(stage, w1, h1)
<relayout happens, stage window resized by clutter>
Leaving the stage at the wrong size. To avoid fighting with Clutter,
switch to resizing the stage with XResizeWindow(), similar to how a
toplevel window is handled by a window manager.
XFixesCreateRegionFromWindow does not take the window's position into account,
which results into setting a wrong shape for windows not located on the
leftmost monitor.
Fix that by creating the region from the window's MetaRectangle.
https://bugzilla.gnome.org/show_bug.cgi?id=657869
* Export meta_display_add_ignored_crossing_serial()
* Add the serial for reshaping the stage
* Increase the size of the "ignored_serials" array a bit to
try to avoid the possibility of losing serials from multiple
reshapes happening close together.
https://bugzilla.gnome.org/show_bug.cgi?id=597190
Some apps that do a lot of rendering on the screen like games, mostly run in
fullscreen where there is no need for them to be redirected doing so does add
an overhead; while performance is critical for those apps.
This can be disabled / enabled at runtime using
meta_enable_unredirect_for_screen / meta_disable_unredirect_for_screen
https://bugzilla.gnome.org/show_bug.cgi?id=597014
Instead of requiring a singleton MetaBackgroundActor for the screen,
allow creating multiple copies that internally share a single
CoglTexture behind the scenes. This will be useful for allowing
multiple views of the screen background with different rendering
options.
https://bugzilla.gnome.org/show_bug.cgi?id=656433
Since we're not setting the frame's output shape any more, it doesn't
make sense to calculate the output shape based on the frame window.
Instead, track the client window directly and calculate the output shape
based on that.
https://bugzilla.gnome.org/show_bug.cgi?id=644930
* When unmanaging a screen, stop redirecting subwindows explicitly,
so that we do that before destroying the window manager selection
window.
* Improve comment in the retry code
* When exiting because the previous compositor couldn't be replaced,
don't g_error() and drop a core file.
https://bugzilla.gnome.org/show_bug.cgi?id=653121
If mutter is going to be a "real" library, then it should install its
includes so that users can do
#include <meta/display.h>
rather than
#include <display.h>
So rename the includedir accordingly, move src/include to src/meta,
and fix up all internal references.
There were a handful of header files in src/include that were not
installed; this appears to have been part of a plan to keep core/,
ui/, and compositor/ from looking at each others' private includes,
but that wasn't really working anyway. So move all non-installed
headers back into core/ or ui/.
https://bugzilla.gnome.org/show_bug.cgi?id=643959
Revert the early_initialize changes (which get in the way in the
"libmutter-wm" paradigm), remove the GConf key for setting plugins,
and remove plugin "params", which weren't being used. Also remove all
the logic for unloading and reloading plugins, since the list never
changes after startup now.
https://bugzilla.gnome.org/show_bug.cgi?id=643959
A logic bug was resulting in the bottom hidden window (hidden means means
minimized or on a different workspace) continually being stacked above
the other hidden windows.
https://bugzilla.gnome.org/show_bug.cgi?id=640679
If we have repeats on for a full-sized image, then if the background
is displayed scaled (for example, in a desktop preview mode) then we
can get artifacts along the edge of the background where the repeat
of the opposite edge is blended in by bilinear scaling. So turn off
repeats when the screen and background image sizes match.
https://bugzilla.gnome.org/show_bug.cgi?id=634833
Add code to track and draw the root window background. The advantage of doing
it here as compared to in a plugin is that we can use the visiblity smarts
of MetaWindowGroup to optimize out drawing the background when obscured.
If handling other than tracking the _XROOTPMAP_ID property is desired in the
future, more functionality like setting the background from a file or doing
cross-fades can be added.
The new background actor is exposed to plugins via meta_plugin_get_background_actor()
similar to other exposed actors to allow cloning the background for use in
other displays. The actual class is not installed for public consumption at
the moment since it has no useful methods.
https://bugzilla.gnome.org/show_bug.cgi?id=634833
For various reasons (mostly the stack tracker correctly predicting the
stacking order before getting events, but also because of the processing
that the compositor does to get the actor stacking order) the compositor
can be told to sync the stack when it has nothing to do. Detect this
at the last moment before actually telling Clutter to restack to avoid
triggering unnecessary redraws.
https://bugzilla.gnome.org/show_bug.cgi?id=634771
Instead of setting shadow parameters on individual windows, add the
idea of a "shadow class". Windows have default shadow classes based
on their frame and window type, which can be overriden by setting
the shadow-class property.
Each shadow class has separably configurable parameters for the
focused and unfocused state. New shadow classes can be defined with
arbitrary names.
https://bugzilla.gnome.org/show_bug.cgi?id=592382
While the Meego developers agreed to switching mutter to GTK+-3.0
unconditionally a while ago, Canonical used a GTK+-2.0 build for their
Unity project. As Canonical now announced a switch to compiz as their
window manager, there is no longer a reason to maintain GTK+-2.0
compatibility.
https://bugzilla.gnome.org/show_bug.cgi?id=633133
Move all objects and functions namespaced with Mutter into the Meta namespace
to get a single consistent namespace. Changes that aren't simply changing mutter
to meta:
MutterWindow => MetaWindowActor
mutter_get_windows => meta_get_window_actors
mutter_plugin_get_windows => meta_plugin_get_window_actors
https://bugzilla.gnome.org/show_bug.cgi?id=628520
Currently mutter-window has its own type field, even though the same
information is already present in meta_window.
And while at it get rid of MetaCompWindowType, it is equally redundant.
https://bugzilla.gnome.org/show_bug.cgi?id=630363
Cleanly build with --warn-fatal. Implementation:
* Liberally apply (skip) where the API is clearly C only, e.g. uses
XLib. The theming code and MutterPlugin are skipped too.
* Add missing (transfer) and (element-type) annotations
For a few functions that had a comment, I turned it into gtk-doc, but
I didn't (with a few exceptions) try to write new documentation in
this pass.
The current effect API passes an unnecessary list of windows to
switch_workspace() and forces a window to be passed in when killing
the switch_workspace() effect.
We can simplify the interface to correspond more closely to how
it is actually used and fix these problems:
Remove the actors parameter to plugin->switch_workspace
Remove the events parameter to plugin->kill_effect and rename it to kill_window_effects
Add plugin->kill_switch_workspace
Remove mutter_plugin_manager_kill_effect
Add mutter_plugin_manager_kill_window_effects
Add mutter_plugin_manager_kill_switch_workspace
Remove mutter_plugin_effect_completed
Add mutter_plugin_[minimize/map/destroy/maximize/unmaximize]_completed
https://bugzilla.gnome.org/show_bug.cgi?id=621082
Although multi-screen support has not been tested and probably
doesn't fully work, the basic setup for multi-screen is that
we have the same list of plugins for all screens, but a different
instance of the plugins for each screen.
To allow plugins to do setup that is screen independent and needs
to occur early in the setup process, we identify a "default plugin
manager" and load (but not start) that plugin manager's plugins
immediately after we know our list of plugins.
That plugin manager is then reused for the first screen we open
and the plugins are started at that time. Separate plugin managers
are loaded and started for any other screens we open.
(A plugin could keep track of whether the screen-independent
setup has been done in a static variable, or it could do everything
in a way that is safe to do repeatedly.)
https://bugzilla.gnome.org/show_bug.cgi?id=615586
Since all windows are now MetaWindows as well as compositor
windows, there's no reason to keep a compositor-specific hash table
mapping from XID to MutterWindow.
This reduces complexity and removes a call to XQueryTree that could
potentially produce a BadWindow error if not error-trapped.
https://bugzilla.gnome.org/show_bug.cgi?id=613398
meta_compositor_process_event uses meta_error_trap_push/pop for
every event processed by meta_compositor_process_event which isn't needed
and can cause performance problems.
https://bugzilla.gnome.org/show_bug.cgi?id=613398
The return value of XGrabKeyboard() wasn't actually being assigned
to the 'result' variable so we didn't notice when grabbing the
keyboard failed.
https://bugzilla.gnome.org/show_bug.cgi?id=596343
mutter_plugin_begin_modal() and mutter_plugin_begin_modal() allow putting
a plugin into a "modal" state. This means:
- The plugin has the keyboard and mouse grabbed
- All keyboard and mouse events go exclusively to the plugin
mutter-plugin.[ch]: Add public API
compositor.c compositor-private.h: Implement the API
mutter-plugin-manager.c: When reloading plugins, make sure none of them
are modal at that moment, and if so force-unmodal them.
common.h: Add META_GRAB_OP_COMPOSITOR
display: When display->grab_op is META_GRAB_OP_COMPOSITOR forward relevant
events exclusively to the compositor.
http://bugzilla.gnome.org/show_bug.cgi?id=590754
When we are painting a stack of 5-10 maximized windows, the
standard bottom-to-top method of drawing every actor results
in a tremendous amount of overdraw and can easily max out
the available memory bandwidth on a low-end* graphics chipset.
It's even worse if window textures are being accessed over
the AGP bus.
When we have opaque windows, we can go ahead and compute visibility
ourselves (in classic X-server fashion) and use that information to
restrict drawing obscured actors.
* Add MutterWindowGroup - a ClutterGroup subclass with logic
for figuring out obscured regions.
* Add mutter_window_get_obscured_region() to get the region
obscured by that window.
* Add mutter_shaped_texture_set_clip_region() to hint
a clip region to the painting code; this is set based on
the computed visible region of MutterWindowGroup.
* Add tidy_texture_frame_set_needs_paint() to hint that the
paint can be skipped entirely; this is used when we detect
that the window shadow is entirely obscured.
http://bugzilla.gnome.org/show_bug.cgi?id=587344
If we are starting on something other than the first workspace,
meta_compositor_switch_workspace() will be called before
meta_compositor_manage_screen(); guard against that.
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
Clean up mutter_window_effect_in_progress() by removing the
include_destroy parameter which was used only in one place that
could be easily done otherwise. (There was another use in
mutter_window_sync_actor_position() that had no point and looked
unintended.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
Add a paint function that checks all windows for repair and
shape updates; this:
- simplifies the logic for when a window needs to be repaired
- avoids duplicate work when we get multiple damage effects
- avoids the need to look ahead in the event queue
Instead of relying on repair to implicitly resize the
MutterWindow actor, set the size explicitly when the core
code updates the geometry. (This is needed because we haven't
repaired yet when we start an animation, and the animation
may depend on the size to, e.g., rescale from the center.)
Because the core geometry update happens before we start
maximize/unmaximize effects we need to work around this by
passing both the old and new geometry to the compositor.
http://bugzilla.gnome.org/show_bug.cgi?id=587251
compositor.c: Move MutterWindow code to mutter-window.c;
rename map_win() to mutter_window_map(), etc.
mutter-window-private.h: New private header file for
MutterWindow functions used internally to the compositor.
compositor-mutter.h: Move MutterWindow declarations to
mutter-window.h; move a couple of private functions to
compositor-private.h
compositor-private.h: Move MetaCompScreen declaration to here:
Conceptually it's private to compositor.c, but MutterWindow
manipulates some of the lists directly for now.
mutter-plugin.c compositor.c: Don't call mutter_window_effect_completed()
for MUTTER_PLUGIN_SWITCH_WORKSPACE, but use a new
mutter_switch_workspace_completed(), since the window is
just used to identify a screen.
http://bugzilla.gnome.org/show_bug.cgi?id=587251
Separate code related to creating the gaussian-blurred shadow texture
into a separate file.
Move the definition of MetaCompositor into a compositor-private.h
so that the shadow code can cache the source in the compositor
structure.
http://bugzilla.gnome.org/show_bug.cgi?id=587251
Remove a number of functions that were either entirely unimplemented
or had empty implementations for the Clutter-compositor.
meta_compositor_begin_move()
meta_compositor_update_move()
meta_compositor_end_move()
meta_compositor_set_active_window()
meta_compositor_free_window()
http://bugzilla.gnome.org/show_bug.cgi?id=581813
Now that we only have one compositor, there's no reason to access the
compositor functions through a vtable. Remove the MetaCompositor virtualization
and make the clutter code implement the meta_compositor_* functions
directly.
Move the checks for the compositor being NULL from the vtable wrappers
to the calling code (most of them were already there, so just a few
needed to be added)
Note: the compositor is actually hard-coded on at the moment and the plan
is to remove the non-composited code entirely, so the checks are
added only to keep things neat: they have no practical effect.
http://bugzilla.gnome.org/show_bug.cgi?id=581813
Mutter is a Clutter-based compositing manager. So, remove the code for
the XRender-based compositor, and make it mandatory to have XComposite,
XRender and Clutter.
Run-time support for non-composited operation is left for now.
* src/compositor/mutter/: Move files from this subdirectory into
the main compositor/ directory.
* compositor/compositor-xrender.ccompositor/compositor-xrender.h:
Remove
* include/compositor-clutter.h: Remove this stray file, it had been
replaced with compositor-mutter.h some time back.
http://bugzilla.gnome.org/show_bug.cgi?id=581813
Fix a problem where GTK+ was warning
'gdk_window_set_user_time called on non-toplevel' for every button
press and click on the mutter stage by excluding such events from
GTK+ processing.
Add a boolean return value to meta_compositor_process_event that
indicates whether the event has been handled and should be filtered
out of the event stream and for mutter, base that on the return
value of the plugin's xevent_filter vfunc.
The metacity core is now directly aware of override redirect windows.
- They get MetaWindows like normal windows, so mutter no longer need to special
case them. The net wm types applicable to override redirects are also
recognised.
- The original positioning/stacking semantics of metacity with respect to OR
windows are maintained, but now it's easier to synchronize the stacking
between the core and mutter.
- mutter no longer needs to manualy track UnmapNotify, MapNotify,
ReparentNotify, CreateNotify and DestroyNotify events; instead map, unmap,
add and remove events can now be consistently delivered via the
MetaCompositor callbacks.
We can't easily use a metacity layer to hide windows as that means we
loose our original stacking position. (Metacity's stack positions are
only valid within a single layer) We now have a "guard window" per
screen that is a fullscreen override redirect that is lowered to the
bottom of the stack. Hidden windows now remain in their original layer
so the stacking position remains valid, but all hidden windows get
XRestacked under the guard window.
A new compositor hook is also added to inform it when a window becomes
hidden/unhidded, this lets us map/unmap the corresponding actor.
missing files in preview commit (TODO: rebase -i and squash this later)
ClutterActors for hidden windows (such windows on different than active
workspaces and windows that are minimized) are available, and reflect the
actual state of the window. This is intended for use in task-switchers etc.
This feature is disabled by default (due to increased demand on resources),
and can be enabled through the metacity/general/live_hidden_windows gconf key.
A trivial sample window switcher is included in the scratch plugin (activated
by clicking on the slide out panel).
Fixed up the build files so we do not build xrender compositor when building
clutter backend; moved clutter initialization to meta_ui_init() so commandline
arguments can be passed into clutter_init().
2008-05-24 Iain Holmes <iain@gnome.org>
* src/compositor/compositor.c: Check the compositor isn't NULL
before
dereferencing it. Fixes#534569
(meta_compositor_get_window_pixmap): Actually return a value
svn path=/trunk/; revision=3723
2008-05-19 Iain Holmes <iain@gnome.org>
* src/include/frame.h
* src/include/display.h
* src/include/xprops.h
* src/include/compositor.h
* src/include/types.h
* src/include/window.h
* src/include/errors.h
* src/include/screen.h: New basic public API for compositor.
* src/compositor/*: Separate the compositor out into its own
separate
directory and set it up for backends. Initial XRender backend.
* src/core/compositor.[ch]: Remove
* src/core/frame.h
* src/core/screen.h
* src/core/display.h
* src/core/window.h: Rename to -private.h so as not to clash
with the
new files in include
* src/core/delete.c
* src/core/workspace.h
* src/core/stack.[ch]
* src/core/keybindings.[ch]
* src/core/errors.c
* src/core/effects.[ch]
* src/core/core.c
* src/core/group.h
* src/core/edge-resistance.[ch]
* src/core/window-props.[ch]
* src/core/constraints.h
* src/core/bell.[ch]
* src/core/iconcache.h
* src/core/session.[ch]
* src/core/main.c
* src/core/place.h
* src/core/xprops.c
* src/ui/tabpopup.c: Use the new -private headers
* src/core/display.c
* src/core/frame.c
* src/core/window.c
* src/core/screen.c: Add the API functions required by the
compositor
* src/Makefile.am: Relocate the new files
svn path=/trunk/; revision=3715