From f1af5208777cb655dbee3ed126bb36de5939071f Mon Sep 17 00:00:00 2001 From: "Samuel G. Fadel" Date: Sat, 2 Feb 2013 20:21:06 -0200 Subject: 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. --- src/T.c | 206 +++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 118 insertions(+), 88 deletions(-) (limited to 'src') 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; } -- cgit v1.2.3