[vte] widget: Add wrapper class for mouse events
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] widget: Add wrapper class for mouse events
- Date: Fri, 1 May 2020 21:10:44 +0000 (UTC)
commit 477c45bcbec34841dda0ee63b58aebe37c356b93
Author: Christian Persch <chpe src gnome org>
Date: Fri May 1 23:08:42 2020 +0200
widget: Add wrapper class for mouse events
Extract all information from the GdkEvent{Button,Crossing,Scroll},
put them into a wrapper class, and pass that down to Terminal,
instead of the native event.
src/vte.cc | 269 ++++++++++++++++++++++-------------------------------
src/vtegtk.cc | 16 ++--
src/vteinternal.hh | 232 ++++++++++++++++++++++++++++++++++++---------
src/widget.cc | 56 +++++++++--
src/widget.hh | 49 ++++++++--
5 files changed, 396 insertions(+), 226 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index 740ad3ab..84b5044e 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1437,7 +1437,7 @@ Terminal::regex_match_check(vte::grid::column_t column,
/*
* Terminal::view_coords_from_event:
- * @event: a #GdkEvent
+ * @event: a mouse event
*
* Translates the event coordinates to view coordinates, by
* subtracting the padding and window offset.
@@ -1446,15 +1446,9 @@ Terminal::regex_match_check(vte::grid::column_t column,
* at that side; use view_coords_visible() to check for that.
*/
vte::view::coords
-Terminal::view_coords_from_event(GdkEvent const* event) const
+Terminal::view_coords_from_event(MouseEvent const& event) const
{
- double x, y;
- if (event == nullptr ||
- ((reinterpret_cast<GdkEventAny const*>(event))->window != m_real_widget->event_window()) ||
- !gdk_event_get_coords(event, &x, &y))
- return vte::view::coords(-1, -1);
-
- return vte::view::coords(x - m_padding.left, y - m_padding.top);
+ return vte::view::coords(event.x() - m_padding.left, event.y() - m_padding.top);
}
bool
@@ -1465,7 +1459,7 @@ Terminal::widget_realized() const noexcept
/*
* Terminal::grid_coords_from_event:
- * @event: a #GdkEvent
+ * @event: a mouse event
*
* Translates the event coordinates to view coordinates, by
* subtracting the padding and window offset.
@@ -1474,20 +1468,20 @@ Terminal::widget_realized() const noexcept
* at that side; use grid_coords_visible() to check for that.
*/
vte::grid::coords
-Terminal::grid_coords_from_event(GdkEvent const* event) const
+Terminal::grid_coords_from_event(MouseEvent const& event) const
{
return grid_coords_from_view_coords(view_coords_from_event(event));
}
/*
* Terminal::confined_grid_coords_from_event:
- * @event: a #GdkEvent
+ * @event: a mouse event
*
* Like grid_coords_from_event(), but also confines the coordinates
* to an actual cell in the visible area.
*/
vte::grid::coords
-Terminal::confined_grid_coords_from_event(GdkEvent const* event) const
+Terminal::confined_grid_coords_from_event(MouseEvent const& event) const
{
auto pos = view_coords_from_event(event);
return confined_grid_coords_from_view_coords(pos);
@@ -1688,9 +1682,9 @@ Terminal::selection_maybe_swap_endpoints(vte::view::coords const& pos)
}
bool
-Terminal::rowcol_from_event(GdkEvent *event,
- long *column,
- long *row)
+Terminal::rowcol_from_event(MouseEvent const& event,
+ long *column,
+ long *row)
{
auto rowcol = grid_coords_from_event(event);
if (!grid_coords_visible(rowcol))
@@ -1702,7 +1696,7 @@ Terminal::rowcol_from_event(GdkEvent *event,
}
char *
-Terminal::hyperlink_check(GdkEvent *event)
+Terminal::hyperlink_check(MouseEvent const& event)
{
long col, row;
const char *hyperlink;
@@ -1734,7 +1728,7 @@ Terminal::hyperlink_check(GdkEvent *event)
}
char *
-Terminal::regex_match_check(GdkEvent* event,
+Terminal::regex_match_check(MouseEvent const& event,
int *tag)
{
long col, row;
@@ -1751,7 +1745,7 @@ Terminal::regex_match_check(GdkEvent* event,
}
bool
-Terminal::regex_match_check_extra(GdkEvent *event,
+Terminal::regex_match_check_extra(MouseEvent const& event,
vte::base::Regex const** regexes,
size_t n_regexes,
uint32_t match_flags,
@@ -1764,7 +1758,6 @@ Terminal::regex_match_check_extra(GdkEvent *event,
long col, row;
guint i;
- assert(event);
assert(regexes != nullptr || n_regexes == 0);
assert(matches != nullptr);
@@ -4495,12 +4488,12 @@ Terminal::beep()
}
unsigned
-Terminal::translate_ctrlkey(vte::terminal::KeyEvent const& event) const noexcept
+Terminal::translate_ctrlkey(KeyEvent const& event) const noexcept
{
if (event.keyval() < 128)
return event.keyval();
- auto display = gdk_window_get_display(gdk_event_get_window((GdkEvent*)event.platform_event()));
+ auto display = gdk_window_get_display(gdk_event_get_window(event.platform_event()));
auto keymap = gdk_keymap_get_for_display(display);
auto keyval = unsigned{event.keyval()};
@@ -4523,33 +4516,8 @@ Terminal::translate_ctrlkey(vte::terminal::KeyEvent const& event) const noexcept
return keyval;
}
-void
-Terminal::read_modifiers(GdkEvent *event)
-{
- GdkKeymap *keymap;
- GdkModifierType mods;
- guint mask;
-
- /* Read the modifiers. */
- if (!gdk_event_get_state((GdkEvent*)event, &mods))
- return;
-
- keymap = gdk_keymap_get_for_display(gdk_window_get_display(((GdkEventAny*)event)->window));
-
- gdk_keymap_add_virtual_modifiers (keymap, &mods);
-
- mask = (guint)mods;
-#if 1
- /* HACK! Treat ALT as ALT; see bug #663779. */
- if (mask & GDK_MOD1_MASK)
- mask |= VTE_ALT_MASK;
-#endif
-
- m_modifiers = mask;
-}
-
bool
-Terminal::widget_key_press(vte::terminal::KeyEvent const& event)
+Terminal::widget_key_press(KeyEvent const& event)
{
char *normal = NULL;
gsize normal_length = 0;
@@ -5012,7 +4980,7 @@ Terminal::widget_key_press(vte::terminal::KeyEvent const& event)
}
bool
-Terminal::widget_key_release(vte::terminal::KeyEvent const& event)
+Terminal::widget_key_release(KeyEvent const& event)
{
m_modifiers = event.modifiers();
@@ -5673,31 +5641,30 @@ Terminal::maybe_feed_focus_event(bool in)
*/
bool
Terminal::maybe_send_mouse_button(vte::grid::coords const& unconfined_rowcol,
- GdkEventType event_type,
- int event_button)
+ MouseEvent const& event)
{
- switch (event_type) {
- case GDK_BUTTON_PRESS:
+ switch (event.type()) {
+ case EventBase::Type::eMOUSE_PRESS:
if (m_mouse_tracking_mode < MouseTrackingMode::eSEND_XY_ON_CLICK) {
return false;
}
break;
- case GDK_BUTTON_RELEASE: {
+ case EventBase::Type::eMOUSE_RELEASE:
if (m_mouse_tracking_mode < MouseTrackingMode::eSEND_XY_ON_BUTTON) {
return false;
}
break;
- }
+ case EventBase::Type::eMOUSE_DOUBLE_PRESS:
+ case EventBase::Type::eMOUSE_TRIPLE_PRESS:
default:
return false;
- break;
}
auto rowcol = confine_grid_coords(unconfined_rowcol);
return feed_mouse_event(rowcol,
- event_button,
+ event.button_value(),
false /* not drag */,
- event_type == GDK_BUTTON_RELEASE);
+ event.is_mouse_release());
}
/*
@@ -5712,7 +5679,7 @@ Terminal::maybe_send_mouse_button(vte::grid::coords const& unconfined_rowcol,
*/
bool
Terminal::maybe_send_mouse_drag(vte::grid::coords const& unconfined_rowcol,
- GdkEventType event_type)
+ MouseEvent const& event)
{
/* Need to ensure the ringview is updated. */
ringview_update();
@@ -5720,8 +5687,8 @@ Terminal::maybe_send_mouse_drag(vte::grid::coords const& unconfined_rowcol,
auto rowcol = confine_grid_coords(unconfined_rowcol);
/* First determine if we even want to send notification. */
- switch (event_type) {
- case GDK_MOTION_NOTIFY:
+ switch (event.type()) {
+ case EventBase::Type::eMOUSE_MOTION:
if (m_mouse_tracking_mode < MouseTrackingMode::eCELL_MOTION_TRACKING)
return false;
@@ -5740,7 +5707,6 @@ Terminal::maybe_send_mouse_drag(vte::grid::coords const& unconfined_rowcol,
break;
default:
return false;
- break;
}
/* As per xterm, report the leftmost pressed button - if any. */
@@ -6856,58 +6822,50 @@ Terminal::start_autoscroll()
}
bool
-Terminal::widget_motion_notify(GdkEventMotion *event)
+Terminal::widget_mouse_motion(MouseEvent const& event)
{
- bool handled = false;
-
/* Need to ensure the ringview is updated. */
ringview_update();
- GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event);
- auto pos = view_coords_from_event(base_event);
+ auto pos = view_coords_from_event(event);
auto rowcol = grid_coords_from_view_coords(pos);
_vte_debug_print(VTE_DEBUG_EVENTS,
"Motion notify %s %s\n",
pos.to_string(), rowcol.to_string());
- read_modifiers(base_event);
+ m_modifiers = event.modifiers();
- switch (event->type) {
- case GDK_MOTION_NOTIFY:
- if (m_will_select_after_threshold) {
- if (!gtk_drag_check_threshold (m_widget,
- m_mouse_last_position.x,
- m_mouse_last_position.y,
- pos.x, pos.y))
- return true;
+ if (m_will_select_after_threshold) {
+ if (!gtk_drag_check_threshold(m_widget,
+ m_mouse_last_position.x,
+ m_mouse_last_position.y,
+ pos.x, pos.y))
+ return true;
- start_selection(vte::view::coords(m_mouse_last_position.x, m_mouse_last_position.y),
- SelectionType::eCHAR);
- }
+ start_selection(vte::view::coords(m_mouse_last_position.x, m_mouse_last_position.y),
+ SelectionType::eCHAR);
+ }
- if (m_selecting &&
- (m_mouse_handled_buttons & 1) != 0) {
- _vte_debug_print(VTE_DEBUG_EVENTS, "Mousing drag 1.\n");
- modify_selection(pos);
-
- /* Start scrolling if we need to. */
- if (pos.y < 0 || pos.y >= m_view_usable_extents.height()) {
- /* Give mouse wigglers something. */
- stop_autoscroll();
- mouse_autoscroll_timer_callback();
- start_autoscroll();
- }
+ auto handled = bool{false};
+ if (m_selecting &&
+ (m_mouse_handled_buttons & 1) != 0) {
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Mousing drag 1.\n");
+ modify_selection(pos);
+
+ /* Start scrolling if we need to. */
+ if (pos.y < 0 || pos.y >= m_view_usable_extents.height()) {
+ /* Give mouse wigglers something. */
+ stop_autoscroll();
+ mouse_autoscroll_timer_callback();
+ start_autoscroll();
+ }
- handled = true;
- }
+ handled = true;
+ }
- if (!handled && m_input_enabled)
- maybe_send_mouse_drag(rowcol, event->type);
- break;
- default:
- break;
- }
+ if (!handled && m_input_enabled)
+ maybe_send_mouse_drag(rowcol, event);
if (pos != m_mouse_last_position) {
m_mouse_last_position = pos;
@@ -6921,7 +6879,7 @@ Terminal::widget_motion_notify(GdkEventMotion *event)
}
bool
-Terminal::widget_button_press(GdkEventButton *event)
+Terminal::widget_mouse_press(MouseEvent const& event)
{
bool handled = false;
gboolean start_selecting = FALSE, extend_selecting = FALSE;
@@ -6929,21 +6887,20 @@ Terminal::widget_button_press(GdkEventButton *event)
/* Need to ensure the ringview is updated. */
ringview_update();
- GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event);
- auto pos = view_coords_from_event(base_event);
+ auto pos = view_coords_from_event(event);
auto rowcol = grid_coords_from_view_coords(pos);
- read_modifiers(base_event);
+ m_modifiers = event.modifiers();
- switch (event->type) {
- case GDK_BUTTON_PRESS:
+ switch (event.type()) {
+ case EventBase::Type::eMOUSE_PRESS:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d single-click at %s\n",
- event->button,
+ event.button_value(),
rowcol.to_string());
/* Handle this event ourselves. */
- switch (event->button) {
- case 1:
+ switch (event.button()) {
+ case MouseEvent::Button::eLEFT:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Handling click ourselves.\n");
/* Grab focus. */
@@ -6985,7 +6942,7 @@ Terminal::widget_button_press(GdkEventButton *event)
break;
/* Paste if the user pressed shift or we're not sending events
* to the app. */
- case 2:
+ case MouseEvent::Button::eMIDDLE:
if ((m_modifiers & GDK_SHIFT_MASK) ||
m_mouse_tracking_mode == MouseTrackingMode::eNONE) {
gboolean do_paste;
@@ -6998,29 +6955,29 @@ Terminal::widget_button_press(GdkEventButton *event)
handled = do_paste;
}
break;
- case 3:
+ case MouseEvent::Button::eRIGHT:
default:
break;
}
- if (event->button >= 1 && event->button <= 3) {
+ if (event.button_value() >= 1 && event.button_value() <= 3) {
if (handled)
- m_mouse_handled_buttons |= (1 << (event->button - 1));
+ m_mouse_handled_buttons |= (1 << (event.button_value() - 1));
else
- m_mouse_handled_buttons &= ~(1 << (event->button - 1));
+ m_mouse_handled_buttons &= ~(1 << (event.button_value() - 1));
}
/* If we haven't done anything yet, try sending the mouse
* event to the app. */
if (handled == FALSE) {
- handled = maybe_send_mouse_button(rowcol, event->type, event->button);
+ handled = maybe_send_mouse_button(rowcol, event);
}
break;
- case GDK_2BUTTON_PRESS:
+ case EventBase::Type::eMOUSE_DOUBLE_PRESS:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d double-click at %s\n",
- event->button,
+ event.button_value(),
rowcol.to_string());
- switch (event->button) {
- case 1:
+ switch (event.button()) {
+ case MouseEvent::Button::eLEFT:
if (m_will_select_after_threshold) {
start_selection(pos,
SelectionType::eCHAR);
@@ -7032,27 +6989,27 @@ Terminal::widget_button_press(GdkEventButton *event)
handled = true;
}
break;
- case 2:
- case 3:
+ case MouseEvent::Button::eMIDDLE:
+ case MouseEvent::Button::eRIGHT:
default:
break;
}
break;
- case GDK_3BUTTON_PRESS:
+ case EventBase::Type::eMOUSE_TRIPLE_PRESS:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d triple-click at %s\n",
- event->button,
+ event.button_value(),
rowcol.to_string());
- switch (event->button) {
- case 1:
+ switch (event.button()) {
+ case MouseEvent::Button::eLEFT:
if ((m_mouse_handled_buttons & 1) != 0) {
start_selection(pos,
SelectionType::eLINE);
handled = true;
}
break;
- case 2:
- case 3:
+ case MouseEvent::Button::eMIDDLE:
+ case MouseEvent::Button::eRIGHT:
default:
break;
}
@@ -7061,8 +7018,8 @@ Terminal::widget_button_press(GdkEventButton *event)
}
/* Save the pointer state for later use. */
- if (event->button >= 1 && event->button <= 3)
- m_mouse_pressed_buttons |= (1 << (event->button - 1));
+ if (event.button_value() >= 1 && event.button_value() <= 3)
+ m_mouse_pressed_buttons |= (1 << (event.button_value() - 1));
m_mouse_last_position = pos;
@@ -7074,41 +7031,40 @@ Terminal::widget_button_press(GdkEventButton *event)
}
bool
-Terminal::widget_button_release(GdkEventButton *event)
+Terminal::widget_mouse_release(MouseEvent const& event)
{
bool handled = false;
/* Need to ensure the ringview is updated. */
ringview_update();
- GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event);
- auto pos = view_coords_from_event(base_event);
+ auto pos = view_coords_from_event(event);
auto rowcol = grid_coords_from_view_coords(pos);
stop_autoscroll();
- read_modifiers(base_event);
+ m_modifiers = event.modifiers();
- switch (event->type) {
- case GDK_BUTTON_RELEASE:
+ switch (event.type()) {
+ case EventBase::Type::eMOUSE_RELEASE:
_vte_debug_print(VTE_DEBUG_EVENTS,
"Button %d released at %s\n",
- event->button, rowcol.to_string());
- switch (event->button) {
- case 1:
+ event.button_value(), rowcol.to_string());
+ switch (event.button()) {
+ case MouseEvent::Button::eLEFT:
if ((m_mouse_handled_buttons & 1) != 0)
handled = maybe_end_selection();
break;
- case 2:
+ case MouseEvent::Button::eMIDDLE:
handled = (m_mouse_handled_buttons & 2) != 0;
m_mouse_handled_buttons &= ~2;
break;
- case 3:
+ case MouseEvent::Button::eRIGHT:
default:
break;
}
if (!handled && m_input_enabled) {
- handled = maybe_send_mouse_button(rowcol, event->type, event->button);
+ handled = maybe_send_mouse_button(rowcol, event);
}
break;
default:
@@ -7116,8 +7072,8 @@ Terminal::widget_button_release(GdkEventButton *event)
}
/* Save the pointer state for later use. */
- if (event->button >= 1 && event->button <= 3)
- m_mouse_pressed_buttons &= ~(1 << (event->button - 1));
+ if (event.button_value() >= 1 && event.button_value() <= 3)
+ m_mouse_pressed_buttons &= ~(1 << (event.button_value() - 1));
m_mouse_last_position = pos;
m_will_select_after_threshold = false;
@@ -7190,10 +7146,9 @@ Terminal::widget_focus_out(GdkEventFocus *event)
}
void
-Terminal::widget_enter(GdkEventCrossing *event)
+Terminal::widget_mouse_enter(MouseEvent const& event)
{
- GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event);
- auto pos = view_coords_from_event(base_event);
+ auto pos = view_coords_from_event(event);
// FIXMEchpe read event modifiers here
@@ -7209,10 +7164,9 @@ Terminal::widget_enter(GdkEventCrossing *event)
}
void
-Terminal::widget_leave(GdkEventCrossing *event)
+Terminal::widget_mouse_leave(MouseEvent const& event)
{
- GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event);
- auto pos = view_coords_from_event(base_event);
+ auto pos = view_coords_from_event(event);
// FIXMEchpe read event modifiers here
@@ -9432,9 +9386,8 @@ vte_cairo_get_clip_region (cairo_t *cr)
}
void
-Terminal::widget_scroll(GdkEventScroll *event)
+Terminal::widget_mouse_scroll(MouseEvent const& event)
{
- gdouble delta_x, delta_y;
gdouble v;
gint cnt, i;
int button;
@@ -9442,27 +9395,27 @@ Terminal::widget_scroll(GdkEventScroll *event)
/* Need to ensure the ringview is updated. */
ringview_update();
- GdkEvent *base_event = reinterpret_cast<GdkEvent*>(event);
- auto rowcol = confined_grid_coords_from_event(base_event);
+ auto rowcol = confined_grid_coords_from_event(event);
- read_modifiers(base_event);
+ m_modifiers = event.modifiers();
- switch (event->direction) {
- case GDK_SCROLL_UP:
+ switch (event.scroll_direction()) {
+ case MouseEvent::ScrollDirection::eUP:
m_mouse_smooth_scroll_delta -= 1.;
_vte_debug_print(VTE_DEBUG_EVENTS, "Scroll up\n");
break;
- case GDK_SCROLL_DOWN:
+ case MouseEvent::ScrollDirection::eDOWN:
m_mouse_smooth_scroll_delta += 1.;
_vte_debug_print(VTE_DEBUG_EVENTS, "Scroll down\n");
break;
- case GDK_SCROLL_SMOOTH:
- gdk_event_get_scroll_deltas ((GdkEvent*) event, &delta_x, &delta_y);
+ case MouseEvent::ScrollDirection::eSMOOTH: {
+ auto const delta_y = event.scroll_delta_y();
m_mouse_smooth_scroll_delta += delta_y;
_vte_debug_print(VTE_DEBUG_EVENTS,
"Smooth scroll by %f, delta now at %f\n",
delta_y, m_mouse_smooth_scroll_delta);
break;
+ }
default:
break;
}
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index e9b568d6..a7b0390a 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -2207,7 +2207,7 @@ vte_terminal_match_check(VteTerminal *terminal,
int *tag)
{
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
- return IMPL(terminal)->regex_match_check(column, row, tag);
+ return WIDGET(terminal)->regex_match_check(column, row, tag);
}
@@ -2235,7 +2235,7 @@ vte_terminal_match_check_event(VteTerminal *terminal,
int *tag)
{
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
- return IMPL(terminal)->regex_match_check(event, tag);
+ return WIDGET(terminal)->regex_match_check(event, tag);
}
/**
@@ -2260,7 +2260,7 @@ vte_terminal_hyperlink_check_event(VteTerminal *terminal,
GdkEvent *event)
{
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
- return IMPL(terminal)->hyperlink_check(event);
+ return WIDGET(terminal)->hyperlink_check(event);
}
/**
@@ -2348,11 +2348,11 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
}
g_return_val_if_fail(matches != NULL, FALSE);
- return IMPL(terminal)->regex_match_check_extra(event,
- regex_array_from_wrappers(regexes),
- n_regexes,
- match_flags,
- matches);
+ return WIDGET(terminal)->regex_match_check_extra(event,
+ regex_array_from_wrappers(regexes),
+ n_regexes,
+ match_flags,
+ matches);
}
/**
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index e238fb32..91a2b7c5 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -267,40 +267,83 @@ class Widget;
namespace terminal {
-class KeyEvent {
+class EventBase {
friend class vte::platform::Widget;
friend class Terminal;
-protected:
-
+public:
enum class Type {
- ePRESS,
- eRELEASE,
+ eKEY_PRESS,
+ eKEY_RELEASE,
+ eMOUSE_DOUBLE_PRESS,
+ eMOUSE_ENTER,
+ eMOUSE_LEAVE,
+ eMOUSE_MOTION,
+ eMOUSE_PRESS,
+ eMOUSE_RELEASE,
+ eMOUSE_SCROLL,
+ eMOUSE_TRIPLE_PRESS,
};
+protected:
+
+ EventBase() noexcept = default;
+
+ constexpr EventBase(GdkEvent* gdk_event,
+ Type type,
+ unsigned timestamp) noexcept
+ : m_platform_event{gdk_event},
+ m_type{type},
+ m_timestamp{timestamp}
+ {
+ }
+
+ constexpr auto platform_event() const noexcept { return m_platform_event; }
+
+public:
+ ~EventBase() noexcept = default;
+
+ EventBase(EventBase const&) = default;
+ EventBase(EventBase&&) = default;
+ EventBase& operator=(EventBase const&) = delete;
+ EventBase& operator=(EventBase&&) = delete;
+
+ constexpr auto const timestamp() const noexcept { return m_timestamp; }
+ constexpr auto const type() const noexcept { return m_type; }
+
+private:
+ GdkEvent* m_platform_event;
+ Type m_type;
+ unsigned m_timestamp;
+}; // class EventBase
+
+class KeyEvent : public EventBase {
+ friend class vte::platform::Widget;
+ friend class Terminal;
+
+protected:
+
KeyEvent() noexcept = default;
- constexpr KeyEvent(Type type,
- unsigned int modifiers,
- unsigned int keyval,
- unsigned int keycode,
+ constexpr KeyEvent(GdkEvent* gdk_event,
+ Type type,
+ unsigned timestamp,
+ unsigned modifiers,
+ unsigned keyval,
+ unsigned keycode,
uint8_t group,
- unsigned int timestamp,
- bool is_modifier,
- GdkEventKey* gdk_event) noexcept
- : m_type{type},
+ bool is_modifier) noexcept
+ : EventBase{gdk_event,
+ type,
+ timestamp},
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}
+ m_is_modifier{is_modifier}
{
}
- constexpr auto platform_event() const noexcept { return m_platform_event; }
-
public:
~KeyEvent() noexcept = default;
@@ -314,23 +357,124 @@ public:
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; }
+ constexpr auto const is_key_press() const noexcept { return type() == Type::eKEY_PRESS; }
+ constexpr auto const is_key_release() const noexcept { return type() == Type::eKEY_RELEASE; }
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 MouseEvent : public EventBase {
+ friend class vte::platform::Widget;
+ friend class Terminal;
+
+public:
+ enum class Button {
+ eNONE = 0,
+ eLEFT = 1,
+ eMIDDLE = 2,
+ eRIGHT = 3,
+ eFOURTH = 4,
+ eFIFTH = 5,
+ };
+
+ enum class ScrollDirection {
+ eUP,
+ eDOWN,
+ eLEFT,
+ eRIGHT,
+ eSMOOTH,
+ eNONE,
+ };
+
+protected:
+
+ MouseEvent() noexcept = default;
+
+ constexpr MouseEvent(GdkEvent* gdk_event,
+ Type type,
+ unsigned timestamp,
+ unsigned modifiers,
+ Button button,
+ double x,
+ double y) noexcept
+ : EventBase{gdk_event,
+ type,
+ timestamp},
+ m_modifiers{modifiers},
+ m_button{button},
+ m_x{x},
+ m_y{y}
+ {
+ }
+
+public:
+ ~MouseEvent() noexcept = default;
+
+ MouseEvent(MouseEvent const&) = default;
+ MouseEvent(MouseEvent&&) = default;
+ MouseEvent& operator=(MouseEvent const&) = delete;
+ MouseEvent& operator=(MouseEvent&&) = delete;
+
+ constexpr auto const button() const noexcept { return m_button; }
+ constexpr auto const button_value() const noexcept { return unsigned(m_button); }
+ constexpr auto const modifiers() const noexcept { return m_modifiers; }
+ constexpr auto const x() const noexcept { return m_x; }
+ constexpr auto const y() const noexcept { return m_y; }
+
+ constexpr auto const is_mouse_double_press() const noexcept { return type() ==
Type::eMOUSE_DOUBLE_PRESS; }
+ constexpr auto const is_mouse_enter() const noexcept { return type() == Type::eMOUSE_ENTER;
}
+ constexpr auto const is_mouse_leave() const noexcept { return type() == Type::eMOUSE_LEAVE;
}
+ constexpr auto const is_mouse_motion() const noexcept { return type() == Type::eMOUSE_MOTION;
}
+ constexpr auto const is_mouse_press() const noexcept { return type() == Type::eMOUSE_PRESS;
}
+ constexpr auto const is_mouse_release() const noexcept { return type() == Type::eMOUSE_RELEASE;
}
+ constexpr auto const is_mouse_scroll() const noexcept { return type() == Type::eMOUSE_SCROLL;
}
+ constexpr auto const is_mouse_single_press() const noexcept { return type() == Type::eMOUSE_PRESS;
}
+ constexpr auto const is_mouse_triple_press() const noexcept { return type() ==
Type::eMOUSE_TRIPLE_PRESS; }
+
+ ScrollDirection scroll_direction() const noexcept
+ {
+ /* Note that we cannot use gdk_event_get_scroll_direction() here since it
+ * returns false for smooth scroll events.
+ */
+ if (!is_mouse_scroll())
+ return ScrollDirection::eNONE;
+ switch (reinterpret_cast<GdkEventScroll*>(platform_event())->direction) {
+ case GDK_SCROLL_UP: return ScrollDirection::eUP;
+ case GDK_SCROLL_DOWN: return ScrollDirection::eDOWN;
+ case GDK_SCROLL_LEFT: return ScrollDirection::eLEFT;
+ case GDK_SCROLL_RIGHT: return ScrollDirection::eRIGHT;
+ case GDK_SCROLL_SMOOTH: return ScrollDirection::eSMOOTH;
+ default: return ScrollDirection::eNONE;
+ }
+ }
+
+ auto scroll_delta_x() const noexcept
+ {
+ auto delta = double{0.};
+ gdk_event_get_scroll_deltas(platform_event(), &delta, nullptr);
+ return delta;
+ }
+
+ auto scroll_delta_y() const noexcept
+ {
+ auto delta = double{0.};
+ gdk_event_get_scroll_deltas(platform_event(), nullptr, &delta);
+ return delta;
+ }
+
+private:
+ unsigned m_modifiers;
+ Button m_button;
+ double m_x;
+ double m_y;
+}; // class MouseEvent
+
class Terminal {
friend class vte::platform::Widget;
@@ -946,8 +1090,8 @@ public:
inline vte::view::coord_t get_allocated_width() const { return m_allocated_rect.width; }
inline vte::view::coord_t get_allocated_height() const { return m_allocated_rect.height; }
- vte::view::coords view_coords_from_event(GdkEvent const* event) const;
- vte::grid::coords grid_coords_from_event(GdkEvent const* event) const;
+ vte::view::coords view_coords_from_event(MouseEvent const& event) const;
+ vte::grid::coords grid_coords_from_event(MouseEvent const& event) const;
vte::view::coords view_coords_from_grid_coords(vte::grid::coords const& rowcol) const;
vte::grid::coords grid_coords_from_view_coords(vte::view::coords const& pos) const;
@@ -960,7 +1104,7 @@ public:
vte::grid::row_t confine_grid_row(vte::grid::row_t const& row) const;
vte::grid::coords confine_grid_coords(vte::grid::coords const& rowcol) const;
- vte::grid::coords confined_grid_coords_from_event(GdkEvent const* event) const;
+ vte::grid::coords confined_grid_coords_from_event(MouseEvent const&) const;
vte::grid::coords confined_grid_coords_from_view_coords(vte::view::coords const& pos) const;
void confine_coordinates(long *xp,
@@ -984,14 +1128,14 @@ public:
void widget_style_updated();
void widget_focus_in(GdkEventFocus *event);
void widget_focus_out(GdkEventFocus *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);
- void widget_leave(GdkEventCrossing *event);
- void widget_scroll(GdkEventScroll *event);
- bool widget_motion_notify(GdkEventMotion *event);
+ bool widget_key_press(KeyEvent const& event);
+ bool widget_key_release(KeyEvent const& event);
+ bool widget_mouse_motion(MouseEvent const& event);
+ bool widget_mouse_press(MouseEvent const& event);
+ bool widget_mouse_release(MouseEvent const& event);
+ void widget_mouse_enter(MouseEvent const& event);
+ void widget_mouse_leave(MouseEvent const& event);
+ void widget_mouse_scroll(MouseEvent const& event);
void widget_draw(cairo_t *cr);
void widget_get_preferred_width(int *minimum_width,
int *natural_width);
@@ -1173,8 +1317,7 @@ public:
void vadjustment_value_changed();
- void read_modifiers(GdkEvent *event);
- unsigned translate_ctrlkey(vte::terminal::KeyEvent const& event) const noexcept;
+ unsigned translate_ctrlkey(KeyEvent const& event) const noexcept;
void apply_mouse_cursor();
void set_pointer_autohidden(bool autohidden);
@@ -1228,13 +1371,13 @@ public:
void match_hilite_clear();
void match_hilite_update();
- bool rowcol_from_event(GdkEvent *event,
+ bool rowcol_from_event(MouseEvent const& event,
long *column,
long *row);
- char *hyperlink_check(GdkEvent *event);
+ char *hyperlink_check(MouseEvent const& event);
- bool regex_match_check_extra(GdkEvent* event,
+ bool regex_match_check_extra(MouseEvent const& event,
vte::base::Regex const** regexes,
size_t n_regexes,
uint32_t match_flags,
@@ -1243,7 +1386,7 @@ public:
char *regex_match_check(vte::grid::column_t column,
vte::grid::row_t row,
int *tag);
- char *regex_match_check(GdkEvent *event,
+ char *regex_match_check(MouseEvent const& event,
int *tag);
void regex_match_remove(int tag) noexcept;
void regex_match_remove_all() noexcept;
@@ -1289,10 +1432,9 @@ public:
bool is_drag,
bool is_release);
bool maybe_send_mouse_button(vte::grid::coords const& rowcol,
- GdkEventType event_type,
- int event_button);
+ MouseEvent const& event);
bool maybe_send_mouse_drag(vte::grid::coords const& rowcol,
- GdkEventType event_type);
+ MouseEvent const& event);
void feed_focus_event(bool in);
void feed_focus_event_initial();
diff --git a/src/widget.cc b/src/widget.cc
index 0a67a7bd..a23fe255 100644
--- a/src/widget.cc
+++ b/src/widget.cc
@@ -205,7 +205,8 @@ 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.platform_event());
+ gtk_im_context_filter_keypress(m_im_context.get(),
+ reinterpret_cast<GdkEventKey*>(event.platform_event()));
}
void
@@ -264,21 +265,58 @@ Widget::read_modifiers_from_gdk(GdkEvent* event) const noexcept
vte::terminal::KeyEvent
Widget::key_event_from_gdk(GdkEventKey* event) const
{
- auto type = vte::terminal::KeyEvent::Type{};
+ auto type = vte::terminal::EventBase::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;
+ case GDK_KEY_PRESS: type = vte::terminal::KeyEvent::Type::eKEY_PRESS; break;
+ case GDK_KEY_RELEASE: type = vte::terminal::KeyEvent::Type::eKEY_RELEASE; break;
default: g_assert_not_reached(); return {};
}
- return {type,
- read_modifiers_from_gdk(reinterpret_cast<GdkEvent*>(event)),
+ auto base_event = reinterpret_cast<GdkEvent*>(event);
+ return {base_event,
+ type,
+ event->time,
+ read_modifiers_from_gdk(base_event),
event->keyval,
event->hardware_keycode, // gdk_event_get_scancode(event),
event->group,
- event->time,
- event->is_modifier != 0,
- event};
+ event->is_modifier != 0};
+}
+
+std::optional<vte::terminal::MouseEvent>
+Widget::mouse_event_from_gdk(GdkEvent* event) const
+{
+ auto type = vte::terminal::EventBase::Type{};
+ switch (gdk_event_get_event_type(event)) {
+ case GDK_2BUTTON_PRESS: type = vte::terminal::MouseEvent::Type::eMOUSE_DOUBLE_PRESS; break;
+ case GDK_3BUTTON_PRESS: type = vte::terminal::MouseEvent::Type::eMOUSE_TRIPLE_PRESS; break;
+ case GDK_BUTTON_PRESS: type = vte::terminal::MouseEvent::Type::eMOUSE_PRESS; break;
+ case GDK_BUTTON_RELEASE: type = vte::terminal::MouseEvent::Type::eMOUSE_RELEASE; break;
+ case GDK_ENTER_NOTIFY: type = vte::terminal::MouseEvent::Type::eMOUSE_ENTER; break;
+ case GDK_LEAVE_NOTIFY: type = vte::terminal::MouseEvent::Type::eMOUSE_LEAVE; break;
+ case GDK_MOTION_NOTIFY: type = vte::terminal::MouseEvent::Type::eMOUSE_MOTION; break;
+ case GDK_SCROLL: type = vte::terminal::MouseEvent::Type::eMOUSE_SCROLL; break;
+ default:
+ return std::nullopt;
+ }
+
+ auto x = double{};
+ auto y = double{};
+ if (gdk_event_get_window(event) != m_event_window ||
+ !gdk_event_get_coords(event, &x, &y))
+ x = y = -1.; // FIXMEchpe or return std::nullopt?
+
+ auto button = unsigned{0};
+ (void)gdk_event_get_button(event, &button);
+
+ auto mouse_event = vte::terminal::MouseEvent{event,
+ type,
+ gdk_event_get_time(event),
+ read_modifiers_from_gdk(event),
+ vte::terminal::MouseEvent::Button(button),
+ x,
+ y};
+ return mouse_event;
}
void
diff --git a/src/widget.hh b/src/widget.hh
index 721b13cc..eed4da85 100644
--- a/src/widget.hh
+++ b/src/widget.hh
@@ -76,12 +76,12 @@ public:
void focus_out(GdkEventFocus *event) noexcept { m_terminal->widget_focus_out(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); }
- void leave(GdkEventCrossing *event) noexcept { m_terminal->widget_leave(event); }
- void scroll(GdkEventScroll *event) noexcept { m_terminal->widget_scroll(event); }
- bool motion_notify(GdkEventMotion *event) noexcept { return m_terminal->widget_motion_notify(event);
}
+ bool button_press(GdkEventButton *event) noexcept { return
m_terminal->widget_mouse_press(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ bool button_release(GdkEventButton *event) noexcept { return
m_terminal->widget_mouse_release(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ void enter(GdkEventCrossing *event) noexcept {
m_terminal->widget_mouse_enter(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ void leave(GdkEventCrossing *event) noexcept {
m_terminal->widget_mouse_leave(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ void scroll(GdkEventScroll *event) noexcept {
m_terminal->widget_mouse_scroll(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ bool motion_notify(GdkEventMotion *event) noexcept { return
m_terminal->widget_mouse_motion(*mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
void paste(GdkAtom board) noexcept { m_terminal->widget_paste(board); }
void copy(VteSelection sel,
@@ -136,6 +136,42 @@ public:
void feed_child(std::string_view const& str) { terminal()->feed_child(str); }
void feed_child_binary(std::string_view const& str) { terminal()->feed_child_binary(str); }
+ char *regex_match_check(vte::grid::column_t column,
+ vte::grid::row_t row,
+ int* tag)
+ {
+ return terminal()->regex_match_check(column, row, tag);
+ }
+
+ char* regex_match_check(GdkEvent* event,
+ int* tag)
+ {
+ if (auto mouse_event = mouse_event_from_gdk(event))
+ return terminal()->regex_match_check(*mouse_event, tag);
+ else
+ return nullptr;
+ }
+
+ bool regex_match_check_extra(GdkEvent* event,
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches)
+ {
+ if (auto mouse_event = mouse_event_from_gdk(event))
+ return terminal()->regex_match_check_extra(*mouse_event, regexes, n_regexes,
match_flags, matches);
+ else
+ return false;
+ }
+
+ char* hyperlink_check(GdkEvent* event)
+ {
+ if (auto mouse_event = mouse_event_from_gdk(event))
+ return terminal()->hyperlink_check(*mouse_event);
+ else
+ return nullptr;
+ }
+
bool should_emit_signal(int id) noexcept;
protected:
@@ -181,6 +217,7 @@ public: // FIXMEchpe
private:
unsigned read_modifiers_from_gdk(GdkEvent* event) const noexcept;
vte::terminal::KeyEvent key_event_from_gdk(GdkEventKey* event) const;
+ std::optional<vte::terminal::MouseEvent> mouse_event_from_gdk(GdkEvent* event) const;
GtkWidget* m_widget;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]