Repository: kivy/kivy

Issue:
Bug in ScrollView causes 'scroll mode' to be entered when tapping on a touch-screen
https://github.com/kivy/kivy/blob/master/kivy/uix/scrollview.py#L753 appears to be wrong:
"if ud['dx'] or ud['dy'] > self.scroll_distance:" causes it to enter scroll mode as soon as ud['dx'] is non-zero.

Tapping on a touch-screen (the Raspberry PI touch screen is what I have) nearly always ends up with ud['dx'] being 1 or 2, which makes selecting something from a drop-down challenging.

Changing the line to

if ud['dx'] > self.scroll_distance or ud['dy'] > self.scroll_distance

fixes the problem.  I don't know if that's the shortest construct available in Python, but it seems to confirm my suspicion.

There's nothing special about my code.  The 'showcase' example has the same issue.



Discussion:
I made a ticket 6 days ago that might involve the same issue. I just recorded this.

https://vid.me/xn59

When I am at the bottom of a scroll view everything works fine but if I am not at the bottom of the scroll view the touch input in my second scroll view cannot be registered with touch input. I thought it was an on_ref_press issue but I guess it has to do with scroll view. Here is the code I used in the video.

This occurs on both my Ubuntu laptop and my Galaxy S6

   from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.popup import Popup
    from kivy.uix.scrollview import ScrollView
    from kivy.uix.image import Image
    from kivy.uix.label import Label
    from kivy.graphics import Color, Rectangle
    from kivy.core.window import Window

```
class MainApp(GridLayout):
    def __init__(self, *args, **kwargs):
            super(MainApp, self).__init__(**kwargs)
#Main Frame#--------------------------------------
                    self.cols = 1
                    self.bind(minimum_height = self.setter('height'))

                    self.main_scroll = ScrollView()
                    self.add_widget(self.main_scroll)

                    self.grid_image = Image(source = '', size_hint_y = None,keep_ratio = True, allow_stretch = True)
                    self.main_scroll.add_widget(self.grid_image)

                    with self.grid_image.canvas:
                        Color(43/255.0, 41/255.0, 42/255.0, 1)
                        self.grid_background = Rectangle()
    #Inner Scroll Frame#-------------------------
                    self.ability_scroll_frame = ScrollView(size_hint_y = None)
                    self.grid_image.add_widget(self.ability_scroll_frame)

                    self.ability_grid_frame = GridLayout(cols = 1,
                                   size_hint_y = None)
                    self.ability_scroll_frame.add_widget(self.ability_grid_frame)

                    self.testlabel = Label(text = '[b][ref=Touch Here]Touch Here[/ref][/b]\nThe Bold Text is the ref text [b][ref=Touch Here]Touch Here[/ref][/b].\nClicking it always works. Touch only works when the main window is scrollable and you are at the bottom of the main scrollview page.\nThe popup should always appear.', markup = True,color = (1,1,1,1))

                    self.testlabel.bind(on_ref_press = self.DefinitionPopup)
                    self.ability_grid_frame.add_widget(self.testlabel)

                    self.bind(size = self.GearGridScale)
                    self.ability_grid_frame.bind(size = self.GearGridScale)
#App Scale#----------------------------------------------
    def GearGridScale(self, *args):
        self.screensize =  [Window.width, Window.height]

        self.gear_grid_width = 4950.0
        self.gear_grid_height = 8000.0

        self.ratio = self.screensize[0]/self.gear_grid_width

        self.new_gear_grid_width = self.ratio * self.gear_grid_width
        self.new_gear_grid_height = self.ratio * self.gear_grid_height

        self.grid_image.size = (self.new_gear_grid_width, self.new_gear_grid_height)

        self.ability_scroll_frame.size = (self.grid_image.width * 0.9, self.grid_image.height * 0.3)
        self.ability_scroll_frame.pos = (self.grid_image.x + (self.grid_image.width - self.ability_scroll_frame.width)/2.0,self.grid_image.height * .01)

        self.ability_grid_frame.size = (self.ability_scroll_frame.width, 4 * self.ability_scroll_frame.width/3750.0 * 700.0)

        self.testlabel.text_size = self.ability_scroll_frame.size
        self.testlabel.valign = 'middle'
        self.testlabel.halign = 'center'

        self.grid_background.size = self.ability_scroll_frame.size
        self.grid_background.pos = self.ability_scroll_frame.pos
#Definition Popup#------------------------------------------------------
    def DefinitionPopup(self, *args):
        self.definitionword = args[1]

        self.definition = Glossary().glossary

        self.definepopup = Popup(title = self.definitionword, size_hint = (0.2, 0.2))

        self.definelabel = Label(text = self.definition[self.definitionword])

        self.definepopup.content = self.definelabel

        self.definepopup.open()

class Glossary():
    def __init__(self):
            self.glossary = {'Touch Here': 'Test Text'}

class TestApp(App):
    def build(self):
        return MainApp()

if __name__ == '__main__':
    TestApp().run()
```


Resolving patch:
diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py
--- a/kivy/uix/scrollview.py
+++ b/kivy/uix/scrollview.py
@@ -750,7 +750,8 @@ def on_scroll_move(self, touch):
         if mode == 'unknown':
             ud['dx'] += abs(touch.dx)
             ud['dy'] += abs(touch.dy)
-            if ud['dx'] or ud['dy'] > self.scroll_distance:
+            if ((ud['dx'] > self.scroll_distance) or
+                    (ud['dy'] > self.scroll_distance)):
                 if not self.do_scroll_x and not self.do_scroll_y:
                     # touch is in parent, but _change expects window coords
                     touch.push()


Test patch: