2023-10-14
This application catches mouse signals and logs them in a GtkTextView:
Type ESCAPE to close the window.
#include <gtk/gtk.h>
//
// Variables
//
static GtkWidget* textview = NULL;
static GtkTextBuffer* buffer = NULL;
//
// Logs output to textview and adds line break.
//
static void log_line(const char* text) {
GtkTextIter iter;
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, g_strdup_printf("%s\n", text), -1);
//
// autoscroll
//
gtk_text_buffer_get_end_iter(buffer, &iter);
GtkTextMark* mark = gtk_text_buffer_create_mark(buffer, "mark", &iter, TRUE);
gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(textview), mark, 0.0, TRUE, 0, 0);
}
//
/// Is called when the mouse cursor enters the label.
//
static void mouse_enter(GtkWidget* label, gdouble x, gdouble y, gpointer user_data) {
const char* text = g_strdup_printf("Enter - x: %f y: %f", x, y);
gtk_label_set_text(GTK_LABEL(label), text);
log_line(text);
}
//
/// Is called when the mouse cursor leaves the label.
//
static void mouse_leave(GtkWidget* label, gpointer user_data) {
const char* text = g_strdup_printf("Leave");
gtk_label_set_text(GTK_LABEL(label), text);
log_line(text);
}
//
// Is called when the mouse cursor moves above the label.
//
static void mouse_motion(GtkWidget* label, gdouble x, gdouble y, gpointer user_data) {
const char* text = g_strdup_printf("Motion - x: %f y: %f", x, y);
gtk_label_set_text(GTK_LABEL(label), text);
log_line(text);
}
//
// Is called when a key is pressed while the main application window has focus.
//
static gboolean key_pressed(GtkWidget* window, guint keyval, guint keycode, GdkModifierType state, gpointer user_data) {
const char* text = g_strdup_printf("key_pressed - keyval: %d keycode: %d", keyval, keycode);
g_print(g_strdup_printf("%s\n", text));
if (keyval == GDK_KEY_Escape) {
g_print(g_strdup_printf("Good bye world.\n"));
gtk_window_destroy(GTK_WINDOW(window));
}
return TRUE;
}
//
// Is called when the main application window is activated.
//
static void activate(GtkApplication* app) {
//
// Initialize window and signals
//
GtkWindow* window = GTK_WINDOW(gtk_application_window_new(app));
{
gtk_window_set_default_size(window, 600, 480);
GtkEventController* event_controller = gtk_event_controller_key_new();
g_signal_connect_object(event_controller, "key-pressed", G_CALLBACK(key_pressed), window, G_CONNECT_SWAPPED);
gtk_widget_add_controller(GTK_WIDGET(window), event_controller);
}
//
// Initialize label and signals
//
GtkWidget* label = gtk_label_new("Hello world!");
{
gtk_widget_set_size_request(label, 600, 240);
GtkEventController* motion_controller = gtk_event_controller_motion_new();
g_signal_connect_object(motion_controller, "enter", G_CALLBACK(mouse_enter), label, G_CONNECT_SWAPPED);
g_signal_connect_object(motion_controller, "leave", G_CALLBACK(mouse_leave), label, G_CONNECT_SWAPPED);
g_signal_connect_object(motion_controller, "motion", G_CALLBACK(mouse_motion), label, G_CONNECT_SWAPPED);
gtk_widget_add_controller(GTK_WIDGET(label), motion_controller);
}
//
// Initialize scrolled window for textview
//
GtkWidget* scrolledwindow = gtk_scrolled_window_new();
{
gtk_scrolled_window_set_max_content_height(GTK_SCROLLED_WINDOW(scrolledwindow), 240);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
//
// Initialize textview and buffer
//
textview = gtk_text_view_new();
gtk_widget_set_size_request(scrolledwindow, 600,240);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolledwindow), textview);
}
//
// Initialize grid
//
{
GtkWidget* grid = gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(grid), scrolledwindow, 0, 1, 1, 1);
gtk_window_set_child(window, grid);
}
gtk_window_present(window);
}
//
// Main function.
//
int main(int argc, char* argv[]) {
g_autoptr(GtkApplication) app = gtk_application_new(NULL, 0);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
return g_application_run(G_APPLICATION(app), argc, argv);
}
Compile with:
cc $(pkg-config --cflags gtk4) main.c $(pkg-config --libs gtk4)
Execute program with:
./a.out
GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); works but after GtkTextIter* iter = NULL; gtk_text_buffer_get_end_iter(buffer, iter); iter is still NULL.gtk_text_view_scroll_to_iter() works odd while gtk_text_view_scroll_to_mark() works okay (as is documented).