commit 9b3ddc49f9869eb04743efb2f57812d9f4810a03
parent 627e6427e56fa864a3228003e1b81dc2176c760e
Author: Michael Forney <mforney@mforney.org>
Date: Sat, 18 Jan 2014 03:48:33 -0800
pointer: Implement cursor handling
Diffstat:
2 files changed, 134 insertions(+), 27 deletions(-)
diff --git a/libswc/pointer.c b/libswc/pointer.c
@@ -1,10 +1,13 @@
#include "pointer.h"
#include "event.h"
+#include "internal.h"
+#include "screen.h"
+#include "shm.h"
#include "util.h"
-#include "view.h"
#include <stdio.h>
#include <assert.h>
+#include <wld/wld.h>
static void enter(struct swc_input_focus_handler * handler,
struct wl_resource * resource, struct swc_surface * surface)
@@ -49,12 +52,108 @@ static void handle_cursor_surface_destroy(struct wl_listener * listener,
struct swc_pointer * pointer = CONTAINER_OF(listener, typeof(*pointer),
cursor.destroy_listener);
- pointer->cursor.surface = NULL;
+ swc_view_attach(&pointer->cursor.view, NULL);
+}
+
+static bool update(struct swc_view * view)
+{
+ return true;
+}
+
+static bool attach(struct swc_view * view, struct swc_buffer * buffer)
+{
+ struct swc_pointer * pointer
+ = CONTAINER_OF(view, typeof(*pointer), cursor.view);
+ struct swc_surface * surface = pointer->cursor.surface;
+
+ if (surface && !pixman_region32_not_empty(&surface->state.damage))
+ return true;
+
+ wld_set_target_buffer(swc.shm->renderer, pointer->cursor.buffer.wld);
+ wld_fill_rectangle(swc.shm->renderer, 0x00000000, 0, 0, 64, 64);
+ wld_copy_rectangle(swc.shm->renderer, buffer->wld, 0, 0, 0, 0,
+ buffer->wld->width, buffer->wld->height);
+ wld_flush(swc.shm->renderer);
+
+ if (surface)
+ pixman_region32_clear(&surface->state.damage);
+
+ /* TODO: Send an early release to the buffer */
+
+ return true;
+}
+
+static bool move(struct swc_view * view, int32_t x, int32_t y)
+{
+ return true;
+}
+
+static const struct swc_view_impl view_impl = {
+ .update = &update,
+ .attach = &attach,
+ .move = &move,
+};
+
+static void handle_view_event(struct wl_listener * listener, void * data)
+{
+ struct swc_pointer * pointer
+ = CONTAINER_OF(listener, typeof(*pointer), cursor.view_listener);
+ struct swc_event * event = data;
+ struct swc_view_event_data * event_data = event->data;
+ struct swc_view * view = event_data->view;
+
+ switch (event->type)
+ {
+ case SWC_VIEW_EVENT_MOVED:
+ {
+ struct swc_screen_internal * screen;
+
+ wl_list_for_each(screen, &swc.screens, link)
+ {
+ if (view->screens & swc_screen_mask(screen))
+ {
+ struct swc_pointer * pointer
+ = CONTAINER_OF(view, typeof(*pointer), cursor.view);
+
+ swc_view_move(&screen->planes.cursor.view,
+ view->geometry.x - screen->base.geometry.x,
+ view->geometry.y - screen->base.geometry.y);
+
+ if (!screen->planes.cursor.view.buffer)
+ {
+ swc_view_attach(&screen->planes.cursor.view,
+ &pointer->cursor.buffer);
+ }
+ }
+ else if (screen->planes.cursor.view.buffer)
+ swc_view_attach(&screen->planes.cursor.view, NULL);
+ }
+ break;
+ }
+ case SWC_VIEW_EVENT_SCREENS_CHANGED:
+ {
+ struct swc_screen_internal * screen;
+ uint32_t entered = event_data->screens_changed.entered,
+ left = event_data->screens_changed.left;
+
+ wl_list_for_each(screen, &swc.screens, link)
+ {
+ if (entered & swc_screen_mask(screen))
+ {
+ swc_view_attach(&screen->planes.cursor.view,
+ &pointer->cursor.buffer);
+ }
+ else if (left & swc_screen_mask(screen))
+ swc_view_attach(&screen->planes.cursor.view, NULL);
+ }
+ break;
+ }
+ }
}
bool swc_pointer_initialize(struct swc_pointer * pointer)
{
- wl_signal_init(&pointer->event_signal);
+ struct wld_buffer * buffer;
pointer->x = wl_fixed_from_int(0);
pointer->y = wl_fixed_from_int(0);
@@ -62,7 +161,18 @@ bool swc_pointer_initialize(struct swc_pointer * pointer)
pointer->focus_handler.enter = &enter;
pointer->focus_handler.leave = &leave;
+ swc_view_initialize(&pointer->cursor.view, &view_impl);
+ pointer->cursor.view_listener.notify = &handle_view_event;
+ wl_signal_add(&pointer->cursor.view.event_signal,
+ &pointer->cursor.view_listener);
+ pointer->cursor.surface = NULL;
pointer->cursor.destroy_listener.notify = &handle_cursor_surface_destroy;
+ buffer = wld_create_buffer(swc.drm->context, 64, 64, WLD_FORMAT_ARGB8888);
+
+ if (!buffer)
+ return false;
+
+ swc_buffer_initialize(&pointer->cursor.buffer, buffer);
swc_input_focus_initialize(&pointer->focus, &pointer->focus_handler);
pixman_region32_init(&pointer->region);
@@ -124,29 +234,25 @@ static void set_cursor(struct wl_client * client,
{
struct swc_pointer * pointer = wl_resource_get_user_data(resource);
struct swc_surface * surface;
- struct swc_pointer_event_data data;
-
- data.old = pointer->cursor.surface;
if (pointer->cursor.surface)
wl_list_remove(&pointer->cursor.destroy_listener.link);
surface = surface_resource ? wl_resource_get_user_data(surface_resource)
: NULL;
+ pointer->cursor.surface = surface;
+ pointer->cursor.hotspot.x = hotspot_x;
+ pointer->cursor.hotspot.y = hotspot_y;
if (surface)
{
+ swc_surface_set_view(surface, &pointer->cursor.view);
wl_resource_add_destroy_listener(surface->resource,
&pointer->cursor.destroy_listener);
+ swc_view_move(&pointer->cursor.view,
+ wl_fixed_to_int(pointer->x) - hotspot_x,
+ wl_fixed_to_int(pointer->y) - hotspot_y);
}
-
- pointer->cursor.surface = surface;
- pointer->cursor.hotspot_x = hotspot_x;
- pointer->cursor.hotspot_y = hotspot_y;
-
- data.new = pointer->cursor.surface;
-
- swc_send_event(&pointer->event_signal, SWC_POINTER_CURSOR_CHANGED, &data);
}
static struct wl_pointer_interface pointer_implementation = {
@@ -224,5 +330,9 @@ void swc_pointer_handle_relative_motion
wl_pointer_send_motion(pointer->focus.resource, time,
surface_x, surface_y);
}
+
+ swc_view_move(&pointer->cursor.view,
+ wl_fixed_to_int(pointer->x) - pointer->cursor.hotspot.x,
+ wl_fixed_to_int(pointer->y) - pointer->cursor.hotspot.y);
}
diff --git a/libswc/pointer.h b/libswc/pointer.h
@@ -1,8 +1,10 @@
#ifndef SWC_POINTER_H
#define SWC_POINTER_H
+#include "buffer.h"
#include "input_focus.h"
#include "surface.h"
+#include "view.h"
#include <wayland-server.h>
#include <pixman.h>
@@ -19,28 +21,23 @@ struct swc_pointer_handler
enum wl_pointer_axis axis, wl_fixed_t amount);
};
-enum swc_pointer_event_type
-{
- SWC_POINTER_CURSOR_CHANGED
-};
-
-struct swc_pointer_event_data
-{
- struct swc_surface * old, * new;
-};
-
struct swc_pointer
{
struct swc_input_focus focus;
struct swc_input_focus_handler focus_handler;
- struct wl_signal event_signal;
-
struct
{
+ struct swc_view view;
+ struct wl_listener view_listener;
struct swc_surface * surface;
- int32_t hotspot_x, hotspot_y;
struct wl_listener destroy_listener;
+ struct swc_buffer buffer;
+
+ struct
+ {
+ int32_t x, y;
+ } hotspot;
} cursor;
struct swc_pointer_handler * handler;