[gnome-builder/wip/plugins] terminal: add very basic terminal to bottom pane



commit fe90bc8ca8b84d17e47093c1a11d2f409440eae1
Author: Christian Hergert <christian hergert me>
Date:   Tue Jun 9 01:52:29 2015 -0700

    terminal: add very basic terminal to bottom pane
    
    We should make GbTerminal a GbView so that it can be use in the document
    area as well.

 configure.ac                               |    5 +-
 data/keybindings/shared.css                |    9 +
 plugins/Makefile.am                        |    1 +
 plugins/terminal/Makefile.am               |   42 ++++
 plugins/terminal/gb-terminal-addin.c       |  154 +++++++++++++
 plugins/terminal/gb-terminal-addin.h       |   32 +++
 plugins/terminal/gb-terminal.c             |  342 ++++++++++++++++++++++++++++
 plugins/terminal/gb-terminal.gresource.xml |    7 +
 plugins/terminal/gb-terminal.h             |   32 +++
 plugins/terminal/gb-terminal.plugin        |    6 +
 plugins/terminal/gb-terminal.ui            |   19 ++
 src/Makefile.am                            |    1 +
 src/workbench/gb-workbench.c               |    2 +-
 13 files changed, 650 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index df957de..0ef9ff5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,13 +146,15 @@ m4_define([pygobject_required_version], [3.0.0])
 m4_define([devhelp_required_version], [3.16.0])
 m4_define([libxml_required_version], [2.9.0])
 m4_define([peas_required_version], [1.14.1])
+m4_define([vte_required_version], [0.40.2])
 
 PKG_CHECK_MODULES(BUILDER,  [gtk+-3.0 >= gtk_required_version
                              gio-2.0 >= glib_required_version
                              gtksourceview-3.0 >= gtksourceview_required_version
                              libdevhelp-3.0 >= devhelp_required_version
                              libgit2-glib-1.0 >= ggit_required_version
-                             libpeas-1.0 >= peas_required_version])
+                             libpeas-1.0 >= peas_required_version
+                            vte-2.91 >= vte_required_version])
 PKG_CHECK_MODULES(EGG,      [glib-2.0 >= glib_required_version
                              gtk+-3.0 >= gtk_required_version])
 PKG_CHECK_MODULES(LIBIDE,   [gio-2.0 >= glib_required_version
@@ -382,6 +384,7 @@ AC_CONFIG_FILES([
        plugins/devhelp/Makefile
        plugins/symbol-tree/Makefile
        plugins/sysmon/Makefile
+       plugins/terminal/Makefile
 
        data/Makefile
        data/gsettings/Makefile
diff --git a/data/keybindings/shared.css b/data/keybindings/shared.css
index 88bc1bb..bd3973e 100644
--- a/data/keybindings/shared.css
+++ b/data/keybindings/shared.css
@@ -7,3 +7,12 @@
   bind "<ctrl>KP_Enter" { "action" ("win", "show-command-bar", "") };
 }
 
+ binding-set builder-vte-terminal
+{
+  bind "<ctrl><shift>c" { "copy-clipboard" () };
+  bind "<ctrl><shift>v" { "paste-clipboard" () };
+}
+
+VteTerminal {
+  gtk-key-bindings: builder-vte-terminal;
+}
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 7a9a9ad..79f0d54 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -3,6 +3,7 @@ SUBDIRS = \
        devhelp \
        symbol-tree \
        sysmon \
+       terminal \
        $(NULL)
 
 -include $(top_srcdir)/git.mk
diff --git a/plugins/terminal/Makefile.am b/plugins/terminal/Makefile.am
new file mode 100644
index 0000000..0840660
--- /dev/null
+++ b/plugins/terminal/Makefile.am
@@ -0,0 +1,42 @@
+DISTCLEANFILES =
+BUILT_SOURCES =
+CLEANFILES =
+EXTRA_DIST =
+
+noinst_LTLIBRARIES = libterminal.la
+
+libterminal_la_SOURCES = \
+       gb-terminal.c \
+       gb-terminal.h \
+       gb-terminal-addin.c \
+       gb-terminal-addin.h \
+       $(NULL)
+
+nodist_libterminal_la_SOURCES = \
+       gb-terminal-resources.c \
+       gb-terminal-resources.h \
+       $(NULL)
+
+libterminal_la_CFLAGS = \
+       $(BUILDER_CFLAGS) \
+       -I$(top_srcdir)/libide \
+       -I$(top_srcdir)/src \
+       -I$(top_srcdir)/src/workbench \
+       -I$(top_srcdir)/src/workspace \
+       -I$(top_srcdir)/contrib/egg \
+       $(NULL)
+
+libterminal_la_LIBADD = \
+       $(BUILDER_LIBS) \
+       $(NULL)
+
+libterminal_la_LDFLAGS = -module
+
+glib_resources_c = gb-terminal-resources.c
+glib_resources_h = gb-terminal-resources.h
+glib_resources_xml = gb-terminal.gresource.xml
+glib_resources_namespace = gb_terminal
+include $(top_srcdir)/build/autotools/Makefile.am.gresources
+
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/terminal/gb-terminal-addin.c b/plugins/terminal/gb-terminal-addin.c
new file mode 100644
index 0000000..729d449
--- /dev/null
+++ b/plugins/terminal/gb-terminal-addin.c
@@ -0,0 +1,154 @@
+/* gb-terminal-addin.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "gb-plugins.h"
+#include "gb-terminal.h"
+#include "gb-terminal-addin.h"
+#include "gb-terminal-resources.h"
+#include "gb-workspace.h"
+
+struct _GbTerminalAddin
+{
+  GObject      parent_instance;
+
+  GbWorkbench *workbench;
+  GbTerminal  *panel_terminal;
+};
+
+static void workbench_addin_iface_init (GbWorkbenchAddinInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbTerminalAddin, gb_terminal_addin, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GB_TYPE_WORKBENCH_ADDIN,
+                                                workbench_addin_iface_init))
+
+enum {
+  PROP_0,
+  PROP_WORKBENCH,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static void
+gb_terminal_addin_load (GbWorkbenchAddin *addin)
+{
+  GbTerminalAddin *self = (GbTerminalAddin *)addin;
+  GbWorkspace *workspace;
+  GtkWidget *bottom_pane;
+
+  g_assert (GB_IS_TERMINAL_ADDIN (self));
+  g_assert (GB_IS_WORKBENCH (self->workbench));
+
+  if (self->panel_terminal == NULL)
+    {
+      self->panel_terminal = g_object_new (GB_TYPE_TERMINAL,
+                                           "visible", TRUE,
+                                           NULL);
+      g_object_add_weak_pointer (G_OBJECT (self->panel_terminal),
+                                 (gpointer *)&self->panel_terminal);
+    }
+
+  workspace = GB_WORKSPACE (gb_workbench_get_workspace (self->workbench));
+  bottom_pane = gb_workspace_get_bottom_pane (workspace);
+  gb_workspace_pane_add_page (GB_WORKSPACE_PANE (bottom_pane),
+                              GTK_WIDGET (self->panel_terminal),
+                              _("Terminal"),
+                              "utilities-terminal-symbolic");
+}
+
+static void
+gb_terminal_addin_unload (GbWorkbenchAddin *addin)
+{
+  GbTerminalAddin *self = (GbTerminalAddin *)addin;
+
+  g_assert (GB_IS_TERMINAL_ADDIN (self));
+
+  if (self->panel_terminal != NULL)
+    {
+      GtkWidget *parent;
+
+      parent = gtk_widget_get_parent (GTK_WIDGET (self->panel_terminal));
+      gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (self->panel_terminal));
+    }
+}
+
+static void
+gb_terminal_addin_finalize (GObject *object)
+{
+  GbTerminalAddin *self = (GbTerminalAddin *)object;
+
+  ide_clear_weak_pointer (&self->workbench);
+
+  G_OBJECT_CLASS (gb_terminal_addin_parent_class)->finalize (object);
+}
+
+static void
+gb_terminal_addin_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GbTerminalAddin *self = GB_TERMINAL_ADDIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_WORKBENCH:
+      ide_set_weak_pointer (&self->workbench, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_terminal_addin_class_init (GbTerminalAddinClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gb_terminal_addin_finalize;
+  object_class->set_property = gb_terminal_addin_set_property;
+
+  gParamSpecs [PROP_WORKBENCH] =
+    g_param_spec_object ("workbench",
+                         _("Workbench"),
+                         _("The workbench window."),
+                         GB_TYPE_WORKBENCH,
+                         (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+gb_terminal_addin_init (GbTerminalAddin *self)
+{
+}
+
+static void
+workbench_addin_iface_init (GbWorkbenchAddinInterface *iface)
+{
+  iface->load = gb_terminal_addin_load;
+  iface->unload = gb_terminal_addin_unload;
+}
+
+GB_DEFINE_EMBEDDED_PLUGIN (gb_terminal,
+                           gb_terminal_get_resource (),
+                           "resource:///org/gnome/builder/plugins/terminal/gb-terminal.plugin",
+                           GB_DEFINE_PLUGIN_TYPE (GB_TYPE_WORKBENCH_ADDIN, GB_TYPE_TERMINAL_ADDIN))
diff --git a/plugins/terminal/gb-terminal-addin.h b/plugins/terminal/gb-terminal-addin.h
new file mode 100644
index 0000000..2c26317
--- /dev/null
+++ b/plugins/terminal/gb-terminal-addin.h
@@ -0,0 +1,32 @@
+/* gb-terminal-addin.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_TERMINAL_ADDIN_H
+#define GB_TERMINAL_ADDIN_H
+
+#include "gb-workbench-addin.h"
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_TERMINAL_ADDIN (gb_terminal_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbTerminalAddin, gb_terminal_addin, GB, TERMINAL_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* GB_TERMINAL_ADDIN_H */
diff --git a/plugins/terminal/gb-terminal.c b/plugins/terminal/gb-terminal.c
new file mode 100644
index 0000000..96c0370
--- /dev/null
+++ b/plugins/terminal/gb-terminal.c
@@ -0,0 +1,342 @@
+/* gb-terminal.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <ide.h>
+#include <vte/vte.h>
+
+#include "gb-terminal.h"
+#include "gb-workbench.h"
+
+struct _GbTerminal
+{
+  GtkBin       parent_instance;
+
+  VteTerminal *terminal;
+
+  guint        has_spawned : 1;
+};
+
+G_DEFINE_TYPE (GbTerminal, gb_terminal, GTK_TYPE_BIN)
+
+enum {
+  PROP_0,
+  LAST_PROP
+};
+
+#if 0
+static GParamSpec *gParamSpecs [LAST_PROP];
+#endif
+
+static void
+gb_terminal_respawn (GbTerminal *self)
+{
+  g_autoptr(GPtrArray) args = NULL;
+  g_autofree gchar *workpath = NULL;
+  GtkWidget *toplevel;
+  GError *error = NULL;
+  IdeContext *context;
+  IdeVcs *vcs;
+  GFile *workdir;
+  GPid child_pid;
+
+  g_assert (GB_IS_TERMINAL (self));
+
+  vte_terminal_reset (self->terminal, TRUE, TRUE);
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+  if (!GB_IS_WORKBENCH (toplevel))
+    return;
+
+  context = gb_workbench_get_context (GB_WORKBENCH (toplevel));
+  vcs = ide_context_get_vcs (context);
+  workdir = ide_vcs_get_working_directory (vcs);
+  workpath = g_file_get_path (workdir);
+
+  args = g_ptr_array_new_with_free_func (g_free);
+  g_ptr_array_add (args, vte_get_user_shell ());
+  g_ptr_array_add (args, NULL);
+
+  vte_terminal_spawn_sync (self->terminal,
+                           VTE_PTY_DEFAULT | VTE_PTY_NO_LASTLOG | VTE_PTY_NO_UTMP | VTE_PTY_NO_WTMP,
+                           workpath,
+                           (gchar **)args->pdata,
+                           NULL,
+                           G_SPAWN_DEFAULT,
+                           NULL,
+                           NULL,
+                           &child_pid,
+                           NULL,
+                           &error);
+
+  if (error != NULL)
+    {
+      g_warning ("%s", error->message);
+      g_clear_error (&error);
+      return;
+    }
+
+  vte_terminal_watch_child (self->terminal, child_pid);
+}
+
+static void
+child_exited_cb (VteTerminal *terminal,
+                 gint         exit_status,
+                 GbTerminal  *self)
+{
+  g_assert (VTE_IS_TERMINAL (terminal));
+  g_assert (GB_IS_TERMINAL (self));
+
+  if (!gtk_widget_in_destruction (GTK_WIDGET (terminal)))
+    gb_terminal_respawn (self);
+}
+
+static void
+gb_terminal_realize (GtkWidget *widget)
+{
+  GbTerminal *self = (GbTerminal *)widget;
+
+  g_assert (GB_IS_TERMINAL (self));
+
+  GTK_WIDGET_CLASS (gb_terminal_parent_class)->realize (widget);
+
+  if (!self->has_spawned)
+    {
+      self->has_spawned = TRUE;
+      gb_terminal_respawn (self);
+    }
+}
+
+static void
+size_allocate_cb (VteTerminal   *terminal,
+                  GtkAllocation *alloc,
+                  GbTerminal    *self)
+{
+  glong width;
+  glong height;
+  glong columns;
+  glong rows;
+
+  g_assert (VTE_IS_TERMINAL (terminal));
+  g_assert (alloc != NULL);
+  g_assert (GB_IS_TERMINAL (self));
+
+  if ((alloc->width == 0) || (alloc->height == 0))
+    return;
+
+  width = vte_terminal_get_char_width (terminal);
+  height = vte_terminal_get_char_height (terminal);
+
+  if ((width == 0) || (height == 0))
+    return;
+
+  columns = alloc->width / width;
+  rows = alloc->height / height;
+
+  if ((columns < 2) || (rows < 2))
+    return;
+
+  vte_terminal_set_size (self->terminal, columns, rows);
+}
+
+static void
+gb_terminal_get_preferred_width (GtkWidget *widget,
+                                 gint      *min_width,
+                                 gint      *nat_width)
+{
+  /*
+   * Since we are placing the terminal in a GtkStack, we need
+   * to fake the size a bit. Otherwise, GtkStack tries to keep the
+   * widget at it's natural size (which prevents us from getting
+   * appropriate size requests.
+   */
+  GTK_WIDGET_CLASS (gb_terminal_parent_class)->get_preferred_width (widget, min_width, nat_width);
+  *nat_width = *min_width;
+}
+
+static void
+gb_terminal_get_preferred_height (GtkWidget *widget,
+                                  gint      *min_height,
+                                  gint      *nat_height)
+{
+  /*
+   * Since we are placing the terminal in a GtkStack, we need
+   * to fake the size a bit. Otherwise, GtkStack tries to keep the
+   * widget at it's natural size (which prevents us from getting
+   * appropriate size requests.
+   */
+  GTK_WIDGET_CLASS (gb_terminal_parent_class)->get_preferred_height (widget, min_height, nat_height);
+  *nat_height = *min_height;
+}
+
+static void
+gb_terminal_set_needs_attention (GbTerminal *self,
+                                 gboolean    needs_attention)
+{
+  GtkWidget *parent;
+
+  g_assert (GB_IS_TERMINAL (self));
+
+  parent = gtk_widget_get_parent (GTK_WIDGET (self));
+
+  if (GTK_IS_STACK (parent))
+    {
+      gtk_container_child_set (GTK_CONTAINER (parent), GTK_WIDGET (self),
+                               "needs-attention", !!needs_attention,
+                               NULL);
+    }
+}
+
+static void
+notification_received_cb (VteTerminal *terminal,
+                          const gchar *summary,
+                          const gchar *body,
+                          GbTerminal  *self)
+{
+  g_assert (VTE_IS_TERMINAL (terminal));
+  g_assert (GB_IS_TERMINAL (self));
+
+  g_print ("notification_received_cb: %s: %s\n", summary, body);
+
+  if (!gtk_widget_has_focus (GTK_WIDGET (terminal)))
+    gb_terminal_set_needs_attention (self, TRUE);
+}
+
+static gboolean
+focus_in_event_cb (VteTerminal *terminal,
+                   GdkEvent    *event,
+                   GbTerminal  *self)
+{
+  g_assert (VTE_IS_TERMINAL (terminal));
+  g_assert (GB_IS_TERMINAL (self));
+
+  gb_terminal_set_needs_attention (self, FALSE);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+focus_out_event_cb (VteTerminal *terminal,
+                    GdkEvent    *event,
+                    GbTerminal  *self)
+{
+  g_assert (VTE_IS_TERMINAL (terminal));
+  g_assert (GB_IS_TERMINAL (self));
+
+  gb_terminal_set_needs_attention (self, FALSE);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+gb_terminal_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gb_terminal_parent_class)->finalize (object);
+}
+
+static void
+gb_terminal_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_terminal_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_terminal_class_init (GbTerminalClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gb_terminal_finalize;
+  object_class->get_property = gb_terminal_get_property;
+  object_class->set_property = gb_terminal_set_property;
+
+  widget_class->realize = gb_terminal_realize;
+  widget_class->get_preferred_width = gb_terminal_get_preferred_width;
+  widget_class->get_preferred_height = gb_terminal_get_preferred_height;
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/plugins/terminal/gb-terminal.ui");
+  gtk_widget_class_bind_template_child (widget_class, GbTerminal, terminal);
+
+  g_type_ensure (VTE_TYPE_TERMINAL);
+}
+
+static void
+gb_terminal_init (GbTerminal *self)
+{
+  GQuark quark;
+  guint signal_id;
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (self->terminal,
+                           "size-allocate",
+                           G_CALLBACK (size_allocate_cb),
+                           self,
+                           0);
+
+  g_signal_connect_object (self->terminal,
+                           "child-exited",
+                           G_CALLBACK (child_exited_cb),
+                           self,
+                           0);
+
+  g_signal_connect_object (self->terminal,
+                           "focus-in-event",
+                           G_CALLBACK (focus_in_event_cb),
+                           self,
+                           0);
+
+  g_signal_connect_object (self->terminal,
+                           "focus-out-event",
+                           G_CALLBACK (focus_out_event_cb),
+                           self,
+                           0);
+
+  if (g_signal_parse_name ("notification-received",
+                           VTE_TYPE_TERMINAL,
+                           &signal_id,
+                           &quark,
+                           FALSE))
+    {
+      g_signal_connect_object (self->terminal,
+                               "notification-received",
+                               G_CALLBACK (notification_received_cb),
+                               self,
+                               0);
+    }
+}
diff --git a/plugins/terminal/gb-terminal.gresource.xml b/plugins/terminal/gb-terminal.gresource.xml
new file mode 100644
index 0000000..3cf8a00
--- /dev/null
+++ b/plugins/terminal/gb-terminal.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/builder/plugins/terminal">
+    <file>gb-terminal.plugin</file>
+    <file>gb-terminal.ui</file>
+  </gresource>
+</gresources>
diff --git a/plugins/terminal/gb-terminal.h b/plugins/terminal/gb-terminal.h
new file mode 100644
index 0000000..6519270
--- /dev/null
+++ b/plugins/terminal/gb-terminal.h
@@ -0,0 +1,32 @@
+/* gb-terminal.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_TERMINAL_H
+#define GB_TERMINAL_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_TERMINAL (gb_terminal_get_type())
+
+G_DECLARE_FINAL_TYPE (GbTerminal, gb_terminal, GB, TERMINAL, GtkBin)
+
+G_END_DECLS
+
+#endif /* GB_TERMINAL_H */
diff --git a/plugins/terminal/gb-terminal.plugin b/plugins/terminal/gb-terminal.plugin
new file mode 100644
index 0000000..e846153
--- /dev/null
+++ b/plugins/terminal/gb-terminal.plugin
@@ -0,0 +1,6 @@
+[Plugin]
+Module=terminal
+Name=Terminal
+Description=A terminal for Builder
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2015 Christian Hergert
diff --git a/plugins/terminal/gb-terminal.ui b/plugins/terminal/gb-terminal.ui
new file mode 100644
index 0000000..f250500
--- /dev/null
+++ b/plugins/terminal/gb-terminal.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.16 -->
+  <template class="GbTerminal" parent="GtkBin">
+    <property name="visible">true</property>
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="expand">true</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="VteTerminal" id="terminal">
+            <property name="expand">true</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index c1efbf0..f0e7a26 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -210,6 +210,7 @@ gnome_builder_PLUGINS = \
        command-bar \
        symbol-tree \
        sysmon \
+       terminal \
        $(NULL)
 
 gnome_builder_SOURCES = \
diff --git a/src/workbench/gb-workbench.c b/src/workbench/gb-workbench.c
index ee51824..08de9a3 100644
--- a/src/workbench/gb-workbench.c
+++ b/src/workbench/gb-workbench.c
@@ -425,8 +425,8 @@ gb_workbench_finalize (GObject *object)
   IDE_ENTRY;
 
   g_clear_object (&self->context);
-  g_clear_object (&self->extensions);
   g_clear_pointer (&self->current_folder_uri, g_free);
+  g_clear_object (&self->extensions);
 
   G_OBJECT_CLASS (gb_workbench_parent_class)->finalize (object);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]