=== modified file 'src/desktop-events.cpp' --- src/desktop-events.cpp 2017-03-20 20:12:31 +0000 +++ src/desktop-events.cpp 2017-04-22 10:42:38 +0000 @@ -16,6 +16,8 @@ # include #endif #include +#include +#include #include #include "ui/dialog/guides.h" @@ -594,7 +596,7 @@ //static std::map switchMap; static std::map toolToUse; static std::string lastName; -static GdkInputSource lastType = GDK_SOURCE_MOUSE; +static GdkInputSource lastType = -1; static void init_extended() { @@ -616,7 +618,7 @@ if ( !devName.empty() && (avoidName != devName) - && (devSrc != Gdk::SOURCE_MOUSE) ) { + ) { // g_message("Adding '%s' as [%d]", devName, devSrc); // Set the initial tool for the device @@ -628,6 +630,8 @@ toolToUse[devName] = TOOLS_ERASER; break; case Gdk::SOURCE_CURSOR: + case Gdk::SOURCE_MOUSE: + case Gdk::SOURCE_TOUCHSCREEN: toolToUse[devName] = TOOLS_SELECT; break; default: @@ -640,20 +644,39 @@ } } +struct TouchEvent +{ + int x0, y0, + x, y; +}; + +float Square(float x) +{ + return x * x; +} +bool handlingGesture; void snoop_extended(GdkEvent* event, SPDesktop *desktop) { - GdkInputSource source = GDK_SOURCE_MOUSE; - std::string name; - + using namespace std::chrono; + using namespace std; + static unordered_map touchEvents; + // scale, rotation, offset when touchscreen zooming/panning/rotation started + static Geom::Point offset0, rotationCenter; + static float rotation0; + static float scale0; + + GdkDevice *device = gdk_event_get_source_device(event); + GdkInputSource source = gdk_device_get_source(device); + int x, y; + int state = 0; switch ( event->type ) { case GDK_MOTION_NOTIFY: { GdkEventMotion* event2 = reinterpret_cast(event); - if ( event2->device ) { - source = gdk_device_get_source(event2->device); - name = gdk_device_get_name(event2->device); - } + state = event2->state; + x = event2->x; + y = event2->y; } break; @@ -663,20 +686,15 @@ case GDK_BUTTON_RELEASE: { GdkEventButton* event2 = reinterpret_cast(event); - if ( event2->device ) { - source = gdk_device_get_source(event2->device); - name = gdk_device_get_name(event2->device); - } + state = event2->state; + x = event2->x; + y = event2->y; } break; case GDK_SCROLL: { GdkEventScroll* event2 = reinterpret_cast(event); - if ( event2->device ) { - source = gdk_device_get_source(event2->device); - name = gdk_device_get_name(event2->device); - } } break; @@ -684,16 +702,131 @@ case GDK_PROXIMITY_OUT: { GdkEventProximity* event2 = reinterpret_cast(event); - if ( event2->device ) { - source = gdk_device_get_source(event2->device); - name = gdk_device_get_name(event2->device); - } } break; - + case GDK_TOUCH_BEGIN: + case GDK_TOUCH_UPDATE: + case GDK_TOUCH_END: + { + GdkEventTouch &touch = *(GdkEventTouch*)event; + //printf("touch type=%d (%f %f) id=%lld time=%u tot=%lld\n", touch.type, touch.x, touch.y, touch.sequence, touch.time, touchEvents.size()); + + if (event->type == GDK_TOUCH_BEGIN) + { + TouchEvent &e = touchEvents[(int)touch.sequence]; + e.x0 = touch.x; + e.y0 = touch.y; + handlingGesture = touchEvents.size() == 2; + if (handlingGesture) + { + rotation0 = desktop->_current_affine.getRotation(); + offset0 = -desktop->_current_affine.getOffset(); + scale0 = desktop->_current_affine.getZoom(); + + auto i = touchEvents.begin(); + TouchEvent &e0 = i->second; + ++i; + TouchEvent &e1 = i->second; + + rotationCenter[Geom::X] = (e0.x0 + e1.x0) * 0.5f; + rotationCenter[Geom::Y] = (e0.y0 + e1.y0) * 0.5f; + } + } + else if (event->type == GDK_TOUCH_END) + { + touchEvents.erase((int)touch.sequence); + handlingGesture = touchEvents.size() == 2; + } + else + { + auto i = touchEvents.find((int)touch.sequence); + if (i == touchEvents.end()) + { + // why are we getting these? + printf("ignoring out-of-order touch event\n"); + break; + } + TouchEvent &e = i->second; + e.x = touch.x; + e.y = touch.y; + static uint32_t lastT; + if (touch.time - lastT < 80) + break; + lastT = touch.time; + + if (touchEvents.size() == 2) + { + auto i = touchEvents.begin(); + TouchEvent &e0 = i->second; + ++i; + TouchEvent &e1 = i->second; + + float scale = sqrtf((Square(e1.x - e0.x) + Square(e1.y - e0.y)) / (Square(e1.x0 - e0.x0) + Square(e1.y0 - e0.y0))); + if (isnan(scale) || isinf(scale) || scale == 0) + break; + + Geom::Point const translation((e0.x + e1.x - e0.x0 - e1.x0) * 0.5f, (e0.y + e1.y - e0.y0 - e1.y0) * 0.5f); + float rotation = atan2(e1.y0 - e0.y0, e1.x0 - e0.x0) - atan2(e1.y - e0.y, e1.x - e0.x); + + float finalRotation = rotation + rotation0; + // snap rotation to 0 like Autodesk Sketchbook + const float MIN_TOUCH_SCREEN_ROTATION = 0.17f; + if (-MIN_TOUCH_SCREEN_ROTATION <= finalRotation && finalRotation <= MIN_TOUCH_SCREEN_ROTATION) + { + finalRotation = 0; + rotation = -rotation0; + } + + desktop->_current_affine.setRotate(finalRotation); + desktop->_current_affine.setScale(scale0 * scale); + + Geom::Point offset(scale * (cosf(-rotation) * (offset0[Geom::X] - rotationCenter[Geom::X]) + sinf(-rotation) * (rotationCenter[Geom::Y] - offset0[Geom::Y])) + rotationCenter[Geom::X], + scale * (sinf(-rotation) * (offset0[Geom::X] - rotationCenter[Geom::X]) + cosf(-rotation) * (offset0[Geom::Y] - rotationCenter[Geom::Y])) + rotationCenter[Geom::Y]); + offset += translation; + /* + printf("offset0=(%f %f) rotationCenter=(%f %f) r1=%f rotation0=%f translate=(%f %f) offset=(%f %f)\n",offset0[Geom::X], offset0[Geom::Y], + rotationCenter[Geom::X], rotationCenter[Geom::Y], rotation, rotation0, translation[Geom::X], translation[Geom::Y], + offset[Geom::X], offset[Geom::Y]); + */ + desktop->_current_affine.setOffset(-offset); + desktop->set_display_area(); + desktop->updateNow(); + } + } + break; + } + case GDK_LEAVE_NOTIFY: + // if you move the mouse outside the window while dragging with fingers, + // GDK_TOUCH_END won't be delivered to this widget + touchEvents.clear(); + break; default: ; } + if (event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY || + source == GDK_SOURCE_TOUCHSCREEN && (event->type < GDK_TOUCH_BEGIN || event->type > GDK_TOUCH_END) || + source == GDK_SOURCE_KEYBOARD) + { + // ENTER & LEAVE events have an improper device name, Virtual Core Pointer, + // which isn't a real slave device (should be System Aggregated Pointer) + + // this will confuse the later auto tool selection + + // Also, emulated pointer events need to be ignored or else they'll switch the tool + // back to the mouse immediately after each touch event + + // also, why are there keyboard events when tapping to change tools? + return; + } + + std::string name; + // for now, make mouse & touch screen share same tool + // making touch screen remember its own tool didn't work because of some spurious MOTION_NOTIFY + // right after switching tools - where are these coming from? + if (source == GDK_SOURCE_TOUCHSCREEN) + name = "System Aggregated Pointer"; + else + name = gdk_device_get_name(device); if (!name.empty()) { if ( lastType != source || lastName != name ) { === modified file 'src/desktop.h' --- src/desktop.h 2017-03-30 09:41:29 +0000 +++ src/desktop.h 2017-04-09 08:48:48 +0000 @@ -533,8 +533,9 @@ Geom::Scale _flip; // Flip part of _w2d Geom::Point _offset; // Point on canvas to align to (0,0) of window }; - +public: DesktopAffine _current_affine; +private: std::list transforms_past; std::list transforms_future; bool _quick_zoom_enabled; ///< Signifies that currently we're in quick zoom mode === modified file 'src/display/sp-canvas.cpp' --- src/display/sp-canvas.cpp 2017-04-09 07:39:28 +0000 +++ src/display/sp-canvas.cpp 2017-04-09 23:36:22 +0000 @@ -72,12 +72,12 @@ #if GTK_CHECK_VERSION(3,20,0) auto const seat = display->get_default_seat(); - seat->ungrab(); + auto const device = seat->get_pointer(); #else auto const dm = display->get_device_manager(); auto const device = dm->get_client_pointer(); + #endif device->ungrab(time); -#endif } /** @@ -632,18 +632,11 @@ auto display = gdk_display_get_default(); #if GTK_CHECK_VERSION(3,20,0) auto seat = gdk_display_get_default_seat(display); - gdk_seat_grab(seat, - getWindow(item->canvas), - GDK_SEAT_CAPABILITY_ALL_POINTING, - FALSE, - cursor, - NULL, - NULL, - NULL); + auto device = gdk_seat_get_pointer(seat); #else auto dm = gdk_display_get_device_manager(display); auto device = gdk_device_manager_get_client_pointer(dm); - +#endif gdk_device_grab(device, getWindow(item->canvas), GDK_OWNERSHIP_NONE, @@ -651,7 +644,6 @@ (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), cursor, etime); -#endif item->canvas->_grabbed_item = item; item->canvas->_grabbed_event_mask = event_mask; @@ -948,6 +940,7 @@ widget_class->leave_notify_event = SPCanvas::handle_crossing; widget_class->focus_in_event = SPCanvas::handle_focus_in; widget_class->focus_out_event = SPCanvas::handle_focus_out; + widget_class->touch_event = SPCanvas::handle_touch; } static void sp_canvas_init(SPCanvas *canvas) @@ -1067,6 +1060,7 @@ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_TOUCH_MASK | ( HAS_BROKEN_MOTION_HINTS ? 0 : GDK_POINTER_MOTION_HINT_MASK ) | GDK_PROXIMITY_IN_MASK | @@ -1167,6 +1161,8 @@ canvas->addIdle(); } +//#pragma GCC push_options +//#pragma GCC optimize("-O0") int SPCanvas::emitEvent(GdkEvent *event) { guint mask; @@ -1200,12 +1196,22 @@ mask = GDK_SCROLL_MASK; mask |= GDK_SMOOTH_SCROLL_MASK; break; + case GDK_TOUCH_BEGIN: + case GDK_TOUCH_UPDATE: + case GDK_TOUCH_END: + mask = GDK_TOUCH_MASK; + break; default: mask = 0; break; } - if (!(mask & _grabbed_event_mask)) return FALSE; + if (!(mask & _grabbed_event_mask)) + { + if (event->type >= GDK_TOUCH_BEGIN && event->type <= GDK_TOUCH_END) + printf("crap dropped event %d %d\n", event->type, _grabbed_event_mask); + return FALSE; + } } // Convert to world coordinates -- we have two cases because of different @@ -1261,20 +1267,43 @@ // handler returns TRUE, just like for GtkWidget events. gint finished = FALSE; - +#if DEBUG_EVENTS + int depth = 0; + char *names[20]; + bool seen = false; + static SPCanvasItem *acetate; + +#endif while (item && !finished) { + #if DEBUG_EVENTS + names[depth] = G_OBJECT_TYPE_NAME(item); + if (!seen) + { + seen = strcmp(names[depth], "SPCanvasAcetate") == 0; + acetate = item; + } + ++depth; + #endif g_object_ref (item); g_signal_emit (G_OBJECT (item), item_signals[ITEM_EVENT], 0, ev, &finished); SPCanvasItem *parent = item->parent; g_object_unref (item); item = parent; } - + #ifdef DEBUG_EVENTS + if (!seen && (event->type >= GDK_TOUCH_BEGIN && event->type <= GDK_TOUCH_END)) + { + printf("crap - touch event not delivered to acetate\n"); + g_object_ref (acetate); + g_signal_emit (G_OBJECT (acetate), item_signals[ITEM_EVENT], 0, ev, &finished); + g_object_unref (acetate); + } + #endif gdk_event_free(ev); return finished; } - +//#pragma GCC pop_options int SPCanvas::pickCurrentItem(GdkEvent *event) { int button_down = 0; @@ -1301,7 +1330,8 @@ // synthesize an enter event. if (event != &_pick_event) { - if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE)) { + if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE) || + event->type >= GDK_TOUCH_BEGIN && event->type <= GDK_TOUCH_END) { // these fields have the same offsets in both types of events _pick_event.crossing.type = GDK_ENTER_NOTIFY; @@ -1404,7 +1434,7 @@ new_event.crossing.subwindow = NULL; retval = emitEvent(&new_event); } - + //printf("new_current_item = %s\n", typeid(*_current_item).name()); return retval; } @@ -1479,6 +1509,92 @@ return SP_CANVAS(widget)->emitEvent(reinterpret_cast(event)); } +gint SPCanvas::handle_touch(GtkWidget *widget, GdkEventTouch *event) +{ + int status; + SPCanvas *canvas = SP_CANVAS (widget); + + trackLatency((GdkEvent *)event); + + GdkEventTouch &touch = *event; + //printf("touch2 type=%d (%f %f) id=%lld\n", touch.type, touch.x, touch.y, touch.sequence); + if (event->window != getWindow(canvas)) { + return FALSE; + } + + if (canvas->_root == NULL) // canvas being deleted + return FALSE; + + extern bool handlingGesture; + if (!handlingGesture) + { + // I found during a pan/zoom gesture, if my finger touches a canvas element, the zoom blows up or glitches - not sure why but proabably due to events getting diverted to the new element instead of the canvas acetate + canvas->_state = 0; // almost all touch events have BUTTON 1 set, but that causes pickCurrentItem to not set _current_item - why? + canvas->pickCurrentItem(reinterpret_cast(event)); + } + + SP_CANVAS(widget)->emitEvent(reinterpret_cast(event)); + + if (!event->emulating_pointer || handlingGesture) + { + // don't generate emulation events in middle of gesture - saw strange case where touch events get processed out of order (TOUCH_UPDATE event occurs after TOUCH_END), completely breaking everything + return TRUE; + //return FALSE; // so that default handler gtk_widget_real_touch_event() can translate touch events in to emulated mouse events + } + GdkEvent *bevent; + // emulate pointer (copied from gtk_real_touch_event) + if (event->type == GDK_TOUCH_BEGIN || + event->type == GDK_TOUCH_END) + { + GdkEventType type; + if (event->type == GDK_TOUCH_BEGIN) + { + type = GDK_BUTTON_PRESS; + } + else + { + type = GDK_BUTTON_RELEASE; + } + bevent = gdk_event_new (type); + bevent->any.window = g_object_ref (event->window); + bevent->any.send_event = FALSE; + bevent->button.time = event->time; + bevent->button.state = event->state; + bevent->button.button = 1; + bevent->button.x_root = event->x_root; + bevent->button.y_root = event->y_root; + bevent->button.x = event->x; + bevent->button.y = event->y; + bevent->button.device = event->device; + bevent->button.axes = g_memdup (event->axes, + sizeof (gdouble) * gdk_device_get_n_axes (event->device)); + gdk_event_set_source_device (bevent, gdk_event_get_source_device ((GdkEvent*)event)); + + if (event->type == GDK_TOUCH_END) + bevent->button.state |= GDK_BUTTON1_MASK; + } + else if (event->type == GDK_TOUCH_UPDATE) + { + bevent = gdk_event_new (GDK_MOTION_NOTIFY); + bevent->any.window = g_object_ref (event->window); + bevent->any.send_event = FALSE; + bevent->motion.time = event->time; + bevent->motion.state = event->state | GDK_BUTTON1_MASK; + bevent->motion.x_root = event->x_root; + bevent->motion.y_root = event->y_root; + bevent->motion.x = event->x; + bevent->motion.y = event->y; + bevent->motion.device = event->device; + bevent->motion.is_hint = FALSE; + bevent->motion.axes = g_memdup (event->axes, + sizeof (gdouble) * gdk_device_get_n_axes (event->device)); + gdk_event_set_source_device (bevent, gdk_event_get_source_device ((GdkEvent*)event)); + } + SP_CANVAS(widget)->emitEvent(reinterpret_cast(bevent)); + gdk_event_free (bevent); + return TRUE; +} + static inline void request_motions(GdkWindow *w, GdkEventMotion *event) { gdk_window_get_device_position(w, gdk_event_get_device((GdkEvent *)(event)), === modified file 'src/display/sp-canvas.h' --- src/display/sp-canvas.h 2017-04-09 07:39:28 +0000 +++ src/display/sp-canvas.h 2017-04-09 07:40:03 +0000 @@ -140,7 +140,7 @@ /// Convenience function to add an idle handler to a canvas. void addIdle(); void removeIdle(); - + public: // GTK virtual functions. static void dispose(GObject *object); @@ -157,6 +157,7 @@ * @todo FIXME: generate motion events to re-select items. */ static gint handle_scroll(GtkWidget *widget, GdkEventScroll *event); + static gint handle_touch(GtkWidget *widget, GdkEventTouch *event); static gint handle_motion(GtkWidget *widget, GdkEventMotion *event); static gboolean handle_draw(GtkWidget *widget, cairo_t *cr); static gint handle_key_event(GtkWidget *widget, GdkEventKey *event); === modified file 'src/ui/tools/arc-tool.cpp' --- src/ui/tools/arc-tool.cpp 2016-08-03 13:29:38 +0000 +++ src/ui/tools/arc-tool.cpp 2017-04-09 07:40:03 +0000 @@ -161,7 +161,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, NULL, event->button.time); handled = true; m.unSetup(); === modified file 'src/ui/tools/box3d-tool.cpp' --- src/ui/tools/box3d-tool.cpp 2016-10-24 22:58:43 +0000 +++ src/ui/tools/box3d-tool.cpp 2017-04-09 07:40:03 +0000 @@ -228,7 +228,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); ret = TRUE; === modified file 'src/ui/tools/calligraphic-tool.cpp' --- src/ui/tools/calligraphic-tool.cpp 2016-11-09 00:23:41 +0000 +++ src/ui/tools/calligraphic-tool.cpp 2017-04-09 07:40:03 +0000 @@ -457,6 +457,7 @@ ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_TOUCH_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); === modified file 'src/ui/tools/dropper-tool.cpp' --- src/ui/tools/dropper-tool.cpp 2016-08-04 11:26:03 +0000 +++ src/ui/tools/dropper-tool.cpp 2017-04-09 07:40:03 +0000 @@ -162,7 +162,7 @@ } sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->acetate); === modified file 'src/ui/tools/eraser-tool.cpp' --- src/ui/tools/eraser-tool.cpp 2016-11-09 00:23:41 +0000 +++ src/ui/tools/eraser-tool.cpp 2017-04-09 07:40:03 +0000 @@ -405,7 +405,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); === modified file 'src/ui/tools/measure-tool.cpp' --- src/ui/tools/measure-tool.cpp 2016-10-03 19:22:23 +0000 +++ src/ui/tools/measure-tool.cpp 2017-04-09 07:40:03 +0000 @@ -568,7 +568,7 @@ snap_manager.unSetup(); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->acetate); break; === modified file 'src/ui/tools/pen-tool.cpp' --- src/ui/tools/pen-tool.cpp 2016-11-05 02:32:30 +0000 +++ src/ui/tools/pen-tool.cpp 2017-04-09 07:40:03 +0000 @@ -390,7 +390,7 @@ this->grab = SP_CANVAS_ITEM(desktop->acetate); sp_canvas_item_grab(this->grab, ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK ), + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK ), NULL, bevent.time); } === modified file 'src/ui/tools/pencil-tool.cpp' --- src/ui/tools/pencil-tool.cpp 2016-11-05 02:32:30 +0000 +++ src/ui/tools/pencil-tool.cpp 2017-04-09 07:40:03 +0000 @@ -151,7 +151,7 @@ this->grab = SP_CANVAS_ITEM(desktop->acetate); sp_canvas_item_grab(this->grab, ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK ), + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK ), NULL, bevent.time); } @@ -235,7 +235,7 @@ this->grab = SP_CANVAS_ITEM(desktop->acetate); sp_canvas_item_grab(this->grab, ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK ), + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK ), NULL, mevent.time); } === modified file 'src/ui/tools/rect-tool.cpp' --- src/ui/tools/rect-tool.cpp 2016-10-24 22:58:43 +0000 +++ src/ui/tools/rect-tool.cpp 2017-04-09 07:40:03 +0000 @@ -191,7 +191,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); === modified file 'src/ui/tools/select-tool.cpp' --- src/ui/tools/select-tool.cpp 2017-03-03 19:54:22 +0000 +++ src/ui/tools/select-tool.cpp 2017-04-09 07:40:03 +0000 @@ -312,7 +312,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->drawing), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->drawing); @@ -511,7 +511,7 @@ } sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->acetate); === modified file 'src/ui/tools/spiral-tool.cpp' --- src/ui/tools/spiral-tool.cpp 2016-08-03 13:29:38 +0000 +++ src/ui/tools/spiral-tool.cpp 2017-04-09 07:40:03 +0000 @@ -162,6 +162,7 @@ ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); === modified file 'src/ui/tools/star-tool.cpp' --- src/ui/tools/star-tool.cpp 2016-08-03 13:29:38 +0000 +++ src/ui/tools/star-tool.cpp 2017-04-09 07:40:03 +0000 @@ -177,7 +177,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, NULL, event->button.time); === modified file 'src/ui/tools/text-tool.cpp' --- src/ui/tools/text-tool.cpp 2017-02-28 11:48:29 +0000 +++ src/ui/tools/text-tool.cpp 2017-04-09 07:40:03 +0000 @@ -534,7 +534,7 @@ this->p0 = button_dt; Inkscape::Rubberband::get(desktop)->start(desktop, this->p0); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, + GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->acetate); this->creating = 1; === modified file 'src/ui/tools/tool-base.cpp' --- src/ui/tools/tool-base.cpp 2017-03-30 09:41:29 +0000 +++ src/ui/tools/tool-base.cpp 2017-04-09 07:40:03 +0000 @@ -371,7 +371,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time - 1); @@ -391,7 +391,7 @@ sp_canvas_item_grab (desktop->canvas_rotate, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK, + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK, NULL, event->button.time ); // sp_canvas_item_hide (desktop->drawing); @@ -405,7 +405,7 @@ panning = 2; sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time - 1); @@ -423,7 +423,7 @@ panning = 3; sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time); @@ -448,7 +448,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->motion.time - 1); } === modified file 'src/ui/tools/zoom-tool.cpp' --- src/ui/tools/zoom-tool.cpp 2017-03-29 09:07:32 +0000 +++ src/ui/tools/zoom-tool.cpp 2017-04-09 07:40:03 +0000 @@ -107,7 +107,7 @@ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, + GDK_POINTER_MOTION_MASK | GDK_TOUCH_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, event->button.time); this->grabbed = SP_CANVAS_ITEM(desktop->acetate);