From edafaa079f1c5ebe201bac33ddf3c476479c3f1f Mon Sep 17 00:00:00 2001 From: Carlos Alberto Lopez Perez Date: Thu, 18 Jul 2024 11:43:26 +0100 Subject: [PATCH] wl: do not set to null the surface and target at touch_on_up() On a multitouch screen, when several fingers are on the screen at the same time, if we set to null surface and target on touch_on_up() then we stop all the ongoing touch gestures and not only the one of the finger that caused the up event. That is becasue touch_on_motion() will refuse to process further events if surface or target are null. Instead of doing that do not set to null this pointers on the touch_on_up() event. The value of those will be set again on the next touch_on_down() event in any case. Also make seat->touch_target a weak reference, that way if the CogViewport gets destroyed before the touch-move and/or touch-up events arrive it will be set to NULL automatically and we avoid use-after-free of a stale pointer. Related: https://github.com/Igalia/cog/issues/698 Related: https://bugs.webkit.org/show_bug.cgi?id=270516 --- platform/wayland/cog-platform-wl.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index c6fc2e3c..5722973d 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -768,7 +768,7 @@ touch_on_down(void *data, CogWlViewport *viewport = wl_surface_get_user_data( surface); // Viewport is attached the context of the wl_surface. Check cog_wl_viewport_create_window(); - seat->touch_target = viewport; + g_set_weak_pointer(&seat->touch_target, viewport); seat->touch.serial = serial; seat->touch.surface = surface; @@ -820,13 +820,7 @@ touch_on_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, return; } - g_assert(seat->touch_target); - CogWlViewport *viewport = COG_WL_VIEWPORT(seat->touch_target); - - struct wl_surface *target_surface = seat->touch.surface; - seat->touch_target = NULL; seat->touch.serial = serial; - seat->touch.surface = NULL; if (id < 0 || id >= 10) return; @@ -838,6 +832,7 @@ touch_on_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get(); CogWlPopup *popup = platform->popup; + struct wl_surface *target_surface = seat->touch.surface; if (popup && popup->wl_surface) { if (target_surface == popup->wl_surface) { cog_popup_menu_handle_event(popup->popup_menu, COG_POPUP_MENU_EVENT_STATE_RELEASED, raw_event.x, @@ -853,7 +848,8 @@ touch_on_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, struct wpe_input_touch_event event = {seat->touch.points, 10, raw_event.type, raw_event.id, raw_event.time}; - CogView *view = cog_viewport_get_visible_view((CogViewport *) viewport); + CogWlViewport *viewport = COG_WL_VIEWPORT(seat->touch_target); + CogView *view = cog_viewport_get_visible_view((CogViewport *) viewport); if (view) wpe_view_backend_dispatch_touch_event(cog_view_get_backend(view), &event);