diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 79013b43..af3fa54b 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -37,6 +37,10 @@ #include "src/layout.h" #include "src/submission.h" +#define LIBFEEDBACK_USE_UNSTABLE_API +#include + +#define SQUEEKBOARD_APP_ID "sm.puri.squeekboard" typedef struct _EekGtkKeyboardPrivate { @@ -48,6 +52,7 @@ typedef struct _EekGtkKeyboardPrivate LevelKeyboard *keyboard; // unowned reference; it's kept in server-context GdkEventSequence *sequence; // unowned reference + LfbEvent *event; } EekGtkKeyboardPrivate; G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA) @@ -135,6 +140,19 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, size_allocate (self, allocation); } +static void +on_event_triggered (LfbEvent *event, + GAsyncResult *res, + gpointer unused) +{ + g_autoptr (GError) err = NULL; + + if (!lfb_event_trigger_feedback_finish (event, res, &err)) { + g_warning ("Failed to trigger feedback for '%s': %s", + lfb_event_get_event (event), err->message); + } +} + static void depress(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { @@ -299,6 +317,11 @@ eek_gtk_keyboard_dispose (GObject *object) priv->keyboard = NULL; } + if (priv->event) { + g_clear_object (&priv->event); + lfb_uninit (); + } + G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object); } @@ -330,7 +353,13 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass) static void eek_gtk_keyboard_init (EekGtkKeyboard *self) { - (void)self; + EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + g_autoptr(GError) err = NULL; + + if (lfb_init(SQUEEKBOARD_APP_ID, &err)) + priv->event = lfb_event_new ("button-pressed"); + else + g_warning ("Failed to init libfeedback: %s", err->message); } static void @@ -376,3 +405,24 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice, return GTK_WIDGET(box);*/ return GTK_WIDGET(ret); } + +/** + * eek_gtk_keyboard_emit_feedback: + * + * Emit button press haptic feedback via libfeedack. + */ +void +eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self) +{ + EekGtkKeyboardPrivate *priv; + + g_return_if_fail (EEK_IS_GTK_KEYBOARD (self)); + + priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + if (priv->event) { + lfb_event_trigger_feedback_async (priv->event, + NULL, + (GAsyncReadyCallback)on_event_triggered, + NULL); + } +} diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index 7570ac05..1f07cba3 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -49,6 +49,7 @@ struct _EekGtkKeyboardClass GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST; GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout); +void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self); G_END_DECLS #endif /* EEK_GTK_KEYBOARD_H */ diff --git a/src/layout.rs b/src/layout.rs index 09fc4f72..41515bc5 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -52,6 +52,14 @@ pub mod c { #[derive(Copy, Clone)] pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget); + #[no_mangle] + extern "C" { + #[allow(improper_ctypes)] + pub fn eek_gtk_keyboard_emit_feedback( + keyboard: EekGtkKeyboard, + ); + } + /// Defined in eek-types.h #[repr(C)] #[derive(Clone, Debug, PartialEq)] @@ -341,6 +349,9 @@ pub mod c { ); // maybe TODO: draw on the display buffer here drawing::queue_redraw(ui_keyboard); + unsafe { + eek_gtk_keyboard_emit_feedback(ui_keyboard); + } }; } @@ -404,6 +415,9 @@ pub mod c { &state, ); // maybe TODO: draw on the display buffer here + unsafe { + eek_gtk_keyboard_emit_feedback(ui_keyboard); + } } } else { for wrapped_key in pressed { diff --git a/src/meson.build b/src/meson.build index 8aa1c78b..1502dd31 100644 --- a/src/meson.build +++ b/src/meson.build @@ -38,6 +38,7 @@ deps = [ dependency('gio-2.0', version: '>=2.26.0'), dependency('gnome-desktop-3.0', version: '>=3.0'), dependency('gtk+-3.0', version: '>=3.0'), + dependency('libfeedback-0.0'), dependency('wayland-client', version: '>=1.14'), dependency('xkbcommon'), cc.find_library('m'),