#include #include #include #include #include #include #include #include #include // #include "vene.h" #include extern "C" { #include "slstatus/slstatus.h" } #define DMENU_ARGS "-b", "-f", "-i", "-l", "30", "-fn", "monospace:size=14" using namespace std; using namespace std::chrono; using namespace std::literals; namespace fs = std::filesystem; char* HOME; char SCREEN_CAPS_DIR[64]; namespace { time_point next_update; bool has_child; Proc child; Cmd browser(BROWSER); Cmd low_battery_notify("notify-send", "--urgency=critical", "Battery Low"); } extern "C" { // from dwm struct Monitor; typedef struct { const char *symbol; void (*arrange)(Monitor *); } Layout; struct Client { char name[256]; float mina, maxa; int x, y, w, h; int oldx, oldy, oldw, oldh; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; Window win; }; struct Monitor { char ltsymbol[16]; float mfact; int nmaster; int num; int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; int showbar; int topbar; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; const Layout *lt[2]; }; typedef union { int i; unsigned int ui; float f; const void *v; } Arg; extern Monitor *selmon; void updatestatus(); void view(const Arg* arg); // end void vene_setup() { // Init vars HOME = getenv("HOME"); strcpy(SCREEN_CAPS_DIR, HOME); strcat(SCREEN_CAPS_DIR, "/screenshots/ss.png"); // strcpy(BOOKMARK_DIR, HOME); // strcat(BOOKMARK_DIR, "/notes/bookmarks/web"); } void vene_updatestatus(char status[]) { using std::string; static string new_stat; new_stat.clear(); try { // Net #if defined(__linux__) for(const auto& dir_entry: fs::directory_iterator("/sys/class/net")) { string interface_state; string interface = dir_entry.path().filename(); switch(interface[0]) { case 'e': // if the name begins with 'e' its ethernet ifstream(dir_entry.path() / "operstate") >> interface_state; if(interface_state == "up") new_stat += "🌐 "; break; case 'w': // 'w' means wifi if(const char* ssid = wifi_essid(interface.c_str()); ssid) // Connected { // State new_stat += "🛜"; new_stat += ssid; new_stat += ' '; // Quality percent if(const char* perc = wifi_perc(interface.c_str()); perc) { new_stat += perc; new_stat += "% "; } } else // Disconnected { string wifi_state; ifstream(dir_entry.path() / "flags") >> wifi_state; if( wifi_state == "0x1003") new_stat += "📡 "; } break; } } #else if(const char* ssid = wifi_essid("iwn0"); ssid) { new_stat += "🛜"; new_stat += ssid; new_stat += ' '; if(const char* perc = wifi_perc("iwn0"); perc) { new_stat += perc; new_stat += "% "; } } #endif // Battery string charge; ifstream("/sys/class/power_supply/BAT0/capacity") >> charge; if( !charge.empty() ) // If we have a charge we have a battery { string state; ifstream("/sys/class/power_supply/BAT0/status") >> state; const char* remaining = ""; if(state == "Discharging") { new_stat += "🔋"; remaining = battery_remaining("BAT0"); // Low battery warning if(remaining && atoi(charge.c_str()) < 15) run(low_battery_notify); // todo: use lib notify } else new_stat += "🔌"; new_stat += charge; new_stat += "% "; new_stat += remaining; new_stat += ' '; } } catch(...){ cerr << "EXCEPT\n"; } // Volume string vol_out = $({"wpctl", "get-volume", "@DEFAULT_AUDIO_SINK@"}); size_t vol_begin = vol_out.find(' '); if(vol_begin != string::npos) { bool is_muted = vol_out.find("[MUTED]") != string::npos; new_stat += is_muted ? "🔇" : "🔉"; size_t first_digit = vol_begin + 1; size_t vol_end = vol_out.find(' ', first_digit); if(vol_end == string::npos) vol_end = vol_out.size() + 1; float vol = stof( vol_out.substr(first_digit, vol_end - first_digit) ); new_stat += to_string(int(vol * 100)) + "% "; } // Time time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); new_stat += (timeinfo->tm_hour/10) + '0'; new_stat += (timeinfo->tm_hour%10) + '0'; new_stat += ':'; new_stat += (timeinfo->tm_min/10) + '0'; new_stat += (timeinfo->tm_min%10) + '0'; strcpy(status, new_stat.c_str()); // todo: write directly to status } void vene_run() // update status bar every 5 sec { time_point now = system_clock::now(); if(has_child && check_exited(child)) { // Clean up all zombies while (waitpid(-1, nullptr, WNOHANG) > 0); has_child = false; updatestatus(); next_update = now + 10s; } else if(!has_child && now > next_update) { // Clean up all zombies while (waitpid(-1, nullptr, WNOHANG) > 0); updatestatus(); next_update = now + 10s; } } void vene_screenshot(const Arg*) { Cmd scrot("scrot", "-s", "-"); Cmd tee("tee", SCREEN_CAPS_DIR); Cmd to_clip("xclip", "-selection", "clipboard", "-t", "image/png"); scrot | tee | to_clip; // todo: cppipe < string } void vene_clip_history(const Arg*) { // Select a history entry and put to clip Cmd clipmenu("clipmenu", DMENU_ARGS); // Paste Cmd xdotool("xdotool", "key", "--delay", "0", "--clearmodifiers", "shift+Insert"); clipmenu && xdotool; } void vene_browser(const Arg* browser_tag) { bool browser_tag_used = false; for(Client* c = selmon->clients; c; c = c->next) if(c->tags & browser_tag->ui) { browser_tag_used = true; break; } if( browser_tag_used ) // browser tag is used, view it { view(browser_tag); } else // start browser { detach(browser); } } void vene_webbookmark() // todo: cppipe exceptions { Cmd dmenu( "dmenu", DMENU_ARGS); string bm_root = HOME + "/sync/bookmarks/web/"s; Cmd list_dirs ("ls", bm_root.c_str()); // Initial bookmark directory string dir = "Luxoft"; while(true) { string bm_dir = bm_root + dir; // Read content of bookmarks file and choose string entry = $(dmenu < bm_dir.c_str()); // Extract link size_t link_begin = entry.find('-'); if(link_begin != string::npos) { Cmd open_bookmark = browser + (entry.c_str() + link_begin + 1); // skip - detach(open_bookmark); break; } // Choose bookmark directory dir = $(list_dirs | dmenu); if( dir.empty() ) return; } } void vene_inc_vol(const Arg*) { Cmd inc_vol("wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", "3%+"); child = detach(inc_vol); has_child = true; } void vene_dec_vol(const Arg*) { Cmd dec_vol("wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", "3%-"); child = detach(dec_vol); has_child = true; } void vene_toggle_vol(const Arg*) { Cmd toggle_vol("wpctl", "set-mute", "@DEFAULT_AUDIO_SINK@", "toggle"); child = detach(toggle_vol); has_child = true; } void vene_toggle_mic(const Arg*) { Cmd toggle_mic("wpctl", "set-mute", "@DEFAULT_AUDIO_SOURCE@", "toggle"); child = detach(toggle_mic); has_child = true; } void vene_zzz(const Arg*) { ofstream("/sys/power/state") << "mem"; } }