Some applications like vi(1) and tmux until 10 minutes or so ago, do not
authornicm <nicm@openbsd.org>
Wed, 31 May 2017 11:00:00 +0000 (11:00 +0000)
committernicm <nicm@openbsd.org>
Wed, 31 May 2017 11:00:00 +0000 (11:00 +0000)
redraw on SIGWINCH if the size returns to the original size between the
original SIGWINCH and when they get around to calling TIOCGWINSZ. So use
the existing resize timer to introduce a small delay between the two
resizes.

usr.bin/tmux/server-client.c
usr.bin/tmux/tmux.h

index 0862a96..1c8e78e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.236 2017/05/31 10:29:15 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.237 2017/05/31 11:00:00 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1038,6 +1038,44 @@ server_client_loop(void)
        }
 }
 
+/* Check if we need to force a resize. */
+static int
+server_client_resize_force(struct window_pane *wp)
+{
+       struct timeval  tv = { .tv_usec = 100000 };
+       struct winsize  ws;
+
+       /*
+        * If we are resizing to the same size as when we entered the loop
+        * (that is, to the same size the application currently thinks it is),
+        * tmux may have gone through several resizes internally and thrown
+        * away parts of the screen. So we need the application to actually
+        * redraw even though its final size has not changed.
+        */
+
+       if (wp->flags & PANE_RESIZEFORCE) {
+               wp->flags &= ~PANE_RESIZEFORCE;
+               return (0);
+       }
+
+       if (wp->sx != wp->osx ||
+           wp->sy != wp->osy ||
+           wp->sx <= 1 ||
+           wp->sy <= 1)
+               return (0);
+
+       memset(&ws, 0, sizeof ws);
+       ws.ws_col = wp->sx;
+       ws.ws_row = wp->sy - 1;
+       if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
+               fatal("ioctl failed");
+       log_debug("%s: %%%u forcing resize", __func__, wp->id);
+
+       evtimer_add(&wp->resize_timer, &tv);
+       wp->flags |= PANE_RESIZEFORCE;
+       return (1);
+}
+
 /* Resize timer event. */
 static void
 server_client_resize_event(__unused int fd, __unused short events, void *data)
@@ -1049,25 +1087,8 @@ server_client_resize_event(__unused int fd, __unused short events, void *data)
 
        if (!(wp->flags & PANE_RESIZE))
                return;
-
-       /*
-        * If we are resizing to the same size as when we entered the loop
-        * (that is, to the same size the application currently thinks it is),
-        * tmux may have gone through several resizes internally and thrown
-        * away parts of the screen. So we need the application to actually
-        * redraw even though its final size has not changed.
-        */
-       if (wp->sx == wp->osx &&
-           wp->sy == wp->osy &&
-           wp->sx > 1 &&
-           wp->sy > 1) {
-               memset(&ws, 0, sizeof ws);
-               ws.ws_col = wp->sx - 1;
-               ws.ws_row = wp->sy - 1;
-               if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
-                       fatal("ioctl failed");
-               log_debug("%s: %%%u forcing resize", __func__, wp->id);
-       }
+       if (server_client_resize_force(wp))
+               return;
 
        memset(&ws, 0, sizeof ws);
        ws.ws_col = wp->sx;
index 4253d4d..6c72939 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.778 2017/05/31 10:29:15 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.779 2017/05/31 11:00:00 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -756,9 +756,10 @@ struct window_pane {
 #define PANE_DROP 0x2
 #define PANE_FOCUSED 0x4
 #define PANE_RESIZE 0x8
-#define PANE_FOCUSPUSH 0x10
-#define PANE_INPUTOFF 0x20
-#define PANE_CHANGED 0x40
+#define PANE_RESIZEFORCE 0x10
+#define PANE_FOCUSPUSH 0x20
+#define PANE_INPUTOFF 0x40
+#define PANE_CHANGED 0x80
 
        int              argc;
        char           **argv;