desktop-shell: implement touch popup grabs

Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
Jonny Lamb 2014-08-20 11:27:10 +02:00 committed by Pekka Paalanen
parent 389d205b58
commit 76cf1feb3b
1 changed files with 143 additions and 12 deletions

View File

@ -223,9 +223,11 @@ struct shell_seat {
struct {
struct weston_pointer_grab grab;
struct weston_touch_grab touch_grab;
struct wl_list surfaces_list;
struct wl_client *client;
int32_t initial_up;
enum { POINTER, TOUCH } type;
} popup_grab;
};
@ -322,6 +324,8 @@ get_default_view(struct weston_surface *surface)
static void
popup_grab_end(struct weston_pointer *pointer);
static void
touch_popup_grab_end(struct weston_touch *touch);
static void
shell_grab_start(struct shell_grab *grab,
@ -333,6 +337,8 @@ shell_grab_start(struct shell_grab *grab,
struct desktop_shell *shell = shsurf->shell;
popup_grab_end(pointer);
if (pointer->seat->touch)
touch_popup_grab_end(pointer->seat->touch);
grab->grab.interface = interface;
grab->shsurf = shsurf;
@ -497,6 +503,7 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
{
struct desktop_shell *shell = shsurf->shell;
touch_popup_grab_end(touch);
if (touch->seat->pointer)
popup_grab_end(touch->seat->pointer);
@ -3116,6 +3123,81 @@ static const struct weston_pointer_grab_interface popup_grab_interface = {
popup_grab_cancel,
};
static void
touch_popup_grab_down(struct weston_touch_grab *grab, uint32_t time,
int touch_id, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_resource *resource;
struct shell_seat *shseat =
container_of(grab, struct shell_seat, popup_grab.touch_grab);
struct wl_display *display = shseat->seat->compositor->wl_display;
uint32_t serial;
struct wl_list *resource_list;
resource_list = &grab->touch->focus_resource_list;
if (!wl_list_empty(resource_list)) {
serial = wl_display_get_serial(display);
wl_resource_for_each(resource, resource_list) {
wl_touch_send_down(resource, serial, time,
grab->touch->focus->surface->resource,
touch_id, sx, sy);
}
}
}
static void
touch_popup_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
{
struct wl_resource *resource;
struct shell_seat *shseat =
container_of(grab, struct shell_seat, popup_grab.touch_grab);
struct wl_display *display = shseat->seat->compositor->wl_display;
uint32_t serial;
struct wl_list *resource_list;
resource_list = &grab->touch->focus_resource_list;
if (!wl_list_empty(resource_list)) {
serial = wl_display_get_serial(display);
wl_resource_for_each(resource, resource_list) {
wl_touch_send_up(resource, serial, time, touch_id);
}
}
}
static void
touch_popup_grab_motion(struct weston_touch_grab *grab, uint32_t time,
int touch_id, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_resource *resource;
struct wl_list *resource_list;
resource_list = &grab->touch->focus_resource_list;
if (!wl_list_empty(resource_list)) {
wl_resource_for_each(resource, resource_list) {
wl_touch_send_motion(resource, time, touch_id, sx, sy);
}
}
}
static void
touch_popup_grab_frame(struct weston_touch_grab *grab)
{
}
static void
touch_popup_grab_cancel(struct weston_touch_grab *grab)
{
touch_popup_grab_end(grab->touch);
}
static const struct weston_touch_grab_interface touch_popup_grab_interface = {
touch_popup_grab_down,
touch_popup_grab_up,
touch_popup_grab_motion,
touch_popup_grab_frame,
touch_popup_grab_cancel,
};
static void
shell_surface_send_popup_done(struct shell_surface *shsurf)
{
@ -3155,21 +3237,59 @@ popup_grab_end(struct weston_pointer *pointer)
}
static void
add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat)
touch_popup_grab_end(struct weston_touch *touch)
{
struct weston_touch_grab *grab = touch->grab;
struct shell_seat *shseat =
container_of(grab, struct shell_seat, popup_grab.touch_grab);
struct shell_surface *shsurf;
struct shell_surface *prev = NULL;
if (touch->grab->interface == &touch_popup_grab_interface) {
weston_touch_end_grab(grab->touch);
shseat->popup_grab.client = NULL;
shseat->popup_grab.touch_grab.interface = NULL;
assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
/* Send the popup_done event to all the popups open */
wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
shell_surface_send_popup_done(shsurf);
shsurf->popup.shseat = NULL;
if (prev) {
wl_list_init(&prev->popup.grab_link);
}
prev = shsurf;
}
wl_list_init(&prev->popup.grab_link);
wl_list_init(&shseat->popup_grab.surfaces_list);
}
}
static void
add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat, int32_t type)
{
struct weston_seat *seat = shseat->seat;
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
shseat->popup_grab.type = type;
shseat->popup_grab.client = wl_resource_get_client(shsurf->resource);
shseat->popup_grab.grab.interface = &popup_grab_interface;
/* We must make sure here that this popup was opened after
* a mouse press, and not just by moving around with other
* popups already open. */
if (shseat->seat->pointer->button_count > 0)
shseat->popup_grab.initial_up = 0;
if (type == POINTER) {
shseat->popup_grab.grab.interface = &popup_grab_interface;
/* We must make sure here that this popup was opened after
* a mouse press, and not just by moving around with other
* popups already open. */
if (shseat->seat->pointer->button_count > 0)
shseat->popup_grab.initial_up = 0;
} else if (type == TOUCH) {
shseat->popup_grab.touch_grab.interface = &touch_popup_grab_interface;
}
wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
if (type == POINTER)
weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
else if (type == TOUCH)
weston_touch_start_grab(seat->touch, &shseat->popup_grab.touch_grab);
} else {
wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
}
@ -3183,8 +3303,13 @@ remove_popup_grab(struct shell_surface *shsurf)
wl_list_remove(&shsurf->popup.grab_link);
wl_list_init(&shsurf->popup.grab_link);
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
shseat->popup_grab.grab.interface = NULL;
if (shseat->popup_grab.type == POINTER) {
weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
shseat->popup_grab.grab.interface = NULL;
} else if (shseat->popup_grab.type == TOUCH) {
weston_touch_end_grab(shseat->popup_grab.touch_grab.touch);
shseat->popup_grab.touch_grab.interface = NULL;
}
}
}
@ -3203,7 +3328,10 @@ shell_map_popup(struct shell_surface *shsurf)
if (shseat->seat->pointer &&
shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
add_popup_grab(shsurf, shseat);
add_popup_grab(shsurf, shseat, POINTER);
} else if (shseat->seat->touch &&
shseat->seat->touch->grab_serial == shsurf->popup.serial) {
add_popup_grab(shsurf, shseat, TOUCH);
} else {
shell_surface_send_popup_done(shsurf);
shseat->popup_grab.client = NULL;
@ -5014,9 +5142,12 @@ idle_handler(struct wl_listener *listener, void *data)
container_of(listener, struct desktop_shell, idle_listener);
struct weston_seat *seat;
wl_list_for_each(seat, &shell->compositor->seat_list, link)
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
if (seat->pointer)
popup_grab_end(seat->pointer);
if (seat->touch)
touch_popup_grab_end(seat->touch);
}
shell_fade(shell, FADE_OUT);
/* lock() is called from shell_fade_done() */