From 689b53e5e704d529b8afca6e70b17fd5529e646e Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:25:09 -0400 Subject: [PATCH 1/6] add callback wiring --- workbench/src/plugin_main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/workbench/src/plugin_main.c b/workbench/src/plugin_main.c index 25ecdf6def..56260521e2 100644 --- a/workbench/src/plugin_main.c +++ b/workbench/src/plugin_main.c @@ -45,6 +45,19 @@ GeanyPlugin *geany_plugin; GeanyData *geany_data; + +/* Callback function for document activate */ +static void plugin_workbench_on_doc_activate(G_GNUC_UNUSED GObject * obj, GeanyDocument * doc, + G_GNUC_UNUSED gpointer user_data) +{ + /* it seems odd to assert this here, + * as an untitled doc (new one) would have no filename. + */ + g_return_if_fail(doc != NULL && doc->file_name != NULL); + sidebar_on_doc_activate(doc); +} + + /* Callback function for document open */ static void plugin_workbench_on_doc_open(G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GeanyDocument * doc, G_GNUC_UNUSED gpointer user_data) @@ -115,6 +128,7 @@ static void plugin_workbench_help (G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNU static PluginCallback plugin_workbench_callbacks[] = { + {"document-activate", (GCallback) &plugin_workbench_on_doc_activate, TRUE, NULL}, {"document-open", (GCallback) &plugin_workbench_on_doc_open, TRUE, NULL}, {"document-close", (GCallback) &plugin_workbench_on_doc_close, TRUE, NULL}, {NULL, NULL, FALSE, NULL} From 21c6aeeb7c69e06b3d42034d914855241cb447ed Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:29:38 -0400 Subject: [PATCH 2/6] fix function typo add sidebar callback and header --- workbench/src/sidebar.c | 34 ++++++++++++++++++++++++++++++++-- workbench/src/sidebar.h | 1 + 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/workbench/src/sidebar.c b/workbench/src/sidebar.c index 0b6da7b2f7..47133665bd 100644 --- a/workbench/src/sidebar.c +++ b/workbench/src/sidebar.c @@ -908,6 +908,36 @@ static void sidebar_update_workbench(GtkTreeIter *iter, gint *position) } +/* Callback function for document activate */ +void sidebar_on_doc_activate(GeanyDocument * doc) +{ + if( workbench_is_empty(wb_globals.opened_wb) || doc == NULL || doc->file_name == NULL) + { + return; + } + g_message("doc activate"); + msgwin_status_add("doc activate"); + //check if doc-file_name is in the workbench + //have to because the file could have been opened outside of the workbench + SIDEBAR_CONTEXT ret_con; + ret_con = workbench_file_is_included_dir(wb_globals.opened_wb, doc->file_name); + if(ret_con.project != NULL && ret_con.directory!=NULL) + { + ITER_SEARCH_RESULT search_result; + if(sidebar_get_filepath_iter(ret_con.project, ret_con.directory, doc->file_name, &search_result)) + { + g_message("found iter"); + msgwin_status_add("found iter"); + GtkTreeIter tree_iter = search_result.iter; + GtkTreeSelection* selector = gtk_tree_view_get_selection ( GTK_TREE_VIEW(sidebar.file_view )); + //activate the file in the filetree? + gtk_tree_selection_select_iter (selector, &tree_iter); + //don't wb_idle_queue_add_action this, as a document selection should be immediate + } + } +} + + /** Update the sidebar. * * Update the sidebar according to the given situation/event @a event @@ -987,7 +1017,7 @@ void sidebar_update (SIDEBAR_EVENT event, SIDEBAR_CONTEXT *context) /* Callback function for clicking on a sidebar item */ -static void sidebar_filew_view_on_row_activated (GtkTreeView *treeview, +static void sidebar_file_view_on_row_activated (GtkTreeView *treeview, GtkTreePath *path, G_GNUC_UNUSED GtkTreeViewColumn *col, G_GNUC_UNUSED gpointer userdata) { gchar *info; @@ -1397,7 +1427,7 @@ void sidebar_init(void) /**** tree view ****/ sidebar.file_view = gtk_tree_view_new(); - g_signal_connect(sidebar.file_view, "row-activated", (GCallback)sidebar_filew_view_on_row_activated, NULL); + g_signal_connect(sidebar.file_view, "row-activated", (GCallback)sidebar_file_view_on_row_activated, NULL); sidebar.file_store = gtk_tree_store_new(FILEVIEW_N_COLUMNS, G_TYPE_ICON, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_POINTER); gtk_tree_view_set_model(GTK_TREE_VIEW(sidebar.file_view), GTK_TREE_MODEL(sidebar.file_store)); diff --git a/workbench/src/sidebar.h b/workbench/src/sidebar.h index 262d4e7b12..acc5a7b0d4 100644 --- a/workbench/src/sidebar.h +++ b/workbench/src/sidebar.h @@ -85,6 +85,7 @@ void sidebar_toggle_selected_project_dir_expansion (void); WB_PROJECT *sidebar_file_view_get_selected_project(GtkTreePath **path); gboolean sidebar_file_view_get_selected_context(SIDEBAR_CONTEXT *context); +void sidebar_on_doc_activate(GeanyDocument * doc); GPtrArray *sidebar_get_selected_project_filelist (gboolean dirnames); GPtrArray *sidebar_get_selected_directory_filelist (gboolean dirnames); From 6c8c7c45f35deb70140cc6d66888bc280b2ec6f2 Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:33:58 -0400 Subject: [PATCH 3/6] add helper function to find a directory from a project --- workbench/src/wb_project.c | 26 ++++++++++++++++++++++++++ workbench/src/wb_project.h | 1 + 2 files changed, 27 insertions(+) diff --git a/workbench/src/wb_project.c b/workbench/src/wb_project.c index 4f107d196f..da9974c72e 100644 --- a/workbench/src/wb_project.c +++ b/workbench/src/wb_project.c @@ -1076,6 +1076,32 @@ gboolean wb_project_dir_file_is_included(WB_PROJECT_DIR *dir, const gchar *filen } +/** Is @a filename included in the project directory? + * + * @param prj The project + * @param filename The file + * @return pointer to WB_PROJECT_DIR + * or NULL if not found + * + **/ +WB_PROJECT_DIR* wb_project_file_is_included_dir(WB_PROJECT *prj, const gchar *filename) +{ + if (prj == NULL) + { + return NULL; + } + GSList *elem = NULL; + foreach_slist(elem ,prj->directories) + { + if (wb_project_dir_file_is_included(elem->data, filename) == TRUE) + { + return elem->data; + } + } + return NULL; +} + + /** Is @a filename included in the project? * * @param dir The project diff --git a/workbench/src/wb_project.h b/workbench/src/wb_project.h index a7d290b03d..3036d42a85 100644 --- a/workbench/src/wb_project.h +++ b/workbench/src/wb_project.h @@ -45,6 +45,7 @@ gboolean wb_project_add_directory(WB_PROJECT *prj, const gchar *dirname); gboolean wb_project_remove_directory (WB_PROJECT *prj, WB_PROJECT_DIR *dir); void wb_project_rescan(WB_PROJECT *prj); gboolean wb_project_file_is_included(WB_PROJECT *prj, const gchar *filename); +WB_PROJECT_DIR* wb_project_file_is_included_dir(WB_PROJECT *prj, const gchar *filename); gboolean wb_project_is_valid_dir_reference(WB_PROJECT *prj, WB_PROJECT_DIR *dir); void wb_project_dir_set_is_prj_base_dir (WB_PROJECT_DIR *directory, gboolean value); From 028cafdd198590587f0cd1fdeefa4229bc821c38 Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:39:46 -0400 Subject: [PATCH 4/6] add helper function to find a sidebar context to work in --- workbench/src/workbench.c | 32 ++++++++++++++++++++++++++++++++ workbench/src/workbench.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/workbench/src/workbench.c b/workbench/src/workbench.c index 9dbbc82010..62b6c6221a 100644 --- a/workbench/src/workbench.c +++ b/workbench/src/workbench.c @@ -605,6 +605,38 @@ WB_PROJECT *workbench_file_is_included (WORKBENCH *wb, const gchar *filename) } +/** Is the file included in the workbench? + * + * @param wb The workbench + * @param filename The file + * @return SIDEBAR_CONTEXT with only the .project and .directory set + * .project and .directory will be set to NULL if not found + * + **/ +SIDEBAR_CONTEXT workbench_file_is_included_dir (WORKBENCH *wb, const gchar *filename){ + SIDEBAR_CONTEXT ret_con; + ret_con.project=NULL; + ret_con.directory=NULL; + if (wb != NULL) + { + guint index; + WB_PROJECT_DIR *root=NULL; + for (index = 0 ; index < wb->projects->len ; index++) + { + WB_PROJECT_ENTRY *current = g_ptr_array_index(wb->projects, index); + root=wb_project_file_is_included_dir(current->project, filename); + if (current != NULL && root != NULL) + { + ret_con.project = current->project; + ret_con.directory = root; + return ret_con; + } + } + } + return ret_con; +} + + /* Add a workbench bookmark */ static gboolean workbench_add_bookmark_int(WORKBENCH *wb, const gchar *filename) { diff --git a/workbench/src/workbench.h b/workbench/src/workbench.h index 17aa7e096b..040c296d33 100644 --- a/workbench/src/workbench.h +++ b/workbench/src/workbench.h @@ -22,6 +22,7 @@ #include #include "wb_project.h" #include "wb_monitor.h" +#include "sidebar.h" typedef enum { @@ -54,6 +55,7 @@ PROJECT_ENTRY_STATUS workbench_get_project_status_by_address(WORKBENCH *wb, WB_P gboolean workbench_add_project(WORKBENCH *wb, const gchar *filename); gboolean workbench_remove_project_with_address(WORKBENCH *wb, WB_PROJECT *project); WB_PROJECT *workbench_file_is_included (WORKBENCH *wb, const gchar *filename); +SIDEBAR_CONTEXT workbench_file_is_included_dir (WORKBENCH *wb, const gchar *filename); void workbench_set_filename(WORKBENCH *wb, const gchar *filename); const gchar *workbench_get_filename(WORKBENCH *wb); From c573da54aaf9a6a7e1d56115c31e675cdcf582a2 Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:02:38 -0400 Subject: [PATCH 5/6] add expand to, and scroll to on editor tab selection aligned static header definition with static implementation --- workbench/src/sidebar.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/workbench/src/sidebar.c b/workbench/src/sidebar.c index 47133665bd..2bd69c8fc4 100644 --- a/workbench/src/sidebar.c +++ b/workbench/src/sidebar.c @@ -83,7 +83,7 @@ typedef struct SIDEBAR static SIDEBAR sidebar = {NULL, NULL, NULL, NULL}; static gboolean sidebar_get_directory_iter(WB_PROJECT *prj, WB_PROJECT_DIR *dir, GtkTreeIter *iter); -static gboolean sidebar_get_filepath_iter (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath, ITER_SEARCH_RESULT *result); +static gboolean sidebar_get_filepath_iter (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath, ITER_SEARCH_RESULT *search_result); /* Remove all child nodes below parent */ static void sidebar_remove_children(GtkTreeIter *parent) @@ -915,8 +915,6 @@ void sidebar_on_doc_activate(GeanyDocument * doc) { return; } - g_message("doc activate"); - msgwin_status_add("doc activate"); //check if doc-file_name is in the workbench //have to because the file could have been opened outside of the workbench SIDEBAR_CONTEXT ret_con; @@ -926,13 +924,16 @@ void sidebar_on_doc_activate(GeanyDocument * doc) ITER_SEARCH_RESULT search_result; if(sidebar_get_filepath_iter(ret_con.project, ret_con.directory, doc->file_name, &search_result)) { - g_message("found iter"); - msgwin_status_add("found iter"); GtkTreeIter tree_iter = search_result.iter; - GtkTreeSelection* selector = gtk_tree_view_get_selection ( GTK_TREE_VIEW(sidebar.file_view )); - //activate the file in the filetree? + GtkTreeSelection* selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(sidebar.file_view )); + //activate the file in the filetree gtk_tree_selection_select_iter (selector, &tree_iter); //don't wb_idle_queue_add_action this, as a document selection should be immediate + GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(sidebar.file_store), &tree_iter); + //expand the file we selected + gtk_tree_view_expand_row (GTK_TREE_VIEW(sidebar.file_view), path, TRUE); + //scroll to the file we selected + gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(sidebar.file_view), path, NULL, TRUE, 0.5f,0.5f); } } } From 7f2c113321941f04fe2301535eba575e01131149 Mon Sep 17 00:00:00 2001 From: WrapEarnPass <293701378+WrapEarnPass@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:07:26 -0400 Subject: [PATCH 6/6] add filetree handler for singleclick/cursor move --- workbench/src/sidebar.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/workbench/src/sidebar.c b/workbench/src/sidebar.c index 2bd69c8fc4..079402b3a9 100644 --- a/workbench/src/sidebar.c +++ b/workbench/src/sidebar.c @@ -1017,7 +1017,43 @@ void sidebar_update (SIDEBAR_EVENT event, SIDEBAR_CONTEXT *context) } -/* Callback function for clicking on a sidebar item */ +/* Callback function for single click or cursor move on a sidebar item */ +static void sidebar_file_view_on_row_selected (GtkTreeView *treeview, + GtkTreePath *path, G_GNUC_UNUSED GtkTreeViewColumn *col, G_GNUC_UNUSED gpointer userdata) +{ + //If the cursor isn’t currently set, then path will be NULL. If no column currently has focus, then focus_column will be NULL. + gtk_tree_view_get_cursor(treeview, &path, &col); + if(path==NULL) + { + return; + } + + GtkTreeModel *model = gtk_tree_view_get_model(treeview); + GtkTreeIter iter; + if (gtk_tree_model_get_iter(model, &iter, path)) + { + guint dataid; + gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_DATA_ID, &dataid, -1); + if(dataid==DATA_ID_FILE) + { + gchar *name; + gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_NAME, &name, -1); + gpointer *filename; + gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, &filename, -1); + GeanyDocument *doc =document_find_by_real_path((gchar *)filename); + if(doc!=NULL) + { + gint page = document_get_notebook_page(doc); + gtk_notebook_set_current_page(GTK_NOTEBOOK(wb_globals.geany_plugin->geany_data->main_widgets->notebook), page); + } + } + } + + g_free(path); +} + + +/* Callback function for double clicking on a sidebar item */ static void sidebar_file_view_on_row_activated (GtkTreeView *treeview, GtkTreePath *path, G_GNUC_UNUSED GtkTreeViewColumn *col, G_GNUC_UNUSED gpointer userdata) { @@ -1428,6 +1464,9 @@ void sidebar_init(void) /**** tree view ****/ sidebar.file_view = gtk_tree_view_new(); + //single click handler + g_signal_connect(sidebar.file_view, "cursor-changed", (GCallback)sidebar_file_view_on_row_selected, NULL); + //double click handler g_signal_connect(sidebar.file_view, "row-activated", (GCallback)sidebar_file_view_on_row_activated, NULL); sidebar.file_store = gtk_tree_store_new(FILEVIEW_N_COLUMNS, G_TYPE_ICON, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_POINTER);