diff options
Diffstat (limited to 'shell/shell-helper.c')
| -rw-r--r-- | shell/shell-helper.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/shell/shell-helper.c b/shell/shell-helper.c new file mode 100644 index 0000000..71e9b6f --- /dev/null +++ b/shell/shell-helper.c @@ -0,0 +1,255 @@ +#include <stdio.h> +#include <assert.h> + +#include <weston/compositor.h> + +#include "shell-helper-server-protocol.h" + +struct shell_helper { + struct weston_compositor *compositor; + + struct wl_listener destroy_listener; + + struct wl_list slide_list; +}; + +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); +} + +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 +}; + +struct slide { + struct weston_surface *surface; + struct weston_view *view; + int x; + int y; + + enum SlideState state; + enum SlideRequest request; + + struct weston_transform transform; + + struct wl_list link; +}; + +static void slide_back(struct slide *slide); + +static void +slide_done_cb(struct weston_view_animation *animation, void *data) +{ + struct slide *slide = data; + + slide->state = SLIDE_STATE_OUT; + + wl_list_insert(&slide->view->transform.position.link, + &slide->transform.link); + weston_matrix_init(&slide->transform.matrix); + weston_matrix_translate(&slide->transform.matrix, + slide->x, + slide->y, + 0); + + weston_view_geometry_dirty(slide->view); + weston_compositor_schedule_repaint(slide->surface->compositor); + + if (slide->request == SLIDE_REQUEST_BACK) { + slide->request = SLIDE_REQUEST_NONE; + slide_back(slide); + } +} + +static void +slide_out(struct slide *slide) +{ + assert(slide->state == SLIDE_STATE_NONE || slide->state == SLIDE_STATE_BACK); + + slide->state = SLIDE_STATE_SLIDING_OUT; + + weston_move_scale_run(slide->view, slide->x, slide->y, + 1.0, 1.0, 0, + slide_done_cb, slide); +} + +static void +slide_back_done_cb(struct weston_view_animation *animation, void *data) +{ + struct slide *slide = data; + + slide->state = SLIDE_STATE_BACK; + + wl_list_remove(&slide->transform.link); + weston_view_geometry_dirty(slide->view); + + if (slide->request == SLIDE_REQUEST_OUT) { + slide->request = SLIDE_REQUEST_NONE; + slide_out(slide); + } else { + wl_list_remove(&slide->link); + free(slide); + } +} + +static void +slide_back(struct slide *slide) +{ + assert(slide->state == SLIDE_STATE_OUT); + + slide->state = SLIDE_STATE_SLIDING_BACK; + + weston_move_scale_run(slide->view, -slide->x, -slide->y, + 1.0, 1.0, 0, + slide_back_done_cb, slide); +} + +static void +shell_helper_slide_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; + struct slide *slide; + + wl_list_for_each(slide, &helper->slide_list, link) { + if (slide->surface == surface) { + if (slide->state == SLIDE_STATE_SLIDING_BACK) + slide->request = SLIDE_REQUEST_OUT; + return; + } + } + + view = container_of(surface->views.next, struct weston_view, surface_link); + + if (!view) + return; + + slide = malloc(sizeof *slide); + if (!slide) + return; + + slide->surface = surface; + slide->view = view; + slide->x = x; + slide->y = y; + + slide->state = SLIDE_STATE_NONE; + slide->request = SLIDE_REQUEST_NONE; + + wl_list_insert(&helper->slide_list, + &slide->link); + + slide_out(slide); +} + +static void +shell_helper_slide_surface_back(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; + int found = 0; + struct slide *slide; + + wl_list_for_each(slide, &helper->slide_list, link) { + if (slide->surface == surface) { + found = 1; + break; + } + } + + if (!found || slide->state == SLIDE_STATE_SLIDING_BACK) + return; + + if (slide->state == SLIDE_STATE_SLIDING_OUT) + slide->request = SLIDE_REQUEST_BACK; + else + slide_back(slide); +} + +static const struct shell_helper_interface helper_implementation = { + shell_helper_move_surface, + shell_helper_slide_surface, + shell_helper_slide_surface_back +}; + +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; + + wl_list_init(&helper->slide_list); + + 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; +} |
