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); } }
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)); } }
bool me::WindowManager::handle_touch_event(MirTouchEvent const* tev) { bool handled = false; geometry::Point cursor = average_pointer(tev); auto const& modifiers = mir_touch_event_modifiers(tev); int fingers = mir_touch_event_point_count(tev); if (fingers > max_fingers) max_fingers = fingers; auto const surf = focus_controller->focused_surface(); if (surf && (modifiers & mir_input_event_modifier_alt || fingers >= 3)) { geometry::Displacement pinch_dir; auto pinch_diam = measure_pinch(tev, pinch_dir); // Start of a gesture: When the latest finger/button goes down if (any_touches_went_down(tev)) { click = cursor; save_edges(*surf, click); handled = true; } else if(max_fingers <= 3) // Avoid accidental movement { geometry::Displacement drag = cursor - old_cursor; surf->move_to(old_pos + drag); if (fingers == 3) { // Resize by pinch/zoom float diam_delta = pinch_diam - old_pinch_diam; /* * Resize vector (dx,dy) has length=diam_delta and * direction=pinch_dir, so solve for (dx,dy)... */ float lenlen = diam_delta * diam_delta; int x = pinch_dir.dx.as_int(); int y = pinch_dir.dy.as_int(); int xx = x * x; int yy = y * y; int xxyy = xx + yy; int dx = sqrtf(lenlen * xx / xxyy); int dy = sqrtf(lenlen * yy / xxyy); if (diam_delta < 0.0f) { dx = -dx; dy = -dy; } int width = old_size.width.as_int() + dx; int height = old_size.height.as_int() + dy; surf->resize({width, height}); } handled = true; } old_pos = surf->top_left(); old_size = surf->size(); old_pinch_diam = pinch_diam; } auto gesture_ended = last_touch_released(tev); if (max_fingers == 4 && gesture_ended) { // Four fingers released geometry::Displacement dir = cursor - click; if (abs(dir.dx.as_int()) >= min_swipe_distance) { focus_controller->focus_next_session(); if (auto const surface = focus_controller->focused_surface()) focus_controller->raise({surface}); handled = true; } } if (fingers == 1 && gesture_ended) max_fingers = 0; old_cursor = cursor; return handled; }