# HG changeset patch # User Christian Brabandt # Date 1503838804 -7200 # Node ID ac8b2f9c14094f2685c6a596339cdbe84ba7d5aa # Parent 6669330ba85ddc08dfe4667cb8419383216d6520 patch 8.0.1005: terminal without job updates slowly in GUI commit https://github.com/vim/vim/commit/4ab7968aa9d8a624cd56f55b5cad2bedb240eb73 Author: Bram Moolenaar Date: Sun Aug 27 14:50:47 2017 +0200 patch 8.0.1005: terminal without job updates slowly in GUI Problem: Terminal without job updates slowly in GUI. Solution: Poll for input when a channel has the keep_open flag. diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -3555,6 +3555,22 @@ channel_handle_events(int only_keep_open } # endif +# if defined(FEAT_GUI) || defined(PROTO) +/* + * Return TRUE when there is any channel with a keep_open flag. + */ + int +channel_any_keep_open() +{ + channel_T *channel; + + for (channel = first_channel; channel != NULL; channel = channel->ch_next) + if (channel->ch_keep_open) + return TRUE; + return FALSE; +} +# endif + /* * Set "channel"/"part" to non-blocking. * Only works for sockets and pipes. diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -789,6 +789,37 @@ property_event(GtkWidget *widget, #endif /* defined(FEAT_CLIENTSERVER) */ +#if GTK_CHECK_VERSION(3,0,0) +typedef gboolean timeout_cb_type; +#else +typedef gint timeout_cb_type; +#endif + +/* + * Start a timer that will invoke the specified callback. + * Returns the ID of the timer. + */ + static guint +timeout_add(int time, timeout_cb_type (*callback)(gpointer), int *flagp) +{ +#if GTK_CHECK_VERSION(3,0,0) + return g_timeout_add((guint)time, (GSourceFunc)callback, flagp); +#else + return gtk_timeout_add((guint32)time, (GtkFunction)callback, flagp); +#endif +} + + static void +timeout_remove(guint timer) +{ +#if GTK_CHECK_VERSION(3,0,0) + g_source_remove(timer); +#else + gtk_timeout_remove(timer); +#endif +} + + /**************************************************************************** * Focus handlers: */ @@ -866,11 +897,7 @@ gui_mch_stop_blink(void) { if (blink_timer) { -#if GTK_CHECK_VERSION(3,0,0) - g_source_remove(blink_timer); -#else - gtk_timeout_remove(blink_timer); -#endif + timeout_remove(blink_timer); blink_timer = 0; } if (blink_state == BLINK_OFF) @@ -881,36 +908,20 @@ gui_mch_stop_blink(void) blink_state = BLINK_NONE; } -#if GTK_CHECK_VERSION(3,0,0) - static gboolean -#else - static gint -#endif + static timeout_cb_type blink_cb(gpointer data UNUSED) { if (blink_state == BLINK_ON) { gui_undraw_cursor(); blink_state = BLINK_OFF; -#if GTK_CHECK_VERSION(3,0,0) - blink_timer = g_timeout_add((guint)blink_offtime, - (GSourceFunc) blink_cb, NULL); -#else - blink_timer = gtk_timeout_add((guint32)blink_offtime, - (GtkFunction) blink_cb, NULL); -#endif + blink_timer = timeout_add(blink_offtime, blink_cb, NULL); } else { gui_update_cursor(TRUE, FALSE); blink_state = BLINK_ON; -#if GTK_CHECK_VERSION(3,0,0) - blink_timer = g_timeout_add((guint)blink_ontime, - (GSourceFunc) blink_cb, NULL); -#else - blink_timer = gtk_timeout_add((guint32)blink_ontime, - (GtkFunction) blink_cb, NULL); -#endif + blink_timer = timeout_add(blink_ontime, blink_cb, NULL); } gui_mch_flush(); @@ -926,23 +937,13 @@ gui_mch_start_blink(void) { if (blink_timer) { -#if GTK_CHECK_VERSION(3,0,0) - g_source_remove(blink_timer); -#else - gtk_timeout_remove(blink_timer); -#endif + timeout_remove(blink_timer); blink_timer = 0; } /* Only switch blinking on if none of the times is zero */ if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) { -#if GTK_CHECK_VERSION(3,0,0) - blink_timer = g_timeout_add((guint)blink_waittime, - (GSourceFunc) blink_cb, NULL); -#else - blink_timer = gtk_timeout_add((guint32)blink_waittime, - (GtkFunction) blink_cb, NULL); -#endif + blink_timer = timeout_add(blink_waittime, blink_cb, NULL); blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); gui_mch_flush(); @@ -1733,7 +1734,6 @@ gui_mch_init_check(void) return OK; } - /**************************************************************************** * Mouse handling callbacks */ @@ -1745,11 +1745,7 @@ static int mouse_timed_out = TRUE; /* * Timer used to recognize multiple clicks of the mouse button */ -#if GTK_CHECK_VERSION(3,0,0) - static gboolean -#else - static gint -#endif + static timeout_cb_type mouse_click_timer_cb(gpointer data) { /* we don't use this information currently */ @@ -1759,13 +1755,9 @@ mouse_click_timer_cb(gpointer data) return FALSE; /* don't happen again */ } -static guint motion_repeat_timer = 0; -static int motion_repeat_offset = FALSE; -#ifdef GTK_DEST_DEFAULT_ALL -static gboolean motion_repeat_timer_cb(gpointer); -#else -static gint motion_repeat_timer_cb(gpointer); -#endif +static guint motion_repeat_timer = 0; +static int motion_repeat_offset = FALSE; +static timeout_cb_type motion_repeat_timer_cb(gpointer); static void process_motion_notify(int x, int y, GdkModifierType state) @@ -1853,13 +1845,8 @@ process_motion_notify(int x, int y, GdkM /* shoot again */ if (!motion_repeat_timer) -#if GTK_CHECK_VERSION(3,0,0) - motion_repeat_timer = g_timeout_add((guint)delay, - motion_repeat_timer_cb, NULL); -#else - motion_repeat_timer = gtk_timeout_add((guint32)delay, - motion_repeat_timer_cb, NULL); -#endif + motion_repeat_timer = timeout_add(delay, motion_repeat_timer_cb, + NULL); } } @@ -1904,11 +1891,7 @@ gui_gtk_window_at_position(GtkWidget *wi /* * Timer used to recognize multiple clicks of the mouse button. */ -#if GTK_CHECK_VERSION(3,0,0) - static gboolean -#else - static gint -#endif + static timeout_cb_type motion_repeat_timer_cb(gpointer data UNUSED) { int x; @@ -2019,23 +2002,14 @@ button_press_event(GtkWidget *widget, /* Handle multiple clicks */ if (!mouse_timed_out && mouse_click_timer) { -#if GTK_CHECK_VERSION(3,0,0) - g_source_remove(mouse_click_timer); -#else - gtk_timeout_remove(mouse_click_timer); -#endif + timeout_remove(mouse_click_timer); mouse_click_timer = 0; repeated_click = TRUE; } mouse_timed_out = FALSE; -#if GTK_CHECK_VERSION(3,0,0) - mouse_click_timer = g_timeout_add((guint)p_mouset, - mouse_click_timer_cb, &mouse_timed_out); -#else - mouse_click_timer = gtk_timeout_add((guint32)p_mouset, - mouse_click_timer_cb, &mouse_timed_out); -#endif + mouse_click_timer = timeout_add(p_mouset, mouse_click_timer_cb, + &mouse_timed_out); switch (event->button) { @@ -2129,11 +2103,7 @@ button_release_event(GtkWidget *widget U area .*/ if (motion_repeat_timer) { -#if GTK_CHECK_VERSION(3,0,0) - g_source_remove(motion_repeat_timer); -#else - gtk_timeout_remove(motion_repeat_timer); -#endif + timeout_remove(motion_repeat_timer); motion_repeat_timer = 0; } @@ -4578,7 +4548,7 @@ mainwin_destroy_cb(GtkObject *object UNU * scrollbar init.), actually do the standard hints and stop the timer. * We'll not let the default hints be set while this timer's active. */ - static gboolean + static timeout_cb_type check_startup_plug_hints(gpointer data UNUSED) { if (init_window_hints_state == 1) @@ -4681,7 +4651,7 @@ gui_mch_open(void) { update_window_manager_hints(pixel_width, pixel_height); init_window_hints_state = 1; - g_timeout_add(1000, check_startup_plug_hints, NULL); + timeout_add(1000, check_startup_plug_hints, NULL); } } @@ -6584,11 +6554,7 @@ gui_mch_update(void) g_main_context_iteration(NULL, TRUE); } -#if GTK_CHECK_VERSION(3,0,0) - static gboolean -#else - static gint -#endif + static timeout_cb_type input_timer_cb(gpointer data) { int *timed_out = (int *) data; @@ -6599,6 +6565,19 @@ input_timer_cb(gpointer data) return FALSE; /* don't happen again */ } +#ifdef FEAT_JOB_CHANNEL + static timeout_cb_type +channel_poll_cb(gpointer data UNUSED) +{ + /* Using an event handler for a channel that may be disconnected does + * not work, it hangs. Instead poll for messages. */ + channel_handle_events(TRUE); + parse_queued_messages(); + + return TRUE; /* repeat */ +} +#endif + /* * GUI input routine called by gui_wait_for_chars(). Waits for a character * from the keyboard. @@ -6615,20 +6594,26 @@ gui_mch_wait_for_chars(long wtime) guint timer; static int timed_out; int retval = FAIL; +#ifdef FEAT_JOB_CHANNEL + guint channel_timer = 0; +#endif timed_out = FALSE; /* this timeout makes sure that we will return if no characters arrived in * time */ if (wtime > 0) -#if GTK_CHECK_VERSION(3,0,0) - timer = g_timeout_add((guint)wtime, input_timer_cb, &timed_out); -#else - timer = gtk_timeout_add((guint32)wtime, input_timer_cb, &timed_out); -#endif + timer = timeout_add(wtime, input_timer_cb, &timed_out); else timer = 0; +#ifdef FEAT_JOB_CHANNEL + /* If there is a channel with the keep_open flag we need to poll for input + * on them. */ + if (channel_any_keep_open()) + channel_timer = timeout_add(20, channel_poll_cb, NULL); +#endif + focus = gui.in_focus; do @@ -6643,12 +6628,6 @@ gui_mch_wait_for_chars(long wtime) focus = gui.in_focus; } -# if defined(FEAT_JOB_CHANNEL) - /* Using an event handler for a channel that may be disconnected does - * not work, it hangs. Instead poll for messages. */ - channel_handle_events(TRUE); -# endif - #ifdef MESSAGE_QUEUE # ifdef FEAT_TIMERS did_add_timer = FALSE; @@ -6684,10 +6663,10 @@ gui_mch_wait_for_chars(long wtime) theend: if (timer != 0 && !timed_out) -#if GTK_CHECK_VERSION(3,0,0) - g_source_remove(timer); -#else - gtk_timeout_remove(timer); + timeout_remove(timer); +#ifdef FEAT_JOB_CHANNEL + if (channel_timer != 0) + timeout_remove(channel_timer); #endif return retval; diff --git a/src/proto/channel.pro b/src/proto/channel.pro --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -35,6 +35,7 @@ char_u *channel_read_block(channel_T *ch void common_channel_read(typval_T *argvars, typval_T *rettv, int raw); channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp); void channel_handle_events(int only_keep_open); +int channel_any_keep_open(void); void channel_set_nonblock(channel_T *channel, ch_part_T part); int channel_send(channel_T *channel, ch_part_T part, char_u *buf_arg, int len_arg, char *fun); void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1005, +/**/ 1004, /**/ 1003,