You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							816 lines
						
					
					
						
							22 KiB
						
					
					
				
			
		
		
	
	
							816 lines
						
					
					
						
							22 KiB
						
					
					
				/*
 | 
						|
 * Copyright © 2016 Quentin "Sardem FF7" Glidic
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the next
 | 
						|
 * paragraph) shall be included in all copies or substantial portions of the
 | 
						|
 * Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
 * DEALINGS IN THE SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include <wayland-server.h>
 | 
						|
 | 
						|
#include "compositor.h"
 | 
						|
#include "zalloc.h"
 | 
						|
 | 
						|
#include "libweston-desktop.h"
 | 
						|
#include "internal.h"
 | 
						|
 | 
						|
struct weston_desktop_view {
 | 
						|
	struct wl_list link;
 | 
						|
	struct weston_view *view;
 | 
						|
	struct weston_desktop_view *parent;
 | 
						|
	struct wl_list children_list;
 | 
						|
	struct wl_list children_link;
 | 
						|
};
 | 
						|
 | 
						|
struct weston_desktop_surface {
 | 
						|
	struct weston_desktop *desktop;
 | 
						|
	struct weston_desktop_client *client;
 | 
						|
	struct wl_list client_link;
 | 
						|
	const struct weston_desktop_surface_implementation *implementation;
 | 
						|
	void *implementation_data;
 | 
						|
	void *user_data;
 | 
						|
	struct weston_surface *surface;
 | 
						|
	struct wl_list view_list;
 | 
						|
	struct weston_position buffer_move;
 | 
						|
	struct wl_listener surface_commit_listener;
 | 
						|
	struct wl_listener surface_destroy_listener;
 | 
						|
	struct wl_listener client_destroy_listener;
 | 
						|
	struct wl_list children_list;
 | 
						|
 | 
						|
	struct wl_list resource_list;
 | 
						|
	bool has_geometry;
 | 
						|
	struct weston_geometry geometry;
 | 
						|
	struct {
 | 
						|
		char *title;
 | 
						|
		char *app_id;
 | 
						|
		pid_t pid;
 | 
						|
	};
 | 
						|
	struct {
 | 
						|
		struct weston_desktop_surface *parent;
 | 
						|
		struct wl_list children_link;
 | 
						|
		struct weston_position position;
 | 
						|
		bool use_geometry;
 | 
						|
	};
 | 
						|
	struct {
 | 
						|
		struct wl_list grab_link;
 | 
						|
	};
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_surface_update_view_position(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view;
 | 
						|
	int32_t x, y;
 | 
						|
 | 
						|
	x = surface->position.x;
 | 
						|
	y = surface->position.y;
 | 
						|
 | 
						|
	if (surface->use_geometry) {
 | 
						|
		struct weston_desktop_surface *parent =
 | 
						|
			weston_desktop_surface_get_parent(surface);
 | 
						|
		struct weston_geometry geometry, parent_geometry;
 | 
						|
 | 
						|
		geometry = weston_desktop_surface_get_geometry(surface);
 | 
						|
		parent_geometry = weston_desktop_surface_get_geometry(parent);
 | 
						|
 | 
						|
		x += parent_geometry.x - geometry.x;
 | 
						|
		y += parent_geometry.y - geometry.y;
 | 
						|
	}
 | 
						|
	wl_list_for_each(view, &surface->view_list, link)
 | 
						|
		weston_view_set_position(view->view, x, y);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_view_propagate_layer(struct weston_desktop_view *view);
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_view_destroy(struct weston_desktop_view *view)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *child_view, *tmp;
 | 
						|
 | 
						|
	wl_list_for_each_safe(child_view, tmp, &view->children_list, children_link)
 | 
						|
		weston_desktop_view_destroy(child_view);
 | 
						|
 | 
						|
	wl_list_remove(&view->children_link);
 | 
						|
	wl_list_remove(&view->link);
 | 
						|
 | 
						|
	weston_view_damage_below(view->view);
 | 
						|
	if (view->parent != NULL)
 | 
						|
		weston_view_destroy(view->view);
 | 
						|
 | 
						|
	free(view);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_destroy(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view, *next_view;
 | 
						|
	struct weston_desktop_surface *child, *next_child;
 | 
						|
 | 
						|
	wl_list_remove(&surface->surface_commit_listener.link);
 | 
						|
	wl_list_remove(&surface->surface_destroy_listener.link);
 | 
						|
	wl_list_remove(&surface->client_destroy_listener.link);
 | 
						|
 | 
						|
	if (!wl_list_empty(&surface->resource_list)) {
 | 
						|
		struct wl_resource *resource, *tmp;
 | 
						|
		wl_resource_for_each_safe(resource, tmp, &surface->resource_list) {
 | 
						|
			wl_resource_set_user_data(resource, NULL);
 | 
						|
			wl_list_remove(wl_resource_get_link(resource));
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	surface->implementation->destroy(surface, surface->implementation_data);
 | 
						|
 | 
						|
	surface->surface->committed = NULL;
 | 
						|
	surface->surface->committed_private = NULL;
 | 
						|
 | 
						|
	weston_desktop_surface_unset_relative_to(surface);
 | 
						|
	wl_list_remove(&surface->client_link);
 | 
						|
 | 
						|
	wl_list_for_each_safe(child, next_child,
 | 
						|
			      &surface->children_list,
 | 
						|
			      children_link)
 | 
						|
		weston_desktop_surface_unset_relative_to(child);
 | 
						|
 | 
						|
	wl_list_for_each_safe(view, next_view, &surface->view_list, link)
 | 
						|
		weston_desktop_view_destroy(view);
 | 
						|
 | 
						|
	free(surface->title);
 | 
						|
	free(surface->app_id);
 | 
						|
 | 
						|
	free(surface);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_surface_surface_committed(struct wl_listener *listener,
 | 
						|
					 void *data)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface =
 | 
						|
		wl_container_of(listener, surface, surface_commit_listener);
 | 
						|
 | 
						|
	if (surface->implementation->committed != NULL)
 | 
						|
		surface->implementation->committed(surface,
 | 
						|
						   surface->implementation_data,
 | 
						|
						   surface->buffer_move.x,
 | 
						|
						   surface->buffer_move.y);
 | 
						|
 | 
						|
	if (surface->parent != NULL) {
 | 
						|
		struct weston_desktop_view *view;
 | 
						|
 | 
						|
		wl_list_for_each(view, &surface->view_list, link) {
 | 
						|
			weston_view_set_transform_parent(view->view,
 | 
						|
							 view->parent->view);
 | 
						|
			weston_desktop_view_propagate_layer(view->parent);
 | 
						|
		}
 | 
						|
		weston_desktop_surface_update_view_position(surface);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!wl_list_empty(&surface->children_list)) {
 | 
						|
		struct weston_desktop_surface *child;
 | 
						|
 | 
						|
		wl_list_for_each(child, &surface->children_list, children_link)
 | 
						|
			weston_desktop_surface_update_view_position(child);
 | 
						|
	}
 | 
						|
 | 
						|
	surface->buffer_move.x = 0;
 | 
						|
	surface->buffer_move.y = 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_surface_surface_destroyed(struct wl_listener *listener,
 | 
						|
					 void *data)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface =
 | 
						|
		wl_container_of(listener, surface, surface_destroy_listener);
 | 
						|
 | 
						|
	weston_desktop_surface_destroy(surface);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_resource_destroy(struct wl_resource *resource)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface =
 | 
						|
		wl_resource_get_user_data(resource);
 | 
						|
 | 
						|
	if (surface != NULL)
 | 
						|
		weston_desktop_surface_destroy(surface);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_surface_committed(struct weston_surface *wsurface,
 | 
						|
				 int32_t sx, int32_t sy)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface = wsurface->committed_private;
 | 
						|
 | 
						|
	surface->buffer_move.x = sx;
 | 
						|
	surface->buffer_move.y = sy;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_surface_client_destroyed(struct wl_listener *listener,
 | 
						|
					void *data)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface =
 | 
						|
		wl_container_of(listener, surface, client_destroy_listener);
 | 
						|
 | 
						|
	weston_desktop_surface_destroy(surface);
 | 
						|
}
 | 
						|
 | 
						|
struct weston_desktop_surface *
 | 
						|
weston_desktop_surface_create(struct weston_desktop *desktop,
 | 
						|
			      struct weston_desktop_client *client,
 | 
						|
			      struct weston_surface *wsurface,
 | 
						|
			      const struct weston_desktop_surface_implementation *implementation,
 | 
						|
			      void *implementation_data)
 | 
						|
{
 | 
						|
	assert(implementation->destroy != NULL);
 | 
						|
 | 
						|
	struct weston_desktop_surface *surface;
 | 
						|
 | 
						|
	surface = zalloc(sizeof(struct weston_desktop_surface));
 | 
						|
	if (surface == NULL) {
 | 
						|
		if (client != NULL)
 | 
						|
			wl_client_post_no_memory(weston_desktop_client_get_client(client));
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	surface->desktop = desktop;
 | 
						|
	surface->implementation = implementation;
 | 
						|
	surface->implementation_data = implementation_data;
 | 
						|
	surface->surface = wsurface;
 | 
						|
 | 
						|
	surface->client = client;
 | 
						|
	surface->client_destroy_listener.notify =
 | 
						|
		weston_desktop_surface_client_destroyed;
 | 
						|
	weston_desktop_client_add_destroy_listener(
 | 
						|
		client, &surface->client_destroy_listener);
 | 
						|
 | 
						|
	wsurface->committed = weston_desktop_surface_committed;
 | 
						|
	wsurface->committed_private = surface;
 | 
						|
 | 
						|
	surface->pid = -1;
 | 
						|
 | 
						|
	surface->surface_commit_listener.notify =
 | 
						|
		weston_desktop_surface_surface_committed;
 | 
						|
	wl_signal_add(&surface->surface->commit_signal,
 | 
						|
		      &surface->surface_commit_listener);
 | 
						|
	surface->surface_destroy_listener.notify =
 | 
						|
		weston_desktop_surface_surface_destroyed;
 | 
						|
	wl_signal_add(&surface->surface->destroy_signal,
 | 
						|
		      &surface->surface_destroy_listener);
 | 
						|
 | 
						|
	wl_list_init(&surface->client_link);
 | 
						|
	wl_list_init(&surface->resource_list);
 | 
						|
	wl_list_init(&surface->children_list);
 | 
						|
	wl_list_init(&surface->children_link);
 | 
						|
	wl_list_init(&surface->view_list);
 | 
						|
	wl_list_init(&surface->grab_link);
 | 
						|
 | 
						|
	return surface;
 | 
						|
}
 | 
						|
 | 
						|
struct wl_resource *
 | 
						|
weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
 | 
						|
				    const struct wl_interface *interface,
 | 
						|
				    const void *implementation, uint32_t id,
 | 
						|
				    wl_resource_destroy_func_t destroy)
 | 
						|
{
 | 
						|
	struct wl_resource *client_resource =
 | 
						|
		weston_desktop_client_get_resource(surface->client);
 | 
						|
	struct wl_client *wl_client  =
 | 
						|
		weston_desktop_client_get_client(surface->client);
 | 
						|
	struct wl_resource *resource;
 | 
						|
 | 
						|
	resource = wl_resource_create(wl_client,
 | 
						|
				      interface,
 | 
						|
				      wl_resource_get_version(client_resource),
 | 
						|
				      id);
 | 
						|
	if (resource == NULL) {
 | 
						|
		wl_client_post_no_memory(wl_client);
 | 
						|
		weston_desktop_surface_destroy(surface);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	if (destroy == NULL)
 | 
						|
		destroy = weston_desktop_surface_resource_destroy;
 | 
						|
	wl_resource_set_implementation(resource, implementation, surface, destroy);
 | 
						|
	wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
 | 
						|
 | 
						|
	return resource;
 | 
						|
}
 | 
						|
 | 
						|
struct weston_desktop_surface *
 | 
						|
weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface =
 | 
						|
		wl_container_of(grab_link, surface, grab_link);
 | 
						|
 | 
						|
	return surface;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
weston_surface_is_desktop_surface(struct weston_surface *wsurface)
 | 
						|
{
 | 
						|
	return wsurface->committed == weston_desktop_surface_committed;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_desktop_surface *
 | 
						|
weston_surface_get_desktop_surface(struct weston_surface *wsurface)
 | 
						|
{
 | 
						|
	if (!weston_surface_is_desktop_surface(wsurface))
 | 
						|
		return NULL;
 | 
						|
	return wsurface->committed_private;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
 | 
						|
				     void *user_data)
 | 
						|
{
 | 
						|
	surface->user_data = user_data;
 | 
						|
}
 | 
						|
 | 
						|
static struct weston_desktop_view *
 | 
						|
weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct wl_client *wl_client=
 | 
						|
		weston_desktop_client_get_client(surface->client);
 | 
						|
	struct weston_desktop_view *view, *child_view;
 | 
						|
	struct weston_view *wview;
 | 
						|
	struct weston_desktop_surface *child;
 | 
						|
 | 
						|
	wview = weston_view_create(surface->surface);
 | 
						|
	if (wview == NULL) {
 | 
						|
		if (wl_client != NULL)
 | 
						|
			wl_client_post_no_memory(wl_client);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	view = zalloc(sizeof(struct weston_desktop_view));
 | 
						|
	if (view == NULL) {
 | 
						|
		if (wl_client != NULL)
 | 
						|
			wl_client_post_no_memory(wl_client);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	view->view = wview;
 | 
						|
	wl_list_init(&view->children_list);
 | 
						|
	wl_list_init(&view->children_link);
 | 
						|
	wl_list_insert(surface->view_list.prev, &view->link);
 | 
						|
 | 
						|
	wl_list_for_each(child, &surface->children_list, children_link) {
 | 
						|
		child_view =
 | 
						|
			weston_desktop_surface_create_desktop_view(child);
 | 
						|
		if (child_view == NULL) {
 | 
						|
			weston_desktop_view_destroy(view);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
 | 
						|
		child_view->parent = view;
 | 
						|
		wl_list_insert(view->children_list.prev,
 | 
						|
			       &child_view->children_link);
 | 
						|
	}
 | 
						|
 | 
						|
	return view;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_view *
 | 
						|
weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view;
 | 
						|
 | 
						|
	view = weston_desktop_surface_create_desktop_view(surface);
 | 
						|
	if (view == NULL)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	return view->view;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_unlink_view(struct weston_view *wview)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface;
 | 
						|
	struct weston_desktop_view *view;
 | 
						|
 | 
						|
	if (!weston_surface_is_desktop_surface(wview->surface))
 | 
						|
		return;
 | 
						|
 | 
						|
	surface = weston_surface_get_desktop_surface(wview->surface);
 | 
						|
	wl_list_for_each(view, &surface->view_list, link) {
 | 
						|
		if (view->view == wview) {
 | 
						|
			weston_desktop_view_destroy(view);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *child;
 | 
						|
	struct wl_list *link = &view->view->layer_link.link;
 | 
						|
 | 
						|
	wl_list_for_each_reverse(child, &view->children_list, children_link) {
 | 
						|
		struct weston_layer_entry *prev =
 | 
						|
			wl_container_of(link->prev, prev, link);
 | 
						|
 | 
						|
		if (prev == &child->view->layer_link)
 | 
						|
			continue;
 | 
						|
 | 
						|
		child->view->is_mapped = true;
 | 
						|
		weston_view_damage_below(child->view);
 | 
						|
		weston_view_geometry_dirty(child->view);
 | 
						|
		weston_layer_entry_remove(&child->view->layer_link);
 | 
						|
		weston_layer_entry_insert(prev, &child->view->layer_link);
 | 
						|
		weston_view_geometry_dirty(child->view);
 | 
						|
		weston_surface_damage(child->view->surface);
 | 
						|
		weston_view_update_transform(child->view);
 | 
						|
 | 
						|
		weston_desktop_view_propagate_layer(child);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view;
 | 
						|
 | 
						|
	wl_list_for_each(view, &surface->view_list, link)
 | 
						|
		weston_desktop_view_propagate_layer(view);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
 | 
						|
{
 | 
						|
	if (surface->implementation->set_activated != NULL)
 | 
						|
		surface->implementation->set_activated(surface,
 | 
						|
						       surface->implementation_data,
 | 
						|
						       activated);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
 | 
						|
{
 | 
						|
	if (surface->implementation->set_fullscreen != NULL)
 | 
						|
		surface->implementation->set_fullscreen(surface,
 | 
						|
							surface->implementation_data,
 | 
						|
							fullscreen);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
 | 
						|
{
 | 
						|
	if (surface->implementation->set_maximized != NULL)
 | 
						|
		surface->implementation->set_maximized(surface,
 | 
						|
						       surface->implementation_data,
 | 
						|
						       maximized);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
 | 
						|
{
 | 
						|
	if (surface->implementation->set_resizing != NULL)
 | 
						|
		surface->implementation->set_resizing(surface,
 | 
						|
						      surface->implementation_data,
 | 
						|
						      resizing);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
 | 
						|
{
 | 
						|
	if (surface->implementation->set_size != NULL)
 | 
						|
		surface->implementation->set_size(surface,
 | 
						|
						  surface->implementation_data,
 | 
						|
						  width, height);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void
 | 
						|
weston_desktop_surface_close(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->implementation->close != NULL)
 | 
						|
		surface->implementation->close(surface,
 | 
						|
					       surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
struct weston_desktop_surface *
 | 
						|
weston_desktop_surface_from_client_link(struct wl_list *link)
 | 
						|
{
 | 
						|
	struct weston_desktop_surface *surface;
 | 
						|
 | 
						|
	surface = wl_container_of(link, surface, client_link);
 | 
						|
	return surface;
 | 
						|
}
 | 
						|
 | 
						|
struct wl_list *
 | 
						|
weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return &surface->client_link;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
 | 
						|
					  const struct weston_desktop_surface_implementation *implementation)
 | 
						|
{
 | 
						|
	return surface->implementation == implementation;
 | 
						|
}
 | 
						|
 | 
						|
const struct weston_desktop_surface_implementation *
 | 
						|
weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->implementation;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->implementation_data;
 | 
						|
}
 | 
						|
 | 
						|
struct weston_desktop_surface *
 | 
						|
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->parent;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return !wl_list_empty(&surface->grab_link);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_desktop_client *
 | 
						|
weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->client;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT void *
 | 
						|
weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->user_data;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_surface *
 | 
						|
weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->surface;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const char *
 | 
						|
weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->title;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const char *
 | 
						|
weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	return surface->app_id;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT pid_t
 | 
						|
weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	pid_t pid;
 | 
						|
 | 
						|
	if (surface->pid != -1) {
 | 
						|
		pid = surface->pid;
 | 
						|
	} else {
 | 
						|
		struct weston_desktop_client *client =
 | 
						|
			weston_desktop_surface_get_client(surface);
 | 
						|
		struct wl_client *wl_client =
 | 
						|
			weston_desktop_client_get_client(client);
 | 
						|
 | 
						|
		/* wl_client should always be valid, because only in the
 | 
						|
		 * xwayland case it wouldn't be, but in that case we won't
 | 
						|
		 * reach here, as the pid is initialized to 0. */
 | 
						|
		assert(wl_client);
 | 
						|
		wl_client_get_credentials(wl_client, &pid, NULL, NULL);
 | 
						|
	}
 | 
						|
	return pid;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->implementation->get_activated == NULL)
 | 
						|
		return false;
 | 
						|
	return surface->implementation->get_activated(surface,
 | 
						|
						      surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->implementation->get_resizing == NULL)
 | 
						|
		return false;
 | 
						|
	return surface->implementation->get_resizing(surface,
 | 
						|
						     surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->implementation->get_maximized == NULL)
 | 
						|
		return false;
 | 
						|
	return surface->implementation->get_maximized(surface,
 | 
						|
						      surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->implementation->get_fullscreen == NULL)
 | 
						|
		return false;
 | 
						|
	return surface->implementation->get_fullscreen(surface,
 | 
						|
						       surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_geometry
 | 
						|
weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	if (surface->has_geometry)
 | 
						|
		return surface->geometry;
 | 
						|
	return weston_surface_get_bounding_box(surface->surface);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_size
 | 
						|
weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_size size = { 0, 0 };
 | 
						|
 | 
						|
	if (surface->implementation->get_max_size == NULL)
 | 
						|
		return size;
 | 
						|
	return surface->implementation->get_max_size(surface,
 | 
						|
						     surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT struct weston_size
 | 
						|
weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_size size = { 0, 0 };
 | 
						|
 | 
						|
	if (surface->implementation->get_min_size == NULL)
 | 
						|
		return size;
 | 
						|
	return surface->implementation->get_min_size(surface,
 | 
						|
						     surface->implementation_data);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
 | 
						|
				 const char *title)
 | 
						|
{
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	tmp = strdup(title);
 | 
						|
	if (tmp == NULL)
 | 
						|
		return;
 | 
						|
 | 
						|
	free(surface->title);
 | 
						|
	surface->title = tmp;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
 | 
						|
				  const char *app_id)
 | 
						|
{
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	tmp = strdup(app_id);
 | 
						|
	if (tmp == NULL)
 | 
						|
		return;
 | 
						|
 | 
						|
	free(surface->app_id);
 | 
						|
	surface->app_id = tmp;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_set_pid(struct weston_desktop_surface *surface,
 | 
						|
			       pid_t pid)
 | 
						|
{
 | 
						|
	surface->pid = pid;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_set_geometry(struct weston_desktop_surface *surface,
 | 
						|
				    struct weston_geometry geometry)
 | 
						|
{
 | 
						|
	surface->has_geometry = true;
 | 
						|
	surface->geometry = geometry;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_set_relative_to(struct weston_desktop_surface *surface,
 | 
						|
				       struct weston_desktop_surface *parent,
 | 
						|
				       int32_t x, int32_t y, bool use_geometry)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view, *parent_view;
 | 
						|
	struct wl_list *link, *tmp;
 | 
						|
 | 
						|
	assert(parent);
 | 
						|
 | 
						|
	surface->position.x = x;
 | 
						|
	surface->position.y = y;
 | 
						|
	surface->use_geometry = use_geometry;
 | 
						|
 | 
						|
	if (surface->parent == parent)
 | 
						|
		return;
 | 
						|
 | 
						|
	surface->parent = parent;
 | 
						|
	wl_list_remove(&surface->children_link);
 | 
						|
	wl_list_insert(surface->parent->children_list.prev,
 | 
						|
		       &surface->children_link);
 | 
						|
 | 
						|
	link = surface->view_list.next;
 | 
						|
	tmp = link->next;
 | 
						|
	wl_list_for_each(parent_view, &parent->view_list, link) {
 | 
						|
		if (link == &surface->view_list) {
 | 
						|
			view = weston_desktop_surface_create_desktop_view(surface);
 | 
						|
			if (view == NULL)
 | 
						|
				return;
 | 
						|
			tmp = &surface->view_list;
 | 
						|
		} else {
 | 
						|
			view = wl_container_of(link, view, link);
 | 
						|
			wl_list_remove(&view->children_link);
 | 
						|
		}
 | 
						|
 | 
						|
		view->parent = parent_view;
 | 
						|
		wl_list_insert(parent_view->children_list.prev,
 | 
						|
			       &view->children_link);
 | 
						|
		weston_desktop_view_propagate_layer(view);
 | 
						|
 | 
						|
		link = tmp;
 | 
						|
		tmp = link->next;
 | 
						|
	}
 | 
						|
	for (; link != &surface->view_list; link = tmp, tmp = link->next) {
 | 
						|
		view = wl_container_of(link, view, link);
 | 
						|
		weston_desktop_view_destroy(view);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_unset_relative_to(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view, *tmp;
 | 
						|
 | 
						|
	if (surface->parent == NULL)
 | 
						|
		return;
 | 
						|
 | 
						|
	surface->parent = NULL;
 | 
						|
	wl_list_remove(&surface->children_link);
 | 
						|
	wl_list_init(&surface->children_link);
 | 
						|
 | 
						|
	wl_list_for_each_safe(view, tmp, &surface->view_list, link)
 | 
						|
		weston_desktop_view_destroy(view);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_popup_grab(struct weston_desktop_surface *surface,
 | 
						|
				  struct weston_desktop_seat *seat,
 | 
						|
				  uint32_t serial)
 | 
						|
{
 | 
						|
	struct wl_client *wl_client =
 | 
						|
		weston_desktop_client_get_client(surface->client);
 | 
						|
	if (weston_desktop_seat_popup_grab_start(seat, wl_client, serial))
 | 
						|
		weston_desktop_seat_popup_grab_add_surface(seat, &surface->grab_link);
 | 
						|
	else
 | 
						|
		weston_desktop_surface_popup_dismiss(surface);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_popup_ungrab(struct weston_desktop_surface *surface,
 | 
						|
				   struct weston_desktop_seat *seat)
 | 
						|
{
 | 
						|
	weston_desktop_seat_popup_grab_remove_surface(seat, &surface->grab_link);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
weston_desktop_surface_popup_dismiss(struct weston_desktop_surface *surface)
 | 
						|
{
 | 
						|
	struct weston_desktop_view *view, *tmp;
 | 
						|
 | 
						|
	wl_list_for_each_safe(view, tmp, &surface->view_list, link)
 | 
						|
		weston_desktop_view_destroy(view);
 | 
						|
	wl_list_remove(&surface->grab_link);
 | 
						|
	wl_list_init(&surface->grab_link);
 | 
						|
	weston_desktop_surface_close(surface);
 | 
						|
}
 | 
						|
 |