blob: c57218863f93da62cb9d250d729a3f247f508d97 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[DartPackage="mojo_services"]
module mojo.ui;
import "mojo/public/interfaces/application/service_provider.mojom";
import "mojo/services/gfx/composition/interfaces/scenes.mojom";
import "mojo/services/gfx/composition/interfaces/scheduling.mojom";
import "mojo/services/ui/views/interfaces/view_containers.mojom";
import "mojo/services/ui/views/interfaces/view_properties.mojom";
import "mojo/services/ui/views/interfaces/view_token.mojom";
// A view is a graphical user interface component which is responsible
// for drawing and supporting user interactions in the area of the screen
// that it occupies.
//
// A view may also act as a container for other views (known as the
// view's children) which it may freely layout and position anywhere
// within its bounds to form a composite user interface. The hierarchy
// of views thus formed is called a view tree.
//
// LIFECYCLE
//
// Use |ViewManager.CreateView()| to create a view. The application
// uses the |View| interface to manage the view's content and implements
// the |ViewListener| interface to handle events.
//
// To destroy a view, simply close the |View| message pipe.
//
// SCENES
//
// Each view must provide content for its main scene, created using the
// |View.CreateScene()| interface. To perform graphical composition of
// other components, the view's main scene may contain references to
// scenes belonging to child views or scenes created by other application
// components which interact with the compositor.
//
// See |mojo.gfx.compositor.Scene| for more information.
//
// ADDING CHILD VIEWS
//
// Use |GetContainer()| to obtain an interface for manipulating child views.
//
// See |mojo.ui.ViewContainer| for more information.
//
// INVALIDATION, LAYOUT, and DRAWING
//
// The invalidation mechanism coordinates layout and drawing of views.
//
// By layout, we mean generally operations which affect the content of a
// view in response to changes to the view's properties, such as its size,
// or changes to its internal state. Layout may also affect the list of
// child views or their properties.
//
// By drawing, we mean generally operations which affect the rendering of a
// view such as rasterizing content and publishing an updated scene.
//
// Views are free to implement layout and drawing however they like but
// view invalidation is the mechanism which should kick them off.
//
// Views receive invalidation events whenever their properties changes or
// on demand in response to a call to |Invalidate()|. Each invalidation
// event includes updated view properties needed for layout together with
// the frame scheduling information needed for drawing the next frame.
//
// To minimize the number of round-trip IPCs, invalidation events are coalesced
// and delivered to views at most once per frame. Views must process
// invalidation events promptly to maintain the responsiveness of the overall
// composed user interface.
//
// Where possible, invalidation events are delivered in parallel to all
// affected views except when invalidation of a parent view may affect
// the properties of its children. In that case, the invalidation is first
// delivered to the parent view which is allotted a small amount of time to
// apply and flush any changes to its children before they receive their
// own invalidation events. This brief pause for synchronization ensures
// efficient propagation of view property changes through the view hierarchy
// during a frame. If the parent is too slow, then the changes it applies
// to its children may not take effect until the next frame.
//
// For best performance, a view should take care to do as little work as
// possible to apply and flush changes to its children before proceeding
// with its own drawing. For example, if we consider a nominal 16.7 ms
// frame interval then spending 4 ms doing layout before flushing children
// means that the children will have 25% less time to do their own work
// for that frame and possibly to update their own children which may end
// up using old properties for that frame as a result.
//
// See |ViewListener.OnInvalidation()| for more information.
//
// GETTING SERVICES
//
// The view's |ServiceProvider| offers access to many services which
// are not directly expressed by the |View| interface itself, such
// as input, accessiblity, and editing capabilities.
//
// For example, perform the following actions to receive input events:
//
// 1. Call |GetServiceProvider()| to obtain the view's service provider.
//
// 2. Ask the service provider for its |mojo.ui.InputConnection|.
//
// 3. Set listeners on the input connection to receive events.
interface View {
// Gets the view's token.
GetToken() => (ViewToken token);
// Gets a service provider to access services which are associated with
// the view such as input, accessibility and editing capabilities.
// The view service provider is private to the view and should not be
// shared with anyone else.
//
// See |mojo.ui.InputConnection|.
GetServiceProvider(mojo.ServiceProvider& service_provider);
// Creates the view's scene, replacing any previous scene the view
// might have had.
//
// The |scene| is used to supply content for the scene. The scene pipe
// is private to the scene and should not be shared with anyone else.
//
// To destroy the scene, simply close the |scene| message pipe.
//
// See also: |mojo.gfx.composition.Compositor.CreateScene()|.
CreateScene(mojo.gfx.composition.Scene& scene);
// Gets an interface for managing the view's children.
GetContainer(ViewContainer& container);
// Invalidates the view, causing the |OnInvalidation| event to be delivered
// to the view's |ViewListener| when it is time to produce the next frame.
//
// This method should be called whenever the content of a view is changing
// (such as during animations). The view manager takes care of scheduling
// the next frame with the graphics subsystem and coordinating invalidations
// across views.
Invalidate();
};
// An interface clients may implement to receive events from a view.
interface ViewListener {
// Called when a view has been invalidated to provide it an opportunity
// to produce the next frame.
//
// Invalidation events are coalesced for efficiency. Certain intermediate
// invalidations may be dropped if the view is unable to keep up
// with them in a timely manner.
//
// While handling the event, the view should perform the following tasks:
//
// 1. Apply view property changes expressed in |ViewInvalidation.properties|.
//
// 2. Apply changes to the properties or structure of child views if needed.
//
// 3. If |ViewInvalidation.container_flush_token| is not zero, call
// |ViewContainer.FlushChildren()| to flush changes to the children
// and allow them to start handling their own invalidation events
// as soon as possible.
//
// 4. Update the content of the view and submit a |SceneUpdate| if needed.
// Make sure to set the |SceneMetadata|'s version number and presentation
// time based on the values provided in the |ViewInvalidation| structure.
//
// 5. Invoke the callback to let the view manager know that the view
// is ready to handle the next invalidation. This may be performed
// earlier in the pipeline as long as the view is keeping up with
// invalidation events (so they do not sit in the queue and become stale).
//
// Although this process is described sequentially, the view implementation
// is free to perform some of this work concurrently, such as rasterizing
// content and submitting scene updates on a dedicated thread. (hint)
//
// TODO(jeffbrown): The abstraction layers are getting in the way here.
// It would be nice to get rid of the need to flush children.
OnInvalidation(ViewInvalidation invalidation) => ();
};
// Provides updated information needed to produce a new frame of content.
//
// See |ViewListener.OnInvalidation()| for details.
struct ViewInvalidation {
// New view properties, or null if they have not changed since the last
// view invalidation.
ViewProperties? properties;
// A unique token to flush changes to children resulting from this
// view invalidation.
//
// This value must be passed to |ViewContainer.FlushChildren()|
// when non-zero.
//
// When the token is non-zero, delivery of invalidation events to child
// views is being temporarily deferred give this view a chance to update
// their properties.
//
// To maintain responsiveness of the overall composed user interface,
// it is important to flush children as quickly as possibly while handling
// the view invalidation. Make sure to do this before starting expensive
// tasks such as rasterization or publishing scene updates!
uint32 container_flush_token = 0; // no flush needed by default
// Specifies the version number which the view should use when publishing
// subsequent scene updates which incorporate the changes described by this
// view invalidation.
//
// This value must be copied into |SceneMetadata.version| before publishing.
uint32 scene_version = 0; // kSceneVersionNone
// Scheduling information for the frame to be drawn.
//
// The value of |frame_info.presentation_time| must be copied into
// |SceneMetadata.presentation_time| before publishing.
//
// See comments on |FrameInfo| on how to properly consume this structure.
mojo.gfx.composition.FrameInfo frame_info;
};