]> 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>
Sat, 23 Jun 2018 12:03:57 +0000 (22:03 +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 722ca94f18f4821ca2f0f566190064c0836ec559..7e17b1e3295decf888171c338daf35d4fec588f0 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -4386,9 +4386,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);
@@ -4848,7 +4848,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 < Frame_maxtask; i++) {
          const char *row = task_show(Curwin, Curwin->ppt[i]);
          if (*row && -1 < find_ofs(Curwin, row)) {
@@ -5430,10 +5430,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 < Frame_maxtask - 1)) w->begtask += 1;
+         if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begnext = +1;
          break;
 #ifdef USE_X_COLHDR // ------------------------------------
       case kbd_LEFT:
@@ -5503,17 +5503,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 < Frame_maxtask - 1) {
-               w->begtask += (w->winlines - 1);
-               if (w->begtask > Frame_maxtask - 1) w->begtask = Frame_maxtask - 1;
-               if (0 > w->begtask) w->begtask = 0;
+               w->begnext = +(w->winlines - 1);
             }
          }
          break;
@@ -5527,8 +5524,7 @@ static void keys_window (int ch) {
       case kbd_END:
          if (VIZCHKw(w)) {
             if (CHKw(w, Show_IDLEPS)) {
-               w->begtask = (Frame_maxtask - w->winlines) + 1;
-               if (0 > w->begtask) w->begtask = 0;
+               w->begnext = (Frame_maxtask - w->winlines) + 1;
                w->begpflg = w->endpflg;
 #ifndef SCROLLVAR_NO
                w->varcolbeg = 0;
@@ -5958,7 +5954,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) {
          case EU_XON:
          case EU_XOF:
             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' == p->state && CHKw(q, Show_HIROWS)))
@@ -6160,7 +6156,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) {
       #undef Jn
    } // end: for 'maxpflgs'
 
-   if (!CHKw(q, INFINDS_xxx)) {
+   if (!CHKw(q, NOPRINT_xxx)) {
       const char *cap = ((CHKw(q, Show_HIROWS) && 'R' == p->state))
          ? q->capclr_rowhigh : q->capclr_rownorm;
       char *row = rbuf;
@@ -6191,6 +6187,51 @@ static const char *task_show (const WIN_t *q, const proc_t *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 >= Frame_maxtask) w->begtask = Frame_maxtask - 1;
+
+   // potentially scroll forward ...
+   if (w->begnext > 0) {
+      for (i = w->begtask; i < Frame_maxtask; i++) {
+         if (user_matched(w, w->ppt[i])
+         && (*task_show(w, w->ppt[i])))
+            break;
+      }
+      if (i < Frame_maxtask) {
+         w->begtask = i;
+         goto wrap_up;
+      }
+      // no luck forward, so let's try backward
+      w->begtask = Frame_maxtask - 1;
+   }
+
+   // potentially scroll backward ...
+   for (i = w->begtask; i > 0; i--) {
+      if (user_matched(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
+
+
         /*
          * Squeeze as many tasks as we can into a single window,
          * after sorting the passed proc table. */
@@ -6215,6 +6256,9 @@ static int window_show (WIN_t *q, int wmax) {
       qsort(q->ppt, Frame_maxtask, sizeof(proc_t*), Fieldstab[q->rc.sortindx].sort);
    }
 
+   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
@@ -6304,7 +6348,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 f489e9571cf0c05e5aab51888b05751d4746c6af..758470dfd24c31ceb16dbf5b30568140349ffa49 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -331,7 +331,7 @@ typedef struct CPU_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
@@ -411,6 +411,7 @@ typedef struct WIN_t {
           begpflg,         // scrolled beginning pos into pflgsall array
           endpflg,         // scrolled ending pos into pflgsall array
           begtask,         // scrolled beginning pos into Frame_maxtask
+          begnext,         // new scrolled delta for next frame's begtask
 #ifndef SCROLLVAR_NO
           varcolbeg,       // scrolled position within variable width col
 #endif
@@ -806,6 +807,7 @@ typedef struct WIN_t {
 //atic void          summary_hlp (CPU_t *cpu, const char *pfx);
 //atic void          summary_show (void);
 //atic const char   *task_show (const WIN_t *q, const proc_t *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);