From 89834550190d287f0e0b86a3eb4ddc0abd99158a Mon Sep 17 00:00:00 2001
From: Simon Schampijer <simon@laptop.org>
Date: Tue, 9 Oct 2012 10:47:10 +0200
Subject: [PATCH] Touch: on long-press on a link or image show the Palette
Show the same Palette as we show when a learner does
a right click on a canvas element.
We use the LongPress event controller from the toolkit for
that. We can only hook this up to the browser widget once
it is realized because we need to enable the touch events
on the x11 window.
When we recognized a long-press event we need to get the
information about that canvas element from WebKit. The
webkit_web_view_get_hit_test_result API [1] which we use
when a right click is recognized does expect an event of
type GdkEventButton to be passed. From the x, y coordinates
we get with the pressed signal we can construct such an
event and and pass that fake event to WebKit.
In order to differentiate between a tap and a tap&hold
event, we need to inhibit the release event to be further
propagated if a long-press occurred before. We use a
boolean to differentiate those two cases.
[1] http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#webkit-web-view-get-hit-test-result
---
palettes.py | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/palettes.py b/palettes.py
index bbebce8..ffd1d80 100644
a
|
b
|
from gi.repository import Gtk |
26 | 26 | from gi.repository import Gdk |
27 | 27 | from gi.repository import WebKit |
28 | 28 | |
| 29 | from gi.repository import SugarGestures |
| 30 | |
29 | 31 | from sugar3.graphics.palette import Palette, Invoker |
30 | 32 | from sugar3 import profile |
31 | 33 | |
… |
… |
class ContentInvoker(Invoker): |
37 | 39 | Invoker.__init__(self) |
38 | 40 | self._position_hint = self.AT_CURSOR |
39 | 41 | self._browser = browser |
| 42 | self._recognized_long_press_event = False |
40 | 43 | self._browser.connect('button-press-event', self.__button_press_cb) |
| 44 | self._browser.connect('button-release-event', self.__button_release_cb) |
| 45 | self._browser.connect('realize', self.__browser_realize_cb) |
41 | 46 | self.attach(self._browser) |
42 | 47 | |
43 | 48 | def get_default_position(self): |
44 | 49 | return self.AT_CURSOR |
45 | 50 | |
| 51 | def __long_pressed_cb(self, controller, x, y): |
| 52 | self._recognized_long_press_event = True |
| 53 | |
| 54 | event = Gdk.EventButton() |
| 55 | event.type = Gdk.EventType._3BUTTON_PRESS |
| 56 | gdk_window = self._browser.get_window() |
| 57 | event.window = gdk_window |
| 58 | event.time = Gtk.get_current_event_time() |
| 59 | event.x = x |
| 60 | event.y = y |
| 61 | x_root, y_root = gdk_window.get_root_coords(x, y) |
| 62 | event.x_root = x_root |
| 63 | event.y_root = y_root |
| 64 | |
| 65 | self._handle_event(event) |
| 66 | |
| 67 | return True |
| 68 | |
| 69 | def __button_release_cb(self, browser, event): |
| 70 | if self._recognized_long_press_event: |
| 71 | self._recognized_long_press_event = False |
| 72 | return True |
| 73 | else: |
| 74 | return False |
| 75 | |
| 76 | def __browser_realize_cb(self, browser): |
| 77 | x11_window = browser.get_window() |
| 78 | x11_window.set_events(x11_window.get_events() | |
| 79 | Gdk.EventMask.POINTER_MOTION_MASK | |
| 80 | Gdk.EventMask.TOUCH_MASK) |
| 81 | |
| 82 | lp = SugarGestures.LongPressController(trigger_delay=100) |
| 83 | lp.connect('pressed', self.__long_pressed_cb) |
| 84 | lp.attach(browser, SugarGestures.EventControllerFlags.NONE) |
| 85 | |
46 | 86 | def get_rect(self): |
47 | 87 | allocation = self._browser.get_allocation() |
48 | 88 | window = self._browser.get_window() |
… |
… |
class ContentInvoker(Invoker): |
73 | 113 | def __button_press_cb(self, browser, event): |
74 | 114 | if event.button != 3: |
75 | 115 | return False |
| 116 | self._handle_event(event) |
| 117 | return True |
| 118 | |
| 119 | def _handle_event(self, event): |
76 | 120 | hit_test = self._browser.get_hit_test_result(event) |
77 | 121 | if hit_test.props.context & WebKit.HitTestResultContext.LINK: |
78 | 122 | link_uri = hit_test.props.link_uri |
… |
… |
class ContentInvoker(Invoker): |
104 | 148 | self.palette = SelectionPalette(self._browser, title, None, None) |
105 | 149 | self.notify_right_click() |
106 | 150 | |
107 | | return True |
108 | | |
109 | 151 | |
110 | 152 | class SelectionPalette(Palette): |
111 | 153 | def __init__(self, browser, title, url, owner_document): |