Skip to content

Commit 4ab7968

Browse files
committed
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.
1 parent 8d9f0ef commit 4ab7968

4 files changed

Lines changed: 98 additions & 100 deletions

File tree

src/channel.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3555,6 +3555,22 @@ channel_handle_events(int only_keep_open)
35553555
}
35563556
# endif
35573557

3558+
# if defined(FEAT_GUI) || defined(PROTO)
3559+
/*
3560+
* Return TRUE when there is any channel with a keep_open flag.
3561+
*/
3562+
int
3563+
channel_any_keep_open()
3564+
{
3565+
channel_T *channel;
3566+
3567+
for (channel = first_channel; channel != NULL; channel = channel->ch_next)
3568+
if (channel->ch_keep_open)
3569+
return TRUE;
3570+
return FALSE;
3571+
}
3572+
# endif
3573+
35583574
/*
35593575
* Set "channel"/"part" to non-blocking.
35603576
* Only works for sockets and pipes.

src/gui_gtk_x11.c

Lines changed: 79 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,37 @@ property_event(GtkWidget *widget,
789789
#endif /* defined(FEAT_CLIENTSERVER) */
790790

791791

792+
#if GTK_CHECK_VERSION(3,0,0)
793+
typedef gboolean timeout_cb_type;
794+
#else
795+
typedef gint timeout_cb_type;
796+
#endif
797+
798+
/*
799+
* Start a timer that will invoke the specified callback.
800+
* Returns the ID of the timer.
801+
*/
802+
static guint
803+
timeout_add(int time, timeout_cb_type (*callback)(gpointer), int *flagp)
804+
{
805+
#if GTK_CHECK_VERSION(3,0,0)
806+
return g_timeout_add((guint)time, (GSourceFunc)callback, flagp);
807+
#else
808+
return gtk_timeout_add((guint32)time, (GtkFunction)callback, flagp);
809+
#endif
810+
}
811+
812+
static void
813+
timeout_remove(guint timer)
814+
{
815+
#if GTK_CHECK_VERSION(3,0,0)
816+
g_source_remove(timer);
817+
#else
818+
gtk_timeout_remove(timer);
819+
#endif
820+
}
821+
822+
792823
/****************************************************************************
793824
* Focus handlers:
794825
*/
@@ -866,11 +897,7 @@ gui_mch_stop_blink(void)
866897
{
867898
if (blink_timer)
868899
{
869-
#if GTK_CHECK_VERSION(3,0,0)
870-
g_source_remove(blink_timer);
871-
#else
872-
gtk_timeout_remove(blink_timer);
873-
#endif
900+
timeout_remove(blink_timer);
874901
blink_timer = 0;
875902
}
876903
if (blink_state == BLINK_OFF)
@@ -881,36 +908,20 @@ gui_mch_stop_blink(void)
881908
blink_state = BLINK_NONE;
882909
}
883910

884-
#if GTK_CHECK_VERSION(3,0,0)
885-
static gboolean
886-
#else
887-
static gint
888-
#endif
911+
static timeout_cb_type
889912
blink_cb(gpointer data UNUSED)
890913
{
891914
if (blink_state == BLINK_ON)
892915
{
893916
gui_undraw_cursor();
894917
blink_state = BLINK_OFF;
895-
#if GTK_CHECK_VERSION(3,0,0)
896-
blink_timer = g_timeout_add((guint)blink_offtime,
897-
(GSourceFunc) blink_cb, NULL);
898-
#else
899-
blink_timer = gtk_timeout_add((guint32)blink_offtime,
900-
(GtkFunction) blink_cb, NULL);
901-
#endif
918+
blink_timer = timeout_add(blink_offtime, blink_cb, NULL);
902919
}
903920
else
904921
{
905922
gui_update_cursor(TRUE, FALSE);
906923
blink_state = BLINK_ON;
907-
#if GTK_CHECK_VERSION(3,0,0)
908-
blink_timer = g_timeout_add((guint)blink_ontime,
909-
(GSourceFunc) blink_cb, NULL);
910-
#else
911-
blink_timer = gtk_timeout_add((guint32)blink_ontime,
912-
(GtkFunction) blink_cb, NULL);
913-
#endif
924+
blink_timer = timeout_add(blink_ontime, blink_cb, NULL);
914925
}
915926
gui_mch_flush();
916927

@@ -926,23 +937,13 @@ gui_mch_start_blink(void)
926937
{
927938
if (blink_timer)
928939
{
929-
#if GTK_CHECK_VERSION(3,0,0)
930-
g_source_remove(blink_timer);
931-
#else
932-
gtk_timeout_remove(blink_timer);
933-
#endif
940+
timeout_remove(blink_timer);
934941
blink_timer = 0;
935942
}
936943
/* Only switch blinking on if none of the times is zero */
937944
if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
938945
{
939-
#if GTK_CHECK_VERSION(3,0,0)
940-
blink_timer = g_timeout_add((guint)blink_waittime,
941-
(GSourceFunc) blink_cb, NULL);
942-
#else
943-
blink_timer = gtk_timeout_add((guint32)blink_waittime,
944-
(GtkFunction) blink_cb, NULL);
945-
#endif
946+
blink_timer = timeout_add(blink_waittime, blink_cb, NULL);
946947
blink_state = BLINK_ON;
947948
gui_update_cursor(TRUE, FALSE);
948949
gui_mch_flush();
@@ -1733,7 +1734,6 @@ gui_mch_init_check(void)
17331734
return OK;
17341735
}
17351736

1736-
17371737
/****************************************************************************
17381738
* Mouse handling callbacks
17391739
*/
@@ -1745,11 +1745,7 @@ static int mouse_timed_out = TRUE;
17451745
/*
17461746
* Timer used to recognize multiple clicks of the mouse button
17471747
*/
1748-
#if GTK_CHECK_VERSION(3,0,0)
1749-
static gboolean
1750-
#else
1751-
static gint
1752-
#endif
1748+
static timeout_cb_type
17531749
mouse_click_timer_cb(gpointer data)
17541750
{
17551751
/* we don't use this information currently */
@@ -1759,13 +1755,9 @@ mouse_click_timer_cb(gpointer data)
17591755
return FALSE; /* don't happen again */
17601756
}
17611757

1762-
static guint motion_repeat_timer = 0;
1763-
static int motion_repeat_offset = FALSE;
1764-
#ifdef GTK_DEST_DEFAULT_ALL
1765-
static gboolean motion_repeat_timer_cb(gpointer);
1766-
#else
1767-
static gint motion_repeat_timer_cb(gpointer);
1768-
#endif
1758+
static guint motion_repeat_timer = 0;
1759+
static int motion_repeat_offset = FALSE;
1760+
static timeout_cb_type motion_repeat_timer_cb(gpointer);
17691761

17701762
static void
17711763
process_motion_notify(int x, int y, GdkModifierType state)
@@ -1853,13 +1845,8 @@ process_motion_notify(int x, int y, GdkModifierType state)
18531845

18541846
/* shoot again */
18551847
if (!motion_repeat_timer)
1856-
#if GTK_CHECK_VERSION(3,0,0)
1857-
motion_repeat_timer = g_timeout_add((guint)delay,
1858-
motion_repeat_timer_cb, NULL);
1859-
#else
1860-
motion_repeat_timer = gtk_timeout_add((guint32)delay,
1861-
motion_repeat_timer_cb, NULL);
1862-
#endif
1848+
motion_repeat_timer = timeout_add(delay, motion_repeat_timer_cb,
1849+
NULL);
18631850
}
18641851
}
18651852

@@ -1904,11 +1891,7 @@ gui_gtk_window_at_position(GtkWidget *widget,
19041891
/*
19051892
* Timer used to recognize multiple clicks of the mouse button.
19061893
*/
1907-
#if GTK_CHECK_VERSION(3,0,0)
1908-
static gboolean
1909-
#else
1910-
static gint
1911-
#endif
1894+
static timeout_cb_type
19121895
motion_repeat_timer_cb(gpointer data UNUSED)
19131896
{
19141897
int x;
@@ -2019,23 +2002,14 @@ button_press_event(GtkWidget *widget,
20192002
/* Handle multiple clicks */
20202003
if (!mouse_timed_out && mouse_click_timer)
20212004
{
2022-
#if GTK_CHECK_VERSION(3,0,0)
2023-
g_source_remove(mouse_click_timer);
2024-
#else
2025-
gtk_timeout_remove(mouse_click_timer);
2026-
#endif
2005+
timeout_remove(mouse_click_timer);
20272006
mouse_click_timer = 0;
20282007
repeated_click = TRUE;
20292008
}
20302009

20312010
mouse_timed_out = FALSE;
2032-
#if GTK_CHECK_VERSION(3,0,0)
2033-
mouse_click_timer = g_timeout_add((guint)p_mouset,
2034-
mouse_click_timer_cb, &mouse_timed_out);
2035-
#else
2036-
mouse_click_timer = gtk_timeout_add((guint32)p_mouset,
2037-
mouse_click_timer_cb, &mouse_timed_out);
2038-
#endif
2011+
mouse_click_timer = timeout_add(p_mouset, mouse_click_timer_cb,
2012+
&mouse_timed_out);
20392013

20402014
switch (event->button)
20412015
{
@@ -2129,11 +2103,7 @@ button_release_event(GtkWidget *widget UNUSED,
21292103
area .*/
21302104
if (motion_repeat_timer)
21312105
{
2132-
#if GTK_CHECK_VERSION(3,0,0)
2133-
g_source_remove(motion_repeat_timer);
2134-
#else
2135-
gtk_timeout_remove(motion_repeat_timer);
2136-
#endif
2106+
timeout_remove(motion_repeat_timer);
21372107
motion_repeat_timer = 0;
21382108
}
21392109

@@ -4578,7 +4548,7 @@ mainwin_destroy_cb(GtkObject *object UNUSED, gpointer data UNUSED)
45784548
* scrollbar init.), actually do the standard hints and stop the timer.
45794549
* We'll not let the default hints be set while this timer's active.
45804550
*/
4581-
static gboolean
4551+
static timeout_cb_type
45824552
check_startup_plug_hints(gpointer data UNUSED)
45834553
{
45844554
if (init_window_hints_state == 1)
@@ -4681,7 +4651,7 @@ gui_mch_open(void)
46814651
{
46824652
update_window_manager_hints(pixel_width, pixel_height);
46834653
init_window_hints_state = 1;
4684-
g_timeout_add(1000, check_startup_plug_hints, NULL);
4654+
timeout_add(1000, check_startup_plug_hints, NULL);
46854655
}
46864656
}
46874657

@@ -6584,11 +6554,7 @@ gui_mch_update(void)
65846554
g_main_context_iteration(NULL, TRUE);
65856555
}
65866556

6587-
#if GTK_CHECK_VERSION(3,0,0)
6588-
static gboolean
6589-
#else
6590-
static gint
6591-
#endif
6557+
static timeout_cb_type
65926558
input_timer_cb(gpointer data)
65936559
{
65946560
int *timed_out = (int *) data;
@@ -6599,6 +6565,19 @@ input_timer_cb(gpointer data)
65996565
return FALSE; /* don't happen again */
66006566
}
66016567

6568+
#ifdef FEAT_JOB_CHANNEL
6569+
static timeout_cb_type
6570+
channel_poll_cb(gpointer data UNUSED)
6571+
{
6572+
/* Using an event handler for a channel that may be disconnected does
6573+
* not work, it hangs. Instead poll for messages. */
6574+
channel_handle_events(TRUE);
6575+
parse_queued_messages();
6576+
6577+
return TRUE; /* repeat */
6578+
}
6579+
#endif
6580+
66026581
/*
66036582
* GUI input routine called by gui_wait_for_chars(). Waits for a character
66046583
* from the keyboard.
@@ -6615,20 +6594,26 @@ gui_mch_wait_for_chars(long wtime)
66156594
guint timer;
66166595
static int timed_out;
66176596
int retval = FAIL;
6597+
#ifdef FEAT_JOB_CHANNEL
6598+
guint channel_timer = 0;
6599+
#endif
66186600

66196601
timed_out = FALSE;
66206602

66216603
/* this timeout makes sure that we will return if no characters arrived in
66226604
* time */
66236605
if (wtime > 0)
6624-
#if GTK_CHECK_VERSION(3,0,0)
6625-
timer = g_timeout_add((guint)wtime, input_timer_cb, &timed_out);
6626-
#else
6627-
timer = gtk_timeout_add((guint32)wtime, input_timer_cb, &timed_out);
6628-
#endif
6606+
timer = timeout_add(wtime, input_timer_cb, &timed_out);
66296607
else
66306608
timer = 0;
66316609

6610+
#ifdef FEAT_JOB_CHANNEL
6611+
/* If there is a channel with the keep_open flag we need to poll for input
6612+
* on them. */
6613+
if (channel_any_keep_open())
6614+
channel_timer = timeout_add(20, channel_poll_cb, NULL);
6615+
#endif
6616+
66326617
focus = gui.in_focus;
66336618

66346619
do
@@ -6643,12 +6628,6 @@ gui_mch_wait_for_chars(long wtime)
66436628
focus = gui.in_focus;
66446629
}
66456630

6646-
# if defined(FEAT_JOB_CHANNEL)
6647-
/* Using an event handler for a channel that may be disconnected does
6648-
* not work, it hangs. Instead poll for messages. */
6649-
channel_handle_events(TRUE);
6650-
# endif
6651-
66526631
#ifdef MESSAGE_QUEUE
66536632
# ifdef FEAT_TIMERS
66546633
did_add_timer = FALSE;
@@ -6684,10 +6663,10 @@ gui_mch_wait_for_chars(long wtime)
66846663

66856664
theend:
66866665
if (timer != 0 && !timed_out)
6687-
#if GTK_CHECK_VERSION(3,0,0)
6688-
g_source_remove(timer);
6689-
#else
6690-
gtk_timeout_remove(timer);
6666+
timeout_remove(timer);
6667+
#ifdef FEAT_JOB_CHANNEL
6668+
if (channel_timer != 0)
6669+
timeout_remove(channel_timer);
66916670
#endif
66926671

66936672
return retval;

src/proto/channel.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ char_u *channel_read_block(channel_T *channel, ch_part_T part, int timeout);
3535
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
3636
channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp);
3737
void channel_handle_events(int only_keep_open);
38+
int channel_any_keep_open(void);
3839
void channel_set_nonblock(channel_T *channel, ch_part_T part);
3940
int channel_send(channel_T *channel, ch_part_T part, char_u *buf_arg, int len_arg, char *fun);
4041
void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,8 @@ static char *(features[]) =
769769

770770
static int included_patches[] =
771771
{ /* Add new patch number below this line */
772+
/**/
773+
1005,
772774
/**/
773775
1004,
774776
/**/

0 commit comments

Comments
 (0)