]> granicus.if.org Git - vim/commitdiff
patch 8.0.1005: terminal without job updates slowly in GUI v8.0.1005
authorBram Moolenaar <Bram@vim.org>
Sun, 27 Aug 2017 12:50:47 +0000 (14:50 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 27 Aug 2017 12:50:47 +0000 (14:50 +0200)
Problem:    Terminal without job updates slowly in GUI.
Solution:   Poll for input when a channel has the keep_open flag.

src/channel.c
src/gui_gtk_x11.c
src/proto/channel.pro
src/version.c

index 508fb0c0f32bf8993ec198cb4650b21fe977e384..b7a268a79a8bdf2614403fec7d486da7751cc074 100644 (file)
@@ -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.
index cfbb36ce933a80938bc73eb6dd112a85fbe71553..3d4ac93ae4c8bc79f59e13f2c8a1ba0641f93640 100644 (file)
@@ -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, GdkModifierType state)
 
        /* 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 *widget,
 /*
  * 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 UNUSED,
        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 UNUSED, gpointer data UNUSED)
  * 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;
index 1b9282c1a8a888f411b1ea3f12a04f548dc4738d..a3a4dc701238923afd3778c56fdebb99e02bfeab 100644 (file)
@@ -35,6 +35,7 @@ char_u *channel_read_block(channel_T *channel, ch_part_T part, int timeout);
 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);
index 4773895079ef6fb7703abf0435ec7e43c5ad6687..68f3534f6dd81b2efce1e53207a0ce74bd0e5b7a 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1005,
 /**/
     1004,
 /**/