/* * Copyright (C) 2014 Collabora Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA * * Author: Jonny Lamb */ #include #include #include #include "shell-helper-server-protocol.h" struct shell_helper { struct weston_compositor *compositor; struct wl_listener destroy_listener; struct weston_layer *panel_layer; }; static void shell_helper_move_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, int32_t x, int32_t y) { struct shell_helper *helper = wl_resource_get_user_data(resource); struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct weston_view *view; view = container_of(surface->views.next, struct weston_view, surface_link); if (!view) return; weston_view_set_position(view, x, y); weston_view_update_transform(view); } static void configure_surface(struct weston_surface *es, int32_t sx, int32_t sy) { struct weston_view *existing_view = es->configure_private; struct weston_view *new_view; new_view = container_of(es->views.next, struct weston_view, surface_link); if (wl_list_empty(&new_view->layer_link)) { /* be sure to append to the list, not insert */ wl_list_insert(&existing_view->layer_link, &new_view->layer_link); weston_compositor_schedule_repaint(es->compositor); } } static void shell_helper_add_surface_to_layer(struct wl_client *client, struct wl_resource *resource, struct wl_resource *new_surface_resource, struct wl_resource *existing_surface_resource) { struct shell_helper *helper = wl_resource_get_user_data(resource); struct weston_surface *new_surface = wl_resource_get_user_data(new_surface_resource); struct weston_surface *existing_surface = wl_resource_get_user_data(existing_surface_resource); struct weston_view *new_view, *existing_view, *next; struct wl_layer *layer; if (new_surface->configure) { wl_resource_post_error(new_surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "surface role already assigned"); return; } existing_view = container_of(existing_surface->views.next, struct weston_view, surface_link); wl_list_for_each_safe(new_view, next, &new_surface->views, surface_link) weston_view_destroy(new_view); new_view = weston_view_create(new_surface); new_surface->configure = configure_surface; new_surface->configure_private = existing_view; new_surface->output = existing_view->output; } static void configure_panel(struct weston_surface *es, int32_t sx, int32_t sy) { struct shell_helper *helper = es->configure_private; struct weston_view *view; view = container_of(es->views.next, struct weston_view, surface_link); if (wl_list_empty(&view->layer_link)) { wl_list_insert(&helper->panel_layer->view_list, &view->layer_link); weston_compositor_schedule_repaint(es->compositor); } } static void shell_helper_set_panel(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource) { struct shell_helper *helper = wl_resource_get_user_data(resource); struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct weston_view *view = container_of(surface->views.next, struct weston_view, surface_link); /* we need to save the panel's layer so we can use it later on, but * it hasn't yet been defined because the original surface configure * function hasn't yet been calld. if we call it here we will have * access to the layer. */ surface->configure(surface, 0, 0); helper->panel_layer = container_of(&view->layer_link, struct weston_layer, view_list); /* set new configure functions that only ensure the surface is in the * correct layer. */ surface->configure = configure_panel; surface->configure_private = helper; } enum SlideState { SLIDE_STATE_NONE, SLIDE_STATE_SLIDING_OUT, SLIDE_STATE_OUT, SLIDE_STATE_SLIDING_BACK, SLIDE_STATE_BACK }; enum SlideRequest { SLIDE_REQUEST_NONE, SLIDE_REQUEST_OUT, SLIDE_REQUEST_BACK }; static const struct shell_helper_interface helper_implementation = { shell_helper_move_surface, shell_helper_add_surface_to_layer, shell_helper_set_panel, }; static void bind_helper(struct wl_client *client, void *data, uint32_t version, uint32_t id) { struct shell_helper *helper = data; struct wl_resource *resource; resource = wl_resource_create(client, &shell_helper_interface, 1, id); if (resource) wl_resource_set_implementation(resource, &helper_implementation, helper, NULL); } static void helper_destroy(struct wl_listener *listener, void *data) { struct shell_helper *helper = container_of(listener, struct shell_helper, destroy_listener); free(helper); } WL_EXPORT int module_init(struct weston_compositor *ec, int *argc, char *argv[]) { struct shell_helper *helper; helper = zalloc(sizeof *helper); if (helper == NULL) return -1; helper->compositor = ec; helper->panel_layer = NULL; helper->destroy_listener.notify = helper_destroy; wl_signal_add(&ec->destroy_signal, &helper->destroy_listener); if (wl_global_create(ec->wl_display, &shell_helper_interface, 1, helper, bind_helper) == NULL) return -1; return 0; }