diff options
| -rw-r--r-- | include/rootston/desktop.h | 2 | ||||
| -rw-r--r-- | include/wlr/types/wlr_wl_shell.h | 17 | ||||
| -rw-r--r-- | rootston/desktop.c | 6 | ||||
| -rw-r--r-- | rootston/meson.build | 3 | ||||
| -rw-r--r-- | rootston/wl_shell.c | 20 | ||||
| -rw-r--r-- | types/wlr_wl_shell.c | 52 | 
6 files changed, 97 insertions, 3 deletions
| 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 <assert.h> +#include <stdlib.h> +#include <stdbool.h> +#include <wayland-server.h> +#include <wlr/types/wlr_box.h> +#include <wlr/types/wlr_surface.h> +#include <wlr/types/wlr_wl_shell.h> +#include <wlr/util/log.h> +#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 <wlr/util/log.h>  #include <wlr/types/wlr_wl_shell.h>  #include <stdlib.h> +#include <wayland-server-protocol.h>  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); +} | 
