diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index d864a658..4e7a815e 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -95,6 +95,7 @@ struct background { struct output { struct wl_output *output; + uint32_t server_output_id; struct wl_list link; struct panel *panel; @@ -1213,6 +1214,7 @@ create_output(struct desktop *desktop, uint32_t id) output->output = display_bind(desktop->display, id, &wl_output_interface, 2); + output->server_output_id = id; wl_output_add_listener(output->output, &output_listener, output); @@ -1241,6 +1243,23 @@ global_handler(struct display *display, uint32_t id, } } +static void +global_handler_remove(struct display *display, uint32_t id, + const char *interface, uint32_t version, void *data) +{ + struct desktop *desktop = data; + struct output *output; + + if (!strcmp(interface, "wl_output")) { + wl_list_for_each(output, &desktop->outputs, link) { + if (output->server_output_id == id) { + output_destroy(output); + break; + } + } + } +} + static void panel_add_launchers(struct panel *panel, struct desktop *desktop) { @@ -1298,6 +1317,7 @@ int main(int argc, char *argv[]) display_set_user_data(desktop.display, &desktop); display_set_global_handler(desktop.display, global_handler); + display_set_global_handler_remove(desktop.display, global_handler_remove); /* Create panel and background for outputs processed before the shell * global interface was processed */ diff --git a/clients/window.c b/clients/window.c index 17d16ed4..331569a0 100644 --- a/clients/window.c +++ b/clients/window.c @@ -117,6 +117,7 @@ struct display { display_output_handler_t output_configure_handler; display_global_handler_t global_handler; + display_global_handler_t global_handler_remove; void *user_data; @@ -339,6 +340,7 @@ struct input { struct output { struct display *display; struct wl_output *output; + uint32_t server_output_id; struct rectangle allocation; struct wl_list link; int transform; @@ -4606,6 +4608,7 @@ display_add_output(struct display *d, uint32_t id) output->scale = 1; output->output = wl_registry_bind(d->registry, id, &wl_output_interface, 2); + output->server_output_id = id; wl_list_insert(d->output_list.prev, &output->link); wl_output_add_listener(output->output, &output_listener, output); @@ -4622,6 +4625,19 @@ output_destroy(struct output *output) free(output); } +static void +display_destroy_output(struct display *d, uint32_t id) +{ + struct output *output; + + wl_list_for_each(output, &d->output_list, link) { + if (output->server_output_id == id) { + output_destroy(output); + break; + } + } +} + void display_set_global_handler(struct display *display, display_global_handler_t handler) @@ -4638,6 +4654,15 @@ display_set_global_handler(struct display *display, global->version, display->user_data); } +void +display_set_global_handler_remove(struct display *display, + display_global_handler_t remove_handler) +{ + display->global_handler_remove = remove_handler; + if (!remove_handler) + return; +} + void display_set_output_configure_handler(struct display *display, display_output_handler_t handler) @@ -4872,9 +4897,15 @@ registry_handle_global_remove(void *data, struct wl_registry *registry, if (global->name != name) continue; - /* XXX: Should destroy bound globals, and call - * the counterpart of display::global_handler - */ + if (strcmp(global->interface, "wl_output") == 0) + display_destroy_output(d, name); + + /* XXX: Should destroy remaining bound globals */ + + if (d->global_handler_remove) + d->global_handler_remove(d, name, global->interface, + global->version, d->user_data); + wl_list_remove(&global->link); free(global->interface); free(global); diff --git a/clients/window.h b/clients/window.h index 461ec1e2..ff7c87bc 100644 --- a/clients/window.h +++ b/clients/window.h @@ -104,6 +104,9 @@ typedef void (*display_global_handler_t)(struct display *display, void display_set_global_handler(struct display *display, display_global_handler_t handler); +void +display_set_global_handler_remove(struct display *display, + display_global_handler_t remove_handler); void * display_bind(struct display *display, uint32_t name, const struct wl_interface *interface, uint32_t version);