desktop-shell: implement touch popup grabs
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
389d205b58
commit
76cf1feb3b
@ -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() */
|
||||
|
Loading…
Reference in New Issue
Block a user