From ed9a43c2134f19ddaa4d8e7c9f680d8a3d8329a6 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 26 Sep 2017 23:59:25 +0200 Subject: [PATCH 01/13] Add first try to add wl_shell to rootston --- include/rootston/desktop.h | 2 ++ include/wlr/types/wlr_wl_shell.h | 17 ++++++++++- rootston/desktop.c | 6 +++- rootston/meson.build | 3 +- rootston/wl_shell.c | 20 ++++++++++++ types/wlr_wl_shell.c | 52 ++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 rootston/wl_shell.c diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 62050972..ef361d87 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -39,6 +39,7 @@ struct roots_desktop { struct wl_listener output_add; struct wl_listener output_remove; struct wl_listener xdg_shell_v6_surface; + struct wl_listener wl_shell_surface; }; struct roots_server; @@ -55,5 +56,6 @@ void output_add_notify(struct wl_listener *listener, void *data); void output_remove_notify(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); +void handle_wl_shell_surface(struct wl_listener *listener, void *data); #endif diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 1443bbf0..614d785b 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -7,20 +7,35 @@ struct wlr_wl_shell { struct wl_global *wl_global; struct wl_list wl_resources; struct wl_list surfaces; + uint32_t ping_timeout; + + struct { + struct wl_signal new_surface; + } events; void *data; }; struct wlr_wl_shell_surface { + struct wlr_wl_shell *shell; + struct wl_client *client; struct wl_resource *surface; struct wlr_texture *wlr_texture; struct wl_list link; + uint32_t ping_serial; + struct wl_event_source *ping_timer; + + struct { + struct wl_signal ping_timeout; + } events; + void *data; }; - struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display); void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell); +void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface); + #endif diff --git a/rootston/desktop.c b/rootston/desktop.c index f0495fa1..f9af3b8e 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -67,7 +67,6 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->layout = wlr_output_layout_create(); desktop->compositor = wlr_compositor_create( server->wl_display, server->renderer); - desktop->wl_shell = wlr_wl_shell_create(server->wl_display); wlr_cursor_attach_output_layout(server->input->cursor, desktop->layout); wlr_cursor_map_to_region(server->input->cursor, config->cursor.mapped_box); @@ -79,6 +78,11 @@ struct roots_desktop *desktop_create(struct roots_server *server, &desktop->xdg_shell_v6_surface); desktop->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface; + desktop->wl_shell = wlr_wl_shell_create(server->wl_display); + wl_signal_add(&desktop->wl_shell->events.new_surface, + &desktop->wl_shell_surface); + desktop->wl_shell_surface.notify = handle_wl_shell_surface; + desktop->gamma_control_manager = wlr_gamma_control_manager_create( server->wl_display); diff --git a/rootston/meson.build b/rootston/meson.build index 30ae1548..de2d04de 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -9,6 +9,7 @@ executable( 'main.c', 'output.c', 'pointer.c', - 'xdg_shell_v6.c' + 'xdg_shell_v6.c', + 'wl_shell.c' ], dependencies: wlroots ) diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c new file mode 100644 index 00000000..0dcc0565 --- /dev/null +++ b/rootston/wl_shell.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "rootston/desktop.h" +#include "rootston/server.h" +#include "rootston/input.h" + +void handle_wl_shell_surface(struct wl_listener *listener, void *data) { + struct roots_desktop *desktop = + wl_container_of(listener, desktop, wl_shell_surface); + + struct wlr_wl_shell_surface *surface = data; + wlr_log(L_DEBUG, "new wl_shell surface"); + wlr_wl_shell_surface_ping(surface); +} diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 84b40fc3..745299bf 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -3,10 +3,19 @@ #include #include #include +#include static void shell_surface_pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial) { wlr_log(L_DEBUG, "TODO: implement shell surface pong"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + + if (surface->ping_serial != serial) { + return; + } + + wl_event_source_timer_update(surface->ping_timer, 0); + surface->ping_serial = 0; } static void shell_surface_move(struct wl_client *client, struct wl_resource @@ -77,6 +86,14 @@ static void destroy_shell_surface(struct wl_resource *resource) { free(state); } +static int wlr_wl_shell_surface_ping_timeout(void *user_data) { + struct wlr_wl_shell_surface *surface = user_data; + wl_signal_emit(&surface->events.ping_timeout, surface); + + surface->ping_serial = 0; + return 1; +} + static void wl_shell_get_shell_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface) { @@ -84,14 +101,33 @@ static void wl_shell_get_shell_surface(struct wl_client *client, struct wlr_wl_shell *wlr_wl_shell = wl_resource_get_user_data(resource); struct wlr_wl_shell_surface *state = calloc(1, sizeof(struct wlr_wl_shell_surface)); + if (state == NULL) { + wl_client_post_no_memory(client); + return; + } + + state->shell = wlr_wl_shell; + state->client = client; state->wlr_texture = wlr_texture; state->surface = surface; + struct wl_resource *shell_surface_resource = wl_resource_create(client, &wl_shell_surface_interface, wl_resource_get_version(resource), id); wlr_log(L_DEBUG, "New wl_shell %p (res %p)", state, shell_surface_resource); wl_resource_set_implementation(shell_surface_resource, &shell_surface_interface, state, destroy_shell_surface); wl_list_insert(&wlr_wl_shell->surfaces, &state->link); + wl_signal_emit(&wlr_wl_shell->events.new_surface, state); + + wl_signal_init(&state->events.ping_timeout); + + struct wl_display *display = wl_client_get_display(client); + struct wl_event_loop *loop = wl_display_get_event_loop(display); + state->ping_timer = wl_event_loop_add_timer(loop, + wlr_wl_shell_surface_ping_timeout, state); + if (state->ping_timer == NULL) { + wl_client_post_no_memory(client); + } } static struct wl_shell_interface wl_shell_impl = { @@ -124,6 +160,7 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) { if (!wlr_wl_shell) { return NULL; } + wlr_wl_shell->ping_timeout = 10000; struct wl_global *wl_global = wl_global_create(display, &wl_shell_interface, 1, wlr_wl_shell, wl_shell_bind); if (!wl_global) { @@ -133,6 +170,7 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) { wlr_wl_shell->wl_global = wl_global; wl_list_init(&wlr_wl_shell->wl_resources); wl_list_init(&wlr_wl_shell->surfaces); + wl_signal_init(&wlr_wl_shell->events.new_surface); return wlr_wl_shell; } @@ -150,3 +188,17 @@ void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell) { // wl_global_destroy(wlr_wl_shell->wl_global); free(wlr_wl_shell); } + +void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface) { + if (surface->ping_serial != 0) { + // already pinged + return; + } + + surface->ping_serial = + wl_display_next_serial(wl_client_get_display(surface->client)); + wl_event_source_timer_update(surface->ping_timer, + surface->shell->ping_timeout); + wl_shell_surface_send_ping(surface->surface, + surface->ping_serial); +} From acf58e04de5652ed13ec46458a39a4dd97ba3b78 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 14:48:53 +0200 Subject: [PATCH 02/13] Fix segfault, add wl_shell view --- include/rootston/view.h | 4 ++-- rootston/meson.build | 2 +- rootston/wl_shell.c | 18 +++++++++++++++++- types/wlr_wl_shell.c | 8 ++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/rootston/view.h b/include/rootston/view.h index b74d1075..eee61563 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -6,8 +6,8 @@ #include struct roots_wl_shell_surface { + struct roots_view *view; // TODO - void *_placeholder; }; struct roots_xdg_surface_v6 { @@ -34,7 +34,7 @@ struct roots_view { // TODO: Something for roots-enforced width/height enum roots_view_type type; union { - struct wlr_shell_surface *wl_shell_surface; + struct wlr_wl_shell_surface *wl_shell_surface; struct wlr_xdg_surface_v6 *xdg_surface_v6; }; union { diff --git a/rootston/meson.build b/rootston/meson.build index de2d04de..6e9e0041 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -10,6 +10,6 @@ executable( 'output.c', 'pointer.c', 'xdg_shell_v6.c', - 'wl_shell.c' + 'wl_shell.c', ], dependencies: wlroots ) diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 0dcc0565..0929a999 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -16,5 +16,21 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct wlr_wl_shell_surface *surface = data; wlr_log(L_DEBUG, "new wl_shell surface"); - wlr_wl_shell_surface_ping(surface); + //wlr_wl_shell_surface_ping(surface); + + struct roots_wl_shell_surface *roots_surface = + calloc(1, sizeof(struct roots_wl_shell_surface)); + // TODO: all of the trimmings + + struct roots_view *view = calloc(1, sizeof(struct roots_view)); + view->type = ROOTS_WL_SHELL_VIEW; + view->x = view->y = 200; + view->wl_shell_surface = surface; + view->roots_wl_shell_surface = roots_surface; + //view->wlr_surface = surface->surface; + //view->get_input_bounds = get_input_bounds; + //view->activate = activate; + view->desktop = desktop; + roots_surface->view = view; + wl_list_insert(&desktop->views, &view->link); } diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 745299bf..42a906c9 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -116,8 +116,6 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wlr_log(L_DEBUG, "New wl_shell %p (res %p)", state, shell_surface_resource); wl_resource_set_implementation(shell_surface_resource, &shell_surface_interface, state, destroy_shell_surface); - wl_list_insert(&wlr_wl_shell->surfaces, &state->link); - wl_signal_emit(&wlr_wl_shell->events.new_surface, state); wl_signal_init(&state->events.ping_timeout); @@ -128,6 +126,9 @@ static void wl_shell_get_shell_surface(struct wl_client *client, if (state->ping_timer == NULL) { wl_client_post_no_memory(client); } + + wl_list_insert(&wlr_wl_shell->surfaces, &state->link); + wl_signal_emit(&wlr_wl_shell->events.new_surface, state); } static struct wl_shell_interface wl_shell_impl = { @@ -199,6 +200,5 @@ void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface) { wl_display_next_serial(wl_client_get_display(surface->client)); wl_event_source_timer_update(surface->ping_timer, surface->shell->ping_timeout); - wl_shell_surface_send_ping(surface->surface, - surface->ping_serial); + wl_shell_surface_send_ping(surface->surface, surface->ping_serial); } From e001e400221115b0fe41fb48df48e85a2ec4f6ba Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 15:03:35 +0200 Subject: [PATCH 03/13] Set view->surface --- examples/compositor.c | 2 +- include/wlr/types/wlr_wl_shell.h | 4 ++-- rootston/wl_shell.c | 2 +- types/wlr_wl_shell.c | 16 ++++++++-------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/compositor.c b/examples/compositor.c index 6f28b193..14831820 100644 --- a/examples/compositor.c +++ b/examples/compositor.c @@ -290,7 +290,7 @@ static void handle_output_frame(struct output_state *output, struct wlr_wl_shell_surface *wl_shell_surface; wl_list_for_each(wl_shell_surface, &sample->wl_shell->surfaces, link) { output_frame_handle_surface(sample, wlr_output, ts, - wl_shell_surface->surface, 200, 200); + wl_shell_surface->resource, 200, 200); } struct wlr_xdg_surface_v6 *xdg_surface; struct wlr_xdg_client_v6 *xdg_client; diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 614d785b..d5b8a982 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -19,8 +19,8 @@ struct wlr_wl_shell { struct wlr_wl_shell_surface { struct wlr_wl_shell *shell; struct wl_client *client; - struct wl_resource *surface; - struct wlr_texture *wlr_texture; + struct wl_resource *resource; + struct wlr_surface *surface; struct wl_list link; uint32_t ping_serial; diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 0929a999..67c8f609 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -27,7 +27,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { view->x = view->y = 200; view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; - //view->wlr_surface = surface->surface; + view->wlr_surface = surface->surface; //view->get_input_bounds = get_input_bounds; //view->activate = activate; view->desktop = desktop; diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 42a906c9..b2a4dc28 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -96,9 +96,9 @@ static int wlr_wl_shell_surface_ping_timeout(void *user_data) { static void wl_shell_get_shell_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, - struct wl_resource *surface) { - struct wlr_texture *wlr_texture = wl_resource_get_user_data(surface); - struct wlr_wl_shell *wlr_wl_shell = wl_resource_get_user_data(resource); + struct wl_resource *surface_resource) { + struct wlr_surface *surface = wl_resource_get_user_data(surface_resource); + struct wlr_wl_shell *wl_shell = wl_resource_get_user_data(resource); struct wlr_wl_shell_surface *state = calloc(1, sizeof(struct wlr_wl_shell_surface)); if (state == NULL) { @@ -106,9 +106,9 @@ static void wl_shell_get_shell_surface(struct wl_client *client, return; } - state->shell = wlr_wl_shell; + state->shell = wl_shell; state->client = client; - state->wlr_texture = wlr_texture; + state->resource = surface_resource; state->surface = surface; struct wl_resource *shell_surface_resource = wl_resource_create(client, @@ -127,8 +127,8 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_client_post_no_memory(client); } - wl_list_insert(&wlr_wl_shell->surfaces, &state->link); - wl_signal_emit(&wlr_wl_shell->events.new_surface, state); + wl_list_insert(&wl_shell->surfaces, &state->link); + wl_signal_emit(&wl_shell->events.new_surface, state); } static struct wl_shell_interface wl_shell_impl = { @@ -200,5 +200,5 @@ void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface) { wl_display_next_serial(wl_client_get_display(surface->client)); wl_event_source_timer_update(surface->ping_timer, surface->shell->ping_timeout); - wl_shell_surface_send_ping(surface->surface, surface->ping_serial); + wl_shell_surface_send_ping(surface->resource, surface->ping_serial); } From 663bfe4cd8a8c2c9f0de285c8112b108e9a61bae Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 21:15:31 +0200 Subject: [PATCH 04/13] wlr_wl_shell: implement all requests except set_popup --- include/rootston/view.h | 5 +- include/wlr/types/wlr_wl_shell.h | 52 +++++++ rootston/wl_shell.c | 17 ++- types/wlr_wl_shell.c | 228 ++++++++++++++++++++++++++----- 4 files changed, 262 insertions(+), 40 deletions(-) diff --git a/include/rootston/view.h b/include/rootston/view.h index eee61563..67ca9b62 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -7,7 +7,10 @@ struct roots_wl_shell_surface { struct roots_view *view; - // TODO + // TODO: Maybe destroy listener should go in roots_view + struct wl_listener destroy; + struct wl_listener ping_timeout; + // TODO: other stuff }; struct roots_xdg_surface_v6 { diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index d5b8a982..612e5811 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -16,6 +16,13 @@ struct wlr_wl_shell { void *data; }; +struct wlr_wl_shell_surface_transient_state { + struct wlr_wl_shell_surface *parent; + int32_t x; + int32_t y; + uint32_t flags; +}; + struct wlr_wl_shell_surface { struct wlr_wl_shell *shell; struct wl_client *client; @@ -26,13 +33,58 @@ struct wlr_wl_shell_surface { uint32_t ping_serial; struct wl_event_source *ping_timer; + bool toplevel; + struct wlr_wl_shell_surface_transient_state *transient_state; + char *title; + char *class_; + struct { + struct wl_signal destroy; struct wl_signal ping_timeout; + + struct wl_signal request_move; + struct wl_signal request_resize; + struct wl_signal request_set_fullscreen; + struct wl_signal request_set_popup; + struct wl_signal request_set_maximized; + struct wl_signal set_toplevel; + struct wl_signal set_transient; + struct wl_signal set_title; + struct wl_signal set_class; } events; void *data; }; +struct wlr_wl_shell_surface_move_event { + struct wl_client *client; + struct wlr_wl_shell_surface *surface; + struct wlr_seat_handle *seat_handle; + uint32_t serial; +}; + +struct wlr_wl_shell_surface_resize_event { + struct wl_client *client; + struct wlr_wl_shell_surface *surface; + struct wlr_seat_handle *seat_handle; + uint32_t serial; + uint32_t edges; +}; + +struct wlr_wl_shell_surface_set_fullscreen_event { + struct wl_client *client; + struct wlr_wl_shell_surface *surface; + uint32_t method; + uint32_t framerate; + struct wlr_output *output; +}; + +struct wlr_wl_shell_surface_set_maximized_event { + struct wl_client *client; + struct wlr_wl_shell_surface *surface; + struct wlr_output *output; +}; + struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display); void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell); diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 67c8f609..fffd9fc9 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -10,17 +10,30 @@ #include "rootston/server.h" #include "rootston/input.h" +static void handle_destroy(struct wl_listener *listener, void *data) { + struct roots_wl_shell_surface *roots_surface = + wl_container_of(listener, roots_surface, destroy); + wl_list_remove(&roots_surface->destroy.link); + wl_list_remove(&roots_surface->ping_timeout.link); + view_destroy(roots_surface->view); + free(roots_surface); +} + void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, wl_shell_surface); struct wlr_wl_shell_surface *surface = data; - wlr_log(L_DEBUG, "new wl_shell surface"); - //wlr_wl_shell_surface_ping(surface); + wlr_log(L_DEBUG, "new shell surface: title=%s, class=%s", + surface->title, surface->class_); + //wlr_wl_shell_surface_ping(surface); // TODO: segfaults struct roots_wl_shell_surface *roots_surface = calloc(1, sizeof(struct roots_wl_shell_surface)); // TODO: all of the trimmings + wl_list_init(&roots_surface->destroy.link); + roots_surface->destroy.notify = handle_destroy; + wl_list_init(&roots_surface->ping_timeout.link); struct roots_view *view = calloc(1, sizeof(struct roots_view)); view->type = ROOTS_WL_SHELL_VIEW; diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index b2a4dc28..972131ae 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -1,3 +1,6 @@ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L +#endif #include #include #include @@ -5,11 +8,10 @@ #include #include -static void shell_surface_pong(struct wl_client *client, struct wl_resource - *resource, uint32_t serial) { - wlr_log(L_DEBUG, "TODO: implement shell surface pong"); +static void shell_surface_pong(struct wl_client *client, + struct wl_resource *resource, uint32_t serial) { + wlr_log(L_DEBUG, "got shell surface pong"); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); - if (surface->ping_serial != serial) { return; } @@ -18,32 +20,128 @@ static void shell_surface_pong(struct wl_client *client, struct wl_resource surface->ping_serial = 0; } -static void shell_surface_move(struct wl_client *client, struct wl_resource - *resource, struct wl_resource *seat, uint32_t serial) { - wlr_log(L_DEBUG, "TODO: implement shell surface move"); +static void shell_surface_move(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial) { + wlr_log(L_DEBUG, "got shell surface move"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_seat_handle *seat_handle = + wl_resource_get_user_data(seat_resource); + + struct wlr_wl_shell_surface_move_event *event = + calloc(1, sizeof(struct wlr_wl_shell_surface_move_event)); + if (event == NULL) { + wl_client_post_no_memory(client); + return; + } + + event->client = client; + event->surface = surface; + event->seat_handle = seat_handle; + event->serial = serial; + + wl_signal_emit(&surface->events.request_move, event); + + free(event); } static void shell_surface_resize(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, - uint32_t edges) { - wlr_log(L_DEBUG, "TODO: implement shell surface resize"); + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial, uint32_t edges) { + wlr_log(L_DEBUG, "got shell surface resize"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_seat_handle *seat_handle = + wl_resource_get_user_data(seat_resource); + + struct wlr_wl_shell_surface_resize_event *event = + calloc(1, sizeof(struct wlr_wl_shell_surface_resize_event)); + if (event == NULL) { + wl_client_post_no_memory(client); + return; + } + + event->client = client; + event->surface = surface; + event->seat_handle = seat_handle; + event->serial = serial; + event->edges = edges; + + wl_signal_emit(&surface->events.request_resize, event); + + free(event); } static void shell_surface_set_toplevel(struct wl_client *client, struct wl_resource *resource) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_toplevel"); + wlr_log(L_DEBUG, "got shell surface toplevel"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + + if (surface->transient_state != NULL) { + return; + } + + surface->toplevel = true; + + wl_signal_emit(&surface->events.set_toplevel, surface); } static void shell_surface_set_transient(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *parent, int32_t x, - int32_t y, uint32_t flags) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_transient"); + struct wl_resource *resource, struct wl_resource *parent_resource, + int32_t x, int32_t y, uint32_t flags) { + wlr_log(L_DEBUG, "got shell surface transient"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_wl_shell_surface *parent = + wl_resource_get_user_data(parent_resource); + + if (surface->toplevel) { + return; + } + + struct wlr_wl_shell_surface_transient_state *state = + calloc(1, sizeof(struct wlr_wl_shell_surface_transient_state)); + if (state == NULL) { + wl_client_post_no_memory(client); + return; + } + + state->parent = parent; + state->x = x; + state->y = y; + state->flags = flags; + + free(surface->transient_state); + surface->transient_state = state; + + wl_signal_emit(&surface->events.set_transient, surface); } static void shell_surface_set_fullscreen(struct wl_client *client, struct wl_resource *resource, uint32_t method, uint32_t framerate, - struct wl_resource *output) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_fullscreen"); + struct wl_resource *output_resource) { + wlr_log(L_DEBUG, "got shell surface fullscreen"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_output *output = wl_resource_get_user_data(output_resource); + + if (surface->toplevel) { + return; + } + + struct wlr_wl_shell_surface_set_fullscreen_event *event = + calloc(1, sizeof(struct wlr_wl_shell_surface_set_fullscreen_event)); + if (event == NULL) { + wl_client_post_no_memory(client); + return; + } + + event->client = client; + event->surface = surface; + event->method = method; + event->framerate = framerate; + event->output = output; + + wl_signal_emit(&surface->events.request_set_fullscreen, event); + + free(event); } static void shell_surface_set_popup(struct wl_client *client, @@ -53,18 +151,61 @@ static void shell_surface_set_popup(struct wl_client *client, } static void shell_surface_set_maximized(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *output) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_maximized"); + struct wl_resource *resource, struct wl_resource *output_resource) { + wlr_log(L_DEBUG, "got shell surface maximized"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_output *output = wl_resource_get_user_data(output_resource); + + if (surface->toplevel) { + return; + } + + struct wlr_wl_shell_surface_set_maximized_event *event = + calloc(1, sizeof(struct wlr_wl_shell_surface_set_maximized_event)); + if (event == NULL) { + wl_client_post_no_memory(client); + return; + } + + event->client = client; + event->surface = surface; + event->output = output; + + wl_signal_emit(&surface->events.request_set_maximized, event); + + free(event); } static void shell_surface_set_title(struct wl_client *client, struct wl_resource *resource, const char *title) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_title"); + wlr_log(L_DEBUG, "new shell surface title: %s", title); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + + char *tmp = strdup(title); + if (tmp == NULL) { + return; + } + + free(surface->title); + surface->title = tmp; + + wl_signal_emit(&surface->events.set_title, surface); } static void shell_surface_set_class(struct wl_client *client, struct wl_resource *resource, const char *class_) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_class"); + wlr_log(L_DEBUG, "new shell surface class: %s", class_); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + + char *tmp = strdup(class_); + if (tmp == NULL) { + return; + } + + free(surface->class_); + surface->class_ = tmp; + + wl_signal_emit(&surface->events.set_class, surface); } struct wl_shell_surface_interface shell_surface_interface = { @@ -81,9 +222,12 @@ struct wl_shell_surface_interface shell_surface_interface = { }; static void destroy_shell_surface(struct wl_resource *resource) { - struct wlr_wl_shell_surface *state = wl_resource_get_user_data(resource); - wl_list_remove(&state->link); - free(state); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + wl_signal_emit(&surface->events.destroy, surface); + wl_list_remove(&surface->link); + free(surface->title); + free(surface->class_); + free(surface); } static int wlr_wl_shell_surface_ping_timeout(void *user_data) { @@ -99,36 +243,46 @@ static void wl_shell_get_shell_surface(struct wl_client *client, struct wl_resource *surface_resource) { struct wlr_surface *surface = wl_resource_get_user_data(surface_resource); struct wlr_wl_shell *wl_shell = wl_resource_get_user_data(resource); - struct wlr_wl_shell_surface *state = + struct wlr_wl_shell_surface *wl_surface = calloc(1, sizeof(struct wlr_wl_shell_surface)); - if (state == NULL) { + if (wl_surface == NULL) { wl_client_post_no_memory(client); return; } - state->shell = wl_shell; - state->client = client; - state->resource = surface_resource; - state->surface = surface; + wl_surface->shell = wl_shell; + wl_surface->client = client; + wl_surface->resource = surface_resource; + wl_surface->surface = surface; struct wl_resource *shell_surface_resource = wl_resource_create(client, &wl_shell_surface_interface, wl_resource_get_version(resource), id); - wlr_log(L_DEBUG, "New wl_shell %p (res %p)", state, shell_surface_resource); + wlr_log(L_DEBUG, "New wl_shell %p (res %p)", wl_surface, shell_surface_resource); wl_resource_set_implementation(shell_surface_resource, - &shell_surface_interface, state, destroy_shell_surface); + &shell_surface_interface, wl_surface, destroy_shell_surface); - wl_signal_init(&state->events.ping_timeout); + wl_signal_init(&wl_surface->events.destroy); + wl_signal_init(&wl_surface->events.ping_timeout); + wl_signal_init(&wl_surface->events.request_move); + wl_signal_init(&wl_surface->events.request_resize); + wl_signal_init(&wl_surface->events.request_set_fullscreen); + wl_signal_init(&wl_surface->events.request_set_popup); + wl_signal_init(&wl_surface->events.request_set_maximized); + wl_signal_init(&wl_surface->events.set_toplevel); + wl_signal_init(&wl_surface->events.set_transient); + wl_signal_init(&wl_surface->events.set_title); + wl_signal_init(&wl_surface->events.set_class); struct wl_display *display = wl_client_get_display(client); struct wl_event_loop *loop = wl_display_get_event_loop(display); - state->ping_timer = wl_event_loop_add_timer(loop, - wlr_wl_shell_surface_ping_timeout, state); - if (state->ping_timer == NULL) { + wl_surface->ping_timer = wl_event_loop_add_timer(loop, + wlr_wl_shell_surface_ping_timeout, wl_surface); + if (wl_surface->ping_timer == NULL) { wl_client_post_no_memory(client); } - wl_list_insert(&wl_shell->surfaces, &state->link); - wl_signal_emit(&wl_shell->events.new_surface, state); + wl_list_insert(&wl_shell->surfaces, &wl_surface->link); + wl_signal_emit(&wl_shell->events.new_surface, wl_surface); } static struct wl_shell_interface wl_shell_impl = { From 14ab56b6c5a782653c0d9d421196926ed534eab1 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 23:10:33 +0200 Subject: [PATCH 05/13] wl_shell: implement set_popup request --- include/wlr/types/wlr_wl_shell.h | 22 +++++++-- types/wlr_wl_shell.c | 80 ++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 19 deletions(-) diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 612e5811..92c35d7d 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -1,6 +1,7 @@ #ifndef WLR_TYPES_WLR_WL_SHELL_H #define WLR_TYPES_WLR_WL_SHELL_H +#include #include struct wlr_wl_shell { @@ -23,6 +24,18 @@ struct wlr_wl_shell_surface_transient_state { uint32_t flags; }; +struct wlr_wl_shell_surface_popup_state { + struct wlr_seat_handle *seat_handle; + uint32_t serial; +}; + +enum wlr_wl_shell_surface_role { + WLR_WL_SHELL_SURFACE_ROLE_NONE, + WLR_WL_SHELL_SURFACE_ROLE_TOPLEVEL, + WLR_WL_SHELL_SURFACE_ROLE_TRANSCIENT, + WLR_WL_SHELL_SURFACE_ROLE_POPUP, +}; + struct wlr_wl_shell_surface { struct wlr_wl_shell *shell; struct wl_client *client; @@ -33,8 +46,10 @@ struct wlr_wl_shell_surface { uint32_t ping_serial; struct wl_event_source *ping_timer; - bool toplevel; + enum wlr_wl_shell_surface_role role; struct wlr_wl_shell_surface_transient_state *transient_state; + struct wlr_wl_shell_surface_popup_state *popup_state; + char *title; char *class_; @@ -45,10 +60,9 @@ struct wlr_wl_shell_surface { struct wl_signal request_move; struct wl_signal request_resize; struct wl_signal request_set_fullscreen; - struct wl_signal request_set_popup; struct wl_signal request_set_maximized; - struct wl_signal set_toplevel; - struct wl_signal set_transient; + + struct wl_signal set_role; struct wl_signal set_title; struct wl_signal set_class; } events; diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 972131ae..4c3aaefc 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -76,13 +76,13 @@ static void shell_surface_set_toplevel(struct wl_client *client, wlr_log(L_DEBUG, "got shell surface toplevel"); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); - if (surface->transient_state != NULL) { + if (surface->role != WLR_WL_SHELL_SURFACE_ROLE_NONE) { return; } - surface->toplevel = true; + surface->role = WLR_WL_SHELL_SURFACE_ROLE_TOPLEVEL; - wl_signal_emit(&surface->events.set_toplevel, surface); + wl_signal_emit(&surface->events.set_role, surface); } static void shell_surface_set_transient(struct wl_client *client, @@ -92,8 +92,9 @@ static void shell_surface_set_transient(struct wl_client *client, struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); struct wlr_wl_shell_surface *parent = wl_resource_get_user_data(parent_resource); + // TODO: check if parent_resource == NULL? - if (surface->toplevel) { + if (surface->role != WLR_WL_SHELL_SURFACE_ROLE_NONE) { return; } @@ -112,7 +113,9 @@ static void shell_surface_set_transient(struct wl_client *client, free(surface->transient_state); surface->transient_state = state; - wl_signal_emit(&surface->events.set_transient, surface); + surface->role = WLR_WL_SHELL_SURFACE_ROLE_TRANSCIENT; + + wl_signal_emit(&surface->events.set_role, surface); } static void shell_surface_set_fullscreen(struct wl_client *client, @@ -120,9 +123,12 @@ static void shell_surface_set_fullscreen(struct wl_client *client, struct wl_resource *output_resource) { wlr_log(L_DEBUG, "got shell surface fullscreen"); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); - struct wlr_output *output = wl_resource_get_user_data(output_resource); + struct wlr_output *output = NULL; + if (output_resource != NULL) { + output = wl_resource_get_user_data(output_resource); + } - if (surface->toplevel) { + if (surface->role == WLR_WL_SHELL_SURFACE_ROLE_TOPLEVEL) { return; } @@ -145,18 +151,64 @@ static void shell_surface_set_fullscreen(struct wl_client *client, } static void shell_surface_set_popup(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, - struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags) { - wlr_log(L_DEBUG, "TODO: implement shell surface set_popup"); + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial, struct wl_resource *parent_resource, int32_t x, int32_t y, + uint32_t flags) { + wlr_log(L_DEBUG, "got shell surface popup"); + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + struct wlr_seat_handle *seat_handle = + wl_resource_get_user_data(seat_resource); + struct wlr_wl_shell_surface *parent = + wl_resource_get_user_data(parent_resource); + // TODO: check if parent_resource == NULL? + + if (surface->role != WLR_WL_SHELL_SURFACE_ROLE_NONE) { + return; + } + + struct wlr_wl_shell_surface_transient_state *transcient_state = + calloc(1, sizeof(struct wlr_wl_shell_surface_transient_state)); + if (transcient_state == NULL) { + wl_client_post_no_memory(client); + return; + } + + transcient_state->parent = parent; + transcient_state->x = x; + transcient_state->y = y; + transcient_state->flags = flags; + + struct wlr_wl_shell_surface_popup_state *popup_state = + calloc(1, sizeof(struct wlr_wl_shell_surface_transient_state)); + if (popup_state == NULL) { + wl_client_post_no_memory(client); + return; + } + + popup_state->seat_handle = seat_handle; + popup_state->serial = serial; + + free(surface->transient_state); + surface->transient_state = transcient_state; + + free(surface->popup_state); + surface->popup_state = popup_state; + + surface->role = WLR_WL_SHELL_SURFACE_ROLE_POPUP; + + wl_signal_emit(&surface->events.set_role, surface); } static void shell_surface_set_maximized(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output_resource) { wlr_log(L_DEBUG, "got shell surface maximized"); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); - struct wlr_output *output = wl_resource_get_user_data(output_resource); + struct wlr_output *output = NULL; + if (output_resource != NULL) { + output = wl_resource_get_user_data(output_resource); + } - if (surface->toplevel) { + if (surface->role == WLR_WL_SHELL_SURFACE_ROLE_TOPLEVEL) { return; } @@ -266,10 +318,8 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_signal_init(&wl_surface->events.request_move); wl_signal_init(&wl_surface->events.request_resize); wl_signal_init(&wl_surface->events.request_set_fullscreen); - wl_signal_init(&wl_surface->events.request_set_popup); wl_signal_init(&wl_surface->events.request_set_maximized); - wl_signal_init(&wl_surface->events.set_toplevel); - wl_signal_init(&wl_surface->events.set_transient); + wl_signal_init(&wl_surface->events.set_role); wl_signal_init(&wl_surface->events.set_title); wl_signal_init(&wl_surface->events.set_class); From 241fec4d8786a0c86507d41f401ac70ec2c0c150 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 23:45:09 +0200 Subject: [PATCH 06/13] wl_shell: add wlr_wl_shell_surface_{configure,popup_done} --- include/wlr/types/wlr_wl_shell.h | 3 +++ types/wlr_wl_shell.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 92c35d7d..03c0da34 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -103,5 +103,8 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display); void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell); void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface); +void wlr_wl_shell_surface_configure(struct wlr_wl_shell_surface *surface, + uint32_t edges, int32_t width, int32_t height); +void wlr_wl_shell_surface_popup_done(struct wlr_wl_shell_surface *surface); #endif diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 4c3aaefc..e418b3d7 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -406,3 +406,12 @@ void wlr_wl_shell_surface_ping(struct wlr_wl_shell_surface *surface) { surface->shell->ping_timeout); wl_shell_surface_send_ping(surface->resource, surface->ping_serial); } + +void wlr_wl_shell_surface_configure(struct wlr_wl_shell_surface *surface, + uint32_t edges, int32_t width, int32_t height) { + wl_shell_surface_send_configure(surface->resource, edges, width, height); +} + +void wlr_wl_shell_surface_popup_done(struct wlr_wl_shell_surface *surface) { + wl_shell_surface_send_popup_done(surface->resource); +} From d6c6b7c506547d9d409e9c064dba9e613d14fc59 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 27 Sep 2017 23:47:39 +0200 Subject: [PATCH 07/13] class_ -> class, free more stuff in destroy_shell_surface --- include/wlr/types/wlr_wl_shell.h | 2 +- rootston/wl_shell.c | 2 +- types/wlr_wl_shell.c | 14 ++++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 03c0da34..3d190588 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -51,7 +51,7 @@ struct wlr_wl_shell_surface { struct wlr_wl_shell_surface_popup_state *popup_state; char *title; - char *class_; + char *class; struct { struct wl_signal destroy; diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index fffd9fc9..817d8b95 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -25,7 +25,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct wlr_wl_shell_surface *surface = data; wlr_log(L_DEBUG, "new shell surface: title=%s, class=%s", - surface->title, surface->class_); + surface->title, surface->class); //wlr_wl_shell_surface_ping(surface); // TODO: segfaults struct roots_wl_shell_surface *roots_surface = diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index e418b3d7..1384c995 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -245,17 +245,17 @@ static void shell_surface_set_title(struct wl_client *client, } static void shell_surface_set_class(struct wl_client *client, - struct wl_resource *resource, const char *class_) { - wlr_log(L_DEBUG, "new shell surface class: %s", class_); + struct wl_resource *resource, const char *class) { + wlr_log(L_DEBUG, "new shell surface class: %s", class); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); - char *tmp = strdup(class_); + char *tmp = strdup(class); if (tmp == NULL) { return; } - free(surface->class_); - surface->class_ = tmp; + free(surface->class); + surface->class = tmp; wl_signal_emit(&surface->events.set_class, surface); } @@ -277,8 +277,10 @@ static void destroy_shell_surface(struct wl_resource *resource) { struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); wl_signal_emit(&surface->events.destroy, surface); wl_list_remove(&surface->link); + free(surface->transient_state); + free(surface->popup_state); free(surface->title); - free(surface->class_); + free(surface->class); free(surface); } From 63f277f3b95e353f034109e16d95ef3aca1d1a9c Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 00:29:37 +0200 Subject: [PATCH 08/13] rootston: handle request_move --- include/rootston/view.h | 5 ++++- rootston/wl_shell.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/rootston/view.h b/include/rootston/view.h index 67ca9b62..1010566a 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -10,7 +10,10 @@ struct roots_wl_shell_surface { // TODO: Maybe destroy listener should go in roots_view struct wl_listener destroy; struct wl_listener ping_timeout; - // TODO: other stuff + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_set_fullscreen; + struct wl_listener request_set_maximized; }; struct roots_xdg_surface_v6 { diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 817d8b95..7a37ce43 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -10,11 +10,41 @@ #include "rootston/server.h" #include "rootston/input.h" +static void handle_move(struct wl_listener *listener, void *data) { + struct roots_wl_shell_surface *roots_surface = + wl_container_of(listener, roots_surface, request_move); + struct roots_view *view = roots_surface->view; + struct roots_input *input = view->desktop->server->input; + struct wlr_wl_shell_surface_move_event *e = data; + + // TODO: Some of this might want to live in cursor.c I guess + struct roots_input_event *event = NULL; + size_t len = sizeof(input->input_events) / sizeof(*input->input_events); + for (size_t i = 0; i < len; ++i) { + if (input->input_events[i].cursor + && input->input_events[i].serial == e->serial) { + event = &input->input_events[i]; + break; + } + } + if (!event || input->mode != ROOTS_CURSOR_PASSTHROUGH) { + return; + } + input->mode = ROOTS_CURSOR_MOVE; + input->offs_x = input->cursor->x - view->x; + input->offs_y = input->cursor->y - view->y; + wlr_seat_pointer_clear_focus(input->wl_seat); +} + static void handle_destroy(struct wl_listener *listener, void *data) { struct roots_wl_shell_surface *roots_surface = wl_container_of(listener, roots_surface, destroy); wl_list_remove(&roots_surface->destroy.link); wl_list_remove(&roots_surface->ping_timeout.link); + wl_list_remove(&roots_surface->request_move.link); + wl_list_remove(&roots_surface->request_resize.link); + wl_list_remove(&roots_surface->request_set_fullscreen.link); + wl_list_remove(&roots_surface->request_set_maximized.link); view_destroy(roots_surface->view); free(roots_surface); } @@ -33,7 +63,14 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { // TODO: all of the trimmings wl_list_init(&roots_surface->destroy.link); roots_surface->destroy.notify = handle_destroy; + wl_signal_add(&surface->events.destroy, &roots_surface->destroy); wl_list_init(&roots_surface->ping_timeout.link); + wl_list_init(&roots_surface->request_move.link); + roots_surface->request_move.notify = handle_move; + wl_signal_add(&surface->events.request_move, &roots_surface->request_move); + wl_list_init(&roots_surface->request_resize.link); + wl_list_init(&roots_surface->request_set_fullscreen.link); + wl_list_init(&roots_surface->request_set_maximized.link); struct roots_view *view = calloc(1, sizeof(struct roots_view)); view->type = ROOTS_WL_SHELL_VIEW; @@ -41,6 +78,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; view->wlr_surface = surface->surface; + // TODO //view->get_input_bounds = get_input_bounds; //view->activate = activate; view->desktop = desktop; From dd9c15c69ecd5877d7a1caee6c2a3875df433a4b Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 00:58:41 +0200 Subject: [PATCH 09/13] rootston: no need to implement get_input_bounds and activate for wl_shell views --- rootston/wl_shell.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 7a37ce43..adb7eaee 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -78,9 +78,6 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; view->wlr_surface = surface->surface; - // TODO - //view->get_input_bounds = get_input_bounds; - //view->activate = activate; view->desktop = desktop; roots_surface->view = view; wl_list_insert(&desktop->views, &view->link); From d41a4a0baeb268515044857d8121c033f3c0b477 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 01:02:30 +0200 Subject: [PATCH 10/13] wl_shell: gluten-free cosmetic variable renaming --- rootston/wl_shell.c | 2 +- types/wlr_wl_shell.c | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index adb7eaee..2b850d09 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -56,7 +56,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct wlr_wl_shell_surface *surface = data; wlr_log(L_DEBUG, "new shell surface: title=%s, class=%s", surface->title, surface->class); - //wlr_wl_shell_surface_ping(surface); // TODO: segfaults + wlr_wl_shell_surface_ping(surface); // TODO: segfaults struct roots_wl_shell_surface *roots_surface = calloc(1, sizeof(struct roots_wl_shell_surface)); diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 1384c995..6f941bda 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -362,23 +362,22 @@ static void wl_shell_bind(struct wl_client *wl_client, void *_wl_shell, } struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) { - struct wlr_wl_shell *wlr_wl_shell = - calloc(1, sizeof(struct wlr_wl_shell)); - if (!wlr_wl_shell) { + struct wlr_wl_shell *wl_shell = calloc(1, sizeof(struct wlr_wl_shell)); + if (!wl_shell) { return NULL; } - wlr_wl_shell->ping_timeout = 10000; + wl_shell->ping_timeout = 10000; struct wl_global *wl_global = wl_global_create(display, - &wl_shell_interface, 1, wlr_wl_shell, wl_shell_bind); + &wl_shell_interface, 1, wl_shell, wl_shell_bind); if (!wl_global) { - free(wlr_wl_shell); + free(wl_shell); return NULL; } - wlr_wl_shell->wl_global = wl_global; - wl_list_init(&wlr_wl_shell->wl_resources); - wl_list_init(&wlr_wl_shell->surfaces); - wl_signal_init(&wlr_wl_shell->events.new_surface); - return wlr_wl_shell; + wl_shell->wl_global = wl_global; + wl_list_init(&wl_shell->wl_resources); + wl_list_init(&wl_shell->surfaces); + wl_signal_init(&wl_shell->events.new_surface); + return wl_shell; } void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell) { From eaa414bbd8b33ae79aed8c41e3198a0bc75ff0fe Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 01:10:39 +0200 Subject: [PATCH 11/13] wl_shell: properly set wl_surface->resource --- types/wlr_wl_shell.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 6f941bda..5040850f 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -306,13 +306,12 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_surface->shell = wl_shell; wl_surface->client = client; - wl_surface->resource = surface_resource; wl_surface->surface = surface; - struct wl_resource *shell_surface_resource = wl_resource_create(client, - &wl_shell_surface_interface, wl_resource_get_version(resource), id); - wlr_log(L_DEBUG, "New wl_shell %p (res %p)", wl_surface, shell_surface_resource); - wl_resource_set_implementation(shell_surface_resource, + wl_surface->resource = wl_resource_create(client, &wl_shell_surface_interface, + wl_resource_get_version(resource), id); + wlr_log(L_DEBUG, "new wl_shell %p (res %p)", wl_surface, wl_surface->resource); + wl_resource_set_implementation(wl_surface->resource, &shell_surface_interface, wl_surface, destroy_shell_surface); wl_signal_init(&wl_surface->events.destroy); From a04462ba8be00640a4a17c096f61c556e488847e Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 01:31:31 +0200 Subject: [PATCH 12/13] wl_shell: listen for wlr_surface destroy signal --- include/wlr/types/wlr_wl_shell.h | 2 ++ types/wlr_wl_shell.c | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 3d190588..11d30d95 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -53,6 +53,8 @@ struct wlr_wl_shell_surface { char *title; char *class; + struct wl_listener surface_destroy_listener; + struct { struct wl_signal destroy; struct wl_signal ping_timeout; diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 5040850f..99371fb4 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -273,10 +274,11 @@ struct wl_shell_surface_interface shell_surface_interface = { .set_class = shell_surface_set_class, }; -static void destroy_shell_surface(struct wl_resource *resource) { - struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); +static void wl_shell_surface_destroy(struct wlr_wl_shell_surface *surface) { wl_signal_emit(&surface->events.destroy, surface); + wl_resource_set_user_data(surface->resource, NULL); wl_list_remove(&surface->link); + wl_list_remove(&surface->surface_destroy_listener.link); free(surface->transient_state); free(surface->popup_state); free(surface->title); @@ -284,6 +286,20 @@ static void destroy_shell_surface(struct wl_resource *resource) { free(surface); } +static void wl_shell_surface_resource_destroy(struct wl_resource *resource) { + struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); + if (surface != NULL) { + wl_shell_surface_destroy(surface); + } +} + +static void handle_wlr_surface_destroyed(struct wl_listener *listener, + void *data) { + struct wlr_wl_shell_surface *surface = + wl_container_of(listener, surface, surface_destroy_listener); + wl_shell_surface_destroy(surface); +} + static int wlr_wl_shell_surface_ping_timeout(void *user_data) { struct wlr_wl_shell_surface *surface = user_data; wl_signal_emit(&surface->events.ping_timeout, surface); @@ -312,7 +328,7 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_resource_get_version(resource), id); wlr_log(L_DEBUG, "new wl_shell %p (res %p)", wl_surface, wl_surface->resource); wl_resource_set_implementation(wl_surface->resource, - &shell_surface_interface, wl_surface, destroy_shell_surface); + &shell_surface_interface, wl_surface, wl_shell_surface_resource_destroy); wl_signal_init(&wl_surface->events.destroy); wl_signal_init(&wl_surface->events.ping_timeout); @@ -324,6 +340,10 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_signal_init(&wl_surface->events.set_title); wl_signal_init(&wl_surface->events.set_class); + wl_signal_add(&wl_surface->surface->signals.destroy, + &wl_surface->surface_destroy_listener); + wl_surface->surface_destroy_listener.notify = handle_wlr_surface_destroyed; + struct wl_display *display = wl_client_get_display(client); struct wl_event_loop *loop = wl_display_get_event_loop(display); wl_surface->ping_timer = wl_event_loop_add_timer(loop, From 4e70d36e61dd720e9caadb74b39d3a0cd6c8cad7 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 28 Sep 2017 01:36:23 +0200 Subject: [PATCH 13/13] examples/compositor: fix handle_output_frame --- examples/compositor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compositor.c b/examples/compositor.c index 14831820..ae21697a 100644 --- a/examples/compositor.c +++ b/examples/compositor.c @@ -290,7 +290,7 @@ static void handle_output_frame(struct output_state *output, struct wlr_wl_shell_surface *wl_shell_surface; wl_list_for_each(wl_shell_surface, &sample->wl_shell->surfaces, link) { output_frame_handle_surface(sample, wlr_output, ts, - wl_shell_surface->resource, 200, 200); + wl_shell_surface->surface->resource, 200, 200); } struct wlr_xdg_surface_v6 *xdg_surface; struct wlr_xdg_client_v6 *xdg_client;