#define __USE_POSIX #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct Atoms { Atom netActiveWindow = 0; Atom netWmPid = 0; Atom wmClientMachine = 0; }; class XInstance { public: Atoms atoms; static constexpr unsigned long MAX_BYTES = 1048576; int screen = 0; Display *display = nullptr; private: unsigned long readProparty(Window wid, Atom atom, unsigned char** prop, int* format) { Atom returnedAtom; unsigned long nitems; unsigned long bytes_after; int ret = XGetWindowProperty( display, wid, atom, 0, XInstance::MAX_BYTES/4, false, AnyPropertyType, &returnedAtom, format, &nitems, &bytes_after, prop); if (ret != Success) { std::cerr<<"XGetWindowProperty failed!\n"; return 0; } else return std::min((*format)/8*nitems, XInstance::MAX_BYTES); } Atom getAtom(const std::string& atomName) { return XInternAtom(display, atomName.c_str(), true); } public: bool open(const std::string& xDisplayName) { display = XOpenDisplay(xDisplayName.c_str()); if (display == nullptr) { std::cerr<<"Can not open display "<(data); XFree(data); return wid; } pid_t getPid(Window wid) { XTextProperty xWidHostNameTextProperty; bool ret = XGetTextProperty(display, wid, &xWidHostNameTextProperty, atoms.wmClientMachine); if (!ret) { char errorString[1024]; XGetErrorText(display, ret, errorString, 1024); std::cerr<<"XGetWMClientMachine failed! "<(data); XFree(data); } else { std::cout<<"Window "< split(const std::string& in, char delim = '\n' ) { std::stringstream ss(in); std::vector tokens; std::string temp_str; while(std::getline(ss, temp_str, delim)) { tokens.push_back(temp_str); } return tokens; } class Process { public: pid_t pid = -1; std::string name; bool operator==(const Process& in) { return pid == in.pid; } bool operator!=(const Process& in) { return pid != in.pid; } Process(){} Process(pid_t pidIn) { std::fstream statusFile; std::string statusString; statusFile.open(std::string("/proc/") + std::to_string(pidIn)+ "/status", std::fstream::in); if(statusFile.is_open()) { std::string statusString((std::istreambuf_iterator(statusFile)), std::istreambuf_iterator()); std::vector lines = split(statusString); if(lines.size() > 0) { pid = pidIn; std::vector tokens = split(lines[0], '\t'); if(tokens.size() > 1) { name = tokens[1]; } } statusFile.close(); } else { std::cout<<"cant open "<<"/proc/" + std::to_string(pidIn)+ "/status"<(blacklistFile)), std::istreambuf_iterator()); } std::vector applicationNames = split(blacklistString); struct stat sb; if( stat("/proc/version", &sb) != 0) { std::cerr<<"proc must be mounted!\n"; return 1; } char* xDisplayName = std::getenv( "DISPLAY" ); if(xDisplayName == nullptr) { std::cerr<<"DISPLAY enviroment variable must be set.\n"; return 1; } if(!xinstance.open(xDisplayName)) exit(1); XSelectInput(xinstance.display, RootWindow(xinstance.display, xinstance.screen), PropertyChangeMask | StructureNotifyMask); XEvent event; Process prevProcess; Window prevWindow = 0; while(true) { XNextEvent(xinstance.display, &event); if (event.type == DestroyNotify) break; if (event.type == PropertyNotify && event.xproperty.atom == xinstance.atoms.netActiveWindow) { Window wid = xinstance.getActiveWindow(); if(wid != 0 && wid != prevWindow) { pid_t windowPid = xinstance.getPid(wid); Process process(windowPid); if(process != prevProcess) { for(size_t i = 0; i < applicationNames.size(); ++i) { if(process.name == applicationNames[i] && process.name != "" && wid != 0) { kill(process.pid, SIGCONT); std::cout<<"Resumeing: "<