+class TapOrHold(object):
+
+ def __init__(self, widget):
+ self._widget = widget
+ self._isTap = True
+ self._isPointerInside = True
+ self._holdTimeoutId = None
+ self._tapTimeoutId = None
+ self._taps = 0
+
+ self._bpeId = None
+ self._breId = None
+ self._eneId = None
+ self._lneId = None
+
+ def enable(self):
+ self._bpeId = self._widget.connect("button-press-event", self._on_button_press)
+ self._breId = self._widget.connect("button-release-event", self._on_button_release)
+ self._eneId = self._widget.connect("enter-notify-event", self._on_enter)
+ self._lneId = self._widget.connect("leave-notify-event", self._on_leave)
+
+ def disable(self):
+ self._widget.disconnect(self._bpeId)
+ self._widget.disconnect(self._breId)
+ self._widget.disconnect(self._eneId)
+ self._widget.disconnect(self._lneId)
+
+ def on_tap(self, taps):
+ print "TAP", taps
+
+ def on_hold(self, taps):
+ print "HOLD", taps
+
+ def on_holding(self):
+ print "HOLDING"
+
+ def on_cancel(self):
+ print "CANCEL"
+
+ def _on_button_press(self, *args):
+ if self._tapTimeoutId is not None:
+ gobject.source_remove(self._tapTimeoutId)
+ self._tapTimeoutId = None
+
+ if self._holdTimeoutId is None:
+ self._tapTimeoutId = None
+
+ self._taps = 1
+ self._holdTimeoutId = gobject.timeout_add(1000, self._on_hold_timeout)
+ else:
+ self._taps = 2
+
+ def _on_button_release(self, *args):
+ assert self._tapTimeoutId is None
+ self._tapTimeoutId = gobject.timeout_add(100, self._on_tap_timeout)
+
+ def _on_actual_press(self, *args):
+ if self._holdTimeoutId is not None:
+ gobject.source_remove(self._holdTimeoutId)
+ self._holdTimeoutId = None
+
+ if self._isPointerInside:
+ if self._isTap:
+ self.on_tap(self._taps)
+ else:
+ self.on_hold(self._taps)
+ else:
+ self.on_cancel()
+
+ def _on_tap_timeout(self, *args):
+ self._tapTimeoutId = None
+ self._on_actual_press()
+ return False
+
+ def _on_hold_timeout(self, *args):
+ self._holdTimeoutId = None
+ self._isTap = False
+ self.on_holding()
+ return False
+
+ def _on_enter(self, *args):
+ self._isPointerInside = True
+
+ def _on_leave(self, *args):
+ self._isPointerInside = False
+
+