To: vim_dev@googlegroups.com Subject: Patch 8.0.1005 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1005 Problem: Terminal without job updates slowly in GUI. Solution: Poll for input when a channel has the keep_open flag. Files: src/channel.c, src/proto/channel.pro, src/gui_gtk_x11.c *** ../vim-8.0.1004/src/channel.c 2017-08-27 13:10:04.360022105 +0200 --- src/channel.c 2017-08-27 13:56:29.098603553 +0200 *************** *** 3555,3560 **** --- 3555,3576 ---- } # 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. *** ../vim-8.0.1004/src/proto/channel.pro 2017-08-26 22:02:45.869432874 +0200 --- src/proto/channel.pro 2017-08-27 14:38:22.874521535 +0200 *************** *** 35,40 **** --- 35,41 ---- 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); *** ../vim-8.0.1004/src/gui_gtk_x11.c 2017-08-26 22:02:45.869432874 +0200 --- src/gui_gtk_x11.c 2017-08-27 14:48:01.314799577 +0200 *************** *** 789,794 **** --- 789,825 ---- #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,876 **** { if (blink_timer) { ! #if GTK_CHECK_VERSION(3,0,0) ! g_source_remove(blink_timer); ! #else ! gtk_timeout_remove(blink_timer); ! #endif blink_timer = 0; } if (blink_state == BLINK_OFF) --- 897,903 ---- { if (blink_timer) { ! timeout_remove(blink_timer); blink_timer = 0; } if (blink_state == BLINK_OFF) *************** *** 881,916 **** blink_state = BLINK_NONE; } ! #if GTK_CHECK_VERSION(3,0,0) ! static gboolean ! #else ! static gint ! #endif 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 } 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 } gui_mch_flush(); --- 908,927 ---- blink_state = BLINK_NONE; } ! static timeout_cb_type blink_cb(gpointer data UNUSED) { if (blink_state == BLINK_ON) { gui_undraw_cursor(); blink_state = BLINK_OFF; ! blink_timer = timeout_add(blink_offtime, blink_cb, NULL); } else { gui_update_cursor(TRUE, FALSE); blink_state = BLINK_ON; ! blink_timer = timeout_add(blink_ontime, blink_cb, NULL); } gui_mch_flush(); *************** *** 926,948 **** { if (blink_timer) { ! #if GTK_CHECK_VERSION(3,0,0) ! g_source_remove(blink_timer); ! #else ! gtk_timeout_remove(blink_timer); ! #endif 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_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); gui_mch_flush(); --- 937,949 ---- { if (blink_timer) { ! 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) { ! blink_timer = timeout_add(blink_waittime, blink_cb, NULL); blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); gui_mch_flush(); *************** *** 1733,1739 **** return OK; } - /**************************************************************************** * Mouse handling callbacks */ --- 1734,1739 ---- *************** *** 1745,1755 **** /* * Timer used to recognize multiple clicks of the mouse button */ ! #if GTK_CHECK_VERSION(3,0,0) ! static gboolean ! #else ! static gint ! #endif mouse_click_timer_cb(gpointer data) { /* we don't use this information currently */ --- 1745,1751 ---- /* * Timer used to recognize multiple clicks of the mouse button */ ! static timeout_cb_type mouse_click_timer_cb(gpointer data) { /* we don't use this information currently */ *************** *** 1759,1771 **** 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 void process_motion_notify(int x, int y, GdkModifierType state) --- 1755,1763 ---- return FALSE; /* don't happen again */ } ! 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,1865 **** /* 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 } } --- 1845,1852 ---- /* shoot again */ if (!motion_repeat_timer) ! motion_repeat_timer = timeout_add(delay, motion_repeat_timer_cb, ! NULL); } } *************** *** 1904,1914 **** /* * Timer used to recognize multiple clicks of the mouse button. */ ! #if GTK_CHECK_VERSION(3,0,0) ! static gboolean ! #else ! static gint ! #endif motion_repeat_timer_cb(gpointer data UNUSED) { int x; --- 1891,1897 ---- /* * Timer used to recognize multiple clicks of the mouse button. */ ! static timeout_cb_type motion_repeat_timer_cb(gpointer data UNUSED) { int x; *************** *** 2019,2041 **** /* 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 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 switch (event->button) { --- 2002,2015 ---- /* Handle multiple clicks */ if (!mouse_timed_out && mouse_click_timer) { ! timeout_remove(mouse_click_timer); mouse_click_timer = 0; repeated_click = TRUE; } mouse_timed_out = FALSE; ! mouse_click_timer = timeout_add(p_mouset, mouse_click_timer_cb, ! &mouse_timed_out); switch (event->button) { *************** *** 2129,2139 **** 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 motion_repeat_timer = 0; } --- 2103,2109 ---- area .*/ if (motion_repeat_timer) { ! timeout_remove(motion_repeat_timer); motion_repeat_timer = 0; } *************** *** 4578,4584 **** * 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 check_startup_plug_hints(gpointer data UNUSED) { if (init_window_hints_state == 1) --- 4548,4554 ---- * 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 timeout_cb_type check_startup_plug_hints(gpointer data UNUSED) { if (init_window_hints_state == 1) *************** *** 4681,4687 **** { update_window_manager_hints(pixel_width, pixel_height); init_window_hints_state = 1; ! g_timeout_add(1000, check_startup_plug_hints, NULL); } } --- 4651,4657 ---- { update_window_manager_hints(pixel_width, pixel_height); init_window_hints_state = 1; ! timeout_add(1000, check_startup_plug_hints, NULL); } } *************** *** 6584,6594 **** g_main_context_iteration(NULL, TRUE); } ! #if GTK_CHECK_VERSION(3,0,0) ! static gboolean ! #else ! static gint ! #endif input_timer_cb(gpointer data) { int *timed_out = (int *) data; --- 6554,6560 ---- g_main_context_iteration(NULL, TRUE); } ! static timeout_cb_type input_timer_cb(gpointer data) { int *timed_out = (int *) data; *************** *** 6599,6604 **** --- 6565,6583 ---- 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,6634 **** guint timer; static int timed_out; int retval = FAIL; 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 else timer = 0; focus = gui.in_focus; do --- 6594,6619 ---- 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) ! 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,6654 **** 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; --- 6628,6633 ---- *************** *** 6684,6693 **** theend: if (timer != 0 && !timed_out) ! #if GTK_CHECK_VERSION(3,0,0) ! g_source_remove(timer); ! #else ! gtk_timeout_remove(timer); #endif return retval; --- 6663,6672 ---- theend: if (timer != 0 && !timed_out) ! timeout_remove(timer); ! #ifdef FEAT_JOB_CHANNEL ! if (channel_timer != 0) ! timeout_remove(channel_timer); #endif return retval; *** ../vim-8.0.1004/src/version.c 2017-08-27 13:50:58.088678687 +0200 --- src/version.c 2017-08-27 13:58:08.129983124 +0200 *************** *** 771,772 **** --- 771,774 ---- { /* Add new patch number below this line */ + /**/ + 1005, /**/ -- How To Keep A Healthy Level Of Insanity: 9. As often as possible, skip rather than walk. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///