summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbkma <[email protected]>2021-02-10 12:02:25 +0100
committerraveit65 <[email protected]>2021-03-02 22:19:58 +0100
commitc0c513f3ef7e7ea432e799d8a5e10cfe94d38908 (patch)
treee4b7840617c282855884bd3fac3c1c1313cb68fa
parent814ae9fdeb8367d0f5b43a4691b32a514cf3e6e9 (diff)
downloadpluma-c0c513f3ef7e7ea432e799d8a5e10cfe94d38908.tar.bz2
pluma-c0c513f3ef7e7ea432e799d8a5e10cfe94d38908.tar.xz
Introduce PlumaWindowActivatable, PlumaAppActivatable, PlumaViewActivatable
These interfaces are for extensions that should be activated against a window/app/view. Backport from - https://gitlab.gnome.org/GNOME/gedit/-/commit/4fe7161560941ae1aa42165ff4d71121ad6f67b9 - https://gitlab.gnome.org/GNOME/gedit/-/commit/56a790a6851ebc98766cc4aca27cb32dde1b41bf - https://gitlab.gnome.org/GNOME/gedit/-/commit/210ed41e48988646203fc94eba19ce94657821cd In pluma-app.c we use gtk_main_quit instead of app object unref when last window closed. Plugin engine finalization calls app_get_default which reconstructs the app object. Before that was reasonably ok because it didn't really do anything, but now the app does stuff in 'init'. See https://gitlab.gnome.org/GNOME/gedit/-/commit/90c9889a4a31fbebfa042c5d2c64bb2b05160b10
-rw-r--r--pluma/Makefile.am23
-rw-r--r--pluma/pluma-app-activatable.c105
-rw-r--r--pluma/pluma-app-activatable.h60
-rw-r--r--pluma/pluma-app.c53
-rw-r--r--pluma/pluma-view-activatable.c93
-rw-r--r--pluma/pluma-view-activatable.h59
-rw-r--r--pluma/pluma-view.c101
-rw-r--r--pluma/pluma-window-activatable.c114
-rw-r--r--pluma/pluma-window-activatable.h61
-rw-r--r--pluma/pluma-window.c29
10 files changed, 666 insertions, 32 deletions
diff --git a/pluma/Makefile.am b/pluma/Makefile.am
index 1dc9403c..28c869f0 100644
--- a/pluma/Makefile.am
+++ b/pluma/Makefile.am
@@ -8,7 +8,7 @@ noinst_LTLIBRARIES = libpluma.la
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(srcdir) \
- -I$(srcdir)/mate-submodules/libegg \
+ -I$(srcdir)/mate-submodules/libegg \
$(PLUMA_CFLAGS) \
$(WARN_CFLAGS) \
$(INTROSPECTION_CFLAGS) \
@@ -65,6 +65,7 @@ NOINST_H_FILES = \
INST_H_FILES = \
pluma-app.h \
+ pluma-app-activatable.h \
pluma-commands.h \
pluma-debug.h \
pluma-document.h \
@@ -82,7 +83,9 @@ INST_H_FILES = \
pluma-tab.h \
pluma-utils.h \
pluma-view.h \
- pluma-window.h
+ pluma-view-activatable.h \
+ pluma-window.h \
+ pluma-window-activatable.h
if !ENABLE_GVFS_METADATA
INST_H_FILES += pluma-metadata-manager.h
@@ -95,6 +98,7 @@ header_DATA = \
libpluma_c_files = \
pluma-app.c \
+ pluma-app-activatable.c \
pluma-close-button.c \
pluma-commands-documents.c \
pluma-commands-edit.c \
@@ -138,12 +142,16 @@ libpluma_c_files = \
pluma-tab-label.c \
pluma-utils.c \
pluma-view.c \
+ pluma-view-activatable.c \
pluma-window.c \
+ pluma-window-activatable.c \
plumatextregion.c
+nodist_libpluma_la_SOURCES = \
+ $(BUILT_SOURCES)
+
libpluma_la_SOURCES = \
$(libpluma_c_files) \
- $(BUILT_SOURCES) \
$(BACON_FILES) \
$(POSIXIO_FILES) \
$(NOINST_H_FILES) \
@@ -187,11 +195,11 @@ INTROSPECTION_GIRS = Pluma-1.0.gir
INTROSPECTION_SCANNER_ARGS = -I$(top_srcdir) --warn-all
Pluma-1.0.gir: pluma
-Pluma_1_0_gir_INCLUDES = Gtk-3.0 GtkSource-3.0
-Pluma_1_0_gir_FILES = $(INST_H_FILES) $(libpluma_c_files) $(BUILT_SOURCES)
+Pluma_1_0_gir_NAMESPACE = Pluma
Pluma_1_0_gir_VERSION = 1.0
Pluma_1_0_gir_PROGRAM = $(builddir)/pluma
-Pluma_1_0_gir_NAMESPACE = Pluma
+Pluma_1_0_gir_FILES = $(INST_H_FILES) $(libpluma_c_files) $(BUILT_SOURCES)
+Pluma_1_0_gir_INCLUDES = Gtk-3.0 GtkSource-3.0
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
@@ -202,9 +210,6 @@ typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(gir_DATA) $(typelib_DATA)
endif
-dist-hook:
- cd $(distdir); rm -f $(BUILT_SOURCES)
-
BACON_DIR=$(srcdir)/../../libbacon/src/
BACON_FILES=bacon-message-connection.h bacon-message-connection.c
diff --git a/pluma/pluma-app-activatable.c b/pluma/pluma-app-activatable.c
new file mode 100644
index 00000000..3d68d9fe
--- /dev/null
+++ b/pluma/pluma-app-activatable.c
@@ -0,0 +1,105 @@
+/*
+ * pluma-app-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ * Copyright (C) 2010 Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#include <config.h>
+
+#include "pluma-app-activatable.h"
+#include "pluma-app.h"
+
+/**
+ * SECTION:pluma-app-activatable
+ * @short_description: Interface for activatable extensions on apps
+ * @see_also: #PeasExtensionSet
+ *
+ * #PlumaAppActivatable is an interface which should be implemented by
+ * extensions that should be activated on a pluma application.
+ **/
+
+G_DEFINE_INTERFACE(PlumaAppActivatable, pluma_app_activatable, G_TYPE_OBJECT)
+
+void
+pluma_app_activatable_default_init (PlumaAppActivatableInterface *iface)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized)
+ {
+ /**
+ * PlumaAppActivatable:app:
+ *
+ * The app property contains the pluma app for this
+ * #PlumaAppActivatable instance.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("app",
+ "App",
+ "The pluma app",
+ PLUMA_TYPE_APP,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ initialized = TRUE;
+ }
+}
+
+/**
+ * pluma_app_activatable_activate:
+ * @activatable: A #PlumaAppActivatable.
+ *
+ * Activates the extension on the application.
+ */
+void
+pluma_app_activatable_activate (PlumaAppActivatable *activatable)
+{
+ PlumaAppActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_APP_ACTIVATABLE (activatable));
+
+ iface = PLUMA_APP_ACTIVATABLE_GET_IFACE (activatable);
+
+ if (iface->activate != NULL)
+ {
+ iface->activate (activatable);
+ }
+}
+
+/**
+ * pluma_app_activatable_deactivate:
+ * @activatable: A #PlumaAppActivatable.
+ *
+ * Deactivates the extension from the application.
+ *
+ */
+void
+pluma_app_activatable_deactivate (PlumaAppActivatable *activatable)
+{
+ PlumaAppActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_APP_ACTIVATABLE (activatable));
+
+ iface = PLUMA_APP_ACTIVATABLE_GET_IFACE (activatable);
+
+ if (iface->deactivate != NULL)
+ {
+ iface->deactivate (activatable);
+ }
+}
diff --git a/pluma/pluma-app-activatable.h b/pluma/pluma-app-activatable.h
new file mode 100644
index 00000000..0362f546
--- /dev/null
+++ b/pluma/pluma-app-activatable.h
@@ -0,0 +1,60 @@
+/*
+ * pluma-app-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 - Steve Frécinaux
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#ifndef __PLUMA_APP_ACTIVATABLE_H__
+#define __PLUMA_APP_ACTIVATABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define PLUMA_TYPE_APP_ACTIVATABLE (pluma_app_activatable_get_type ())
+#define PLUMA_APP_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLUMA_TYPE_APP_ACTIVATABLE, PlumaAppActivatable))
+#define PLUMA_APP_ACTIVATABLE_IFACE(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), PLUMA_TYPE_APP_ACTIVATABLE, PlumaAppActivatableInterface))
+#define PLUMA_IS_APP_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLUMA_TYPE_APP_ACTIVATABLE))
+#define PLUMA_APP_ACTIVATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PLUMA_TYPE_APP_ACTIVATABLE, PlumaAppActivatableInterface))
+
+typedef struct _PlumaAppActivatable PlumaAppActivatable; /* dummy typedef */
+typedef struct _PlumaAppActivatableInterface PlumaAppActivatableInterface;
+
+struct _PlumaAppActivatableInterface
+{
+ GTypeInterface g_iface;
+
+ /* Virtual public methods */
+ void (*activate) (PlumaAppActivatable *activatable);
+ void (*deactivate) (PlumaAppActivatable *activatable);
+};
+
+/*
+ * Public methods
+ */
+GType pluma_app_activatable_get_type (void) G_GNUC_CONST;
+
+void pluma_app_activatable_activate (PlumaAppActivatable *activatable);
+void pluma_app_activatable_deactivate (PlumaAppActivatable *activatable);
+
+G_END_DECLS
+
+#endif /* __PLUMA_APP_ACTIVATABLE_H__ */
diff --git a/pluma/pluma-app.c b/pluma/pluma-app.c
index 60ce9bac..ef4e3fe4 100644
--- a/pluma/pluma-app.c
+++ b/pluma/pluma-app.c
@@ -36,8 +36,10 @@
#include <unistd.h>
#include <glib/gi18n.h>
+#include <libpeas/peas-extension-set.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
+
#include "pluma-app.h"
#include "pluma-commands.h"
#include "pluma-notebook.h"
@@ -46,6 +48,8 @@
#include "pluma-enum-types.h"
#include "pluma-dirs.h"
#include "pluma-settings.h"
+#include "pluma-app-activatable.h"
+#include "pluma-plugins-engine.h"
#define PLUMA_PAGE_SETUP_FILE "pluma-page-setup"
#define PLUMA_PRINT_SETTINGS_FILE "pluma-print-settings"
@@ -68,6 +72,8 @@ struct _PlumaAppPrivate
GtkPrintSettings *print_settings;
GSettings *window_settings;
+
+ PeasExtensionSet *extensions;
};
G_DEFINE_TYPE_WITH_PRIVATE (PlumaApp, pluma_app, G_TYPE_OBJECT)
@@ -93,6 +99,7 @@ pluma_app_dispose (GObject *object)
PlumaApp *app = PLUMA_APP (object);
g_clear_object (&app->priv->window_settings);
+ g_clear_object (&app->priv->extensions);
G_OBJECT_CLASS (pluma_app_parent_class)->dispose (object);
}
@@ -338,6 +345,25 @@ save_print_settings (PlumaApp *app)
}
static void
+extension_added (PeasExtensionSet *extensions,
+ PeasPluginInfo *info,
+ PeasExtension *exten,
+ PlumaApp *app)
+{
+ peas_extension_call (exten, "activate");
+}
+
+static void
+extension_removed (PeasExtensionSet *extensions,
+ PeasPluginInfo *info,
+ PeasExtension *exten,
+ PlumaApp *app)
+{
+ peas_extension_call (exten, "deactivate");
+}
+
+
+static void
pluma_app_init (PlumaApp *app)
{
PlumaSettings *settings;
@@ -352,13 +378,23 @@ pluma_app_init (PlumaApp *app)
/* initial lockdown state */
app->priv->lockdown = pluma_settings_get_lockdown (settings);
-}
-static void
-app_weak_notify (gpointer data,
- GObject *where_the_app_was)
-{
- gtk_main_quit ();
+ app->priv->extensions = peas_extension_set_new (PEAS_ENGINE (pluma_plugins_engine_get_default ()),
+ PLUMA_TYPE_APP_ACTIVATABLE,
+ "app", app,
+ NULL);
+
+ g_signal_connect (app->priv->extensions,
+ "extension-added",
+ G_CALLBACK (extension_added),
+ app);
+
+ g_signal_connect (app->priv->extensions,
+ "extension-removed",
+ G_CALLBACK (extension_removed),
+ app);
+
+ peas_extension_set_call (app->priv->extensions, "activate");
}
/**
@@ -381,9 +417,6 @@ pluma_app_get_default (void)
g_object_add_weak_pointer (G_OBJECT (app),
(gpointer) &app);
- g_object_weak_ref (G_OBJECT (app),
- app_weak_notify,
- NULL);
return app;
}
@@ -460,7 +493,7 @@ window_destroy (PlumaWindow *window,
save_page_setup (app);
save_print_settings (app);
- g_object_unref (app);
+ gtk_main_quit ();
}
}
diff --git a/pluma/pluma-view-activatable.c b/pluma/pluma-view-activatable.c
new file mode 100644
index 00000000..ad29dee8
--- /dev/null
+++ b/pluma/pluma-view-activatable.c
@@ -0,0 +1,93 @@
+/*
+ * pluma-view-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#include <config.h>
+
+#include "pluma-view-activatable.h"
+#include "pluma-view.h"
+
+/**
+ * SECTION:pluma-view-activatable
+ * @short_description: Interface for activatable extensions on views
+ * @see_also: #PeasExtensionSet
+ *
+ * #PlumaViewActivatable is an interface which should be implemented by
+ * extensions that should be activated on a pluma view.
+ **/
+G_DEFINE_INTERFACE(PlumaViewActivatable, pluma_view_activatable, G_TYPE_OBJECT)
+
+void
+pluma_view_activatable_default_init (PlumaViewActivatableInterface *iface)
+{
+ /**
+ * PlumaViewActivatable:view:
+ *
+ * The window property contains the pluma window for this
+ * #PlumaViewActivatable instance.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("view",
+ "view",
+ "A pluma view",
+ PLUMA_TYPE_VIEW,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * pluma_view_activatable_activate:
+ * @activatable: A #PlumaViewActivatable.
+ *
+ * Activates the extension on the window property.
+ */
+void
+pluma_view_activatable_activate (PlumaViewActivatable *activatable)
+{
+ PlumaViewActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_VIEW_ACTIVATABLE (activatable));
+
+ iface = PLUMA_VIEW_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->activate != NULL)
+ {
+ iface->activate (activatable);
+ }
+}
+
+/**
+ * pluma_view_activatable_deactivate:
+ * @activatable: A #PlumaViewActivatable.
+ *
+ * Deactivates the extension on the window property.
+ */
+void
+pluma_view_activatable_deactivate (PlumaViewActivatable *activatable)
+{
+ PlumaViewActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_VIEW_ACTIVATABLE (activatable));
+
+ iface = PLUMA_VIEW_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->deactivate != NULL)
+ {
+ iface->deactivate (activatable);
+ }
+}
diff --git a/pluma/pluma-view-activatable.h b/pluma/pluma-view-activatable.h
new file mode 100644
index 00000000..4fc170c8
--- /dev/null
+++ b/pluma/pluma-view-activatable.h
@@ -0,0 +1,59 @@
+/*
+ * pluma-view-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 - Steve Frécinaux
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#ifndef __PLUMA_VIEW_ACTIVATABLE_H__
+#define __PLUMA_VIEW_ACTIVATABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define PLUMA_TYPE_VIEW_ACTIVATABLE (pluma_view_activatable_get_type ())
+#define PLUMA_VIEW_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLUMA_TYPE_VIEW_ACTIVATABLE, PlumaViewActivatable))
+#define PLUMA_VIEW_ACTIVATABLE_IFACE(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), PLUMA_TYPE_VIEW_ACTIVATABLE, PlumaViewActivatableInterface))
+#define PLUMA_IS_VIEW_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLUMA_TYPE_VIEW_ACTIVATABLE))
+#define PLUMA_VIEW_ACTIVATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PLUMA_TYPE_VIEW_ACTIVATABLE, PlumaViewActivatableInterface))
+
+typedef struct _PlumaViewActivatable PlumaViewActivatable; /* dummy typedef */
+typedef struct _PlumaViewActivatableInterface PlumaViewActivatableInterface;
+
+struct _PlumaViewActivatableInterface
+{
+ GTypeInterface g_iface;
+
+ /* Virtual public methods */
+ void (*activate) (PlumaViewActivatable *activatable);
+ void (*deactivate) (PlumaViewActivatable *activatable);
+};
+
+/*
+ * Public methods
+ */
+GType pluma_view_activatable_get_type (void) G_GNUC_CONST;
+
+void pluma_view_activatable_activate (PlumaViewActivatable *activatable);
+void pluma_view_activatable_deactivate (PlumaViewActivatable *activatable);
+
+G_END_DECLS
+
+#endif /* __PLUMA_VIEW_ACTIVATABLE_H__ */
diff --git a/pluma/pluma-view.c b/pluma/pluma-view.c
index dfeb9154..d09599a7 100644
--- a/pluma/pluma-view.c
+++ b/pluma/pluma-view.c
@@ -39,10 +39,13 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
+#include <libpeas/peas-extension-set.h>
#include <glib/gi18n.h>
#include "pluma-view.h"
+#include "pluma-view-activatable.h"
+#include "pluma-plugins-engine.h"
#include "pluma-debug.h"
#include "pluma-pango.h"
#include "pluma-utils.h"
@@ -101,22 +104,29 @@ struct _PlumaViewPrivate
GtkCssProvider *css_provider;
PangoFontDescription *font_desc;
+
+ PeasExtensionSet *extensions;
};
/* The search entry completion is shared among all the views */
GtkListStore *search_completion_model = NULL;
static void pluma_view_dispose (GObject *object);
+
static void pluma_view_finalize (GObject *object);
+
static gint pluma_view_focus_out (GtkWidget *widget,
GdkEventFocus *event);
+
static gboolean pluma_view_scroll_event (GtkWidget *widget,
GdkEventScroll *event);
+
static gboolean pluma_view_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint timestamp);
+
static void pluma_view_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
@@ -124,21 +134,30 @@ static void pluma_view_drag_data_received (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint timestamp);
+
static gboolean pluma_view_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint timestamp);
+static void pluma_view_realize (GtkWidget *widget);
+
+static void pluma_view_unrealize (GtkWidget *widget);
+
static gboolean pluma_view_button_press_event (GtkWidget *widget,
GdkEventButton *event);
+
static gboolean pluma_view_button_release_event (GtkWidget *widget,
GdkEventButton *event);
+
static void pluma_view_populate_popup (GtkTextView *text_view,
GtkWidget *widget);
static gboolean start_interactive_search (PlumaView *view);
+
static gboolean start_interactive_goto_line (PlumaView *view);
+
static gboolean reset_searched_text (PlumaView *view);
static void hide_search_window (PlumaView *view,
@@ -146,6 +165,7 @@ static void hide_search_window (PlumaView *view,
static gboolean pluma_view_draw (GtkWidget *widget,
cairo_t *cr);
+
static void search_highlight_updated_cb (PlumaDocument *doc,
GtkTextIter *start,
GtkTextIter *end,
@@ -251,6 +271,10 @@ pluma_view_class_init (PlumaViewClass *klass)
widget_class->drag_drop = pluma_view_drag_drop;
widget_class->button_press_event = pluma_view_button_press_event;
widget_class->button_release_event = pluma_view_button_release_event;
+
+ widget_class->realize = pluma_view_realize;
+ widget_class->unrealize = pluma_view_unrealize;
+
text_view_class->populate_popup = pluma_view_populate_popup;
klass->start_interactive_search = start_interactive_search;
klass->start_interactive_goto_line = start_interactive_goto_line;
@@ -388,6 +412,11 @@ on_notify_buffer_cb (PlumaView *view,
"search_highlight_updated",
G_CALLBACK (search_highlight_updated_cb),
view);
+
+ /* We only activate the extensions when the right buffer is set,
+ * because most plugins will expect this behaviour, and we won't
+ * change the buffer later anyway. */
+ peas_extension_set_call (view->priv->extensions, "activate", view);
}
#ifdef GTK_SOURCE_VERSION_3_24
@@ -578,6 +607,12 @@ pluma_view_init (PlumaView *view)
if (tl != NULL)
gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
+ view->priv->extensions =
+ peas_extension_set_new (PEAS_ENGINE (pluma_plugins_engine_get_default ()),
+ PLUMA_TYPE_VIEW_ACTIVATABLE,
+ "view", view,
+ NULL);
+
/* Act on buffer change */
g_signal_connect (view,
"notify::buffer",
@@ -592,6 +627,12 @@ pluma_view_dispose (GObject *object)
view = PLUMA_VIEW (object);
+ if (view->priv->extensions != NULL)
+ {
+ g_object_unref (view->priv->extensions);
+ view->priv->extensions = NULL;
+ }
+
if (view->priv->search_window != NULL)
{
gtk_widget_destroy (view->priv->search_window);
@@ -1281,6 +1322,66 @@ search_window_button_press_event (GtkWidget *widget,
}
static void
+extension_added (PeasExtensionSet *extensions,
+ PeasPluginInfo *info,
+ PeasExtension *exten,
+ PlumaView *view)
+{
+ pluma_view_activatable_activate (PLUMA_VIEW_ACTIVATABLE (exten));
+}
+
+static void
+extension_removed (PeasExtensionSet *extensions,
+ PeasPluginInfo *info,
+ PeasExtension *exten,
+ PlumaView *view)
+{
+ pluma_view_activatable_deactivate (PLUMA_VIEW_ACTIVATABLE (exten));
+}
+
+static void
+pluma_view_realize (GtkWidget *widget)
+{
+ PlumaView *view = PLUMA_VIEW (widget);
+
+ GTK_WIDGET_CLASS (pluma_view_parent_class)->realize (widget);
+
+ g_signal_connect (view->priv->extensions,
+ "extension-added",
+ G_CALLBACK (extension_added),
+ view);
+ g_signal_connect (view->priv->extensions,
+ "extension-removed",
+ G_CALLBACK (extension_removed),
+ view);
+
+ /* We only activate the extensions when the view is realized,
+ * because most plugins will expect this behaviour, and we won't
+ * change the buffer later anyway. */
+ peas_extension_set_foreach (view->priv->extensions,
+ (PeasExtensionSetForeachFunc) extension_added,
+ view);
+}
+
+static void
+pluma_view_unrealize (GtkWidget *widget)
+{
+ PlumaView *view = PLUMA_VIEW (widget);
+
+ g_signal_handlers_disconnect_by_func (view->priv->extensions, extension_added, view);
+ g_signal_handlers_disconnect_by_func (view->priv->extensions, extension_removed, view);
+
+ /* We need to deactivate the extension on unrealize because it is not
+ mandatory that a view has been realized when we dispose it, leading
+ to deactivating the plugin without being activated */
+ peas_extension_set_foreach (view->priv->extensions,
+ (PeasExtensionSetForeachFunc) extension_removed,
+ view);
+
+ GTK_WIDGET_CLASS (pluma_view_parent_class)->unrealize (widget);
+}
+
+static void
search_again (PlumaView *view,
gboolean search_backward)
{
diff --git a/pluma/pluma-window-activatable.c b/pluma/pluma-window-activatable.c
new file mode 100644
index 00000000..74597b2a
--- /dev/null
+++ b/pluma/pluma-window-activatable.c
@@ -0,0 +1,114 @@
+/*
+ * pluma-window-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#include <config.h>
+
+#include "pluma-window-activatable.h"
+#include "pluma-window.h"
+
+/**
+ * SECTION:pluma-window-activatable
+ * @short_description: Interface for activatable extensions on windows
+ * @see_also: #PeasExtensionSet
+ *
+ * #PlumaWindowActivatable is an interface which should be implemented by
+ * extensions that should be activated on a pluma main window.
+ **/
+G_DEFINE_INTERFACE(PlumaWindowActivatable, pluma_window_activatable, G_TYPE_OBJECT)
+
+void
+pluma_window_activatable_default_init (PlumaWindowActivatableInterface *iface)
+{
+ /**
+ * PlumaWindowActivatable:window:
+ *
+ * The window property contains the pluma window for this
+ * #PlumaWindowActivatable instance.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("window",
+ "Window",
+ "The pluma window",
+ PLUMA_TYPE_WINDOW,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * pluma_window_activatable_activate:
+ * @activatable: A #PlumaWindowActivatable.
+ *
+ * Activates the extension on the window property.
+ */
+void
+pluma_window_activatable_activate (PlumaWindowActivatable *activatable)
+{
+ PlumaWindowActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_WINDOW_ACTIVATABLE (activatable));
+
+ iface = PLUMA_WINDOW_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->activate != NULL)
+ {
+ iface->activate (activatable);
+ }
+}
+
+/**
+ * pluma_window_activatable_deactivate:
+ * @activatable: A #PlumaWindowActivatable.
+ *
+ * Deactivates the extension on the window property.
+ */
+void
+pluma_window_activatable_deactivate (PlumaWindowActivatable *activatable)
+{
+ PlumaWindowActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_WINDOW_ACTIVATABLE (activatable));
+
+ iface = PLUMA_WINDOW_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->deactivate != NULL)
+ {
+ iface->deactivate (activatable);
+ }
+}
+
+/**
+ * pluma_window_activatable_update_state:
+ * @activatable: A #PlumaWindowActivatable.
+ *
+ * Triggers an update of the extension insternal state to take into account
+ * state changes in the window state, due to some event or user action.
+ */
+void
+pluma_window_activatable_update_state (PlumaWindowActivatable *activatable)
+{
+ PlumaWindowActivatableInterface *iface;
+
+ g_return_if_fail (PLUMA_IS_WINDOW_ACTIVATABLE (activatable));
+
+ iface = PLUMA_WINDOW_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->update_state != NULL)
+ {
+ iface->update_state (activatable);
+ }
+}
diff --git a/pluma/pluma-window-activatable.h b/pluma/pluma-window-activatable.h
new file mode 100644
index 00000000..de95b05d
--- /dev/null
+++ b/pluma/pluma-window-activatable.h
@@ -0,0 +1,61 @@
+/*
+ * pluma-window-activatable.h
+ * This file is part of pluma
+ *
+ * Copyright (C) 2010 - Steve Frécinaux
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/.
+ */
+
+#ifndef __PLUMA_WINDOW_ACTIVATABLE_H__
+#define __PLUMA_WINDOW_ACTIVATABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define PLUMA_TYPE_WINDOW_ACTIVATABLE (pluma_window_activatable_get_type ())
+#define PLUMA_WINDOW_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLUMA_TYPE_WINDOW_ACTIVATABLE, PlumaWindowActivatable))
+#define PLUMA_WINDOW_ACTIVATABLE_IFACE(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), PLUMA_TYPE_WINDOW_ACTIVATABLE, PlumaWindowActivatableInterface))
+#define PLUMA_IS_WINDOW_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLUMA_TYPE_WINDOW_ACTIVATABLE))
+#define PLUMA_WINDOW_ACTIVATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PLUMA_TYPE_WINDOW_ACTIVATABLE, PlumaWindowActivatableInterface))
+
+typedef struct _PlumaWindowActivatable PlumaWindowActivatable; /* dummy typedef */
+typedef struct _PlumaWindowActivatableInterface PlumaWindowActivatableInterface;
+
+struct _PlumaWindowActivatableInterface
+{
+ GTypeInterface g_iface;
+
+ /* Virtual public methods */
+ void (*activate) (PlumaWindowActivatable *activatable);
+ void (*deactivate) (PlumaWindowActivatable *activatable);
+ void (*update_state) (PlumaWindowActivatable *activatable);
+};
+
+/*
+ * Public methods
+ */
+GType pluma_window_activatable_get_type (void) G_GNUC_CONST;
+
+void pluma_window_activatable_activate (PlumaWindowActivatable *activatable);
+void pluma_window_activatable_deactivate (PlumaWindowActivatable *activatable);
+void pluma_window_activatable_update_state (PlumaWindowActivatable *activatable);
+
+G_END_DECLS
+
+#endif /* __PLUMA_WINDOW_ACTIVATABLE_H__ */
diff --git a/pluma/pluma-window.c b/pluma/pluma-window.c
index 337af89c..e797b6e0 100644
--- a/pluma/pluma-window.c
+++ b/pluma/pluma-window.c
@@ -41,7 +41,6 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
-#include <libpeas/peas-activatable.h>
#include <libpeas/peas-extension-set.h>
#include "pluma-ui.h"
@@ -57,6 +56,7 @@
#include "pluma-panel.h"
#include "pluma-documents-panel.h"
#include "pluma-plugins-engine.h"
+#include "pluma-window-activatable.h"
#include "pluma-enum-types.h"
#include "pluma-dirs.h"
#include "pluma-status-combo-box.h"
@@ -919,7 +919,7 @@ set_sensitivity_according_to_tab (PlumaWindow *window,
update_next_prev_doc_sensitivity (window, tab);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static void
@@ -2771,7 +2771,7 @@ sync_name (PlumaTab *tab,
g_free (escaped_name);
g_free (tip);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static PlumaWindow *
@@ -3167,7 +3167,7 @@ selection_changed (PlumaDocument *doc,
editable &&
gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)));
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static void
@@ -3176,7 +3176,7 @@ sync_languages_menu (PlumaDocument *doc,
PlumaWindow *window)
{
update_languages_menu (window);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static void
@@ -3188,7 +3188,7 @@ readonly_changed (PlumaDocument *doc,
sync_name (window->priv->active_tab, NULL, window);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static void
@@ -3196,7 +3196,7 @@ editable_changed (PlumaView *view,
GParamSpec *arg1,
PlumaWindow *window)
{
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
static void
@@ -3408,7 +3408,7 @@ notebook_tab_removed (PlumaNotebook *notebook,
if (window->priv->num_tabs == 0)
{
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ peas_extension_set_call (window->priv->extensions, "update_state");
}
update_window_state (window);
@@ -4096,9 +4096,10 @@ pluma_window_init (PlumaWindow *window)
pluma_debug_message (DEBUG_WINDOW, "Update plugins ui");
window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (pluma_plugins_engine_get_default ()),
- PEAS_TYPE_ACTIVATABLE, "object", window, NULL);
-
- peas_extension_set_call (window->priv->extensions, "activate");
+ PLUMA_TYPE_WINDOW_ACTIVATABLE,
+ "window",
+ window,
+ NULL);
g_signal_connect (window->priv->extensions,
"extension-added",
@@ -4109,8 +4110,10 @@ pluma_window_init (PlumaWindow *window)
G_CALLBACK (on_extension_removed),
window);
- /* set visibility of panes.
- * This needs to be done after plugins activatation */
+ peas_extension_set_call (window->priv->extensions, "activate");
+
+ /* set visibility of panes.
+ This needs to be done after plugins activatation */
init_panels_visibility (window);
update_sensitivity_according_to_open_tabs (window);