#include #include #include #include #include #include #include #include #include #include #include #include #include #include // include with: sudo apt install nlohmann-json3-dev using json = nlohmann::json; using namespace std; // Utility to execute shell commands and capture output string execCmd(const string &cmd){ array buffer; string result; FILE* pipe=popen(cmd.c_str(),"r"); if(!pipe)return ""; while(fgets(buffer.data(),buffer.size(),pipe)!=nullptr)result+=buffer.data(); pclose(pipe); if(!result.empty()&&result.back()=='\n')result.pop_back(); return result; } // ----- Module functions ----- string getBattery(){ string percent=execCmd("cat /sys/class/power_supply/BAT*/capacity 2>/dev/null"); string status=execCmd("cat /sys/class/power_supply/BAT*/status 2>/dev/null"); string energyNow=execCmd("cat /sys/class/power_supply/BAT*/energy_now 2>/dev/null"); string powerNow=execCmd("cat /sys/class/power_supply/BAT*/power_now 2>/dev/null"); string energyFull=execCmd("cat /sys/class/power_supply/BAT*/energy_full 2>/dev/null"); int val=percent.empty()?0:stoi(percent); string icon; if(status=="Charging")icon="󰂄"; else if(val>90)icon="󰁹"; else if(val>70)icon="󰂀"; else if(val>50)icon="󰁾"; else if(val>30)icon="󰁼"; else icon="󰁺"; string timeLeft; if(!energyNow.empty()&&!powerNow.empty()){ double eNow=stod(energyNow); double pNow=stod(powerNow); double eFull=energyFull.empty()?eNow:eNow+1000; if(pNow>0){ double hours=0; if(status=="Charging")hours=(eFull-eNow)/pNow; else if(status=="Discharging")hours=eNow/pNow; int h=(int)hours; int m=(int)((hours-h)*60); stringstream tss; tss<<" ("</dev/null"); if(mode=="performance")return " 󰓅 Performance "; if(mode=="balanced")return " 󰾅 Balanced "; if(mode=="power-saver")return " 󰾆 Power Saver "; return " 󰾆 Unknown "; } string getSound(){ string vol=execCmd("pamixer --get-volume 2>/dev/null"); string mute=execCmd("pamixer --get-mute 2>/dev/null"); string icon=(mute=="true")?" 󰝟":" 󰕾"; return icon+" "+(vol.empty()?"0":vol)+"% "; } string getMic(){ string vol=execCmd("pamixer --default-source --get-volume 2>/dev/null"); string mute=execCmd("pamixer --default-source --get-mute 2>/dev/null"); string icon=(mute=="true")?" 󰍭":" 󰍬"; return icon+" "+(vol.empty()?"0":vol)+"% "; } string getDunst(){ string status=execCmd("dunstctl is-paused 2>/dev/null"); return (status=="true")?" 󰂛 Off ":" 󰂚 On "; } string getBrightness(){ namespace fs = std::filesystem; string path; for(const auto& dir: fs::directory_iterator("/sys/class/backlight/")){ path = dir.path(); break; } if(path.empty()) return " 🌞 N/A "; string cur = execCmd("cat "+path+"/brightness"); string max = execCmd("cat "+path+"/max_brightness"); if(cur.empty() || max.empty()) return " 🌞 N/A "; double perc = stod(cur) / stod(max) * 100.0; string icon = (perc > 75) ? "󰃠" : (perc > 50) ? "󰃡" : (perc > 25) ? "󰃢" : "󰃣"; stringstream ss; ss << " " << icon << " " << fixed << setprecision(0) << perc << "% "; return ss.str(); } double getCpuUsage() { static long long lastTotal=0, lastIdle=0; std::ifstream file("/proc/stat"); std::string line; getline(file,line); // first line: "cpu …" std::istringstream ss(line); std::string cpu; long long user, nice, system, idle, iowait, irq, softirq, steal; ss >> cpu >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal; long long idleTime = idle + iowait; long long total = user+nice+system+idle+iowait+irq+softirq+steal; long long diffIdle = idleTime - lastIdle; long long diffTotal = total - lastTotal; lastIdle = idleTime; lastTotal = total; if(diffTotal==0)return 0.0; return (double)(diffTotal - diffIdle) / diffTotal * 100.0; } string getCPU(){ string temp=execCmd("sensors | grep 'Package id 0:' | awk '{print $4}' | tr -d '+'"); double usage = getCpuUsage(); //execCmd("mpstat 1 1 | awk '/all/ {print 100-$12}'"); stringstream ss; ss<<" 󰍛 "<>key>>val>>unit){ if(key=="MemTotal:")total=val; if(key=="MemAvailable:")avail=val; } long used=total-avail; double usedGB=used/1024.0/1024.0; double totalGB=total/1024.0/1024.0; string icon=" 󰍛"; stringstream ss; ss</dev/null"); string eth=execCmd("ip link show | grep 'state UP' | grep eth | awk '{print $2}' | tr -d ':'"); string ip=execCmd("hostname -I | awk '{print $1}'"); string out; if(!wifi.empty()){ string strength=execCmd("awk 'NR==3 {print int($3)}' /proc/net/wireless 2>/dev/null"); out+="󰖩 "+wifi; if(!strength.empty())out+=" ("+strength+"%)"; if(!ip.empty())out+=" "+ip; }else out+="󰖪 Wi-Fi Off"; if(!eth.empty()){ if(!out.empty())out+=" | "; out+="󰈀 "+eth; if(!ip.empty())out+=" "+ip; }else{ if(out.find("Wi-Fi Off")==string::npos){ // only show 'no eth' if not both off out+=" | 󰌙 No ETH"; } } if(out.find("󰖩")==string::npos&&out.find("󰈀")==string::npos) out="󰖪 Offline"; return " "+out+" "; } string getStorage(){ string df=execCmd("df -h /home/ | awk 'NR==2 {print $3\"/\"$2}'"); return " 󰋊 "+df+" "; } string getDateTime(){ time_t t=time(nullptr); tm* now=localtime(&t); stringstream ss; const char* days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; ss<<" 󰃭 "<tm_wday]<<" "< blocks; // TEXT | BACK blocks.push_back(makeBlock("battery",getBattery(),"#cdd6f4","#000000")); //313244 blocks.push_back(makeBlock("power",getPowerMode(),"#f9e2af","#000000")); //45475a blocks.push_back(makeBlock("sound",getSound(),"#a6e3a1","#000000")); //313244 // blocks.push_back(makeBlock("mic",getMic(),"#f38ba8","#000000")); //313244 // blocks.push_back(makeBlock("dunst",getDunst(),"#b4befe","#313244")); blocks.push_back(makeBlock("brightness", getBrightness(), "#f38ba8", "#000000")); //313244 blocks.push_back(makeBlock("cpu",getCPU(),"#89b4fa","#000000")); //45475a blocks.push_back(makeBlock("ram",getRAM(),"#fab387","#000000")); //313244 blocks.push_back(makeBlock("net",getNetwork(),"#94e2d5","#000000")); //45475a blocks.push_back(makeBlock("storage",getStorage(),"#f5c2e7","#000000")); //313244 blocks.push_back(makeBlock("clock",getDateTime(),"#f2cdcd","#000000")); //45475a if(!first)cout<<","<0 && (fds[0].revents&POLLIN)){ string line; if(getline(cin,line)){ try{ json click=json::parse(line); string name=click.value("name",""); if(name=="power")system("~/Projects/C+++/statusBar/scripts/toggle_performance.sh &"); // else if(name=="dunst")system("~/Projects/C+++/statusBar/scripts/toggle_dunst.sh &"); else if(name=="mic")system("~/Projects/C+++/statusBar/scripts/toggle_mic.sh &"); else if(name=="sound")system("~/Projects/C+++/statusBar/scripts/toggle_sound.sh &"); else if(name=="net")system("alacritty -e nmtui &"); }catch(...){ // ignore malformed input } } } this_thread::sleep_for(chrono::milliseconds(500)); } }