diff --git a/src/include/pw3270/v3270.h b/src/include/pw3270/v3270.h index 3bda914..0f7806f 100644 --- a/src/include/pw3270/v3270.h +++ b/src/include/pw3270/v3270.h @@ -163,6 +163,10 @@ LIB3270_EXPORT int v3270_set_host_charset(GtkWidget *widget, const gchar *name); + LIB3270_EXPORT void v3270_set_auto_disconnect(GtkWidget *widget, guint minutes); + LIB3270_EXPORT guint v3270_get_auto_disconnect(GtkWidget *widget); + + // Clipboard typedef enum _v3270_select_format { diff --git a/src/pw3270/main.c b/src/pw3270/main.c index 33f9447..a4a603b 100644 --- a/src/pw3270/main.c +++ b/src/pw3270/main.c @@ -55,6 +55,7 @@ static GtkWidget * toplevel = NULL; static GtkWidget * trace_window = NULL; static unsigned int syscolors = 16; + static unsigned int timer = 0; static const gchar * systype = NULL; static const gchar * toggleset = NULL; static const gchar * togglereset = NULL; @@ -408,6 +409,7 @@ int main(int argc, char *argv[]) { "togglereset", 'R', 0, G_OPTION_ARG_STRING, &togglereset, N_( "Set toggles OFF" ), NULL }, { "charset", 'C', 0, G_OPTION_ARG_STRING, &charset, N_( "Set host charset" ), NULL }, { "model", 'M', 0, G_OPTION_ARG_STRING, &model, N_( "The model of 3270 display to be emulated" ), NULL }, + { "autodisconnect", 'D', 0, G_OPTION_ARG_INT, &timer, N_( "Minutes for auto-disconnect" ), 0 }, #if defined( HAVE_SYSLOG ) { "syslog", 'l', 0, G_OPTION_ARG_NONE, &log_to_syslog, N_( "Send messages to syslog" ), NULL }, @@ -562,6 +564,8 @@ int main(int argc, char *argv[]) if(model) lib3270_set_model(pw3270_get_session(toplevel),model); + v3270_set_auto_disconnect(pw3270_get_terminal_widget(toplevel),timer); + pw3270_start_plugins(toplevel); gtk_window_present(GTK_WINDOW(toplevel)); diff --git a/src/pw3270/v3270/keyboard.c b/src/pw3270/v3270/keyboard.c index 61a6f99..319fd0e 100644 --- a/src/pw3270/v3270/keyboard.c +++ b/src/pw3270/v3270/keyboard.c @@ -198,6 +198,7 @@ { v3270 * terminal = GTK_V3270(widget); + terminal->activity.timestamp = time(0); update_keyboard_state(terminal,event,TRUE); if(gtk_im_context_filter_keypress(terminal->input_method,event)) @@ -229,12 +230,14 @@ void v3270_tab(GtkWidget *widget) { g_return_if_fail(GTK_IS_V3270(widget)); + GTK_V3270(widget)->activity.timestamp = time(0); lib3270_nextfield(GTK_V3270(widget)->host); } void v3270_backtab(GtkWidget *widget) { g_return_if_fail(GTK_IS_V3270(widget)); + GTK_V3270(widget)->activity.timestamp = time(0); lib3270_previousfield(GTK_V3270(widget)->host); } @@ -246,6 +249,7 @@ g_return_if_fail(GTK_IS_V3270(widget)); host = GTK_V3270(widget)->host; + GTK_V3270(widget)->activity.timestamp = time(0); utf = g_convert((char *) str, -1, lib3270_get_display_charset(host), "UTF-8", NULL, NULL, NULL); @@ -264,7 +268,6 @@ if(utf) { lib3270_input_string(GTK_V3270(widget)->host, (const unsigned char *) utf); -// lib3270_set_string(GTK_V3270(widget)->host, (const unsigned char *) utf); g_free(utf); } else diff --git a/src/pw3270/v3270/private.h b/src/pw3270/v3270/private.h index a27e6e1..c297004 100644 --- a/src/pw3270/v3270/private.h +++ b/src/pw3270/v3270/private.h @@ -199,6 +199,14 @@ G_BEGIN_DECLS H3270 * host; /**< Related 3270 session */ gchar * session_name; /**< Session name (for window title) */ + // Auto disconnect + struct + { + time_t timestamp; /**< Last action in this widget */ + guint disconnect; /**< Time (in minutes) for auto disconnect */ + GSource * timer; /**< Auto disconnect timer */ + } activity; + // Scripting struct { @@ -224,6 +232,7 @@ G_BEGIN_DECLS PROP_SELECTION, PROP_MODEL, PROP_LUNAME, + PROP_AUTO_DISCONNECT, /* Toggles - always the last one, the real values are PROP_TOGGLE+LIB3270_TOGGLE */ PROP_TOGGLE diff --git a/src/pw3270/v3270/properties.c b/src/pw3270/v3270/properties.c index 91b2cc1..7cd695f 100644 --- a/src/pw3270/v3270/properties.c +++ b/src/pw3270/v3270/properties.c @@ -53,6 +53,10 @@ lib3270_set_model(window->host,g_value_get_string(value)); break; + case PROP_AUTO_DISCONNECT: + v3270_set_auto_disconnect(GTK_WIDGET(object),g_value_get_int(value)); + break; + default: if(prop_id < (PROP_TOGGLE + LIB3270_TOGGLE_COUNT)) { @@ -74,6 +78,10 @@ g_value_set_string(value,lib3270_get_model(window->host)); break; + case PROP_AUTO_DISCONNECT: + g_value_set_int(value,v3270_get_auto_disconnect(GTK_WIDGET(object))); + break; + case PROP_LUNAME: g_value_set_string(value,lib3270_get_luname(window->host)); break; @@ -129,6 +137,14 @@ FALSE,G_PARAM_READABLE|G_PARAM_WRITABLE); g_object_class_install_property(gobject_class,PROP_LUNAME,v3270_properties[PROP_LUNAME]); + + v3270_properties[PROP_AUTO_DISCONNECT] = g_param_spec_string( + "auto_disconnect", + "auto_disconnect", + "Minutes to disconnect when idle", + FALSE,G_PARAM_READABLE|G_PARAM_WRITABLE); + g_object_class_install_property(gobject_class,PROP_LUNAME,v3270_properties[PROP_LUNAME]); + // Toggle properties int f; @@ -138,3 +154,15 @@ g_object_class_install_property(gobject_class,PROP_TOGGLE+f,v3270_properties[PROP_TOGGLE+f]); } } + + LIB3270_EXPORT void v3270_set_auto_disconnect(GtkWidget *widget, guint minutes) + { + g_return_if_fail(GTK_IS_V3270(widget)); + GTK_V3270(widget)->activity.disconnect = minutes; + } + + LIB3270_EXPORT guint v3270_get_auto_disconnect(GtkWidget *widget) + { + g_return_val_if_fail(GTK_IS_V3270(widget),0); + return GTK_V3270(widget)->activity.disconnect; + } diff --git a/src/pw3270/v3270/widget.c b/src/pw3270/v3270/widget.c index f04778f..37325d4 100644 --- a/src/pw3270/v3270/widget.c +++ b/src/pw3270/v3270/widget.c @@ -675,8 +675,8 @@ static void update_toggle(H3270 *session, LIB3270_TOGGLE ix, unsigned char value break; case LIB3270_TOGGLE_INSERT: - v3270_draw_ins_status(GTK_WIDGET(session->widget)); - v3270_cursor_draw(GTK_WIDGET(session->widget)); + v3270_draw_ins_status(GTK_V3270(session->widget)); + v3270_cursor_draw(GTK_V3270(session->widget)); break; case LIB3270_TOGGLE_BOLD: @@ -762,6 +762,8 @@ static void update_connect(H3270 *session, unsigned char connected) g_object_notify(G_OBJECT(widget),"online"); #endif // GTK_CHECK_VERSION + widget->activity.timestamp = time(0); + gtk_widget_queue_draw(GTK_WIDGET(widget)); } @@ -881,6 +883,21 @@ static int emit_print_signal(H3270 *session) return 0; } +static gboolean activity_tick(v3270 *widget) +{ + trace("idle=%d (%d) timeout=%d",time(0) - widget->activity.timestamp,((time(0) - widget->activity.timestamp)/60),widget->activity.disconnect); + + if(widget->activity.disconnect && lib3270_is_connected(widget->host) && ((time(0) - widget->activity.timestamp)/60) >= widget->activity.disconnect) + lib3270_disconnect(widget->host); + + return TRUE; +} + +static void release_activity_timer(v3270 *widget) +{ + widget->activity.timer = NULL; +} + static void v3270_init(v3270 *widget) { widget->host = lib3270_session_new(""); @@ -917,6 +934,10 @@ static void v3270_init(v3270 *widget) widget->host->update_ssl = v3270_update_ssl; widget->host->print = emit_print_signal; + // Reset timer + widget->activity.timestamp = time(0); + widget->activity.disconnect = 0; + // Setup input method widget->input_method = gtk_im_multicontext_new(); g_signal_connect(G_OBJECT(widget->input_method),"commit",G_CALLBACK(v3270_key_commit),widget); @@ -932,6 +953,9 @@ static void v3270_init(v3270 *widget) gtk_widget_add_events(GTK_WIDGET(widget),GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_MOTION_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_ENTER_NOTIFY_MASK|GDK_SCROLL_MASK); gtk_widget_set_has_tooltip(GTK_WIDGET(widget),TRUE); + // Setup auto disconnect timer + widget->cursor.timer = NULL; + trace("%s",__FUNCTION__); } @@ -1013,6 +1037,13 @@ static void v3270_destroy(GtkObject *widget) g_source_unref(terminal->cursor.timer); } + if(terminal->activity.timer) + { + g_source_destroy(terminal->activity.timer); + while(terminal->activity.timer) + g_source_unref(terminal->activity.timer); + } + if(terminal->input_method) { g_object_unref(terminal->input_method); @@ -1049,7 +1080,7 @@ static gboolean timer_tick(v3270 *widget) return TRUE; } -static void release_timer(v3270 *widget) +static void release_cursor_timer(v3270 *widget) { widget->cursor.timer = NULL; } @@ -1144,12 +1175,22 @@ static void v3270_realize(GtkWidget * widget) v3270 *terminal = GTK_V3270(widget); terminal->cursor.timer = g_timeout_source_new(500); - g_source_set_callback(terminal->cursor.timer,(GSourceFunc) timer_tick, widget, (GDestroyNotify) release_timer); + g_source_set_callback(terminal->cursor.timer,(GSourceFunc) timer_tick, widget, (GDestroyNotify) release_cursor_timer); g_source_attach(terminal->cursor.timer, NULL); g_source_unref(terminal->cursor.timer); } + if(!GTK_V3270(widget)->activity.timer) + { + v3270 *terminal = GTK_V3270(widget); + + terminal->activity.timer = g_timeout_source_new(10000); + g_source_set_callback(terminal->activity.timer,(GSourceFunc) activity_tick, widget, (GDestroyNotify) release_activity_timer); + g_source_attach(terminal->activity.timer, NULL); + g_source_unref(terminal->activity.timer); + } + } static void v3270_size_allocate(GtkWidget * widget, GtkAllocation * allocation) @@ -1464,6 +1505,7 @@ static void v3270_activate(GtkWidget *widget) v3270 * terminal = GTK_V3270(widget); trace("%s: %p",__FUNCTION__,terminal); + terminal->activity.timestamp = time(0); if(lib3270_connected(terminal->host)) lib3270_enter(terminal->host); -- libgit2 0.21.2