wl-shell: fix popup grab
This commit is contained in:
parent
f7e7f6271d
commit
821cf92498
|
@ -71,6 +71,7 @@ struct wlr_wl_shell_surface {
|
||||||
struct wlr_wl_shell_surface *parent;
|
struct wlr_wl_shell_surface *parent;
|
||||||
struct wl_list popup_link;
|
struct wl_list popup_link;
|
||||||
struct wl_list popups;
|
struct wl_list popups;
|
||||||
|
bool popup_mapped;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
|
|
|
@ -17,11 +17,39 @@ static void shell_pointer_grab_end(struct wlr_seat_pointer_grab *grab) {
|
||||||
|
|
||||||
struct wlr_wl_shell_surface *popup, *tmp = NULL;
|
struct wlr_wl_shell_surface *popup, *tmp = NULL;
|
||||||
wl_list_for_each_safe(popup, tmp, &popup_grab->popups, grab_link) {
|
wl_list_for_each_safe(popup, tmp, &popup_grab->popups, grab_link) {
|
||||||
|
if (popup->popup_mapped) {
|
||||||
wl_shell_surface_send_popup_done(popup->resource);
|
wl_shell_surface_send_popup_done(popup->resource);
|
||||||
|
popup->popup_mapped = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (grab->seat->pointer_state.grab == grab) {
|
||||||
wlr_seat_pointer_end_grab(grab->seat);
|
wlr_seat_pointer_end_grab(grab->seat);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_pointer_grab_maybe_end(struct wlr_seat_pointer_grab *grab) {
|
||||||
|
struct wlr_wl_shell_popup_grab *popup_grab = grab->data;
|
||||||
|
|
||||||
|
if (grab->seat->pointer_state.grab != grab) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_mapped = false;
|
||||||
|
|
||||||
|
struct wlr_wl_shell_surface *popup, *tmp = NULL;
|
||||||
|
wl_list_for_each_safe(popup, tmp, &popup_grab->popups, grab_link) {
|
||||||
|
if (popup->popup_mapped) {
|
||||||
|
has_mapped = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_mapped) {
|
||||||
|
shell_pointer_grab_end(grab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void shell_pointer_grab_enter(struct wlr_seat_pointer_grab *grab,
|
static void shell_pointer_grab_enter(struct wlr_seat_pointer_grab *grab,
|
||||||
struct wlr_surface *surface, double sx, double sy) {
|
struct wlr_surface *surface, double sx, double sy) {
|
||||||
|
@ -307,6 +335,7 @@ static void shell_surface_protocol_set_popup(struct wl_client *client,
|
||||||
surface->transient_state->y = y;
|
surface->transient_state->y = y;
|
||||||
shell_surface_popup_set_parent(surface, wl_parent);
|
shell_surface_popup_set_parent(surface, wl_parent);
|
||||||
grab->client = surface->client;
|
grab->client = surface->client;
|
||||||
|
surface->popup_mapped = true;
|
||||||
wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab);
|
wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -337,6 +366,7 @@ static void shell_surface_protocol_set_popup(struct wl_client *client,
|
||||||
shell_surface_popup_set_parent(surface, wl_parent);
|
shell_surface_popup_set_parent(surface, wl_parent);
|
||||||
grab->client = surface->client;
|
grab->client = surface->client;
|
||||||
wl_list_insert(&grab->popups, &surface->grab_link);
|
wl_list_insert(&grab->popups, &surface->grab_link);
|
||||||
|
surface->popup_mapped = true;
|
||||||
wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab);
|
wlr_seat_pointer_start_grab(seat_handle->wlr_seat, &grab->pointer_grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +487,16 @@ static void handle_wlr_surface_committed(struct wl_listener *listener,
|
||||||
surface->configured = true;
|
surface->configured = true;
|
||||||
wl_signal_emit(&surface->shell->events.new_surface, surface);
|
wl_signal_emit(&surface->shell->events.new_surface, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (surface->popup_mapped &&
|
||||||
|
surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP &&
|
||||||
|
!surface->surface->texture->valid) {
|
||||||
|
surface->popup_mapped = false;
|
||||||
|
struct wlr_wl_shell_popup_grab *grab =
|
||||||
|
shell_popup_grab_from_seat(surface->shell,
|
||||||
|
surface->popup_state->seat);
|
||||||
|
shell_pointer_grab_maybe_end(&grab->pointer_grab);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shell_surface_ping_timeout(void *user_data) {
|
static int shell_surface_ping_timeout(void *user_data) {
|
||||||
|
@ -611,6 +651,9 @@ struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at(
|
||||||
double *popup_sx, double *popup_sy) {
|
double *popup_sx, double *popup_sy) {
|
||||||
struct wlr_wl_shell_surface *popup;
|
struct wlr_wl_shell_surface *popup;
|
||||||
wl_list_for_each(popup, &surface->popups, popup_link) {
|
wl_list_for_each(popup, &surface->popups, popup_link) {
|
||||||
|
if (!popup->popup_mapped) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
double _popup_sx = popup->transient_state->x;
|
double _popup_sx = popup->transient_state->x;
|
||||||
double _popup_sy = popup->transient_state->y;
|
double _popup_sy = popup->transient_state->y;
|
||||||
int popup_width =
|
int popup_width =
|
||||||
|
|
Loading…
Reference in New Issue