aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel G. Fadel <samuelfadel@gmail.com>2013-02-02 20:21:06 -0200
committerSamuel G. Fadel <samuelfadel@gmail.com>2013-02-02 20:21:06 -0200
commitf1af5208777cb655dbee3ed126bb36de5939071f (patch)
treea7603e9d0f6f0de158027f41d7b101aa760c298e
parentb9a161dda660fceaa950ce7e507908ca7e499c91 (diff)
T now supports multiple windows under the same process. In the future T will be a singleton process to save resources and own all running terminals. Maybe a simple daemon will do.
-rw-r--r--PKGBUILD4
-rw-r--r--src/T.c206
2 files changed, 120 insertions, 90 deletions
diff --git a/PKGBUILD b/PKGBUILD
index 8e1b835..e63270c 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,14 +1,14 @@
# Maintainer: Samuel Fadel <samuelfadel at DOMAIN> (DOMAIN is gmail dot com)
pkgname=T
-pkgver=0.5
+pkgver=0.6
pkgrel=1
pkgdesc="Lean Terminal emulator"
arch=('i686' 'x86_64')
license=('GPL')
depends=('gtk2' 'vte')
source=("http://domain.tld/${pkgname}-${pkgver}.tar.bz2")
-sha1sums=('b0ff968aafa6e1c8ef1f331224171c0b52d3e08d')
+sha1sums=('1a0170b0e48eead516dfdb7e9c8ac34e36c5177d')
build() {
cd "${srcdir}/${pkgname}-${pkgver}"
diff --git a/src/T.c b/src/T.c
index 5a2fb7f..93e838a 100644
--- a/src/T.c
+++ b/src/T.c
@@ -12,7 +12,7 @@
#include "config.h"
-static GtkWindow *main_window;
+static int window_count;
/* Event callbacks */
static gboolean window_delete_event_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
@@ -23,148 +23,178 @@ static void terminal_window_title_changed_callback(VteTerminal *terminal, gpoint
/* Helper setup functions */
static void setup_pty(VteTerminal *terminal, GPid *child_pid);
static void set_app_preferences(VteTerminal *terminal);
-static void setup_terminal(VteTerminal *terminal);
-static void setup_main_window(void);
+static void setup_terminal(GtkWindow *window, VteTerminal *terminal);
+static void setup_window(GtkWindow *window);
+static void spawn_window(void);
static gboolean
window_delete_event_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
{
- /* TODO: always false? */
- return FALSE;
+ /* TODO: always false? */
+ return FALSE;
}
static void
window_destroy_callback(GtkWidget *widget, gpointer data)
{
- gtk_main_quit();
+ window_count--;
+
+ if (window_count == 0)
+ gtk_main_quit();
}
static gboolean
terminal_key_press_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
{
- GdkEventKey *key_event = (GdkEventKey *) event;
- VteTerminal *terminal = (VteTerminal *) widget;
-
- if ((key_event->state & GDK_SHIFT_MASK) == 0
- || (key_event->state & GDK_CONTROL_MASK) == 0)
- return FALSE;
-
- switch (key_event->keyval) {
- case GDK_KEY_C:
- case GDK_KEY_c:
- vte_terminal_copy_clipboard(terminal);
- break;
- case GDK_KEY_V:
- case GDK_KEY_v:
- vte_terminal_paste_clipboard(terminal);
- break;
- case GDK_KEY_N:
- case GDK_KEY_n:
- fork();
- break;
- }
-
- return TRUE;
+ GdkEventKey *key_event = (GdkEventKey *) event;
+ VteTerminal *terminal = (VteTerminal *) widget;
+
+ if ((key_event->state & GDK_SHIFT_MASK) == 0
+ || (key_event->state & GDK_CONTROL_MASK) == 0)
+ return FALSE;
+
+ switch (key_event->keyval) {
+ case GDK_KEY_C:
+ case GDK_KEY_c:
+ vte_terminal_copy_clipboard(terminal);
+ break;
+ case GDK_KEY_V:
+ case GDK_KEY_v:
+ vte_terminal_paste_clipboard(terminal);
+ break;
+ case GDK_KEY_N:
+ case GDK_KEY_n:
+ spawn_window();
+ break;
+ }
+
+ return TRUE;
}
static void
terminal_child_exited_callback(VteTerminal *terminal, gpointer data)
{
- gtk_main_quit();
+ GtkWindow *window;
+
+ window = (GtkWindow *) data;
+ gtk_widget_destroy(GTK_WIDGET(window));
}
static void
terminal_window_title_changed_callback(VteTerminal *terminal, gpointer data)
{
- gtk_window_set_title(main_window, vte_terminal_get_window_title(terminal));
+ GtkWindow *window;
+
+ window = (GtkWindow *) data;
+ gtk_window_set_title(window, vte_terminal_get_window_title(terminal));
}
static void
setup_pty(VteTerminal *terminal, GPid *child_pid)
{
- VtePty* pty;
- char *argv[] = { NULL, NULL };
-
- /* TODO: error handling */
- argv[0] = vte_get_user_shell();
- pty = vte_terminal_pty_new(terminal, VTE_PTY_DEFAULT, NULL);
- vte_terminal_set_pty_object(terminal, pty);
- vte_terminal_fork_command_full(terminal, VTE_PTY_DEFAULT, ".", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, child_pid, NULL);
+ VtePty* pty;
+ char *argv[] = { NULL, NULL };
+
+ /* TODO: error handling */
+ argv[0] = vte_get_user_shell();
+ pty = vte_terminal_pty_new(terminal, VTE_PTY_DEFAULT, NULL);
+ vte_terminal_set_pty_object(terminal, pty);
+ vte_terminal_fork_command_full(terminal, VTE_PTY_DEFAULT, ".", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, child_pid, NULL);
}
static void
set_app_preferences(VteTerminal *terminal)
{
- /*
- * Options set here can be configured through config.h
- */
-
- int i;
- GdkColor palette[PALETTE_SIZE], bg_color, fg_color;
-
- /* Set preferences */
- vte_terminal_set_mouse_autohide(terminal, MOUSE_AUTOHIDE);
- vte_terminal_set_visible_bell(terminal, VISIBLE_BELL);
- vte_terminal_set_audible_bell(terminal, AUDIBLE_BELL);
- vte_terminal_set_font_from_string(terminal, FONT_NAME);
-
- gdk_color_parse(FOREGROUND_COLOR, &fg_color);
- gdk_color_parse(BACKGROUND_COLOR, &bg_color);
- for (i = 0; i < PALETTE_SIZE; ++i)
- gdk_color_parse(COLOR_PALETTE[i], &palette[i]);
- vte_terminal_set_colors(terminal, &fg_color, &bg_color, palette, PALETTE_SIZE);
+ /*
+ * Options set here can be configured through config.h
+ */
+
+ int i;
+ GdkColor palette[PALETTE_SIZE], bg_color, fg_color;
+
+ /* Set preferences */
+ vte_terminal_set_mouse_autohide(terminal, MOUSE_AUTOHIDE);
+ vte_terminal_set_visible_bell(terminal, VISIBLE_BELL);
+ vte_terminal_set_audible_bell(terminal, AUDIBLE_BELL);
+ vte_terminal_set_font_from_string(terminal, FONT_NAME);
+
+ gdk_color_parse(FOREGROUND_COLOR, &fg_color);
+ gdk_color_parse(BACKGROUND_COLOR, &bg_color);
+ for (i = 0; i < PALETTE_SIZE; ++i)
+ gdk_color_parse(COLOR_PALETTE[i], &palette[i]);
+ vte_terminal_set_colors(terminal, &fg_color, &bg_color, palette, PALETTE_SIZE);
}
static void
-setup_terminal(VteTerminal *terminal)
+setup_terminal(GtkWindow *window, VteTerminal *terminal)
{
- GPid child_pid;
+ GPid child_pid;
- setup_pty(terminal, &child_pid);
- vte_terminal_watch_child(terminal, child_pid);
+ setup_pty(terminal, &child_pid);
+ vte_terminal_watch_child(terminal, child_pid);
- g_signal_connect(terminal, "child-exited", G_CALLBACK(terminal_child_exited_callback), NULL);
- g_signal_connect(terminal, "window-title-changed", G_CALLBACK(terminal_window_title_changed_callback), NULL);
- g_signal_connect(terminal, "key-press-event", G_CALLBACK(terminal_key_press_callback), NULL);
+ g_signal_connect(terminal, "child-exited", G_CALLBACK(terminal_child_exited_callback), window);
+ g_signal_connect(terminal, "window-title-changed", G_CALLBACK(terminal_window_title_changed_callback), window);
+ g_signal_connect(terminal, "key-press-event", G_CALLBACK(terminal_key_press_callback), window);
- set_app_preferences(terminal);
+ set_app_preferences(terminal);
}
static void
-setup_main_window(void)
+setup_window(GtkWindow *window)
{
- GdkGeometry hints;
- VteTerminal *terminal;
+ GdkGeometry hints;
+ VteTerminal *terminal;
- terminal = (VteTerminal *) vte_terminal_new();
- setup_terminal(terminal);
+ terminal = (VteTerminal *) vte_terminal_new();
+ setup_terminal(window, terminal);
- hints.base_width = vte_terminal_get_char_width(terminal);
- hints.base_height = vte_terminal_get_char_height(terminal);
- hints.min_width = hints.base_width * MIN_WIDTH;
- hints.min_height = hints.base_height * MIN_HEIGHT;
- hints.width_inc = hints.base_width;
- hints.height_inc = hints.base_height;
- gtk_window_set_geometry_hints(main_window, GTK_WIDGET(terminal), &hints, GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
+ hints.base_width = vte_terminal_get_char_width(terminal);
+ hints.base_height = vte_terminal_get_char_height(terminal);
+ hints.min_width = hints.base_width * MIN_WIDTH;
+ hints.min_height = hints.base_height * MIN_HEIGHT;
+ hints.width_inc = hints.base_width;
+ hints.height_inc = hints.base_height;
+ gtk_window_set_geometry_hints(window, GTK_WIDGET(terminal), &hints, GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
- g_signal_connect(main_window, "delete-event", G_CALLBACK(window_delete_event_callback), NULL);
- g_signal_connect(main_window, "destroy", G_CALLBACK(window_destroy_callback), NULL);
- gtk_window_set_icon_name(main_window, "utilities-terminal");
+ g_signal_connect(window, "delete-event", G_CALLBACK(window_delete_event_callback), NULL);
+ g_signal_connect(window, "destroy", G_CALLBACK(window_destroy_callback), NULL);
+ gtk_window_set_icon_name(window, "utilities-terminal");
- gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(terminal));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(terminal));
- gtk_widget_show(GTK_WIDGET(terminal));
- gtk_widget_show(GTK_WIDGET(main_window));
+ gtk_widget_show(GTK_WIDGET(terminal));
+ gtk_widget_show(GTK_WIDGET(window));
+}
+
+static void
+spawn_window(void)
+{
+ GtkWindow *window;
+
+ window = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ setup_window(window);
+
+ window_count++;
}
int
main(int argc, char *argv[])
{
- gtk_init(&argc, &argv);
+ gtk_init(&argc, &argv);
+
+ /* Initial state: single window */
+ window_count = 0;
+ spawn_window();
+
+ /*
+ * TODO
+ * Find out a nice and clean way of opening more windows when the user
+ * does not have focus on a T window. Maybe fire spawn_window() when we
+ * detect a running T process?
+ */
- main_window = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
- setup_main_window();
- gtk_main();
+ gtk_main();
- return 0;
+ return 0;
}