mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
Add support for Touch events to Ardour Canvas
This commit is contained in:
parent
7a5fe4c5a1
commit
ac6c00da26
2 changed files with 127 additions and 35 deletions
|
|
@ -557,8 +557,9 @@ GtkCanvas::GtkCanvas ()
|
||||||
|
|
||||||
/* these are the events we want to know about */
|
/* these are the events we want to know about */
|
||||||
add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK |
|
add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK |
|
||||||
Gdk::SCROLL_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK |
|
Gdk::SCROLL_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK |
|
||||||
Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
|
Gdk::TOUCH_BEGIN_MASK | Gdk::TOUCH_UPDATE_MASK | Gdk::TOUCH_END_MASK |
|
||||||
|
Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -616,39 +617,8 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
|
||||||
|
|
||||||
/* find the items at the given window position */
|
/* find the items at the given window position */
|
||||||
|
|
||||||
vector<Item const *> items;
|
|
||||||
_root.add_items_at_point (point, items);
|
|
||||||
|
|
||||||
DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("%1 covers %2 items\n", point, items.size()));
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasEnterLeave)) {
|
|
||||||
for (auto const & item : items) {
|
|
||||||
std::cerr << "\tItem " << item->whoami() << " ignore events ? " << item->ignore_events() << " vis ? " << item->visible() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* put all items at point that are event-sensitive and visible and NOT
|
|
||||||
groups into within_items. Note that items is sorted from bottom to
|
|
||||||
top, but we're going to reverse that for within_items so that its
|
|
||||||
first item is the upper-most item that can be chosen as _current_item.
|
|
||||||
*/
|
|
||||||
|
|
||||||
vector<Item const *>::const_iterator i;
|
|
||||||
list<Item const *> within_items;
|
list<Item const *> within_items;
|
||||||
|
get_items_enclosing(point, within_items);
|
||||||
for (i = items.begin(); i != items.end(); ++i) {
|
|
||||||
|
|
||||||
Item const * possible_item = *i;
|
|
||||||
|
|
||||||
/* We ignore invisible items, containers and items that ignore events */
|
|
||||||
|
|
||||||
if (!possible_item->visible() || possible_item->ignore_events() || dynamic_cast<ArdourCanvas::Container const *>(possible_item) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
within_items.push_front (possible_item);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("after filtering insensitive + containers, we have %1 items\n", within_items.size()));
|
DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("after filtering insensitive + containers, we have %1 items\n", within_items.size()));
|
||||||
|
|
||||||
|
|
@ -680,6 +650,42 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Given @p point (a position in window coordinates)
|
||||||
|
* return a list of items in order top to bottom.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GtkCanvas::get_items_enclosing (Duple const & point, list<Item const *> &enclosing_items)
|
||||||
|
{
|
||||||
|
/* find the items at the given window position */
|
||||||
|
vector<Item const*> items;
|
||||||
|
_root.add_items_at_point (point, items);
|
||||||
|
|
||||||
|
DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("%1 covers %2 items\n", point, items.size()));
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (DEBUG_ENABLED(PBD::DEBUG::CanvasEnterLeave)) {
|
||||||
|
for (auto const& item : items) {
|
||||||
|
std::cerr << "\tItem " << item->whoami() << " ignore events ? " << item->ignore_events() << " vis ? " << item->visible() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* put all items at point that are event-sensitive and visible and NOT
|
||||||
|
* groups into enclosing_items. Note that items is sorted from bottom to
|
||||||
|
* top, but we're going to reverse that for enclosing_items so that its
|
||||||
|
* first item is the upper-most item that can be chosen as _current_item.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (auto const& possible_item : items) {
|
||||||
|
/* We ignore invisible items, containers and items that ignore events */
|
||||||
|
if (!possible_item->visible() || possible_item->ignore_events() || dynamic_cast<ArdourCanvas::Container const *>(possible_item) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
enclosing_items.push_front (possible_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Deliver a series of enter & leave events based on the pointer position being at window
|
/** Deliver a series of enter & leave events based on the pointer position being at window
|
||||||
* coordinate @p point, and pointer @p state (modifier keys, etc)
|
* coordinate @p point, and pointer @p state (modifier keys, etc)
|
||||||
*/
|
*/
|
||||||
|
|
@ -851,9 +857,27 @@ bool
|
||||||
GtkCanvas::deliver_event (GdkEvent* event)
|
GtkCanvas::deliver_event (GdkEvent* event)
|
||||||
{
|
{
|
||||||
/* Point in in canvas coordinate space */
|
/* Point in in canvas coordinate space */
|
||||||
|
|
||||||
const Item* event_item;
|
const Item* event_item;
|
||||||
|
|
||||||
|
/* touch events require a separate path with no pre-light, and a 'grab' for each finger (i.e. sequence) */
|
||||||
|
if (event->type == GDK_TOUCH_BEGIN || event->type == GDK_TOUCH_UPDATE || event->type == GDK_TOUCH_END ) {
|
||||||
|
int touchp = event->touch.sequence;
|
||||||
|
std::map<int, Item*>::iterator ei = _touched_item.find (touchp);
|
||||||
|
if (ei == _touched_item.end ()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
event_item = ei->second;
|
||||||
|
if (event_item && !event_item->ignore_events () && event_item->Event (event)) {
|
||||||
|
/* this item has just handled the event */
|
||||||
|
DEBUG_TRACE (
|
||||||
|
PBD::DEBUG::CanvasEvents,
|
||||||
|
string_compose ("canvas touch event handled by %1 %2\n", event_item->whatami(), event_item->name.empty() ? "[unknown]" : event_item->name)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_grabbed_item) {
|
if (_grabbed_item) {
|
||||||
/* we have a grabbed item, so everything gets sent there */
|
/* we have a grabbed item, so everything gets sent there */
|
||||||
DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("%1 %2 (%3) was grabbed, send event there\n",
|
DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("%1 %2 (%3) was grabbed, send event there\n",
|
||||||
|
|
@ -1279,6 +1303,66 @@ GtkCanvas::on_motion_notify_event (GdkEventMotion* ev)
|
||||||
return deliver_event (reinterpret_cast<GdkEvent*> (©));
|
return deliver_event (reinterpret_cast<GdkEvent*> (©));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GtkCanvas::on_touch_begin_event (GdkEventTouch *ev)
|
||||||
|
{
|
||||||
|
std::cout << "GtkCanvas::on_touch_begin\n" << std::endl;
|
||||||
|
|
||||||
|
/* translate event coordinates from window to canvas */
|
||||||
|
|
||||||
|
GdkEvent copy = *((GdkEvent*)ev);
|
||||||
|
Duple winpos = Duple (ev->x, ev->y);
|
||||||
|
Duple where = window_to_canvas (winpos);
|
||||||
|
|
||||||
|
copy.touch.x = where.x;
|
||||||
|
copy.touch.y = where.y;
|
||||||
|
|
||||||
|
/* Coordinates in the event will be canvas coordinates, correctly adjusted
|
||||||
|
for scroll if this GtkCanvas is in a GtkCanvasViewport.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::list<Item const*> within_items;
|
||||||
|
get_items_enclosing (winpos, within_items);
|
||||||
|
|
||||||
|
if (!within_items.empty()) {
|
||||||
|
_touched_item[ev->sequence] = const_cast<Item*> (within_items.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas scroll @ %1, %2 => %3\n", ev->x, ev->y, where));
|
||||||
|
return deliver_event (reinterpret_cast<GdkEvent*>(©));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GtkCanvas::on_touch_update_event (GdkEventTouch* ev)
|
||||||
|
{
|
||||||
|
GdkEvent copy = *((GdkEvent*)ev);
|
||||||
|
Duple winpos = Duple (ev->x, ev->y);
|
||||||
|
Duple where = window_to_canvas (winpos);
|
||||||
|
|
||||||
|
copy.touch.x = where.x;
|
||||||
|
copy.touch.y = where.y;
|
||||||
|
|
||||||
|
return deliver_event (reinterpret_cast<GdkEvent*>(©));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GtkCanvas::on_touch_end_event (GdkEventTouch *ev)
|
||||||
|
{
|
||||||
|
GdkEvent copy = *((GdkEvent*)ev);
|
||||||
|
Duple winpos = Duple (ev->x, ev->y);
|
||||||
|
Duple where = window_to_canvas (winpos);
|
||||||
|
|
||||||
|
copy.touch.x = where.x;
|
||||||
|
copy.touch.y = where.y;
|
||||||
|
|
||||||
|
bool ret = deliver_event (reinterpret_cast<GdkEvent*>(©));
|
||||||
|
|
||||||
|
/* remove "GRAB" */
|
||||||
|
_touched_item.erase (ev->sequence);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GtkCanvas::on_enter_notify_event (GdkEventCrossing* ev)
|
GtkCanvas::on_enter_notify_event (GdkEventCrossing* ev)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,9 @@ protected:
|
||||||
bool on_button_press_event (GdkEventButton *);
|
bool on_button_press_event (GdkEventButton *);
|
||||||
bool on_button_release_event (GdkEventButton* event);
|
bool on_button_release_event (GdkEventButton* event);
|
||||||
bool on_motion_notify_event (GdkEventMotion *);
|
bool on_motion_notify_event (GdkEventMotion *);
|
||||||
|
bool on_touch_begin_event (GdkEventTouch *);
|
||||||
|
bool on_touch_update_event (GdkEventTouch* event);
|
||||||
|
bool on_touch_end_event (GdkEventTouch *);
|
||||||
bool on_enter_notify_event (GdkEventCrossing*);
|
bool on_enter_notify_event (GdkEventCrossing*);
|
||||||
bool on_leave_notify_event (GdkEventCrossing*);
|
bool on_leave_notify_event (GdkEventCrossing*);
|
||||||
void on_style_changed (const Glib::RefPtr<Gtk::Style>&);
|
void on_style_changed (const Glib::RefPtr<Gtk::Style>&);
|
||||||
|
|
@ -283,6 +286,8 @@ protected:
|
||||||
bool deliver_event (GdkEvent *);
|
bool deliver_event (GdkEvent *);
|
||||||
void deliver_enter_leave (Duple const & point, int state);
|
void deliver_enter_leave (Duple const & point, int state);
|
||||||
|
|
||||||
|
void get_items_enclosing (Duple const& point, std::list<Item const*>& enclosing_items);
|
||||||
|
|
||||||
void pick_current_item (int state);
|
void pick_current_item (int state);
|
||||||
void pick_current_item (Duple const &, int state);
|
void pick_current_item (Duple const &, int state);
|
||||||
|
|
||||||
|
|
@ -300,6 +305,9 @@ private:
|
||||||
/** the item that currently has key focus or 0 */
|
/** the item that currently has key focus or 0 */
|
||||||
Item * _focused_item;
|
Item * _focused_item;
|
||||||
|
|
||||||
|
/** for multitouch: the item(s) that have been touched (effectively a GRAB) */
|
||||||
|
std::map<int, Item*> _touched_item;
|
||||||
|
|
||||||
bool _single_exposure;
|
bool _single_exposure;
|
||||||
bool _use_image_surface;
|
bool _use_image_surface;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue