Redesign the compositor / server interface.
This lets the compositor directly provide the implementation of the RMI objects for the surface object and a new compositor object. We avoid the manual forwarding of requests into the compositor and the clumsy compositor interface struct.
This commit is contained in:
parent
0ea4710b3d
commit
d2412e2c2e
165
egl-compositor.c
165
egl-compositor.c
@ -89,10 +89,11 @@ struct egl_compositor {
|
||||
};
|
||||
|
||||
struct egl_surface {
|
||||
struct wl_surface base;
|
||||
struct egl_compositor *compositor;
|
||||
GLuint texture;
|
||||
struct wl_map map;
|
||||
EGLSurface surface;
|
||||
struct wl_surface *wl_surface;
|
||||
int width, height;
|
||||
struct wl_list link;
|
||||
};
|
||||
@ -102,6 +103,10 @@ struct screenshooter {
|
||||
struct egl_compositor *ec;
|
||||
};
|
||||
|
||||
struct screenshooter_interface {
|
||||
void (*shoot)(struct wl_client *client, struct screenshooter *shooter);
|
||||
};
|
||||
|
||||
static void
|
||||
screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter)
|
||||
{
|
||||
@ -120,7 +125,7 @@ screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter)
|
||||
}
|
||||
|
||||
static const struct wl_method screenshooter_methods[] = {
|
||||
{ "shoot", screenshooter_shoot, "", NULL }
|
||||
{ "shoot", "", NULL }
|
||||
};
|
||||
|
||||
static const struct wl_interface screenshooter_interface = {
|
||||
@ -129,6 +134,10 @@ static const struct wl_interface screenshooter_interface = {
|
||||
screenshooter_methods,
|
||||
};
|
||||
|
||||
struct screenshooter_interface screenshooter_implementation = {
|
||||
screenshooter_shoot
|
||||
};
|
||||
|
||||
static struct screenshooter *
|
||||
screenshooter_create(struct egl_compositor *ec)
|
||||
{
|
||||
@ -139,6 +148,7 @@ screenshooter_create(struct egl_compositor *ec)
|
||||
return NULL;
|
||||
|
||||
shooter->base.interface = &screenshooter_interface;
|
||||
shooter->base.implementation = (void(**)(void)) &screenshooter_implementation;
|
||||
shooter->ec = ec;
|
||||
|
||||
return shooter;
|
||||
@ -498,7 +508,8 @@ repaint(void *data)
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
|
||||
wl_display_post_frame(ec->wl_display, ec->current_frame, msecs);
|
||||
wl_display_post_frame(ec->wl_display, &ec->base,
|
||||
ec->current_frame, msecs);
|
||||
ec->current_frame++;
|
||||
|
||||
wl_event_source_timer_update(ec->timer_source, 10);
|
||||
@ -518,36 +529,13 @@ schedule_repaint(struct egl_compositor *ec)
|
||||
wl_event_loop_add_idle(loop, repaint, ec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_create(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
struct egl_surface *es;
|
||||
|
||||
es = malloc(sizeof *es);
|
||||
if (es == NULL)
|
||||
return;
|
||||
|
||||
es->surface = EGL_NO_SURFACE;
|
||||
es->wl_surface = surface;
|
||||
wl_surface_set_data(surface, es);
|
||||
wl_list_insert(ec->surface_list.prev, &es->link);
|
||||
|
||||
glGenTextures(1, &es->texture);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_destroy(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface)
|
||||
surface_destroy(struct wl_client *client,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
struct egl_surface *es;
|
||||
|
||||
es = wl_surface_get_data(surface);
|
||||
if (es == NULL)
|
||||
return;
|
||||
struct egl_surface *es = (struct egl_surface *) surface;
|
||||
struct egl_compositor *ec = es->compositor;
|
||||
|
||||
wl_list_remove(&es->link);
|
||||
egl_surface_destroy(es, ec);
|
||||
@ -556,16 +544,12 @@ notify_surface_destroy(struct wl_compositor *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_attach(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface, uint32_t name,
|
||||
uint32_t width, uint32_t height, uint32_t stride)
|
||||
surface_attach(struct wl_client *client,
|
||||
struct wl_surface *surface, uint32_t name,
|
||||
uint32_t width, uint32_t height, uint32_t stride)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
struct egl_surface *es;
|
||||
|
||||
es = wl_surface_get_data(surface);
|
||||
if (es == NULL)
|
||||
return;
|
||||
struct egl_surface *es = (struct egl_surface *) surface;
|
||||
struct egl_compositor *ec = es->compositor;
|
||||
|
||||
if (es->surface != EGL_NO_SURFACE)
|
||||
eglDestroySurface(ec->display, es->surface);
|
||||
@ -584,30 +568,28 @@ notify_surface_attach(struct wl_compositor *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_map(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface, struct wl_map *map)
|
||||
surface_map(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
struct egl_surface *es;
|
||||
struct egl_surface *es = (struct egl_surface *) surface;
|
||||
|
||||
es = wl_surface_get_data(surface);
|
||||
if (es == NULL)
|
||||
return;
|
||||
|
||||
es->map = *map;
|
||||
es->map.x = x;
|
||||
es->map.y = y;
|
||||
es->map.width = width;
|
||||
es->map.height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_copy(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
int32_t dst_x, int32_t dst_y,
|
||||
uint32_t name, uint32_t stride,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
surface_copy(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
int32_t dst_x, int32_t dst_y,
|
||||
uint32_t name, uint32_t stride,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
struct egl_surface *es = (struct egl_surface *) surface;
|
||||
struct egl_compositor *ec = es->compositor;
|
||||
EGLSurface src;
|
||||
struct egl_surface *es;
|
||||
|
||||
es = wl_surface_get_data(surface);
|
||||
|
||||
/* FIXME: glCopyPixels should work, but then we'll have to
|
||||
* call eglMakeCurrent to set up the src and dest surfaces
|
||||
@ -623,23 +605,56 @@ notify_surface_copy(struct wl_compositor *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
notify_surface_damage(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
surface_damage(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
/* FIXME: This need to take a damage region, of course. */
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
notify_commit(struct wl_compositor *compositor)
|
||||
const static struct wl_surface_interface surface_interface = {
|
||||
surface_destroy,
|
||||
surface_attach,
|
||||
surface_map,
|
||||
surface_copy,
|
||||
surface_damage
|
||||
};
|
||||
|
||||
static void
|
||||
compositor_create_surface(struct wl_client *client,
|
||||
struct wl_compositor *compositor, uint32_t id)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
struct egl_surface *es;
|
||||
|
||||
es = malloc(sizeof *es);
|
||||
if (es == NULL)
|
||||
/* FIXME: Send OOM event. */
|
||||
return;
|
||||
|
||||
es->compositor = ec;
|
||||
es->surface = EGL_NO_SURFACE;
|
||||
wl_list_insert(ec->surface_list.prev, &es->link);
|
||||
glGenTextures(1, &es->texture);
|
||||
wl_client_add_surface(client, &es->base,
|
||||
&surface_interface, id);
|
||||
}
|
||||
|
||||
static void
|
||||
compositor_commit(struct wl_client *client,
|
||||
struct wl_compositor *compositor, uint32_t key)
|
||||
{
|
||||
struct egl_compositor *ec = (struct egl_compositor *) compositor;
|
||||
|
||||
schedule_repaint(ec);
|
||||
|
||||
return ec->current_frame;
|
||||
wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
|
||||
}
|
||||
|
||||
const static struct wl_compositor_interface compositor_interface = {
|
||||
compositor_create_surface,
|
||||
compositor_commit
|
||||
};
|
||||
|
||||
static struct egl_surface *
|
||||
pick_surface(struct egl_input_device *device)
|
||||
{
|
||||
@ -677,7 +692,7 @@ notify_motion(struct egl_input_device *device, int x, int y)
|
||||
if (es) {
|
||||
sx = (x - es->map.x) * es->width / es->map.width;
|
||||
sy = (y - es->map.y) * es->height / es->map.height;
|
||||
wl_surface_post_event(es->wl_surface, &device->base,
|
||||
wl_surface_post_event(&es->base, &device->base,
|
||||
WL_INPUT_MOTION, x, y, sx, sy);
|
||||
}
|
||||
|
||||
@ -715,7 +730,7 @@ notify_button(struct egl_input_device *device,
|
||||
sy = (device->y - es->map.y) * es->height / es->map.height;
|
||||
|
||||
/* FIXME: Swallow click on raise? */
|
||||
wl_surface_post_event(es->wl_surface, &device->base,
|
||||
wl_surface_post_event(&es->base, &device->base,
|
||||
WL_INPUT_BUTTON, button, state,
|
||||
device->x, device->y, sx, sy);
|
||||
|
||||
@ -737,29 +752,16 @@ notify_key(struct egl_input_device *device,
|
||||
schedule_repaint(ec);
|
||||
} else if (!wl_list_empty(&ec->surface_list)) {
|
||||
if (device->focus_surface != NULL)
|
||||
wl_surface_post_event(device->focus_surface->wl_surface,
|
||||
wl_surface_post_event(&device->focus_surface->base,
|
||||
&device->base,
|
||||
WL_INPUT_KEY, key, state);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_compositor_interface interface = {
|
||||
notify_surface_create,
|
||||
notify_surface_destroy,
|
||||
notify_surface_attach,
|
||||
notify_surface_map,
|
||||
notify_surface_copy,
|
||||
notify_surface_damage,
|
||||
notify_commit,
|
||||
};
|
||||
|
||||
struct evdev_input_device *
|
||||
evdev_input_device_create(struct egl_input_device *device,
|
||||
struct wl_display *display, const char *path);
|
||||
|
||||
void
|
||||
egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y);
|
||||
|
||||
static void
|
||||
create_input_device(struct egl_compositor *ec, const char *glob)
|
||||
{
|
||||
@ -984,7 +986,6 @@ egl_compositor_create(struct wl_display *display)
|
||||
if (ec == NULL)
|
||||
return NULL;
|
||||
|
||||
ec->base.interface = &interface;
|
||||
ec->wl_display = display;
|
||||
|
||||
ec->display = eglCreateDisplayNative(gem_device, "i965");
|
||||
@ -1027,6 +1028,8 @@ egl_compositor_create(struct wl_display *display)
|
||||
glOrtho(0, ec->width, ec->height, 0, 0, 1000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
wl_display_set_compositor(display, &ec->base, &compositor_interface);
|
||||
|
||||
wl_list_init(&ec->input_device_list);
|
||||
for (i = 0; option_input_devices[i]; i++)
|
||||
create_input_device(ec, option_input_devices[i]);
|
||||
@ -1086,8 +1089,6 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
wl_display_set_compositor(display, &ec->base);
|
||||
|
||||
if (wl_display_add_socket(display, socket_name, sizeof socket_name)) {
|
||||
fprintf(stderr, "failed to add socket: %m\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
10
flower.c
10
flower.c
@ -104,7 +104,7 @@ draw_stuff(int width, int height)
|
||||
}
|
||||
|
||||
struct flower {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_surface *surface;
|
||||
int i;
|
||||
int x, y, width, height;
|
||||
@ -118,7 +118,7 @@ move_flower(struct flower *flower)
|
||||
flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2,
|
||||
flower->width, flower->height);
|
||||
flower->i++;
|
||||
wl_display_commit(flower->display, 0);
|
||||
wl_compositor_commit(flower->compositor, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -126,7 +126,7 @@ event_handler(struct wl_display *display,
|
||||
uint32_t object, uint32_t opcode,
|
||||
uint32_t size, uint32_t *p, void *data)
|
||||
{
|
||||
if (object == 1 && opcode == 4)
|
||||
if (object == 2 && opcode == 1)
|
||||
move_flower(data);
|
||||
}
|
||||
|
||||
@ -158,12 +158,12 @@ int main(int argc, char *argv[])
|
||||
source = wl_glib_source_new(display);
|
||||
g_source_attach(source, NULL);
|
||||
|
||||
flower.display = display;
|
||||
flower.compositor = wl_display_get_compositor(display);
|
||||
flower.x = 512;
|
||||
flower.y = 384;
|
||||
flower.width = 200;
|
||||
flower.height = 200;
|
||||
flower.surface = wl_display_create_surface(display);
|
||||
flower.surface = wl_compositor_create_surface(flower.compositor);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
srandom(ts.tv_nsec);
|
||||
|
5
gears.c
5
gears.c
@ -47,6 +47,7 @@ struct gears {
|
||||
struct window *window;
|
||||
|
||||
struct wl_display *wl_display;
|
||||
struct wl_compositor *compositor;
|
||||
struct rectangle rectangle;
|
||||
|
||||
EGLDisplay display;
|
||||
@ -320,7 +321,7 @@ frame_handler(struct window *window, uint32_t frame, uint32_t timestamp, void *d
|
||||
&gears->rectangle,
|
||||
gears->buffer->name, gears->buffer->stride);
|
||||
|
||||
wl_display_commit(gears->wl_display, 0);
|
||||
wl_compositor_commit(gears->compositor, 0);
|
||||
|
||||
gears->angle += 1;
|
||||
}
|
||||
@ -379,6 +380,8 @@ gears_create(struct wl_display *display, int fd)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClearColor(0, 0, 0, 0.92);
|
||||
|
||||
gears->compositor = wl_display_get_compositor(display);
|
||||
|
||||
draw_gears(gears);
|
||||
|
||||
frame_handler(gears->window, 0, 0, gears);
|
||||
|
@ -53,6 +53,7 @@ static const char socket_name[] = "\0wayland";
|
||||
struct terminal {
|
||||
struct window *window;
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
int redraw_scheduled, redraw_pending;
|
||||
char *data;
|
||||
int width, height, start, row, column;
|
||||
@ -194,7 +195,7 @@ terminal_draw(struct terminal *terminal)
|
||||
|
||||
window_draw(terminal->window);
|
||||
terminal_draw_contents(terminal);
|
||||
wl_display_commit(terminal->display, 0);
|
||||
wl_compositor_commit(terminal->compositor, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -531,6 +532,7 @@ terminal_create(struct wl_display *display, int fd)
|
||||
terminal->redraw_scheduled = 1;
|
||||
terminal->margin = 5;
|
||||
|
||||
terminal->compositor = wl_display_get_compositor(display);
|
||||
window_set_resize_handler(terminal->window, resize_handler, terminal);
|
||||
window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal);
|
||||
window_set_key_handler(terminal->window, key_handler, terminal);
|
||||
|
@ -64,6 +64,10 @@ struct wl_display {
|
||||
void *event_handler_data;
|
||||
};
|
||||
|
||||
struct wl_compositor {
|
||||
struct wl_proxy proxy;
|
||||
};
|
||||
|
||||
struct wl_surface {
|
||||
struct wl_proxy proxy;
|
||||
};
|
||||
@ -249,11 +253,28 @@ wl_display_write(struct wl_display *display, const void *data, size_t count)
|
||||
wl_connection_write(display->connection, data, count);
|
||||
}
|
||||
|
||||
#define WL_DISPLAY_CREATE_SURFACE 0
|
||||
#define WL_DISPLAY_COMMIT 1
|
||||
WL_EXPORT struct wl_compositor *
|
||||
wl_display_get_compositor(struct wl_display *display)
|
||||
{
|
||||
struct wl_compositor *compositor;
|
||||
uint32_t id;
|
||||
|
||||
id = wl_display_get_object_id(display, "compositor");
|
||||
if (id == 0)
|
||||
return NULL;
|
||||
|
||||
compositor = malloc(sizeof *compositor);
|
||||
compositor->proxy.display = display;
|
||||
compositor->proxy.id = id;
|
||||
|
||||
return compositor;
|
||||
}
|
||||
|
||||
#define WL_COMPOSITOR_CREATE_SURFACE 0
|
||||
#define WL_COMPOSITOR_COMMIT 1
|
||||
|
||||
WL_EXPORT struct wl_surface *
|
||||
wl_display_create_surface(struct wl_display *display)
|
||||
wl_compositor_create_surface(struct wl_compositor *compositor)
|
||||
{
|
||||
struct wl_surface *surface;
|
||||
uint32_t request[3];
|
||||
@ -262,26 +283,28 @@ wl_display_create_surface(struct wl_display *display)
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
surface->proxy.id = wl_display_allocate_id(display);
|
||||
surface->proxy.display = display;
|
||||
surface->proxy.id = wl_display_allocate_id(compositor->proxy.display);
|
||||
surface->proxy.display = compositor->proxy.display;
|
||||
|
||||
request[0] = display->proxy.id;
|
||||
request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
|
||||
request[0] = compositor->proxy.id;
|
||||
request[1] = WL_COMPOSITOR_CREATE_SURFACE | ((sizeof request) << 16);
|
||||
request[2] = surface->proxy.id;
|
||||
wl_connection_write(display->connection, request, sizeof request);
|
||||
wl_connection_write(compositor->proxy.display->connection,
|
||||
request, sizeof request);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
wl_display_commit(struct wl_display *display, uint32_t key)
|
||||
wl_compositor_commit(struct wl_compositor *compositor, uint32_t key)
|
||||
{
|
||||
uint32_t request[3];
|
||||
|
||||
request[0] = display->proxy.id;
|
||||
request[1] = WL_DISPLAY_COMMIT | ((sizeof request) << 16);
|
||||
request[0] = compositor->proxy.id;
|
||||
request[1] = WL_COMPOSITOR_COMMIT | ((sizeof request) << 16);
|
||||
request[2] = key;
|
||||
wl_connection_write(display->connection, request, sizeof request);
|
||||
wl_connection_write(compositor->proxy.display->connection,
|
||||
request, sizeof request);
|
||||
}
|
||||
|
||||
#define WL_SURFACE_DESTROY 0
|
||||
|
@ -56,10 +56,13 @@ void wl_display_set_event_handler(struct wl_display *display,
|
||||
wl_display_event_func_t handler,
|
||||
void *data);
|
||||
|
||||
struct wl_compositor *
|
||||
wl_display_get_compositor(struct wl_display *display);
|
||||
|
||||
struct wl_surface *
|
||||
wl_display_create_surface(struct wl_display *display);
|
||||
wl_compositor_create_surface(struct wl_compositor *compositor);
|
||||
void
|
||||
wl_display_commit(struct wl_display *display, uint32_t key);
|
||||
wl_compositor_commit(struct wl_compositor *compositor, uint32_t key);
|
||||
|
||||
void wl_surface_destroy(struct wl_surface *surface);
|
||||
void wl_surface_attach(struct wl_surface *surface,
|
||||
|
288
wayland.c
288
wayland.c
@ -43,7 +43,6 @@ struct wl_client {
|
||||
struct wl_display *display;
|
||||
struct wl_list object_list;
|
||||
struct wl_list link;
|
||||
uint32_t pending_frame;
|
||||
};
|
||||
|
||||
struct wl_display {
|
||||
@ -51,160 +50,18 @@ struct wl_display {
|
||||
struct wl_event_loop *loop;
|
||||
struct wl_hash *objects;
|
||||
|
||||
struct wl_object *pointer;
|
||||
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_compositor_interface *compositor_interface;
|
||||
|
||||
struct wl_list surface_list;
|
||||
struct wl_list client_list;
|
||||
struct wl_list pending_frame_list;
|
||||
uint32_t client_id_range;
|
||||
uint32_t id;
|
||||
|
||||
struct wl_list global_list;
|
||||
};
|
||||
|
||||
struct wl_surface {
|
||||
struct wl_object base;
|
||||
|
||||
struct wl_client *client;
|
||||
/* provided by client */
|
||||
int width, height;
|
||||
int buffer;
|
||||
int stride;
|
||||
|
||||
struct wl_map map;
|
||||
struct wl_list link;
|
||||
|
||||
/* how to convert buffer contents to pixels in screen format;
|
||||
* yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
|
||||
|
||||
/* how to transform/render rectangular contents to polygons. */
|
||||
|
||||
void *compositor_data;
|
||||
};
|
||||
|
||||
struct wl_object_ref {
|
||||
struct wl_object *object;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
static void
|
||||
wl_surface_destroy(struct wl_client *client,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
interface = client->display->compositor->interface;
|
||||
interface->notify_surface_destroy(client->display->compositor,
|
||||
surface);
|
||||
wl_list_remove(&surface->link);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_surface_attach(struct wl_client *client,
|
||||
struct wl_surface *surface, uint32_t name,
|
||||
uint32_t width, uint32_t height, uint32_t stride)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
interface = client->display->compositor->interface;
|
||||
interface->notify_surface_attach(client->display->compositor,
|
||||
surface, name, width, height, stride);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_surface_map(struct wl_client *client, struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
/* FIXME: This needs to take a tri-mesh argument... - count
|
||||
* and a list of tris. 0 tris means unmap. */
|
||||
|
||||
surface->map.x = x;
|
||||
surface->map.y = y;
|
||||
surface->map.width = width;
|
||||
surface->map.height = height;
|
||||
|
||||
interface = client->display->compositor->interface;
|
||||
interface->notify_surface_map(client->display->compositor,
|
||||
surface, &surface->map);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_surface_copy(struct wl_client *client, struct wl_surface *surface,
|
||||
int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
interface = client->display->compositor->interface;
|
||||
interface->notify_surface_copy(client->display->compositor,
|
||||
surface, dst_x, dst_y,
|
||||
name, stride, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_surface_damage(struct wl_client *client, struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
interface = client->display->compositor->interface;
|
||||
interface->notify_surface_damage(client->display->compositor,
|
||||
surface, x, y, width, height);
|
||||
}
|
||||
|
||||
static const struct wl_method surface_methods[] = {
|
||||
{ "destroy", wl_surface_destroy, "" },
|
||||
{ "attach", wl_surface_attach, "uuuu" },
|
||||
{ "map", wl_surface_map, "iiii" },
|
||||
{ "copy", wl_surface_copy, "iiuuiiii" },
|
||||
{ "damage", wl_surface_damage, "iiii" }
|
||||
};
|
||||
|
||||
static const struct wl_interface surface_interface = {
|
||||
"surface", 1,
|
||||
ARRAY_LENGTH(surface_methods),
|
||||
surface_methods,
|
||||
};
|
||||
|
||||
static struct wl_surface *
|
||||
wl_surface_create(struct wl_display *display,
|
||||
struct wl_client *client, uint32_t id)
|
||||
{
|
||||
struct wl_surface *surface;
|
||||
const struct wl_compositor_interface *interface;
|
||||
|
||||
surface = malloc(sizeof *surface);
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
surface->base.id = id;
|
||||
surface->base.interface = &surface_interface;
|
||||
surface->client = client;
|
||||
|
||||
wl_list_insert(display->surface_list.prev, &surface->link);
|
||||
|
||||
interface = display->compositor->interface;
|
||||
interface->notify_surface_create(display->compositor, surface);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
wl_surface_set_data(struct wl_surface *surface, void *data)
|
||||
{
|
||||
surface->compositor_data = data;
|
||||
}
|
||||
|
||||
WL_EXPORT void *
|
||||
wl_surface_get_data(struct wl_surface *surface)
|
||||
{
|
||||
return surface->compositor_data;
|
||||
}
|
||||
|
||||
void
|
||||
wl_client_destroy(struct wl_client *client);
|
||||
|
||||
@ -264,8 +121,9 @@ wl_client_marshal(struct wl_client *client, struct wl_object *sender,
|
||||
|
||||
static void
|
||||
wl_client_demarshal(struct wl_client *client, struct wl_object *target,
|
||||
const struct wl_method *method, size_t size)
|
||||
uint32_t opcode, size_t size)
|
||||
{
|
||||
const struct wl_method *method;
|
||||
ffi_type *types[20];
|
||||
ffi_cif cif;
|
||||
uint32_t *p, result;
|
||||
@ -279,7 +137,9 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target,
|
||||
void *args[20];
|
||||
struct wl_object *object;
|
||||
uint32_t data[64];
|
||||
void (*func)(void);
|
||||
|
||||
method = &target->interface->methods[opcode];
|
||||
count = strlen(method->signature) + 2;
|
||||
if (count > ARRAY_LENGTH(types)) {
|
||||
printf("too many args (%d)\n", count);
|
||||
@ -341,22 +201,20 @@ wl_client_demarshal(struct wl_client *client, struct wl_object *target,
|
||||
args[i] = &values[i];
|
||||
}
|
||||
|
||||
func = target->implementation[opcode];
|
||||
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count, &ffi_type_uint32, types);
|
||||
ffi_call(&cif, FFI_FN(method->func), &result, args);
|
||||
ffi_call(&cif, func, &result, args);
|
||||
}
|
||||
|
||||
#define WL_DISPLAY_INVALID_OBJECT 0
|
||||
#define WL_DISPLAY_INVALID_METHOD 1
|
||||
#define WL_DISPLAY_NO_MEMORY 2
|
||||
#define WL_DISPLAY_ACKNOWLEDGE 3
|
||||
#define WL_DISPLAY_FRAME 4
|
||||
|
||||
static void
|
||||
wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct wl_client *client = data;
|
||||
struct wl_connection *connection = client->connection;
|
||||
const struct wl_method *method;
|
||||
struct wl_object *object;
|
||||
uint32_t p[2], opcode, size;
|
||||
uint32_t cmask = 0;
|
||||
@ -397,8 +255,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||
continue;
|
||||
}
|
||||
|
||||
method = &object->interface->methods[opcode];
|
||||
wl_client_demarshal(client, object, method, size);
|
||||
wl_client_demarshal(client, object, opcode, size);
|
||||
wl_connection_consume(connection, size);
|
||||
len -= size;
|
||||
}
|
||||
@ -455,6 +312,7 @@ wl_client_create(struct wl_display *display, int fd)
|
||||
wl_client_connection_update,
|
||||
client);
|
||||
wl_list_init(&client->object_list);
|
||||
wl_list_init(&client->link);
|
||||
|
||||
wl_connection_write(client->connection,
|
||||
&display->client_id_range,
|
||||
@ -474,11 +332,19 @@ wl_client_create(struct wl_display *display, int fd)
|
||||
struct wl_object_ref, link);
|
||||
}
|
||||
|
||||
wl_list_insert(display->client_list.prev, &client->link);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_object_destroy(struct wl_object *object)
|
||||
{
|
||||
const struct wl_surface_interface *interface =
|
||||
(const struct wl_surface_interface *) object->implementation;
|
||||
|
||||
/* FIXME: Need generic object destructor. */
|
||||
interface->destroy(NULL, (struct wl_surface *) object);
|
||||
}
|
||||
|
||||
void
|
||||
wl_client_destroy(struct wl_client *client)
|
||||
{
|
||||
@ -492,7 +358,7 @@ wl_client_destroy(struct wl_client *client)
|
||||
ref = container_of(client->object_list.next,
|
||||
struct wl_object_ref, link);
|
||||
wl_list_remove(&ref->link);
|
||||
wl_surface_destroy(client, (struct wl_surface *) ref->object);
|
||||
wl_object_destroy(ref->object);
|
||||
free(ref);
|
||||
}
|
||||
|
||||
@ -501,14 +367,33 @@ wl_client_destroy(struct wl_client *client)
|
||||
free(client);
|
||||
}
|
||||
|
||||
static int
|
||||
wl_display_create_surface(struct wl_client *client,
|
||||
struct wl_display *display, uint32_t id)
|
||||
static const struct wl_method surface_methods[] = {
|
||||
{ "destroy", "" },
|
||||
{ "attach", "uuuu" },
|
||||
{ "map", "iiii" },
|
||||
{ "copy", "iiuuiiii" },
|
||||
{ "damage", "iiii" }
|
||||
};
|
||||
|
||||
static const struct wl_interface surface_interface = {
|
||||
"surface", 1,
|
||||
ARRAY_LENGTH(surface_methods),
|
||||
surface_methods,
|
||||
};
|
||||
|
||||
WL_EXPORT int
|
||||
wl_client_add_surface(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
const struct wl_surface_interface *implementation,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_surface *surface;
|
||||
struct wl_display *display = client->display;
|
||||
struct wl_object_ref *ref;
|
||||
|
||||
surface = wl_surface_create(display, client, id);
|
||||
surface->base.id = id;
|
||||
surface->base.interface = &surface_interface;
|
||||
surface->base.implementation = (void (**)(void)) implementation;
|
||||
surface->client = client;
|
||||
|
||||
ref = malloc(sizeof *ref);
|
||||
if (ref == NULL) {
|
||||
@ -524,39 +409,61 @@ wl_display_create_surface(struct wl_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_display_commit(struct wl_client *client,
|
||||
struct wl_display *display, uint32_t key)
|
||||
#define WL_COMPOSITOR_ACKNOWLEDGE 0
|
||||
#define WL_COMPOSITOR_FRAME 1
|
||||
|
||||
WL_EXPORT void
|
||||
wl_client_send_acknowledge(struct wl_client *client,
|
||||
struct wl_compositor *compositor,
|
||||
uint32_t key, uint32_t frame)
|
||||
{
|
||||
const struct wl_compositor_interface *interface;
|
||||
uint32_t frame;
|
||||
wl_list_remove(&client->link);
|
||||
wl_list_insert(client->display->pending_frame_list.prev,
|
||||
&client->link);
|
||||
wl_client_marshal(client, &compositor->base,
|
||||
WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
|
||||
}
|
||||
|
||||
client->pending_frame = 1;
|
||||
static const struct wl_method compositor_methods[] = {
|
||||
{ "create_surface", "n" },
|
||||
{ "commit", "u" }
|
||||
};
|
||||
|
||||
interface = display->compositor->interface;
|
||||
frame = interface->notify_commit(display->compositor);
|
||||
wl_client_marshal(client, &display->base,
|
||||
WL_DISPLAY_ACKNOWLEDGE, key, frame);
|
||||
static const struct wl_event compositor_events[] = {
|
||||
{ "acknowledge", "uu" },
|
||||
{ "frame", "uu" }
|
||||
};
|
||||
|
||||
static const struct wl_interface compositor_interface = {
|
||||
"compositor", 1,
|
||||
ARRAY_LENGTH(compositor_methods), compositor_methods,
|
||||
ARRAY_LENGTH(compositor_events), compositor_events,
|
||||
};
|
||||
|
||||
WL_EXPORT int
|
||||
wl_display_set_compositor(struct wl_display *display,
|
||||
struct wl_compositor *compositor,
|
||||
const struct wl_compositor_interface *implementation)
|
||||
{
|
||||
compositor->base.interface = &compositor_interface;
|
||||
compositor->base.implementation = (void (**)(void)) implementation;
|
||||
|
||||
wl_display_add_object(display, &compositor->base);
|
||||
if (wl_display_add_global(display, &compositor->base))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct wl_method display_methods[] = {
|
||||
{ "create_surface", wl_display_create_surface, "n" },
|
||||
{ "commit", wl_display_commit, "u" }
|
||||
};
|
||||
|
||||
static const struct wl_event display_events[] = {
|
||||
{ "invalid_object", "u" },
|
||||
{ "invalid_method", "uu" },
|
||||
{ "no_memory", "" },
|
||||
{ "acknowledge", "uu" },
|
||||
{ "frame", "uu" }
|
||||
};
|
||||
|
||||
static const struct wl_interface display_interface = {
|
||||
"display", 1,
|
||||
ARRAY_LENGTH(display_methods), display_methods,
|
||||
0, NULL,
|
||||
ARRAY_LENGTH(display_events), display_events,
|
||||
};
|
||||
|
||||
@ -581,14 +488,14 @@ wl_display_create(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wl_list_init(&display->surface_list);
|
||||
wl_list_init(&display->client_list);
|
||||
wl_list_init(&display->pending_frame_list);
|
||||
wl_list_init(&display->global_list);
|
||||
|
||||
display->client_id_range = 256; /* Gah, arbitrary... */
|
||||
|
||||
display->id = 1;
|
||||
display->base.interface = &display_interface;
|
||||
display->base.implementation = NULL;
|
||||
wl_display_add_object(display, &display->base);
|
||||
if (wl_display_add_global(display, &display->base)) {
|
||||
wl_event_loop_destroy(display->loop);
|
||||
@ -636,9 +543,6 @@ wl_surface_post_event(struct wl_surface *surface,
|
||||
struct wl_input_device {
|
||||
struct wl_object base;
|
||||
struct wl_display *display;
|
||||
uint32_t button_state[16];
|
||||
uint32_t button_count;
|
||||
int32_t x, y;
|
||||
};
|
||||
|
||||
static const struct wl_method input_device_methods[] = {
|
||||
@ -666,29 +570,23 @@ wl_input_device_get_interface(void)
|
||||
|
||||
WL_EXPORT void
|
||||
wl_display_post_frame(struct wl_display *display,
|
||||
struct wl_compositor *compositor,
|
||||
uint32_t frame, uint32_t msecs)
|
||||
{
|
||||
struct wl_client *client;
|
||||
|
||||
client = container_of(display->client_list.next,
|
||||
client = container_of(display->pending_frame_list.next,
|
||||
struct wl_client, link);
|
||||
|
||||
while (&client->link != &display->client_list) {
|
||||
if (client->pending_frame) {
|
||||
wl_client_marshal(client, &display->base,
|
||||
WL_DISPLAY_FRAME, frame, msecs);
|
||||
client->pending_frame = 0;
|
||||
}
|
||||
while (&client->link != &display->pending_frame_list) {
|
||||
wl_client_marshal(client, &compositor->base,
|
||||
WL_COMPOSITOR_FRAME, frame, msecs);
|
||||
client = container_of(client->link.next,
|
||||
struct wl_client, link);
|
||||
}
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
wl_display_set_compositor(struct wl_display *display,
|
||||
struct wl_compositor *compositor)
|
||||
{
|
||||
display->compositor = compositor;
|
||||
wl_list_remove(&display->pending_frame_list);
|
||||
wl_list_init(&display->pending_frame_list);
|
||||
}
|
||||
|
||||
WL_EXPORT struct wl_event_loop *
|
||||
|
90
wayland.h
90
wayland.h
@ -73,7 +73,6 @@ struct wl_argument {
|
||||
|
||||
struct wl_method {
|
||||
const char *name;
|
||||
void *func;
|
||||
const char *signature;
|
||||
const void **types;
|
||||
};
|
||||
@ -94,10 +93,10 @@ struct wl_interface {
|
||||
|
||||
struct wl_object {
|
||||
const struct wl_interface *interface;
|
||||
void (**implementation)(void);
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct wl_surface;
|
||||
struct wl_display;
|
||||
struct wl_input_device;
|
||||
|
||||
@ -105,9 +104,6 @@ struct wl_map {
|
||||
int32_t x, y, width, height;
|
||||
};
|
||||
|
||||
void wl_surface_set_data(struct wl_surface *surface, void *data);
|
||||
void *wl_surface_get_data(struct wl_surface *surface);
|
||||
|
||||
struct wl_display *wl_display_create(void);
|
||||
struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display);
|
||||
int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size);
|
||||
@ -121,50 +117,66 @@ wl_display_add_global(struct wl_display *display, struct wl_object *object);
|
||||
const struct wl_interface *
|
||||
wl_input_device_get_interface(void);
|
||||
|
||||
void
|
||||
wl_display_post_frame(struct wl_display *display,
|
||||
uint32_t frame, uint32_t msecs);
|
||||
|
||||
#define WL_INPUT_MOTION 0
|
||||
#define WL_INPUT_BUTTON 1
|
||||
#define WL_INPUT_KEY 2
|
||||
|
||||
struct wl_compositor {
|
||||
struct wl_object base;
|
||||
};
|
||||
|
||||
struct wl_surface {
|
||||
struct wl_object base;
|
||||
struct wl_client *client;
|
||||
};
|
||||
|
||||
struct wl_compositor_interface {
|
||||
void (*create_surface)(struct wl_client *client,
|
||||
struct wl_compositor *compositor, uint32_t id);
|
||||
void (*commit)(struct wl_client *client,
|
||||
struct wl_compositor *compositor, uint32_t key);
|
||||
};
|
||||
|
||||
struct wl_surface_interface {
|
||||
void (*destroy)(struct wl_client *client,
|
||||
struct wl_surface *surface);
|
||||
void (*attach)(struct wl_client *client,
|
||||
struct wl_surface *surface, uint32_t name,
|
||||
uint32_t width, uint32_t height, uint32_t stride);
|
||||
void (*map)(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
void (*copy)(struct wl_client *client, struct wl_surface *surface,
|
||||
int32_t dst_x, int32_t dst_y, uint32_t name, uint32_t stride,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
void (*damage)(struct wl_client *client, struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
};
|
||||
|
||||
void
|
||||
wl_surface_post_event(struct wl_surface *surface,
|
||||
struct wl_object *sender,
|
||||
uint32_t event, ...);
|
||||
|
||||
struct wl_compositor {
|
||||
const struct wl_compositor_interface *interface;
|
||||
};
|
||||
int
|
||||
wl_display_set_compositor(struct wl_display *display,
|
||||
struct wl_compositor *compositor,
|
||||
const struct wl_compositor_interface *implementation);
|
||||
|
||||
struct wl_compositor_interface {
|
||||
void (*notify_surface_create)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface);
|
||||
void (*notify_surface_destroy)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface);
|
||||
void (*notify_surface_attach)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
uint32_t name,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t stride);
|
||||
void (*notify_surface_map)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
struct wl_map *map);
|
||||
void (*notify_surface_copy)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
int32_t dst_x, int32_t dst_y,
|
||||
uint32_t name, uint32_t stride,
|
||||
int32_t x, int32_t y,
|
||||
int32_t width, int32_t height);
|
||||
void (*notify_surface_damage)(struct wl_compositor *compositor,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y,
|
||||
int32_t width, int32_t height);
|
||||
uint32_t (*notify_commit)(struct wl_compositor *compositor);
|
||||
};
|
||||
int
|
||||
wl_client_add_surface(struct wl_client *client,
|
||||
struct wl_surface *surface,
|
||||
const struct wl_surface_interface *implementation,
|
||||
uint32_t id);
|
||||
|
||||
void wl_display_set_compositor(struct wl_display *display,
|
||||
struct wl_compositor *compositor);
|
||||
void
|
||||
wl_client_send_acknowledge(struct wl_client *client,
|
||||
struct wl_compositor *compositor,
|
||||
uint32_t key, uint32_t frame);
|
||||
|
||||
void
|
||||
wl_display_post_frame(struct wl_display *display,
|
||||
struct wl_compositor *compositor,
|
||||
uint32_t frame, uint32_t msecs);
|
||||
|
||||
#endif
|
||||
|
12
window.c
12
window.c
@ -41,6 +41,7 @@
|
||||
|
||||
struct window {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_surface *surface;
|
||||
const char *title;
|
||||
int x, y, width, height;
|
||||
@ -196,9 +197,9 @@ event_handler(struct wl_display *display,
|
||||
int location;
|
||||
int grip_size = 16;
|
||||
|
||||
/* FIXME: Object ID 1 is the display, for anything else we
|
||||
/* FIXME: Object ID 2 is the compositor, for anything else we
|
||||
* assume it's an input device. */
|
||||
if (object == 1 && opcode == 3) {
|
||||
if (object == 2 && opcode == 0) {
|
||||
uint32_t key = p[0];
|
||||
|
||||
/* Ignore acknowledge events for window move requests. */
|
||||
@ -218,7 +219,7 @@ event_handler(struct wl_display *display,
|
||||
(*window->acknowledge_handler)(window, key,
|
||||
window->user_data);
|
||||
|
||||
} else if (object == 1 && opcode == 4) {
|
||||
} else if (object == 2 && opcode == 1) {
|
||||
/* The frame event means that the previous frame was
|
||||
* composited, and we can now send the request to copy
|
||||
* the frame we've rendered in the mean time into the
|
||||
@ -244,7 +245,7 @@ event_handler(struct wl_display *display,
|
||||
window->y - window->margin,
|
||||
window->width + 2 * window->margin,
|
||||
window->height + 2 * window->margin);
|
||||
wl_display_commit(window->display, 1);
|
||||
wl_compositor_commit(window->compositor, 1);
|
||||
break;
|
||||
case WINDOW_RESIZING_LOWER_RIGHT:
|
||||
if (window->grab_device != object)
|
||||
@ -387,7 +388,8 @@ window_create(struct wl_display *display, int fd,
|
||||
memset(window, 0, sizeof *window);
|
||||
window->display = display;
|
||||
window->title = strdup(title);
|
||||
window->surface = wl_display_create_surface(display);
|
||||
window->compositor = wl_display_get_compositor(display);
|
||||
window->surface = wl_compositor_create_surface(window->compositor);
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
window->minimum_width = 100;
|
||||
|
Loading…
Reference in New Issue
Block a user