Handle middle mouse clicks on breadcrumbs

Also, don't act on button releases happening outside the widget.
This commit is contained in:
Přemysl Eric Janouch 2022-01-07 05:30:19 +01:00
parent 06ab13797d
commit 235af37382
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 38 additions and 9 deletions

View File

@ -31,6 +31,7 @@ struct _FivSidebar {
G_DEFINE_TYPE(FivSidebar, fiv_sidebar, GTK_TYPE_SCROLLED_WINDOW) G_DEFINE_TYPE(FivSidebar, fiv_sidebar, GTK_TYPE_SCROLLED_WINDOW)
G_DEFINE_QUARK(fiv-sidebar-location-quark, fiv_sidebar_location) G_DEFINE_QUARK(fiv-sidebar-location-quark, fiv_sidebar_location)
G_DEFINE_QUARK(fiv-sidebar-self-quark, fiv_sidebar_self)
enum { enum {
OPEN_LOCATION, OPEN_LOCATION,
@ -66,7 +67,7 @@ fiv_sidebar_class_init(FivSidebarClass *klass)
// TODO(p): Consider a return value, and using it. // TODO(p): Consider a return value, and using it.
sidebar_signals[OPEN_LOCATION] = sidebar_signals[OPEN_LOCATION] =
g_signal_new("open_location", G_TYPE_FROM_CLASS(klass), 0, 0, g_signal_new("open-location", G_TYPE_FROM_CLASS(klass), 0, 0,
NULL, NULL, NULL, G_TYPE_NONE, NULL, NULL, NULL, G_TYPE_NONE,
2, G_TYPE_FILE, GTK_TYPE_PLACES_OPEN_FLAGS); 2, G_TYPE_FILE, GTK_TYPE_PLACES_OPEN_FLAGS);
} }
@ -84,10 +85,30 @@ on_rowlabel_query_tooltip(GtkWidget *widget,
return TRUE; return TRUE;
} }
static GtkWidget * static gboolean
create_row(GFile *file, const char *icon_name) on_breadcrumb_release(
G_GNUC_UNUSED GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
// This also prevents unwanted primary button click handling in GtkListBox.
if (event->x > gdk_window_get_width(event->window) ||
event->y > gdk_window_get_height(event->window))
return TRUE;
guint state = event->state & gtk_accelerator_get_default_mod_mask();
if (event->button != GDK_BUTTON_MIDDLE || state != 0)
return FALSE;
GtkListBoxRow *row = GTK_LIST_BOX_ROW(user_data);
g_signal_emit(g_object_get_qdata(G_OBJECT(row), fiv_sidebar_self_quark()),
sidebar_signals[OPEN_LOCATION], 0,
g_object_get_qdata(G_OBJECT(row), fiv_sidebar_location_quark()),
GTK_PLACES_OPEN_NEW_WINDOW);
return TRUE;
}
static GtkWidget *
create_row(FivSidebar *self, GFile *file, const char *icon_name)
{ {
// TODO(p): Handle errors better.
GError *error = NULL; GError *error = NULL;
GFileInfo *info = GFileInfo *info =
g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
@ -116,7 +137,11 @@ create_row(GFile *file, const char *icon_name)
gtk_widget_get_style_context(rowlabel), "sidebar-label"); gtk_widget_get_style_context(rowlabel), "sidebar-label");
gtk_container_add(GTK_CONTAINER(rowbox), rowlabel); gtk_container_add(GTK_CONTAINER(rowbox), rowlabel);
// The revealer is primarily necessary to match Adwaita CSS rules,
// but it conveniently also has its own GdkWindow to hook events on.
GtkWidget *revealer = gtk_revealer_new(); GtkWidget *revealer = gtk_revealer_new();
gtk_widget_add_events(
revealer, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
gtk_revealer_set_reveal_child( gtk_revealer_set_reveal_child(
GTK_REVEALER(revealer), TRUE); GTK_REVEALER(revealer), TRUE);
gtk_revealer_set_transition_type( gtk_revealer_set_transition_type(
@ -126,6 +151,11 @@ create_row(GFile *file, const char *icon_name)
GtkWidget *row = gtk_list_box_row_new(); GtkWidget *row = gtk_list_box_row_new();
g_object_set_qdata_full(G_OBJECT(row), fiv_sidebar_location_quark(), g_object_set_qdata_full(G_OBJECT(row), fiv_sidebar_location_quark(),
g_object_ref(file), (GDestroyNotify) g_object_unref); g_object_ref(file), (GDestroyNotify) g_object_unref);
g_object_set_qdata_full(G_OBJECT(row), fiv_sidebar_self_quark(),
g_object_ref(self), (GDestroyNotify) g_object_unref);
g_signal_connect(revealer, "button-release-event",
G_CALLBACK(on_breadcrumb_release), row);
gtk_container_add(GTK_CONTAINER(row), revealer); gtk_container_add(GTK_CONTAINER(row), revealer);
gtk_widget_show_all(row); gtk_widget_show_all(row);
return row; return row;
@ -150,19 +180,19 @@ update_location(FivSidebar *self)
if (!(iter = parent)) if (!(iter = parent))
break; break;
if ((row = create_row(parent, "go-up-symbolic"))) if ((row = create_row(self, parent, "go-up-symbolic")))
gtk_list_box_prepend(GTK_LIST_BOX(self->listbox), row); gtk_list_box_prepend(GTK_LIST_BOX(self->listbox), row);
} }
// Other options are "folder-{visiting,open}-symbolic", though the former // Other options are "folder-{visiting,open}-symbolic", though the former
// is mildly inappropriate (means: open in another window). // is mildly inappropriate (means: open in another window).
if ((row = create_row(location, "circle-filled-symbolic"))) if ((row = create_row(self, location, "circle-filled-symbolic")))
gtk_container_add(GTK_CONTAINER(self->listbox), row); gtk_container_add(GTK_CONTAINER(self->listbox), row);
GPtrArray *subdirs = fiv_io_model_get_subdirectories(self->model); GPtrArray *subdirs = fiv_io_model_get_subdirectories(self->model);
for (guint i = 0; i < subdirs->len; i++) { for (guint i = 0; i < subdirs->len; i++) {
GFile *file = g_file_new_for_uri(subdirs->pdata[i]); GFile *file = g_file_new_for_uri(subdirs->pdata[i]);
if ((row = create_row(file, "go-down-symbolic"))) if ((row = create_row(self, file, "go-down-symbolic")))
gtk_container_add(GTK_CONTAINER(self->listbox), row); gtk_container_add(GTK_CONTAINER(self->listbox), row);
g_object_unref(file); g_object_unref(file);
} }

3
fiv.c
View File

@ -1431,8 +1431,7 @@ main(int argc, char *argv[])
gtk_container_set_focus_hadjustment(GTK_CONTAINER(browser_port), NULL); gtk_container_set_focus_hadjustment(GTK_CONTAINER(browser_port), NULL);
gtk_container_set_focus_vadjustment(GTK_CONTAINER(browser_port), NULL); gtk_container_set_focus_vadjustment(GTK_CONTAINER(browser_port), NULL);
// TODO(p): As with GtkFileChooserWidget, bind C-h to filtering, // TODO(p): Mayhaps forward some key presses to the sidebar, somehow.
// and mayhaps forward the rest to the sidebar, somehow.
g.browser_sidebar = make_browser_sidebar(g.model); g.browser_sidebar = make_browser_sidebar(g.model);
g.browser_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); g.browser_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);