gsr-hyprland-helper: workaround flatpak bug with environment variables

This commit is contained in:
dec05eba
2026-01-27 18:49:18 +01:00
parent 3b2a09f8e1
commit 1dbe34c891
2 changed files with 73 additions and 35 deletions

View File

@@ -1,6 +1,7 @@
#include "../include/HyprlandWorkaround.hpp" #include "../include/HyprlandWorkaround.hpp"
#include "../include/Process.hpp"
#include <iostream> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <thread> #include <thread>
@@ -8,27 +9,62 @@ namespace gsr {
static ActiveHyprlandWindow active_hyprland_window; static ActiveHyprlandWindow active_hyprland_window;
static bool hyprland_listener_thread_started = false; static bool hyprland_listener_thread_started = false;
static void hyprland_listener_thread() { static bool get_hyprland_socket_path(char *path, int path_len) {
const bool inside_flatpak = access("/app/manifest.json", F_OK) == 0; const char* xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
const char* instance_sig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!xdg_runtime_dir || !instance_sig) {
fprintf(stderr, "Error: HyprlandWorkaround: environment variables not set\n");
return false;
}
if (snprintf(path, path_len, "%s/hypr/%s/.socket2.sock", xdg_runtime_dir, instance_sig) >= path_len) {
fprintf(stderr, "Error: HyprlandWorkaround: path to hyprland socket (%s/hypr/%s/.socket2.sock) is more than %d characters long\n", xdg_runtime_dir, instance_sig, path_len);
return false;
}
return true;
}
static void hyprland_listener_thread() {
char hyprland_socket_path[256];
char buffer[4096];
const std::string prefix = "Window title changed: ";
std::string line;
FILE *stdout_file = nullptr;
// Get path inside the flatpak before flatpak-spawn is called because of a bug in flatpak:
// https://github.com/flatpak/flatpak/issues/6486
// where environment variables are missing in flatpak-spawn --host
if(!get_hyprland_socket_path(hyprland_socket_path, sizeof(hyprland_socket_path))) {
fprintf(stderr, "Error: HyprlandWorkaround: failed to get hyprland socket path\n");
return;
}
const bool inside_flatpak = access("/app/manifest.json", F_OK) == 0;
const char *hyprland_helper_bin = const char *hyprland_helper_bin =
inside_flatpak ? inside_flatpak ?
"flatpak-spawn --host -- /var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/gsr-hyprland-helper" "flatpak-spawn --host -- /var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/gsr-hyprland-helper"
: "gsr-hyprland-helper"; : "gsr-hyprland-helper";
FILE* pipe = popen(hyprland_helper_bin, "r"); const char *args[] = { hyprland_helper_bin, hyprland_socket_path, nullptr };
if (!pipe) { int read_fd = -1;
std::cerr << "Failed to start gsr-hyprland-helper process\n"; const pid_t process_id = exec_program(args, &read_fd, false);
if(process_id == -1) {
fprintf(stderr, "Error: HyprlandWorkaround: failed to execute gsr-hyprland-helper\n");
return; return;
} }
std::cerr << "Started Hyprland helper thread\n"; stdout_file = fdopen(read_fd, "r");
if (!stdout_file) {
perror("Error: HyprlandWorkaround: fdopen");
goto done;
return;
}
read_fd = -1;
char buffer[4096]; fprintf(stderr, "Info: HyprlandWorkaround: started Hyprland helper thread\n");
const std::string prefix = "Window title changed: ";
std::string line; while (fgets(buffer, sizeof(buffer), stdout_file) != nullptr) {
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
line = buffer; line = buffer;
if (!line.empty() && line.back() == '\n') { if (!line.empty() && line.back() == '\n') {
@@ -41,7 +77,21 @@ namespace gsr {
} }
} }
pclose(pipe); done:
if(stdout_file)
fclose(stdout_file);
if(read_fd > 0)
close(read_fd);
if(process_id > 0) {
kill(process_id, SIGKILL);
int status;
if(waitpid(process_id, &status, 0) == -1) {
perror("waitpid failed");
/* Ignore... */
}
}
} }
std::string get_current_hyprland_window_title() { std::string get_current_hyprland_window_title() {

View File

@@ -1,27 +1,10 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
static bool get_hyprland_socket_path(char *path, int path_len) {
const char* xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
const char* instance_sig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!xdg_runtime_dir || !instance_sig) {
fprintf(stderr, "Error: gsr-hypland-helper: environment variables not set\n");
return false;
}
if (snprintf(path, path_len, "%s/hypr/%s/.socket2.sock", xdg_runtime_dir, instance_sig) >= path_len) {
fprintf(stderr, "Error: gsr-hypland-helper: path to hyprland socket (%s/hypr/%s/.socket2.sock) is more than %d characters long\n", xdg_runtime_dir, instance_sig, path_len);
return false;
}
return true;
}
static void print_window_title(const char *window_title) { static void print_window_title(const char *window_title) {
if (window_title[0] == 0) { if (window_title[0] == 0) {
printf("Window title changed: %s\n", "Desktop"); printf("Window title changed: %s\n", "Desktop");
@@ -32,7 +15,7 @@ static void print_window_title(const char *window_title) {
fflush(stdout); fflush(stdout);
} }
static int handle_ipc(void) { static int handle_ipc(const char *hyprland_socket_path) {
const int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); const int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_fd == -1) { if (sock_fd == -1) {
perror("Error: gsr-hyprland-helper: socket"); perror("Error: gsr-hyprland-helper: socket");
@@ -43,8 +26,9 @@ static int handle_ipc(void) {
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
if (!get_hyprland_socket_path(addr.sun_path, sizeof(addr.sun_path))) { if (snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", hyprland_socket_path) >= (int)sizeof(addr.sun_path)) {
return 1; fprintf(stderr, "Error: gsr-hypland-helper: path to hyprland socket (%s) is more than %d characters long\n", hyprland_socket_path, (int)sizeof(addr.sun_path));
return false;
} }
if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
@@ -90,6 +74,10 @@ static int handle_ipc(void) {
} }
int main(void) { int main(int argc, char **argv) {
return handle_ipc(); if(argc != 2) {
fprintf(stderr, "usage: gsr-hyprland-helper <hyprland-socket-path>\n");
return 1;
}
return handle_ipc(argv[1]);
} }