diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-05-11 10:38:08 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2021-05-11 14:39:08 +0200 |
commit | 0064b47ee1ea9e8c7a63497889d2aa7e0126b95d (patch) | |
tree | 9254f1649efee5b60203136ef19686177b04672e /vcl | |
parent | 9267e9fbd2ad1a05986f7ce16d4fef28cf7f08fb (diff) |
gtk4: add initial keyboard event support
basic typing works now
Change-Id: Iee248855c44151a9418818081910f748ff911755
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115391
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 5 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtkframe.cxx | 129 |
2 files changed, 132 insertions, 2 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index e7fff2ffbcfe..f80e6f068edf 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -295,6 +295,7 @@ class GtkSalFrame final : public SalFrame bool WindowCloseRequest(); void DrawingAreaMotion(int nEventX, int nEventY, guint32 nTime, guint nState); void DrawingAreaCrossing(SalEvent nEventType, int nEventX, int nEventY, guint32 nTime, guint nState); + bool DrawingAreaKey(SalEvent nEventType, guint keyval, guint keycode, guint32 nTime, guint nState); #if GTK_CHECK_VERSION(4, 0, 0) static void signalMap( GtkWidget*, gpointer ); static void signalUnmap( GtkWidget*, gpointer ); @@ -302,15 +303,17 @@ class GtkSalFrame final : public SalFrame static void signalMotion(GtkEventControllerMotion *controller, double x, double y, gpointer); static void signalEnter(GtkEventControllerMotion *controller, double x, double y, gpointer); static void signalLeave(GtkEventControllerMotion *controller, gpointer); + static gboolean signalKeyPressed(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer user_data); + static gboolean signalKeyReleased(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer user_data); #else static gboolean signalMap( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalUnmap( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalDelete( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalMotion( GtkWidget*, GdkEventMotion*, gpointer ); + static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer ); #endif #if !GTK_CHECK_VERSION(4, 0, 0) static gboolean signalConfigure( GtkWidget*, GdkEventConfigure*, gpointer ); - static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer ); static gboolean signalWindowState( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalScroll( GtkWidget*, GdkEvent*, gpointer ); static gboolean signalCrossing( GtkWidget*, GdkEventCrossing*, gpointer ); diff --git a/vcl/unx/gtk3/gtkframe.cxx b/vcl/unx/gtk3/gtkframe.cxx index b1f2becba4b2..718140d0ac86 100644 --- a/vcl/unx/gtk3/gtkframe.cxx +++ b/vcl/unx/gtk3/gtkframe.cxx @@ -1025,9 +1025,17 @@ void GtkSalFrame::InitCommon() #endif #if !GTK_CHECK_VERSION(4,0,0) g_signal_connect( G_OBJECT(m_pWindow), "configure-event", G_CALLBACK(signalConfigure), this ); + g_signal_connect( G_OBJECT(m_pWindow), "window-state-event", G_CALLBACK(signalWindowState), this ); +#endif +#if !GTK_CHECK_VERSION(4,0,0) g_signal_connect( G_OBJECT(m_pWindow), "key-press-event", G_CALLBACK(signalKey), this ); g_signal_connect( G_OBJECT(m_pWindow), "key-release-event", G_CALLBACK(signalKey), this ); - g_signal_connect( G_OBJECT(m_pWindow), "window-state-event", G_CALLBACK(signalWindowState), this ); +#else + GtkEventController* pKeyController = gtk_event_controller_key_new(); + g_signal_connect(pKeyController, "key-pressed", G_CALLBACK(signalKeyPressed), this); + g_signal_connect(pKeyController, "key-released", G_CALLBACK(signalKeyReleased), this); + gtk_widget_add_controller(pEventWidget, pKeyController); + #endif g_signal_connect( G_OBJECT(m_pWindow), "destroy", G_CALLBACK(signalDestroy), this ); @@ -3896,6 +3904,125 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe return bStopProcessingKey; } +#else + +bool GtkSalFrame::DrawingAreaKey(SalEvent nEventType, guint keyval, guint keycode, guint32 nTime, guint state) +{ + UpdateLastInputEventTime(nTime); + +#if 0 + if (m_pIMHandler && m_pIMHandler->handleKeyEvent(pEvent)) + return true; +#endif + + vcl::DeletionListener aDel(this); + + bool bStopProcessingKey = false; + + // handle modifiers + if( keyval == GDK_KEY_Shift_L || keyval == GDK_KEY_Shift_R || + keyval == GDK_KEY_Control_L || keyval == GDK_KEY_Control_R || + keyval == GDK_KEY_Alt_L || keyval == GDK_KEY_Alt_R || + keyval == GDK_KEY_Meta_L || keyval == GDK_KEY_Meta_R || + keyval == GDK_KEY_Super_L || keyval == GDK_KEY_Super_R ) + { + sal_uInt16 nModCode = GetKeyModCode(state); + ModKeyFlags nExtModMask = ModKeyFlags::NONE; + sal_uInt16 nModMask = 0; + // pressing just the ctrl key leads to a keysym of XK_Control but + // the event state does not contain ControlMask. In the release + // event it's the other way round: it does contain the Control mask. + // The modifier mode therefore has to be adapted manually. + switch (keyval) + { + case GDK_KEY_Control_L: + nExtModMask = ModKeyFlags::LeftMod1; + nModMask = KEY_MOD1; + break; + case GDK_KEY_Control_R: + nExtModMask = ModKeyFlags::RightMod1; + nModMask = KEY_MOD1; + break; + case GDK_KEY_Alt_L: + nExtModMask = ModKeyFlags::LeftMod2; + nModMask = KEY_MOD2; + break; + case GDK_KEY_Alt_R: + nExtModMask = ModKeyFlags::RightMod2; + nModMask = KEY_MOD2; + break; + case GDK_KEY_Shift_L: + nExtModMask = ModKeyFlags::LeftShift; + nModMask = KEY_SHIFT; + break; + case GDK_KEY_Shift_R: + nExtModMask = ModKeyFlags::RightShift; + nModMask = KEY_SHIFT; + break; + // Map Meta/Super to MOD3 modifier on all Unix systems + // except macOS + case GDK_KEY_Meta_L: + case GDK_KEY_Super_L: + nExtModMask = ModKeyFlags::LeftMod3; + nModMask = KEY_MOD3; + break; + case GDK_KEY_Meta_R: + case GDK_KEY_Super_R: + nExtModMask = ModKeyFlags::RightMod3; + nModMask = KEY_MOD3; + break; + } + + SalKeyModEvent aModEvt; + aModEvt.mbDown = nEventType == SalEvent::KeyInput; + + if (!aModEvt.mbDown) + { + aModEvt.mnModKeyCode = m_nKeyModifiers; + aModEvt.mnCode = nModCode & ~nModMask; + m_nKeyModifiers &= ~nExtModMask; + } + else + { + aModEvt.mnCode = nModCode | nModMask; + m_nKeyModifiers |= nExtModMask; + aModEvt.mnModKeyCode = m_nKeyModifiers; + } + + CallCallbackExc(SalEvent::KeyModChange, &aModEvt); + } + else + { + bStopProcessingKey = doKeyCallback(state, + keyval, + keycode, + 0, // group + sal_Unicode(gdk_keyval_to_unicode(keyval)), + nEventType == SalEvent::KeyInput, + false); + if (!aDel.isDeleted()) + m_nKeyModifiers = ModKeyFlags::NONE; + } + + if (m_pIMHandler) + m_pIMHandler->updateIMSpotLocation(); + + return bStopProcessingKey; +} + +gboolean GtkSalFrame::signalKeyPressed(GtkEventControllerKey* pController, guint keyval, guint keycode, GdkModifierType state, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + GdkEvent* pEvent = gtk_event_controller_get_current_event(GTK_EVENT_CONTROLLER(pController)); + return pThis->DrawingAreaKey(SalEvent::KeyInput, keyval, keycode, gdk_event_get_time(pEvent), state); +} + +gboolean GtkSalFrame::signalKeyReleased(GtkEventControllerKey* pController, guint keyval, guint keycode, GdkModifierType state, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + GdkEvent* pEvent = gtk_event_controller_get_current_event(GTK_EVENT_CONTROLLER(pController)); + return pThis->DrawingAreaKey(SalEvent::KeyUp, keyval, keycode, gdk_event_get_time(pEvent), state); +} #endif bool GtkSalFrame::WindowCloseRequest() |