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:
Yusuf Salk
2025-10-06 23:54:22 +03:00
committed by Yusuf Salk
parent 184a59fa0e
commit 1c6413db04
6 changed files with 116 additions and 0 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
};

View File

@@ -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)) {

View File

@@ -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);