diff options
-rw-r--r-- | include/rootston/view.h | 5 | ||||
-rw-r--r-- | include/wlr/types/wlr_wl_shell.h | 52 | ||||
-rw-r--r-- | rootston/wl_shell.c | 17 | ||||
-rw-r--r-- | 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 <assert.h> #include <wayland-server.h> #include <wlr/util/log.h> @@ -5,11 +8,10 @@ #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"); +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 = { |