|
|
3fc286 |
From 8447b9f9369ce850f1888b4bd8d03540de88cab0 Mon Sep 17 00:00:00 2001
|
|
|
3fc286 |
From: Andrea Azzarone <andrea.azzarone@canonical.com>
|
|
|
3fc286 |
Date: Tue, 2 Apr 2019 17:33:12 +0100
|
|
|
3fc286 |
Subject: [PATCH] open-document-selector: Properly remove idle
|
|
|
3fc286 |
|
|
|
3fc286 |
It's not possible to use g_idle_remove_by_data when the idle was added with
|
|
|
3fc286 |
gdk_threads_add_idle_full. gdk_threads_add_idle_full uses g_idle_add_full
|
|
|
3fc286 |
internally but it creates a temporary data strucuture. The address of this
|
|
|
3fc286 |
temporary data structure should be passed to g_idle_remove_by_data. For obvious
|
|
|
3fc286 |
reasons we cannot do that, so let's use g_source_remove.
|
|
|
3fc286 |
|
|
|
3fc286 |
Failing to remove the idle when the open document selector is disposed could
|
|
|
3fc286 |
result in a crash because the idle function (real_populate_liststore) would
|
|
|
3fc286 |
access invalid memory.
|
|
|
3fc286 |
|
|
|
3fc286 |
Also remove populate_scheduled because it's not needed for two reasons:
|
|
|
3fc286 |
1. populate_liststore and real_populate_liststore always run in the same thread
|
|
|
3fc286 |
2. if populate_liststore is called before real_populate_liststore is run, there
|
|
|
3fc286 |
is no need to schedule two calls two real_populate_liststore.
|
|
|
3fc286 |
|
|
|
3fc286 |
Close: https://bugs.launchpad.net/bugs/1646762
|
|
|
3fc286 |
---
|
|
|
3fc286 |
gedit/gedit-open-document-selector.c | 36 ++++++++++------------------
|
|
|
3fc286 |
1 file changed, 12 insertions(+), 24 deletions(-)
|
|
|
3fc286 |
|
|
|
3fc286 |
diff --git a/gedit/gedit-open-document-selector.c b/gedit/gedit-open-document-selector.c
|
|
|
3fc286 |
index 5389ef0bd..b3c1ed503 100644
|
|
|
3fc286 |
--- a/gedit/gedit-open-document-selector.c
|
|
|
3fc286 |
+++ b/gedit/gedit-open-document-selector.c
|
|
|
3fc286 |
@@ -24,77 +24,76 @@
|
|
|
3fc286 |
|
|
|
3fc286 |
#include <time.h>
|
|
|
3fc286 |
|
|
|
3fc286 |
#include <glib.h>
|
|
|
3fc286 |
#include <glib/gi18n.h>
|
|
|
3fc286 |
#include <gtk/gtk.h>
|
|
|
3fc286 |
|
|
|
3fc286 |
#include <glib/gstdio.h>
|
|
|
3fc286 |
#include <gio/gio.h>
|
|
|
3fc286 |
|
|
|
3fc286 |
#include "gedit-recent.h"
|
|
|
3fc286 |
#include "gedit-utils.h"
|
|
|
3fc286 |
#include "gedit-window.h"
|
|
|
3fc286 |
#include "gedit-debug.h"
|
|
|
3fc286 |
|
|
|
3fc286 |
struct _GeditOpenDocumentSelector
|
|
|
3fc286 |
{
|
|
|
3fc286 |
GtkBox parent_instance;
|
|
|
3fc286 |
|
|
|
3fc286 |
GeditWindow *window;
|
|
|
3fc286 |
GtkWidget *search_entry;
|
|
|
3fc286 |
|
|
|
3fc286 |
GtkWidget *open_button;
|
|
|
3fc286 |
GtkWidget *treeview;
|
|
|
3fc286 |
GtkListStore *liststore;
|
|
|
3fc286 |
GtkCellRenderer *name_renderer;
|
|
|
3fc286 |
GtkCellRenderer *path_renderer;
|
|
|
3fc286 |
GtkWidget *placeholder_box;
|
|
|
3fc286 |
GtkWidget *scrolled_window;
|
|
|
3fc286 |
|
|
|
3fc286 |
+ guint populate_listbox_id;
|
|
|
3fc286 |
+
|
|
|
3fc286 |
GdkRGBA name_label_color;
|
|
|
3fc286 |
PangoFontDescription *name_font;
|
|
|
3fc286 |
GdkRGBA path_label_color;
|
|
|
3fc286 |
PangoFontDescription *path_font;
|
|
|
3fc286 |
|
|
|
3fc286 |
GeditOpenDocumentSelectorStore *selector_store;
|
|
|
3fc286 |
GList *recent_items;
|
|
|
3fc286 |
GList *home_dir_items;
|
|
|
3fc286 |
GList *desktop_dir_items;
|
|
|
3fc286 |
GList *local_bookmarks_dir_items;
|
|
|
3fc286 |
GList *file_browser_root_items;
|
|
|
3fc286 |
GList *active_doc_dir_items;
|
|
|
3fc286 |
GList *current_docs_items;
|
|
|
3fc286 |
GList *all_items;
|
|
|
3fc286 |
-
|
|
|
3fc286 |
- guint populate_liststore_is_idle : 1;
|
|
|
3fc286 |
- guint populate_scheduled : 1;
|
|
|
3fc286 |
};
|
|
|
3fc286 |
|
|
|
3fc286 |
typedef enum
|
|
|
3fc286 |
{
|
|
|
3fc286 |
SELECTOR_TAG_NONE,
|
|
|
3fc286 |
SELECTOR_TAG_MATCH
|
|
|
3fc286 |
} SelectorTag;
|
|
|
3fc286 |
|
|
|
3fc286 |
enum
|
|
|
3fc286 |
{
|
|
|
3fc286 |
NAME_COLUMN,
|
|
|
3fc286 |
PATH_COLUMN,
|
|
|
3fc286 |
URI_COLUMN,
|
|
|
3fc286 |
N_COLUMNS
|
|
|
3fc286 |
};
|
|
|
3fc286 |
|
|
|
3fc286 |
enum
|
|
|
3fc286 |
{
|
|
|
3fc286 |
PROP_0,
|
|
|
3fc286 |
PROP_WINDOW,
|
|
|
3fc286 |
LAST_PROP
|
|
|
3fc286 |
};
|
|
|
3fc286 |
|
|
|
3fc286 |
static GParamSpec *properties[LAST_PROP];
|
|
|
3fc286 |
|
|
|
3fc286 |
enum
|
|
|
3fc286 |
{
|
|
|
3fc286 |
SELECTOR_FILE_ACTIVATED,
|
|
|
3fc286 |
LAST_SIGNAL
|
|
|
3fc286 |
};
|
|
|
3fc286 |
@@ -483,61 +482,60 @@ fileitem_list_remove_duplicates (GList *items)
|
|
|
3fc286 |
GList *l1;
|
|
|
3fc286 |
|
|
|
3fc286 |
if ((l1 = l->next) == NULL)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
break;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
l_uri = ((FileItem *)l->data)->uri;
|
|
|
3fc286 |
l1_uri = ((FileItem *)l1->data)->uri;
|
|
|
3fc286 |
if (g_strcmp0 (l_uri, l1_uri) == 0)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gedit_open_document_selector_free_fileitem_item ((FileItem *)l1->data);
|
|
|
3fc286 |
dummy_ptr = g_list_delete_link (items, l1);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
else
|
|
|
3fc286 |
{
|
|
|
3fc286 |
l = l->next;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
}
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
static gboolean
|
|
|
3fc286 |
real_populate_liststore (gpointer data)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
|
|
|
3fc286 |
GeditOpenDocumentSelectorStore *selector_store;
|
|
|
3fc286 |
GList *l;
|
|
|
3fc286 |
GList *filter_items = NULL;
|
|
|
3fc286 |
gchar *filter;
|
|
|
3fc286 |
GRegex *filter_regex = NULL;
|
|
|
3fc286 |
- selector->populate_liststore_is_idle = FALSE;
|
|
|
3fc286 |
|
|
|
3fc286 |
DEBUG_SELECTOR_TIMER_DECL
|
|
|
3fc286 |
DEBUG_SELECTOR_TIMER_NEW
|
|
|
3fc286 |
|
|
|
3fc286 |
gtk_list_store_clear (selector->liststore);
|
|
|
3fc286 |
|
|
|
3fc286 |
selector_store = selector->selector_store;
|
|
|
3fc286 |
filter = gedit_open_document_selector_store_get_filter (selector_store);
|
|
|
3fc286 |
if (filter && *filter != '\0')
|
|
|
3fc286 |
{
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: all lists\n", selector););
|
|
|
3fc286 |
|
|
|
3fc286 |
filter_items = fileitem_list_filter (selector->all_items, (const gchar *)filter);
|
|
|
3fc286 |
filter_items = g_list_sort_with_data (filter_items, (GCompareDataFunc)sort_items_by_mru, NULL);
|
|
|
3fc286 |
fileitem_list_remove_duplicates (filter_items);
|
|
|
3fc286 |
|
|
|
3fc286 |
filter_regex = g_regex_new (filter, G_REGEX_CASELESS, 0, NULL);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
else
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gint recent_limit;
|
|
|
3fc286 |
GList *recent_items;
|
|
|
3fc286 |
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: recent files list\n", selector););
|
|
|
3fc286 |
|
|
|
3fc286 |
recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
|
|
|
3fc286 |
|
|
|
3fc286 |
if (recent_limit > 0 )
|
|
|
3fc286 |
{
|
|
|
3fc286 |
recent_items = fileitem_list_filter (selector->recent_items, NULL);
|
|
|
3fc286 |
@@ -551,87 +549,79 @@ real_populate_liststore (gpointer data)
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
g_free (filter);
|
|
|
3fc286 |
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: length:%i\n",
|
|
|
3fc286 |
selector, g_list_length (filter_items)););
|
|
|
3fc286 |
|
|
|
3fc286 |
/* Show the placeholder if no results, show the treeview otherwise */
|
|
|
3fc286 |
gtk_widget_set_visible (selector->scrolled_window, (filter_items != NULL));
|
|
|
3fc286 |
gtk_widget_set_visible (selector->placeholder_box, (filter_items == NULL));
|
|
|
3fc286 |
|
|
|
3fc286 |
for (l = filter_items; l != NULL; l = l->next)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
FileItem *item;
|
|
|
3fc286 |
|
|
|
3fc286 |
item = l->data;
|
|
|
3fc286 |
create_row (selector, (const FileItem *)item, filter_regex);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
if (filter_regex)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
g_regex_unref (filter_regex);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
gedit_open_document_selector_free_file_items_list (filter_items);
|
|
|
3fc286 |
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: time:%lf\n\n",
|
|
|
3fc286 |
selector, DEBUG_SELECTOR_TIMER_GET););
|
|
|
3fc286 |
DEBUG_SELECTOR_TIMER_DESTROY
|
|
|
3fc286 |
|
|
|
3fc286 |
- if (selector->populate_scheduled)
|
|
|
3fc286 |
- {
|
|
|
3fc286 |
- selector->populate_scheduled = FALSE;
|
|
|
3fc286 |
- return G_SOURCE_CONTINUE;
|
|
|
3fc286 |
- }
|
|
|
3fc286 |
- else
|
|
|
3fc286 |
- {
|
|
|
3fc286 |
- return G_SOURCE_REMOVE;
|
|
|
3fc286 |
- }
|
|
|
3fc286 |
+ selector->populate_listbox_id = 0;
|
|
|
3fc286 |
+ return G_SOURCE_REMOVE;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
static void
|
|
|
3fc286 |
populate_liststore (GeditOpenDocumentSelector *selector)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
/* Populate requests are compressed */
|
|
|
3fc286 |
- if (selector->populate_liststore_is_idle)
|
|
|
3fc286 |
+ if (selector->populate_listbox_id != 0)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: idle\n", selector););
|
|
|
3fc286 |
-
|
|
|
3fc286 |
- selector->populate_scheduled = TRUE;
|
|
|
3fc286 |
return;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: scheduled\n", selector););
|
|
|
3fc286 |
-
|
|
|
3fc286 |
- selector->populate_liststore_is_idle = TRUE;
|
|
|
3fc286 |
- gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, real_populate_liststore, selector, NULL);
|
|
|
3fc286 |
+ selector->populate_listbox_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
|
|
|
3fc286 |
+ real_populate_liststore,
|
|
|
3fc286 |
+ selector,
|
|
|
3fc286 |
+ NULL);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
static gboolean
|
|
|
3fc286 |
on_treeview_key_press (GtkTreeView *treeview,
|
|
|
3fc286 |
GdkEventKey *event,
|
|
|
3fc286 |
GeditOpenDocumentSelector *selector)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
guint keyval;
|
|
|
3fc286 |
gboolean is_control_pressed;
|
|
|
3fc286 |
GtkTreeSelection *tree_selection;
|
|
|
3fc286 |
GtkTreePath *root_path;
|
|
|
3fc286 |
GdkModifierType modifiers;
|
|
|
3fc286 |
|
|
|
3fc286 |
if (gdk_event_get_keyval ((GdkEvent *)event, &keyval) == TRUE)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
tree_selection = gtk_tree_view_get_selection (treeview);
|
|
|
3fc286 |
root_path = gtk_tree_path_new_from_string ("0");
|
|
|
3fc286 |
|
|
|
3fc286 |
modifiers = gtk_accelerator_get_default_mod_mask ();
|
|
|
3fc286 |
is_control_pressed = (event->state & modifiers) == GDK_CONTROL_MASK;
|
|
|
3fc286 |
|
|
|
3fc286 |
if ((keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up) &&
|
|
|
3fc286 |
!is_control_pressed)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
if (gtk_tree_selection_path_is_selected (tree_selection, root_path))
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gtk_tree_selection_unselect_all (tree_selection);
|
|
|
3fc286 |
gtk_widget_grab_focus (selector->search_entry);
|
|
|
3fc286 |
|
|
|
3fc286 |
return GDK_EVENT_STOP;
|
|
|
3fc286 |
@@ -683,66 +673,64 @@ on_entry_activated (GtkEntry *entry,
|
|
|
3fc286 |
uri = g_strconcat ("file://", entry_text, NULL);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
}
|
|
|
3fc286 |
else
|
|
|
3fc286 |
{
|
|
|
3fc286 |
g_free (scheme);
|
|
|
3fc286 |
uri = g_strdup (entry_text);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
file = g_file_new_for_uri (uri);
|
|
|
3fc286 |
if (g_file_query_exists (file, NULL))
|
|
|
3fc286 |
{
|
|
|
3fc286 |
DEBUG_SELECTOR (g_print ("Selector(%p): search entry activated : loading '%s'\n",
|
|
|
3fc286 |
selector, uri););
|
|
|
3fc286 |
|
|
|
3fc286 |
gtk_entry_set_text (entry, "");
|
|
|
3fc286 |
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->treeview));
|
|
|
3fc286 |
gtk_tree_selection_unselect_all (selection);
|
|
|
3fc286 |
|
|
|
3fc286 |
g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
g_object_unref (file);
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
static void
|
|
|
3fc286 |
gedit_open_document_selector_dispose (GObject *object)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
|
|
|
3fc286 |
|
|
|
3fc286 |
- while (TRUE)
|
|
|
3fc286 |
+ if (selector->populate_listbox_id != 0)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
- if (!g_idle_remove_by_data (selector))
|
|
|
3fc286 |
- {
|
|
|
3fc286 |
- break;
|
|
|
3fc286 |
- }
|
|
|
3fc286 |
+ g_source_remove (selector->populate_listbox_id);
|
|
|
3fc286 |
+ selector->populate_listbox_id = 0;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
g_clear_pointer (&selector->name_font, pango_font_description_free);
|
|
|
3fc286 |
g_clear_pointer (&selector->path_font, pango_font_description_free);
|
|
|
3fc286 |
|
|
|
3fc286 |
if (selector->recent_items)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gedit_open_document_selector_free_file_items_list (selector->recent_items);
|
|
|
3fc286 |
selector->recent_items = NULL;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
if (selector->home_dir_items)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gedit_open_document_selector_free_file_items_list (selector->home_dir_items);
|
|
|
3fc286 |
selector->home_dir_items = NULL;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
if (selector->desktop_dir_items)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gedit_open_document_selector_free_file_items_list (selector->desktop_dir_items);
|
|
|
3fc286 |
selector->desktop_dir_items = NULL;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
if (selector->local_bookmarks_dir_items)
|
|
|
3fc286 |
{
|
|
|
3fc286 |
gedit_open_document_selector_free_file_items_list (selector->local_bookmarks_dir_items);
|
|
|
3fc286 |
selector->local_bookmarks_dir_items = NULL;
|
|
|
3fc286 |
}
|
|
|
3fc286 |
|
|
|
3fc286 |
if (selector->file_browser_root_items)
|
|
|
3fc286 |
--
|
|
|
3fc286 |
2.25.1
|
|
|
3fc286 |
|