[Libreoffice-commits] core.git: vcl/inc vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue May 11 12:39:57 UTC 2021


 vcl/inc/unx/gtk/gtkframe.hxx |    5 +
 vcl/unx/gtk3/gtkframe.cxx    |  129 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 132 insertions(+), 2 deletions(-)

New commits:
commit 0064b47ee1ea9e8c7a63497889d2aa7e0126b95d
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue May 11 10:38:08 2021 +0100
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Tue May 11 14:39:08 2021 +0200

    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 at redhat.com>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

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()


More information about the Libreoffice-commits mailing list