mirror of https://github.com/xzeldon/htop.git
Another mega-patch for the refactoring process.
Kinda runs, but functionality from the original main loop is still missing. Patience.
This commit is contained in:
parent
3383d8e556
commit
c2108e5a48
55
Action.c
55
Action.c
|
@ -12,6 +12,7 @@ in the source distribution for its full text.
|
||||||
#include "AffinityPanel.h"
|
#include "AffinityPanel.h"
|
||||||
#include "CategoriesPanel.h"
|
#include "CategoriesPanel.h"
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
|
#include "MainPanel.h"
|
||||||
#include "OpenFilesScreen.h"
|
#include "OpenFilesScreen.h"
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "ScreenManager.h"
|
#include "ScreenManager.h"
|
||||||
|
@ -58,37 +59,8 @@ typedef struct State_ {
|
||||||
Header* header;
|
Header* header;
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
typedef bool(*Action_ForeachProcessFn)(Process*, size_t);
|
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
int Action_selectedPid(Panel* panel) {
|
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
|
||||||
if (p) {
|
|
||||||
return p->pid;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Action_foreachProcess(Panel* panel, Action_ForeachProcessFn fn, int arg, bool* wasAnyTagged) {
|
|
||||||
bool ok = true;
|
|
||||||
bool anyTagged = false;
|
|
||||||
for (int i = 0; i < Panel_size(panel); i++) {
|
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
|
||||||
if (p->tag) {
|
|
||||||
ok = fn(p, arg) && ok;
|
|
||||||
anyTagged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!anyTagged) {
|
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
|
||||||
if (p) ok = fn(p, arg) && ok;
|
|
||||||
}
|
|
||||||
if (wasAnyTagged)
|
|
||||||
*wasAnyTagged = anyTagged;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object* Action_pickFromVector(State* st, Panel* list, int x, const char** keyLabels) {
|
Object* Action_pickFromVector(State* st, Panel* list, int x, const char** keyLabels) {
|
||||||
Panel* panel = st->panel;
|
Panel* panel = st->panel;
|
||||||
Header* header = st->header;
|
Header* header = st->header;
|
||||||
|
@ -97,14 +69,14 @@ Object* Action_pickFromVector(State* st, Panel* list, int x, const char** keyLab
|
||||||
int y = panel->y;
|
int y = panel->y;
|
||||||
const char* fuKeys[] = {"Enter", "Esc", NULL};
|
const char* fuKeys[] = {"Enter", "Esc", NULL};
|
||||||
int fuEvents[] = {13, 27};
|
int fuEvents[] = {13, 27};
|
||||||
ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, settings, false);
|
ScreenManager* scr = ScreenManager_new(0, header->height, 0, -1, HORIZONTAL, header, settings, false);
|
||||||
scr->allowFocusChange = false;
|
scr->allowFocusChange = false;
|
||||||
ScreenManager_add(scr, list, FunctionBar_new(keyLabels, fuKeys, fuEvents), x - 1);
|
ScreenManager_add(scr, list, FunctionBar_new(keyLabels, fuKeys, fuEvents), x - 1);
|
||||||
ScreenManager_add(scr, panel, NULL, -1);
|
ScreenManager_add(scr, panel, NULL, -1);
|
||||||
Panel* panelFocus;
|
Panel* panelFocus;
|
||||||
int ch;
|
int ch;
|
||||||
bool unfollow = false;
|
bool unfollow = false;
|
||||||
int pid = Action_selectedPid(panel);
|
int pid = MainPanel_selectedPid((MainPanel*)panel);
|
||||||
if (header->pl->following == -1) {
|
if (header->pl->following == -1) {
|
||||||
header->pl->following = pid;
|
header->pl->following = pid;
|
||||||
unfollow = true;
|
unfollow = true;
|
||||||
|
@ -141,9 +113,9 @@ static void Setup_run(Settings* settings, const Header* header, ProcessList* pl)
|
||||||
ScreenManager_delete(scr);
|
ScreenManager_delete(scr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool changePriority(Panel* panel, int delta) {
|
static bool changePriority(MainPanel* panel, int delta) {
|
||||||
bool anyTagged;
|
bool anyTagged;
|
||||||
bool ok = Action_foreachProcess(panel, (Action_ForeachProcessFn) Process_changePriorityBy, delta, &anyTagged);
|
bool ok = MainPanel_foreachProcess(panel, (MainPanel_ForeachProcessFn) Process_changePriorityBy, delta, &anyTagged);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
beep();
|
beep();
|
||||||
return anyTagged;
|
return anyTagged;
|
||||||
|
@ -165,13 +137,6 @@ bool Action_setUserOnly(const char* userName, uid_t* userId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* getMainPanelValue(Panel* panel, int i) {
|
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
|
||||||
if (p)
|
|
||||||
return p->comm;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tagAllChildren(Panel* panel, Process* parent) {
|
static void tagAllChildren(Panel* panel, Process* parent) {
|
||||||
parent->tag = true;
|
parent->tag = true;
|
||||||
pid_t ppid = parent->pid;
|
pid_t ppid = parent->pid;
|
||||||
|
@ -266,12 +231,12 @@ static Htop_Reaction actionIncSearch(State* st) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionHigherPriority(State* st) {
|
static Htop_Reaction actionHigherPriority(State* st) {
|
||||||
bool changed = changePriority(st->panel, -1);
|
bool changed = changePriority((MainPanel*)st->panel, -1);
|
||||||
return changed ? HTOP_REFRESH : HTOP_OK;
|
return changed ? HTOP_REFRESH : HTOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionLowerPriority(State* st) {
|
static Htop_Reaction actionLowerPriority(State* st) {
|
||||||
bool changed = changePriority(st->panel, 1);
|
bool changed = changePriority((MainPanel*)st->panel, 1);
|
||||||
return changed ? HTOP_REFRESH : HTOP_OK;
|
return changed ? HTOP_REFRESH : HTOP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +279,7 @@ static Htop_Reaction actionSetAffinity(State* st) {
|
||||||
void* set = Action_pickFromVector(st, affinityPanel, 15, fuFunctions);
|
void* set = Action_pickFromVector(st, affinityPanel, 15, fuFunctions);
|
||||||
if (set) {
|
if (set) {
|
||||||
Affinity* affinity = AffinityPanel_getAffinity(affinityPanel, st->pl);
|
Affinity* affinity = AffinityPanel_getAffinity(affinityPanel, st->pl);
|
||||||
bool ok = Action_foreachProcess(panel, (Action_ForeachProcessFn) Affinity_set, (size_t) affinity, NULL);
|
bool ok = MainPanel_foreachProcess((MainPanel*)panel, (MainPanel_ForeachProcessFn) Affinity_set, (size_t) affinity, NULL);
|
||||||
if (!ok) beep();
|
if (!ok) beep();
|
||||||
Affinity_delete(affinity);
|
Affinity_delete(affinity);
|
||||||
}
|
}
|
||||||
|
@ -332,7 +297,7 @@ static Htop_Reaction actionKill(State* st) {
|
||||||
Panel_setHeader(st->panel, "Sending...");
|
Panel_setHeader(st->panel, "Sending...");
|
||||||
Panel_draw(st->panel, true);
|
Panel_draw(st->panel, true);
|
||||||
refresh();
|
refresh();
|
||||||
Action_foreachProcess(st->panel, (Action_ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL);
|
MainPanel_foreachProcess((MainPanel*)st->panel, (MainPanel_ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL);
|
||||||
napms(500);
|
napms(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +326,7 @@ static Htop_Reaction actionFilterByUser(State* st) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Htop_Reaction actionFollow(State* st) {
|
static Htop_Reaction actionFollow(State* st) {
|
||||||
st->pl->following = Action_selectedPid(st->panel);
|
st->pl->following = MainPanel_selectedPid((MainPanel*)st->panel);
|
||||||
return HTOP_KEEP_FOLLOWING;
|
return HTOP_KEEP_FOLLOWING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
Action.h
6
Action.h
|
@ -39,12 +39,6 @@ typedef struct State_ {
|
||||||
Header* header;
|
Header* header;
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
typedef bool(*Action_ForeachProcessFn)(Process*, size_t);
|
|
||||||
|
|
||||||
|
|
||||||
int Action_selectedPid(Panel* panel);
|
|
||||||
|
|
||||||
bool Action_foreachProcess(Panel* panel, Action_ForeachProcessFn fn, int arg, bool* wasAnyTagged);
|
|
||||||
|
|
||||||
Object* Action_pickFromVector(State* st, Panel* list, int x, const char** keyLabels);
|
Object* Action_pickFromVector(State* st, Panel* list, int x, const char** keyLabels);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
|
||||||
|
|
||||||
#include "BatteryMeter.h"
|
#include "BatteryMeter.h"
|
||||||
|
|
||||||
#include "Platform.h"
|
#include "Battery.h"
|
||||||
#include "ProcessList.h"
|
#include "ProcessList.h"
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
@ -35,7 +35,7 @@ static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
|
||||||
ACPresence isOnAC;
|
ACPresence isOnAC;
|
||||||
double percent;
|
double percent;
|
||||||
|
|
||||||
Platform_getBatteryLevel(&percent, &isOnAC);
|
Battery_getData(&percent, &isOnAC);
|
||||||
|
|
||||||
if (percent == -1) {
|
if (percent == -1) {
|
||||||
this->values[0] = 0;
|
this->values[0] = 0;
|
||||||
|
|
|
@ -111,7 +111,6 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||||
result = IGNORED;
|
result = IGNORED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == HANDLED) {
|
if (result == HANDLED) {
|
||||||
int size = ScreenManager_size(this->scr);
|
int size = ScreenManager_size(this->scr);
|
||||||
for (int i = 1; i < size; i++)
|
for (int i = 1; i < size; i++)
|
||||||
|
@ -131,7 +130,6 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
Header.c
27
Header.c
|
@ -18,15 +18,16 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Meter.h"
|
#include "Meter.h"
|
||||||
|
#include "Settings.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
typedef struct Header_ {
|
typedef struct Header_ {
|
||||||
Vector** columns;
|
Vector** columns;
|
||||||
|
Settings* settings;
|
||||||
struct ProcessList_* pl;
|
struct ProcessList_* pl;
|
||||||
int height;
|
|
||||||
int pad;
|
|
||||||
int nrColumns;
|
int nrColumns;
|
||||||
bool margin;
|
int pad;
|
||||||
|
int height;
|
||||||
} Header;
|
} Header;
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
@ -39,15 +40,15 @@ typedef struct Header_ {
|
||||||
#define Header_forEachColumn(this_, i_) for (int i_=0; i_ < this->nrColumns; i_++)
|
#define Header_forEachColumn(this_, i_) for (int i_=0; i_ < this->nrColumns; i_++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Header* Header_new(struct ProcessList_* pl, int nrColumns) {
|
Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns) {
|
||||||
Header* this = calloc(1, sizeof(Header));
|
Header* this = calloc(1, sizeof(Header));
|
||||||
this->columns = calloc(nrColumns, sizeof(Vector*));
|
this->columns = calloc(nrColumns, sizeof(Vector*));
|
||||||
|
this->settings = settings;
|
||||||
|
this->pl = pl;
|
||||||
this->nrColumns = nrColumns;
|
this->nrColumns = nrColumns;
|
||||||
Header_forEachColumn(this, i) {
|
Header_forEachColumn(this, i) {
|
||||||
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
this->margin = true;
|
|
||||||
this->pl = pl;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +60,17 @@ void Header_delete(Header* this) {
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Header_populateFromSettings(Header* this) {
|
||||||
|
Header_forEachColumn(this, col) {
|
||||||
|
MeterColumnSettings* colSettings = &this->settings->columns[col];
|
||||||
|
for (int i = 0; i < colSettings->len; i++) {
|
||||||
|
Header_addMeterByName(this, colSettings->names[i], col);
|
||||||
|
Header_setMode(this, i, colSettings->modes[i], col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Header_calculateHeight(this);
|
||||||
|
}
|
||||||
|
|
||||||
MeterModeId Header_addMeterByName(Header* this, char* name, int column) {
|
MeterModeId Header_addMeterByName(Header* this, char* name, int column) {
|
||||||
Vector* meters = this->columns[column];
|
Vector* meters = this->columns[column];
|
||||||
|
|
||||||
|
@ -157,7 +169,7 @@ void Header_draw(const Header* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Header_calculateHeight(Header* this) {
|
int Header_calculateHeight(Header* this) {
|
||||||
int pad = this->margin ? 2 : 0;
|
int pad = this->settings->headerMargin ? 2 : 0;
|
||||||
int maxHeight = pad;
|
int maxHeight = pad;
|
||||||
|
|
||||||
Header_forEachColumn(this, col) {
|
Header_forEachColumn(this, col) {
|
||||||
|
@ -170,5 +182,6 @@ int Header_calculateHeight(Header* this) {
|
||||||
maxHeight = MAX(maxHeight, height);
|
maxHeight = MAX(maxHeight, height);
|
||||||
}
|
}
|
||||||
this->height = maxHeight;
|
this->height = maxHeight;
|
||||||
|
this->pad = pad;
|
||||||
return maxHeight;
|
return maxHeight;
|
||||||
}
|
}
|
||||||
|
|
11
Header.h
11
Header.h
|
@ -10,15 +10,16 @@ in the source distribution for its full text.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Meter.h"
|
#include "Meter.h"
|
||||||
|
#include "Settings.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
typedef struct Header_ {
|
typedef struct Header_ {
|
||||||
Vector** columns;
|
Vector** columns;
|
||||||
|
Settings* settings;
|
||||||
struct ProcessList_* pl;
|
struct ProcessList_* pl;
|
||||||
int height;
|
|
||||||
int pad;
|
|
||||||
int nrColumns;
|
int nrColumns;
|
||||||
bool margin;
|
int pad;
|
||||||
|
int height;
|
||||||
} Header;
|
} Header;
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,10 +31,12 @@ typedef struct Header_ {
|
||||||
#define Header_forEachColumn(this_, i_) for (int i_=0; i_ < this->nrColumns; i_++)
|
#define Header_forEachColumn(this_, i_) for (int i_=0; i_ < this->nrColumns; i_++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Header* Header_new(struct ProcessList_* pl, int nrColumns);
|
Header* Header_new(struct ProcessList_* pl, Settings* settings, int nrColumns);
|
||||||
|
|
||||||
void Header_delete(Header* this);
|
void Header_delete(Header* this);
|
||||||
|
|
||||||
|
void Header_populateFromSettings(Header* this);
|
||||||
|
|
||||||
MeterModeId Header_addMeterByName(Header* this, char* name, int column);
|
MeterModeId Header_addMeterByName(Header* this, char* name, int column);
|
||||||
|
|
||||||
void Header_setMode(Header* this, int i, MeterModeId mode, int column);
|
void Header_setMode(Header* this, int i, MeterModeId mode, int column);
|
||||||
|
|
4
Meter.c
4
Meter.c
|
@ -23,6 +23,8 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#define METER_BUFFER_LEN 256
|
#define METER_BUFFER_LEN 256
|
||||||
|
|
||||||
|
#define GRAPH_DELAY (DEFAULT_DELAY/2)
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "ListItem.h"
|
#include "ListItem.h"
|
||||||
|
|
||||||
|
@ -342,7 +344,7 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
if (!timercmp(&now, &(data->time), <)) {
|
if (!timercmp(&now, &(data->time), <)) {
|
||||||
struct timeval delay = { .tv_sec = (int)(DEFAULT_DELAY/10), .tv_usec = (DEFAULT_DELAY-((int)(DEFAULT_DELAY/10)*10)) * 100000 };
|
struct timeval delay = { .tv_sec = (int)(GRAPH_DELAY/10), .tv_usec = (GRAPH_DELAY-((int)(GRAPH_DELAY/10)*10)) * 100000 };
|
||||||
timeradd(&now, &delay, &(data->time));
|
timeradd(&now, &delay, &(data->time));
|
||||||
|
|
||||||
for (int i = 0; i < nValues - 1; i++)
|
for (int i = 0; i < nValues - 1; i++)
|
||||||
|
|
2
Meter.h
2
Meter.h
|
@ -11,6 +11,8 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#define METER_BUFFER_LEN 256
|
#define METER_BUFFER_LEN 256
|
||||||
|
|
||||||
|
#define GRAPH_DELAY (DEFAULT_DELAY/2)
|
||||||
|
|
||||||
#include "ListItem.h"
|
#include "ListItem.h"
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
10
Panel.c
10
Panel.c
|
@ -28,11 +28,11 @@ in the source distribution for its full text.
|
||||||
typedef struct Panel_ Panel;
|
typedef struct Panel_ Panel;
|
||||||
|
|
||||||
typedef enum HandlerResult_ {
|
typedef enum HandlerResult_ {
|
||||||
HANDLED = 0x00,
|
HANDLED = 0x01,
|
||||||
IGNORED = 0x01,
|
IGNORED = 0x02,
|
||||||
BREAK_LOOP = 0x02,
|
BREAK_LOOP = 0x04,
|
||||||
REFRESH = 0x04,
|
REFRESH = 0x08,
|
||||||
RECALCULATE = 0x08,
|
RECALCULATE = 0x10,
|
||||||
} HandlerResult;
|
} HandlerResult;
|
||||||
|
|
||||||
#define EVENT_SETSELECTED -1
|
#define EVENT_SETSELECTED -1
|
||||||
|
|
10
Panel.h
10
Panel.h
|
@ -17,11 +17,11 @@ in the source distribution for its full text.
|
||||||
typedef struct Panel_ Panel;
|
typedef struct Panel_ Panel;
|
||||||
|
|
||||||
typedef enum HandlerResult_ {
|
typedef enum HandlerResult_ {
|
||||||
HANDLED = 0x00,
|
HANDLED = 0x01,
|
||||||
IGNORED = 0x01,
|
IGNORED = 0x02,
|
||||||
BREAK_LOOP = 0x02,
|
BREAK_LOOP = 0x04,
|
||||||
REFRESH = 0x04,
|
REFRESH = 0x08,
|
||||||
RECALCULATE = 0x08,
|
RECALCULATE = 0x10,
|
||||||
} HandlerResult;
|
} HandlerResult;
|
||||||
|
|
||||||
#define EVENT_SETSELECTED -1
|
#define EVENT_SETSELECTED -1
|
||||||
|
|
|
@ -81,10 +81,11 @@ void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int
|
||||||
Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1);
|
Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1);
|
||||||
lastX = last->x + last->w + 1;
|
lastX = last->x + last->w + 1;
|
||||||
}
|
}
|
||||||
|
int height = LINES - this->y1 + this->y2;
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
Panel_resize(item, size, LINES-this->y1+this->y2);
|
Panel_resize(item, size, height);
|
||||||
} else {
|
} else {
|
||||||
Panel_resize(item, COLS-this->x1+this->x2-lastX, LINES-this->y1+this->y2);
|
Panel_resize(item, COLS-this->x1+this->x2-lastX, height);
|
||||||
}
|
}
|
||||||
Panel_move(item, lastX, this->y1);
|
Panel_move(item, lastX, this->y1);
|
||||||
}
|
}
|
||||||
|
@ -114,16 +115,19 @@ void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
|
||||||
this->x2 = x2;
|
this->x2 = x2;
|
||||||
this->y2 = y2;
|
this->y2 = y2;
|
||||||
int panels = this->panelCount;
|
int panels = this->panelCount;
|
||||||
int lastX = 0;
|
if (this->orientation == HORIZONTAL) {
|
||||||
for (int i = 0; i < panels - 1; i++) {
|
int lastX = 0;
|
||||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
for (int i = 0; i < panels - 1; i++) {
|
||||||
Panel_resize(panel, panel->w, LINES-y1+y2);
|
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||||
|
Panel_resize(panel, panel->w, LINES-y1+y2);
|
||||||
|
Panel_move(panel, lastX, y1);
|
||||||
|
lastX = panel->x + panel->w + 1;
|
||||||
|
}
|
||||||
|
Panel* panel = (Panel*) Vector_get(this->panels, panels-1);
|
||||||
|
Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
|
||||||
Panel_move(panel, lastX, y1);
|
Panel_move(panel, lastX, y1);
|
||||||
lastX = panel->x + panel->w + 1;
|
|
||||||
}
|
}
|
||||||
Panel* panel = (Panel*) Vector_get(this->panels, panels-1);
|
// TODO: VERTICAL
|
||||||
Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
|
|
||||||
Panel_move(panel, lastX, y1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
|
@ -154,25 +158,29 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
||||||
timeToRecalculate = (newTime - oldTime > this->settings->delay);
|
timeToRecalculate = (newTime - oldTime > this->settings->delay);
|
||||||
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
|
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
|
||||||
|
//fprintf(stderr, "\n%p %f ", this, newTime);
|
||||||
if (timeToRecalculate) {
|
|
||||||
Header_draw(this->header);
|
|
||||||
oldTime = newTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doRefresh) {
|
if (doRefresh) {
|
||||||
if (timeToRecalculate || forceRecalculate) {
|
if (timeToRecalculate || forceRecalculate) {
|
||||||
ProcessList_scan(this->header->pl);
|
ProcessList_scan(this->header->pl);
|
||||||
forceRecalculate = false;
|
//fprintf(stderr, "scan ");
|
||||||
}
|
}
|
||||||
|
//fprintf(stderr, "sortTo=%d ", sortTimeout);
|
||||||
if (sortTimeout == 0 || this->settings->treeView) {
|
if (sortTimeout == 0 || this->settings->treeView) {
|
||||||
ProcessList_sort(this->header->pl);
|
ProcessList_sort(this->header->pl);
|
||||||
|
//fprintf(stderr, "sort ");
|
||||||
sortTimeout = 1;
|
sortTimeout = 1;
|
||||||
}
|
}
|
||||||
//this->header->pl->incFilter = IncSet_filter(inc);
|
//this->header->pl->incFilter = IncSet_filter(inc);
|
||||||
ProcessList_rebuildPanel(this->header->pl);
|
ProcessList_rebuildPanel(this->header->pl);
|
||||||
|
//fprintf(stderr, "rebuild ");
|
||||||
drawPanel = true;
|
drawPanel = true;
|
||||||
}
|
}
|
||||||
|
if (timeToRecalculate || forceRecalculate) {
|
||||||
|
Header_draw(this->header);
|
||||||
|
//fprintf(stderr, "drawHeader ");
|
||||||
|
oldTime = newTime;
|
||||||
|
forceRecalculate = false;
|
||||||
|
}
|
||||||
doRefresh = true;
|
doRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +188,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
for (int i = 0; i < panels; i++) {
|
for (int i = 0; i < panels; i++) {
|
||||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||||
Panel_draw(panel, i == focus);
|
Panel_draw(panel, i == focus);
|
||||||
|
//fprintf(stderr, "drawPanel ");
|
||||||
if (i < panels) {
|
if (i < panels) {
|
||||||
if (this->orientation == HORIZONTAL) {
|
if (this->orientation == HORIZONTAL) {
|
||||||
mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
|
mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
|
||||||
|
@ -197,6 +206,8 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
int prevCh = ch;
|
int prevCh = ch;
|
||||||
ch = getch();
|
ch = getch();
|
||||||
|
|
||||||
|
//fprintf(stderr, "ch=%d ", ch);
|
||||||
|
|
||||||
if (ch == KEY_MOUSE) {
|
if (ch == KEY_MOUSE) {
|
||||||
MEVENT mevent;
|
MEVENT mevent;
|
||||||
int ok = getmouse(&mevent);
|
int ok = getmouse(&mevent);
|
||||||
|
@ -218,9 +229,9 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Panel_eventHandlerFn(panelFocus)) {
|
if (Panel_eventHandlerFn(panelFocus)) {
|
||||||
HandlerResult result = Panel_eventHandler(panelFocus, ch);
|
HandlerResult result = Panel_eventHandler(panelFocus, ch);
|
||||||
|
//fprintf(stderr, "eventResult=%d ", result);
|
||||||
if (result & REFRESH) {
|
if (result & REFRESH) {
|
||||||
doRefresh = true;
|
doRefresh = true;
|
||||||
sortTimeout = 0;
|
sortTimeout = 0;
|
||||||
|
@ -230,14 +241,15 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
sortTimeout = 0;
|
sortTimeout = 0;
|
||||||
}
|
}
|
||||||
if (result & HANDLED) {
|
if (result & HANDLED) {
|
||||||
|
drawPanel = true;
|
||||||
continue;
|
continue;
|
||||||
} else if (result & BREAK_LOOP) {
|
} else if (result & BREAK_LOOP) {
|
||||||
quit = true;
|
quit = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == ERR) {
|
if (ch == ERR) {
|
||||||
|
sortTimeout--;
|
||||||
if (prevCh == ch && !timeToRecalculate) {
|
if (prevCh == ch && !timeToRecalculate) {
|
||||||
closeTimeout++;
|
closeTimeout++;
|
||||||
if (closeTimeout == 100) {
|
if (closeTimeout == 100) {
|
||||||
|
@ -246,6 +258,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
} else
|
} else
|
||||||
closeTimeout = 0;
|
closeTimeout = 0;
|
||||||
drawPanel = false;
|
drawPanel = false;
|
||||||
|
//fprintf(stderr, "err ");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
drawPanel = true;
|
drawPanel = true;
|
||||||
|
@ -285,9 +298,12 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
quit = true;
|
quit = true;
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
//fprintf(stderr, "onKey ");
|
||||||
|
sortTimeout = resetSortTimeout;
|
||||||
Panel_onKey(panelFocus, ch);
|
Panel_onKey(panelFocus, ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
//fprintf(stderr, "loop ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastFocus)
|
if (lastFocus)
|
||||||
|
|
|
@ -20,7 +20,10 @@ int TasksMeter_attributes[] = {
|
||||||
|
|
||||||
static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
||||||
Platform_setTasksValues(this);
|
Platform_setTasksValues(this);
|
||||||
snprintf(buffer, len, "%d/%d", (int) this->values[0], (int) this->total);
|
if (this->pl->settings->hideKernelThreads) {
|
||||||
|
this->values[0] = 0;
|
||||||
|
}
|
||||||
|
snprintf(buffer, len, "%d/%d", (int) this->values[3], (int) this->total);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TasksMeter_display(Object* cast, RichString* out) {
|
static void TasksMeter_display(Object* cast, RichString* out) {
|
||||||
|
|
11
htop.c
11
htop.c
|
@ -188,10 +188,13 @@ int main(int argc, char** argv) {
|
||||||
UsersTable* ut = UsersTable_new();
|
UsersTable* ut = UsersTable_new();
|
||||||
ProcessList* pl = ProcessList_new(ut, flags.pidWhiteList, flags.userId);
|
ProcessList* pl = ProcessList_new(ut, flags.pidWhiteList, flags.userId);
|
||||||
|
|
||||||
Header* header = Header_new(pl, 2);
|
|
||||||
Settings* settings = Settings_new(pl->cpuCount);
|
Settings* settings = Settings_new(pl->cpuCount);
|
||||||
pl->settings = settings;
|
pl->settings = settings;
|
||||||
|
|
||||||
|
Header* header = Header_new(pl, settings, 2);
|
||||||
|
|
||||||
|
Header_populateFromSettings(header);
|
||||||
|
|
||||||
if (flags.delay != -1)
|
if (flags.delay != -1)
|
||||||
settings->delay = flags.delay;
|
settings->delay = flags.delay;
|
||||||
if (!flags.useColors)
|
if (!flags.useColors)
|
||||||
|
@ -225,8 +228,8 @@ int main(int argc, char** argv) {
|
||||||
};
|
};
|
||||||
MainPanel_setState(panel, &state);
|
MainPanel_setState(panel, &state);
|
||||||
|
|
||||||
ScreenManager* scr = ScreenManager_new(0, 0, 0, -1, HORIZONTAL, header, settings, true);
|
ScreenManager* scr = ScreenManager_new(0, header->height, 0, -1, HORIZONTAL, header, settings, true);
|
||||||
ScreenManager_add(scr, (Panel*) panel, defaultBar, 0);
|
ScreenManager_add(scr, (Panel*) panel, defaultBar, -1);
|
||||||
|
|
||||||
ProcessList_scan(pl);
|
ProcessList_scan(pl);
|
||||||
millisleep(75);
|
millisleep(75);
|
||||||
|
@ -265,7 +268,7 @@ int main(int argc, char** argv) {
|
||||||
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
||||||
bool timeToRecalculate = (newTime - oldTime > settings->delay);
|
bool timeToRecalculate = (newTime - oldTime > settings->delay);
|
||||||
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
|
if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
|
||||||
int following = follow ? Action_selectedPid(panel) : -1;
|
int following = follow ? MainPanel_selectedPid((MainPanel*)panel) : -1;
|
||||||
if (timeToRecalculate) {
|
if (timeToRecalculate) {
|
||||||
Header_draw(header);
|
Header_draw(header);
|
||||||
oldTime = newTime;
|
oldTime = newTime;
|
||||||
|
|
285
linux/Battery.c
285
linux/Battery.c
|
@ -11,28 +11,24 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
#include "BatteryMeter.h"
|
#include "BatteryMeter.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
static unsigned long int parseUevent(FILE * file, const char *key) {
|
#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply"
|
||||||
char line[100];
|
|
||||||
unsigned long int dValue = 0;
|
|
||||||
char* saveptr;
|
|
||||||
|
|
||||||
while (fgets(line, sizeof line, file)) {
|
// ----------------------------------------
|
||||||
if (strncmp(line, key, strlen(key)) == 0) {
|
// READ FROM /proc
|
||||||
char *value;
|
// ----------------------------------------
|
||||||
strtok_r(line, "=", &saveptr);
|
|
||||||
value = strtok_r(NULL, "=", &saveptr);
|
// This implementation reading from from /proc/acpi is really inefficient,
|
||||||
dValue = atoi(value);
|
// but I think this is on the way out so I did not rewrite it.
|
||||||
break;
|
// The /sys implementation below does things the right way.
|
||||||
}
|
|
||||||
}
|
|
||||||
return dValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
|
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
|
||||||
const char batteryPath[] = PROCDIR "/acpi/battery/";
|
const char batteryPath[] = PROCDIR "/acpi/battery/";
|
||||||
|
@ -94,15 +90,15 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short
|
||||||
static ACPresence procAcpiCheck() {
|
static ACPresence procAcpiCheck() {
|
||||||
ACPresence isOn = AC_ERROR;
|
ACPresence isOn = AC_ERROR;
|
||||||
const char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
|
const char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
DIR *dir = opendir(power_supplyPath);
|
||||||
if (!power_supplyDir) {
|
if (!dir) {
|
||||||
return AC_ERROR;
|
return AC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent result;
|
struct dirent result;
|
||||||
struct dirent* dirEntry;
|
struct dirent* dirEntry;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
int err = readdir_r((DIR *) dir, &result, &dirEntry);
|
||||||
if (err || !dirEntry)
|
if (err || !dirEntry)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -139,62 +135,12 @@ static ACPresence procAcpiCheck() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (power_supplyDir)
|
if (dir)
|
||||||
closedir(power_supplyDir);
|
closedir(dir);
|
||||||
return isOn;
|
return isOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ACPresence sysCheck() {
|
static double Battery_getProcBatData() {
|
||||||
ACPresence isOn = AC_ERROR;
|
|
||||||
const char *power_supplyPath = "/sys/class/power_supply";
|
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
|
||||||
if (!power_supplyDir) {
|
|
||||||
return AC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dirent result;
|
|
||||||
struct dirent* dirEntry;
|
|
||||||
for (;;) {
|
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
|
||||||
if (err || !dirEntry)
|
|
||||||
break;
|
|
||||||
|
|
||||||
char* entryName = (char *) dirEntry->d_name;
|
|
||||||
if (strncmp(entryName, "A", 1)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char onlinePath[50];
|
|
||||||
snprintf((char *) onlinePath, sizeof onlinePath, "%s/%s/online", power_supplyPath, entryName);
|
|
||||||
FILE* file = fopen(onlinePath, "r");
|
|
||||||
if (!file) {
|
|
||||||
isOn = AC_ERROR;
|
|
||||||
} else {
|
|
||||||
isOn = (fgetc(file) - '0');
|
|
||||||
fclose(file);
|
|
||||||
if (isOn == AC_PRESENT) {
|
|
||||||
// If any AC adapter is being used then stop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (power_supplyDir)
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
|
|
||||||
return isOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACPresence Battery_isOnAC() {
|
|
||||||
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
|
|
||||||
return procAcpiCheck();
|
|
||||||
} else if (access("/sys/class/power_supply", F_OK) == 0) {
|
|
||||||
return sysCheck();
|
|
||||||
} else {
|
|
||||||
return AC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double Battery_getProcBatData() {
|
|
||||||
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
|
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
|
||||||
if (totalFull == 0)
|
if (totalFull == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -206,11 +152,58 @@ double Battery_getProcBatData() {
|
||||||
return totalRemain * 100.0 / (double) totalFull;
|
return totalRemain * 100.0 / (double) totalFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Battery_getSysBatData() {
|
static void Battery_getProcData(double* level, ACPresence* isOnAC) {
|
||||||
const char *power_supplyPath = "/sys/class/power_supply/";
|
*level = Battery_getProcBatData();
|
||||||
DIR *power_supplyDir = opendir(power_supplyPath);
|
*isOnAC = procAcpiCheck();
|
||||||
if (!power_supplyDir)
|
}
|
||||||
return 0;
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// READ FROM /sys
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
static inline ssize_t xread(int fd, void *buf, size_t count) {
|
||||||
|
// Read some bytes. Retry on EINTR and when we don't get as many bytes as we requested.
|
||||||
|
size_t alreadyRead = 0;
|
||||||
|
for(;;) {
|
||||||
|
ssize_t res = read(fd, buf, count);
|
||||||
|
if (res == -1 && errno == EINTR) continue;
|
||||||
|
if (res > 0) {
|
||||||
|
buf = ((char*)buf)+res;
|
||||||
|
count -= res;
|
||||||
|
alreadyRead += res;
|
||||||
|
}
|
||||||
|
if (res == -1) return -1;
|
||||||
|
if (count == 0 || res == 0) return alreadyRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the suffix of `str` if its beginning matches `prefix`.
|
||||||
|
* Returns NULL if the prefix does not match.
|
||||||
|
* Examples:
|
||||||
|
* match("hello world", "hello "); -> "world"
|
||||||
|
* match("hello world", "goodbye "); -> NULL
|
||||||
|
*/
|
||||||
|
static inline const char* match(const char* str, const char* prefix) {
|
||||||
|
for (;;) {
|
||||||
|
if (*prefix == '\0') {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
if (*prefix != *str) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
prefix++; str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Battery_getSysData(double* level, ACPresence* isOnAC) {
|
||||||
|
|
||||||
|
*level = 0;
|
||||||
|
*isOnAC = AC_ERROR;
|
||||||
|
|
||||||
|
DIR *dir = opendir(SYS_POWERSUPPLY_DIR);
|
||||||
|
if (!dir)
|
||||||
|
return;
|
||||||
|
|
||||||
unsigned long int totalFull = 0;
|
unsigned long int totalFull = 0;
|
||||||
unsigned long int totalRemain = 0;
|
unsigned long int totalRemain = 0;
|
||||||
|
@ -218,52 +211,120 @@ double Battery_getSysBatData() {
|
||||||
struct dirent result;
|
struct dirent result;
|
||||||
struct dirent* dirEntry;
|
struct dirent* dirEntry;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry);
|
int err = readdir_r((DIR *) dir, &result, &dirEntry);
|
||||||
if (err || !dirEntry)
|
if (err || !dirEntry)
|
||||||
break;
|
break;
|
||||||
char* entryName = (char *) dirEntry->d_name;
|
char* entryName = (char *) dirEntry->d_name;
|
||||||
|
const char filePath[50];
|
||||||
|
|
||||||
if (strncmp(entryName, "BAT", 3)) {
|
if (entryName[0] == 'B' && entryName[1] == 'A' && entryName[2] == 'T') {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char ueventPath[50];
|
snprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName);
|
||||||
|
int fd = open(filePath, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
closedir(dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[1024];
|
||||||
|
ssize_t buflen = xread(fd, buffer, 1023);
|
||||||
|
close(fd);
|
||||||
|
if (buflen < 1) {
|
||||||
|
closedir(dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer[buflen] = '\0';
|
||||||
|
char *buf = buffer;
|
||||||
|
char *line = NULL;
|
||||||
|
bool full = false;
|
||||||
|
bool now = false;
|
||||||
|
while ((line = strsep(&buf, "\n")) != NULL) {
|
||||||
|
const char* ps = match(line, "POWER_SUPPLY_");
|
||||||
|
if (!ps) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char* energy = match(ps, "ENERGY_");
|
||||||
|
if (!energy) {
|
||||||
|
energy = match(ps, "CHARGE_");
|
||||||
|
}
|
||||||
|
if (!energy) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char* value = (!full) ? match(energy, "FULL=") : NULL;
|
||||||
|
if (value) {
|
||||||
|
totalFull += atoi(value);
|
||||||
|
full = true;
|
||||||
|
if (now) break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
value = (!now) ? match(energy, "NOW=") : NULL;
|
||||||
|
if (value) {
|
||||||
|
totalRemain += atoi(value);
|
||||||
|
now = true;
|
||||||
|
if (full) break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (entryName[0] == 'A') {
|
||||||
|
if (*isOnAC != AC_ERROR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf((char *) ueventPath, sizeof ueventPath, "%s%s/uevent", power_supplyPath, entryName);
|
snprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/online", entryName);
|
||||||
|
int fd = open(filePath, O_RDONLY);
|
||||||
FILE *file;
|
if (fd == -1) {
|
||||||
if ((file = fopen(ueventPath, "r")) == NULL) {
|
closedir(dir);
|
||||||
closedir(power_supplyDir);
|
return;
|
||||||
return 0;
|
}
|
||||||
}
|
char buffer[2] = "";
|
||||||
|
for(;;) {
|
||||||
if ((totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL="))) {
|
ssize_t res = read(fd, buffer, 1);
|
||||||
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
|
if (res == -1 && errno == EINTR) continue;
|
||||||
} else {
|
break;
|
||||||
//reset file pointer
|
}
|
||||||
if (fseek(file, 0, SEEK_SET) < 0) {
|
close(fd);
|
||||||
closedir(power_supplyDir);
|
if (buffer[0] == '0') {
|
||||||
fclose(file);
|
*isOnAC = AC_ABSENT;
|
||||||
return 0;
|
} else if (buffer[0] == '1') {
|
||||||
|
*isOnAC = AC_PRESENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
*level = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
|
||||||
|
}
|
||||||
|
|
||||||
//Some systems have it as CHARGE instead of ENERGY.
|
static enum { BAT_PROC, BAT_SYS, BAT_ERR } Battery_method = BAT_PROC;
|
||||||
if ((totalFull += parseUevent(file, "POWER_SUPPLY_CHARGE_FULL="))) {
|
|
||||||
totalRemain += parseUevent(file, "POWER_SUPPLY_CHARGE_NOW=");
|
|
||||||
} else {
|
|
||||||
//reset file pointer
|
|
||||||
if (fseek(file, 0, SEEK_SET) < 0) {
|
|
||||||
closedir(power_supplyDir);
|
|
||||||
fclose(file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
static time_t Battery_cacheTime = 0;
|
||||||
|
static double Battery_cacheLevel = 0;
|
||||||
|
static ACPresence Battery_cacheIsOnAC = 0;
|
||||||
|
|
||||||
|
void Battery_getData(double* level, ACPresence* isOnAC) {
|
||||||
|
time_t now = time(NULL);
|
||||||
|
// update battery reading is slow. Update it each 10 seconds only.
|
||||||
|
if (now < Battery_cacheTime + 10) {
|
||||||
|
*level = Battery_cacheLevel;
|
||||||
|
*isOnAC = Battery_cacheIsOnAC;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
|
if (Battery_method == BAT_PROC) {
|
||||||
closedir(power_supplyDir);
|
Battery_getProcData(level, isOnAC);
|
||||||
return percent;
|
if (*level == 0) {
|
||||||
|
Battery_method = BAT_SYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Battery_method == BAT_SYS) {
|
||||||
|
Battery_getSysData(level, isOnAC);
|
||||||
|
if (*level == 0) {
|
||||||
|
Battery_method = BAT_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Battery_method == BAT_ERR) {
|
||||||
|
*level = -1;
|
||||||
|
*isOnAC = AC_ERROR;
|
||||||
|
}
|
||||||
|
Battery_cacheLevel = *level;
|
||||||
|
Battery_cacheIsOnAC = *isOnAC;
|
||||||
|
Battery_cacheTime = now;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,27 @@ Linux battery readings written by Ian P. Hands (iphands@gmail.com, ihands@redhat
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ACPresence Battery_isOnAC();
|
#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply"
|
||||||
|
|
||||||
double Battery_getProcBatData();
|
// ----------------------------------------
|
||||||
|
// READ FROM /proc
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
double Battery_getSysBatData();
|
// This implementation reading from from /proc/acpi is really inefficient,
|
||||||
|
// but I think this is on the way out so I did not rewrite it.
|
||||||
|
// The /sys implementation below does things the right way.
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// READ FROM /sys
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the suffix of `str` if its beginning matches `prefix`.
|
||||||
|
* Returns NULL if the prefix does not match.
|
||||||
|
* Examples:
|
||||||
|
* match("hello world", "hello "); -> "world"
|
||||||
|
* match("hello world", "goodbye "); -> NULL
|
||||||
|
*/
|
||||||
|
void Battery_getData(double* level, ACPresence* isOnAC);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Action.h"
|
#include "Action.h"
|
||||||
|
#include "MainPanel.h"
|
||||||
#include "BatteryMeter.h"
|
#include "BatteryMeter.h"
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ static Htop_Reaction Platform_actionSetIOPriority(State* st) {
|
||||||
void* set = Action_pickFromVector(st, ioprioPanel, 21, fuFunctions);
|
void* set = Action_pickFromVector(st, ioprioPanel, 21, fuFunctions);
|
||||||
if (set) {
|
if (set) {
|
||||||
IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel);
|
IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel);
|
||||||
bool ok = Action_foreachProcess(panel, (Action_ForeachProcessFn) LinuxProcess_setIOPriority, (size_t) ioprio, NULL);
|
bool ok = MainPanel_foreachProcess((MainPanel*)panel, (MainPanel_ForeachProcessFn) LinuxProcess_setIOPriority, (size_t) ioprio, NULL);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
beep();
|
beep();
|
||||||
}
|
}
|
||||||
|
@ -106,23 +107,6 @@ int Platform_getMaxPid() {
|
||||||
return maxPid;
|
return maxPid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Platform_getBatteryLevel(double* level, ACPresence* isOnAC) {
|
|
||||||
|
|
||||||
double percent = Battery_getProcBatData();
|
|
||||||
|
|
||||||
if (percent == 0) {
|
|
||||||
percent = Battery_getSysBatData();
|
|
||||||
if (percent == 0) {
|
|
||||||
*level = -1;
|
|
||||||
*isOnAC = AC_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*isOnAC = Battery_isOnAC();
|
|
||||||
*level = percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Platform_setCPUValues(Meter* this, int cpu) {
|
double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
LinuxProcessList* pl = (LinuxProcessList*) this->pl;
|
LinuxProcessList* pl = (LinuxProcessList*) this->pl;
|
||||||
CPUData* cpuData = &(pl->cpus[cpu]);
|
CPUData* cpuData = &(pl->cpus[cpu]);
|
||||||
|
|
|
@ -10,6 +10,7 @@ in the source distribution for its full text.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Action.h"
|
#include "Action.h"
|
||||||
|
#include "MainPanel.h"
|
||||||
#include "BatteryMeter.h"
|
#include "BatteryMeter.h"
|
||||||
|
|
||||||
void Platform_setBindings(Htop_Action* keys);
|
void Platform_setBindings(Htop_Action* keys);
|
||||||
|
@ -22,8 +23,6 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen);
|
||||||
|
|
||||||
int Platform_getMaxPid();
|
int Platform_getMaxPid();
|
||||||
|
|
||||||
void Platform_getBatteryLevel(double* level, ACPresence* isOnAC);
|
|
||||||
|
|
||||||
double Platform_setCPUValues(Meter* this, int cpu);
|
double Platform_setCPUValues(Meter* this, int cpu);
|
||||||
|
|
||||||
void Platform_setMemoryValues(Meter* this);
|
void Platform_setMemoryValues(Meter* this);
|
||||||
|
|
Loading…
Reference in New Issue