{
return compositor->display;
}
-
-PEPPER_API void
-pepper_compositor_set_user_data(pepper_compositor_t *compositor, uint32_t key, void *data)
-{
- PEPPER_TRACE("TODO: %s\n", __FUNCTION__);
-}
-
-PEPPER_API void *
-pepper_compositor_get_user_data(pepper_compositor_t *compositor, uint32_t key)
-{
- PEPPER_TRACE("TODO: %s\n", __FUNCTION__);
- return NULL;
-}
extern "C" {
#endif
-typedef struct pepper_wayland_output_info pepper_wayland_output_info_t;
+typedef struct pepper_wayland pepper_wayland_t;
-struct pepper_wayland_output_info
-{
- const char *socket_name;
-};
+PEPPER_API pepper_wayland_t *
+pepper_wayland_connect(pepper_compositor_t *compositor, const char *socket_name);
-PEPPER_API pepper_bool_t
-pepper_wayland_init(pepper_compositor_t *compositor);
+PEPPER_API void
+pepper_wayland_destroy(pepper_wayland_t *conn);
-PEPPER_API const pepper_output_interface_t *
-pepper_wayland_get_output_interface();
+PEPPER_API pepper_bool_t
+pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h);
#ifdef __cplusplus
}
#include "wayland-internal.h"
-#define WAYLAND_DATA_KEY 0x721dfa02
-
static void
handle_global(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
- wayland_connection_t *conn = data;
+ pepper_wayland_t *conn = data;
if (strcmp(interface, "wl_compositor") == 0)
{
static int
handle_wayland_event(int fd, uint32_t mask, void *data)
{
- wayland_connection_t *conn = data;
+ pepper_wayland_t *conn = data;
int count = 0;
if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
return count;
}
-wayland_connection_t *
-wayland_get_connection(pepper_compositor_t *compositor, const char *socket_name)
+PEPPER_API pepper_wayland_t *
+pepper_wayland_connect(const char *socket_name, pepper_compositor_t *compositor)
{
- wayland_data_t *data;
- wayland_connection_t *conn = NULL;
-
- data = pepper_compositor_get_user_data(compositor, WAYLAND_DATA_KEY);
- if (!data)
- {
- PEPPER_ERROR("Wayland module is not initialized. Call pepper_wayland_init() first.\n");
- return NULL;
- }
-
- if (!wl_list_empty(&data->connections))
- {
- wayland_connection_t *c;
- wl_list_for_each(c, &data->connections, link)
- {
- if (strcmp(c->socket_name, socket_name) == 0)
- {
- conn = c;
- break;
- }
- }
- }
+ pepper_wayland_t *conn;
+ struct wl_display *compositor_display;
+ struct wl_event_loop *loop;
+ conn = pepper_calloc(1, sizeof(pepper_wayland_t));
if (!conn)
- {
- struct wl_display *display;
- struct wl_event_loop *loop;
-
- conn = (wayland_connection_t *)pepper_calloc(1, sizeof(wayland_connection_t));
- if (!conn)
- return NULL;
+ return NULL;
- conn->data = data;
- conn->display = wl_display_connect(socket_name);
- conn->fd = wl_display_get_fd(conn->display);
- conn->socket_name = pepper_string_copy(socket_name);
+ conn->compositor = compositor;
- display = pepper_compositor_get_display(compositor);
- loop = wl_display_get_event_loop(display);
+ conn->socket_name = pepper_string_copy(socket_name);
+ conn->display = wl_display_connect(socket_name);
+ conn->fd = wl_display_get_fd(conn->display);
- conn->event_source = wl_event_loop_add_fd(loop, conn->fd, WL_EVENT_READABLE,
- handle_wayland_event, conn);
+ compositor_display = pepper_compositor_get_display(compositor);
+ loop = wl_display_get_event_loop(compositor_display);
+ conn->event_source = wl_event_loop_add_fd(loop, conn->fd, WL_EVENT_READABLE,
+ handle_wayland_event, conn);
- conn->registry = wl_display_get_registry(conn->display);
- wl_registry_add_listener(conn->registry, ®istry_listener, conn);
- wl_display_roundtrip(conn->display);
+ wl_signal_init(&conn->destroy_signal);
- wl_list_insert(&data->connections, &conn->link);
- }
+ conn->registry = wl_display_get_registry(conn->display);
+ wl_registry_add_listener(conn->registry, ®istry_listener, conn);
+ wl_display_roundtrip(conn->display);
return conn;
}
-PEPPER_API pepper_bool_t
-pepper_wayland_init(pepper_compositor_t *compositor)
+PEPPER_API void
+pepper_wayland_destroy(pepper_wayland_t *conn)
{
- wayland_data_t *data = pepper_compositor_get_user_data(compositor, WAYLAND_DATA_KEY);
+ wl_signal_emit(&conn->destroy_signal);
- if (data)
- {
- PEPPER_ERROR("Wayland key is already used by another module.\n");
- return PEPPER_FALSE;
- }
+ if (conn->socket_name)
+ pepper_string_free(conn->socket_name);
+
+ if (conn->event_source)
+ wl_event_source_remove(conn->event_source);
+
+ if (conn->registry)
+ wl_registry_destroy(conn->registry);
+
+ if (conn->compositor)
+ wl_compositor_destroy(conn->compositor);
+
+ if (conn->seat)
+ wl_seat_destroy(conn->seat);
+
+ if (conn->pointer)
+ wl_pointer_destroy(conn->pointer);
- data = (wayland_data_t *)pepper_calloc(1, sizeof(wayland_data_t));
- if (!data)
- return PEPPER_FALSE;
+ if (conn->keyboard)
+ wl_keyboard_destroy(conn->keyboard);
- data->compositor = compositor;
- wl_list_init(&data->connections);
- pepper_compositor_set_user_data(compositor, WAYLAND_DATA_KEY, data);
+ if (conn->touch)
+ wl_touch_destroy(conn->touch);
- return PEPPER_TRUE;
+ if (conn->shell)
+ wl_shell_destroy(conn->shell);
}
static void
seat_handle_caps(void *data, struct wl_seat *seat, enum wl_seat_capability caps)
{
- wayland_connection_t *conn = data;
+ pepper_wayland_t *conn = data;
if ((caps & WL_SEAT_CAPABILITY_POINTER) && (!conn->pointer))
{
};
void
-wayland_handle_global_seat(wayland_connection_t *conn, struct wl_registry *registry,
+wayland_handle_global_seat(pepper_wayland_t *conn, struct wl_registry *registry,
uint32_t name, uint32_t version)
{
conn->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
wl_seat_add_listener(conn->seat, &seat_listener, conn);
}
-
-#if 0
-PEPPER_API pepper_seat_t *
-pepper_compositor_add_wayland_seat(pepper_compositor_t *compositor,
- const char *socket_name)
-{
- wayland_connection_t *conn;
- pepper_seat_t *seat;
-
- conn = wayland_get_connection(compositor, socket_name);
- if (!conn)
- return NULL;
-
- seat = pepper_seat_create(compositor);
-
- if (conn->pointer)
- wl_pointer_add_listener(conn->pointer, &pointer_listener, seat);
-
- if (conn->keyboard)
- wl_pointer_add_listener(conn->keyboard, &keyboard_listener, seat);
-
- if (conn->touch)
- wl_pointer_add_listener(conn->touch, &touch_listener, seat);
-
- conn->seat = seat;
-
- return seat;
-}
-#endif
#include <wayland-client.h>
#include <common.h>
-typedef struct wayland_connection wayland_connection_t;
-typedef struct wayland_data wayland_data_t;
typedef struct wayland_output wayland_output_t;
-struct wayland_connection
+struct pepper_wayland
{
- wayland_data_t *data;
+ pepper_compositor_t *compositor;
- char *socket_name;
- struct wl_display *display;
+ char *socket_name;
+ struct wl_display *display;
int fd;
- struct wl_event_source *event_source;
+ struct wl_event_source *event_source;
- struct wl_registry *registry;
- struct wl_compositor *compositor;
- struct wl_seat *seat;
- struct wl_pointer *pointer;
- struct wl_keyboard *keyboard;
- struct wl_touch *touch;
- struct wl_shell *shell;
+ struct wl_registry *registry;
+ struct wl_compositor *compositor;
+ struct wl_seat *seat;
+ struct wl_pointer *pointer;
+ struct wl_keyboard *keyboard;
+ struct wl_touch *touch;
+ struct wl_shell *shell;
- struct wl_list link;
-};
-
-struct wayland_data
-{
- pepper_compositor_t *compositor;
- struct wl_list connections;
+ struct wl_signal destroy_signal;
};
struct wayland_output
{
- wayland_connection_t *connection;
- pepper_output_t *base;
+ pepper_wayland_t *conn;
- int32_t w, h;
- int32_t subpixel;
- int32_t scale;
+ struct wl_signal destroy_signal;
+ struct wl_signal mode_change_signal;
- struct wl_surface *surface;
- struct wl_shell_surface *shell_surface;
-};
+ struct wl_listener conn_destroy_listener;
+
+ int32_t w, h;
+ int32_t subpixel;
-wayland_connection_t *
-wayland_get_connection(pepper_compositor_t *compositor, const char *socket_name);
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+};
void
-wayland_handle_global_seat(wayland_connection_t *conn, struct wl_registry *registry,
+wayland_handle_global_seat(pepper_wayland_t *conn, struct wl_registry *registry,
uint32_t name, uint32_t version);
static void
shell_surface_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges,
- int32_t width, int32_t height)
+ int32_t w, int32_t h)
{
wayland_output_t *output = data;
PEPPER_IGNORE(shell_surface);
PEPPER_IGNORE(edges);
- output->w = width;
- output->h = height;
+ output->w = w;
+ output->h = h;
- pepper_output_update_mode(output->base);
+ wl_signal_emit(&output->mode_change_signal, NULL);
}
static void
shell_surface_popup_done,
};
-static void *
-wayland_output_create(pepper_compositor_t *compositor, int32_t w, int32_t h, void *data)
+static void
+wayland_output_destroy(void *o)
{
- pepper_wayland_output_info_t *info = data;
- wayland_connection_t *conn;
- wayland_output_t *output;
-
- conn = wayland_get_connection(compositor, info->socket_name);
- if (!conn)
- return NULL;
-
- output = pepper_calloc(1, sizeof(wayland_output_t));
- if (!output)
- return NULL;
-
- output->connection = conn;
-
- output->w = w;
- output->h = h;
+ wayland_output_t *output = o;
- /* Hard-Coded: subpixel order to horizontal RGB. */
- output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
+ wl_signal_emit(&output->destroy_signal, output);
- /* Hard-Coded: scale value to 1. */
- output->scale = 1;
+ wl_list_remove(&conn_destroy_listener.link);
- output->surface = wl_compositor_create_surface(conn->compositor);
- output->shell_surface = wl_shell_get_shell_surface(conn->shell, output->surface);
- wl_shell_surface_add_listener(output->shell_surface, &shell_surface_listener, output);
+ wl_surface_destroy(output->surface);
+ wl_shell_surface_destroy(output->shell_surface);
- return output;
+ pepper_free(output);
}
static void
-wayland_output_destroy(void *o)
+wayland_output_add_destroy_listener(void *o, struct wl_listener *listener)
{
wayland_output_t *output = o;
+ wl_signal_add(&output->destroy_signal, listener);
+}
- wl_surface_destroy(output->surface);
- wl_shell_surface_destroy(output->shell_surface);
-
- pepper_free(output);
+static void
+wayland_output_add_mode_change_listener(void *o, struct wl_listener *listener)
+{
+ wayland_output_t *output = o;
+ wl_signal_add(&output->mode_change_signal, listener);
}
static int32_t
return model_name;
}
-static int32_t
-wayland_output_get_scale(void *o)
-{
- wayland_output_t *output = o;
- return output->scale;
-}
-
static int
wayland_output_get_mode_count(void *o)
{
return;
mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
- mode->width = output->w;
- mode->height = output->h;
+ mode->w = output->w;
+ mode->h = output->h;
mode->refresh = 60000;
}
+static pepper_bool_t
+wayland_output_set_mode(void *o, const pepper_output_mode_t *mode)
+{
+ wayland_output_t *output = o;
+
+ if (mode->w <= 0 || mode->h <= 0)
+ return PEPPER_FALSE;
+
+ if (mode->refresh != 60000)
+ return PEPPER_FALSE;
+
+ if (output->w != w || output->h != h)
+ {
+ output->w = w;
+ output->h = h;
+
+ /* TODO: Handle resize here. */
+
+ wl_signal_emit(&output->mode_change_signal, output);
+ }
+
+ return PEPPER_TRUE;
+}
+
static const pepper_output_interface_t wayland_output_interface =
{
- wayland_output_create,
wayland_output_destroy,
+ wayland_output_add_destroy_listener,
+ wayland_output_add_mode_change_listener,
+
wayland_output_get_subpixel_order,
wayland_output_get_maker_name,
wayland_output_get_model_name,
- wayland_output_get_scale,
+
wayland_output_get_mode_count,
wayland_output_get_mode,
+ wayland_output_set_mode,
};
-PEPPER_API const pepper_output_interface_t *
-pepper_wayland_get_output_interface()
+PEPPER_API pepper_bool_t
+pepper_wayland_output_create(pepper_wayland_t *conn, int32_t w, int32_t h)
{
- return &wayland_output_interface;
+ wayland_output_t *output;
+
+ output = pepper_calloc(1, sizeof(wayland_output_t));
+ if (!output)
+ return PEPPER_FALSE;
+
+ output->conn = conn;
+
+ output->w = w;
+ output->h = h;
+
+ /* Hard-Coded: subpixel order to horizontal RGB. */
+ output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
+
+ /* Create wayland resources. */
+ output->surface = wl_compositor_create_surface(conn->compositor);
+ output->shell_surface = wl_shell_get_shell_surface(conn->shell, output->surface);
+ wl_shell_surface_add_listener(output->shell_surface, &shell_surface_listener, output);
+
+ /* Add compositor base class output object for this output. */
+ if (!pepper_compositor_add_output(conn->compositor, &wayland_output_interface, output))
+ {
+ wayland_output_destroy(output);
+ return PEPPER_FALSE;
+ }
+
+ return PEPPER_TRUE;
}
#include "pepper-internal.h"
static void
+output_update_mode(pepper_output_t *output)
+{
+ int i;
+ struct wl_resource *resource;
+
+ output->current_mode = NULL;
+
+ if (output->modes)
+ pepper_free(output->modes);
+
+ output->mode_count = output->interface->get_mode_count(output->data);
+ PEPPER_ASSERT(output->mode_count > 0);
+
+ output->modes = pepper_calloc(output->mode_count, sizeof(pepper_output_mode_t));
+ if (!output->modes)
+ {
+ pepper_output_destroy(output);
+ return;
+ }
+
+ for (i = 0; i < output->mode_count; i++)
+ {
+ output->interface->get_mode(output->data, i, &output->modes[i]);
+
+ if (output->modes[i].flags & WL_OUTPUT_MODE_CURRENT)
+ output->current_mode = &output->modes[i];
+
+ }
+
+ wl_resource_for_each(resource, &output->resources)
+ {
+ for (i = 0; i < output->mode_count; i++)
+ {
+ wl_output_send_mode(resource, output->modes[i].flags,
+ output->modes[i].w, output->modes[i].h,
+ output->modes[i].refresh);
+ }
+
+ wl_output_send_done(resource);
+ }
+}
+
+static void
output_send_geometry(pepper_output_t *output)
{
struct wl_resource *resource;
for (i = 0; i < output->mode_count; i++)
{
wl_output_send_mode(resource, output->modes[i].flags,
- output->modes[i].width, output->modes[i].height,
+ output->modes[i].w, output->modes[i].h,
output->modes[i].refresh);
}
wl_output_send_done(resource);
}
-PEPPER_API pepper_output_t *
-pepper_output_create(pepper_compositor_t *compositor,
- int32_t x, int32_t y, int32_t w, int32_t h, int32_t transform, int32_t scale,
- const pepper_output_interface_t *interface, void *data)
+static void
+handle_output_data_destroy(struct wl_listener *listener, void *data)
+{
+ pepper_output_t *output = wl_container_of(listener, output, data_destroy_listener);
+ output->data = NULL;
+ output->interface = NULL;
+ pepper_output_destroy(output);
+}
+
+static void
+handle_mode_change(struct wl_listener *listener, void *data)
+{
+ pepper_output_t *output = wl_container_of(listener, output, data_destroy_listener);
+ output_update_mode(output);
+}
+
+PEPPER_API pepper_bool_t
+pepper_compositor_add_output(pepper_compositor_t *compositor,
+ pepper_output_interface_t *interface, void *data)
{
pepper_output_t *output;
output = pepper_calloc(1, sizeof(pepper_output_t));
if (!output)
- return NULL;
+ return PEPPER_FALSE;
wl_list_init(&output->resources);
output->compositor = compositor;
output->global = wl_global_create(compositor->display, &wl_output_interface, 2, output,
output_bind);
- /* Create backend-side object. */
- output->interface = *interface;
- output->data = interface->create(compositor, w, h, data);
-
- /* Initialize output geometry. */
- output->geometry.x = x;
- output->geometry.y = y;
- output->geometry.w = w;
- output->geometry.h = h;
- output->geometry.transform;
- output->geometry.subpixel = interface->get_subpixel_order(output->data);
- output->geometry.maker = interface->get_maker_name(output->data);
- output->geometry.model = interface->get_model_name(output->data);
+ if (!output->global)
+ {
+ pepper_free(output);
+ return PEPPER_FALSE;
+ }
- /* Initialize output scale. */
- output->scale = interface->get_scale(output->data);
+ /* Create backend-side object. */
+ output->interface = interface;
+ output->data = data;
/* Initialize output modes. */
- pepper_output_update_mode(output);
+ output_update_mode(output);
+
+ /* TODO: Set scale value according to the config or something. */
+ output->scale = 1;
- return output;
+ /* Initialize geometry. TODO: Calculate position and size of the output. */
+ output->geometry.transform;
+ output->geometry.subpixel = interface->get_subpixel_order(data);
+ output->geometry.maker = interface->get_maker_name(data);
+ output->geometry.model = interface->get_model_name(data);
+ output->geometry.x = 0;
+ output->geometry.y = 0;
+ output->geometry.w = output->current_mode->w;
+ output->geometry.h = output->current_mode->h;
+
+ /* Install listeners. */
+ output->data_destroy_listener.notify = handle_output_data_destroy;
+ interface->add_destroy_listener(data, &output->data_destroy_listener);
+
+ output->mode_change_listener.notify = handle_mode_change;
+ interface->add_mode_change_listener(data, &output->mode_change_listener);
+
+ return PEPPER_TRUE;
}
PEPPER_API pepper_compositor_t *
PEPPER_API void
pepper_output_destroy(pepper_output_t *output)
{
- output->interface.destroy(output->data);
+ if (output->interface && output->data)
+ output->interface->destroy(output->data);
+
+ wl_global_destroy(output->global);
+ wl_list_remove(&output->data_destroy_listener.link);
+ wl_list_remove(&output->mode_change_listener.link);
+
+ /* TODO: Handle removal of this output. e.g. Re-position outputs. */
+
pepper_free(output);
}
PEPPER_API pepper_bool_t
pepper_output_set_mode(pepper_output_t *output, const pepper_output_mode_t *mode)
{
- PEPPER_TRACE("TODO: %s\n", __FUNCTION__);
- return PEPPER_FALSE;
-}
-
-PEPPER_API void
-pepper_output_update_mode(pepper_output_t *output)
-{
- int i;
- struct wl_resource *resource;
-
- output->current_mode = NULL;
-
- if (output->modes)
- pepper_free(output->modes);
-
- output->mode_count = output->interface.get_mode_count(output->data);
- PEPPER_ASSERT(output->mode_count > 0);
-
- output->modes = pepper_calloc(output->mode_count, sizeof(pepper_output_mode_t));
- if (!output->modes)
- {
- pepper_output_destroy(output);
- return;
- }
-
- for (i = 0; i < output->mode_count; i++)
- {
- output->interface.get_mode(output->data, i, &output->modes[i]);
-
- if (output->modes[i].flags & WL_OUTPUT_MODE_CURRENT)
- output->current_mode = &output->modes[i];
-
- }
-
- wl_resource_for_each(resource, &output->resources)
- {
- for (i = 0; i < output->mode_count; i++)
- {
- wl_output_send_mode(resource, output->modes[i].flags,
- output->modes[i].width, output->modes[i].height,
- output->modes[i].refresh);
- }
-
- wl_output_send_done(resource);
- }
+ return output->interface->set_mode(output->data, mode);
}
pepper_output_mode_t *current_mode;
/* Backend-specific variables. */
- pepper_output_interface_t interface;
+ pepper_output_interface_t *interface;
void *data;
+
+ /* Listeners for backend-side events. */
+ struct wl_listener data_destroy_listener;
+ struct wl_listener mode_change_listener;
};
struct pepper_buffer
typedef struct pepper_output pepper_output_t;
typedef struct pepper_output_interface pepper_output_interface_t;
-/* Compositor functions. */
-PEPPER_API pepper_compositor_t *
-pepper_compositor_create(const char *socket_name);
-
-PEPPER_API void
-pepper_compositor_destroy(pepper_compositor_t *compositor);
-
-PEPPER_API struct wl_display *
-pepper_compositor_get_display(pepper_compositor_t *compositor);
-
-PEPPER_API void
-pepper_compositor_set_user_data(pepper_compositor_t *compositor, uint32_t key, void *data);
-
-PEPPER_API void *
-pepper_compositor_get_user_data(pepper_compositor_t *compositor, uint32_t key);
+typedef enum
+{
+ PEPPER_RENDER_METHOD_NONE,
+ PEPPER_RENDER_METHOD_PIXMAN,
+ PEPPER_RENDER_METHOD_NATIVE,
+} pepper_render_method_t;
-/* Output. */
struct pepper_output_geometry
{
int32_t x;
struct pepper_output_mode
{
uint32_t flags;
- int32_t width;
- int32_t height;
+ int32_t w, h;
int32_t refresh;
};
struct pepper_output_interface
{
- void * (*create)(pepper_compositor_t *compositor, int32_t w, int32_t h, void *data);
void (*destroy)(void *output);
+ void (*add_destroy_listener)(void *output, struct wl_listener *listener);
+ void (*add_mode_change_listener)(void *output, struct wl_listener *listener);
+
int32_t (*get_subpixel_order)(void *output);
const char * (*get_maker_name)(void *output);
const char * (*get_model_name)(void *output);
- int32_t (*get_scale)(void *output);
+
int (*get_mode_count)(void *output);
void (*get_mode)(void *output, int index, pepper_output_mode_t *mode);
+ pepper_bool_t (*set_mode)(void *output, const pepper_output_mode_t *mode);
};
-PEPPER_API pepper_output_t *
-pepper_output_create(pepper_compositor_t *compositor,
- int32_t x, int32_t y, int32_t w, int32_t h, int32_t transform, int32_t scale,
- const pepper_output_interface_t *interface, void *data);
+/* Compositor functions. */
+PEPPER_API pepper_compositor_t *
+pepper_compositor_create(const char *socket_name);
+
+PEPPER_API void
+pepper_compositor_destroy(pepper_compositor_t *compositor);
+
+PEPPER_API struct wl_display *
+pepper_compositor_get_display(pepper_compositor_t *compositor);
+
+PEPPER_API pepper_bool_t
+pepper_compositor_add_output(pepper_compositor_t *compositor,
+ pepper_output_interface_t *interface,
+ void *data);
PEPPER_API pepper_compositor_t *
pepper_output_get_compositor(pepper_output_t *output);
PEPPER_API pepper_bool_t
pepper_output_set_mode(pepper_output_t *output, const pepper_output_mode_t *mode);
-PEPPER_API void
-pepper_output_update_mode(pepper_output_t *output);
-
/* Input. */
#ifdef __cplusplus