mirror of
https://github.com/aristocratos/btop.git
synced 2025-12-23 22:29:08 -05:00
feature: add process renice functionality
This adds the ability to change the nice value of a process from within btop. A new menu is introduced, accessible by pressing 'N', which allows the user to input a new nice value for the selected process. Fixes #1245
This commit is contained in:
@@ -1662,11 +1662,14 @@ namespace Proc {
|
||||
}
|
||||
out += title_left + hi_color + Fx::b + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right
|
||||
+ title_left + hi_color + Fx::b + 's' + t_color + "ignals" + Fx::ub + title_right
|
||||
+ title_left + hi_color + Fx::b + 'N' + t_color + "ice" + Fx::ub + title_right
|
||||
+ Mv::to(d_y, d_x + d_width - 10) + title_left + t_color + Fx::b + hide + Symbols::enter + Fx::ub + title_right;
|
||||
if (alive and selected == 0) {
|
||||
Input::mouse_mappings["k"] = {d_y, mouse_x, 1, 4};
|
||||
mouse_x += 6;
|
||||
Input::mouse_mappings["s"] = {d_y, mouse_x, 1, 7};
|
||||
mouse_x += 9;
|
||||
Input::mouse_mappings["N"] = {d_y, mouse_x, 1, 5};
|
||||
}
|
||||
if (selected == 0) Input::mouse_mappings["enter"] = {d_y, d_x + d_width - 9, 1, 6};
|
||||
|
||||
@@ -1760,6 +1763,9 @@ namespace Proc {
|
||||
}
|
||||
out += title_left_down + Fx::b + hi_color + 's' + t_color + "ignals" + Fx::ub + title_right_down;
|
||||
if (selected > 0) Input::mouse_mappings["s"] = {y + height - 1, mouse_x, 1, 7};
|
||||
mouse_x += 9;
|
||||
out += title_left_down + Fx::b + hi_color + 'N' + t_color + "ice" + Fx::ub + title_right_down;
|
||||
if (selected > 0) Input::mouse_mappings["N"] = {y + height -1, mouse_x, 1, 5};
|
||||
|
||||
//? Labels for fields in list
|
||||
if (not proc_tree)
|
||||
|
||||
@@ -421,6 +421,12 @@ namespace Input {
|
||||
Menu::show(Menu::Menus::SignalChoose);
|
||||
return;
|
||||
}
|
||||
else if (key == "N" and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) {
|
||||
atomic_wait(Runner::active);
|
||||
if (Config::getB("show_detailed") and Config::getI("proc_selected") == 0 and Proc::detailed.status == "Dead") return;
|
||||
Menu::show(Menu::Menus::Renice);
|
||||
return;
|
||||
}
|
||||
else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k", "g", "G"))) {
|
||||
proc_mouse_scroll:
|
||||
redraw = false;
|
||||
|
||||
@@ -203,6 +203,7 @@ namespace Menu {
|
||||
{"Selected t", "Terminate selected process with SIGTERM - 15."},
|
||||
{"Selected k", "Kill selected process with SIGKILL - 9."},
|
||||
{"Selected s", "Select or enter signal to send to process."},
|
||||
{"Selected N", "Select new nice value for selected process."},
|
||||
{"", " "},
|
||||
{"", "For bug reporting and project updates, visit:"},
|
||||
{"", "https://github.com/aristocratos/btop"},
|
||||
@@ -1595,6 +1596,94 @@ static int optionsMenu(const string& key) {
|
||||
return (redraw ? Changed : retval);
|
||||
}
|
||||
|
||||
static int reniceMenu(const string& key) {
|
||||
auto s_pid = (Config::getB("show_detailed") and Config::getI("selected_pid") == 0 ? Config::getI("detailed_pid") : Config::getI("selected_pid"));
|
||||
static int x{};
|
||||
static int y{};
|
||||
static int selected_nice = 0;
|
||||
static string nice_edit;
|
||||
|
||||
if (bg.empty()) {
|
||||
selected_nice = 0;
|
||||
nice_edit.clear();
|
||||
}
|
||||
auto& out = Global::overlay;
|
||||
int retval = Changed;
|
||||
|
||||
if (redraw) {
|
||||
x = Term::width/2 - 25;
|
||||
y = Term::height/2 - 6;
|
||||
bg = Draw::createBox(x + 2, y, 50, 13, Theme::c("hi_fg"), true, "renice");
|
||||
bg += Mv::to(y+2, x+3) + Theme::c("title") + Fx::b + cjust("Renice PID " + to_string(s_pid) + " ("
|
||||
+ uresize((s_pid == Config::getI("detailed_pid") ? Proc::detailed.entry.name : Config::getS("selected_name")), 15) + ")", 48);
|
||||
}
|
||||
else if (is_in(key, "escape", "q")) {
|
||||
return Closed;
|
||||
}
|
||||
else if (is_in(key, "enter", "space")) {
|
||||
if (s_pid > 0) {
|
||||
if (not nice_edit.empty()) {
|
||||
try {
|
||||
selected_nice = stoi(nice_edit);
|
||||
}
|
||||
catch (...) { selected_nice = 0; }
|
||||
}
|
||||
if (not Proc::set_priority(s_pid, selected_nice)) {
|
||||
// TODO: show error message
|
||||
}
|
||||
}
|
||||
return Closed;
|
||||
}
|
||||
else if (key.size() == 1 and (isdigit(key.at(0)) or (key.at(0) == '-' and nice_edit.empty()))) {
|
||||
nice_edit += key;
|
||||
}
|
||||
else if (key == "backspace" and not nice_edit.empty()) {
|
||||
nice_edit.pop_back();
|
||||
}
|
||||
else if (is_in(key, "up", "k")) {
|
||||
if (++selected_nice > 19) selected_nice = -20;
|
||||
nice_edit.clear();
|
||||
}
|
||||
else if (is_in(key, "down", "j")) {
|
||||
if (--selected_nice < -20) selected_nice = 19;
|
||||
nice_edit.clear();
|
||||
}
|
||||
else if (is_in(key, "left", "h")) {
|
||||
if ((selected_nice -= 5) < -20) selected_nice += 40;
|
||||
nice_edit.clear();
|
||||
}
|
||||
else if (is_in(key, "right", "l")) {
|
||||
if ((selected_nice += 5) > 19) selected_nice -= 40;
|
||||
nice_edit.clear();
|
||||
}
|
||||
else {
|
||||
retval = NoChange;
|
||||
}
|
||||
|
||||
if (retval == Changed) {
|
||||
int cy = y+4;
|
||||
if (not nice_edit.empty()) {
|
||||
try {
|
||||
selected_nice = stoi(nice_edit);
|
||||
}
|
||||
catch (...) { selected_nice = 0; }
|
||||
}
|
||||
out = bg + Mv::to(cy++, x+3) + Theme::c("main_fg") + Fx::ub
|
||||
+ rjust("Enter nice value: ", 30) + Theme::c("hi_fg") + (nice_edit.empty() ? to_string(selected_nice) : nice_edit) + Theme::c("main_fg") + Fx::bl + "█" + Fx::ubl;
|
||||
|
||||
cy++;
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓", 20, true) + Theme::c("main_fg") + Fx::ub + " | To change value.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "← →", 20, true) + Theme::c("main_fg") + Fx::ub + " | To change value by 5.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("0-9", 20) + Theme::c("main_fg") + Fx::ub + " | Enter manually.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 20) + Theme::c("main_fg") + Fx::ub + " | To set nice value.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or 'q'", 20) + Theme::c("main_fg") + Fx::ub + " | To abort.";
|
||||
|
||||
out += Fx::reset;
|
||||
}
|
||||
|
||||
return (redraw ? Changed : retval);
|
||||
}
|
||||
|
||||
//* Add menus here and update enum Menus in header
|
||||
const auto menuFunc = vector{
|
||||
ref(sizeError),
|
||||
@@ -1603,6 +1692,7 @@ static int optionsMenu(const string& key) {
|
||||
ref(signalReturn),
|
||||
ref(optionsMenu),
|
||||
ref(helpMenu),
|
||||
ref(reniceMenu),
|
||||
ref(mainMenu),
|
||||
};
|
||||
bitset<8> menuMask;
|
||||
|
||||
@@ -72,6 +72,8 @@ namespace Menu {
|
||||
|
||||
//? Clears content vector and private strings
|
||||
void clear();
|
||||
int getX() const { return x; }
|
||||
int getY() const { return y; }
|
||||
};
|
||||
|
||||
extern bitset<8> menuMask;
|
||||
@@ -84,6 +86,7 @@ namespace Menu {
|
||||
SignalReturn,
|
||||
Options,
|
||||
Help,
|
||||
Renice,
|
||||
Main
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <ranges>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
@@ -87,6 +88,13 @@ namespace Gpu {
|
||||
#endif
|
||||
|
||||
namespace Proc {
|
||||
bool set_priority(pid_t pid, int priority) {
|
||||
if (setpriority(PRIO_PROCESS, pid, priority) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void proc_sorter(vector<proc_info>& proc_vec, const string& sorting, bool reverse, bool tree) {
|
||||
if (reverse) {
|
||||
switch (v_index(sort_vector, sorting)) {
|
||||
|
||||
@@ -431,6 +431,9 @@ namespace Proc {
|
||||
vector<tree_proc> children;
|
||||
};
|
||||
|
||||
//* Change priority (nice) of pid, returns true on success otherwise false
|
||||
bool set_priority(pid_t pid, int priority);
|
||||
|
||||
//* Sort vector of proc_info's
|
||||
void proc_sorter(vector<proc_info>& proc_vec, const string& sorting, bool reverse, bool tree = false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user