make more settings dynamically configurable

urgent_on_bell, dynamic_title and clickable_url can now be turned on and
off dynamically
This commit is contained in:
Daniel Micay 2012-07-16 17:56:45 -04:00
parent d84707ea77
commit 911ae4de61
1 changed files with 80 additions and 69 deletions

133
termite.c
View File

@ -43,19 +43,29 @@ typedef struct search_panel_info {
GtkWidget *entry; GtkWidget *entry;
GtkWidget *panel; GtkWidget *panel;
enum overlay_mode mode; enum overlay_mode mode;
select_info select;
} search_panel_info; } search_panel_info;
typedef struct config_info {
gboolean dynamic_title, urgent_on_bell, clickable_url;
int tag;
} config_info;
typedef struct keybind_info {
search_panel_info panel;
select_info select;
config_info config;
} keybind_info;
static char *browser_cmd[3] = {NULL}; static char *browser_cmd[3] = {NULL};
static void launch_browser(char *url); static void launch_browser(char *url);
static void window_title_cb(VteTerminal *vte, GtkWindow *window); static void window_title_cb(VteTerminal *vte, gboolean *dynamic_title);
static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info); static gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, keybind_info *info);
static gboolean entry_key_press_cb(GtkEntry *entry, GdkEventKey *event, search_panel_info *info); static gboolean entry_key_press_cb(GtkEntry *entry, GdkEventKey *event, search_panel_info *info);
static gboolean position_overlay_cb(GtkBin *overlay, GtkWidget *widget, GdkRectangle *alloc); static gboolean position_overlay_cb(GtkBin *overlay, GtkWidget *widget, GdkRectangle *alloc);
static gboolean button_press_cb(VteTerminal *vte, GdkEventButton *event); static gboolean button_press_cb(VteTerminal *vte, GdkEventButton *event, gboolean *clickable_url);
static void beep_cb(GtkWindow *window); static void beep_cb(GtkWidget *vte, gboolean *urgent_on_bell);
static gboolean focus_cb(GtkWindow *window); static gboolean focus_cb(GtkWindow *window);
static gboolean add_to_list_store(char *key, void *value, GtkListStore *store); static gboolean add_to_list_store(char *key, void *value, GtkListStore *store);
@ -64,9 +74,8 @@ static void search(VteTerminal *vte, const char *pattern, bool reverse);
static void overlay_show(search_panel_info *info, overlay_mode mode, bool complete); static void overlay_show(search_panel_info *info, overlay_mode mode, bool complete);
static void get_vte_padding(VteTerminal *vte, int *w, int *h); static void get_vte_padding(VteTerminal *vte, int *w, int *h);
static char *check_match(VteTerminal *vte, int event_x, int event_y); static char *check_match(VteTerminal *vte, int event_x, int event_y);
static void load_config(GtkWindow *window, VteTerminal *vte, static void load_config(GtkWindow *window, VteTerminal *vte, config_info *info,
gboolean *dynamic_title, gboolean *urgent_on_bell, const char **term);
gboolean *clickable_url, const char **term);
void launch_browser(char *url) { void launch_browser(char *url) {
browser_cmd[1] = url; browser_cmd[1] = url;
@ -184,14 +193,14 @@ static void move_to_row_start(VteTerminal *vte, select_info *select, long row) {
} }
/* {{{ CALLBACKS */ /* {{{ CALLBACKS */
void window_title_cb(VteTerminal *vte, GtkWindow *window) { void window_title_cb(VteTerminal *vte, gboolean *dynamic_title) {
const char * const t = vte_terminal_get_window_title(vte); const char * const title = *dynamic_title ? vte_terminal_get_window_title(vte) : NULL;
gtk_window_set_title(window, t ? t : "termite"); gtk_window_set_title(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(vte))),
title ? title : "termite");
} }
gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *info) { gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, keybind_info *info) {
const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask(); const guint modifiers = event->state & gtk_accelerator_get_default_mod_mask();
gboolean dynamic_title = FALSE, urgent_on_bell = FALSE, clickable_url = FALSE;
if (info->select.mode) { if (info->select.mode) {
if (modifiers == GDK_CONTROL_MASK) { if (modifiers == GDK_CONTROL_MASK) {
if (gdk_keyval_to_lower(event->keyval) == GDK_KEY_v) { if (gdk_keyval_to_lower(event->keyval) == GDK_KEY_v) {
@ -243,10 +252,10 @@ gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *i
vte_terminal_copy_clipboard(vte); vte_terminal_copy_clipboard(vte);
break; break;
case GDK_KEY_slash: case GDK_KEY_slash:
overlay_show(info, OVERLAY_SEARCH, true); overlay_show(&info->panel, OVERLAY_SEARCH, true);
break; break;
case GDK_KEY_question: case GDK_KEY_question:
overlay_show(info, OVERLAY_RSEARCH, true); overlay_show(&info->panel, OVERLAY_RSEARCH, true);
break; break;
case GDK_KEY_n: case GDK_KEY_n:
vte_terminal_search_find_next(vte); vte_terminal_search_find_next(vte);
@ -278,12 +287,11 @@ gboolean key_press_cb(VteTerminal *vte, GdkEventKey *event, search_panel_info *i
return TRUE; return TRUE;
case GDK_KEY_Escape: case GDK_KEY_Escape:
load_config(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(vte))), load_config(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(vte))),
vte, &dynamic_title, &urgent_on_bell, vte, &info->config, NULL);
&clickable_url, NULL);
return TRUE; return TRUE;
} }
} else if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) { } else if (modifiers == GDK_CONTROL_MASK && event->keyval == GDK_KEY_Tab) {
overlay_show(info, OVERLAY_COMPLETION, true); overlay_show(&info->panel, OVERLAY_COMPLETION, true);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -338,18 +346,22 @@ gboolean position_overlay_cb(GtkBin *overlay, GtkWidget *widget, GdkRectangle *a
return TRUE; return TRUE;
} }
gboolean button_press_cb(VteTerminal *vte, GdkEventButton *event) { gboolean button_press_cb(VteTerminal *vte, GdkEventButton *event, gboolean *clickable_url) {
if (*clickable_url) {
char *match = check_match(vte, (int)event->x, (int)event->y); char *match = check_match(vte, (int)event->x, (int)event->y);
if (event->button == 1 && event->type == GDK_BUTTON_PRESS && match) { if (event->button == 1 && event->type == GDK_BUTTON_PRESS && match) {
launch_browser(match); launch_browser(match);
g_free(match); g_free(match);
return TRUE; return TRUE;
} }
}
return FALSE; return FALSE;
} }
void beep_cb(GtkWindow *window) { void beep_cb(GtkWidget *vte, gboolean *urgent_on_bell) {
gtk_window_set_urgency_hint(window, TRUE); if (*urgent_on_bell) {
gtk_window_set_urgency_hint(GTK_WINDOW(gtk_widget_get_toplevel(vte)), TRUE);
}
} }
gboolean focus_cb(GtkWindow *window) { gboolean focus_cb(GtkWindow *window) {
@ -486,9 +498,8 @@ static bool get_config_color(GKeyFile *config, const char *key, GdkColor *color)
return success; return success;
} }
static void load_config(GtkWindow *window, VteTerminal *vte, static void load_config(GtkWindow *window, VteTerminal *vte, config_info *info,
gboolean *dynamic_title, gboolean *urgent_on_bell, const char **term) {
gboolean *clickable_url, const char **term) {
static const char * const filename = "termite.cfg"; static const char * const filename = "termite.cfg";
const char *dir = g_get_user_config_dir(); const char *dir = g_get_user_config_dir();
@ -528,24 +539,38 @@ static void load_config(GtkWindow *window, VteTerminal *vte,
vte_terminal_set_allow_bold(vte, cfgbool); vte_terminal_set_allow_bold(vte, cfgbool);
} }
if (get_config_boolean(config, "options", "dynamic_title", &cfgbool)) { if (get_config_boolean(config, "options", "dynamic_title", &cfgbool)) {
*dynamic_title = cfgbool; info->dynamic_title = cfgbool;
} }
if (get_config_boolean(config, "options", "urgent_on_bell", &cfgbool)) { if (get_config_boolean(config, "options", "urgent_on_bell", &cfgbool)) {
*urgent_on_bell = cfgbool; info->urgent_on_bell = cfgbool;
}
if (get_config_boolean(config, "options", "clickable_url", &cfgbool)) {
*clickable_url = cfgbool;
} }
if (get_config_boolean(config, "options", "search_wrap", &cfgbool)) { if (get_config_boolean(config, "options", "search_wrap", &cfgbool)) {
vte_terminal_search_set_wrap_around(vte, cfgbool); vte_terminal_search_set_wrap_around(vte, cfgbool);
} }
vte_terminal_match_remove(vte, info->tag);
if (get_config_boolean(config, "options", "clickable_url", &cfgbool)) {
info->clickable_url = cfgbool;
}
if (info->clickable_url) {
info->tag =
vte_terminal_match_add_gregex(vte,
g_regex_new(url_regex,
G_REGEX_CASELESS,
G_REGEX_MATCH_NOTEMPTY,
NULL),
(GRegexMatchFlags)0);
vte_terminal_match_set_cursor_type(vte, info->tag, GDK_HAND2);
} else if (info->tag != -1) {
vte_terminal_match_remove(vte, info->tag);
info->tag = -1;
}
g_free(browser_cmd[0]); g_free(browser_cmd[0]);
if (get_config_string(config, "options", "browser", &cfgstr)) { if (get_config_string(config, "options", "browser", &cfgstr)) {
browser_cmd[0] = cfgstr; browser_cmd[0] = cfgstr;
} else { } else {
browser_cmd[0] = g_strdup(g_getenv("BROWSER")); browser_cmd[0] = g_strdup(g_getenv("BROWSER"));
if (!browser_cmd[0]) *clickable_url = false; if (!browser_cmd[0]) info->clickable_url = false;
} }
if (get_config_string(config, "options", "font", &cfgstr)) { if (get_config_string(config, "options", "font", &cfgstr)) {
@ -653,7 +678,6 @@ static void load_config(GtkWindow *window, VteTerminal *vte,
int main(int argc, char **argv) { int main(int argc, char **argv) {
GError *error = NULL; GError *error = NULL;
const char *term = "termite"; const char *term = "termite";
gboolean dynamic_title = FALSE, urgent_on_bell = FALSE, clickable_url = FALSE;
gboolean version = FALSE; gboolean version = FALSE;
GOptionContext *context = g_option_context_new(NULL); GOptionContext *context = g_option_context_new(NULL);
@ -720,58 +744,45 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
select_info select = {SELECT_OFF, 0, 0, 0, 0}; search_panel_info panel = {vte, gtk_entry_new(),
search_panel_info info = {vte, gtk_entry_new(),
gtk_alignment_new(0, 0, 1, 1), gtk_alignment_new(0, 0, 1, 1),
OVERLAY_HIDDEN, select}; OVERLAY_HIDDEN};
keybind_info info = {panel, {SELECT_OFF, 0, 0, 0, 0}, {FALSE, FALSE, FALSE, -1}};
load_config(GTK_WINDOW(window), VTE_TERMINAL(vte), &dynamic_title, load_config(GTK_WINDOW(window), VTE_TERMINAL(vte), &info.config, &term);
&urgent_on_bell, &clickable_url, &term);
vte_terminal_set_pty_object(VTE_TERMINAL(vte), pty); vte_terminal_set_pty_object(VTE_TERMINAL(vte), pty);
vte_pty_set_term(pty, term); vte_pty_set_term(pty, term);
gtk_alignment_set_padding(GTK_ALIGNMENT(info.panel), 5, 5, 5, 5); gtk_alignment_set_padding(GTK_ALIGNMENT(panel.panel), 5, 5, 5, 5);
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), info.panel); gtk_overlay_add_overlay(GTK_OVERLAY(overlay), panel.panel);
gtk_widget_set_halign(info.entry, GTK_ALIGN_START); gtk_widget_set_halign(panel.entry, GTK_ALIGN_START);
gtk_widget_set_valign(info.entry, GTK_ALIGN_END); gtk_widget_set_valign(panel.entry, GTK_ALIGN_END);
gtk_container_add(GTK_CONTAINER(info.panel), info.entry); gtk_container_add(GTK_CONTAINER(panel.panel), panel.entry);
gtk_container_add(GTK_CONTAINER(overlay), vte); gtk_container_add(GTK_CONTAINER(overlay), vte);
gtk_container_add(GTK_CONTAINER(window), overlay); gtk_container_add(GTK_CONTAINER(window), overlay);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(vte, "child-exited", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(vte, "child-exited", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(vte, "key-press-event", G_CALLBACK(key_press_cb), &info); g_signal_connect(vte, "key-press-event", G_CALLBACK(key_press_cb), &info);
g_signal_connect(info.entry, "key-press-event", G_CALLBACK(entry_key_press_cb), &info); g_signal_connect(panel.entry, "key-press-event", G_CALLBACK(entry_key_press_cb), &panel);
g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL); g_signal_connect(overlay, "get-child-position", G_CALLBACK(position_overlay_cb), NULL);
if (clickable_url) { g_signal_connect(vte, "button-press-event", G_CALLBACK(button_press_cb), &info.config.clickable_url);
int tag = vte_terminal_match_add_gregex(VTE_TERMINAL(vte),
g_regex_new(url_regex,
G_REGEX_CASELESS,
G_REGEX_MATCH_NOTEMPTY,
NULL),
(GRegexMatchFlags)0);
vte_terminal_match_set_cursor_type(VTE_TERMINAL(vte), tag, GDK_HAND2);
g_signal_connect(vte, "button-press-event", G_CALLBACK(button_press_cb), NULL);
}
if (urgent_on_bell) { g_signal_connect(vte, "beep", G_CALLBACK(beep_cb), &info.config.urgent_on_bell);
g_signal_connect_swapped(vte, "beep", G_CALLBACK(beep_cb), window);
g_signal_connect(window, "focus-in-event", G_CALLBACK(focus_cb), NULL); g_signal_connect(window, "focus-in-event", G_CALLBACK(focus_cb), NULL);
g_signal_connect(window, "focus-out-event", G_CALLBACK(focus_cb), NULL); g_signal_connect(window, "focus-out-event", G_CALLBACK(focus_cb), NULL);
}
if (dynamic_title) { window_title_cb(VTE_TERMINAL(vte), &info.config.dynamic_title);
window_title_cb(VTE_TERMINAL(vte), GTK_WINDOW(window)); g_signal_connect(vte, "window-title-changed", G_CALLBACK(window_title_cb),
g_signal_connect(vte, "window-title-changed", G_CALLBACK(window_title_cb), window); &info.config.dynamic_title);
}
if (geometry) { if (geometry) {
gtk_widget_show_all(overlay); gtk_widget_show_all(overlay);
gtk_widget_show_all(info.panel); gtk_widget_show_all(panel.panel);
if (!gtk_window_parse_geometry(GTK_WINDOW(window), geometry)) { if (!gtk_window_parse_geometry(GTK_WINDOW(window), geometry)) {
g_printerr("Invalid geometry string: %s\n", geometry); g_printerr("Invalid geometry string: %s\n", geometry);
} }
@ -780,7 +791,7 @@ int main(int argc, char **argv) {
gtk_widget_grab_focus(vte); gtk_widget_grab_focus(vte);
gtk_widget_show_all(window); gtk_widget_show_all(window);
gtk_widget_hide(info.panel); gtk_widget_hide(panel.panel);
GdkWindow *gdk_window = gtk_widget_get_window(window); GdkWindow *gdk_window = gtk_widget_get_window(window);
if (!gdk_window) { if (!gdk_window) {