mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Linux: resolve procps symbols at runtime
This is done to be able to support both libprocps and libproc2. Either of them or neither might be available on all platforms and this should not prevent the plugin from being used at all.
This commit is contained in:
parent
57e4b1a3f1
commit
83914d5378
|
|
@ -464,27 +464,24 @@ else()
|
|||
|
||||
find_path(PROCPS_INCLUDE_DIR NAMES proc/procps.h)
|
||||
find_path(PROCPS2_INCLUDE_DIR NAMES libproc2/pids.h)
|
||||
find_library(PROCPS_LIBRARY NAMES procps)
|
||||
find_library(PROCPS2_LIBRARY NAMES proc2)
|
||||
if(PROCPS_INCLUDE_DIR AND PROCPS_LIBRARY)
|
||||
if(PROCPS_INCLUDE_DIR)
|
||||
message(STATUS "${PROJECT_NAME} using procps")
|
||||
set(PROC_INCLUDE_DIR "${PROCPS_INCLUDE_DIR}")
|
||||
set(PROC_LIBRARY "${PROCPS_LIBRARY}")
|
||||
target_compile_definitions(${LIB_NAME} PRIVATE USE_PROCPS)
|
||||
elseif(PROCPS2_INCLUDE_DIR AND PROCPS2_LIBRARY)
|
||||
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS_AVAILABLE)
|
||||
set(PROCESS_CONDITION_SUPPORTED 1)
|
||||
endif()
|
||||
if(PROCPS2_INCLUDE_DIR)
|
||||
message(STATUS "${PROJECT_NAME} using libproc2")
|
||||
set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}")
|
||||
set(PROC_LIBRARY "${PROCPS2_LIBRARY}")
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"found neither procps nor libproc2!
|
||||
please either set ...
|
||||
PROCPS_INCLUDE_DIR and PROCPS_LIBRARY
|
||||
... or ...
|
||||
PROCPS2_INCLUDE_DIR and PROCPS2_LIBRARY")
|
||||
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_AVAILABLE)
|
||||
set(PROCESS_CONDITION_SUPPORTED 1)
|
||||
endif()
|
||||
if(NOT DEFINED PROCESS_CONDITION_SUPPORTED)
|
||||
message(
|
||||
WARNING
|
||||
"found neither procps nor libproc2! Process condition will not be functional!"
|
||||
)
|
||||
endif()
|
||||
target_link_libraries(${LIB_NAME} PRIVATE "${PROC_LIBRARY}")
|
||||
target_include_directories(${LIB_NAME} PRIVATE "${PROC_INCLUDE_DIR}")
|
||||
|
||||
find_package(CURL)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "platform-funcs.hpp"
|
||||
#include "hotkey.hpp"
|
||||
#include "log-helper.hpp"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
|
@ -25,9 +26,10 @@
|
|||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QLibrary>
|
||||
#ifdef USE_PROCPS
|
||||
#ifdef PROCPS_AVAILABLE
|
||||
#include <proc/readproc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef PROCPS2_AVAILABLE
|
||||
#include <libproc2/pids.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
|
|
@ -53,6 +55,31 @@ std::chrono::high_resolution_clock::time_point lastMouseLeftClickTime{};
|
|||
std::chrono::high_resolution_clock::time_point lastMouseMiddleClickTime{};
|
||||
std::chrono::high_resolution_clock::time_point lastMouseRightClickTime{};
|
||||
|
||||
static QLibrary *libprocps = nullptr;
|
||||
#ifdef PROCPS_AVAILABLE
|
||||
typedef PROCTAB *(*openproc_func)(int flags);
|
||||
typedef void (*closeproc_func)(PROCTAB *PT);
|
||||
typedef proc_t *(*readproc_func)(PROCTAB *__restrict const PT,
|
||||
proc_t *__restrict p);
|
||||
static openproc_func openproc_ = nullptr;
|
||||
static closeproc_func closeproc_ = nullptr;
|
||||
static readproc_func readproc_ = nullptr;
|
||||
#endif
|
||||
static bool libprocpsSupported = false;
|
||||
|
||||
static QLibrary *libproc2 = nullptr;
|
||||
#ifdef PROCPS2_AVAILABLE
|
||||
typedef int (*procps_pids_new_func)(struct pids_info **info,
|
||||
enum pids_item *items, int numitems);
|
||||
typedef struct pids_stack *(*procps_pids_get_func)(struct pids_info *info,
|
||||
enum pids_fetch_type which);
|
||||
typedef int (*procps_pids_unref_func)(struct pids_info **info);
|
||||
static procps_pids_new_func procps_pids_new_ = nullptr;
|
||||
static procps_pids_get_func procps_pids_get_ = nullptr;
|
||||
static procps_pids_unref_func procps_pids_unref_ = nullptr;
|
||||
#endif
|
||||
static bool libprocps2Supported = false;
|
||||
|
||||
Display *disp()
|
||||
{
|
||||
if (!xdisplay) {
|
||||
|
|
@ -338,46 +365,57 @@ std::optional<std::string> GetTextInWindow(const std::string &)
|
|||
return {};
|
||||
}
|
||||
|
||||
#ifdef USE_PROCPS
|
||||
void GetProcessList(QStringList &processes)
|
||||
static void getProcessListProcps(QStringList &processes)
|
||||
{
|
||||
processes.clear();
|
||||
PROCTAB *proc = openproc(PROC_FILLSTAT);
|
||||
#ifdef PROCPS_AVAILABLE
|
||||
PROCTAB *proc = openproc_(PROC_FILLSTAT);
|
||||
proc_t proc_info;
|
||||
memset(&proc_info, 0, sizeof(proc_info));
|
||||
while (readproc(proc, &proc_info) != NULL) {
|
||||
while (readproc_(proc, &proc_info) != NULL) {
|
||||
QString procName(proc_info.cmd);
|
||||
if (!procName.isEmpty() && !processes.contains(procName)) {
|
||||
processes << procName;
|
||||
}
|
||||
}
|
||||
closeproc(proc);
|
||||
closeproc_(proc);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void GetProcessList(QStringList &processes)
|
||||
|
||||
static void getProcessListProcps2(QStringList &processes)
|
||||
{
|
||||
processes.clear();
|
||||
#ifdef PROCPS2_AVAILABLE
|
||||
struct pids_info *info = NULL;
|
||||
struct pids_stack *stack;
|
||||
enum pids_item Items[] = {
|
||||
PIDS_CMD,
|
||||
};
|
||||
|
||||
if (procps_pids_new(&info, Items, sizeof(Items) / sizeof(Items[0])) <
|
||||
if (procps_pids_new_(&info, Items, sizeof(Items) / sizeof(Items[0])) <
|
||||
0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((stack = procps_pids_get(info, PIDS_FETCH_TASKS_ONLY))) {
|
||||
while ((stack = procps_pids_get_(info, PIDS_FETCH_TASKS_ONLY))) {
|
||||
auto cmd = PIDS_VAL(0, str, stack, info);
|
||||
QString procName(cmd);
|
||||
if (!procName.isEmpty() && !processes.contains(procName)) {
|
||||
processes << procName;
|
||||
}
|
||||
}
|
||||
procps_pids_unref(&info);
|
||||
}
|
||||
procps_pids_unref_(&info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetProcessList(QStringList &processes)
|
||||
{
|
||||
processes.clear();
|
||||
if (libprocpsSupported) {
|
||||
getProcessListProcps(processes);
|
||||
return;
|
||||
}
|
||||
if (libprocps2Supported) {
|
||||
getProcessListProcps2(processes);
|
||||
}
|
||||
}
|
||||
|
||||
long getForegroundProcessPid()
|
||||
{
|
||||
|
|
@ -633,6 +671,58 @@ void PressKeys(const std::vector<HotkeyType> keys, int duration)
|
|||
XFlush(display);
|
||||
}
|
||||
|
||||
static void initXtst()
|
||||
{
|
||||
libXtstHandle = new QLibrary("libXtst", nullptr);
|
||||
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
|
||||
int _;
|
||||
canSimulateKeyPresses = pressFunc &&
|
||||
XQueryExtension(disp(), "XTEST", &_, &_, &_);
|
||||
}
|
||||
|
||||
static void initXss()
|
||||
{
|
||||
libXssHandle = new QLibrary("libXss", nullptr);
|
||||
allocSSFunc = (XScreenSaverAllocInfoFunc)libXssHandle->resolve(
|
||||
"XScreenSaverAllocInfo");
|
||||
querySSFunc = (XScreenSaverQueryInfoFunc)libXssHandle->resolve(
|
||||
"XScreenSaverQueryInfo");
|
||||
int _;
|
||||
canGetIdleTime = allocSSFunc && querySSFunc &&
|
||||
XQueryExtension(disp(), ScreenSaverName, &_, &_, &_);
|
||||
}
|
||||
|
||||
static void initProcps()
|
||||
{
|
||||
#ifdef PROCPS_AVAILABLE
|
||||
libprocps = new QLibrary("libprocps", nullptr);
|
||||
openproc_ = (openproc_func)libprocps->resolve("openproc");
|
||||
closeproc_ = (closeproc_func)libprocps->resolve("closeproc");
|
||||
readproc_ = (readproc_func)libprocps->resolve("readproc");
|
||||
if (openproc_ && closeproc_ && readproc_) {
|
||||
libprocpsSupported = true;
|
||||
blog(LOG_INFO, "libprocps symbols resolved successfully!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void initProc2()
|
||||
{
|
||||
#ifdef PROCPS2_AVAILABLE
|
||||
libproc2 = new QLibrary("libproc2", nullptr);
|
||||
procps_pids_new_ =
|
||||
(procps_pids_new_func)libproc2->resolve("procps_pids_new");
|
||||
procps_pids_get_ =
|
||||
(procps_pids_get_func)libproc2->resolve("procps_pids_get");
|
||||
procps_pids_unref_ =
|
||||
(procps_pids_unref_func)libproc2->resolve("procps_pids_unref");
|
||||
if (procps_pids_new_ && procps_pids_get_ && procps_pids_unref_) {
|
||||
libprocps2Supported = true;
|
||||
blog(LOG_INFO, "libproc2 symbols resolved successfully!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlatformInit()
|
||||
{
|
||||
auto display = disp();
|
||||
|
|
@ -640,31 +730,26 @@ void PlatformInit()
|
|||
return;
|
||||
}
|
||||
|
||||
libXtstHandle = new QLibrary("libXtst", nullptr);
|
||||
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
|
||||
int _;
|
||||
canSimulateKeyPresses = pressFunc &&
|
||||
XQueryExtension(disp(), "XTEST", &_, &_, &_);
|
||||
initXtst();
|
||||
initXss();
|
||||
initProcps();
|
||||
initProc2();
|
||||
}
|
||||
|
||||
libXssHandle = new QLibrary("libXss", nullptr);
|
||||
allocSSFunc = (XScreenSaverAllocInfoFunc)libXssHandle->resolve(
|
||||
"XScreenSaverAllocInfo");
|
||||
querySSFunc = (XScreenSaverQueryInfoFunc)libXssHandle->resolve(
|
||||
"XScreenSaverQueryInfo");
|
||||
canGetIdleTime = allocSSFunc && querySSFunc &&
|
||||
XQueryExtension(disp(), ScreenSaverName, &_, &_, &_);
|
||||
static void cleanupHelper(QLibrary *lib)
|
||||
{
|
||||
if (lib) {
|
||||
delete lib;
|
||||
lib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformCleanup()
|
||||
{
|
||||
if (libXtstHandle) {
|
||||
delete libXtstHandle;
|
||||
libXtstHandle = nullptr;
|
||||
}
|
||||
if (libXssHandle) {
|
||||
delete libXssHandle;
|
||||
libXssHandle = nullptr;
|
||||
}
|
||||
cleanupHelper(libXtstHandle);
|
||||
cleanupHelper(libXssHandle);
|
||||
cleanupHelper(libprocps);
|
||||
cleanupHelper(libproc2);
|
||||
cleanupDisplay();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user