mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-03-31 09:17:04 +09:00
Added Hyprland workaround to get current window title
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ compile_commands.json
|
|||||||
**/xdg-output-unstable-v1-protocol.c
|
**/xdg-output-unstable-v1-protocol.c
|
||||||
|
|
||||||
depends/.wraplock
|
depends/.wraplock
|
||||||
|
|
||||||
|
.cache
|
||||||
|
build/
|
||||||
12
include/HyprlandWorkaround.hpp
Normal file
12
include/HyprlandWorkaround.hpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace gsr {
|
||||||
|
struct ActiveHyprlandWindow {
|
||||||
|
std::string window_id = "";
|
||||||
|
std::string title = "Game";
|
||||||
|
};
|
||||||
|
|
||||||
|
void start_hyprland_listener_thread();
|
||||||
|
std::string get_current_hyprland_window_title();
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ src = [
|
|||||||
'src/CursorTracker/CursorTrackerX11.cpp',
|
'src/CursorTracker/CursorTrackerX11.cpp',
|
||||||
'src/CursorTracker/CursorTrackerWayland.cpp',
|
'src/CursorTracker/CursorTrackerWayland.cpp',
|
||||||
'src/Utils.cpp',
|
'src/Utils.cpp',
|
||||||
|
'src/HyprlandWorkaround.cpp',
|
||||||
'src/WindowUtils.cpp',
|
'src/WindowUtils.cpp',
|
||||||
'src/RegionSelector.cpp',
|
'src/RegionSelector.cpp',
|
||||||
'src/WindowSelector.cpp',
|
'src/WindowSelector.cpp',
|
||||||
|
|||||||
158
src/HyprlandWorkaround.cpp
Normal file
158
src/HyprlandWorkaround.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include "../include/HyprlandWorkaround.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <thread>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <array>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
namespace gsr {
|
||||||
|
static ActiveHyprlandWindow *active_hyprland_window = nullptr;
|
||||||
|
static bool hyprland_listener_thread_started = false;
|
||||||
|
|
||||||
|
static std::string get_hyprland_socket_path() {
|
||||||
|
const char* xdg_runtime_dir = std::getenv("XDG_RUNTIME_DIR");
|
||||||
|
const char* instance_sig = std::getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
|
|
||||||
|
if (!xdg_runtime_dir || !instance_sig) {
|
||||||
|
std::cerr << "Error: Env vars XDG_RUNTIME_DIR or HYPRLAND_INSTANCE_SIGNATURE not set." << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string(xdg_runtime_dir) + "/hypr/" + instance_sig + "/.socket2.sock";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hyprland_listener_thread() {
|
||||||
|
int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sock_fd == -1) {
|
||||||
|
perror("socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
std::memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
std::string socket_path = get_hyprland_socket_path();
|
||||||
|
std::strncpy(addr.sun_path, socket_path.c_str(), sizeof(addr.sun_path) - 1);
|
||||||
|
|
||||||
|
if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||||
|
perror("connect");
|
||||||
|
close(sock_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Connected to Hyprland event socket: " << socket_path << std::endl;
|
||||||
|
|
||||||
|
std::array<char, 4096> buffer; // fixed buffer, scary!
|
||||||
|
std::string incomplete_line;
|
||||||
|
|
||||||
|
while (hyprland_listener_thread_started) {
|
||||||
|
ssize_t bytes_read = read(sock_fd, buffer.data(), buffer.size());
|
||||||
|
|
||||||
|
if (bytes_read == 0) {
|
||||||
|
std::cerr << "Connection closed by Hyprland" << std::endl;
|
||||||
|
hyprland_listener_thread_started = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read < 0) {
|
||||||
|
perror("read");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string chunk(buffer.data(), bytes_read);
|
||||||
|
std::string data = incomplete_line + chunk;
|
||||||
|
|
||||||
|
size_t start_pos = 0;
|
||||||
|
size_t newline_pos;
|
||||||
|
|
||||||
|
while ((newline_pos = data.find('\n', start_pos)) != std::string::npos) {
|
||||||
|
std::string line = data.substr(start_pos, newline_pos - start_pos);
|
||||||
|
|
||||||
|
size_t delimiter = line.find(">>");
|
||||||
|
|
||||||
|
if (delimiter != std::string::npos) {
|
||||||
|
std::string event_name = line.substr(0, delimiter);
|
||||||
|
std::string event_data = line.substr(delimiter+2);
|
||||||
|
|
||||||
|
if (event_name == "activewindowv2") {
|
||||||
|
active_hyprland_window->window_id = event_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event_name == "activewindow") {
|
||||||
|
size_t title_delimiter = event_data.find(",");
|
||||||
|
if (title_delimiter != std::string::npos) {
|
||||||
|
std::string window_title = event_data.substr(title_delimiter+1);
|
||||||
|
if (window_title == "gsr ui" || window_title == "gsr notify") {
|
||||||
|
// ignoring ourselves
|
||||||
|
start_pos = newline_pos + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
active_hyprland_window->title = window_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event_name == "windowtitlev2") {
|
||||||
|
size_t data_delimiter = event_data.find(",");
|
||||||
|
if (data_delimiter != std::string::npos) {
|
||||||
|
std::string win_id = event_data.substr(0, data_delimiter);
|
||||||
|
std::string new_window_title = event_data.substr(data_delimiter+1);
|
||||||
|
if (new_window_title == "gsr ui" || new_window_title == "gsr notify") {
|
||||||
|
// ignoring ourselves
|
||||||
|
start_pos = newline_pos + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (active_hyprland_window->window_id != win_id) {
|
||||||
|
// not our case
|
||||||
|
start_pos = newline_pos + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
active_hyprland_window->title = new_window_title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pos = newline_pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_pos < data.length()) {
|
||||||
|
incomplete_line = data.substr(start_pos);
|
||||||
|
} else {
|
||||||
|
incomplete_line.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_current_hyprland_window_title() {
|
||||||
|
if (active_hyprland_window == nullptr) {
|
||||||
|
return "Game";
|
||||||
|
}
|
||||||
|
|
||||||
|
return active_hyprland_window->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_hyprland_listener_thread() {
|
||||||
|
if (hyprland_listener_thread_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active_hyprland_window == nullptr) {
|
||||||
|
active_hyprland_window = new ActiveHyprlandWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
hyprland_listener_thread_started = true;
|
||||||
|
|
||||||
|
std::thread([&] {
|
||||||
|
hyprland_listener_thread();
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "../include/gui/ScreenshotSettingsPage.hpp"
|
#include "../include/gui/ScreenshotSettingsPage.hpp"
|
||||||
#include "../include/gui/GlobalSettingsPage.hpp"
|
#include "../include/gui/GlobalSettingsPage.hpp"
|
||||||
#include "../include/gui/Utils.hpp"
|
#include "../include/gui/Utils.hpp"
|
||||||
|
#include "../include/HyprlandWorkaround.hpp"
|
||||||
#include "../include/gui/PageStack.hpp"
|
#include "../include/gui/PageStack.hpp"
|
||||||
#include "../include/WindowUtils.hpp"
|
#include "../include/WindowUtils.hpp"
|
||||||
#include "../include/GlobalHotkeys/GlobalHotkeys.hpp"
|
#include "../include/GlobalHotkeys/GlobalHotkeys.hpp"
|
||||||
@@ -548,6 +549,10 @@ namespace gsr {
|
|||||||
save_config(config);
|
save_config(config);
|
||||||
show_notification("Wayland doesn't support GPU Screen Recorder UI properly,\nthings may not work as expected. Use X11 if you experience issues.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
|
show_notification("Wayland doesn't support GPU Screen Recorder UI properly,\nthings may not work as expected. Use X11 if you experience issues.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_window_manager_name(x11_dpy).find("Hyprland") != std::string::npos) {
|
||||||
|
start_hyprland_listener_thread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_led_indicator_after_settings_change();
|
update_led_indicator_after_settings_change();
|
||||||
@@ -1092,7 +1097,6 @@ namespace gsr {
|
|||||||
window.reset();
|
window.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//window->set_low_latency(true);
|
//window->set_low_latency(true);
|
||||||
|
|
||||||
unsigned char data = 2; // Prefer being composed to allow transparency
|
unsigned char data = 2; // Prefer being composed to allow transparency
|
||||||
@@ -1967,10 +1971,19 @@ namespace gsr {
|
|||||||
|
|
||||||
const Window gsr_ui_window = window ? (Window)window->get_system_handle() : None;
|
const Window gsr_ui_window = window ? (Window)window->get_system_handle() : None;
|
||||||
std::string focused_window_name = get_window_name_at_cursor_position(display, gsr_ui_window);
|
std::string focused_window_name = get_window_name_at_cursor_position(display, gsr_ui_window);
|
||||||
|
|
||||||
|
const std::string wm_name = get_window_manager_name(display);
|
||||||
|
const bool is_hyprland = wm_name.find("Hyprland") != std::string::npos;
|
||||||
|
|
||||||
|
if (is_hyprland) {
|
||||||
|
focused_window_name = get_current_hyprland_window_title();
|
||||||
|
}
|
||||||
|
else {
|
||||||
if(focused_window_name.empty())
|
if(focused_window_name.empty())
|
||||||
focused_window_name = get_focused_window_name(display, WindowCaptureType::FOCUSED, false);
|
focused_window_name = get_focused_window_name(display, WindowCaptureType::FOCUSED, false);
|
||||||
if(focused_window_name.empty())
|
if(focused_window_name.empty())
|
||||||
focused_window_name = "Game";
|
focused_window_name = "Game";
|
||||||
|
}
|
||||||
|
|
||||||
string_replace_characters(focused_window_name.data(), "/\\", ' ');
|
string_replace_characters(focused_window_name.data(), "/\\", ' ');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user