From 981221c9da5cbebbdd84fcdc0b6ad1a860c73132 Mon Sep 17 00:00:00 2001 From: Jaehoon Jeong Date: Tue, 6 Oct 2015 15:35:05 +0900 Subject: [PATCH] shell: Add popup grab Change-Id: I0851d7ed9611c7ae65823ddb103a90aaadf2454f --- src/lib/desktop-shell/desktop-shell-internal.h | 8 +- src/lib/desktop-shell/shell-surface.c | 161 ++++++++++++++++++++++--- src/lib/desktop-shell/wl-shell.c | 2 +- src/lib/desktop-shell/xdg-shell.c | 2 +- 4 files changed, 154 insertions(+), 19 deletions(-) diff --git a/src/lib/desktop-shell/desktop-shell-internal.h b/src/lib/desktop-shell/desktop-shell-internal.h index 1381118..be33f2a 100644 --- a/src/lib/desktop-shell/desktop-shell-internal.h +++ b/src/lib/desktop-shell/desktop-shell-internal.h @@ -99,8 +99,8 @@ struct shell_surface pepper_bool_t has_next_geometry; - const void *old_grab; - void *old_grab_data; + const void *old_pointer_grab; + void *old_pointer_grab_data; struct { @@ -127,6 +127,8 @@ struct shell_surface double x, y; uint32_t flags; pepper_seat_t *seat; + uint32_t serial; + pepper_bool_t button_up; } popup; struct @@ -218,7 +220,7 @@ shell_surface_set_toplevel(shell_surface_t *shsurf); void shell_surface_set_popup(shell_surface_t *shsurf, pepper_seat_t *seat, pepper_surface_t *parent, - double x, double y, uint32_t flags); + double x, double y, uint32_t flags, uint32_t serial); void shell_surface_set_transient(shell_surface_t *shsurf, pepper_surface_t *parent, diff --git a/src/lib/desktop-shell/shell-surface.c b/src/lib/desktop-shell/shell-surface.c index e6d023e..8a0bbad 100644 --- a/src/lib/desktop-shell/shell-surface.c +++ b/src/lib/desktop-shell/shell-surface.c @@ -61,12 +61,20 @@ handle_surface_commit(pepper_event_listener_t *listener, } static void +shell_surface_end_popup_grab(shell_surface_t *shsurf); + +static void handle_surface_destroy(pepper_event_listener_t *listener, pepper_object_t *surface, uint32_t id, void *info, void *data) { shell_surface_t *shsurf = data; shell_surface_t *child, *tmp; + if (shsurf->type == SHELL_SURFACE_TYPE_POPUP) + { + shell_surface_end_popup_grab(shsurf); + } + pepper_event_listener_remove(shsurf->surface_destroy_listener); pepper_event_listener_remove(shsurf->surface_commit_listener); @@ -380,14 +388,16 @@ shell_surface_set_popup(shell_surface_t *shsurf, pepper_surface_t *parent, double x, double y, - uint32_t flags) + uint32_t flags, + uint32_t serial) { shell_surface_set_parent(shsurf, parent); - shsurf->popup.x = x; - shsurf->popup.y = y; - shsurf->popup.flags = flags; - shsurf->popup.seat = seat; + shsurf->popup.x = x; + shsurf->popup.y = y; + shsurf->popup.flags = flags; + shsurf->popup.seat = seat; + shsurf->popup.serial = serial; shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_POPUP); } @@ -729,8 +739,6 @@ shell_surface_set_initial_position(shell_surface_t *shsurf) static void shell_surface_map_toplevel(shell_surface_t *shsurf) { - - /* Restore original geometry */ if (shsurf->type == SHELL_SURFACE_TYPE_FULLSCREEN || shsurf->type == SHELL_SURFACE_TYPE_MAXIMIZED || shsurf->type == SHELL_SURFACE_TYPE_MINIMIZED) @@ -746,6 +754,131 @@ shell_surface_map_toplevel(shell_surface_t *shsurf) } static void +pointer_popup_grab_motion(pepper_pointer_t *pointer, void *data, + uint32_t time, double x, double y) +{ + double vx, vy; + pepper_compositor_t *compositor = pepper_pointer_get_compositor(pointer); + pepper_view_t *view = pepper_compositor_pick_view(compositor, x, y, &vx, &vy); + + pepper_pointer_set_focus(pointer, view); + pepper_pointer_send_motion(pointer, time, vx, vy); +} + +static struct wl_client * +pepper_view_get_client(pepper_view_t *view) +{ + pepper_surface_t *surface = pepper_view_get_surface(view); + if (surface) + { + struct wl_resource *resource = pepper_surface_get_resource(surface); + if (resource) + return wl_resource_get_client(resource); + } + + return NULL; +} + +static void +pointer_popup_grab_button(pepper_pointer_t *pointer, void *data, + uint32_t time, uint32_t button, uint32_t state) +{ + shell_surface_t *shsurf = data; + struct wl_client *client = NULL; + pepper_view_t *focus; + + focus = pepper_pointer_get_focus(pointer); + + if (focus) + client = pepper_view_get_client(focus); + + /* The popup_done event is sent out when a popup grab is broken, that is, when the user + * clicks a surface that doesn't belong to the client owning the popup surface. */ + + if (client == shsurf->client) + { + pepper_pointer_send_button(pointer, time, button, state); + } + else if (shsurf->popup.button_up) + { + shell_surface_end_popup_grab(data); + } + + if (state == WL_POINTER_BUTTON_STATE_RELEASED) + shsurf->popup.button_up = PEPPER_TRUE; +} + +static void +pointer_popup_grab_axis(pepper_pointer_t *pointer, void *data, + uint32_t time, uint32_t axis, double value) +{ + /* TODO */ +} + +static void +pointer_popup_grab_cancel(pepper_pointer_t *pointer, void *data) +{ + shell_surface_end_popup_grab(data); +} + +static pepper_pointer_grab_t pointer_popup_grab = +{ + pointer_popup_grab_motion, + pointer_popup_grab_button, + pointer_popup_grab_axis, + pointer_popup_grab_cancel, +}; + +static void +shell_surface_send_popup_done(shell_surface_t *shsurf) +{ + if (shsurf->resource) + { + if (shsurf_is_xdg_popup(shsurf)) + xdg_popup_send_popup_done(shsurf->resource); + else if (shsurf_is_wl_shell_surface(shsurf) && shsurf->type == SHELL_SURFACE_TYPE_POPUP ) + wl_shell_surface_send_popup_done(shsurf->resource); + } +} + +static void +shell_surface_end_popup_grab(shell_surface_t *shsurf) +{ + pepper_pointer_t *pointer = pepper_seat_get_pointer(shsurf->popup.seat); + + if(pointer) + { + const pepper_pointer_grab_t *grab = pepper_pointer_get_grab(pointer); + if (grab == &pointer_popup_grab ) + pepper_pointer_set_grab(pointer, + shsurf->old_pointer_grab, + shsurf->old_pointer_grab_data); + } + + shell_surface_send_popup_done(shsurf); +} + +static void +shell_surface_add_popup_grab(shell_surface_t *shsurf) +{ + pepper_pointer_t *pointer = pepper_seat_get_pointer(shsurf->popup.seat); + + /* TODO: Find the object that serial belongs to */ + + if (pointer) + { + shsurf->old_pointer_grab = pepper_pointer_get_grab(pointer); + shsurf->old_pointer_grab_data = pepper_pointer_get_grab_data(pointer); + + pepper_pointer_set_grab(pointer, &pointer_popup_grab, shsurf); + + shsurf->popup.button_up = PEPPER_FALSE; + } + + /* TODO: touch */ +} + +static void shell_surface_map_popup(shell_surface_t *shsurf) { shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell); @@ -758,7 +891,7 @@ shell_surface_map_popup(shell_surface_t *shsurf) pepper_view_stack_top(shsurf->view, PEPPER_TRUE); - /* TODO: add_popup_grab(), but how? */ + shell_surface_add_popup_grab(shsurf); } static void @@ -948,7 +1081,7 @@ pointer_move_grab_button(pepper_pointer_t *pointer, void *data, if (button == BTN_LEFT && state == PEPPER_BUTTON_STATE_RELEASED) { shell_surface_t *shsurf = data; - pepper_pointer_set_grab(pointer, shsurf->old_grab, shsurf->old_grab_data); + pepper_pointer_set_grab(pointer, shsurf->old_pointer_grab, shsurf->old_pointer_grab_data); } } @@ -998,8 +1131,8 @@ shell_surface_move(shell_surface_t *shsurf, pepper_seat_t *seat, uint32_t serial shsurf->move.dx = vx - px; shsurf->move.dy = vy - py; - shsurf->old_grab = pepper_pointer_get_grab(pointer); - shsurf->old_grab_data = pepper_pointer_get_grab_data(pointer); + shsurf->old_pointer_grab = pepper_pointer_get_grab(pointer); + shsurf->old_pointer_grab_data = pepper_pointer_get_grab_data(pointer); pepper_pointer_set_grab(pointer, &pointer_move_grab, shsurf); } @@ -1038,7 +1171,7 @@ pointer_resize_grab_button(pepper_pointer_t *pointer, void *data, { shell_surface_t *shsurf = data; - pepper_pointer_set_grab(pointer, shsurf->old_grab, shsurf->old_grab_data); + pepper_pointer_set_grab(pointer, shsurf->old_pointer_grab, shsurf->old_pointer_grab_data); shsurf->resize.resizing = PEPPER_FALSE; shsurf->resize.edges = 0; } @@ -1093,7 +1226,7 @@ shell_surface_resize(shell_surface_t *shsurf, pepper_seat_t *seat, uint32_t seri shsurf->send_configure(shsurf, 0, 0); } - shsurf->old_grab = pepper_pointer_get_grab(pointer); - shsurf->old_grab_data = pepper_pointer_get_grab_data(pointer); + shsurf->old_pointer_grab = pepper_pointer_get_grab(pointer); + shsurf->old_pointer_grab_data = pepper_pointer_get_grab_data(pointer); pepper_pointer_set_grab(pointer, &pointer_resize_grab, shsurf); } diff --git a/src/lib/desktop-shell/wl-shell.c b/src/lib/desktop-shell/wl-shell.c index 4f76adc..5c566d1 100644 --- a/src/lib/desktop-shell/wl-shell.c +++ b/src/lib/desktop-shell/wl-shell.c @@ -101,7 +101,7 @@ wl_shell_surface_set_popup(struct wl_client *client, } parent = wl_resource_get_user_data(parent_res); - shell_surface_set_popup(shsurf, seat, parent, x, y, flags); + shell_surface_set_popup(shsurf, seat, parent, x, y, flags, serial); } static void diff --git a/src/lib/desktop-shell/xdg-shell.c b/src/lib/desktop-shell/xdg-shell.c index a14bad3..ca0430c 100644 --- a/src/lib/desktop-shell/xdg-shell.c +++ b/src/lib/desktop-shell/xdg-shell.c @@ -320,7 +320,7 @@ xdg_shell_get_xdg_popup(struct wl_client *client, if (!shsurf) wl_client_post_no_memory(client); - shell_surface_set_popup(shsurf, seat, parent, x, y, 0); + shell_surface_set_popup(shsurf, seat, parent, x, y, 0, serial); } static void -- 2.7.4