diff options
Diffstat (limited to 'overlay-plugin.c')
-rw-r--r-- | overlay-plugin.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/overlay-plugin.c b/overlay-plugin.c new file mode 100644 index 0000000..35318a4 --- /dev/null +++ b/overlay-plugin.c @@ -0,0 +1,279 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <linux/input.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/uio.h> + +#include "weston/compositor.h" +#include "overlay-server-protocol.h" + +struct overlay { + struct weston_compositor *compositor; + struct wl_global *global; + struct wl_resource *resource; + struct wl_listener destroy_listener; + struct wl_listener surface_destroy_listener; + struct weston_surface *surface; + struct weston_binding *binding; + struct weston_layer layer; + struct wl_seat *seat; + struct wl_pointer_grab grab; + struct weston_output *output; +}; + +static void +handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct overlay *overlay = + container_of(listener, struct overlay, + surface_destroy_listener); + + overlay->surface = NULL; +} + +static void +overlay_close(struct overlay *overlay) +{ + overlay_send_done(overlay->resource); + wl_pointer_end_grab(overlay->grab.pointer); +} + +static void +overlay_grab_focus(struct wl_pointer_grab *grab, + struct wl_surface *surface, + wl_fixed_t x, wl_fixed_t y) +{ + struct wl_pointer *pointer = grab->pointer; + struct overlay *overlay = container_of(grab, struct overlay, grab); + + if (surface == &overlay->surface->surface) { + wl_pointer_set_focus(pointer, surface, x, y); + grab->focus = surface; + } else { + wl_pointer_set_focus(pointer, NULL, + wl_fixed_from_int(0), + wl_fixed_from_int(0)); + grab->focus = NULL; + } +} + +static void +overlay_grab_motion(struct wl_pointer_grab *grab, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + struct wl_resource *resource; + + resource = grab->pointer->focus_resource; + if (resource) + wl_pointer_send_motion(resource, time, sx, sy); +} + +static void +overlay_grab_button(struct wl_pointer_grab *grab, + uint32_t time, uint32_t button, uint32_t state_w) +{ + struct wl_resource *resource; + struct overlay *overlay = container_of(grab, struct overlay, grab); + struct wl_display *display; + enum wl_pointer_button_state state = state_w; + uint32_t serial; + + resource = grab->pointer->focus_resource; + if (resource) { + display = wl_client_get_display(resource->client); + serial = wl_display_get_serial(display); + wl_pointer_send_button(resource, serial, time, button, state); + } else { + overlay_close(overlay); + } +} + +static const struct wl_pointer_grab_interface overlay_grab_interface = { + overlay_grab_focus, + overlay_grab_motion, + overlay_grab_button, +}; + +static struct weston_output * +get_output_for_pointer(struct overlay *overlay) +{ + struct weston_output *output; + int x, y; + + x = wl_fixed_to_int(overlay->seat->pointer->x); + y = wl_fixed_to_int(overlay->seat->pointer->y); + + wl_list_for_each(output, &overlay->compositor->output_list, link) { + if (pixman_region32_contains_point(&output->region, + x, y, NULL)) + return output; + } + + return NULL; +} + +static void +overlay_configure(struct weston_surface *surface, int32_t sx, int32_t sy) +{ + struct overlay *overlay = surface->private; + struct weston_output *output; + int width, height; + + if (wl_list_empty(&surface->layer_link)) { + wl_list_insert(&overlay->layer.surface_list, + &surface->layer_link); + + wl_keyboard_set_focus(overlay->seat->keyboard, + &surface->surface); + + overlay->grab.interface = &overlay_grab_interface; + wl_pointer_start_grab(overlay->seat->pointer, &overlay->grab); + overlay->output = get_output_for_pointer(overlay); + } + + output = overlay->output; + width = surface->buffer_ref.buffer->width; + height = surface->buffer_ref.buffer->height; + + surface->geometry.x = output->x + (output->width - width) / 2; + surface->geometry.y = output->y + (output->height - height) / 2; + surface->geometry.width = surface->buffer_ref.buffer->width; + surface->geometry.height = surface->buffer_ref.buffer->height; + surface->geometry.dirty = 1; + + if (!weston_surface_is_mapped(surface)) + weston_surface_update_transform(surface); +} + +static void +overlay_handle_surface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct overlay *overlay = resource->data; + + overlay->surface = surface_resource->data; + overlay->surface_destroy_listener.notify = handle_surface_destroy; + wl_signal_add(&surface_resource->destroy_signal, + &overlay->surface_destroy_listener); + + overlay->surface->configure = overlay_configure; + overlay->surface->private = overlay; +} + +static void +overlay_handle_close(struct wl_client *client, + struct wl_resource *resource) +{ + struct overlay *overlay = resource->data; + + overlay_close(overlay); +} + +static const struct overlay_interface overlay_implementation = { + overlay_handle_surface, + overlay_handle_close +}; + +static void +overlay_binding(struct wl_seat *_seat, + uint32_t time, uint32_t key, void *data) +{ + struct overlay *overlay = data; + + fprintf(stderr, "overlay binding pressed\n"); + + overlay->seat = _seat; + if (overlay->resource) + overlay_send_activate(overlay->resource); +} + +static void +handle_overlay_destroy(struct wl_resource *resource) +{ + struct overlay *overlay = resource->data; + + overlay->resource = NULL; + free(resource); +} + +static void +bind_overlay(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct overlay *overlay = data; + + fprintf(stderr, "client %p binds to overlay global\n", client); + + overlay->resource = + wl_client_add_object(client, &overlay_interface, + &overlay_implementation, id, overlay); + overlay->resource->destroy = handle_overlay_destroy; +} + +static void +overlay_destroy(struct wl_listener *listener, void *data) +{ + struct overlay *overlay = + container_of(listener, struct overlay, destroy_listener); + + wl_display_remove_global(overlay->compositor->wl_display, + overlay->global); + free(overlay); +} + +int +module_init(struct weston_compositor *compositor); + +WL_EXPORT int +module_init(struct weston_compositor *compositor) +{ + struct overlay *overlay; + + overlay = malloc(sizeof *overlay); + if (overlay == NULL) + return -1; + + overlay->compositor = compositor; + overlay->global = wl_display_add_global(compositor->wl_display, + &overlay_interface, + overlay, bind_overlay); + + overlay->destroy_listener.notify = overlay_destroy; + wl_signal_add(&compositor->destroy_signal, &overlay->destroy_listener); + + overlay->binding = + weston_compositor_add_key_binding(compositor, KEY_SPACE, + MODIFIER_SUPER, + overlay_binding, overlay); + + weston_layer_init(&overlay->layer, &compositor->cursor_layer.link); + + weston_log("overlay initialized\n"); + + return 0; +} |