// Copyright 2014 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. module ui.mojom; import "mojo/public/mojom/base/unguessable_token.mojom"; import "services/ui/public/interfaces/cursor/cursor.mojom"; import "services/ui/public/interfaces/screen_provider_observer.mojom"; import "services/ui/public/interfaces/window_manager_constants.mojom"; import "services/ui/public/interfaces/window_tree_constants.mojom"; import "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom"; import "services/viz/public/interfaces/compositing/frame_sink_id.mojom"; import "services/viz/public/interfaces/compositing/local_surface_id.mojom"; import "services/viz/public/interfaces/compositing/surface_info.mojom"; import "ui/base/mojo/ui_base_types.mojom"; import "ui/events/mojo/event.mojom"; import "ui/events/mojo/event_constants.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; import "ui/gfx/image/mojo/image.mojom"; import "ui/gfx/mojo/transform.mojom"; import "ui/platform_window/mojo/text_input_state.mojom"; // Windows are identified by a uint64. The upper 32 bits are the id assigned to // the client by the Window Service, and the lower 32 an id assigned by the // client. Windows created by the client supply a client id of 0, which the // Window Service maps appropriately. For clients that see Windows created by // another client, the upper 32 bits are set to identify the other client. // // The root window is identified with a connection id of 0, and value of 1. // // Most functions to the WindowTree take a change_id parameter. When // WindowTree completes processing of a function WindowTree calls // WindowTreeClient::OnChangeCompleted() with the change_id supplied by the // client and the result of the function. This allows the client to track // whether the call succeeded or not. Calls are done via the client interface // rather than a callback to ensure ordering. The server does not interpret the // change id in anyway, it is up to the client to assign a value and use it. // Generally the change id is an ever increasing integer. // // Event processing happens in the following order: // . The event is sent to the accelerator registered for the PRE_TARGET. If // the client consumes the event, matching pointer watchers are notified and // processing stops. If the client does not consume the event processing // continues. // . Target window (lookup of the target window depends upon the event type) and // matching pointer watchers are notified at the same time. The target is only // notified once, even if it has a matching pointer watcher registered. If the // target consumes the event, processing stops. // . Accelerator registered for POST_TARGET. No response is expected from the // client for the POST_TARGET and processing of the next continues // immediately. interface WindowTree { // Creates a new window with the specified id. It is up to the client to // ensure the id is unique to the connection (the id need not be globally // unique). Additionally the connection id (embedded in |window_id|) must // match that of the connection. // Errors: // ERROR_CODE_VALUE_IN_USE: a window already exists with the specified id. // ERROR_CODE_ILLEGAL_ARGUMENT: The connection part of |window_id| does not // match the connection id of the client. NewWindow(uint32 change_id, uint64 window_id, map>? properties); // Requests the WindowManager to create a new top level window. On success // OnTopLevelCreated() is called with the WindowData for the new window. On // failure OnChangeCompleted() is called. // TODO(sky): this likely needs context, maybe in |properties|. NewTopLevelWindow(uint32 change_id, uint64 window_id, map> properties); // Deletes a window. This does not recurse. No hierarchy change notifications // are sent as a result of this. Only the connection that created the window // can delete it. DeleteWindow() may also be used to remove a window as an // embed root from the client. When DeleteWindow() is used to remove an embed // root, the client no longer has access to the embed root. The embedder of // the root is notified of the change via OnEmbeddedAppDisconnected(). DeleteWindow(uint32 change_id, uint64 window_id); // Requests input event capture for the given |window_id|. Capture is only // allowed if the window is processing an event. When a window gains capture, // current input events are canceled. The given window will receive all // subsequent input until an alternate window is set via SetCapture, or // ReleaseCapture is called for |window_id|. OnCaptureChanged() is called to // notify of capture changing (as long as the client did not initiate the // change). SetCapture(uint32 change_id, uint64 window_id); // Releases input event capture for the given |window_id|. This does nothing // if |window_id| does not currently have capture. ReleaseCapture(uint32 change_id, uint64 window_id); // Starts the pointer watcher that monitors pointer events (up/down events if // |wants_moves| is false, up/down and move if |wants_moves| is true), even if // they are not targeted at a window in this tree. For pointer events that // would normally be sent to the requesting client (if the event target is // this window tree) OnWindowInputEvent() is called, all other matching // pointer events (if the target is another tree) result in // OnPointerEventObserved(). There is only ever one pointer watcher active at // a given time. The client should prefer |want_moves| to be false, as there's // a system-wide performance/battery penalty for listening to moves. // // See class description for details on event delivery. StartPointerWatcher(bool want_moves); // Stops the pointer watcher for all events. StopPointerWatcher(); // Sets the specified bounds of the specified window. The window will paint // the frame in the provided |local_frame_id|, if any. SetWindowBounds(uint32 change_id, uint64 window_id, gfx.mojom.Rect bounds, viz.mojom.LocalSurfaceId? local_surface_id); SetWindowTransform(uint32 change_id, uint64 window_id, gfx.mojom.Transform transform); // Sets the client area of the specified window. The client area is specified // by way of insets. Everything outside of the insets, and not in // |additional_client_areas| is considered non-client area. // TODO(sky): convert additional_client_areas to a path. SetClientArea(uint64 window_id, gfx.mojom.Insets insets, array? additional_client_areas); // Mouse events outside a hit test mask do not hit the window. The |mask| is // in window local coordinates. Pass null to clear the mask. // TODO(jamescook): Convert |mask| to a path. http://crbug.com/613210 SetHitTestMask(uint64 window_id, gfx.mojom.Rect? mask); // Called by clients that want to accept drag and drops. Windows default to // this being disabled; a window must actively opt-in to receiving OnDrag*() // calls. SetCanAcceptDrops(uint64 window_id, bool accepts_drops); // Sets the visibility of the specified window to |visible|. Connections are // allowed to change the visibility of any window they have created, as well // as any of their roots. SetWindowVisibility(uint32 change_id, uint64 window_id, bool visible); // Sets an individual named property. Setting an individual property to null // deletes the property. SetWindowProperty(uint32 change_id, uint64 window_id, string name, array? value); // Sets the opacity of the specified window to |opacity|. SetWindowOpacity(uint32 change_id, uint64 window_id, float opacity); // Attaches a CompositorFrameSink to a particular window. AttachCompositorFrameSink( uint64 window_id, viz.mojom.CompositorFrameSink& compositor_frame_sink, viz.mojom.CompositorFrameSinkClient client); // Reparents a window. // This fails for any of the following reasons: // . |parent| or |child| does not identify a valid window. // . |child| is an ancestor of |parent|. // . |child| is already a child of |parent|. // // This may result in a connection getting OnWindowDeleted(). See // RemoveWindowFromParent for details. AddWindow(uint32 change_id, uint64 parent, uint64 child); // Removes a window from its current parent. This fails if the window is not // valid or the window already has no parent. // // Removing a window from a parent may result in OnWindowDeleted() being sent // to other connections. For example, connection A has windows 1 and 2, with 2 // a child of 1. Connection B has a root 1. If 2 is removed from 1 then B gets // OnWindowDeleted(). This is done as window 2 is effectively no longer // visible to connection B. RemoveWindowFromParent(uint32 change_id, uint64 window_id); // Ties the lifetime of |transient_window_id| to the lifetime of |window_id|. // This also places |transient_window_id| on top of |window_id|. // This fails for any of the following reasons: // . |window_id| or |transient_window_id| does not identify a valid window. // . |transient_window_id| is an ancestor of |window_id|. // . |transient_window_id| is modal to system. AddTransientWindow(uint32 change_id, uint64 window_id, uint64 transient_window_id); // Decouples the lifetime of |transient_window_id| from its transient parent. // This does not change transient window's position in the window hierarchy. RemoveTransientWindowFromParent(uint32 change_id, uint64 transient_window_id); // Changes modality type of |window_id|. This releases capture if necessary. // This fails for any of the following reasons: // . |window_id| does not identify a valid window. // . Client does not have a valid user id (i.e., it is an embedded app). SetModalType(uint32 change_id, uint64 window_id, ModalType type); // Sets the modal parent of a CHILD_MODAL window. This is the modal parent of // the window, which is not necessarily the same as the parent of the window. SetChildModalParent(uint32 change_id, uint64 window_id, uint64 parent_window_id); // Reorders a window in its parent, relative to |relative_window_id| according // to |direction|. Only the connection that created the window's parent can // reorder its children. ReorderWindow(uint32 change_id, uint64 window_id, uint64 relative_window_id, OrderDirection direction); // Returns the windows comprising the tree starting at |window_id|. // |window_id| is the first result in the return value, unless |window_id| is // invalid, in which case an empty vector is returned. The windows are visited // using a depth first search (pre-order). GetWindowTree(uint64 window_id) => (array windows); // A connection may grant access to another connection by way of Embed(). // Embed() results in the supplied WindowTreeClient being configured with a // root window of |window_id|. The supplied WindowTreeClient may create child // windows and do other various tree operations (including Embed()), but does // not see nor have access to any of the windows above the embed point. // // The caller must have created |window_id|. If not the request fails and the // response is false. // // The embedder can dictate the behaviour of the embedded client by setting // the appropriate embed flags (e.g. kEmbedFlagEmbedderInterceptsEvents). // // When a connection embeds a WindowTreeClient the originating connection no // longer has privileges to access or see any of the children of the window. // If the window had existing children the children are removed. The // WindowManager gets to see the whole tree. // // A window may only have one embedding in it at a time. Subsequent calls to // Embed() for the same window result in the currently embedded // WindowTreeClient being removed. The embedded app is told this by way of // OnUnembed(), which is followed by OnWindowDeleted() (as the connection no // longer has access to the window). // // The embedder can detect when the embedded app disconnects by way of // OnEmbeddedAppDisconnected(). // // The callback returns whether the embedding was successful. Embed(uint64 window_id, WindowTreeClient client, uint32 embed_flags) => (bool success); // Schedules a future call to Embed() using the returned token. This is used // when two clients need to work together to complete an embedding without // passing the WindowTreeClient between the two. This ensures a client isn't // able to spoof another client (say by directly passing events to the // client). // // For example, client A embeds client B in a window. Client A wants client B // to embed a WindowTreeClient in a window created by client B. This can be // accomplished by client A calling ScheduleEmbed() and then passing the // token returned from ScheduleEmbed() to client B (using a separate pipe) so // that client B may call EmbedUsingToken(). ScheduleEmbed(WindowTreeClient client) => (mojo_base.mojom.UnguessableToken token); // Creates an UnguessableToken for use in a future call, by another client, to // EmbedUsingToken(). // // The following example shows how to use this api. Client A wants client B // to embed it in a window created by client B. // 1. Client A calls ScheduleEmbedForExistingClient() to get a token. // 2. Client A passes the token to client B. This communication is done using // an additional channel, outside of WindowTree/WindowTreeClient. // 3. Client B calls EmbedUsingToken(). // 4. Client A receives OnEmbedFromToken() with the token from step 1. // // |window_id| is the id used for the window once EmbedUsingToken() is called. // More specifically, when OnEmbedFromToken() is called |window_id| is the id // of the window identified in the WindowData. ScheduleEmbedForExistingClient(uint32 window_id) => ( mojo_base.mojom.UnguessableToken token); // Pair with ScheduleEmbed() or ScheduleEmbedForExistingClient() to complete // an embedding, see them for details. EmbedUsingToken(uint64 window_id, mojo_base.mojom.UnguessableToken token, uint32 embed_flags) => (bool success); // Sets focus to the specified window, use 0 to clear focus. For a window to // get focus the following has to happen: the window is drawn, the window has // been marked as focusable (see SetCanFocus()) and the window is in a // container the WindowManager has identified as allowing activation // (see WindowManagerClient::AddActivationParent()). SetFocus(uint32 change_id, uint64 window_id); // Marks the specified window as being able to receive focus. SetCanFocus(uint64 window_id, bool can_focus); // Sets the cursor when the pointer is inside |window_id|. SetCursor(uint32 change_id, uint64 window_id, CursorData cursor); // Set text input state for the given window. SetWindowTextInputState(uint64 window_id, TextInputState state); // Set the input method editor UI (software keyboard, etc) visibility. // If state is non-null, the specified window's text input state is updated. // Otherwise the existing state is used. SetImeVisibility(uint64 window_id, bool visible, TextInputState? state); // Sets the EventTargetingPolicy. See EventTargetingPolicy for details. SetEventTargetingPolicy(uint64 window_id, EventTargetingPolicy policy); // See documentation for WindowTreeClient::OnWindowInputEvent(). OnWindowInputEventAck(uint32 event_id, EventResult result); // If the current focus is (or is a child of) |window_id|, requests that the // window manager change the focus to the next activatable window. DeactivateWindow(uint64 window_id); // Stacks the window |above_id| above |below_id|. These two windows must // share the same parent. This function is intended for use with top-levels // only. For non-top-levels, use ReorderWindow(). // TODO(sky): unify this and ReorderWindow(). https://crbug.com/850133. StackAbove(uint32 change_id, uint64 above_id, uint64 below_id); // Stacks the window above all sibling windows. StackAtTop(uint32 change_id, uint64 window_id); // Tells the window manager to perform |string_action| for |window_id|. PerformWmAction(uint64 window_id, string action); // Returns a shared memory segment that contains two 16-bit ints packed into a // single Atomic32, which represent the current location of the mouse cursor // where the location is (x << 16) | y. GetCursorLocationMemory() => (handle cursor_buffer); // Tells the window manager to start moving the window. OnChangeCompleted is // called on whether the move was canceled. Because there's a delay between // when a client sends this message and when the window manager starts acting // on it, pass the cursor location at the start of the move. PerformWindowMove(uint32 change_id, uint64 window_id, MoveLoopSource source, gfx.mojom.Point cursor); // Tells the window manager to cancel any in progress window move started with // StartWindowMove() and to revert the window bounds to how they were. CancelWindowMove(uint64 window_id); // Called by the client to start a drag operation. |source_window_id| is the // source window, |screen_location| is what the source thinks their location // of the pointer which started the drag is, |drag_data| is the entire set of // mime to raw data mapping. |drag_image| and |drag_image_offset| describe // an image to hold behind the cursor which represents the data on the // clipboard. We send this during the start of the drag because most views // clients will try to read all this data on first entry. PerformDragDrop(uint32 change_id, uint64 source_window_id, gfx.mojom.Point screen_location, map> drag_data, gfx.mojom.ImageSkia? drag_image, gfx.mojom.Vector2d drag_image_offset, uint32 drag_operation, PointerKind source); // Called by the client to cancel any in progress drag drop operation. This // will result in a change completed for the underlying change. CancelDragDrop(uint64 window_id); // Called by the client to start a session of observing the topmost window // under the cursor or touch point. Once called, OnTopmostWindowChanged() is // called on the client whenever the topmost window changes. |source| // specifies what type of located events should be observed (mouse or touch), // and |window_id| specifies the initial target of the located event. ObserveTopmostWindow(MoveLoopSource source, uint64 window_id); // Called by the client to request stopping the ongoing session of observing // the topmost window under the cursor. StopObservingTopmostWindow(); }; // Changes to windows are not sent to the connection that originated the // change. For example, if connection 1 changes the bounds of a window by // calling SetWindowBounds(), connection 1 does not receive // OnWindowBoundsChanged(). interface WindowTreeClient { // Invoked when the client application has been embedded at |root|. // See Embed() on WindowTree for more details. |tree| will be a handle back to // the window manager service, unless the connection is to the root connection // in which case it will be null. |parent_drawn| is true if roots parent is // drawn, see OnParentDrawnStateChanged() for details. |display_id| identifies // the display this root window is on. If the embedded window has a size, // |local_surface_id| identifies the ID to use to submit CompositorFrames. OnEmbed(WindowData root, WindowTree? tree, int64 display_id, uint64 focused_window, bool parent_drawn, viz.mojom.LocalSurfaceId? local_surface_id); // See description in ScheduleEmbedForExistingClient() for details on this. // Supplied arguments match that of OnEmbed(). OnEmbedFromToken(mojo_base.mojom.UnguessableToken token, WindowData root, int64 display_id, viz.mojom.LocalSurfaceId? local_surface_id); // Invoked when the application embedded at |window| is disconnected. In other // words the embedded app closes the connection to the server. This is called // on the connection that created |window| as well as any ancestors that have // the embed root policy. OnEmbeddedAppDisconnected(uint64 window); // Sent when another connection is embedded in the Window this connection was // previously embedded in. See Embed() for more information. OnUnembed(uint64 window); // Sent when capture changes. This is not sent if the client initiated the // change. OnCaptureChanged(uint64 new_capture, uint64 old_capture); // This is called on the client that initiated a call to Embed(), and informs // the owner (embedder) of the new FrameSinkId of the window (embedding // results in changing the FrameSinkId). OnFrameSinkIdAllocated(uint64 window, viz.mojom.FrameSinkId frame_sink_id); // Called in response to NewTopLevelWindow() successfully completing. // |parent_drawn| is true if the parent of the window is drawn, see // OnDrawnStateChanged() for details. |display_id| identifies the display this // window is on. If the top level window has a size, |local_surface_id| // identifies the ID to use to submit CompositorFrames. OnTopLevelCreated(uint32 change_id, WindowData data, int64 display_id, bool parent_drawn, viz.mojom.LocalSurfaceId? local_surface_id); // Invoked when a window's bounds have changed. Only the client embedded in // |window| gets a non_empty |local_surface_id|. OnWindowBoundsChanged(uint64 window, gfx.mojom.Rect old_bounds, gfx.mojom.Rect new_bounds, viz.mojom.LocalSurfaceId? local_surface_id); OnWindowTransformChanged(uint64 window, gfx.mojom.Transform old_transform, gfx.mojom.Transform new_transform); OnTransientWindowAdded(uint64 window_id, uint64 transient_window_id); OnTransientWindowRemoved(uint64 window_id, uint64 transient_window_id); // Invoked when a change is done to the hierarchy. A value of 0 is used to // identify a null window. For example, if the old_parent is NULL, 0 is // supplied. // If |window| was not visible to this client, but is visible now because // |new_parent| is visible to this client, then |windows| contains details // about |window|, and all its descendants. |windows| includes any windows // the client may already know about, but did not know the parent because // the parent was previously not visible to this client. // This is not sent for hierarchy changes of windows not known to this client // or not attached to the tree. OnWindowHierarchyChanged(uint64 window, uint64 old_parent, uint64 new_parent, array windows); // Invoked when the order of windows within a parent changes. OnWindowReordered(uint64 window_id, uint64 relative_window_id, OrderDirection direction); // Invoked when a window is deleted. OnWindowDeleted(uint64 window); // Invoked when the visibility of the specified window changes. OnWindowVisibilityChanged(uint64 window, bool visible); // Invoked when the opacity of the specified window has changed. OnWindowOpacityChanged(uint64 window, float old_opacity, float new_opacity); // Invoked when the drawn state of |window|'s parent changes. The drawn state // is determined by the visibility of a Window and the Windows ancestors. A // Window is drawn if all ancestors are visible, not drawn if any ancestor is // hidden. // // The initial drawn state is communicated by way of OnTopLevelCreated() or // OnEmbed(). // // This function is only called for root Windows as the drawn state of all // other windows can be determined from their parent. OnWindowParentDrawnStateChanged(uint64 window, bool drawn); // Invoked when a window property is changed. If this change is a removal, // |new_data| is null. OnWindowSharedPropertyChanged(uint64 window, string name, array? new_data); // Invoked when an event is targeted at the specified window. The client must // call WindowTree::OnWindowInputEventAck() with the same |event_id| to notify // that the event has been processed, and with an EventResult value to notify // if the event was consumed. |matches_pointer_watcher| is true if the client // has called StartPointerWatcher() and the event matches the type of events // specified by StartPointerWatcher(). The client will not receive farther // events until the event is ack'ed, regardless of the value of // |matches_pointer_watcher|. OnWindowInputEvent(uint32 event_id, uint64 window, int64 display_id, ui.mojom.Event event, bool matches_pointer_watcher); // Called when a pointer event that would not normally be targeted at this // client is encountered and the client called StartPointerWatcher(). See // StartPointerWatcher() for details. |window_id| is the window id of the // event target, or 0 if the window is not known to this client. The // client should not acknowledge these events. OnPointerEventObserved(ui.mojom.Event event, uint64 window_id, int64 display_id); // Called in two distinct cases: when a window known to the connection gains // focus, or when focus moves from a window known to the connection to a // window not known to the connection. In the later case |focused_window_id| // is 0. As with other functions this is only called if the client did not // initiate the change. OnWindowFocused(uint64 focused_window_id); OnWindowCursorChanged(uint64 window_id, CursorData cursor); // Invoked when a client window submits a new surface ID. The surface ID and // associated information is propagated to the parent connection. The parent // compositor can take ownership of this surface ID and embed it along with // frame_size and device_scale_factor in a layer. // TODO(fsamuel): Surface IDs should be passed to parents directly instead of // going through the window server. http://crbug.com/655231 OnWindowSurfaceChanged(uint64 window_id, viz.mojom.SurfaceInfo surface_info); // Called when the mouse cursor enters a window on this connection for the // first time, providing a list of available mime types. We want to send this // set of data only one time, so this isn't part of OnDragEnter(), which // occurs every time the mouse enters a window. OnDragDropStart(map> drag_data); // Called when the mouse cursor enters a window that has opted into // accepting drags through SetAcceptsDrags(), providing a list // of available mime types. Returns a bitmask of the supported // operations. |screen_position| is in screen coordinates. OnDragEnter(uint64 window, uint32 key_state, gfx.mojom.Point screen_position, uint32 effect_bitmask) => (uint32 supported_op_bitmask); // Called when the pointer moves over the window after the initial // DragEnter. Returns a bitmask of the supported operations at this // location. |screen_position| is in screen coordinates. OnDragOver(uint64 window, uint32 key_state, gfx.mojom.Point screen_position, uint32 effect_bitmask) => (uint32 supported_op_bitmask); // Called when the pointer leaves a window or if the drop is // canceled. OnDragLeave(uint64 window); // Called when the drop occurs on a window. Returns the action // taken. |screen_position| is in screen coordinates. OnCompleteDrop(uint64 window, uint32 key_state, gfx.mojom.Point screen_position, uint32 effect_bitmask) => (uint32 action_taken); // Called on the client that requested PerformDragDrop() to return which drag // action was completed. This is called instead of OnChangeCompleted(). OnPerformDragDropCompleted(uint32 change_id, bool success, uint32 action_taken); // Called after OnCompleteDrop completes for every connection which received // an OnDragDropStart() message. This signals that a client can forget the // |drag_data| passed in via the first message. OnDragDropDone(); // Called when the topmost window under the cursor/touch changes. The client // receives at most two IDs for the topmost windows. The first one is for the // topmost window. The second one is optionally for the second topmost window // if the first one happens to be the current event target. The second one // will be used by the client when they want to ignore the event target. // Each ID can be 0 when the window is not hosted by the client. OnTopmostWindowChanged(array topmost_ids); // A change initiated from the client has completed. See description of // change ids for details. OnChangeCompleted(uint32 change_id, bool success); // The WindowManager is requesting the specified window to close. If the // client allows the change it should delete the window. RequestClose(uint64 window_id); // Requests the ScreenProviderObserver from the client. See // ScreenProviderObserver for details. GetScreenProviderObserver(associated ScreenProviderObserver& observer); }; // Mus provides this interface as a way for clients to connect and obtain a // WindowTree handle with a supplied WindowTreeClient handle. The // WindowTreeClient has no roots, use NewTopLevelWindow() to create one. interface WindowTreeFactory { CreateWindowTree(WindowTree& tree_request, WindowTreeClient client); };