[vte] widget: Add wrapper class for key events
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] widget: Add wrapper class for key events
- Date: Fri, 1 May 2020 21:10:29 +0000 (UTC)
commit 19ea46dadd7898389753241ea2d1b5429bc4bd7d
Author: Christian Persch <chpe src gnome org>
Date: Fri May 1 23:08:42 2020 +0200
widget: Add wrapper class for key events
Extract all information from the GdkEventKey, put them into a wrapper class,
and pass that down to Terminal, instead of the native event.
src/fwd.hh | 6 +++++
src/vte.cc | 52 +++++++++++++++++++---------------------
src/vteinternal.hh | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++---
src/widget.cc | 40 +++++++++++++++++++++++++++++--
src/widget.hh | 9 ++++---
5 files changed, 142 insertions(+), 35 deletions(-)
---
diff --git a/src/fwd.hh b/src/fwd.hh
index 11525a98..7cdfb741 100644
--- a/src/fwd.hh
+++ b/src/fwd.hh
@@ -25,4 +25,10 @@ class Pty;
} // namespace base
+namespace platform {
+
+class Widget;
+
+} // namespace platform
+
} // namespace vte
diff --git a/src/vte.cc b/src/vte.cc
index a7425afc..885288af 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -4494,36 +4494,33 @@ Terminal::beep()
m_real_widget->beep();
}
-guint
-Terminal::translate_ctrlkey(GdkEventKey *event)
+unsigned
+Terminal::translate_ctrlkey(vte::terminal::KeyEvent const& event) const noexcept
{
- guint keyval;
- GdkKeymap *keymap;
- unsigned int i;
+ if (event.keyval() < 128)
+ return event.keyval();
- if (event->keyval < 128)
- return event->keyval;
-
- keymap = gdk_keymap_get_for_display(gdk_window_get_display (event->window));
+ auto display = gdk_window_get_display(gdk_event_get_window((GdkEvent*)event.platform_event()));
+ auto keymap = gdk_keymap_get_for_display(display);
+ auto keyval = unsigned{event.keyval()};
/* Try groups in order to find one mapping the key to ASCII */
- for (i = 0; i < 4; i++) {
- GdkModifierType consumed_modifiers;
-
+ for (auto i = unsigned{0}; i < 4; i++) {
+ auto consumed_modifiers = GdkModifierType{};
gdk_keymap_translate_keyboard_state (keymap,
- event->hardware_keycode,
- (GdkModifierType)event->state,
+ event.keycode(),
+ GdkModifierType(event.modifiers()),
i,
&keyval, NULL, NULL, &consumed_modifiers);
if (keyval < 128) {
_vte_debug_print (VTE_DEBUG_EVENTS,
- "ctrl+Key, group=%d de-grouped into keyval=0x%x\n",
- event->group, keyval);
- return keyval;
+ "ctrl+Key, group=%d de-grouped into keyval=0x%x\n",
+ event.group(), keyval);
+ break;
}
}
- return event->keyval;
+ return keyval;
}
void
@@ -4552,7 +4549,7 @@ Terminal::read_modifiers(GdkEvent *event)
}
bool
-Terminal::widget_key_press(GdkEventKey *event)
+Terminal::widget_key_press(vte::terminal::KeyEvent const& event)
{
char *normal = NULL;
gsize normal_length = 0;
@@ -4565,10 +4562,11 @@ Terminal::widget_key_press(GdkEventKey *event)
/* If it's a keypress, record that we got the event, in case the
* input method takes the event from us. */
- if (event->type == GDK_KEY_PRESS) {
+ // FIXMEchpe this is ::widget_key_press; what other event type could it even be!?
+ if (event.is_key_press()) {
/* Store a copy of the key. */
- keyval = event->keyval;
- read_modifiers((GdkEvent*)event);
+ keyval = event.keyval();
+ m_modifiers = event.modifiers();
// FIXMEchpe?
if (m_cursor_blink_timer) {
@@ -4588,7 +4586,7 @@ Terminal::widget_key_press(GdkEventKey *event)
"Keypress, modifiers=0x%x, "
"keyval=0x%x, raw string=`%s'.\n",
m_modifiers,
- keyval, event->string);
+ keyval, ((GdkEventKey*)event.platform_event())->string);
/* We steal many keypad keys here. */
if (!m_im_preedit_active) {
@@ -4687,10 +4685,10 @@ Terminal::widget_key_press(GdkEventKey *event)
}
/* Now figure out what to send to the child. */
- if ((event->type == GDK_KEY_PRESS) && !modifier) {
+ if (event.is_key_press() && !modifier) {
handled = FALSE;
/* Map the key to a sequence name if we can. */
- switch (keyval) {
+ switch (event.keyval()) {
case GDK_KEY_BackSpace:
switch (m_backspace_binding) {
case EraseMode::eASCII_BACKSPACE:
@@ -5014,9 +5012,9 @@ Terminal::widget_key_press(GdkEventKey *event)
}
bool
-Terminal::widget_key_release(GdkEventKey *event)
+Terminal::widget_key_release(vte::terminal::KeyEvent const& event)
{
- read_modifiers((GdkEvent*)event);
+ m_modifiers = event.modifiers();
if (m_input_enabled &&
m_real_widget->im_filter_keypress(event))
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index b37272ad..e238fb32 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -267,6 +267,70 @@ class Widget;
namespace terminal {
+class KeyEvent {
+ friend class vte::platform::Widget;
+ friend class Terminal;
+
+protected:
+
+ enum class Type {
+ ePRESS,
+ eRELEASE,
+ };
+
+ KeyEvent() noexcept = default;
+
+ constexpr KeyEvent(Type type,
+ unsigned int modifiers,
+ unsigned int keyval,
+ unsigned int keycode,
+ uint8_t group,
+ unsigned int timestamp,
+ bool is_modifier,
+ GdkEventKey* gdk_event) noexcept
+ : m_type{type},
+ m_modifiers{modifiers},
+ m_keyval{keyval},
+ m_keycode{keycode},
+ m_group{group},
+ m_timestamp{timestamp},
+ m_is_modifier{is_modifier},
+ m_platform_event{gdk_event}
+ {
+ }
+
+ constexpr auto platform_event() const noexcept { return m_platform_event; }
+
+public:
+ ~KeyEvent() noexcept = default;
+
+ KeyEvent(KeyEvent const&) = delete;
+ KeyEvent(KeyEvent&&) = delete;
+ KeyEvent& operator=(KeyEvent const&) = delete;
+ KeyEvent& operator=(KeyEvent&&) = delete;
+
+ constexpr auto const group() const noexcept { return m_group; }
+ constexpr auto const is_modifier() const noexcept { return m_is_modifier; }
+ constexpr auto const keycode() const noexcept { return m_keycode; }
+ constexpr auto const keyval() const noexcept { return m_keyval; }
+ constexpr auto const modifiers() const noexcept { return m_modifiers; }
+ constexpr auto const timestamp() const noexcept { return m_timestamp; }
+ constexpr auto const type() const noexcept { return m_type; }
+
+ constexpr auto const is_key_press() const noexcept { return type() == Type::ePRESS; }
+ constexpr auto const is_key_release() const noexcept { return type() == Type::eRELEASE; }
+
+private:
+ Type m_type;
+ unsigned m_modifiers;
+ unsigned m_keyval;
+ unsigned m_keycode;
+ uint8_t m_group;
+ unsigned m_timestamp;
+ bool m_is_modifier;
+ GdkEventKey* m_platform_event;
+}; // class KeyEvent
+
class Terminal {
friend class vte::platform::Widget;
@@ -920,8 +984,8 @@ public:
void widget_style_updated();
void widget_focus_in(GdkEventFocus *event);
void widget_focus_out(GdkEventFocus *event);
- bool widget_key_press(GdkEventKey *event);
- bool widget_key_release(GdkEventKey *event);
+ bool widget_key_press(vte::terminal::KeyEvent const& event);
+ bool widget_key_release(vte::terminal::KeyEvent const& event);
bool widget_button_press(GdkEventButton *event);
bool widget_button_release(GdkEventButton *event);
void widget_enter(GdkEventCrossing *event);
@@ -1110,7 +1174,7 @@ public:
void vadjustment_value_changed();
void read_modifiers(GdkEvent *event);
- guint translate_ctrlkey(GdkEventKey *event);
+ unsigned translate_ctrlkey(vte::terminal::KeyEvent const& event) const noexcept;
void apply_mouse_cursor();
void set_pointer_autohidden(bool autohidden);
diff --git a/src/widget.cc b/src/widget.cc
index a8bd6c36..0a67a7bd 100644
--- a/src/widget.cc
+++ b/src/widget.cc
@@ -201,11 +201,11 @@ Widget::emit_eof() noexcept
}
bool
-Widget::im_filter_keypress(GdkEventKey* event) noexcept
+Widget::im_filter_keypress(vte::terminal::KeyEvent const& event) noexcept
{
// FIXMEchpe this can only be called when realized, so the m_im_context check is redundant
return m_im_context &&
- gtk_im_context_filter_keypress(m_im_context.get(), event);
+ gtk_im_context_filter_keypress(m_im_context.get(), event.platform_event());
}
void
@@ -245,6 +245,42 @@ Widget::im_set_cursor_location(cairo_rectangle_int_t const* rect) noexcept
gtk_im_context_set_cursor_location(m_im_context.get(), rect);
}
+unsigned
+Widget::read_modifiers_from_gdk(GdkEvent* event) const noexcept
+{
+ /* Read the modifiers. See bug #663779 for more information on why we do this. */
+ auto mods = GdkModifierType{};
+ if (!gdk_event_get_state(event, &mods))
+ return 0;
+
+ /* Map non-virtual modifiers to virtual modifiers (Super, Hyper, Meta) */
+ auto display = gdk_window_get_display(gdk_event_get_window(event));
+ auto keymap = gdk_keymap_get_for_display(display);
+ gdk_keymap_add_virtual_modifiers(keymap, &mods);
+
+ return unsigned(mods);
+}
+
+vte::terminal::KeyEvent
+Widget::key_event_from_gdk(GdkEventKey* event) const
+{
+ auto type = vte::terminal::KeyEvent::Type{};
+ switch (gdk_event_get_event_type(reinterpret_cast<GdkEvent*>(event))) {
+ case GDK_KEY_PRESS: type = vte::terminal::KeyEvent::Type::ePRESS; break;
+ case GDK_KEY_RELEASE: type = vte::terminal::KeyEvent::Type::eRELEASE; break;
+ default: g_assert_not_reached(); return {};
+ }
+
+ return {type,
+ read_modifiers_from_gdk(reinterpret_cast<GdkEvent*>(event)),
+ event->keyval,
+ event->hardware_keycode, // gdk_event_get_scancode(event),
+ event->group,
+ event->time,
+ event->is_modifier != 0,
+ event};
+}
+
void
Widget::map() noexcept
{
diff --git a/src/widget.hh b/src/widget.hh
index d904fe33..721b13cc 100644
--- a/src/widget.hh
+++ b/src/widget.hh
@@ -74,8 +74,8 @@ public:
void focus_in(GdkEventFocus *event) noexcept { m_terminal->widget_focus_in(event); }
void focus_out(GdkEventFocus *event) noexcept { m_terminal->widget_focus_out(event); }
- bool key_press(GdkEventKey *event) noexcept { return m_terminal->widget_key_press(event); }
- bool key_release(GdkEventKey *event) noexcept { return m_terminal->widget_key_release(event); }
+ bool key_press(GdkEventKey *event) noexcept { return
m_terminal->widget_key_press(key_event_from_gdk(event)); }
+ bool key_release(GdkEventKey *event) noexcept { return
m_terminal->widget_key_release(key_event_from_gdk(event)); }
bool button_press(GdkEventButton *event) noexcept { return m_terminal->widget_button_press(event); }
bool button_release(GdkEventButton *event) noexcept { return
m_terminal->widget_button_release(event); }
void enter(GdkEventCrossing *event) noexcept { m_terminal->widget_enter(event); }
@@ -160,7 +160,7 @@ protected:
void set_cursor(GdkCursor* cursor) noexcept;
void set_cursor(Cursor const& cursor) noexcept;
- bool im_filter_keypress(GdkEventKey* event) noexcept;
+ bool im_filter_keypress(vte::terminal::KeyEvent const& event) noexcept;
void im_focus_in() noexcept;
void im_focus_out() noexcept;
@@ -179,6 +179,9 @@ public: // FIXMEchpe
void im_preedit_changed() noexcept;
private:
+ unsigned read_modifiers_from_gdk(GdkEvent* event) const noexcept;
+ vte::terminal::KeyEvent key_event_from_gdk(GdkEventKey* event) const;
+
GtkWidget* m_widget;
vte::terminal::Terminal* m_terminal;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]