From dc5eba30caaa3a3b1f8698a89eea1c3c855be926 Mon Sep 17 00:00:00 2001
From: Simon Schampijer <simon@laptop.org>
Date: Thu, 1 Nov 2012 19:05:54 +0100
Subject: [PATCH toolkit-gtk3] CellRendererInvoker: add support for long-press
events
This one is tricky because where the CellRendererInvoker is
used (Home View activity list and Journal list view) we do
use Palettes based on a GtkMenu. In the Journal list view
this Palette has submenus so it can not be easily replaced
with our custom Palette. That is why I am trying to make this
case work with a GtkMenu.
When the Palette does pop up it grabs the focus. This means that
the invoker does not see a TOUCH_END event. Same is the longpress
controller that is why we have to reset the controller when
the long-press is detected, otherwise it is not usable a second
time.
The default behavior of a GtkMenu is that it does pop down
on a long press/release event. So when doing a long press
on the icon the Palette was popping down directly. We can
stop this by listening on the button-release event in the
Menu and return True when the event happens in the invoker
coordinates.
Finally there are several issues with motion events: in the
invoker we listen to motion events on the treeview in order to
be able to popup/popdown the Palette on hovering over the
icon. This event is triggered as well when the icon is
tapped. I am not sure this is expected behavior and if it is
correct by design how to prevent it.
The second case where the motion events are triggered is
when you tap somewhere in the Palette when it is up. For
example you want to get to one of the submenues. Since the
Palette tracks motion events to work for the hover case [2]
we do get a leave event when the Palette is tapped and the
Palette does pop down. Same here, do we know when the motion
event is coming from a mouse or not? How could this be
prevented? Should I track if a Palette is raised by a mouse
click or a touch event and only do the motion tracking when
the mouse is in use?
[1] http://git.sugarlabs.org/sugar-toolkit-gtk3/sugar-toolkit-gtk3/blobs/master/src/sugar3/graphics/palettewindow.py#line1261
[2] http://git.sugarlabs.org/sugar-toolkit-gtk3/sugar-toolkit-gtk3/blobs/master/src/sugar3/graphics/palettewindow.py#line118
---
src/sugar3/graphics/palettewindow.py | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/sugar3/graphics/palettewindow.py b/src/sugar3/graphics/palettewindow.py
index e1fde4a..e2d8a9f 100644
a
|
b
|
class _PaletteMenuWidget(Gtk.Menu): |
152 | 152 | menu.connect('motion-notify-event', self._motion_notify_cb) |
153 | 153 | menu.connect('enter-notify-event', self._enter_notify_cb) |
154 | 154 | menu.connect('leave-notify-event', self._leave_notify_cb) |
| 155 | menu.connect('button-release-event', self._button_release_event_cb) |
155 | 156 | self._entered = False |
156 | 157 | self._mouse_in_palette = False |
157 | 158 | self._mouse_in_invoker = False |
… |
… |
class _PaletteMenuWidget(Gtk.Menu): |
219 | 220 | self._mouse_in_invoker = in_invoker |
220 | 221 | self._reevaluate_state() |
221 | 222 | |
| 223 | def _button_release_event_cb(self, widget, event): |
| 224 | x = event.x_root |
| 225 | y = event.y_root |
| 226 | |
| 227 | if type(self._invoker) is CellRendererInvoker: |
| 228 | in_invoker = self._invoker.point_in_cell_renderer(x, y) |
| 229 | else: |
| 230 | rect = self._invoker.get_rect() |
| 231 | in_invoker = x >= rect.x and x < (rect.x + rect.width) \ |
| 232 | and y >= rect.y and y < (rect.y + rect.height) |
| 233 | |
| 234 | if in_invoker: |
| 235 | return True |
| 236 | |
222 | 237 | def _reevaluate_state(self): |
223 | 238 | if self._entered: |
224 | 239 | # If we previously advised that the mouse was inside, but now the |
… |
… |
class CellRendererInvoker(Invoker): |
1251 | 1266 | self._motion_hid = None |
1252 | 1267 | self._leave_hid = None |
1253 | 1268 | self._release_hid = None |
| 1269 | self._long_pressed_hid = None |
1254 | 1270 | self.path = None |
1255 | 1271 | |
| 1272 | self._long_pressed_controller = SugarGestures.LongPressController() |
| 1273 | |
1256 | 1274 | def attach_cell_renderer(self, tree_view, cell_renderer): |
1257 | 1275 | self._tree_view = tree_view |
1258 | 1276 | self._cell_renderer = cell_renderer |
… |
… |
class CellRendererInvoker(Invoker): |
1263 | 1281 | self.__leave_notify_event_cb) |
1264 | 1282 | self._release_hid = tree_view.connect('button-release-event', |
1265 | 1283 | self.__button_release_event_cb) |
1266 | | |
| 1284 | self._long_pressed_hid = self._long_pressed_controller.connect( \ |
| 1285 | 'pressed', self.__long_pressed_event_cb, tree_view) |
| 1286 | self._long_pressed_controller.attach(tree_view, |
| 1287 | SugarGestures.EventControllerFlags.NONE) |
1267 | 1288 | Invoker.attach(self, cell_renderer) |
1268 | 1289 | |
1269 | 1290 | def detach(self): |
… |
… |
class CellRendererInvoker(Invoker): |
1271 | 1292 | self._tree_view.disconnect(self._motion_hid) |
1272 | 1293 | self._tree_view.disconnect(self._leave_hid) |
1273 | 1294 | self._tree_view.disconnect(self._release_hid) |
| 1295 | self._long_pressed_controller.detach(self._tree_view) |
| 1296 | self._long_pressed_controller.disconnect(self._long_pressed_hid) |
1274 | 1297 | |
1275 | 1298 | def get_rect(self): |
1276 | 1299 | allocation = self._tree_view.get_allocation() |
… |
… |
class CellRendererInvoker(Invoker): |
1349 | 1372 | else: |
1350 | 1373 | return False |
1351 | 1374 | |
| 1375 | def __long_pressed_event_cb(self, controller, x, y, widget): |
| 1376 | if self.point_in_cell_renderer(x, y): |
| 1377 | controller.reset() |
| 1378 | self.notify_right_click() |
| 1379 | |
1352 | 1380 | def point_in_cell_renderer(self, event_x, event_y): |
1353 | 1381 | pos = self._tree_view.get_path_at_pos(int(event_x), int(event_y)) |
1354 | 1382 | if pos is None: |