summaryrefslogtreecommitdiff
path: root/waterfox/patch-bug1321069
blob: 66634001e091dc589c3f57e6728f97dc92918be9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
commit a09c25bcc3b4
Author: Kartikaya Gupta <kgupta@mozilla.com>
Date:   Wed May 30 09:49:23 2018 -0400

    Bug 1321069 - Redirect the end event of a long-tap sequence back to the content window. r=karlt, a=RyanVM
    
    In the case of a long-tap touch sequence, a new popup window (the
    contextmenu) is spawned while the sequence is ongoing. The touch-end of
    the sequence ends up getting delivered to the popup window, instead of
    the original content window, and that causes the touch-handling
    machinery state in the content window to get out of sync with reality.
    This patch detects this scenario and redirects the touch events on the
    popup window back to the original content window.
    
    MozReview-Commit-ID: L2vvKLlogRA
    
    --HG--
    extra : source : 27a160b7025ffaadd7cc1ce326ce8729c2b180a0
---
 widget/gtk/nsWindow.cpp | 36 +++++++++++++++++++++++++++++++++++-
 widget/gtk/nsWindow.h   |  3 +++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp
index 54ec8615051f1..18d0ccac4dbd6 100644
--- widget/gtk/nsWindow.cpp
+++ widget/gtk/nsWindow.cpp
@@ -3455,11 +3455,41 @@ nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
                            aSelectionData, aInfo, aTime);
 }
 
+nsWindow*
+nsWindow::GetTransientForWindowIfPopup()
+{
+    if (mWindowType != eWindowType_popup) {
+        return nullptr;
+    }
+    GtkWindow* toplevel = gtk_window_get_transient_for(GTK_WINDOW(mShell));
+    if (toplevel) {
+        return get_window_for_gtk_widget(GTK_WIDGET(toplevel));
+    }
+    return nullptr;
+}
+
+bool
+nsWindow::IsHandlingTouchSequence(GdkEventSequence* aSequence)
+{
+    return mHandleTouchEvent && mTouches.Contains(aSequence);
+}
+
 #if GTK_CHECK_VERSION(3,4,0)
 gboolean
 nsWindow::OnTouchEvent(GdkEventTouch* aEvent)
 {
     if (!mHandleTouchEvent) {
+        // If a popup window was spawned (e.g. as the result of a long-press)
+        // and touch events got diverted to that window within a touch sequence,
+        // ensure the touch event gets sent to the original window instead. We
+        // keep the checks here very conservative so that we only redirect
+        // events in this specific scenario.
+        nsWindow* targetWindow = GetTransientForWindowIfPopup();
+        if (targetWindow &&
+            targetWindow->IsHandlingTouchSequence(aEvent->sequence)) {
+            return targetWindow->OnTouchEvent(aEvent);
+        }
+
         return FALSE;
     }
 
@@ -4780,12 +4810,16 @@ nsWindow::GrabPointer(guint32 aTime)
         return;
 
     gint retval;
+    // Note that we need GDK_TOUCH_MASK below to work around a GDK/X11 bug that
+    // causes touch events that would normally be received by this client on
+    // other windows to be discarded during the grab.
     retval = gdk_pointer_grab(mGdkWindow, TRUE,
                               (GdkEventMask)(GDK_BUTTON_PRESS_MASK |
                                              GDK_BUTTON_RELEASE_MASK |
                                              GDK_ENTER_NOTIFY_MASK |
                                              GDK_LEAVE_NOTIFY_MASK |
-                                             GDK_POINTER_MOTION_MASK),
+                                             GDK_POINTER_MOTION_MASK |
+                                             GDK_TOUCH_MASK),
                               (GdkWindow *)nullptr, nullptr, aTime);
 
     if (retval == GDK_GRAB_NOT_VIEWABLE) {
diff --git widget/gtk/nsWindow.h widget/gtk/nsWindow.h
index c28c1749c76dc..33e8c4db7c1c0 100644
--- widget/gtk/nsWindow.h
+++ widget/gtk/nsWindow.h
@@ -434,7 +434,10 @@ private:
     nsIWidgetListener* GetListener();
     bool               IsComposited() const;
 
     void               UpdateClientOffsetForCSDWindow();
+
+    nsWindow*          GetTransientForWindowIfPopup();
+    bool               IsHandlingTouchSequence(GdkEventSequence* aSequence);
 
     GtkWidget          *mShell;
     MozContainer       *mContainer;
bgstack15