Ticket #4128: 0001-CellRendererInvoker-add-support-for-long-press-event.patch

File 0001-CellRendererInvoker-add-support-for-long-press-event.patch, 5.7 KB (added by erikos, 11 years ago)

CellRendererInvoker: add support for long-press events

  • src/sugar3/graphics/palettewindow.py

    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): 
    152152                menu.connect('motion-notify-event', self._motion_notify_cb)
    153153            menu.connect('enter-notify-event', self._enter_notify_cb)
    154154            menu.connect('leave-notify-event', self._leave_notify_cb)
     155            menu.connect('button-release-event', self._button_release_event_cb)
    155156        self._entered = False
    156157        self._mouse_in_palette = False
    157158        self._mouse_in_invoker = False
    class _PaletteMenuWidget(Gtk.Menu): 
    219220            self._mouse_in_invoker = in_invoker
    220221            self._reevaluate_state()
    221222
     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
    222237    def _reevaluate_state(self):
    223238        if self._entered:
    224239            # If we previously advised that the mouse was inside, but now the
    class CellRendererInvoker(Invoker): 
    12511266        self._motion_hid = None
    12521267        self._leave_hid = None
    12531268        self._release_hid = None
     1269        self._long_pressed_hid = None
    12541270        self.path = None
    12551271
     1272        self._long_pressed_controller = SugarGestures.LongPressController()
     1273
    12561274    def attach_cell_renderer(self, tree_view, cell_renderer):
    12571275        self._tree_view = tree_view
    12581276        self._cell_renderer = cell_renderer
    class CellRendererInvoker(Invoker): 
    12631281                                            self.__leave_notify_event_cb)
    12641282        self._release_hid = tree_view.connect('button-release-event',
    12651283                                              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)
    12671288        Invoker.attach(self, cell_renderer)
    12681289
    12691290    def detach(self):
    class CellRendererInvoker(Invoker): 
    12711292        self._tree_view.disconnect(self._motion_hid)
    12721293        self._tree_view.disconnect(self._leave_hid)
    12731294        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)
    12741297
    12751298    def get_rect(self):
    12761299        allocation = self._tree_view.get_allocation()
    class CellRendererInvoker(Invoker): 
    13491372        else:
    13501373            return False
    13511374
     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
    13521380    def point_in_cell_renderer(self, event_x, event_y):
    13531381        pos = self._tree_view.get_path_at_pos(int(event_x), int(event_y))
    13541382        if pos is None: