]> granicus.if.org Git - procps-ng/commitdiff
top: normalize vertical scrolling for hidden processes
authorJim Warner <james.warner@comcast.net>
Wed, 20 Jun 2018 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Tue, 26 Jun 2018 11:25:18 +0000 (21:25 +1000)
To my knowledge, nobody has ever complained about some
anomalies when scrolling vertically if tasks should be
hidden from view. This can happen with the user filter
('u/U') or other filter ('o/O') features. And although
some tasks are not shown, they still impact scrolling.

This is most apparent when that scroll coordinates msg
is on ('C') & up/down arrow keys used (vs. pgup/pgdn).

Now that we can collapse/expand forked children, there
is a potential for yet more of those hidden processes.

So this commit normalizes vertical scrolling providing
an expected behavior. In other words, the up/down keys
skip the unseen tasks to reposition on a visible task.

Signed-off-by: Jim Warner <james.warner@comcast.net>
top/top.c
top/top.h

index f20f20c871f7bdf1101e1dc57503418c568569fb..5fed17d62239b58f84bbc41e9d1f872d0d1d0da5 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -3919,9 +3919,9 @@ static void win_names (WIN_t *q, const char *name) {
 static void win_reset (WIN_t *q) {
          SETw(q, Show_IDLEPS | Show_TASKON);
 #ifndef SCROLLVAR_NO
-         q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->varcolbeg = 0;
+         q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->varcolbeg = 0;
 #else
-         q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = 0;
+         q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = 0;
 #endif
          Monpidsidx = 0;
          osel_clear(q);
@@ -4408,7 +4408,7 @@ static void find_string (int ch) {
 #endif
    }
    if (Curwin->findstr[0]) {
-      SETw(Curwin, INFINDS_xxx);
+      SETw(Curwin, NOPRINT_xxx);
       for (i = Curwin->begtask; i < PIDSmaxt; i++) {
          const char *row = task_show(Curwin, Curwin->ppt[i]);
          if (*row && -1 < find_ofs(Curwin, row)) {
@@ -4990,10 +4990,10 @@ static void keys_window (int ch) {
          }
          break;
       case kbd_UP:
-         if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS) && 0 < w->begtask) w->begtask -= 1;
+         if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begnext = -1;
          break;
       case kbd_DOWN:
-         if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS) && (w->begtask < PIDSmaxt - 1)) w->begtask += 1;
+         if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begnext = +1;
          break;
 #ifdef USE_X_COLHDR // ------------------------------------
       case kbd_LEFT:
@@ -5063,17 +5063,14 @@ static void keys_window (int ch) {
       case kbd_PGUP:
          if (VIZCHKw(w)) {
             if (CHKw(w, Show_IDLEPS) && 0 < w->begtask) {
-               w->begtask -= (w->winlines - 1);
-               if (0 > w->begtask) w->begtask = 0;
+               w->begnext = -(w->winlines - 1);
             }
          }
          break;
       case kbd_PGDN:
          if (VIZCHKw(w)) {
             if (CHKw(w, Show_IDLEPS) && w->begtask < PIDSmaxt - 1) {
-               w->begtask += (w->winlines - 1);
-               if (w->begtask > PIDSmaxt - 1) w->begtask = PIDSmaxt - 1;
-               if (0 > w->begtask) w->begtask = 0;
+               w->begnext = +(w->winlines - 1);
             }
          }
          break;
@@ -5087,8 +5084,7 @@ static void keys_window (int ch) {
       case kbd_END:
          if (VIZCHKw(w)) {
             if (CHKw(w, Show_IDLEPS)) {
-               w->begtask = (PIDSmaxt - w->winlines) + 1;
-               if (0 > w->begtask) w->begtask = 0;
+               w->begnext = (PIDSmaxt - w->winlines) + 1;
                w->begpflg = w->endpflg;
 #ifndef SCROLLVAR_NO
                w->varcolbeg = 0;
@@ -5507,7 +5503,7 @@ static const char *task_show (const WIN_t *q, struct pids_stack *p) {
          case EU_XOF:
          case EU_XON:
             cp = NULL;
-            if (!CHKw(q, INFINDS_xxx | NOHIFND_xxx | NOHISEL_xxx)) {
+            if (!CHKw(q, NOPRINT_xxx | NOHIFND_xxx | NOHISEL_xxx)) {
                /* treat running tasks specially - entire row may get highlighted
                   so we needn't turn it on and we MUST NOT turn it off */
                if (!('R' == rSv(EU_STA, s_ch) && CHKw(q, Show_HIROWS)))
@@ -5662,7 +5658,7 @@ static const char *task_show (const WIN_t *q, struct pids_stack *p) {
       #undef Jn
    } // end: for 'maxpflgs'
 
-   if (!CHKw(q, INFINDS_xxx)) {
+   if (!CHKw(q, NOPRINT_xxx)) {
       const char *cap = ((CHKw(q, Show_HIROWS) && 'R' == rSv(EU_STA, s_ch)))
          ? q->capclr_rowhigh : q->capclr_rownorm;
       char *row = rbuf;
@@ -5693,6 +5689,51 @@ static const char *task_show (const WIN_t *q, struct pids_stack *p) {
 } // end: task_show
 
 
+        /*
+         * A window_show *Helper* function ensuring that Curwin's 'begtask'
+         * represents a visible process (not any hidden/filtered-out task).
+         * In reality, this function is called:
+         *   1) exclusively for the current window
+         *   2) immediately after interacting with a user
+         *   3) with the only key stuck: up, down, pgup, pgdn or end */
+static void window_hlp (void) {
+   WIN_t *w = Curwin;             // avoid gcc bloat with a local copy
+   int i;
+
+   SETw(w, NOPRINT_xxx);
+   w->begtask += w->begnext;
+   if (w->begtask < 0) w->begtask = 0;
+   if (w->begtask >= PIDSmaxt) w->begtask = PIDSmaxt - 1;
+
+   // potentially scroll forward ...
+   if (w->begnext > 0) {
+      for (i = w->begtask; i < PIDSmaxt; i++) {
+         if (wins_usrselect(w, w->ppt[i])
+         && (*task_show(w, w->ppt[i])))
+            break;
+      }
+      if (i < PIDSmaxt) {
+         w->begtask = i;
+         goto wrap_up;
+      }
+      // no luck forward, so let's try backward
+      w->begtask = PIDSmaxt - 1;
+   }
+
+   // potentially scroll backward ...
+   for (i = w->begtask; i > 0; i--) {
+      if (wins_usrselect(w, w->ppt[i])
+      && (*task_show(w, w->ppt[i])))
+         break;
+   }
+   w->begtask = i;
+
+wrap_up:
+   w->begnext = 0;
+   OFFw(w, NOPRINT_xxx);
+} // end: window_hlp
+
+
 static int window_show (WIN_t *q, int wmax) {
  #define sORDER  CHKw(q, Qsrt_NORMAL) ? PIDS_SORT_DESCEND : PIDS_SORT_ASCEND
  /* the isBUSY macro determines if a task is 'active' --
@@ -5717,6 +5758,9 @@ static int window_show (WIN_t *q, int wmax) {
          error_exit(fmtmk(N_fmt(LIB_errorpid_fmt),__LINE__, strerror(errno)));
    }
 
+   if (q->begnext) window_hlp();
+   else OFFw(q, NOPRINT_xxx);
+
    i = q->begtask;
    lwin = 1;                                        // 1 for the column header
    wmax = winMIN(wmax, q->winlines + 1);            // ditto for winlines, too
@@ -5807,7 +5851,6 @@ static void frame_make (void) {
    Tree_idx = Pseudo_row = Msg_row = scrlins = 0;
    summary_show();
    Max_lines = (Screen_rows - Msg_row) - 1;
-   OFFw(w, INFINDS_xxx);
 
    // we're now on Msg_row so clear out any residual messages ...
    putp(Cap_clr_eol);
index 85aef479e76f590f7fd3af86153892fe00e4353b..3bbdba839234628bd4f5dd8b2e06a4b513bcdc9a 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -245,7 +245,7 @@ typedef          long long SIC_t;
 #define Show_JRSTRS  0x040000     // 'j' - right justify "string" data cols
 #define Show_JRNUMS  0x020000     // 'J' - right justify "numeric" data cols
         // these flag(s) have no command as such - they're for internal use
-#define INFINDS_xxx  0x010000     // build rows for find_string, not display
+#define NOPRINT_xxx  0x010000     // build task rows only (not for display)
 #define EQUWINS_xxx  0x000001     // rebalance all wins & tasks (off i,n,u/U)
 #ifndef USE_X_COLHDR
 #define NOHISEL_xxx  0x200000     // restrict Show_HICOLS for osel temporarily
@@ -325,6 +325,7 @@ typedef struct WIN_t {
           begpflg,         // scrolled beginning pos into pflgsall array
           endpflg,         // scrolled ending pos into pflgsall array
           begtask,         // scrolled beginning pos into total tasks
+          begnext,         // new scrolled delta for next frame's begtask
 #ifndef SCROLLVAR_NO
           varcolbeg,       // scrolled position within variable width col
 #endif
@@ -665,6 +666,7 @@ typedef struct WIN_t {
 //atic void          summary_hlp (struct stat_stack *this, const char *pfx);
 //atic void          summary_show (void);
 //atic const char   *task_show (const WIN_t *q, struct pids_stack *p);
+//atic void          window_hlp (void);
 //atic int           window_show (WIN_t *q, int wmax);
 /*------  Entry point plus two  ------------------------------------------*/
 //atic void          frame_hlp (int wix, int max);