static void handle_touch_event (GdkWindow *window, const MirTouchEvent *mir_touch_event) { const MirInputEvent *mir_input_event = mir_touch_event_input_event (mir_touch_event); guint n = mir_touch_event_point_count (mir_touch_event); GdkEvent *gdk_event; guint i; for (i = 0; i < n; i++) { MirTouchAction action = mir_touch_event_action (mir_touch_event, i); if (action == mir_touch_action_up) gdk_event = gdk_event_new (GDK_TOUCH_END); else if (action == mir_touch_action_down) gdk_event = gdk_event_new (GDK_TOUCH_BEGIN); else gdk_event = gdk_event_new (GDK_TOUCH_UPDATE); gdk_event->touch.window = window; gdk_event->touch.sequence = GINT_TO_POINTER (mir_touch_event_id (mir_touch_event, i)); gdk_event->touch.time = mir_input_event_get_event_time (mir_input_event); gdk_event->touch.state = get_modifier_state (mir_touch_event_modifiers (mir_touch_event), 0); gdk_event->touch.x = mir_touch_event_axis_value (mir_touch_event, i, mir_touch_axis_x); gdk_event->touch.y = mir_touch_event_axis_value (mir_touch_event, i, mir_touch_axis_y); gdk_event->touch.x_root = mir_touch_event_axis_value (mir_touch_event, i, mir_touch_axis_x); gdk_event->touch.y_root = mir_touch_event_axis_value (mir_touch_event, i, mir_touch_axis_y); gdk_event->touch.emulating_pointer = TRUE; gdk_event_set_pointer_emulated (gdk_event, TRUE); send_event (window, get_pointer (window), gdk_event); } }
void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev) { const MirTouchEvent *tev = mir_input_event_get_touch_event(ev); // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That // needs to be fixed as soon as the compat input lib adds query support. const float kMaxPressure = 1.28; const QRect kWindowGeometry = window->geometry(); QList<QWindowSystemInterface::TouchPoint> touchPoints; // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left // as Qt::TouchPointMoved const unsigned int kPointerCount = mir_touch_event_point_count(tev); touchPoints.reserve(int(kPointerCount)); for (unsigned int i = 0; i < kPointerCount; ++i) { QWindowSystemInterface::TouchPoint touchPoint; const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x(); const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major); const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor); const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure); touchPoint.id = mir_touch_event_id(tev, i); touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height()); touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH); touchPoint.pressure = kP / kMaxPressure; MirTouchAction touch_action = mir_touch_event_action(tev, i); switch (touch_action) { case mir_touch_action_down: mLastInputWindow = window; touchPoint.state = Qt::TouchPointPressed; break; case mir_touch_action_up: touchPoint.state = Qt::TouchPointReleased; break; case mir_touch_action_change: touchPoint.state = Qt::TouchPointMoved; break; default: Q_UNREACHABLE(); } touchPoints.append(touchPoint); } ulong timestamp = mir_input_event_get_event_time(ev) / 1000000; QWindowSystemInterface::handleTouchEvent(window->window(), timestamp, mTouchDevice, touchPoints); }
TEST_F(InputEventBuilder, makes_valid_touch_event) { unsigned touch_count = 3; MirTouchId touch_ids[] = {7, 9, 4}; MirTouchAction actions[] = { mir_touch_action_up, mir_touch_action_change, mir_touch_action_change}; MirTouchTooltype tooltypes[] = {mir_touch_tooltype_unknown, mir_touch_tooltype_finger, mir_touch_tooltype_stylus}; float x_axis_values[] = { 7, 14.3, 19.6 }; float y_axis_values[] = { 3, 9, 11 }; float pressure_values[] = {3, 9, 14.6}; float touch_major_values[] = {11, 9, 14}; float touch_minor_values[] = {13, 3, 9.13}; float size_values[] = {4, 9, 6}; auto ev = mev::make_event(device_id, timestamp, mac, modifiers); for (unsigned i = 0; i < touch_count; i++) { mev::add_touch(*ev, touch_ids[i], actions[i], tooltypes[i], x_axis_values[i], y_axis_values[i], pressure_values[i], touch_major_values[i], touch_minor_values[i], size_values[i]); } auto e = ev.get(); EXPECT_EQ(mir_event_type_input, mir_event_get_type(e)); auto ie = mir_event_get_input_event(e); EXPECT_EQ(mir_input_event_type_touch, mir_input_event_get_type(ie)); auto tev = mir_input_event_get_touch_event(ie); EXPECT_EQ(modifiers, mir_touch_event_modifiers(tev)); EXPECT_EQ(touch_count, mir_touch_event_point_count(tev)); EXPECT_EQ(mac, mir_touch_event_get_cookie(tev).mac); EXPECT_EQ(timestamp.count(), mir_touch_event_get_cookie(tev).timestamp); for (unsigned i = 0; i < touch_count; i++) { EXPECT_EQ(touch_ids[i], mir_touch_event_id(tev, i)); EXPECT_EQ(actions[i], mir_touch_event_action(tev, i)); EXPECT_EQ(tooltypes[i], mir_touch_event_tooltype(tev, i)); EXPECT_EQ(x_axis_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_x)); EXPECT_EQ(y_axis_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_y)); EXPECT_EQ(pressure_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure)); EXPECT_EQ(touch_major_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major)); EXPECT_EQ(touch_minor_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor)); EXPECT_EQ(size_values[i], mir_touch_event_axis_value(tev, i, mir_touch_axis_size)); } }