Skip to content

Commit

Permalink
Fix emission of document-activate signal and associated UI glitches
Browse files Browse the repository at this point in the history
PR geany#3267 broke handling of several
special tab switch cases:

* By showing the tab's child too early, it prevented the switch-page
  handler to properly work in situations where there was only one page,
  as the tab switch would happen at page creation yet the document
  would not be valid yet.
* It removed explicit emission of the switch-page signal when the
  source and target pages are the same after session opening, which
  happens if the active session page is the first one.

Fix this by mostly reverting 23367de
and implementing the delay directly in the switch-page handler.

Fixes geany#3684.
  • Loading branch information
b4n committed Jun 13, 2024
1 parent de4f029 commit 293157c
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 52 deletions.
59 changes: 48 additions & 11 deletions src/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,18 +515,8 @@ void on_normal_size1_activate(GtkMenuItem *menuitem, gpointer user_data)
}


/* Changes window-title after switching tabs and lots of other things.
* note: using 'after' makes Scintilla redraw before the UI, appearing more responsive */
static void on_notebook1_switch_page_after(GtkNotebook *notebook, gpointer page,
guint page_num, gpointer user_data)
static void handle_switch_page(GeanyDocument *doc)
{
GeanyDocument *doc;

if (G_UNLIKELY(main_status.opening_session_files || main_status.closing_all))
return;

doc = document_get_from_notebook_child(page);

if (doc != NULL)
{
GtkEntry *filter_entry = GTK_ENTRY(ui_lookup_widget(main_widgets.window, "entry_tagfilter"));
Expand Down Expand Up @@ -559,6 +549,53 @@ static void on_notebook1_switch_page_after(GtkNotebook *notebook, gpointer page,
}


static gboolean delay_handle_switch_page(gpointer data)
{
gulong *handler_id = data;

if (main_status.opening_session_files)
return G_SOURCE_CONTINUE;
/* guard against the unlikely case where we didn't run yet but are already
* closing all documents */
else if (! main_status.closing_all)
handle_switch_page(document_get_current());

*handler_id = 0;
return G_SOURCE_REMOVE;
}


/* Changes window-title after switching tabs and lots of other things.
* note: using 'after' makes Scintilla redraw before the UI, appearing more responsive
*
* When page switch happens while opening session files, we delay handling of the
* event to when session opening is complete. This is mostly to avoid repeatedly update
* the UI unnecessarily, which isn't entirely cheap */
static void on_notebook1_switch_page_after(GtkNotebook *notebook, gpointer page,
guint page_num, gpointer user_data)
{
static gulong handler_id = 0;

if (main_status.opening_session_files)
{
/* if opening session files, delay the handling to after session is fully open */
if (handler_id == 0)
handler_id = g_idle_add(delay_handle_switch_page, &handler_id);
return;
}
else if (main_status.closing_all)
return;

if (handler_id != 0)
{
g_source_remove(handler_id);
handler_id = 0;
}

handle_switch_page(document_get_from_notebook_child(page));
}


static void on_tv_notebook_switch_page(GtkNotebook *notebook, gpointer page,
guint page_num, gpointer user_data)
{
Expand Down
39 changes: 9 additions & 30 deletions src/document.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ enum
};


static guint show_tab_idle = 0;
static guint doc_id_counter = 0;


Expand Down Expand Up @@ -859,6 +858,9 @@ GeanyDocument *document_new_file(const gchar *utf8_filename, GeanyFiletype *ft,

document_set_filetype(doc, ft); /* also re-parses tags */

/* now the document is fully ready, display it (see notebook_new_tab()) */
gtk_widget_show(document_get_notebook_child(doc));

ui_set_window_title(doc);
build_menu_update(doc);
document_set_text_changed(doc, FALSE);
Expand Down Expand Up @@ -1264,40 +1266,14 @@ void document_apply_indent_settings(GeanyDocument *doc)

void document_show_tab(GeanyDocument *doc)
{
if (show_tab_idle)
{
g_source_remove(show_tab_idle);
show_tab_idle = 0;
}

gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook),
document_get_notebook_page(doc));

/* finally, let the editor widget grab the focus so you can start coding
* right away */
document_try_focus(doc, NULL);
}


static gboolean show_tab_cb(gpointer data)
{
GeanyDocument *doc = (GeanyDocument *) data;

show_tab_idle = 0;
/* doc might not be valid e.g. if user closed a tab whilst Geany is opening files */
if (DOC_VALID(doc))
document_show_tab(doc);

return G_SOURCE_REMOVE;
}


void document_show_tab_idle(GeanyDocument *doc)
{
if (show_tab_idle)
g_source_remove(show_tab_idle);

show_tab_idle = g_idle_add(show_tab_cb, doc);
/* FIXME: is that actually useful?? I don't see any difference disabling this code... */
if (!main_status.opening_session_files)
document_try_focus(doc, NULL);
}


Expand Down Expand Up @@ -1517,6 +1493,9 @@ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename
display_filename, gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)),
(readonly) ? _(", read-only") : "");
}

/* now the document is fully ready, display it (see notebook_new_tab()) */
gtk_widget_show(document_get_notebook_child(doc));
}

g_free(display_filename);
Expand Down
7 changes: 2 additions & 5 deletions src/editor.c
Original file line number Diff line number Diff line change
Expand Up @@ -4743,11 +4743,8 @@ gboolean editor_goto_pos(GeanyEditor *editor, gint pos, gboolean mark)
sci_goto_pos(editor->sci, pos, TRUE);
editor->scroll_percent = 0.25F;

/* switch to the page, via idle callback in case of batch-opening */
if (main_status.opening_session_files)
document_show_tab_idle(editor->document);
else
document_show_tab(editor->document);
/* switch to the page */
document_show_tab(editor->document);

return TRUE;
}
Expand Down
6 changes: 3 additions & 3 deletions src/keyfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,8 +1353,8 @@ static gboolean open_session_file(gchar **tmp, guint len)


/* Open session files
* Note: notebook page switch handler and adding to recent files list is always disabled
* for all files opened within this function */
* Note: notebook page switch handler is delayed, and adding to recent files list is
* always disabled for all files opened within this function */
void configuration_open_files(GPtrArray *session_files)
{
gboolean failure = FALSE;
Expand All @@ -1380,7 +1380,7 @@ void configuration_open_files(GPtrArray *session_files)
if (failure)
ui_set_statusbar(TRUE, _("Failed to load one or more session files."));
else
document_show_tab_idle(session_notebook_page >= 0 ? document_get_from_page(session_notebook_page) : document_get_current());
document_show_tab(session_notebook_page >= 0 ? document_get_from_page(session_notebook_page) : document_get_current());

session_notebook_page = -1;
main_status.opening_session_files--;
Expand Down
2 changes: 1 addition & 1 deletion src/libmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ gboolean main_handle_filename(const gchar *locale_filename)

doc = document_find_by_filename(utf8_filename);
if (doc)
document_show_tab_idle(doc);
document_show_tab(doc);
else
doc = document_new_file(utf8_filename, NULL, NULL);
g_free(utf8_filename);
Expand Down
2 changes: 0 additions & 2 deletions src/notebook.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,6 @@ gint notebook_new_tab(GeanyDocument *this)
page = GTK_WIDGET(this->editor->sci);
gtk_box_pack_start(GTK_BOX(vbox), page, TRUE, TRUE, 0);

gtk_widget_show_all(vbox);

this->priv->tab_label = gtk_label_new(NULL);

/* get button press events for the tab label and the space between it and
Expand Down

0 comments on commit 293157c

Please sign in to comment.