#+TITLE: GTK-3 Touchscreen events
#+DATE: 2014-05-20 12:00:00 UTC
#+DESCRIPTION: Example of catching touch screen events and filtering device type, helpful for making touch friendly gtk apps.
#+FILETAGS: GTK-3:python:widgets:touchscreen
#+CATEGORY: python
#+SLUG: 14-gtk-touchscreen-input
#+THUMBNAIL: ../../../images/gtk/tut14-touchscreen-events.png
#+BEGIN_COMMENT
.. title: GTK-3 Touchscreen events
.. slug: 14-gtk-touchscreen-input
.. date: 2014-05-20 12:00:00 UTC
.. tags: GTK-3, python, widgets, touchscreen
.. category: python
.. description: Example of catching touch screen events and filtering device type, helpful for making touch friendly gtk apps.
.. type: text
#+END_COMMENT

#+CAPTION: File downloader
[[../../../images/gtk/tut14-touchscreen-events.png]]

The example below demonstrates filtering events for a specific device, in this case a touch screen we then capture touch begin update and end events.

To my knowledge gestures are not supports so you will need to count the begins to determine the number of fingers and handle the updates to determine whats happening.

#+BEGIN_SRC python
#!/usr/bin/env python
import sys
from gi.repository import Gtk, GdkX11, Gdk


class gui():

    def __init__(self):
        self.touch_count = 0
        self.window = Gtk.Window()
        self.window.realize()
        self.window.resize(300, 300)
        self.window.set_resizable(True)
        self.window.set_reallocate_redraws(True)
        self.window.set_title("GTK3 touch events")
        self.window.connect('delete_event', Gtk.main_quit)
        self.window.connect('destroy', lambda quit: Gtk.main_quit())

        self.drawing_area = Gtk.DrawingArea()
        #add the type of events we are interested in retrieving, skip this step and your events will never fire
        self.drawing_area.add_events(Gdk.EventMask.TOUCH_MASK)
        self.drawing_area.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        self.drawing_area.connect('button_press_event', self.touched)
        self.drawing_area.connect('touch-event', self.touched)
        self.drawing_area.set_double_buffered(False)

        self.window.add(self.drawing_area)
        self.window.show_all()

    def touched(self, widget, ev):
        # detect the type of device we can filter events using this
        # if we dont a touch event and mouse event can be triggered from one touch for example
        if ev.get_source_device().get_source() == Gdk.InputSource.TOUCHPAD:
            print('touchpad device')
        if ev.get_source_device().get_source() == Gdk.InputSource.MOUSE:
            print('mouse device')
        if ev.get_source_device().get_source() == Gdk.InputSource.TOUCHSCREEN:
            print('touchscreen device')
            
            #from what i can tell there is no support for gestures so you would need another library
            #or to handle this yourself
            if ev.touch.type == Gdk.EventType.TOUCH_BEGIN:
                self.touch_count += 1
                print('start %d %s %s' % (self.touch_count, ev.touch.x,ev.touch.y))
            if ev.touch.type == Gdk.EventType.TOUCH_UPDATE:
                print('UPDATE %d %s %s' % (self.touch_count, ev.touch.x,ev.touch.y))
            if ev.touch.type == Gdk.EventType.TOUCH_END:
                self.touch_count -= 1
                print('end %d %s %s' % (self.touch_count, ev.touch.x,ev.touch.y))
            if ev.touch.type == Gdk.EventType.TOUCH_CANCEL:
                self.touch_count -= 1
                print('cancelled')

def main():
    g = gui()
    Gtk.main()

if __name__ == '__main__':
    main()
#+END_SRC

