summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2021-05-11 10:38:08 +0100
committerCaolán McNamara <caolanm@redhat.com>2021-05-11 14:39:08 +0200
commit0064b47ee1ea9e8c7a63497889d2aa7e0126b95d (patch)
tree9254f1649efee5b60203136ef19686177b04672e
parent9267e9fbd2ad1a05986f7ce16d4fef28cf7f08fb (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>
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx5
-rw-r--r--vcl/unx/gtk3/gtkframe.cxx129
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()