mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	surface: move impl to types/wlr_{sub,}compositor.c
This commit is contained in:
		
							parent
							
								
									4ec683ad1c
								
							
						
					
					
						commit
						36b5d5888c
					
				
					 5 changed files with 1433 additions and 1466 deletions
				
			
		| 
						 | 
					@ -1,20 +0,0 @@
 | 
				
			||||||
#ifndef TYPES_WLR_SURFACE_H
 | 
					 | 
				
			||||||
#define TYPES_WLR_SURFACE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <wlr/types/wlr_surface.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wlr_renderer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Create a new surface resource with the provided new ID.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct wlr_surface *surface_create(struct wl_client *client,
 | 
					 | 
				
			||||||
	uint32_t version, uint32_t id, struct wlr_renderer *renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Create a new subsurface resource with the provided new ID.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct wlr_subsurface *subsurface_create(struct wlr_surface *surface,
 | 
					 | 
				
			||||||
	struct wlr_surface *parent, uint32_t version, uint32_t id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,6 @@ wlr_files += files(
 | 
				
			||||||
	'wlr_screencopy_v1.c',
 | 
						'wlr_screencopy_v1.c',
 | 
				
			||||||
	'wlr_server_decoration.c',
 | 
						'wlr_server_decoration.c',
 | 
				
			||||||
	'wlr_subcompositor.c',
 | 
						'wlr_subcompositor.c',
 | 
				
			||||||
	'wlr_surface.c',
 | 
					 | 
				
			||||||
	'wlr_switch.c',
 | 
						'wlr_switch.c',
 | 
				
			||||||
	'wlr_tablet_pad.c',
 | 
						'wlr_tablet_pad.c',
 | 
				
			||||||
	'wlr_tablet_tool.c',
 | 
						'wlr_tablet_tool.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -4,12 +4,383 @@
 | 
				
			||||||
#include <wlr/types/wlr_subcompositor.h>
 | 
					#include <wlr/types/wlr_subcompositor.h>
 | 
				
			||||||
#include <wlr/types/wlr_surface.h>
 | 
					#include <wlr/types/wlr_surface.h>
 | 
				
			||||||
#include "types/wlr_region.h"
 | 
					#include "types/wlr_region.h"
 | 
				
			||||||
#include "types/wlr_surface.h"
 | 
					 | 
				
			||||||
#include "util/signal.h"
 | 
					#include "util/signal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SUBCOMPOSITOR_VERSION 1
 | 
					#define SUBCOMPOSITOR_VERSION 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const struct wlr_surface_role subsurface_role;
 | 
					static bool subsurface_is_synchronized(struct wlr_subsurface *subsurface) {
 | 
				
			||||||
 | 
						while (subsurface != NULL) {
 | 
				
			||||||
 | 
							if (subsurface->synchronized) {
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!subsurface->parent) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!wlr_surface_is_subsurface(subsurface->parent)) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							subsurface = wlr_subsurface_from_wlr_surface(subsurface->parent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_unmap(struct wlr_subsurface *subsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_destroy(struct wlr_subsurface *subsurface) {
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (subsurface->has_cache) {
 | 
				
			||||||
 | 
							wlr_surface_unlock_cached(subsurface->surface,
 | 
				
			||||||
 | 
								subsurface->cached_seq);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface_unmap(subsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_signal_emit_safe(&subsurface->events.destroy, subsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->surface_destroy.link);
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->surface_client_commit.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (subsurface->parent) {
 | 
				
			||||||
 | 
							wl_list_remove(&subsurface->current.link);
 | 
				
			||||||
 | 
							wl_list_remove(&subsurface->pending.link);
 | 
				
			||||||
 | 
							wl_list_remove(&subsurface->parent_destroy.link);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_resource_set_user_data(subsurface->resource, NULL);
 | 
				
			||||||
 | 
						if (subsurface->surface) {
 | 
				
			||||||
 | 
							subsurface->surface->role_data = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(subsurface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct wl_subsurface_interface subsurface_implementation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_subsurface *subsurface_from_resource(
 | 
				
			||||||
 | 
							struct wl_resource *resource) {
 | 
				
			||||||
 | 
						assert(wl_resource_instance_of(resource, &wl_subsurface_interface,
 | 
				
			||||||
 | 
							&subsurface_implementation));
 | 
				
			||||||
 | 
						return wl_resource_get_user_data(resource);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_resource_destroy(struct wl_resource *resource) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						subsurface_destroy(subsurface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_destroy(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource) {
 | 
				
			||||||
 | 
						wl_resource_destroy(resource);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_set_position(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource, int32_t x, int32_t y) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface->pending.x = x;
 | 
				
			||||||
 | 
						subsurface->pending.y = y;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_subsurface *subsurface_find_sibling(
 | 
				
			||||||
 | 
							struct wlr_subsurface *subsurface, struct wlr_surface *surface) {
 | 
				
			||||||
 | 
						struct wlr_surface *parent = subsurface->parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_subsurface *sibling;
 | 
				
			||||||
 | 
						wl_list_for_each(sibling, &parent->pending.subsurfaces_below, pending.link) {
 | 
				
			||||||
 | 
							if (sibling->surface == surface && sibling != subsurface) {
 | 
				
			||||||
 | 
								return sibling;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_for_each(sibling, &parent->pending.subsurfaces_above, pending.link) {
 | 
				
			||||||
 | 
							if (sibling->surface == surface && sibling != subsurface) {
 | 
				
			||||||
 | 
								return sibling;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_place_above(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource, struct wl_resource *sibling_resource) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_surface *sibling_surface =
 | 
				
			||||||
 | 
							wlr_surface_from_resource(sibling_resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_list *node;
 | 
				
			||||||
 | 
						if (sibling_surface == subsurface->parent) {
 | 
				
			||||||
 | 
							node = &subsurface->parent->pending.subsurfaces_above;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							struct wlr_subsurface *sibling =
 | 
				
			||||||
 | 
								subsurface_find_sibling(subsurface, sibling_surface);
 | 
				
			||||||
 | 
							if (!sibling) {
 | 
				
			||||||
 | 
								wl_resource_post_error(subsurface->resource,
 | 
				
			||||||
 | 
									WL_SUBSURFACE_ERROR_BAD_SURFACE,
 | 
				
			||||||
 | 
									"%s: wl_surface@%" PRIu32 "is not a parent or sibling",
 | 
				
			||||||
 | 
									"place_above", wl_resource_get_id(sibling_resource));
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							node = &sibling->pending.link;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->pending.link);
 | 
				
			||||||
 | 
						wl_list_insert(node, &subsurface->pending.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface->reordered = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_place_below(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource, struct wl_resource *sibling_resource) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_surface *sibling_surface =
 | 
				
			||||||
 | 
							wlr_surface_from_resource(sibling_resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_list *node;
 | 
				
			||||||
 | 
						if (sibling_surface == subsurface->parent) {
 | 
				
			||||||
 | 
							node = &subsurface->parent->pending.subsurfaces_below;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							struct wlr_subsurface *sibling =
 | 
				
			||||||
 | 
								subsurface_find_sibling(subsurface, sibling_surface);
 | 
				
			||||||
 | 
							if (!sibling) {
 | 
				
			||||||
 | 
								wl_resource_post_error(subsurface->resource,
 | 
				
			||||||
 | 
									WL_SUBSURFACE_ERROR_BAD_SURFACE,
 | 
				
			||||||
 | 
									"%s: wl_surface@%" PRIu32 " is not a parent or sibling",
 | 
				
			||||||
 | 
									"place_below", wl_resource_get_id(sibling_resource));
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							node = &sibling->pending.link;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->pending.link);
 | 
				
			||||||
 | 
						wl_list_insert(node->prev, &subsurface->pending.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface->reordered = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_set_sync(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface->synchronized = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_set_desync(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_resource *resource) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (subsurface->synchronized) {
 | 
				
			||||||
 | 
							subsurface->synchronized = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!subsurface_is_synchronized(subsurface) &&
 | 
				
			||||||
 | 
									subsurface->has_cache) {
 | 
				
			||||||
 | 
								wlr_surface_unlock_cached(subsurface->surface,
 | 
				
			||||||
 | 
									subsurface->cached_seq);
 | 
				
			||||||
 | 
								subsurface->has_cache = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct wl_subsurface_interface subsurface_implementation = {
 | 
				
			||||||
 | 
						.destroy = subsurface_handle_destroy,
 | 
				
			||||||
 | 
						.set_position = subsurface_handle_set_position,
 | 
				
			||||||
 | 
						.place_above = subsurface_handle_place_above,
 | 
				
			||||||
 | 
						.place_below = subsurface_handle_place_below,
 | 
				
			||||||
 | 
						.set_sync = subsurface_handle_set_sync,
 | 
				
			||||||
 | 
						.set_desync = subsurface_handle_set_desync,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Checks if this subsurface needs to be marked as mapped. This can happen if:
 | 
				
			||||||
 | 
					 * - The subsurface has a buffer
 | 
				
			||||||
 | 
					 * - Its parent is mapped
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void subsurface_consider_map(struct wlr_subsurface *subsurface,
 | 
				
			||||||
 | 
							bool check_parent) {
 | 
				
			||||||
 | 
						if (subsurface->mapped || !wlr_surface_has_buffer(subsurface->surface)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (check_parent) {
 | 
				
			||||||
 | 
							if (subsurface->parent == NULL) {
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (wlr_surface_is_subsurface(subsurface->parent)) {
 | 
				
			||||||
 | 
								struct wlr_subsurface *parent =
 | 
				
			||||||
 | 
									wlr_subsurface_from_wlr_surface(subsurface->parent);
 | 
				
			||||||
 | 
								if (parent == NULL || !parent->mapped) {
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now we can map the subsurface
 | 
				
			||||||
 | 
						wlr_signal_emit_safe(&subsurface->events.map, subsurface);
 | 
				
			||||||
 | 
						subsurface->mapped = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Try mapping all children too
 | 
				
			||||||
 | 
						struct wlr_subsurface *child;
 | 
				
			||||||
 | 
						wl_list_for_each(child, &subsurface->surface->current.subsurfaces_below,
 | 
				
			||||||
 | 
								current.link) {
 | 
				
			||||||
 | 
							subsurface_consider_map(child, false);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_for_each(child, &subsurface->surface->current.subsurfaces_above,
 | 
				
			||||||
 | 
								current.link) {
 | 
				
			||||||
 | 
							subsurface_consider_map(child, false);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_unmap(struct wlr_subsurface *subsurface) {
 | 
				
			||||||
 | 
						if (!subsurface->mapped) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_signal_emit_safe(&subsurface->events.unmap, subsurface);
 | 
				
			||||||
 | 
						subsurface->mapped = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Unmap all children
 | 
				
			||||||
 | 
						struct wlr_subsurface *child;
 | 
				
			||||||
 | 
						wl_list_for_each(child, &subsurface->surface->current.subsurfaces_below,
 | 
				
			||||||
 | 
								current.link) {
 | 
				
			||||||
 | 
							subsurface_unmap(child);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_for_each(child, &subsurface->surface->current.subsurfaces_above,
 | 
				
			||||||
 | 
								current.link) {
 | 
				
			||||||
 | 
							subsurface_unmap(child);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_role_commit(struct wlr_surface *surface) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							wlr_subsurface_from_wlr_surface(surface);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subsurface_consider_map(subsurface, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_role_precommit(struct wlr_surface *surface) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							wlr_subsurface_from_wlr_surface(surface);
 | 
				
			||||||
 | 
						if (subsurface == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
 | 
				
			||||||
 | 
								surface->pending.buffer == NULL) {
 | 
				
			||||||
 | 
							// This is a NULL commit
 | 
				
			||||||
 | 
							subsurface_unmap(subsurface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct wlr_surface_role subsurface_role = {
 | 
				
			||||||
 | 
						.name = "wl_subsurface",
 | 
				
			||||||
 | 
						.commit = subsurface_role_commit,
 | 
				
			||||||
 | 
						.precommit = subsurface_role_precommit,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_parent_destroy(struct wl_listener *listener,
 | 
				
			||||||
 | 
							void *data) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							wl_container_of(listener, subsurface, parent_destroy);
 | 
				
			||||||
 | 
						subsurface_unmap(subsurface);
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->current.link);
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->pending.link);
 | 
				
			||||||
 | 
						wl_list_remove(&subsurface->parent_destroy.link);
 | 
				
			||||||
 | 
						subsurface->parent = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_surface_destroy(struct wl_listener *listener,
 | 
				
			||||||
 | 
							void *data) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							wl_container_of(listener, subsurface, surface_destroy);
 | 
				
			||||||
 | 
						subsurface_destroy(subsurface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void subsurface_handle_surface_client_commit(
 | 
				
			||||||
 | 
							struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							wl_container_of(listener, subsurface, surface_client_commit);
 | 
				
			||||||
 | 
						struct wlr_surface *surface = subsurface->surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (subsurface_is_synchronized(subsurface)) {
 | 
				
			||||||
 | 
							if (subsurface->has_cache) {
 | 
				
			||||||
 | 
								// We already lock a previous commit. The prevents any future
 | 
				
			||||||
 | 
								// commit to be applied before we release the previous commit.
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							subsurface->has_cache = true;
 | 
				
			||||||
 | 
							subsurface->cached_seq = wlr_surface_lock_pending(surface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_subsurface *subsurface_create(struct wlr_surface *surface,
 | 
				
			||||||
 | 
							struct wlr_surface *parent, uint32_t version, uint32_t id) {
 | 
				
			||||||
 | 
						struct wl_client *client = wl_resource_get_client(surface->resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_subsurface *subsurface =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_subsurface));
 | 
				
			||||||
 | 
						if (!subsurface) {
 | 
				
			||||||
 | 
							wl_client_post_no_memory(client);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						subsurface->synchronized = true;
 | 
				
			||||||
 | 
						subsurface->surface = surface;
 | 
				
			||||||
 | 
						subsurface->resource =
 | 
				
			||||||
 | 
							wl_resource_create(client, &wl_subsurface_interface, version, id);
 | 
				
			||||||
 | 
						if (subsurface->resource == NULL) {
 | 
				
			||||||
 | 
							free(subsurface);
 | 
				
			||||||
 | 
							wl_client_post_no_memory(client);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_resource_set_implementation(subsurface->resource,
 | 
				
			||||||
 | 
							&subsurface_implementation, subsurface, subsurface_resource_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_signal_init(&subsurface->events.destroy);
 | 
				
			||||||
 | 
						wl_signal_init(&subsurface->events.map);
 | 
				
			||||||
 | 
						wl_signal_init(&subsurface->events.unmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_signal_add(&surface->events.destroy, &subsurface->surface_destroy);
 | 
				
			||||||
 | 
						subsurface->surface_destroy.notify = subsurface_handle_surface_destroy;
 | 
				
			||||||
 | 
						wl_signal_add(&surface->events.client_commit,
 | 
				
			||||||
 | 
							&subsurface->surface_client_commit);
 | 
				
			||||||
 | 
						subsurface->surface_client_commit.notify =
 | 
				
			||||||
 | 
							subsurface_handle_surface_client_commit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// link parent
 | 
				
			||||||
 | 
						subsurface->parent = parent;
 | 
				
			||||||
 | 
						wl_signal_add(&parent->events.destroy, &subsurface->parent_destroy);
 | 
				
			||||||
 | 
						subsurface->parent_destroy.notify = subsurface_handle_parent_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&subsurface->current.link);
 | 
				
			||||||
 | 
						wl_list_insert(parent->pending.subsurfaces_above.prev,
 | 
				
			||||||
 | 
							&subsurface->pending.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						surface->role_data = subsurface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return subsurface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool wlr_surface_is_subsurface(struct wlr_surface *surface) {
 | 
					bool wlr_surface_is_subsurface(struct wlr_surface *surface) {
 | 
				
			||||||
	return surface->role == &subsurface_role;
 | 
						return surface->role == &subsurface_role;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1442
									
								
								types/wlr_surface.c
									
										
									
									
									
								
							
							
						
						
									
										1442
									
								
								types/wlr_surface.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue