static void handle_key_event (GdkWindow *window, const MirInputEvent *event) { const MirKeyboardEvent *keyboard_event = mir_input_event_get_keyboard_event (event); GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); GdkKeymap *keymap; guint modifier_state; guint button_state; if (!keyboard_event) return; switch (mir_keyboard_event_action (keyboard_event)) { case mir_keyboard_action_up: case mir_keyboard_action_down: // FIXME: Convert keycode _gdk_mir_window_impl_get_cursor_state (impl, NULL, NULL, NULL, &button_state); modifier_state = get_modifier_state (mir_keyboard_event_modifiers (keyboard_event), button_state); keymap = gdk_keymap_get_for_display (gdk_window_get_display (window)); generate_key_event (window, mir_keyboard_event_action (keyboard_event) == mir_keyboard_action_down ? GDK_KEY_PRESS : GDK_KEY_RELEASE, modifier_state, mir_keyboard_event_key_code (keyboard_event), mir_keyboard_event_scan_code (keyboard_event), _gdk_mir_keymap_key_is_modifier (keymap, mir_keyboard_event_key_code (keyboard_event)), NANO_TO_MILLI (mir_input_event_get_event_time (event))); break; default: //case mir_key_action_multiple: // FIXME break; } }
void _gdk_mir_print_key_event (const MirInputEvent *event) { const MirKeyboardEvent *keyboard_event = mir_input_event_get_keyboard_event (event); if (!keyboard_event) return; g_printerr ("KEY\n"); g_printerr (" Device %lld\n", (long long int) mir_input_event_get_device_id (event)); g_printerr (" Action "); switch (mir_keyboard_event_action (keyboard_event)) { case mir_keyboard_action_down: g_printerr ("down"); break; case mir_keyboard_action_up: g_printerr ("up"); break; case mir_keyboard_action_repeat: g_printerr ("repeat"); break; default: g_printerr ("%u", mir_keyboard_event_action (keyboard_event)); break; } g_printerr ("\n"); _gdk_mir_print_modifiers (mir_keyboard_event_modifiers (keyboard_event)); g_printerr (" Key Code %i\n", mir_keyboard_event_key_code (keyboard_event)); g_printerr (" Scan Code %i\n", mir_keyboard_event_scan_code (keyboard_event)); g_printerr (" Event Time %lli\n", (long long int) mir_input_event_get_event_time (event)); }
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); }
void _gdk_mir_print_motion_event (const MirInputEvent *event) { const MirPointerEvent *pointer_event = mir_input_event_get_pointer_event (event); if (!pointer_event) return; g_printerr ("MOTION\n"); g_printerr (" Device %lld\n", (long long int) mir_input_event_get_device_id (event)); g_printerr (" Action "); switch (mir_pointer_event_action (pointer_event)) { case mir_pointer_action_button_down: g_printerr ("down"); break; case mir_pointer_action_button_up: g_printerr ("up"); break; case mir_pointer_action_enter: g_printerr ("enter"); break; case mir_pointer_action_leave: g_printerr ("leave"); break; case mir_pointer_action_motion: g_printerr ("motion"); break; default: g_printerr ("%u", mir_pointer_event_action (pointer_event)); } g_printerr ("\n"); _gdk_mir_print_modifiers (mir_pointer_event_modifiers (pointer_event)); g_printerr (" Button State"); if (mir_pointer_event_button_state (pointer_event, mir_pointer_button_primary)) g_printerr (" primary"); if (mir_pointer_event_button_state (pointer_event, mir_pointer_button_secondary)) g_printerr (" secondary"); if (mir_pointer_event_button_state (pointer_event, mir_pointer_button_tertiary)) g_printerr (" tertiary"); if (mir_pointer_event_button_state (pointer_event, mir_pointer_button_back)) g_printerr (" back"); if (mir_pointer_event_button_state (pointer_event, mir_pointer_button_forward)) g_printerr (" forward"); g_printerr ("\n"); g_printerr (" Offset (%f, %f)\n", mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_x), mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_y)); g_printerr (" Event Time %lli\n", (long long int) mir_input_event_get_event_time (event)); }
void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event) { const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event); ulong timestamp = mir_input_event_get_event_time(event) / 1000000; xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event); quint32 scan_code = mir_keyboard_event_scan_code(key_event); quint32 native_modifiers = mir_keyboard_event_modifiers(key_event); // Key modifier and unicode index mapping. auto modifiers = qt_modifiers_from_mir(native_modifiers); MirKeyboardAction action = mir_keyboard_event_action(key_event); QEvent::Type keyType = action == mir_keyboard_action_up ? QEvent::KeyRelease : QEvent::KeyPress; if (action == mir_keyboard_action_down) mLastInputWindow = window; QString text; QVarLengthArray<char, 32> chars(32); { int result = xkb_keysym_to_utf8(xk_sym, chars.data(), chars.size()); if (result > 0) { text = QString::fromUtf8(chars.constData()); } } int sym = translateKeysym(xk_sym, text); bool is_auto_rep = action == mir_keyboard_action_repeat; QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); if (context) { QKeyEvent qKeyEvent(keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep); qKeyEvent.setTimestamp(timestamp); if (context->filterEvent(&qKeyEvent)) { qCDebug(mirclient, "key event filtered out by input context"); return; } } QWindowSystemInterface::handleExtendedKeyEvent(window->window(), timestamp, keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep); }
void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev) { const auto window = platformWindow->window(); const auto timestamp = mir_input_event_get_event_time(ev) / 1000000; const auto pev = mir_input_event_get_pointer_event(ev); const auto action = mir_pointer_event_action(pev); const auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev)); const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); mLastInputWindow = platformWindow; switch (action) { case mir_pointer_action_button_up: case mir_pointer_action_button_down: case mir_pointer_action_motion: { const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll); const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll); if (hDelta != 0 || vDelta != 0) { // QWheelEvent::DefaultDeltasPerStep = 120 but doesn't exist on vivid const QPoint angleDelta(120 * hDelta, 120 * vDelta); QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint, QPoint(), angleDelta, modifiers, Qt::ScrollUpdate); } auto buttons = extract_buttons(pev); QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */, buttons, modifiers); break; } case mir_pointer_action_enter: QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint); break; case mir_pointer_action_leave: QWindowSystemInterface::handleLeaveEvent(window); break; default: Q_UNREACHABLE(); } }
static void handle_motion_event (GdkWindow *window, const MirInputEvent *event) { const MirPointerEvent *pointer_event = mir_input_event_get_pointer_event (event); GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); gdouble x, y; gboolean cursor_inside; guint button_state; guint modifier_state; guint32 event_time; GdkEventType event_type; guint changed_button_state; if (!pointer_event) return; _gdk_mir_window_impl_get_cursor_state (impl, &x, &y, &cursor_inside, &button_state); modifier_state = get_modifier_state (mir_pointer_event_modifiers (pointer_event), mir_pointer_event_get_button_state (pointer_event)); event_time = NANO_TO_MILLI (mir_input_event_get_event_time (event)); /* TODO: Remove once we have proper transient window support. */ if (mir_pointer_event_action (pointer_event) == mir_pointer_action_leave) { LeaveInfo info; info.x = x; info.y = y; info.time = event_time; info.except = window; /* Leave all transient children from leaf to root, except the root since we do it later. */ _gdk_mir_window_transient_children_foreach (window, leave_windows_except, &info); } else { LeaveInfo info; info.x = x; info.y = y; info.time = event_time; info.except = _gdk_mir_window_get_visible_transient_child (window, x, y, &x, &y); /* Leave all transient children from leaf to root, except the pointer window since we enter it. */ _gdk_mir_window_transient_children_foreach (window, leave_windows_except, &info); window = info.except; if (window) { /* Enter the pointer window. */ gboolean cursor_inside_pointer_window; impl = GDK_MIR_WINDOW_IMPL (window->impl); _gdk_mir_window_impl_get_cursor_state (impl, NULL, NULL, &cursor_inside_pointer_window, NULL); if (!cursor_inside_pointer_window) { generate_crossing_event (window, GDK_ENTER_NOTIFY, x, y, event_time); _gdk_mir_window_impl_set_cursor_state (impl, x, y, TRUE, mir_pointer_event_get_button_state (pointer_event)); } } } if (window) { gdouble new_x; gdouble new_y; gdouble hscroll; gdouble vscroll; /* Update which window has focus */ _gdk_mir_pointer_set_location (get_pointer (window), x, y, window, modifier_state); switch (mir_pointer_event_action (pointer_event)) { case mir_pointer_action_button_up: case mir_pointer_action_button_down: event_type = mir_pointer_event_action (pointer_event) == mir_pointer_action_button_down ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE; changed_button_state = button_state ^ mir_pointer_event_get_button_state (pointer_event); if (changed_button_state == 0 || (changed_button_state & mir_pointer_button_primary) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_PRIMARY, modifier_state, event_time); if ((changed_button_state & mir_pointer_button_secondary) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_SECONDARY, modifier_state, event_time); if ((changed_button_state & mir_pointer_button_tertiary) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_MIDDLE, modifier_state, event_time); button_state = mir_pointer_event_get_button_state (pointer_event); break; case mir_pointer_action_motion: new_x = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_x); new_y = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_y); hscroll = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_hscroll); vscroll = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_vscroll); if (hscroll > 0.5 || vscroll > 0.5) generate_scroll_event (window, x, y, hscroll, vscroll, modifier_state, event_time); if (ABS (new_x - x) > 0.5 || ABS (new_y - y) > 0.5) generate_motion_event (window, new_x, new_y, modifier_state, event_time); break; case mir_pointer_action_leave: if (cursor_inside) { cursor_inside = FALSE; generate_crossing_event (window, GDK_LEAVE_NOTIFY, x, y, event_time); } break; default: break; } _gdk_mir_window_impl_set_cursor_state (impl, x, y, cursor_inside, button_state); } }
static void handle_motion_event (GdkWindow *window, const MirInputEvent *event) { const MirPointerEvent *pointer_event = mir_input_event_get_pointer_event (event); GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl); gdouble x, y; gboolean cursor_inside; guint button_state; guint new_button_state; guint modifier_state; guint32 event_time; GdkEventType event_type; guint changed_button_state; if (!pointer_event) return; _gdk_mir_window_impl_get_cursor_state (impl, &x, &y, &cursor_inside, &button_state); new_button_state = get_button_state (pointer_event); modifier_state = get_modifier_state (mir_pointer_event_modifiers (pointer_event), new_button_state); event_time = NANO_TO_MILLI (mir_input_event_get_event_time (event)); if (window) { gdouble new_x; gdouble new_y; gdouble hscroll; gdouble vscroll; /* Update which window has focus */ _gdk_mir_pointer_set_location (get_pointer (window), x, y, window, modifier_state); switch (mir_pointer_event_action (pointer_event)) { case mir_pointer_action_button_up: case mir_pointer_action_button_down: event_type = mir_pointer_event_action (pointer_event) == mir_pointer_action_button_down ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE; changed_button_state = button_state ^ new_button_state; if (changed_button_state == 0 || (changed_button_state & GDK_BUTTON1_MASK) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_PRIMARY, modifier_state, event_time); if ((changed_button_state & GDK_BUTTON2_MASK) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_MIDDLE, modifier_state, event_time); if ((changed_button_state & GDK_BUTTON3_MASK) != 0) generate_button_event (window, event_type, x, y, GDK_BUTTON_SECONDARY, modifier_state, event_time); button_state = new_button_state; break; case mir_pointer_action_motion: new_x = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_x); new_y = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_y); hscroll = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_hscroll); vscroll = mir_pointer_event_axis_value (pointer_event, mir_pointer_axis_vscroll); if (hscroll != 0.0 || vscroll != 0.0) generate_scroll_event (window, x, y, hscroll, vscroll, modifier_state, event_time); if (ABS (new_x - x) > 0.5 || ABS (new_y - y) > 0.5) { generate_motion_event (window, new_x, new_y, modifier_state, event_time); x = new_x; y = new_y; } break; case mir_pointer_action_enter: if (!cursor_inside) { cursor_inside = TRUE; generate_crossing_event (window, GDK_ENTER_NOTIFY, x, y, event_time); } break; case mir_pointer_action_leave: if (cursor_inside) { cursor_inside = FALSE; generate_crossing_event (window, GDK_LEAVE_NOTIFY, x, y, event_time); } break; default: break; } _gdk_mir_window_impl_set_cursor_state (impl, x, y, cursor_inside, button_state); } }