Skip to content

Commit

Permalink
v1.8.2 - [Linux]: Optimized Internal Library && Tray Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukylix committed Feb 1, 2024
1 parent 9a54594 commit 86c6801
Show file tree
Hide file tree
Showing 6 changed files with 6,048 additions and 5,976 deletions.
1 change: 1 addition & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"args": [
"-shared",
"-fPIC",
"-lX11",
"-o",
"./resources/chrolog.so",
"./src/lib//chrolog/chrolog.cpp",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chrolog",
"version": "1.8.1",
"version": "1.8.2",
"description": "A automated time tracking tool",
"main": "./out/main/index.mjs",
"author": "lukylix",
Expand Down
288 changes: 180 additions & 108 deletions src/lib/chrolog/chrolog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
#include <psapi.h>
#endif
#ifdef linux
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
#include <stdexcept>
#include <cstring>
#include <vector>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

#include <dlfcn.h>
#include <filesystem>
#include <sys/wait.h>
#include <cstring>
#include <dirent.h>
#include <stdlib.h>
#include <filesystem>
#include <dlfcn.h>
#include <signal.h>
#include <sys/stat.h>
#include <set>
#include <fstream>
#include <unordered_set>
#endif

#include <stdint.h>
Expand Down Expand Up @@ -249,154 +252,212 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv

#ifdef linux // Linux

static bool isGonome = false;
static bool shouldExit = false;

static std::set<int> g_processIds;
static std::set<int>::iterator processIter;
static bool shouldExit = false;

std::string trim(const std::string &str)
const char *EmptyString()
{
size_t first = str.find_first_not_of(' ');
if (std::string::npos == first)
{
return str;
}
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last - first + 1));
char *cstr = new char[1];
cstr[0] = '\0';
return cstr;
}

std::string getLibraryPath()
int GetActiveWindowPID()
{
Dl_info dl_info;
dladdr((void *)getLibraryPath, &dl_info);
std::filesystem::path libPath(dl_info.dli_fname);
return libPath.parent_path();
}
Display *display = XOpenDisplay(nullptr);
if (!display)
{
return -1;
}

std::string exec(std::string cmd)
{
const char *cmdChar = cmd.c_str();
std::array<char, 128> buffer;
std::string result;
try
Window root = DefaultRootWindow(display);
Atom netActiveWindow = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
Atom type;
int format;
unsigned long nitems;
unsigned long bytesAfter;
unsigned char *data;
if (XGetWindowProperty(display, root, netActiveWindow, 0, 1, False, XA_WINDOW, &type, &format, &nitems, &bytesAfter, &data) != Success || nitems == 0)
{
FILE *pipe = popen(cmdChar, "r");
if (!pipe)
{
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
{
result += buffer.data();
}
if (pclose(pipe) != 0)
{
throw std::runtime_error("pclose() failed!");
}
XCloseDisplay(display);
return -1;
}

Window win = ((Window *)data)[0];
XFree(data);
if (win == None)
{
XCloseDisplay(display);
return -1;
}
catch (std::exception &e)
Atom netWmPid = XInternAtom(display, "_NET_WM_PID", False);
if (XGetWindowProperty(display, win, netWmPid, 0, 1, False, XA_CARDINAL, &type, &format, &nitems, &bytesAfter, &data) != Success || nitems == 0)
{
result = "";
return result;
XCloseDisplay(display);
return -1;
}
return result;
int pid = ((int *)data)[0];
XFree(data);
return pid;
}

const char *GetActiveAppGnome()
const char *GetProcessPath(int pid)
{
std::string cmd = "readlink -f /proc/$(xdotool getwindowpid $(xdotool getwindowfocus))/exe";
std::string result = exec(cmd.c_str());
std::string process = trim(result.substr(result.find_last_of("/") + 1));
char *cstr = new char[process.length() + 1];
strcpy(cstr, process.c_str());
return cstr;
char procPath[PATH_MAX];
snprintf(procPath, sizeof(procPath), "/proc/%d/exe", pid);
char processName[PATH_MAX];
ssize_t len = readlink(procPath, processName, sizeof(processName) - 1);
if (len == -1)
{
return EmptyString();
}
processName[len] = '\0';
std::string to_remove = " (deleted)";
std::string processNameStr = processName;
size_t pos = processNameStr.find(to_remove);
if (pos != std::string::npos)
{
processNameStr.erase(pos, to_remove.length());
}
strcpy(processName, processNameStr.c_str());

const char *processNameConst = processName;
return processNameConst;
}

const char *GetActiveAppX11()
const char *GetProcessName(const char *processPath)
{
std::string cmd = "readlink -f /proc/$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_PID | cut -d ' ' -f 3)/exe";
std::string result = exec(cmd.c_str());
std::string process = trim(result.substr(result.find_last_of("/") + 1));
if (processPath[0] == '\0')
{
return EmptyString();
}
size_t lastSlashIndex = std::string(processPath).find_last_of("/");
if (lastSlashIndex == std::string::npos)
return EmptyString();
std::string process = processPath;
process = process.substr(lastSlashIndex + 1);
if (process.empty())
return EmptyString();
char *cstr = new char[process.length() + 1];
strcpy(cstr, process.c_str());
return cstr;
}

const char *GetActiveApp()
{
if (isGonome)
int activeWindowPID = GetActiveWindowPID();
if (activeWindowPID == -1)
{
return GetActiveAppGnome();
return EmptyString();
}
else
const char *processPath = GetProcessPath(activeWindowPID);
if (processPath[0] == '\0')
{
return GetActiveAppX11();
return EmptyString();
}
const char *processName = GetProcessName(processPath);
return processName;
}

char **GetProcessInfos(int pid)
int getProcessUID(int pid)
{
std::string cmd = "ps -p " + std::to_string(pid) + " -o comm=,cmd=";
std::string result = exec(cmd.c_str());
std::string resultTrimmed = trim(result);
std::string process = trim(resultTrimmed.substr(0, resultTrimmed.find(" ")));
std::string secondHalf = trim(resultTrimmed.substr(resultTrimmed.find(" ") + 1));
std::string processPath = trim(secondHalf.substr(0, secondHalf.find(" ")));

char *processChar = new char[process.length() + 1];
strcpy(processChar, process.c_str());
char *processPathChar = new char[processPath.length() + 1];
strcpy(processPathChar, processPath.c_str());
char **vec = new char *[2];
if (process.empty())
{
vec[0] = new char[1];
vec[0][0] = '\0';
}
else
struct stat info;
char path[256];
sprintf(path, "/proc/%d", pid);
if (stat(path, &info) == 0)
{
vec[0] = processChar;
int uid = info.st_uid;
return uid;
}
if (processPath.empty())
{
vec[1] = new char[1];
vec[1][0] = '\0';
}
else
return -1;
}

int GetMinUID()
{
std::ifstream file("/etc/login.defs");
std::string line;

while (std::getline(file, line))
{
vec[1] = processPathChar;
std::istringstream iss(line);
std::string word;
iss >> word;
if (word == "UID_MIN")
{
iss >> word;
return std::stoi(word);
break;
}
}
return vec;

return 1000;
}

static int minUID = GetMinUID();

char *IntToString(int value)
{
int length = snprintf(NULL, 0, "%d", value);
char *str = new char[length + 1];
snprintf(str, length + 1, "%d", value);
return str;
}

char **GetProcessInfos(int pid)
{
const char *processPathConst = GetProcessPath(pid);
char *processPath = new char[strlen(processPathConst) + 1];
strcpy(processPath, processPathConst);

const char *processNameConst = GetProcessName(processPath);
char *processName = new char[strlen(processNameConst) + 1];
strcpy(processName, processNameConst);

char **infos = new char *[2];
infos[0] = processPath;
infos[1] = processName;
return infos;
}

bool EnumWindowsProcessIds()
{
std::unordered_set<std::string> processNames;

g_processIds.clear();
std::string cmd = "ps -U root -u root -N -o pid=";
std::string result = exec(cmd.c_str());
std::string resultTrimmed = trim(result);
if (resultTrimmed.empty())
DIR *dir = opendir("/proc");
if (dir == NULL)
{
return false;
}
std::string delimiter = "\n";
size_t pos = 0;
std::string token;
while ((pos = resultTrimmed.find(delimiter)) != std::string::npos)
struct dirent *entry;
while ((entry = readdir(dir)) != NULL)
{
token = resultTrimmed.substr(0, pos);
int tokenInt = std::stoi(token);
if (tokenInt < 1000)
{
resultTrimmed.erase(0, pos + delimiter.length());
int pid = atoi(entry->d_name);
int uid = getProcessUID(pid);
if (uid < minUID)
continue;
}
g_processIds.insert(std::stoi(token));
resultTrimmed.erase(0, pos + delimiter.length());

const char *path = GetProcessPath(pid);
if (path[0] == '\0')
continue;

const char *processName = GetProcessName(path);
if (processName[0] == '\0' || processNames.find(processName) != processNames.end())

continue;

processNames.insert(processName);

g_processIds.insert(pid);
}

closedir(dir);
processIter = g_processIds.begin();
return true;
}

int GetNextProcessId()
{

Expand All @@ -410,6 +471,14 @@ int GetNextProcessId()
return processId ? processId : 0;
}

std::string getLibraryPath()
{
Dl_info dl_info;
dladdr((void *)getLibraryPath, &dl_info);
std::filesystem::path libPath(dl_info.dli_fname);
return libPath.parent_path();
}

pid_t child_pid;

void sendSiginalToChild(int sig)
Expand All @@ -423,7 +492,10 @@ void sendSiginalToChild(int sig)
void initialize()
{
setenv("DISPLAY", ":0", 0);
std::string cmd = "'" + getLibraryPath() + "/chrolog-server" + "'";
std::string path = getLibraryPath() + "/chrolog-server";
std::string cmd = "'" + path + "'";
if (!std::filesystem::exists(path))
return;
std::string cmdSudo = "/usr/bin/pkexec --disable-internal-agent " + cmd + " &";
pid_t pid = fork();
if (pid == 0)
Expand Down
1 change: 0 additions & 1 deletion src/main/utilis/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ const addProcessToFetch = (pid) => {

export const getProcessesListener = async () => {
if (lastProcessFetchTime + 1000 > Date.now() || !isChrologLoaded) return
console.log('get-windows-with-icons')
lastProcessFetchTime = Date.now()
processes = []
const isSucess = load({
Expand Down
Loading

0 comments on commit 86c6801

Please sign in to comment.