From 95537f39e44353151b78dde8bf08bc1613fa8772 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 31 Oct 2021 06:05:54 -0700 Subject: [PATCH] Switch to using process names for process condition and executable tab (#337) Previously the process condition and executable tab were just reusing the window title functionality. --- .github/workflows/build-debian.yml | 2 +- .github/workflows/build.yml | 3 +- CMakeLists.txt | 25 +++++--- src/linux/advanced-scene-switcher-nix.cpp | 76 +++++++++++++++++++++-- 4 files changed, 89 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-debian.yml b/.github/workflows/build-debian.yml index 0e9e00a3..886722b1 100644 --- a/.github/workflows/build-debian.yml +++ b/.github/workflows/build-debian.yml @@ -43,7 +43,7 @@ jobs: # devscripts and libobs-dev are needed but they were already installed # from check_libobs_revision and install_frontend_header sections. sudo apt update - sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev + sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev libprocps-dev - name: build run: | debuild --no-lintian --no-sign diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc1b8812..899cafd0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -179,7 +179,8 @@ jobs: libxss-dev \ libx11-xcb-dev \ libxcb-xfixes0-dev \ - libopencv-dev + libopencv-dev \ + libprocps-dev - name: 'Configure' shell: bash run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index fd884eb4..19ac5d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,9 +137,20 @@ endif() if(UNIX AND NOT APPLE) find_package(X11 REQUIRED COMPONENTS Xtst Xss) - link_libraries(${X11_LIBRARIES}) + find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h) + if(NOT PROCPS_INCLUDE_DIR) + message( + FATAL_ERROR "procps include dir not found - please set PROCPS_INCLUDE_DIR" + ) + endif() + find_library(PROCPS_LIBRARY NAMES procps) + if(NOT PROCPS_LIBRARY) + message(FATAL_ERROR "procps lib not found - please set PROCPS_LIBRARY") + endif() + message (STATUS "WHAT THE FUCK IS GOING ON ${PROCPS_LIBRARY}") + link_libraries(${X11_LIBRARIES} ${procps_LIBRARIES}) include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}" - "${X11_Xss_INCLUDE_PATH}") + "${X11_Xss_INCLUDE_PATH}" "${PROCPS_INCLUDE_DIR}") endif() if(WIN32) @@ -154,7 +165,7 @@ elseif(APPLE) else() set(advanced-scene-switcher_PLATFORM_SOURCES src/linux/advanced-scene-switcher-nix.cpp) - set(advanced-scene-switcher_PLATFORM_LIBS Xss) + set(advanced-scene-switcher_PLATFORM_LIBS Xss ${PROCPS_LIBRARY}) endif() # asio and websocketpp @@ -401,11 +412,7 @@ if(BUILD_OUT_OF_TREE) else() # In tree build target_link_libraries( - advanced-scene-switcher - ${advanced-scene-switcher_PLATFORM_LIBS} - ${OpenCV_LIBRARIES} - obs-frontend-api - Qt5::Widgets - libobs) + advanced-scene-switcher ${advanced-scene-switcher_PLATFORM_LIBS} + ${OpenCV_LIBRARIES} obs-frontend-api Qt5::Widgets libobs) install_obs_plugin_with_data(advanced-scene-switcher data) endif() diff --git a/src/linux/advanced-scene-switcher-nix.cpp b/src/linux/advanced-scene-switcher-nix.cpp index 6685816f..feff37b3 100644 --- a/src/linux/advanced-scene-switcher-nix.cpp +++ b/src/linux/advanced-scene-switcher-nix.cpp @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include static Display *xdisplay = 0; @@ -363,17 +366,78 @@ bool isFullscreen(const std::string &title) void GetProcessList(QStringList &processes) { processes.clear(); - for (size_t i = 0; i < getTopLevelWindows().size(); ++i) { - std::string s = GetWindowTitle(i); - if (s != "") - processes << QString::fromStdString(s); + PROCTAB *proc = openproc(PROC_FILLSTAT); + proc_t proc_info; + memset(&proc_info, 0, sizeof(proc_info)); + while (readproc(proc, &proc_info) != NULL) { + QString procName(proc_info.cmd); + if (!procName.isEmpty() && !processes.contains(proc_info.cmd)) { + processes << QString(proc_info.cmd); + } } + closeproc(proc); +} + +int getForegroundProcessPid() +{ + if (!ewmhIsSupported()) { + return -1; + } + + auto dpy = disp(); + Atom active = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", true); + Atom actualType; + int format; + unsigned long num, bytes; + Window *window = 0; + int pid = -1; + + Window rootWin = RootWindow(dpy, 0); + + int xstatus = XGetWindowProperty(dpy, rootWin, active, 0L, ~0L, false, + AnyPropertyType, &actualType, &format, + &num, &bytes, (uint8_t **)&window); + + if (xstatus == 0 && window == nullptr) { + return -1; + } + + Atom atom, actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop; + atom = XInternAtom(dpy, "_NET_WM_PID", True); + auto status = XGetWindowProperty(dpy, *window, atom, 0, 1024, False, + AnyPropertyType, &actual_type, + &actual_format, &nitems, &bytes_after, + &prop); + + if (status != 0) { + return -2; + } + if (!prop) { + return -3; + } + + pid = prop[1] * 256; + pid += prop[0]; + return pid; +} + +std::string getProcNameFromPid(int pid) +{ + std::string path = "/proc/" + std::to_string(pid) + "/comm"; + std::ifstream t(path); + std::stringstream buffer; + buffer << t.rdbuf(); + return buffer.str(); } bool isInFocus(const QString &executable) { - std::string current; - GetCurrentWindowTitle(current); + auto pid = getForegroundProcessPid(); + std::string current = getProcNameFromPid(pid); // True if executable switch equals current window bool equals = (executable.toStdString() == current);