From cd1204f71f7222ea896c94bea3194d3b220845be Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 8 Oct 2017 16:49:37 -0400 Subject: wl-shell: render popups in the right place --- rootston/output.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'rootston') diff --git a/rootston/output.c b/rootston/output.c index d1b2c7de..90ba1eb7 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -97,13 +97,39 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, } } +static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct roots_desktop *desktop, + struct wlr_output *wlr_output, struct timespec *when, double lx, + double ly, float rotation, bool is_child) { + if (is_child || !wlr_wl_shell_surface_is_transient(surface)) { + render_surface(surface->surface, desktop, wlr_output, when, + lx, ly, rotation); + struct wlr_wl_shell_surface *child; + wl_list_for_each(child, &surface->children, child_link) { + render_wl_shell_surface(child, desktop, wlr_output, when, + lx + child->transient_state->x, + ly + child->transient_state->y, + rotation, true); + } + } +} + static void render_view(struct roots_view *view, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when) { - render_surface(view->wlr_surface, desktop, wlr_output, when, - view->x, view->y, view->rotation); - if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { + switch (view->type) { + case ROOTS_XDG_SHELL_V6_VIEW: + render_surface(view->wlr_surface, desktop, wlr_output, when, + view->x, view->y, view->rotation); render_xdg_v6_popups(view->xdg_surface_v6, desktop, wlr_output, when, view->x, view->y, view->rotation); + break; + case ROOTS_WL_SHELL_VIEW: + render_wl_shell_surface(view->wl_shell_surface, desktop, wlr_output, + when, view->x, view->y, view->rotation, false); + break; + case ROOTS_XWAYLAND_VIEW: + render_surface(view->wlr_surface, desktop, wlr_output, when, + view->x, view->y, view->rotation); + break; } } -- cgit v1.2.3 From d4c065e59b1d0275d91dac83bed8cfa54d2e57b5 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 9 Oct 2017 18:36:11 -0400 Subject: wl_shell: map transient surfaces closer to parent --- rootston/output.c | 2 +- rootston/wl_shell.c | 23 ++++++++++++++++++++++- types/wlr_wl_shell.c | 12 ++++++------ 3 files changed, 29 insertions(+), 8 deletions(-) (limited to 'rootston') diff --git a/rootston/output.c b/rootston/output.c index 90ba1eb7..29a4413f 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -100,7 +100,7 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation, bool is_child) { - if (is_child || !wlr_wl_shell_surface_is_transient(surface)) { + if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { render_surface(surface->surface, desktop, wlr_output, when, lx, ly, rotation); struct wlr_wl_shell_surface *child; diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 009a8c06..34f53c7a 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -73,6 +73,14 @@ static void handle_destroy(struct wl_listener *listener, void *data) { free(roots_surface); } +static int shell_surface_compare_equals(const void *item, const void *cmp_to) { + const struct roots_view *view = item; + if (view->type == ROOTS_WL_SHELL_VIEW && view->wl_shell_surface == cmp_to) { + return 0; + } + return -1; +} + void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, wl_shell_surface); @@ -107,7 +115,20 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct roots_view *view = calloc(1, sizeof(struct roots_view)); view->type = ROOTS_WL_SHELL_VIEW; - view->x = view->y = 200; + + if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { + // we need to map it relative to the parent + int i = + list_seq_find(desktop->views, + shell_surface_compare_equals, surface->parent); + if (i != -1) { + struct roots_view *parent = desktop->views->items[i]; + view->x = parent->x + surface->transient_state->x; + view->y = parent->y + surface->transient_state->y; + } + } else { + view->x = view->y = 200; + } view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; view->wlr_surface = surface->surface; diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index c5394d97..6421cc45 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -195,9 +195,9 @@ static void shell_surface_set_toplevel(struct wl_client *client, NULL); } -static void shell_surface_set_parent(struct wlr_wl_shell_surface *surface, +static void popup_set_parent(struct wlr_wl_shell_surface *surface, struct wlr_wl_shell_surface *parent) { - assert(surface); + assert(surface && surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP); if (surface->parent == parent) { return; } @@ -243,7 +243,7 @@ static void shell_surface_set_transient(struct wl_client *client, return; } - shell_surface_set_parent(surface, wl_parent); + surface->parent = wl_parent; transient_state->x = x; transient_state->y = y; transient_state->flags = flags; @@ -307,7 +307,7 @@ static void shell_surface_set_popup(struct wl_client *client, if (surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { surface->transient_state->x = x; surface->transient_state->y = y; - shell_surface_set_parent(surface, wl_parent); + popup_set_parent(surface, wl_parent); grab->client = surface->client; wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab); return; @@ -319,7 +319,6 @@ static void shell_surface_set_popup(struct wl_client *client, wl_client_post_no_memory(client); return; } - shell_surface_set_parent(surface, wl_parent); transient_state->x = x; transient_state->y = y; transient_state->flags = flags; @@ -337,6 +336,7 @@ static void shell_surface_set_popup(struct wl_client *client, shell_surface_set_state(surface, WLR_WL_SHELL_SURFACE_STATE_POPUP, transient_state, popup_state); + popup_set_parent(surface, wl_parent); grab->client = surface->client; wl_list_insert(&grab->popups, &surface->grab_link); wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab); @@ -422,7 +422,7 @@ static void wl_shell_surface_destroy(struct wlr_wl_shell_surface *surface) { struct wlr_wl_shell_surface *child; wl_list_for_each(child, &surface->children, child_link) { - shell_surface_set_parent(child, NULL); + popup_set_parent(child, NULL); } wl_list_remove(&surface->child_link); -- cgit v1.2.3 From fe3c6c929be467b3e1ec860c94c9524a6686bd61 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 10 Oct 2017 10:00:09 -0400 Subject: wl-shell: popup input handling --- include/wlr/types/wlr_wl_shell.h | 9 +++++++++ rootston/desktop.c | 21 +++++++++++++++++++++ rootston/wl_shell.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) (limited to 'rootston') diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 162874e9..6133b80d 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -125,4 +125,13 @@ void wlr_wl_shell_surface_configure(struct wlr_wl_shell_surface *surface, void wlr_wl_shell_surface_popup_done(struct wlr_wl_shell_surface *surface); bool wlr_wl_shell_surface_is_transient(struct wlr_wl_shell_surface *surface); +/** + * Find a popup within this surface at the surface-local coordinates. Returns + * the popup and coordinates in the topmost surface coordinate system or NULL if + * no popup is found at that location. + */ +struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( + struct wlr_wl_shell_surface *surface, double sx, double sy, + double *popup_sx, double *popup_sy); + #endif diff --git a/rootston/desktop.c b/rootston/desktop.c index bef0fad4..d5cac575 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -103,6 +103,12 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, for (int i = desktop->views->length - 1; i >= 0; --i) { struct roots_view *view = desktop->views->items[i]; + if (view->type == ROOTS_WL_SHELL_VIEW && + view->wl_shell_surface->state == + WLR_WL_SHELL_SURFACE_STATE_POPUP) { + continue; + } + double view_sx = lx - view->x; double view_sy = ly - view->y; @@ -138,6 +144,21 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, } } + if (view->type == ROOTS_WL_SHELL_VIEW) { + // TODO: test if this works with rotated views + double popup_sx, popup_sy; + struct wlr_wl_shell_surface *popup = + wlr_wl_shell_surface_popup_at(view->wl_shell_surface, + view_sx, view_sy, &popup_sx, &popup_sy); + + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + return view; + } + } + double sub_x, sub_y; struct wlr_subsurface *subsurface = wlr_surface_subsurface_at(view->wlr_surface, diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 34f53c7a..a629575b 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -138,3 +138,40 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { roots_surface->view = view; list_add(desktop->views, view); } + +struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( + struct wlr_wl_shell_surface *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + struct wlr_wl_shell_surface *popup; + wl_list_for_each(popup, &surface->children, child_link) { + double _popup_sx = popup->transient_state->x; + double _popup_sy = popup->transient_state->y; + int popup_width = + popup->surface->current->buffer_width; + int popup_height = + popup->surface->current->buffer_height; + + struct wlr_wl_shell_surface *_popup = + wlr_wl_shell_surface_popup_at(popup, + popup->transient_state->x, + popup->transient_state->y, + popup_sx, popup_sy); + if (_popup) { + *popup_sx = sx + _popup_sx; + *popup_sy = sy + _popup_sy; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + if (pixman_region32_contains_point(&popup->surface->current->input, + sx - _popup_sx, sy - _popup_sy, NULL)) { + *popup_sx = _popup_sx; + *popup_sy = _popup_sy; + return popup; + } + } + } + + return NULL; +} -- cgit v1.2.3 From f7e7f6271ddb44ed80ab928116ab731a7d878edc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 10 Oct 2017 10:54:10 -0400 Subject: wl-shell: cleanup --- include/wlr/types/wlr_wl_shell.h | 6 +- rootston/output.c | 10 +-- rootston/wl_shell.c | 37 ---------- types/wlr_wl_shell.c | 151 +++++++++++++++++++++++---------------- 4 files changed, 98 insertions(+), 106 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index e768d9d5..bea92b8b 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -69,8 +69,8 @@ struct wlr_wl_shell_surface { struct wl_listener surface_commit_listener; struct wlr_wl_shell_surface *parent; - struct wl_list child_link; - struct wl_list children; // transient and popups + struct wl_list popup_link; + struct wl_list popups; struct { struct wl_signal destroy; @@ -124,8 +124,6 @@ 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, enum wl_shell_surface_resize edges, int32_t width, int32_t height); -void wlr_wl_shell_surface_popup_done(struct wlr_wl_shell_surface *surface); -bool wlr_wl_shell_surface_is_transient(struct wlr_wl_shell_surface *surface); /** * Find a popup within this surface at the surface-local coordinates. Returns diff --git a/rootston/output.c b/rootston/output.c index 29a4413f..2c061739 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -103,11 +103,11 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, struct if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { render_surface(surface->surface, desktop, wlr_output, when, lx, ly, rotation); - struct wlr_wl_shell_surface *child; - wl_list_for_each(child, &surface->children, child_link) { - render_wl_shell_surface(child, desktop, wlr_output, when, - lx + child->transient_state->x, - ly + child->transient_state->y, + struct wlr_wl_shell_surface *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + render_wl_shell_surface(popup, desktop, wlr_output, when, + lx + popup->transient_state->x, + ly + popup->transient_state->y, rotation, true); } } diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index a629575b..34f53c7a 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -138,40 +138,3 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { roots_surface->view = view; list_add(desktop->views, view); } - -struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( - struct wlr_wl_shell_surface *surface, double sx, double sy, - double *popup_sx, double *popup_sy) { - struct wlr_wl_shell_surface *popup; - wl_list_for_each(popup, &surface->children, child_link) { - double _popup_sx = popup->transient_state->x; - double _popup_sy = popup->transient_state->y; - int popup_width = - popup->surface->current->buffer_width; - int popup_height = - popup->surface->current->buffer_height; - - struct wlr_wl_shell_surface *_popup = - wlr_wl_shell_surface_popup_at(popup, - popup->transient_state->x, - popup->transient_state->y, - popup_sx, popup_sy); - if (_popup) { - *popup_sx = sx + _popup_sx; - *popup_sy = sy + _popup_sy; - return _popup; - } - - if ((sx > _popup_sx && sx < _popup_sx + popup_width) && - (sy > _popup_sy && sy < _popup_sy + popup_height)) { - if (pixman_region32_contains_point(&popup->surface->current->input, - sx - _popup_sx, sy - _popup_sy, NULL)) { - *popup_sx = _popup_sx; - *popup_sy = _popup_sy; - return popup; - } - } - } - - return NULL; -} diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index de018865..5851c63a 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -10,7 +10,7 @@ #include #include -static const char *wlr_wl_shell_surface_role = "wl_shell_surface"; +static const char *wlr_wl_shell_surface_role = "wl-shell-surface"; static void shell_pointer_grab_end(struct wlr_seat_pointer_grab *grab) { struct wlr_wl_shell_popup_grab *popup_grab = grab->data; @@ -67,7 +67,7 @@ static const struct wlr_pointer_grab_interface shell_pointer_grab_impl = { .axis = shell_pointer_grab_axis, }; -static void shell_surface_pong(struct wl_client *client, +static void shell_surface_protocol_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); @@ -79,7 +79,7 @@ static void shell_surface_pong(struct wl_client *client, surface->ping_serial = 0; } -static void shell_surface_move(struct wl_client *client, +static void shell_surface_protocol_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"); @@ -128,7 +128,8 @@ static struct wlr_wl_shell_popup_grab *shell_popup_grab_from_seat( return shell_grab; } -static void shell_destroy_popup_state(struct wlr_wl_shell_surface *surface) { +static void shell_surface_destroy_popup_state( + struct wlr_wl_shell_surface *surface) { if (surface->popup_state) { wl_list_remove(&surface->grab_link); struct wlr_wl_shell_popup_grab *grab = @@ -145,7 +146,7 @@ static void shell_destroy_popup_state(struct wlr_wl_shell_surface *surface) { } -static void shell_surface_resize(struct wl_client *client, +static void shell_surface_protocol_resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, enum wl_shell_surface_resize edges) { wlr_log(L_DEBUG, "got shell surface resize"); @@ -177,13 +178,13 @@ static void shell_surface_set_state(struct wlr_wl_shell_surface *surface, surface->state = state; free(surface->transient_state); surface->transient_state = transient_state; - shell_destroy_popup_state(surface); + shell_surface_destroy_popup_state(surface); surface->popup_state = popup_state; wl_signal_emit(&surface->events.set_state, surface); } -static void shell_surface_set_toplevel(struct wl_client *client, +static void shell_surface_protocol_set_toplevel(struct wl_client *client, struct wl_resource *resource) { wlr_log(L_DEBUG, "got shell surface toplevel"); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); @@ -191,7 +192,7 @@ static void shell_surface_set_toplevel(struct wl_client *client, NULL); } -static void popup_set_parent(struct wlr_wl_shell_surface *surface, +static void shell_surface_popup_set_parent(struct wlr_wl_shell_surface *surface, struct wlr_wl_shell_surface *parent) { assert(surface && surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP); if (surface->parent == parent) { @@ -199,13 +200,13 @@ static void popup_set_parent(struct wlr_wl_shell_surface *surface, } surface->parent = parent; if (parent) { - wl_list_remove(&surface->child_link); - wl_list_insert(&parent->children, &surface->child_link); + wl_list_remove(&surface->popup_link); + wl_list_insert(&parent->popups, &surface->popup_link); } } -static struct wlr_wl_shell_surface *shell_get_shell_surface(struct wlr_wl_shell *shell, - struct wlr_surface *surface) { +static struct wlr_wl_shell_surface *shell_find_shell_surface( + struct wlr_wl_shell *shell, struct wlr_surface *surface) { if (surface) { struct wlr_wl_shell_surface *wl_surface; wl_list_for_each(wl_surface, &shell->surfaces, link) { @@ -217,7 +218,7 @@ static struct wlr_wl_shell_surface *shell_get_shell_surface(struct wlr_wl_shell return NULL; } -static void shell_surface_set_transient(struct wl_client *client, +static void shell_surface_protocol_set_transient(struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent_resource, int32_t x, int32_t y, enum wl_shell_surface_transient flags) { wlr_log(L_DEBUG, "got shell surface transient"); @@ -226,7 +227,8 @@ static void shell_surface_set_transient(struct wl_client *client, wl_resource_get_user_data(parent_resource); // TODO: check if parent_resource == NULL? - struct wlr_wl_shell_surface *wl_parent = shell_get_shell_surface(surface->shell, parent); + struct wlr_wl_shell_surface *wl_parent = + shell_find_shell_surface(surface->shell, parent); if (!wl_parent) { return; @@ -248,7 +250,7 @@ static void shell_surface_set_transient(struct wl_client *client, transient_state, NULL); } -static void shell_surface_set_fullscreen(struct wl_client *client, +static void shell_surface_protocol_set_fullscreen(struct wl_client *client, struct wl_resource *resource, enum wl_shell_surface_fullscreen_method method, uint32_t framerate, struct wl_resource *output_resource) { @@ -281,7 +283,7 @@ static void shell_surface_set_fullscreen(struct wl_client *client, } -static void shell_surface_set_popup(struct wl_client *client, +static void shell_surface_protocol_set_popup(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, struct wl_resource *parent_resource, int32_t x, int32_t y, enum wl_shell_surface_transient flags) { @@ -298,12 +300,12 @@ static void shell_surface_set_popup(struct wl_client *client, } struct wlr_wl_shell_surface *wl_parent = - shell_get_shell_surface(surface->shell, parent); + shell_find_shell_surface(surface->shell, parent); if (surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { surface->transient_state->x = x; surface->transient_state->y = y; - popup_set_parent(surface, wl_parent); + shell_surface_popup_set_parent(surface, wl_parent); grab->client = surface->client; wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab); return; @@ -332,13 +334,13 @@ static void shell_surface_set_popup(struct wl_client *client, shell_surface_set_state(surface, WLR_WL_SHELL_SURFACE_STATE_POPUP, transient_state, popup_state); - popup_set_parent(surface, wl_parent); + shell_surface_popup_set_parent(surface, wl_parent); grab->client = surface->client; wl_list_insert(&grab->popups, &surface->grab_link); wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab); } -static void shell_surface_set_maximized(struct wl_client *client, +static void shell_surface_protocol_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); @@ -366,7 +368,7 @@ static void shell_surface_set_maximized(struct wl_client *client, free(event); } -static void shell_surface_set_title(struct wl_client *client, +static void shell_surface_protocol_set_title(struct wl_client *client, struct wl_resource *resource, const char *title) { wlr_log(L_DEBUG, "new shell surface title: %s", title); struct wlr_wl_shell_surface *surface = wl_resource_get_user_data(resource); @@ -382,7 +384,7 @@ static void shell_surface_set_title(struct wl_client *client, wl_signal_emit(&surface->events.set_title, surface); } -static void shell_surface_set_class(struct wl_client *client, +static void shell_surface_protocol_set_class(struct wl_client *client, 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); @@ -398,29 +400,29 @@ static void shell_surface_set_class(struct wl_client *client, wl_signal_emit(&surface->events.set_class, surface); } -struct wl_shell_surface_interface shell_surface_interface = { - .pong = shell_surface_pong, - .move = shell_surface_move, - .resize = shell_surface_resize, - .set_toplevel = shell_surface_set_toplevel, - .set_transient = shell_surface_set_transient, - .set_fullscreen = shell_surface_set_fullscreen, - .set_popup = shell_surface_set_popup, - .set_maximized = shell_surface_set_maximized, - .set_title = shell_surface_set_title, - .set_class = shell_surface_set_class, +static const struct wl_shell_surface_interface shell_surface_impl = { + .pong = shell_surface_protocol_pong, + .move = shell_surface_protocol_move, + .resize = shell_surface_protocol_resize, + .set_toplevel = shell_surface_protocol_set_toplevel, + .set_transient = shell_surface_protocol_set_transient, + .set_fullscreen = shell_surface_protocol_set_fullscreen, + .set_popup = shell_surface_protocol_set_popup, + .set_maximized = shell_surface_protocol_set_maximized, + .set_title = shell_surface_protocol_set_title, + .set_class = shell_surface_protocol_set_class, }; -static void wl_shell_surface_destroy(struct wlr_wl_shell_surface *surface) { +static void shell_surface_destroy(struct wlr_wl_shell_surface *surface) { wl_signal_emit(&surface->events.destroy, surface); - shell_destroy_popup_state(surface); + shell_surface_destroy_popup_state(surface); wl_resource_set_user_data(surface->resource, NULL); struct wlr_wl_shell_surface *child; - wl_list_for_each(child, &surface->children, child_link) { - popup_set_parent(child, NULL); + wl_list_for_each(child, &surface->popups, popup_link) { + shell_surface_popup_set_parent(child, NULL); } - wl_list_remove(&surface->child_link); + wl_list_remove(&surface->popup_link); wl_list_remove(&surface->link); wl_list_remove(&surface->surface_destroy_listener.link); @@ -432,10 +434,10 @@ static void wl_shell_surface_destroy(struct wlr_wl_shell_surface *surface) { free(surface); } -static void wl_shell_surface_resource_destroy(struct wl_resource *resource) { +static void 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); + shell_surface_destroy(surface); } } @@ -443,7 +445,7 @@ 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); + shell_surface_destroy(surface); } static void handle_wlr_surface_committed(struct wl_listener *listener, void *data) { @@ -457,7 +459,7 @@ static void handle_wlr_surface_committed(struct wl_listener *listener, } } -static int wlr_wl_shell_surface_ping_timeout(void *user_data) { +static int shell_surface_ping_timeout(void *user_data) { struct wlr_wl_shell_surface *surface = user_data; wl_signal_emit(&surface->events.ping_timeout, surface); @@ -465,7 +467,7 @@ static int wlr_wl_shell_surface_ping_timeout(void *user_data) { return 1; } -static void wl_shell_get_shell_surface(struct wl_client *client, +static void shell_protocol_get_shell_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) { struct wlr_surface *surface = wl_resource_get_user_data(surface_resource); @@ -482,8 +484,8 @@ static void wl_shell_get_shell_surface(struct wl_client *client, return; } wl_list_init(&wl_surface->grab_link); - wl_list_init(&wl_surface->child_link); - wl_list_init(&wl_surface->children); + wl_list_init(&wl_surface->popup_link); + wl_list_init(&wl_surface->popups); wl_surface->shell = wl_shell; wl_surface->client = client; @@ -494,8 +496,8 @@ static void wl_shell_get_shell_surface(struct wl_client *client, 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, - wl_shell_surface_resource_destroy); + &shell_surface_impl, wl_surface, + shell_surface_resource_destroy); wl_signal_init(&wl_surface->events.destroy); wl_signal_init(&wl_surface->events.ping_timeout); @@ -518,7 +520,7 @@ static void wl_shell_get_shell_surface(struct wl_client *client, 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, - wlr_wl_shell_surface_ping_timeout, wl_surface); + shell_surface_ping_timeout, wl_surface); if (wl_surface->ping_timer == NULL) { wl_client_post_no_memory(client); } @@ -526,15 +528,15 @@ static void wl_shell_get_shell_surface(struct wl_client *client, wl_list_insert(&wl_shell->surfaces, &wl_surface->link); } -static struct wl_shell_interface wl_shell_impl = { - .get_shell_surface = wl_shell_get_shell_surface +static struct wl_shell_interface shell_impl = { + .get_shell_surface = shell_protocol_get_shell_surface }; -static void wl_shell_destroy(struct wl_resource *resource) { +static void shell_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(resource)); } -static void wl_shell_bind(struct wl_client *wl_client, void *_wl_shell, +static void shell_bind(struct wl_client *wl_client, void *_wl_shell, uint32_t version, uint32_t id) { struct wlr_wl_shell *wl_shell = _wl_shell; assert(wl_client && wl_shell); @@ -546,8 +548,8 @@ static void wl_shell_bind(struct wl_client *wl_client, void *_wl_shell, } struct wl_resource *wl_resource = wl_resource_create(wl_client, &wl_shell_interface, version, id); - wl_resource_set_implementation(wl_resource, &wl_shell_impl, wl_shell, - wl_shell_destroy); + wl_resource_set_implementation(wl_resource, &shell_impl, wl_shell, + shell_destroy); wl_list_insert(&wl_shell->wl_resources, wl_resource_get_link(wl_resource)); } @@ -558,7 +560,7 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) { } wl_shell->ping_timeout = 10000; struct wl_global *wl_global = wl_global_create(display, &wl_shell_interface, - 1, wl_shell, wl_shell_bind); + 1, wl_shell, shell_bind); if (!wl_global) { free(wl_shell); return NULL; @@ -604,10 +606,39 @@ void wlr_wl_shell_surface_configure(struct wlr_wl_shell_surface *surface, 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); -} +struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( + struct wlr_wl_shell_surface *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + struct wlr_wl_shell_surface *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + double _popup_sx = popup->transient_state->x; + double _popup_sy = popup->transient_state->y; + int popup_width = + popup->surface->current->buffer_width; + int popup_height = + popup->surface->current->buffer_height; + + struct wlr_wl_shell_surface *_popup = + wlr_wl_shell_surface_popup_at(popup, + popup->transient_state->x, + popup->transient_state->y, + popup_sx, popup_sy); + if (_popup) { + *popup_sx = sx + _popup_sx; + *popup_sy = sy + _popup_sy; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + if (pixman_region32_contains_point(&popup->surface->current->input, + sx - _popup_sx, sy - _popup_sy, NULL)) { + *popup_sx = _popup_sx; + *popup_sy = _popup_sy; + return popup; + } + } + } -bool wlr_wl_shell_surface_is_transient(struct wlr_wl_shell_surface *surface) { - return surface->parent != NULL; + return NULL; } -- cgit v1.2.3