mirror of https://github.com/xzeldon/htop.git
Highlight new and old processes (#74)
This commit is contained in:
parent
bbf01054bf
commit
dde71c6637
12
CRT.c
12
CRT.c
|
@ -111,6 +111,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
||||||
|
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||||
|
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||||
[PROCESS_THREAD] = ColorPair(Green,Black),
|
[PROCESS_THREAD] = ColorPair(Green,Black),
|
||||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Black),
|
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Black),
|
||||||
[BAR_BORDER] = A_BOLD,
|
[BAR_BORDER] = A_BOLD,
|
||||||
|
@ -188,6 +190,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD,
|
[PROCESS_D_STATE] = A_BOLD,
|
||||||
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
||||||
[PROCESS_LOW_PRIORITY] = A_DIM,
|
[PROCESS_LOW_PRIORITY] = A_DIM,
|
||||||
|
[PROCESS_NEW] = A_BOLD,
|
||||||
|
[PROCESS_TOMB] = A_DIM,
|
||||||
[PROCESS_THREAD] = A_BOLD,
|
[PROCESS_THREAD] = A_BOLD,
|
||||||
[PROCESS_THREAD_BASENAME] = A_REVERSE,
|
[PROCESS_THREAD_BASENAME] = A_REVERSE,
|
||||||
[BAR_BORDER] = A_BOLD,
|
[BAR_BORDER] = A_BOLD,
|
||||||
|
@ -265,6 +269,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,White),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,White),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green,White),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green,White),
|
||||||
|
[PROCESS_NEW] = ColorPair(White,Green),
|
||||||
|
[PROCESS_TOMB] = ColorPair(White,Red),
|
||||||
[PROCESS_THREAD] = ColorPair(Blue,White),
|
[PROCESS_THREAD] = ColorPair(Blue,White),
|
||||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,White),
|
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,White),
|
||||||
[BAR_BORDER] = ColorPair(Blue,White),
|
[BAR_BORDER] = ColorPair(Blue,White),
|
||||||
|
@ -342,6 +348,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
||||||
|
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||||
|
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||||
[PROCESS_THREAD] = ColorPair(Blue,Black),
|
[PROCESS_THREAD] = ColorPair(Blue,Black),
|
||||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black),
|
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black),
|
||||||
[BAR_BORDER] = ColorPair(Blue,Black),
|
[BAR_BORDER] = ColorPair(Blue,Black),
|
||||||
|
@ -419,6 +427,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Blue),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Blue),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Blue),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Blue),
|
||||||
|
[PROCESS_NEW] = ColorPair(Blue,Green),
|
||||||
|
[PROCESS_TOMB] = ColorPair(Blue,Red),
|
||||||
[PROCESS_THREAD] = ColorPair(Green,Blue),
|
[PROCESS_THREAD] = ColorPair(Green,Blue),
|
||||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Blue),
|
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Blue),
|
||||||
[BAR_BORDER] = A_BOLD | ColorPair(Yellow,Blue),
|
[BAR_BORDER] = A_BOLD | ColorPair(Yellow,Blue),
|
||||||
|
@ -498,6 +508,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red,Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green,Black),
|
||||||
|
[PROCESS_NEW] = ColorPair(Black,Green),
|
||||||
|
[PROCESS_TOMB] = ColorPair(Black,Red),
|
||||||
[BAR_BORDER] = A_BOLD | ColorPair(Green,Black),
|
[BAR_BORDER] = A_BOLD | ColorPair(Green,Black),
|
||||||
[BAR_SHADOW] = ColorPair(Cyan,Black),
|
[BAR_SHADOW] = ColorPair(Cyan,Black),
|
||||||
[SWAP] = ColorPair(Red,Black),
|
[SWAP] = ColorPair(Red,Black),
|
||||||
|
|
2
CRT.h
2
CRT.h
|
@ -72,6 +72,8 @@ typedef enum ColorElements_ {
|
||||||
PROCESS_BASENAME,
|
PROCESS_BASENAME,
|
||||||
PROCESS_HIGH_PRIORITY,
|
PROCESS_HIGH_PRIORITY,
|
||||||
PROCESS_LOW_PRIORITY,
|
PROCESS_LOW_PRIORITY,
|
||||||
|
PROCESS_NEW,
|
||||||
|
PROCESS_TOMB,
|
||||||
PROCESS_THREAD,
|
PROCESS_THREAD,
|
||||||
PROCESS_THREAD_BASENAME,
|
PROCESS_THREAD_BASENAME,
|
||||||
BAR_BORDER,
|
BAR_BORDER,
|
||||||
|
|
|
@ -93,6 +93,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage)));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency)));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
|
||||||
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Highlight new and old processes"), &(settings->highlightChanges)));
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity)));
|
||||||
#endif
|
#endif
|
||||||
|
|
12
Panel.c
12
Panel.c
|
@ -266,16 +266,18 @@ void Panel_draw(Panel* this, bool focus) {
|
||||||
Object_display(itemObj, &item);
|
Object_display(itemObj, &item);
|
||||||
int itemLen = RichString_sizeVal(item);
|
int itemLen = RichString_sizeVal(item);
|
||||||
int amt = MINIMUM(itemLen - scrollH, this->w);
|
int amt = MINIMUM(itemLen - scrollH, this->w);
|
||||||
bool selected = (i == this->selected);
|
if (i == this->selected) {
|
||||||
if (selected) {
|
item.highlightAttr = selectionColor;
|
||||||
attrset(selectionColor);
|
}
|
||||||
RichString_setAttr(&item, selectionColor);
|
if (item.highlightAttr) {
|
||||||
|
attrset(item.highlightAttr);
|
||||||
|
RichString_setAttr(&item, item.highlightAttr);
|
||||||
this->selectedLen = itemLen;
|
this->selectedLen = itemLen;
|
||||||
}
|
}
|
||||||
mvhline(y + line, x, ' ', this->w);
|
mvhline(y + line, x, ' ', this->w);
|
||||||
if (amt > 0)
|
if (amt > 0)
|
||||||
RichString_printoffnVal(item, y + line, x, scrollH, amt);
|
RichString_printoffnVal(item, y + line, x, scrollH, amt);
|
||||||
if (selected)
|
if (item.highlightAttr)
|
||||||
attrset(CRT_colors[RESET_COLOR]);
|
attrset(CRT_colors[RESET_COLOR]);
|
||||||
RichString_end(item);
|
RichString_end(item);
|
||||||
line++;
|
line++;
|
||||||
|
|
17
Process.c
17
Process.c
|
@ -6,6 +6,7 @@ Released under the GNU GPLv2, see the COPYING file
|
||||||
in the source distribution for its full text.
|
in the source distribution for its full text.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "config.h" // IWYU pragma: keep
|
#include "config.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
|
@ -381,6 +382,12 @@ void Process_display(const Object* cast, RichString* out) {
|
||||||
RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
|
RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
|
||||||
if (this->tag == true)
|
if (this->tag == true)
|
||||||
RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
|
RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
|
||||||
|
if (this->settings->highlightChanges) {
|
||||||
|
if (Process_isNew(this))
|
||||||
|
out->highlightAttr = CRT_colors[PROCESS_NEW];
|
||||||
|
if (Process_isTomb(this))
|
||||||
|
out->highlightAttr = CRT_colors[PROCESS_TOMB];
|
||||||
|
}
|
||||||
assert(out->chlen > 0);
|
assert(out->chlen > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,6 +420,16 @@ void Process_toggleTag(Process* this) {
|
||||||
this->tag = this->tag == true ? false : true;
|
this->tag = this->tag == true ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Process_isNew(const Process* this) {
|
||||||
|
if (this->processList && this->processList->scanTs >= this->seenTs)
|
||||||
|
return (this->processList->scanTs - this->seenTs <= this->processList->settings->highlightDelaySecs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process_isTomb(const Process* this) {
|
||||||
|
return (this->tombTs > 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool Process_setPriority(Process* this, int priority) {
|
bool Process_setPriority(Process* this, int priority) {
|
||||||
CRT_dropPrivileges();
|
CRT_dropPrivileges();
|
||||||
int old_prio = getpriority(PRIO_PROCESS, this->pid);
|
int old_prio = getpriority(PRIO_PROCESS, this->pid);
|
||||||
|
|
11
Process.h
11
Process.h
|
@ -10,17 +10,18 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "RichString.h"
|
#include "RichString.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#define SYS_ioprio_get __NR_ioprio_get
|
#define SYS_ioprio_get __NR_ioprio_get
|
||||||
#define SYS_ioprio_set __NR_ioprio_set
|
#define SYS_ioprio_set __NR_ioprio_set
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PROCESS_FLAG_IO 0x0001
|
#define PROCESS_FLAG_IO 0x0001
|
||||||
|
#define DEFAULT_HIGHLIGHT_SECS 5
|
||||||
|
|
||||||
typedef enum ProcessFields {
|
typedef enum ProcessFields {
|
||||||
NULL_PROCESSFIELD = 0,
|
NULL_PROCESSFIELD = 0,
|
||||||
|
@ -59,6 +60,7 @@ struct Settings_;
|
||||||
typedef struct Process_ {
|
typedef struct Process_ {
|
||||||
Object super;
|
Object super;
|
||||||
|
|
||||||
|
const struct ProcessList_* processList;
|
||||||
const struct Settings_* settings;
|
const struct Settings_* settings;
|
||||||
|
|
||||||
unsigned long long int time;
|
unsigned long long int time;
|
||||||
|
@ -99,6 +101,9 @@ typedef struct Process_ {
|
||||||
|
|
||||||
int exit_signal;
|
int exit_signal;
|
||||||
|
|
||||||
|
time_t seenTs;
|
||||||
|
time_t tombTs;
|
||||||
|
|
||||||
unsigned long int minflt;
|
unsigned long int minflt;
|
||||||
unsigned long int majflt;
|
unsigned long int majflt;
|
||||||
} Process;
|
} Process;
|
||||||
|
@ -172,6 +177,10 @@ void Process_init(Process* this, const struct Settings_* settings);
|
||||||
|
|
||||||
void Process_toggleTag(Process* this);
|
void Process_toggleTag(Process* this);
|
||||||
|
|
||||||
|
bool Process_isNew(const Process* this);
|
||||||
|
|
||||||
|
bool Process_isTomb(const Process* this);
|
||||||
|
|
||||||
bool Process_setPriority(Process* this, int priority);
|
bool Process_setPriority(Process* this, int priority);
|
||||||
|
|
||||||
bool Process_changePriorityBy(Process* this, Arg delta);
|
bool Process_changePriorityBy(Process* this, Arg delta);
|
||||||
|
|
|
@ -9,11 +9,11 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "XUtils.h"
|
#include "XUtils.h"
|
||||||
|
|
||||||
|
|
||||||
ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
|
ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
|
||||||
this->processes = Vector_new(klass, true, DEFAULT_SIZE);
|
this->processes = Vector_new(klass, true, DEFAULT_SIZE);
|
||||||
this->processTable = Hashtable_new(140, false);
|
this->processTable = Hashtable_new(140, false);
|
||||||
|
@ -27,6 +27,9 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users
|
||||||
// set later by platform-specific code
|
// set later by platform-specific code
|
||||||
this->cpuCount = 0;
|
this->cpuCount = 0;
|
||||||
|
|
||||||
|
this->scanTs = 0;
|
||||||
|
this->firstScanTs = 0;
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
this->topologyOk = false;
|
this->topologyOk = false;
|
||||||
if (hwloc_topology_init(&this->topology) == 0) {
|
if (hwloc_topology_init(&this->topology) == 0) {
|
||||||
|
@ -81,6 +84,14 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
|
||||||
void ProcessList_add(ProcessList* this, Process* p) {
|
void ProcessList_add(ProcessList* this, Process* p) {
|
||||||
assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1);
|
assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1);
|
||||||
assert(Hashtable_get(this->processTable, p->pid) == NULL);
|
assert(Hashtable_get(this->processTable, p->pid) == NULL);
|
||||||
|
p->processList = this;
|
||||||
|
|
||||||
|
if (this->scanTs == this->firstScanTs) {
|
||||||
|
// prevent highlighting processes found in first scan
|
||||||
|
p->seenTs = this->firstScanTs - this->settings->highlightDelaySecs - 1;
|
||||||
|
} else {
|
||||||
|
p->seenTs = this->scanTs;
|
||||||
|
}
|
||||||
|
|
||||||
Vector_add(this->processes, p);
|
Vector_add(this->processes, p);
|
||||||
Hashtable_put(this->processTable, p->pid, p);
|
Hashtable_put(this->processTable, p->pid, p);
|
||||||
|
@ -283,6 +294,7 @@ Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
// in pause mode only gather global data for meters (CPU/memory/...)
|
// in pause mode only gather global data for meters (CPU/memory/...)
|
||||||
if (pauseProcessUpdate) {
|
if (pauseProcessUpdate) {
|
||||||
|
@ -302,13 +314,35 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
||||||
this->kernelThreads = 0;
|
this->kernelThreads = 0;
|
||||||
this->runningTasks = 0;
|
this->runningTasks = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// set scanTs
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
|
||||||
|
if (this->firstScanTs == 0) {
|
||||||
|
this->firstScanTs = now.tv_sec;
|
||||||
|
}
|
||||||
|
this->scanTs = now.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessList_goThroughEntries(this, false);
|
ProcessList_goThroughEntries(this, false);
|
||||||
|
|
||||||
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||||
Process* p = (Process*) Vector_get(this->processes, i);
|
Process* p = (Process*) Vector_get(this->processes, i);
|
||||||
if (p->updated == false)
|
if (p->tombTs > 0) {
|
||||||
|
// remove tombed process
|
||||||
|
if (this->scanTs >= p->tombTs) {
|
||||||
ProcessList_remove(this, p);
|
ProcessList_remove(this, p);
|
||||||
else
|
}
|
||||||
|
} else if (p->updated == false) {
|
||||||
|
// process no longer exists
|
||||||
|
if (this->settings->highlightChanges) {
|
||||||
|
// mark tombed
|
||||||
|
p->tombTs = this->scanTs + this->settings->highlightDelaySecs;
|
||||||
|
} else {
|
||||||
|
// immediately remove
|
||||||
|
ProcessList_remove(this, p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
p->updated = false;
|
p->updated = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ typedef struct ProcessList_ {
|
||||||
|
|
||||||
int cpuCount;
|
int cpuCount;
|
||||||
|
|
||||||
|
time_t scanTs;
|
||||||
|
time_t firstScanTs;
|
||||||
} ProcessList;
|
} ProcessList;
|
||||||
|
|
||||||
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
|
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
|
||||||
|
|
|
@ -39,6 +39,7 @@ typedef struct RichString_ {
|
||||||
int chlen;
|
int chlen;
|
||||||
CharType* chptr;
|
CharType* chptr;
|
||||||
CharType chstr[RICHSTRING_MAXLEN+1];
|
CharType chstr[RICHSTRING_MAXLEN+1];
|
||||||
|
int highlightAttr;
|
||||||
} RichString;
|
} RichString;
|
||||||
|
|
||||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
||||||
|
|
|
@ -102,6 +102,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
||||||
|
|
||||||
*timedOut = (newTime - *oldTime > this->settings->delay);
|
*timedOut = (newTime - *oldTime > this->settings->delay);
|
||||||
*rescan = *rescan || *timedOut;
|
*rescan = *rescan || *timedOut;
|
||||||
if (newTime < *oldTime) *rescan = true; // clock was adjusted?
|
if (newTime < *oldTime) *rescan = true; // clock was adjusted?
|
||||||
|
|
|
@ -158,6 +158,10 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo
|
||||||
this->highlightMegabytes = atoi(option[1]);
|
this->highlightMegabytes = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "highlight_threads")) {
|
} else if (String_eq(option[0], "highlight_threads")) {
|
||||||
this->highlightThreads = atoi(option[1]);
|
this->highlightThreads = atoi(option[1]);
|
||||||
|
} else if (String_eq(option[0], "highlight_changes")) {
|
||||||
|
this->highlightChanges = atoi(option[1]);
|
||||||
|
} else if (String_eq(option[0], "highlight_changes_delay_secs")) {
|
||||||
|
this->highlightDelaySecs = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "header_margin")) {
|
} else if (String_eq(option[0], "header_margin")) {
|
||||||
this->headerMargin = atoi(option[1]);
|
this->headerMargin = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "expand_system_time")) {
|
} else if (String_eq(option[0], "expand_system_time")) {
|
||||||
|
@ -265,6 +269,8 @@ bool Settings_write(Settings* this) {
|
||||||
fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName);
|
fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName);
|
||||||
fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes);
|
fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes);
|
||||||
fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads);
|
fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads);
|
||||||
|
fprintf(fd, "highlight_changes=%d\n", (int) this->highlightChanges);
|
||||||
|
fprintf(fd, "highlight_changes_delay_secs=%d\n", (int) this->highlightDelaySecs);
|
||||||
fprintf(fd, "tree_view=%d\n", (int) this->treeView);
|
fprintf(fd, "tree_view=%d\n", (int) this->treeView);
|
||||||
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
|
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
|
||||||
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
|
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
|
||||||
|
@ -307,6 +313,7 @@ Settings* Settings_new(int initialCpuCount) {
|
||||||
this->updateProcessNames = false;
|
this->updateProcessNames = false;
|
||||||
this->showProgramPath = true;
|
this->showProgramPath = true;
|
||||||
this->highlightThreads = true;
|
this->highlightThreads = true;
|
||||||
|
this->highlightDelaySecs = DEFAULT_HIGHLIGHT_SECS;
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
this->topologyAffinity = false;
|
this->topologyAffinity = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,6 +48,8 @@ typedef struct Settings_ {
|
||||||
bool highlightBaseName;
|
bool highlightBaseName;
|
||||||
bool highlightMegabytes;
|
bool highlightMegabytes;
|
||||||
bool highlightThreads;
|
bool highlightThreads;
|
||||||
|
bool highlightChanges;
|
||||||
|
int highlightDelaySecs;
|
||||||
bool updateProcessNames;
|
bool updateProcessNames;
|
||||||
bool accountGuestInCPUMeter;
|
bool accountGuestInCPUMeter;
|
||||||
bool headerMargin;
|
bool headerMargin;
|
||||||
|
|
|
@ -4,7 +4,7 @@ htop \- interactive process viewer
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
.LP
|
.LP
|
||||||
.B htop
|
.B htop
|
||||||
.RB [ \-dCFhpustv ]
|
.RB [ \-dCFhpustvH ]
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
.LP
|
.LP
|
||||||
.B htop
|
.B htop
|
||||||
|
@ -62,6 +62,9 @@ Output version information and exit
|
||||||
.TP
|
.TP
|
||||||
\fB\-t \-\-tree
|
\fB\-t \-\-tree
|
||||||
Show processes in tree view
|
Show processes in tree view
|
||||||
|
.TP
|
||||||
|
\fB\-H \-\-highlight-changes=DELAY\fR
|
||||||
|
Highlight new and old processes
|
||||||
.SH "INTERACTIVE COMMANDS"
|
.SH "INTERACTIVE COMMANDS"
|
||||||
.LP
|
.LP
|
||||||
The following commands are supported while in
|
The following commands are supported while in
|
||||||
|
|
29
htop.c
29
htop.c
|
@ -57,6 +57,7 @@ static void printHelpFlag(void) {
|
||||||
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
||||||
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
||||||
"-V --version Print version info\n"
|
"-V --version Print version info\n"
|
||||||
|
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Long options may be passed with a single dash.\n\n"
|
"Long options may be passed with a single dash.\n\n"
|
||||||
"Press F1 inside htop for online help.\n"
|
"Press F1 inside htop for online help.\n"
|
||||||
|
@ -76,6 +77,8 @@ typedef struct CommandLineSettings_ {
|
||||||
bool enableMouse;
|
bool enableMouse;
|
||||||
bool treeView;
|
bool treeView;
|
||||||
bool allowUnicode;
|
bool allowUnicode;
|
||||||
|
bool highlightChanges;
|
||||||
|
int highlightDelaySecs;
|
||||||
} CommandLineSettings;
|
} CommandLineSettings;
|
||||||
|
|
||||||
static CommandLineSettings parseArguments(int argc, char** argv) {
|
static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||||
|
@ -90,6 +93,8 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||||
.enableMouse = true,
|
.enableMouse = true,
|
||||||
.treeView = false,
|
.treeView = false,
|
||||||
.allowUnicode = true,
|
.allowUnicode = true,
|
||||||
|
.highlightChanges = false,
|
||||||
|
.highlightDelaySecs = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option long_opts[] =
|
static struct option long_opts[] =
|
||||||
|
@ -106,12 +111,13 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||||
{"tree", no_argument, 0, 't'},
|
{"tree", no_argument, 0, 't'},
|
||||||
{"pid", required_argument, 0, 'p'},
|
{"pid", required_argument, 0, 'p'},
|
||||||
{"filter", required_argument, 0, 'F'},
|
{"filter", required_argument, 0, 'F'},
|
||||||
|
{"highlight-changes", optional_argument, 0, 'H'},
|
||||||
{0,0,0,0}
|
{0,0,0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
int opt, opti=0;
|
int opt, opti=0;
|
||||||
/* Parse arguments */
|
/* Parse arguments */
|
||||||
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:", long_opts, &opti))) {
|
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) {
|
||||||
if (opt == EOF) break;
|
if (opt == EOF) break;
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -198,6 +204,23 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'H': {
|
||||||
|
const char *delay = optarg;
|
||||||
|
if (!delay && optind < argc && argv[optind] != NULL &&
|
||||||
|
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
|
||||||
|
delay = argv[optind++];
|
||||||
|
}
|
||||||
|
if (delay) {
|
||||||
|
if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) {
|
||||||
|
if (flags.highlightDelaySecs < 1) flags.highlightDelaySecs = 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags.highlightChanges = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -271,6 +294,10 @@ int main(int argc, char** argv) {
|
||||||
settings->enableMouse = false;
|
settings->enableMouse = false;
|
||||||
if (flags.treeView)
|
if (flags.treeView)
|
||||||
settings->treeView = true;
|
settings->treeView = true;
|
||||||
|
if (flags.highlightChanges)
|
||||||
|
settings->highlightChanges = true;
|
||||||
|
if (flags.highlightDelaySecs != -1)
|
||||||
|
settings->highlightDelaySecs = flags.highlightDelaySecs;
|
||||||
|
|
||||||
CRT_init(settings->delay, settings->colorScheme, flags.allowUnicode);
|
CRT_init(settings->delay, settings->colorScheme, flags.allowUnicode);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue