diff --git a/TODO b/TODO index ead122d..14ab4d6 100644 --- a/TODO +++ b/TODO @@ -3,3 +3,5 @@ -- store in TermitTab only flags: SET_NAME, SET_FG_FONT, SET_BG_FONT, etc values are already stored in VteTerminal, so we can simply read VteTerminal properties on demand thus we can achieve smaller memory usage + + diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 72bbe95..a29f673 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -25,6 +25,9 @@ pre. Example: don't close tab with Ctrl-w, use CtrlShift-w _event_ - string with one of those values: DoubleClick _luaFunction_ - callback function +*bindEvent(_event_, _luaFunction_)* - Sets new event handler. If luaFunction is nil removes event-handling. +_event_ - string with one of the values: contents-changed +_luaFunction_ - callback function *closeTab()* - Closes active tab. diff --git a/doc/termit.1 b/doc/termit.1 index 7ee6f88..72258c1 100644 --- a/doc/termit.1 +++ b/doc/termit.1 @@ -140,6 +140,18 @@ removes mouse\(hybinding. event \(hy string with one of those values: DoubleClick luaFunction \(hy callback function .P +.B bindEvent +( +.I event +, +.I luaFunction +) + Sets new event\(ybinding. If luaFunction is +.I nil +removes event\(binding. + event \(hy string with one of those values: contents-changed + luaFunction \(hy callback function, receives no arguments +.P .B closeTab () Closes active tab. diff --git a/src/Sources.cmake b/src/Sources.cmake index afe4c46..d7e38b7 100644 --- a/src/Sources.cmake +++ b/src/Sources.cmake @@ -15,10 +15,10 @@ SET( TERMIT_SRCS termit.c termit_core_api.c callbacks.c sessions.c - keybindings.c lua_conf.c lua_api.c configs.c + keybindings.c eventbindings.c lua_conf.c lua_api.c configs.c termit_style.c termit_preferences.c ) SET( TERMIT_HDRS termit_core_api.h callbacks.h configs.h sessions.h - keybindings.h lua_api.h termit.h termit_style.h + keybindings.h eventbindings.h lua_api.h termit.h termit_style.h ) diff --git a/src/callbacks.c b/src/callbacks.c index 742f2d2..03393de 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -26,6 +26,7 @@ #include "termit_style.h" #include "lua_api.h" #include "keybindings.h" +#include "eventbindings.h" #include "callbacks.h" static gboolean confirm_exit() @@ -426,3 +427,8 @@ gboolean termit_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer use { return termit_key_event(event); } + +void termit_on_contents_changed(VteTerminal *vteterminal, gpointer userdata) +{ + termit_event("contents-changed"); +} diff --git a/src/callbacks.h b/src/callbacks.h index 1e9ff79..874633e 100644 --- a/src/callbacks.h +++ b/src/callbacks.h @@ -38,5 +38,6 @@ void termit_on_toggle_search(GtkToggleButton*, gpointer); void termit_on_find_next(GtkButton*, gpointer); void termit_on_find_prev(GtkButton*, gpointer); gboolean termit_on_search_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data); +void termit_on_contents_changed(VteTerminal *vteterminal, gpointer userdata); #endif /* TERMIT_CALLBACKS_H */ diff --git a/src/configs.c b/src/configs.c index ae1fb84..13c26c7 100644 --- a/src/configs.c +++ b/src/configs.c @@ -19,6 +19,7 @@ #include "termit.h" #include "keybindings.h" +#include "eventbindings.h" #include "configs.h" #include "lua_api.h" @@ -173,6 +174,7 @@ void termit_configs_set_defaults() configs.key_bindings = g_array_new(FALSE, TRUE, sizeof(struct KeyBinding)); configs.mouse_bindings = g_array_new(FALSE, TRUE, sizeof(struct MouseBinding)); configs.matches = g_array_new(FALSE, TRUE, sizeof(struct Match)); + configs.event_bindings = g_array_new(FALSE, TRUE, sizeof(struct EventBinding)); configs.start_maximized = FALSE; configs.hide_titlebar_when_maximized = FALSE; @@ -248,6 +250,13 @@ void termit_config_deinit() } g_array_free(configs.matches, TRUE); + i = 0; + for(; ilen; ++i) { + struct EventBinding* eb = &g_array_index(configs.key_bindings, struct EventBinding, i); + termit_lua_unref(&eb->lua_callback); + } + g_array_free(configs.event_bindings, TRUE); + termit_lua_unref(&configs.get_window_title_callback); termit_lua_unref(&configs.get_tab_title_callback); termit_lua_unref(&configs.get_statusbar_callback); diff --git a/src/configs.h b/src/configs.h index 3866923..3010dde 100644 --- a/src/configs.h +++ b/src/configs.h @@ -63,6 +63,7 @@ struct Configs GtkPositionType tab_pos; struct TermitStyle style; GArray* default_tabs; // TabInfo + GArray* event_bindings; // Event Handlers }; struct Match diff --git a/src/eventbindings.c b/src/eventbindings.c new file mode 100644 index 0000000..74e5e87 --- /dev/null +++ b/src/eventbindings.c @@ -0,0 +1,82 @@ +/* Copyright © 2007-2016 Nimrod Maclomair + * + * 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 . + */ + +#include + +#include +#include +#include + +#include "termit.h" +#include "configs.h" +#include "termit_core_api.h" +#include "lua_api.h" +#include "eventbindings.h" + + +static gint get_event_index(const gchar* event) +{ + // DEBUG + TRACE("get_event_index running"); + guint i = 0; + for (; ilen; ++i){ + struct EventBinding* eb = &g_array_index(configs.event_bindings, struct EventBinding, i); + if( !strcmp(event, eb->name)) { + return i; + } + } + return -1; +} + +void termit_event_bind(const gchar* event, int lua_callback) +{ + gint ev_index = get_event_index(event); + if(ev_index == -1){ + struct EventBinding eb = {}; + eb.name = g_strdup(event); + eb.lua_callback = lua_callback; + g_array_append_val(configs.event_bindings, eb); + } else { + struct EventBinding* eb = &g_array_index(configs.event_bindings, struct EventBinding, ev_index); + termit_lua_unref(&eb->lua_callback); + eb->lua_callback = lua_callback; + } +} + +void termit_event_unbind(const gchar* event) +{ + gint ev_index = get_event_index(event); + if(ev_index == -1){ + TRACE("VTE event [%s] not found - skipping", event); + return; + } + struct EventBinding* eb = &g_array_index(configs.event_bindings, struct EventBinding, ev_index); + termit_lua_unref(&eb->lua_callback); + g_array_remove_index(configs.event_bindings, ev_index); +} + +gboolean termit_event(const gchar* event) +{ + gint ev_index = get_event_index(event); + if(ev_index == -1){ + TRACE("VTE event [%s] not found - skipping", event); + return FALSE; + } + TRACE("VTE event [%s] running", event); + struct EventBinding* eb = &g_array_index(configs.event_bindings, struct EventBinding, ev_index); + termit_lua_dofunction(eb->lua_callback); + return FALSE; // TODO: is that correct? +} diff --git a/src/eventbindings.h b/src/eventbindings.h new file mode 100644 index 0000000..4b751e7 --- /dev/null +++ b/src/eventbindings.h @@ -0,0 +1,33 @@ +/* Copyright © 2020 Nimrod Maclomair + * + * 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 . + */ + +#ifndef TERMIT_EVENTBINDINGS_H +#define TERMIT_EVENTBINDINGS_H + +struct EventBinding +{ + gchar* name; + int lua_callback; +}; + + +void termit_event_bind(const gchar* event, int lua_callback); +void termit_event_unbind(const gchar* event); +gboolean termit_event(const gchar* event); + + +#endif + diff --git a/src/lua_api.c b/src/lua_api.c index d5c697e..bf98055 100644 --- a/src/lua_api.c +++ b/src/lua_api.c @@ -22,6 +22,7 @@ #include "termit.h" #include "termit_core_api.h" #include "keybindings.h" +#include "eventbindings.h" #include "configs.h" #include "callbacks.h" #include "lua_api.h" @@ -218,6 +219,27 @@ static int termit_lua_bindMouse(lua_State* ls) return 0; } +static int termit_lua_bindEvent(lua_State* ls) +{ + if( lua_isnil(ls, 1)) { + TRACE("NIL skipping."); + return 0; + } else if (!lua_isstring(ls, 1)){ + TRACE("1st arg no string, skipping"); + return 0; + } + const char* signal_name = lua_tostring(ls, 1); + if (lua_isnil(ls, 2)) { + TRACE("unbindEvent: %s", signal_name); + termit_event_unbind(signal_name); + } else if (lua_isfunction(ls, 2)){ + int func = luaL_ref(ls, LUA_REGISTRYINDEX); + TRACE("bind event: %s - %d", signal_name, func); + termit_event_bind(signal_name, func); + } + return 0; +} + static int termit_lua_toggleMenubar(lua_State* ls) { termit_toggle_menubar(); @@ -694,6 +716,7 @@ struct TermitLuaFunction {"addPopupMenu", termit_lua_addPopupMenu, 0}, {"bindKey", termit_lua_bindKey, 0}, {"bindMouse", termit_lua_bindMouse, 0}, + {"bindEvent", termit_lua_bindEvent, 0}, {"closeTab", termit_lua_closeTab, 0}, {"copy", termit_lua_copy, 0}, {"currentTab", termit_lua_currentTab, 0}, diff --git a/src/termit_core_api.c b/src/termit_core_api.c index f0ca2b7..39a4651 100644 --- a/src/termit_core_api.c +++ b/src/termit_core_api.c @@ -421,6 +421,7 @@ void termit_append_tab_with_details(const struct TabInfo* ti) g_signal_connect(G_OBJECT(pTab->vte), "bell", G_CALLBACK(termit_on_beep), pTab); g_signal_connect(G_OBJECT(pTab->vte), "focus-in-event", G_CALLBACK(termit_on_focus), pTab); g_signal_connect(G_OBJECT(pTab->vte), "window-title-changed", G_CALLBACK(termit_on_tab_title_changed), NULL); + g_signal_connect(G_OBJECT(pTab->vte), "contents-changed", G_CALLBACK(termit_on_contents_changed), NULL); pTab->onChildExitedHandlerId = g_signal_connect(G_OBJECT(pTab->vte), "child-exited", G_CALLBACK(termit_on_child_exited), &termit_close_tab); g_signal_connect_swapped(G_OBJECT(pTab->vte), "button-press-event", G_CALLBACK(termit_on_popup), NULL);