[pacman-dev] [PATCH] Hide cursor while pacman is running

Anatol Pomozov anatol.pomozov at gmail.com
Wed Mar 4 20:56:10 UTC 2020


Use ASCII control codes to hide cursor at the pacman start and then
show the cursor when pacman finishes.

It helps to avoid annoying blinking when progress bars are re-drawn.

Cursor is reenabled if pacman expects user's input.

Signed-off-by: Anatol Pomozov <anatol.pomozov at gmail.com>
---
 src/common/util-common.c | 15 +++++++++++++++
 src/common/util-common.h |  3 +++
 src/pacman/pacman.c      |  2 ++
 src/pacman/sighandler.c  |  5 +++++
 4 files changed, 25 insertions(+)

diff --git a/src/common/util-common.c b/src/common/util-common.c
index 7d43ac0d..ad2a8ad1 100644
--- a/src/common/util-common.c
+++ b/src/common/util-common.c
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "util-common.h"
 
@@ -104,6 +105,18 @@ int llstat(char *path, struct stat *buf)
 	return ret;
 }
 
+void console_hide_cursor(void) {
+	if(isatty(fileno(stdout))) {
+		printf("\e[?25l");
+	}
+}
+
+void console_show_cursor(void) {
+	if(isatty(fileno(stdout))) {
+		printf("\e[?25h");
+	}
+}
+
 /** Wrapper around fgets() which properly handles EINTR
  * @param s string to read into
  * @param size maximum length to read
@@ -114,6 +127,7 @@ char *safe_fgets(char *s, int size, FILE *stream)
 {
 	char *ret;
 	int errno_save = errno, ferror_save = ferror(stream);
+	console_show_cursor();
 	while((ret = fgets(s, size, stream)) == NULL && !feof(stream)) {
 		if(errno == EINTR) {
 			/* clear any errors we set and try again */
@@ -125,6 +139,7 @@ char *safe_fgets(char *s, int size, FILE *stream)
 			break;
 		}
 	}
+	console_hide_cursor();
 	return ret;
 }
 
diff --git a/src/common/util-common.h b/src/common/util-common.h
index 483d5da4..8eacde7e 100644
--- a/src/common/util-common.h
+++ b/src/common/util-common.h
@@ -28,6 +28,9 @@ char *mdirname(const char *path);
 
 int llstat(char *path, struct stat *buf);
 
+void console_hide_cursor(void);
+void console_show_cursor(void);
+
 char *safe_fgets(char *s, int size, FILE *stream);
 
 void wordsplit_free(char **ws);
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index d58c428a..aafd9e63 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -300,6 +300,7 @@ static void cleanup(int ret)
 
 	/* free memory */
 	FREELIST(pm_targets);
+	console_show_cursor();
 	exit(ret);
 }
 
@@ -1084,6 +1085,7 @@ int main(int argc, char *argv[])
 	int ret = 0;
 	uid_t myuid = getuid();
 
+	console_hide_cursor();
 	install_segv_handler();
 
 	/* i18n init */
diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c
index 46e6481f..adad411a 100644
--- a/src/pacman/sighandler.c
+++ b/src/pacman/sighandler.c
@@ -27,6 +27,9 @@
 #include "sighandler.h"
 #include "util.h"
 
+/* the same ANSI sequence as used in console_show_cursor */
+#define SHOW_CURSOR_ANSI "\e[?25h"
+
 /** Write function that correctly handles EINTR.
  */
 static ssize_t xwrite(int fd, const void *buf, size_t count)
@@ -60,6 +63,7 @@ static void soft_interrupt_handler(int signum)
 		const char msg[] = "\nHangup signal received\n";
 		xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1);
 	}
+	xwrite(STDOUT_FILENO, SHOW_CURSOR_ANSI, sizeof(SHOW_CURSOR_ANSI) - 1);
 	if(alpm_trans_interrupt(config->handle) == 0) {
 		/* a transaction is being interrupted, don't exit pacman yet. */
 		return;
@@ -95,6 +99,7 @@ static void segv_handler(int signum)
 	const char msg[] = "\nerror: segmentation fault\n"
 		"Please submit a full bug report with --debug if appropriate.\n";
 	xwrite(STDERR_FILENO, msg, sizeof(msg) - 1);
+	xwrite(STDOUT_FILENO, SHOW_CURSOR_ANSI, sizeof(SHOW_CURSOR_ANSI) - 1);
 
 	/* restore the default handler */
 	_reset_handler(signum);
-- 
2.25.1


More information about the pacman-dev mailing list