From 3e5a5e01fead702b6df298cc7172e56043762c06 Mon Sep 17 00:00:00 2001 From: Carl Klemm Date: Thu, 4 Jun 2020 18:18:43 +0200 Subject: [PATCH] Inital version --- CMakeLists.txt | 16 +++ main.cpp | 289 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b51b074 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.4) + + +project(sigstoped) + +set(SRC_FILES main.cpp ) +set(LIBS -lX11) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) + +target_link_libraries( ${PROJECT_NAME} ${LIBS}) +target_include_directories(${PROJECT_NAME} PRIVATE "/usr/include/glib-2.0/" "/usr/lib/glib-2.0/include" "/usr/include/gdk-pixbuf-2.0") +set_target_properties( ${PROJECT_NAME} PROPERTIES COMPILE_FLAGS -m64 LINK_FLAGS -m64) +add_definitions(" -std=c++17 -Wall -O2 -flto -fno-strict-aliasing") + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1c0aa81 --- /dev/null +++ b/main.cpp @@ -0,0 +1,289 @@ +#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; + } + 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); + + for(size_t i = 0; i < applicationNames.size(); ++i) + { + if(process.name == applicationNames[i]) + { + kill(process.pid, SIGCONT); + std::cout<<"Resumeing: "<