From 7aa510426931863436bb507f53a3702b606fe5f8 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Mon, 21 Jul 2025 21:23:26 +0200 Subject: [PATCH] add key event handler to the filesview widget --- mizunara/gtk-filesview.c | 92 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/mizunara/gtk-filesview.c b/mizunara/gtk-filesview.c index 01a81be..7326f2e 100644 --- a/mizunara/gtk-filesview.c +++ b/mizunara/gtk-filesview.c @@ -78,6 +78,15 @@ static void button_pressed( gdouble y, gpointer user_data); +static gboolean key_pressed( + GtkEventControllerKey* self, + guint keyval, + guint keycode, + GdkModifierType state, + MzFilesView *view); + + + static void mz_files_view_class_init(MzFilesViewClass *klass) { printf("mz_files_view_class_init\n"); klass->parent_class.snapshot = mz_files_view_snapshot; @@ -103,7 +112,9 @@ static void mz_files_view_init(MzFilesView *self) { // default item size self->item_width = 180; self->item_height = 170; - + + gtk_widget_set_focusable(GTK_WIDGET(self), TRUE); + // event handler GtkDragSource *dnd_source = gtk_drag_source_new(); g_signal_connect(dnd_source, "prepare", G_CALLBACK(dnd_prepare), self); @@ -123,6 +134,10 @@ static void mz_files_view_init(MzFilesView *self) { GtkGesture *click = gtk_gesture_click_new (); g_signal_connect(click, "pressed", G_CALLBACK(button_pressed), self); gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(click)); + + GtkEventController *keyctrl = gtk_event_controller_key_new(); + g_signal_connect(keyctrl, "key-pressed", G_CALLBACK(key_pressed), self); + gtk_widget_add_controller(GTK_WIDGET(self), keyctrl); } void mz_files_view_dispose(GObject *object) { @@ -495,6 +510,7 @@ static void drag_begin_cb( { MzFilesView *view = user_data; printf("drag_begin_cb: %f\n", start_x); + gtk_widget_grab_focus((GtkWidget*)view); // update selection int item_width = view->item_width; @@ -654,6 +670,80 @@ static void button_pressed( } } +static gboolean key_pressed( + GtkEventControllerKey* self, + guint keyval, + guint keycode, + GdkModifierType state, + MzFilesView *view) +{ + int x = 0; + int y = 0; + switch (keyval) { + case GDK_KEY_Left: + x--; + break; + case GDK_KEY_Right: + x++; + break; + case GDK_KEY_Up: + y--; + break; + case GDK_KEY_Down: + y++; + break; + default: + return FALSE; + } + + if(view->numitems == 0) { + return TRUE; + } + + if(view->selection_count == 0) { + view->items[0].isselected = TRUE; + } else { + // find first selection and unselect everything else + size_t selx = -1; + size_t sely = -1; + size_t selcount = view->selection_count; + for(size_t i=0;inumitems;i++) { + if(view->items[i].isselected) { + if(selx == -1) { + selx = i % view->current_items_per_line; + sely = i / view->current_items_per_line; + } + view->items[i].isselected = FALSE; + if(--selcount == 0) { + break; + } + } + } + + selx += x; + sely += y; + if(selx >= view->current_items_per_line) { + selx = 0; + sely++; + } + if(selx < 0) { + selx = view->current_items_per_line-1; + sely--; + } + + if(sely < 0) { + return TRUE; + } + + size_t selected_index = sely * view->current_items_per_line + selx; + if(selected_index < view->numitems) { + view->items[selected_index].isselected = TRUE; + } + } + + gtk_widget_queue_draw(GTK_WIDGET(view)); + return TRUE; +} /* -------------------------- public -------------------------- */ -- 2.47.3