static GdkModifierType
gdk_android_events_meta_to_gdk (gint32 modifiers)
{
GdkModifierType ret = 0; if (modifiers & AMETA_SHIFT_ON)
ret |= GDK_SHIFT_MASK; if (modifiers & AMETA_CAPS_LOCK_ON)
ret |= GDK_LOCK_MASK; if (modifiers & AMETA_CTRL_ON)
ret |= GDK_CONTROL_MASK; if (modifiers & AMETA_ALT_ON)
ret |= GDK_ALT_MASK; if (modifiers & AMETA_META_ON)
ret |= GDK_META_MASK; return ret;
}
static GdkModifierType
gdk_android_events_buttons_to_gdkmods (gint32 buttons)
{
GdkModifierType ret = 0; if (buttons & AMOTION_EVENT_BUTTON_PRIMARY)
ret |= GDK_BUTTON1_MASK; if (buttons & AMOTION_EVENT_BUTTON_SECONDARY)
ret |= GDK_BUTTON3_MASK; // X11 button numbering if (buttons & AMOTION_EVENT_BUTTON_TERTIARY)
ret |= GDK_BUTTON2_MASK; // ditto if (buttons & AMOTION_EVENT_BUTTON_BACK)
ret |= GDK_BUTTON4_MASK; if (buttons & AMOTION_EVENT_BUTTON_FORWARD)
ret |= GDK_BUTTON5_MASK; return ret;
}
// Taken from Thomas Mueller on SO, licensed under CC BY-SA 4.0 // https://stackoverflow.com/a/12996028/10890264 static guint
gdk_android_events_int_hash (guint32 num)
{
num = ((num >> 16) ^ num) * 0x45d9f3bu;
num = ((num >> 16) ^ num) * 0x45d9f3bu;
num = (num >> 16) ^ num; return num;
}
gint64 time = AMotionEvent_getEventTime (event) / 1000000/* ns to ms */;
// Update keyboard focus on motion events only for autohide surfaces // This *doesn't really* match the behaviour of Mutter (autohide popups // get keyboard focus on present, while non-autohide popups do not), // especially as motion events shouldn't update keyboard focus, but it'll // work in the grand scheme of things for now. if (GDK_IS_ANDROID_TOPLEVEL(surface) || ((GdkSurface *)surface)->autohide)
{
GdkDevice *keyboard = gdk_seat_get_keyboard ((GdkSeat *) display->seat);
gdk_android_device_keyboard_maybe_update_surface_focus ((GdkAndroidDevice *) keyboard, surface);
}
if (GDK_ANDROID_EVENTS_COMPARE_MASK (src, AINPUT_SOURCE_TOUCHSCREEN))
{ // I think it might be better to drop the down time and only rely on the event identity
guint base_sequence = gdk_android_surface_long_hash ((guint64) AMotionEvent_getDownTime (event));
base_sequence ^= (guint) event_identifier;
size_t pointers = AMotionEvent_getPointerCount (event); for (size_t i = 0; i < pointers; i++)
{
GdkEventType ev_type = gdk_android_events_touch_action_to_gdk (event, i);
// this will cause conflicts in cases where the mouse/touchpad and // a stylus is used at the same time, but I don't know if this is // worth handling if (masked_action == AMOTION_EVENT_ACTION_DOWN)
dev_impl->button_state |= AMOTION_EVENT_BUTTON_PRIMARY; else
dev_impl->button_state &= ~AMOTION_EVENT_BUTTON_PRIMARY;
}
gdk_android_device_maybe_update_surface ((GdkAndroidDevice *) dev, surface, mods, time, x, y);
} elseif (masked_action == AMOTION_EVENT_ACTION_BUTTON_PRESS ||
masked_action == AMOTION_EVENT_ACTION_BUTTON_RELEASE)
{ // This code serves little purpose, as BUTTON_BACK and BUTTON_FORWARD are // are seemingly not actually passed to the application. Instead // BUTTON_BACK triggers the navigate back action and BUTTON_FORWARD does // (at least visibly) nothing. /*gint32 button_state = AMotionEvent_getButtonState(event);
// as changes in BUTTON_STYLUS_{PRIMARY,SECONDARY} do not emit a special // event, we'll have to check for changes during move events. This should // be fine, given that it's quite hard if not impossible (depending on the // tablet) to press a stylus button without causing a move event.
gint32 button_state = AMotionEvent_getButtonState (event); if (GDK_ANDROID_EVENTS_BUTTON_IS_DIFFERENT (button_state, dev_impl->button_state, AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))
gdk_android_events_emit_button_press (AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, button_state,
GDK_BUTTON_MIDDLE,
surface, event, dev,
time, mods,
x, y); if (GDK_ANDROID_EVENTS_BUTTON_IS_DIFFERENT (button_state, dev_impl->button_state, AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))
gdk_android_events_emit_button_press (AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, button_state,
GDK_BUTTON_SECONDARY,
surface, event, dev,
time, mods,
x, y); const guint update_mask = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY | AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
dev_impl->button_state = (dev_impl->button_state & ~update_mask) | (button_state & update_mask);
gdk_android_device_maybe_update_surface ((GdkAndroidDevice *) dev, surface, mods, time, x, y);
} elseif (masked_action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
masked_action == AMOTION_EVENT_ACTION_HOVER_EXIT)
{ // This would be a good place to put crossing events, however it seems like android also // produces hover enter/hover exit events when clicking the button. /*GdkEvent *ev = gdk_crossing_event_new ((masked_action == AMOTION_EVENT_ACTION_HOVER_ENTER) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY, (GdkSurface*)surface,dev, time,mods, x,y, GDK_CROSSING_NORMAL, GDK_NOTIFY_UNKNOWN);
gdk_android_seat_consume_event((GdkDisplay *)display, ev);*/
} else
{
g_warning ("Unhandled pointer event: %d [%d] on %p [%s]", masked_action, src, surface, G_OBJECT_TYPE_NAME (surface));
}
} elseif (GDK_ANDROID_EVENTS_COMPARE_MASK (src, AINPUT_SOURCE_JOYSTICK))
{
(*env)->PushLocalFrame (env, 2);
jobject jdevice = (*env)->CallObjectMethod (env, motion_event, gdk_android_get_java_cache ()->a_input_event.get_device); struct
{
gint32 axis;
guint index;
gfloat min;
gfloat max;
GdkEvent *(*constructor) (GdkSurface *surface, GdkDevice *device, guint32 time, guint group, guint index, guint mode, double value);
} pad_axes[] = {
{ AMOTION_EVENT_AXIS_WHEEL, 0, 0.f, 360.f, gdk_pad_event_new_ring }
}; for (gsize i = 0; i < G_N_ELEMENTS (pad_axes); i++)
{
gdouble value; if (gdk_android_seat_normalize_range (env, jdevice, event, 0, pad_axes[i].axis, pad_axes[i].min, pad_axes[i].max, &value) && value != 0.)
{ // the value != 0. check is less than ideal, as 0 is a legitimate value, but // android also returns 0 when the finger leaves the ring (and often just // randomly too)
GdkEvent *ev = pad_axes[i].constructor ((GdkSurface *) surface, gdk_seat_get_keyboard ((GdkSeat *) display->seat),
time, 0, pad_axes[i].index, 0,
value);
gdk_android_seat_consume_event ((GdkDisplay *) display, ev);
}
}
(*env)->PopLocalFrame (env, NULL);
}
gint32 action = AKeyEvent_getAction (event); // The AKeyState enum values UP and DOWN are actually inversed // when the key is depressed the keystate is 0 (UP), while the // keystate becomes 1 (DOWN) once the key was released again.
GdkEventType event_type = (action == AKEY_STATE_UP || action == AKEY_STATE_VIRTUAL) ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.