Attachment/Detachment is not working propertly
vbarbarosh opened this issue · comments
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.2 (jessie)
Release: 8.2
Codename: jessie
$ wget https://github.com/martanne/abduco/archive/v0.4.tar.gz
$ tar xf v0.4.tar.gz
$ cd abduco-0.4
$ make
$ ./abduco -c hello htop
--- CTRL-\ ---
$ ./abduco
Active sessions (on host corei3)
$ ./abduco -a hello
Thanks for the detailed report!
abduco expects that the client application redraws its complete user interface after having received a SIGWINCH
signal. This doesn't seem to be the case for htop though (maybe its developers want to chime in and correct me here @hishamhm). If you resize the terminal (either before or after re-attaching) it redraws correctly, right?
A short term "solution" is to run abduco -c hello dvtm htop
that way dvtm will catch the SIGWINCH
signal and redraw all its client windows even if the terminal size did not change.
@martanne Hi! I produce a full redraw in htop when I get a KEY_RESIZE from ncurses. Perhaps ncurses is not triggering a KEY_RESIZE event if it gets SIGWINCH and the size didn't really change.
That is what I suspected, but after skimming through the ncurses sources (they are a big mess by the way) it seems to emit it. I wrote the following test program to confirm it.
#include <curses.h>
#include <time.h>
int main(int argc, char *argv[]) {
initscr();
for (;;) {
int key = getch();
switch (key) {
case ERR:
addstr("getch failed\n");
break;
case KEY_RESIZE:
{
char buf[1024];
time_t t = time(NULL);
struct tm *now = localtime(&t);
if (!now) {
addstr("localtime failed\n");
break;
}
strftime(buf, sizeof buf, "%c", now);
addstr(buf);
addstr(" RESIZE\n");
break;
}
case 'q':
endwin();
return 0;
}
refresh();
}
}
I think the "problem" is that curses caches the screen content, when you then redraw the interface in response to a KEY_RESIZE
it will only emit the changes made since the last redraw (it doesn't know that we are connecting from an empty terminal). Adding a clear()
call before redrawing the user interface would likely fix it. Is there a central place to add such a call and confirm my suspicion?
Is there a central place to add such a call and confirm my suspicion?
In htop? In current git, I think you can do it in function ScreenManager_resize
.
That is what I had expected, unfortunately ScreenManager_resize
never gets called. What happens is the following ScreenManager_run
- calls
getch()
- invokes the event handler of the main pannel with
KEY_RESIZE
as key- The event handler dispatches based on the registered actions in its keys array and sets
result = HANDLED
- The registered action for KEY_RESIZE is actionResize
- The event handler dispatches based on the registered actions in its keys array and sets
result & HANDLED
is true and the loop is started from the beginning without having calledScreenManager_resize
The patch below seems to fix the issue for me. I also added a clear
call to ScreenManager_resize
in case other panels do not handle KEY_RESIZE
on their own.
From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= <mat@brain-dump.org>
Date: Thu, 7 Jan 2016 12:32:57 +0100
Subject: [PATCH] Redraw complete user interface upon terminal resize
---
Action.c | 10 +++++-----
ScreenManager.c | 1 +
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/Action.c b/Action.c
index 5e0e109..e81fe97 100644
--- a/Action.c
+++ b/Action.c
@@ -183,11 +183,6 @@ static Htop_Reaction sortBy(State* st) {
// ----------------------------------------
-static Htop_Reaction actionResize(State* st) {
- Panel_resize(st->panel, COLS, LINES-(st->panel->y)-1);
- return HTOP_REDRAW_BAR;
-}
-
static Htop_Reaction actionSortByMemory(State* st) {
return Action_setSortKey(st->settings, PERCENT_MEM);
}
@@ -377,6 +372,11 @@ static Htop_Reaction actionRedraw() {
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}
+static Htop_Reaction actionResize(State* st) {
+ Panel_resize(st->panel, COLS, LINES-(st->panel->y)-1);
+ return actionRedraw();
+}
+
static struct { const char* key; const char* info; } helpLeft[] = {
{ .key = " Arrows: ", .info = "scroll process list" },
{ .key = " Digits: ", .info = "incremental PID search" },
diff --git a/ScreenManager.c b/ScreenManager.c
index df7431f..c328f07 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -99,6 +99,7 @@ Panel* ScreenManager_remove(ScreenManager* this, int idx) {
}
void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
+ clear();
this->x1 = x1;
this->y1 = y1;
this->x2 = x2;
--
2.6.4