Add hook to allow globals to send cold-plug events to new clients.

This lets us boot strap the client side state cache.  This commit also adds the first user
of this feature, an output object that represents the current output.  Very simple
at this point, but will grow to something more like RandR 1.2.
This commit is contained in:
Kristian Høgsberg 2008-12-21 23:37:12 -05:00
parent 8049cbb88a
commit ee02ca6fa4
7 changed files with 124 additions and 22 deletions

View file

@ -67,6 +67,9 @@ struct wl_display {
wl_display_event_func_t event_handler;
void *event_handler_data;
uint32_t output_id;
int32_t width, height;
};
struct wl_compositor {
@ -96,6 +99,13 @@ connection_update(struct wl_connection *connection,
return 0;
}
WL_EXPORT void
wl_display_get_geometry(struct wl_display *display, int32_t *width, int32_t *height)
{
*width = display->width;
*height = display->height;
}
static void
add_visual(struct wl_display *display, struct wl_global *global)
{
@ -258,6 +268,9 @@ handle_display_event(struct wl_display *display,
if (strcmp(global->interface, "visual") == 0)
add_visual(display, global);
else if (strcmp(global->interface, "output") == 0) {
display->output_id = p[0];
}
break;
case WL_DISPLAY_RANGE:
@ -266,6 +279,18 @@ handle_display_event(struct wl_display *display,
}
}
static void
handle_output_event(struct wl_display *display,
uint32_t opcode, uint32_t *p, uint32_t size)
{
switch (opcode) {
case WL_OUTPUT_PRESENCE:
display->width = p[0];
display->height = p[1];
break;
}
}
static void
handle_event(struct wl_display *display,
uint32_t object, uint32_t opcode, uint32_t size)
@ -275,6 +300,8 @@ handle_event(struct wl_display *display,
wl_connection_copy(display->connection, p, size);
if (object == 1) {
handle_display_event(display, opcode, p + 2, size);
} if (object == display->output_id) {
handle_output_event(display, opcode, p + 2, size);
} else if (display->event_handler != NULL)
display->event_handler(display, object, opcode, size, p + 2,
display->event_handler_data);

View file

@ -57,6 +57,9 @@ void wl_display_set_event_handler(struct wl_display *display,
wl_display_event_func_t handler,
void *data);
void
wl_display_get_geometry(struct wl_display *display,
int32_t *width, int32_t *height);
struct wl_compositor *
wl_display_get_compositor(struct wl_display *display);
struct wl_visual *

View file

@ -83,3 +83,14 @@ WL_EXPORT const struct wl_interface wl_input_device_interface = {
0, NULL,
ARRAY_LENGTH(input_device_events), input_device_events,
};
static const struct wl_message output_events[] = {
{ "presence", "uu" },
};
WL_EXPORT const struct wl_interface wl_output_interface = {
"output", 1,
0, NULL,
ARRAY_LENGTH(output_events), output_events,
};

View file

@ -78,4 +78,9 @@ extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface wl_input_device_interface;
#define WL_OUTPUT_PRESENCE 0
extern const struct wl_interface wl_output_interface;
#endif

View file

@ -56,6 +56,10 @@ struct wl_visual {
struct wl_object base;
};
struct wl_output {
struct wl_object base;
};
struct wlsc_input_device {
struct wl_object base;
int32_t x, y;
@ -70,6 +74,7 @@ struct wlsc_input_device {
struct egl_compositor {
struct wl_compositor base;
struct wl_output output;
struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual;
EGLDisplay display;
@ -825,19 +830,29 @@ add_visuals(struct egl_compositor *ec)
ec->argb_visual.base.interface = &visual_interface;
ec->argb_visual.base.implementation = NULL;
wl_display_add_object(ec->wl_display, &ec->argb_visual.base);
wl_display_add_global(ec->wl_display, &ec->argb_visual.base);
wl_display_add_global(ec->wl_display, &ec->argb_visual.base, NULL);
ec->premultiplied_argb_visual.base.interface = &visual_interface;
ec->premultiplied_argb_visual.base.implementation = NULL;
wl_display_add_object(ec->wl_display,
&ec->premultiplied_argb_visual.base);
wl_display_add_global(ec->wl_display,
&ec->premultiplied_argb_visual.base);
&ec->premultiplied_argb_visual.base, NULL);
ec->rgb_visual.base.interface = &visual_interface;
ec->rgb_visual.base.implementation = NULL;
wl_display_add_object(ec->wl_display, &ec->rgb_visual.base);
wl_display_add_global(ec->wl_display, &ec->rgb_visual.base);
wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL);
}
static void
post_output_presence(struct wl_client *client, struct wl_object *global)
{
struct egl_compositor *ec =
container_of(global, struct egl_compositor, output.base);
wl_client_post_event(client, global,
WL_OUTPUT_PRESENCE, ec->width, ec->height);
}
static const char gem_device[] = "/dev/dri/card0";
@ -1021,6 +1036,12 @@ egl_compositor_create(struct wl_display *display)
glClearColor(0, 0, 0.2, 1);
wl_display_set_compositor(display, &ec->base, &compositor_interface);
/* FIXME: This needs to be much more expressive... something like randr 1.2. */
ec->output.base.interface = &wl_output_interface;
wl_display_add_object(display, &ec->output.base);
wl_display_add_global(display, &ec->output.base, post_output_presence);
add_visuals(ec);
wl_list_init(&ec->input_device_list);
@ -1033,7 +1054,7 @@ egl_compositor_create(struct wl_display *display)
shooter = screenshooter_create(ec);
wl_display_add_object(display, &shooter->base);
wl_display_add_global(display, &shooter->base);
wl_display_add_global(display, &shooter->base, NULL);
loop = wl_display_get_event_loop(ec->wl_display);

View file

@ -64,6 +64,12 @@ struct wl_object_ref {
struct wl_list link;
};
struct wl_global {
struct wl_object *object;
wl_client_connect_func_t func;
struct wl_list link;
};
void
wl_client_destroy(struct wl_client *client);
@ -122,6 +128,17 @@ wl_client_marshal(struct wl_client *client, struct wl_object *sender,
va_end(ap);
}
WL_EXPORT void
wl_client_post_event(struct wl_client *client, struct wl_object *sender,
uint32_t opcode, ...)
{
va_list ap;
va_start(ap, opcode);
wl_client_vmarshal(client, sender, opcode, ap);
va_end(ap);
}
static void
wl_client_demarshal(struct wl_client *client, struct wl_object *target,
uint32_t opcode, size_t size)
@ -284,7 +301,7 @@ static struct wl_client *
wl_client_create(struct wl_display *display, int fd)
{
struct wl_client *client;
struct wl_object_ref *ref;
struct wl_global *global;
client = malloc(sizeof *client);
if (client == NULL)
@ -303,17 +320,25 @@ wl_client_create(struct wl_display *display, int fd)
wl_display_post_range(display, client);
ref = container_of(display->global_list.next,
struct wl_object_ref, link);
while (&ref->link != &display->global_list) {
global = container_of(display->global_list.next,
struct wl_global, link);
while (&global->link != &display->global_list) {
wl_client_marshal(client, &client->display->base,
WL_DISPLAY_GLOBAL,
ref->object,
ref->object->interface->name,
ref->object->interface->version);
global->object,
global->object->interface->name,
global->object->interface->version);
global = container_of(global->link.next,
struct wl_global, link);
}
ref = container_of(ref->link.next,
struct wl_object_ref, link);
global = container_of(display->global_list.next,
struct wl_global, link);
while (&global->link != &display->global_list) {
if (global->func)
global->func(client, global->object);
global = container_of(global->link.next,
struct wl_global, link);
}
return client;
@ -403,7 +428,7 @@ wl_display_set_compositor(struct wl_display *display,
compositor->base.implementation = (void (**)(void)) implementation;
wl_display_add_object(display, &compositor->base);
if (wl_display_add_global(display, &compositor->base))
if (wl_display_add_global(display, &compositor->base, NULL))
return -1;
return 0;
@ -439,7 +464,7 @@ wl_display_create(void)
display->base.interface = &wl_display_interface;
display->base.implementation = NULL;
wl_display_add_object(display, &display->base);
if (wl_display_add_global(display, &display->base)) {
if (wl_display_add_global(display, &display->base, NULL)) {
wl_event_loop_destroy(display->loop);
free(display);
return NULL;
@ -456,16 +481,18 @@ wl_display_add_object(struct wl_display *display, struct wl_object *object)
}
WL_EXPORT int
wl_display_add_global(struct wl_display *display, struct wl_object *object)
wl_display_add_global(struct wl_display *display,
struct wl_object *object, wl_client_connect_func_t func)
{
struct wl_object_ref *ref;
struct wl_global *global;
ref = malloc(sizeof *ref);
if (ref == NULL)
global = malloc(sizeof *global);
if (global == NULL)
return -1;
ref->object = object;
wl_list_insert(display->global_list.prev, &ref->link);
global->object = object;
global->func = func;
wl_list_insert(display->global_list.prev, &global->link);
return 0;
}

View file

@ -85,7 +85,10 @@ int wl_display_add_socket(struct wl_display *display, const char *name, size_t n
void wl_display_run(struct wl_display *display);
void wl_display_add_object(struct wl_display *display, struct wl_object *object);
int wl_display_add_global(struct wl_display *display, struct wl_object *object);
typedef void (*wl_client_connect_func_t)(struct wl_client *client, struct wl_object *global);
int wl_display_add_global(struct wl_display *display, struct wl_object *object, wl_client_connect_func_t func);
struct wl_compositor {
struct wl_object base;
@ -120,6 +123,11 @@ struct wl_surface_interface {
int32_t x, int32_t y, int32_t width, int32_t height);
};
void
wl_client_post_event(struct wl_client *client,
struct wl_object *sender,
uint32_t event, ...);
void
wl_surface_post_event(struct wl_surface *surface,
struct wl_object *sender,