I’m creating a multi line text view with GTK3 where I want to catch certain key events. The idea is to let the default action happen when the user presses enter
and insert a line break into the text when the user presses either SHIFT+Enter
or CTRL+Enter
. My setup looks like this:
// Base dialog
GtkWidget* dialog = gtk_dialog_new();
// no automatic layout since I position everything myself
GtkWidget* content_area_fixed = gtk_fixed_new();
gtk_widget_set_size_request(content_area_fixed, someWidth, someHeight);
gtk_container_add(GTK_CONTAINER(content_area_automatic), content_area_fixed);
GtkWidget* content_area = content_area_fixed;
I’m creating a multi line text input like this and subscribing to the key-press-event
and key-release-event
of the text view like this:
// rough break down of multi line text input
auto textBuffer = gtk_text_buffer_new(NULL);
gtk_text_buffer_set_text(textBuffer, "", 0);
g_signal_connect_after(textBuffer, "insert-text", G_CALLBACK(onTextBuffer_insert_text), NULL);
auto textView = (GtkTextView*)gtk_text_view_new_with_buffer(textBuffer);
gtk_text_view_set_accepts_tab(textView, false);
// Connect to handling keyboard events
gtk_widget_add_events(GTK_WIDGET(content_area), GDK_KEY_PRESS_MASK);
g_signal_connect_after(GTK_WIDGET(textView), "key-press-event", G_CALLBACK(onTextBuffer_key_event), NULL);
g_signal_connect_after(GTK_WIDGET(textView), "key-release-event", G_CALLBACK(onTextBuffer_key_event), NULL);
// add scrollable window which allows the size to stay fixed with multi-line text
GtkWidget* scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(scrolledwindow), (GtkWidget*)textView);
gtk_container_add(GTK_CONTAINER(content_area), scrolledwindow);
// omitting setting position and size to keep example short
Finally, the key-event callback looks like this:
// keyboard input callback for text view
static gboolean onTextBuffer_key_event(GtkWidget* self, GdkEventKey event, gpointer user_data)
{
switch (event.type) {
case GDK_KEY_PRESS:
{
std::cout << "Pressing HW " << event.hardware_keycode << " (keyval " << event.keyval << ")" << std::endl;
return TRUE;
}
case GDK_KEY_RELEASE:
{
std::cout << "Releasing HW " << event.hardware_keycode << " (keyval " << event.keyval << ")" << std::endl;
return TRUE;
}
default:
{
std::cout << "Other event type not interested in received " << event.type << std::endl;
return FALSE;
}
}
}
When running that dialog via gtk_widget_show_all(dialog)
, all I’m seeing in the output for any key press or release like a
, shift
or enter
is:
Other event type not interested in received 0
So basically, I’m only receiving GDK_DELETE
and not a single GDK_KEY_PRESS
or GDK_KEY_PRESS
. Also, the keyval
of every event is 32767
/0x7fff
.
I also tried different widgets as the first parameter for gtk_widget_add_events()
like GTK_WIDGET(scrolledwindow)
, GTK_WIDGET(textView)
or GTK_WIDGET(dialog)
but none of them changed the situation.
Any idea what I can do to get the actual key events while the user is editing the text view?
Also, maybe there’s an easier approach to make the enter
key emit the dialog’s default response while the text view has focus?