| // 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; |
| }; |