/* * This an unstable interface of wlroots. No guarantees are made regarding the * future consistency of this API. */ #ifndef WLR_USE_UNSTABLE #error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" #endif #ifndef WLR_TYPES_WLR_COMPOSITOR_H #define WLR_TYPES_WLR_COMPOSITOR_H #include #include #include #include #include #include #include #include enum wlr_surface_state_field { WLR_SURFACE_STATE_BUFFER = 1 << 0, WLR_SURFACE_STATE_SURFACE_DAMAGE = 1 << 1, WLR_SURFACE_STATE_BUFFER_DAMAGE = 1 << 2, WLR_SURFACE_STATE_OPAQUE_REGION = 1 << 3, WLR_SURFACE_STATE_INPUT_REGION = 1 << 4, WLR_SURFACE_STATE_TRANSFORM = 1 << 5, WLR_SURFACE_STATE_SCALE = 1 << 6, WLR_SURFACE_STATE_FRAME_CALLBACK_LIST = 1 << 7, WLR_SURFACE_STATE_VIEWPORT = 1 << 8, WLR_SURFACE_STATE_OFFSET = 1 << 9, }; struct wlr_surface_state { uint32_t committed; // enum wlr_surface_state_field // Sequence number of the surface state. Incremented on each commit, may // overflow. uint32_t seq; struct wlr_buffer *buffer; int32_t dx, dy; // relative to previous position pixman_region32_t surface_damage, buffer_damage; // clipped to bounds pixman_region32_t opaque, input; enum wl_output_transform transform; int32_t scale; struct wl_list frame_callback_list; // wl_resource int width, height; // in surface-local coordinates int buffer_width, buffer_height; struct wl_list subsurfaces_below; struct wl_list subsurfaces_above; /** * The viewport is applied after the surface transform and scale. * * If has_src is true, the surface content is cropped to the provided * rectangle. If has_dst is true, the surface content is scaled to the * provided rectangle. */ struct { bool has_src, has_dst; // In coordinates after scale/transform are applied, but before the // destination rectangle is applied struct wlr_fbox src; int dst_width, dst_height; // in surface-local coordinates } viewport; // Number of locks that prevent this surface state from being committed. size_t cached_state_locks; struct wl_list cached_state_link; // wlr_surface.cached // Sync'ed object states, one per struct wlr_surface_synced struct wl_array synced; // void * }; struct wlr_surface_role { const char *name; /** * If true, the role isn't represented by any object. * For example, this applies to cursor surfaces. */ bool no_object; /** * Called when the client sends the wl_surface.commit request. May be NULL. * Typically used to check that the pending state is valid, and send * protocol errors if not. * * If the role is represented by an object, this is only called if * such object exists. */ void (*client_commit)(struct wlr_surface *surface); /** * Called when a new surface state is committed. May be NULL. * * If the role is represented by an object, this is only called if * such object exists. */ void (*commit)(struct wlr_surface *surface); /** * Called when the surface is unmapped. May be NULL. * * If the role is represented by an object, this is only called if * such object exists. */ void (*unmap)(struct wlr_surface *surface); /** * Called when the object representing the role is destroyed. May be NULL. */ void (*destroy)(struct wlr_surface *surface); }; struct wlr_surface_output { struct wlr_surface *surface; struct wlr_output *output; struct wl_list link; // wlr_surface.current_outputs struct wl_listener bind; struct wl_listener destroy; }; struct wlr_surface { struct wl_resource *resource; struct wlr_compositor *compositor; /** * The surface's buffer, if any. A surface has an attached buffer when it * commits with a non-null buffer in its pending state. A surface will not * have a buffer if it has never committed one, has committed a null buffer, * or something went wrong with uploading the buffer. */ struct wlr_client_buffer *buffer; /** * The last commit's buffer damage, in buffer-local coordinates. This * contains both the damage accumulated by the client via * `wlr_surface_state.surface_damage` and `wlr_surface_state.buffer_damage`. * If the buffer has been resized, the whole buffer is damaged. * * This region needs to be scaled and transformed into output coordinates, * just like the buffer's texture. In addition, if the buffer has shrunk the * old size needs to be damaged and if the buffer has moved the old and new * positions need to be damaged. */ pixman_region32_t buffer_damage; /** * The current opaque region, in surface-local coordinates. It is clipped to * the surface bounds. If the surface's buffer is using a fully opaque * format, this is set to the whole surface. */ pixman_region32_t opaque_region; /** * The current input region, in surface-local coordinates. It is clipped to * the surface bounds. * * If the protocol states that the input region is ignored, this is empty. */ pixman_region32_t input_region; /** * `current` contains the current, committed surface state. `pending` * accumulates state changes from the client between commits and shouldn't * be accessed by the compositor directly. */ struct wlr_surface_state current, pending; struct wl_list cached; // wlr_surface_state.cached_link /** * Whether the surface is ready to be displayed. */ bool mapped; /** * The lifetime-bound role of the surface. NULL if the role was never set. */ const struct wlr_surface_role *role; /** * The role object representing the role. NULL if the role isn't * represented by any object or the object was destroyed. */ struct wl_resource *role_resource; struct { struct wl_signal client_commit; struct wl_signal commit; /** * The `map` event signals that the surface has a non-null buffer * committed and is ready to be displayed. */ struct wl_signal map; /** * The `unmap` event signals that the surface shouldn't be displayed * anymore. This can happen when a null buffer is committed, * the associated role object is destroyed, or when the role-specific * conditions for the surface to be mapped no longer apply. */ struct wl_signal unmap; /** * Note: unlike other new_* signals, new_subsurface is emitted when * the subsurface is added to the parent surface's current state, * not when the object is created. */ struct wl_signal new_subsurface; // struct wlr_subsurface struct wl_signal destroy; } events; struct wl_list current_outputs; // wlr_surface_output.link struct wlr_addon_set addons; void *data; // private state struct wl_listener role_resource_destroy; struct { int32_t scale; enum wl_output_transform transform; int width, height; int buffer_width, buffer_height; } previous; bool unmap_commit; bool opaque; bool handling_commit; bool pending_rejected; int32_t preferred_buffer_scale; bool preferred_buffer_transform_sent; enum wl_output_transform preferred_buffer_transform; struct wl_list synced; // wlr_surface_synced.link size_t synced_len; struct wl_resource *pending_buffer_resource; struct wl_listener pending_buffer_resource_destroy; }; struct wlr_renderer; struct wlr_compositor { struct wl_global *global; struct wlr_renderer *renderer; // may be NULL struct wl_listener display_destroy; struct wl_listener renderer_destroy; struct { struct wl_signal new_surface; struct wl_signal destroy; } events; }; typedef void (*wlr_surface_iterator_func_t)(struct wlr_surface *surface, int sx, int sy, void *data); /** * Set the lifetime role for this surface. * * If the surface already has a different role and/or has a role object set, * the function fails and sends an error to the client. * * Returns true on success, false otherwise. */ bool wlr_surface_set_role(struct wlr_surface *surface, const struct wlr_surface_role *role, struct wl_resource *error_resource, uint32_t error_code); /** * Set the role object for this surface. The surface must have a role and * no already set role object. * * When the resource is destroyed, the surface is unmapped, * wlr_surface_role.destroy is called and the role object is unset. */ void wlr_surface_set_role_object(struct wlr_surface *surface, struct wl_resource *role_resource); /** * Map the surface. If the surface is already mapped, this is no-op. * * This function must only be used by surface role implementations. */ void wlr_surface_map(struct wlr_surface *surface); /** * Unmap the surface. If the surface is already unmapped, this is no-op. * * This function must only be used by surface role implementations. */ void wlr_surface_unmap(struct wlr_surface *surface); /** * Mark the pending state of a surface as rejected due to a protocol violation, * preventing it from being cached or committed. * * This function must only be used while processing a commit request. */ void wlr_surface_reject_pending(struct wlr_surface *surface, struct wl_resource *resource, uint32_t code, const char *msg, ...); /** * Whether or not this surface currently has an attached buffer. A surface has * an attached buffer when it commits with a non-null buffer in its pending * state. A surface will not have a buffer if it has never committed one or has * committed a null buffer. */ bool wlr_surface_has_buffer(struct wlr_surface *surface); /** * Check whether this surface state has an attached buffer. * * A surface has an attached buffer when the client commits with a non-null * buffer. A surface will not have a buffer if the client never committed one, * or committed a null buffer. * * Note that wlr_surface_state.buffer may be NULL even if this function returns * true: the buffer field is reset after commit, to allow the buffer to be * released to the client. Additionally, the buffer import or upload may fail. */ bool wlr_surface_state_has_buffer(const struct wlr_surface_state *state); /** * Get the texture of the buffer currently attached to this surface. Returns * NULL if no buffer is currently attached or if something went wrong with * uploading the buffer. */ struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface); /** * Get the root of the subsurface tree for this surface. Can return NULL if * a surface in the tree has been destroyed. */ struct wlr_surface *wlr_surface_get_root_surface(struct wlr_surface *surface); /** * Check if the surface accepts input events at the given surface-local * coordinates. Does not check the surface's subsurfaces. */ bool wlr_surface_point_accepts_input(struct wlr_surface *surface, double sx, double sy); /** * Find a surface in this surface's tree that accepts input events and has all * parents mapped (except this surface, which can be unmapped) at the given * surface-local coordinates. Returns the surface and coordinates in the leaf * surface coordinate system or NULL if no surface is found at that location. */ struct wlr_surface *wlr_surface_surface_at(struct wlr_surface *surface, double sx, double sy, double *sub_x, double *sub_y); /** * Notify the client that the surface has entered an output. * * This is a no-op if the surface has already entered the output. */ void wlr_surface_send_enter(struct wlr_surface *surface, struct wlr_output *output); /** * Notify the client that the surface has left an output. * * This is a no-op if the surface has already left the output. */ void wlr_surface_send_leave(struct wlr_surface *surface, struct wlr_output *output); /** * Complete the queued frame callbacks for this surface. * * This will send an event to the client indicating that now is a good time to * draw its next frame. */ void wlr_surface_send_frame_done(struct wlr_surface *surface, const struct timespec *when); /** * Get the bounding box that contains the surface and all subsurfaces in * surface coordinates. * X and y may be negative, if there are subsurfaces with negative position. */ void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box); /** * Get the struct wlr_surface corresponding to a wl_surface resource. * * This asserts that the resource is a valid wl_surface resource created by * wlroots and will never return NULL. */ struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource); /** * Call `iterator` on each mapped surface in the surface tree (whether or not * this surface is mapped), with the surface's position relative to the root * surface. The function is called from root to leaves (in rendering order). */ void wlr_surface_for_each_surface(struct wlr_surface *surface, wlr_surface_iterator_func_t iterator, void *user_data); /** * Get the effective surface damage in surface-local coordinate space. */ void wlr_surface_get_effective_damage(struct wlr_surface *surface, pixman_region32_t *damage); /** * Get the source rectangle describing the region of the buffer that needs to * be sampled to render this surface's current state. The box is in * buffer-local coordinates. * * If the viewport's source rectangle is unset, the position is zero and the * size is the buffer's. */ void wlr_surface_get_buffer_source_box(struct wlr_surface *surface, struct wlr_fbox *box); /** * Acquire a lock for the pending surface state. * * The state won't be committed before the caller releases the lock. Instead, * the state becomes cached. The caller needs to use wlr_surface_unlock_cached() * to release the lock. * * Returns a surface commit sequence number for the cached state. */ uint32_t wlr_surface_lock_pending(struct wlr_surface *surface); /** * Release a lock for a cached state. * * Callers should not assume that the cached state will immediately be * committed. Another caller may still have an active lock. */ void wlr_surface_unlock_cached(struct wlr_surface *surface, uint32_t seq); /** * Set the preferred buffer scale for the surface. * * This sends an event to the client indicating the preferred scale to use for * buffers attached to this surface. */ void wlr_surface_set_preferred_buffer_scale(struct wlr_surface *surface, int32_t scale); /** * Set the preferred buffer transform for the surface. * * This sends an event to the client indicating the preferred transform to use * for buffers attached to this surface. */ void wlr_surface_set_preferred_buffer_transform(struct wlr_surface *surface, enum wl_output_transform transform); /** * Implementation for struct wlr_surface_synced. * * struct wlr_surface takes care of allocating the sync'ed object state. * * The only mandatory field is state_size. */ struct wlr_surface_synced_impl { // Size in bytes of the state struct. size_t state_size; // Initialize a state. If NULL, this is a no-op. void (*init_state)(void *state); // Finish a state. If NULL, this is a no-op. void (*finish_state)(void *state); // Move a state. If NULL, memcpy() is used. void (*move_state)(void *dst, void *src); }; /** * An object synchronized with a surface. * * This is typically used by surface add-ons which integrate with the surface * commit mechanism. * * A sync'ed object maintains state whose lifecycle is managed by * struct wlr_surface_synced_impl. Clients make requests to mutate the pending * state, then clients commit the pending state via wl_surface.commit. The * pending state may become cached, then becomes current when it's applied. */ struct wlr_surface_synced { struct wlr_surface *surface; const struct wlr_surface_synced_impl *impl; struct wl_list link; // wlr_surface.synced size_t index; }; /** * Initialize a sync'ed object. * * pending and current must be pointers to the sync'ed object's state. This * function will initialize them. */ bool wlr_surface_synced_init(struct wlr_surface_synced *synced, struct wlr_surface *surface, const struct wlr_surface_synced_impl *impl, void *pending, void *current); /** * Finish a sync'ed object. * * This must be called before the struct wlr_surface is destroyed. */ void wlr_surface_synced_finish(struct wlr_surface_synced *synced); /** * Obtain a sync'ed object state. */ void *wlr_surface_synced_get_state(struct wlr_surface_synced *synced, const struct wlr_surface_state *state); /** * Get a Pixman region from a wl_region resource. */ const pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource); /** * Create the wl_compositor global, which can be used by clients to create * surfaces and regions. * * If a renderer is supplied, the compositor will create struct wlr_texture * objects from client buffers on surface commit. */ struct wlr_compositor *wlr_compositor_create(struct wl_display *display, uint32_t version, struct wlr_renderer *renderer); /** * Set the renderer used for creating struct wlr_texture objects from client * buffers on surface commit. * * The renderer may be NULL, in which case no textures are created. * * Calling this function does not update existing textures, it only affects * future surface commits. */ void wlr_compositor_set_renderer(struct wlr_compositor *compositor, struct wlr_renderer *renderer); #endif