commit 5b1678fb06b19d8465846d93e07db74f813335ad
parent 28f049f8c0e24edffdd6d08750e900f3111d8feb
Author: Michael Forney <mforney@mforney.org>
Date: Sat, 16 Aug 2014 12:40:25 -0700
view: Use a view_handler structure instead of swc_event
Diffstat:
6 files changed, 140 insertions(+), 165 deletions(-)
diff --git a/libswc/compositor.c b/libswc/compositor.c
@@ -57,7 +57,7 @@ struct target
struct wld_surface * surface;
struct wld_buffer * next_buffer, * current_buffer;
struct view * view;
- struct wl_listener view_listener;
+ struct view_handler view_handler;
uint32_t mask;
struct wl_listener screen_destroy_listener;
@@ -112,40 +112,34 @@ static struct target * target_get(struct screen * screen)
: NULL;
}
-static void handle_screen_view_event(struct wl_listener * listener, void * data)
+static void handle_screen_frame(struct view_handler * handler, uint32_t time)
{
- struct swc_event * event = data;
- struct view_event_data * event_data = event->data;
- struct target * target = wl_container_of(listener, target, view_listener);
-
- switch (event->type)
- {
- case VIEW_EVENT_FRAME:
- {
- struct compositor_view * view;
+ struct target * target = wl_container_of(handler, target, view_handler);
+ struct compositor_view * view;
- compositor.pending_flips &= ~target->mask;
+ compositor.pending_flips &= ~target->mask;
- wl_list_for_each(view, &compositor.views, link)
- {
- if (view->base.screens & target->mask)
- view_frame(&view->base, event_data->frame.time);
- }
+ wl_list_for_each(view, &compositor.views, link)
+ {
+ if (view->base.screens & target->mask)
+ view_frame(&view->base, time);
+ }
- if (target->current_buffer)
- wld_surface_release(target->surface, target->current_buffer);
+ if (target->current_buffer)
+ wld_surface_release(target->surface, target->current_buffer);
- target->current_buffer = target->next_buffer;
+ target->current_buffer = target->next_buffer;
- /* If we had scheduled updates that couldn't run because we were
- * waiting on a page flip, run them now. */
- if (compositor.scheduled_updates && !compositor.updating)
- perform_update(NULL);
- break;
- }
- }
+ /* If we had scheduled updates that couldn't run because we were
+ * waiting on a page flip, run them now. */
+ if (compositor.scheduled_updates && !compositor.updating)
+ perform_update(NULL);
}
+static const struct view_handler_impl screen_view_handler = {
+ .frame = &handle_screen_frame,
+};
+
static int target_swap_buffers(struct target * target)
{
target->next_buffer = wld_surface_take(target->surface);
@@ -169,8 +163,8 @@ static struct target * target_new(struct screen * screen)
goto error1;
target->view = &screen->planes.framebuffer.view;
- target->view_listener.notify = &handle_screen_view_event;
- wl_signal_add(&target->view->event_signal, &target->view_listener);
+ target->view_handler.impl = &screen_view_handler;
+ wl_list_insert(&target->view->handlers, &target->view_handler.link);
target->current_buffer = NULL;
target->mask = screen_mask(screen);
target_swap_buffers(target);
diff --git a/libswc/panel.c b/libswc/panel.c
@@ -23,7 +23,6 @@
#include "panel.h"
#include "compositor.h"
-#include "event.h"
#include "internal.h"
#include "keyboard.h"
#include "output.h"
@@ -44,7 +43,7 @@ struct panel
struct swc_surface * surface;
struct wl_listener surface_destroy_listener;
struct compositor_view * view;
- struct wl_listener view_listener;
+ struct view_handler view_handler;
struct screen * screen;
struct screen_modifier modifier;
uint32_t edge;
@@ -107,7 +106,7 @@ static void dock(struct wl_client * client, struct wl_resource * resource,
}
if (panel->docked)
- wl_list_remove(&panel->view_listener.link);
+ wl_list_remove(&panel->view_handler.link);
if (panel->screen && screen_changed)
{
@@ -128,7 +127,7 @@ static void dock(struct wl_client * client, struct wl_resource * resource,
update_position(panel);
compositor_view_show(panel->view);
- wl_signal_add(&panel->view->base.event_signal, &panel->view_listener);
+ wl_list_insert(&panel->view->base.handlers, &panel->view_handler.link);
wl_list_insert(&screen->modifiers, &panel->modifier.link);
if (focus)
@@ -165,6 +164,17 @@ static const struct swc_panel_interface panel_implementation = {
.set_strut = &set_strut
};
+static void handle_resize(struct view_handler * handler)
+{
+ struct panel * panel = wl_container_of(handler, panel, view_handler);
+
+ update_position(panel);
+}
+
+static const struct view_handler_impl view_handler_impl = {
+ .resize = &handle_resize,
+};
+
static void modify(struct screen_modifier * modifier,
const struct swc_rectangle * geometry,
pixman_region32_t * usable)
@@ -211,7 +221,6 @@ static void destroy_panel(struct wl_resource * resource)
if (panel->docked)
{
- wl_list_remove(&panel->view_listener.link);
wl_list_remove(&panel->modifier.link);
screen_update_usable_geometry(panel->screen);
compositor_view_destroy(panel->view);
@@ -220,19 +229,6 @@ static void destroy_panel(struct wl_resource * resource)
free(panel);
}
-static void handle_view_event(struct wl_listener * listener, void * data)
-{
- struct panel * panel = wl_container_of(listener, panel, view_listener);
- struct swc_event * event = data;
-
- switch (event->type)
- {
- case VIEW_EVENT_RESIZED:
- update_position(panel);
- break;
- }
-}
-
static void handle_surface_destroy(struct wl_listener * listener, void * data)
{
struct panel * panel
@@ -261,7 +257,7 @@ struct panel * panel_new(struct wl_client * client, uint32_t id,
panel->surface = surface;
panel->surface_destroy_listener.notify = &handle_surface_destroy;
- panel->view_listener.notify = &handle_view_event;
+ panel->view_handler.impl = &view_handler_impl;
panel->modifier.modify = &modify;
panel->screen = NULL;
panel->offset = 0;
diff --git a/libswc/surface.c b/libswc/surface.c
@@ -107,6 +107,60 @@ static void state_set_buffer(struct swc_surface_state * state,
state->buffer_resource = resource;
}
+static void handle_frame(struct view_handler * handler, uint32_t time)
+{
+ struct swc_surface * surface
+ = wl_container_of(handler, surface, view_handler);
+ struct wl_resource * resource, * tmp;
+
+ wl_list_for_each_safe(resource, tmp,
+ &surface->state.frame_callbacks, link)
+ {
+ wl_callback_send_done(resource, time);
+ wl_resource_destroy(resource);
+ }
+
+ wl_list_init(&surface->state.frame_callbacks);
+}
+
+static void handle_screens(struct view_handler * handler,
+ uint32_t entered, uint32_t left)
+{
+ struct swc_surface * surface
+ = wl_container_of(handler, surface, view_handler);
+ struct screen * screen;
+ struct swc_output * output;
+ struct wl_client * client;
+ struct wl_resource * resource;
+
+ client = wl_resource_get_client(surface->resource);
+
+ wl_list_for_each(screen, &swc.screens, link)
+ {
+ if (!((entered | left) & screen_mask(screen)))
+ continue;
+
+ wl_list_for_each(output, &screen->outputs, link)
+ {
+ resource = wl_resource_find_for_client
+ (&output->resources, client);
+
+ if (resource)
+ {
+ if (entered & screen_mask(screen))
+ wl_surface_send_enter(surface->resource, resource);
+ else if (left & screen_mask(screen))
+ wl_surface_send_leave(surface->resource, resource);
+ }
+ }
+ }
+}
+
+static const struct view_handler_impl view_handler_impl = {
+ .frame = &handle_frame,
+ .screens = &handle_screens,
+};
+
static void destroy(struct wl_client * client, struct wl_resource * resource)
{
wl_resource_destroy(resource);
@@ -291,69 +345,11 @@ static void surface_destroy(struct wl_resource * resource)
state_finalize(&surface->pending.state);
if (surface->view)
- wl_list_remove(&surface->view_listener.link);
+ wl_list_remove(&surface->view_handler.link);
free(surface);
}
-static void handle_view_event(struct wl_listener * listener, void * data)
-{
- struct swc_surface * surface
- = wl_container_of(listener, surface, view_listener);
- struct swc_event * event = data;
- struct view_event_data * event_data = event->data;
-
- switch (event->type)
- {
- case VIEW_EVENT_FRAME:
- {
- struct wl_resource * resource, * tmp;
-
- wl_list_for_each_safe(resource, tmp,
- &surface->state.frame_callbacks, link)
- {
- wl_callback_send_done(resource, event_data->frame.time);
- wl_resource_destroy(resource);
- }
-
- wl_list_init(&surface->state.frame_callbacks);
- break;
- }
- case VIEW_EVENT_SCREENS_CHANGED:
- {
- struct screen * screen;
- struct swc_output * output;
- struct wl_client * client;
- struct wl_resource * resource;
- uint32_t entered = event_data->screens_changed.entered,
- left = event_data->screens_changed.left;
-
- client = wl_resource_get_client(surface->resource);
-
- wl_list_for_each(screen, &swc.screens, link)
- {
- if (!((entered | left) & screen_mask(screen)))
- continue;
-
- wl_list_for_each(output, &screen->outputs, link)
- {
- resource = wl_resource_find_for_client
- (&output->resources, client);
-
- if (resource)
- {
- if (entered & screen_mask(screen))
- wl_surface_send_enter(surface->resource, resource);
- else if (left & screen_mask(screen))
- wl_surface_send_leave(surface->resource, resource);
- }
- }
- }
- break;
- }
- }
-}
-
/**
* Construct a new surface, adding it to the given client as id.
*
@@ -374,7 +370,7 @@ struct swc_surface * swc_surface_new(struct wl_client * client,
/* Initialize the surface. */
surface->pending.commit = 0;
surface->view = NULL;
- surface->view_listener.notify = &handle_view_event;
+ surface->view_handler.impl = &view_handler_impl;
state_initialize(&surface->state);
state_initialize(&surface->pending.state);
@@ -394,13 +390,13 @@ void swc_surface_set_view(struct swc_surface * surface, struct view * view)
return;
if (surface->view)
- wl_list_remove(&surface->view_listener.link);
+ wl_list_remove(&surface->view_handler.link);
surface->view = view;
if (view)
{
- wl_signal_add(&view->event_signal, &surface->view_listener);
+ wl_list_insert(&view->handlers, &surface->view_handler.link);
view_attach(view, surface->state.buffer);
view_update(view);
}
diff --git a/libswc/surface.h b/libswc/surface.h
@@ -24,6 +24,8 @@
#ifndef SWC_SURFACE_H
#define SWC_SURFACE_H
+#include "view.h"
+
#include <stdbool.h>
#include <wayland-server.h>
#include <pixman.h>
@@ -69,7 +71,7 @@ struct swc_surface
} pending;
struct view * view;
- struct wl_listener view_listener;
+ struct view_handler view_handler;
};
struct swc_surface * swc_surface_new(struct wl_client * client,
diff --git a/libswc/view.c b/libswc/view.c
@@ -29,6 +29,16 @@
#include <wld/wld.h>
+#define HANDLE(view, handler, method, ...) \
+ do \
+ { \
+ wl_list_for_each(handler, &view->handlers, link) \
+ { \
+ if (handler->impl->method) \
+ handler->impl->method(handler, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
void view_initialize(struct view * view, const struct view_impl * impl)
{
view->impl = impl;
@@ -38,7 +48,7 @@ void view_initialize(struct view * view, const struct view_impl * impl)
view->geometry.height = 0;
view->buffer = NULL;
view->screens = 0;
- wl_signal_init(&view->event_signal);
+ wl_list_init(&view->handlers);
}
void view_finalize(struct view * view)
@@ -77,28 +87,28 @@ bool view_move(struct view * view, int32_t x, int32_t y)
bool view_set_position(struct view * view, int32_t x, int32_t y)
{
- struct view_event_data data = { .view = view };
+ struct view_handler * handler;
if (x == view->geometry.x && y == view->geometry.y)
return false;
view->geometry.x = x;
view->geometry.y = y;
- swc_send_event(&view->event_signal, VIEW_EVENT_MOVED, &data);
+ HANDLE(view, handler, move);
return true;
}
bool view_set_size(struct view * view, uint32_t width, uint32_t height)
{
- struct view_event_data data = { .view = view };
+ struct view_handler * handler;
if (view->geometry.width == width && view->geometry.height == height)
return false;
view->geometry.width = width;
view->geometry.height = height;
- swc_send_event(&view->event_signal, VIEW_EVENT_RESIZED, &data);
+ HANDLE(view, handler, resize);
return true;
}
@@ -114,16 +124,12 @@ void view_set_screens(struct view * view, uint32_t screens)
if (view->screens == screens)
return;
- struct view_event_data data = {
- .view = view,
- .screens_changed = {
- .entered = screens & ~view->screens,
- .left = view->screens & ~screens
- }
- };
+ uint32_t entered = screens & ~view->screens,
+ left = view->screens & ~screens;
+ struct view_handler * handler;
view->screens = screens;
- swc_send_event(&view->event_signal, VIEW_EVENT_SCREENS_CHANGED, &data);
+ HANDLE(view, handler, screens, entered, left);
}
void view_update_screens(struct view * view)
@@ -142,8 +148,8 @@ void view_update_screens(struct view * view)
void view_frame(struct view * view, uint32_t time)
{
- struct view_event_data data = { .view = view, .frame = { time } };
+ struct view_handler * handler;
- swc_send_event(&view->event_signal, VIEW_EVENT_FRAME, &data);
+ HANDLE(view, handler, frame, time);
}
diff --git a/libswc/view.h b/libswc/view.h
@@ -26,44 +26,6 @@
#include "swc.h"
-enum
-{
- /* Sent when the view has displayed the next frame. */
- VIEW_EVENT_FRAME,
-
- /* Sent when the origin of the view has moved. */
- VIEW_EVENT_MOVED,
-
- /* Sent when the view's size changes. */
- VIEW_EVENT_RESIZED,
-
- /* Sent when the set of screens the view is visible on changes. */
- VIEW_EVENT_SCREENS_CHANGED
-};
-
-/**
- * This structure contains data sent along with a view's events.
- *
- * Extra data correspending to the particular event is stored in the
- * corresponding struct inside the union.
- */
-struct view_event_data
-{
- struct view * view;
- union
- {
- struct
- {
- uint32_t time;
- } frame;
-
- struct
- {
- uint32_t left, entered;
- } screens_changed;
- };
-};
-
/**
* A view represents a component that can display buffers to the user.
*
@@ -79,14 +41,20 @@ struct view_event_data
struct view
{
const struct view_impl * impl;
+ struct wl_list handlers;
- struct wl_signal event_signal;
struct swc_rectangle geometry;
uint32_t screens;
struct wld_buffer * buffer;
};
+struct view_handler
+{
+ const struct view_handler_impl * impl;
+ struct wl_list link;
+};
+
/**
* Every view must have an implementation containing these functions.
*
@@ -99,6 +67,19 @@ struct view_impl
bool (* move)(struct view * view, int32_t x, int32_t y);
};
+struct view_handler_impl
+{
+ /* Called when the view has displayed the next frame. */
+ void (* frame)(struct view_handler * handler, uint32_t time);
+ /* Called after the view's position changes. */
+ void (* move)(struct view_handler * handler);
+ /* Called after the view's size changes. */
+ void (* resize)(struct view_handler * handler);
+ /* Called when the set of screens the view is visible on changes. */
+ void (* screens)(struct view_handler * handler,
+ uint32_t left, uint32_t entered);
+};
+
/**
* Attach a new buffer to the view.
*