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:
parent
d84707ea77
commit
911ae4de61
133
termite.c
133
termite.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue