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. We do check the origin of the event and do not trigger the enter/leave when originated from a touchscreen. We do setup the path for the CellRenderer however. 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, we check if the event originated from a touchscreen and do discard it in that case. Signed-off-by: Simon Schampijer <simon@laptop.org> Acked-by: Manuel Quiñones <manuq@laptop.org>
This commit is contained in:
parent
2834344b98
commit
ad9b0e9866
@ -152,6 +152,7 @@ class _PaletteMenuWidget(Gtk.Menu):
|
|||||||
menu.connect('motion-notify-event', self._motion_notify_cb)
|
menu.connect('motion-notify-event', self._motion_notify_cb)
|
||||||
menu.connect('enter-notify-event', self._enter_notify_cb)
|
menu.connect('enter-notify-event', self._enter_notify_cb)
|
||||||
menu.connect('leave-notify-event', self._leave_notify_cb)
|
menu.connect('leave-notify-event', self._leave_notify_cb)
|
||||||
|
menu.connect('button-release-event', self._button_release_event_cb)
|
||||||
self._entered = False
|
self._entered = False
|
||||||
self._mouse_in_palette = False
|
self._mouse_in_palette = False
|
||||||
self._mouse_in_invoker = False
|
self._mouse_in_invoker = False
|
||||||
@ -187,6 +188,9 @@ class _PaletteMenuWidget(Gtk.Menu):
|
|||||||
def _enter_notify_cb(self, widget, event):
|
def _enter_notify_cb(self, widget, event):
|
||||||
if event.mode in (Gdk.CrossingMode.GRAB, Gdk.CrossingMode.GTK_GRAB):
|
if event.mode in (Gdk.CrossingMode.GRAB, Gdk.CrossingMode.GTK_GRAB):
|
||||||
return False
|
return False
|
||||||
|
if event.get_source_device().get_source() == \
|
||||||
|
Gdk.InputSource.TOUCHSCREEN:
|
||||||
|
return False
|
||||||
if Gtk.get_event_widget(event) not in self._menus:
|
if Gtk.get_event_widget(event) not in self._menus:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -197,6 +201,9 @@ class _PaletteMenuWidget(Gtk.Menu):
|
|||||||
def _leave_notify_cb(self, widget, event):
|
def _leave_notify_cb(self, widget, event):
|
||||||
if event.mode in (Gdk.CrossingMode.GRAB, Gdk.CrossingMode.GTK_GRAB):
|
if event.mode in (Gdk.CrossingMode.GRAB, Gdk.CrossingMode.GTK_GRAB):
|
||||||
return False
|
return False
|
||||||
|
if event.get_source_device().get_source() == \
|
||||||
|
Gdk.InputSource.TOUCHSCREEN:
|
||||||
|
return False
|
||||||
if Gtk.get_event_widget(event) not in self._menus:
|
if Gtk.get_event_widget(event) not in self._menus:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -205,6 +212,9 @@ class _PaletteMenuWidget(Gtk.Menu):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _motion_notify_cb(self, widget, event):
|
def _motion_notify_cb(self, widget, event):
|
||||||
|
if event.get_source_device().get_source() == \
|
||||||
|
Gdk.InputSource.TOUCHSCREEN:
|
||||||
|
return False
|
||||||
x = event.x_root
|
x = event.x_root
|
||||||
y = event.y_root
|
y = event.y_root
|
||||||
|
|
||||||
@ -219,6 +229,20 @@ class _PaletteMenuWidget(Gtk.Menu):
|
|||||||
self._mouse_in_invoker = in_invoker
|
self._mouse_in_invoker = in_invoker
|
||||||
self._reevaluate_state()
|
self._reevaluate_state()
|
||||||
|
|
||||||
|
def _button_release_event_cb(self, widget, event):
|
||||||
|
x = event.x_root
|
||||||
|
y = event.y_root
|
||||||
|
|
||||||
|
if type(self._invoker) is CellRendererInvoker:
|
||||||
|
in_invoker = self._invoker.point_in_cell_renderer(x, y)
|
||||||
|
else:
|
||||||
|
rect = self._invoker.get_rect()
|
||||||
|
in_invoker = x >= rect.x and x < (rect.x + rect.width) \
|
||||||
|
and y >= rect.y and y < (rect.y + rect.height)
|
||||||
|
|
||||||
|
if in_invoker:
|
||||||
|
return True
|
||||||
|
|
||||||
def _reevaluate_state(self):
|
def _reevaluate_state(self):
|
||||||
if self._entered:
|
if self._entered:
|
||||||
# If we previously advised that the mouse was inside, but now the
|
# If we previously advised that the mouse was inside, but now the
|
||||||
@ -1251,8 +1275,11 @@ class CellRendererInvoker(Invoker):
|
|||||||
self._motion_hid = None
|
self._motion_hid = None
|
||||||
self._leave_hid = None
|
self._leave_hid = None
|
||||||
self._release_hid = None
|
self._release_hid = None
|
||||||
|
self._long_pressed_hid = None
|
||||||
self.path = None
|
self.path = None
|
||||||
|
|
||||||
|
self._long_pressed_controller = SugarGestures.LongPressController()
|
||||||
|
|
||||||
def attach_cell_renderer(self, tree_view, cell_renderer):
|
def attach_cell_renderer(self, tree_view, cell_renderer):
|
||||||
self._tree_view = tree_view
|
self._tree_view = tree_view
|
||||||
self._cell_renderer = cell_renderer
|
self._cell_renderer = cell_renderer
|
||||||
@ -1263,7 +1290,10 @@ class CellRendererInvoker(Invoker):
|
|||||||
self.__leave_notify_event_cb)
|
self.__leave_notify_event_cb)
|
||||||
self._release_hid = tree_view.connect('button-release-event',
|
self._release_hid = tree_view.connect('button-release-event',
|
||||||
self.__button_release_event_cb)
|
self.__button_release_event_cb)
|
||||||
|
self._long_pressed_hid = self._long_pressed_controller.connect( \
|
||||||
|
'pressed', self.__long_pressed_event_cb, tree_view)
|
||||||
|
self._long_pressed_controller.attach(tree_view,
|
||||||
|
SugarGestures.EventControllerFlags.NONE)
|
||||||
Invoker.attach(self, cell_renderer)
|
Invoker.attach(self, cell_renderer)
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
@ -1271,6 +1301,8 @@ class CellRendererInvoker(Invoker):
|
|||||||
self._tree_view.disconnect(self._motion_hid)
|
self._tree_view.disconnect(self._motion_hid)
|
||||||
self._tree_view.disconnect(self._leave_hid)
|
self._tree_view.disconnect(self._leave_hid)
|
||||||
self._tree_view.disconnect(self._release_hid)
|
self._tree_view.disconnect(self._release_hid)
|
||||||
|
self._long_pressed_controller.detach(self._tree_view)
|
||||||
|
self._long_pressed_controller.disconnect(self._long_pressed_hid)
|
||||||
|
|
||||||
def get_rect(self):
|
def get_rect(self):
|
||||||
allocation = self._tree_view.get_allocation()
|
allocation = self._tree_view.get_allocation()
|
||||||
@ -1310,11 +1342,18 @@ class CellRendererInvoker(Invoker):
|
|||||||
self.palette = None
|
self.palette = None
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
|
if event.get_source_device().get_source() == \
|
||||||
|
Gdk.InputSource.TOUCHSCREEN:
|
||||||
|
return False
|
||||||
self.notify_mouse_enter()
|
self.notify_mouse_enter()
|
||||||
else:
|
else:
|
||||||
if self.path is not None:
|
if self.path is not None:
|
||||||
self._redraw_path(self.path)
|
self._redraw_path(self.path)
|
||||||
self.path = None
|
self.path = None
|
||||||
|
|
||||||
|
if event.get_source_device().get_source() == \
|
||||||
|
Gdk.InputSource.TOUCHSCREEN:
|
||||||
|
return False
|
||||||
self.notify_mouse_leave()
|
self.notify_mouse_leave()
|
||||||
|
|
||||||
def _redraw_path(self, path):
|
def _redraw_path(self, path):
|
||||||
@ -1349,6 +1388,11 @@ class CellRendererInvoker(Invoker):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def __long_pressed_event_cb(self, controller, x, y, widget):
|
||||||
|
if self.point_in_cell_renderer(x, y):
|
||||||
|
controller.reset()
|
||||||
|
self.notify_right_click()
|
||||||
|
|
||||||
def point_in_cell_renderer(self, event_x, event_y):
|
def point_in_cell_renderer(self, event_x, event_y):
|
||||||
pos = self._tree_view.get_path_at_pos(int(event_x), int(event_y))
|
pos = self._tree_view.get_path_at_pos(int(event_x), int(event_y))
|
||||||
if pos is None:
|
if pos is None:
|
||||||
|
Loading…
Reference in New Issue
Block a user