add hyprland socket support
This commit is contained in:
134
src/services/hyprland.cpp
Normal file
134
src/services/hyprland.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "services/hyprland.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
HyprlandService::HyprlandService() {}
|
||||
|
||||
HyprlandService::~HyprlandService()
|
||||
{
|
||||
if (m_fd != -1)
|
||||
{
|
||||
close(m_fd);
|
||||
}
|
||||
}
|
||||
|
||||
void HyprlandService::on_hyprland_event(std::string event, std::string data)
|
||||
{
|
||||
if (event == "workspace")
|
||||
{
|
||||
std::cout << "Switched to workspace: " << data << std::endl;
|
||||
// Update your UI here...
|
||||
}
|
||||
else if (event == "activewindow")
|
||||
{
|
||||
std::cout << "Active window changed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void HyprlandService::start()
|
||||
{
|
||||
std::string socket_path = get_socket_path();
|
||||
if (socket_path.empty())
|
||||
return;
|
||||
|
||||
// 1. Create Socket
|
||||
m_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (m_fd == -1)
|
||||
{
|
||||
std::cerr << "[Hyprland] Failed to create socket" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Connect
|
||||
struct sockaddr_un addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socket_path.c_str(), sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (connect(m_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
std::cerr << "[Hyprland] Failed to connect to " << socket_path << std::endl;
|
||||
close(m_fd);
|
||||
m_fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "[Hyprland] Connected to event socket." << std::endl;
|
||||
|
||||
// 3. Register with GLib Main Loop
|
||||
// This tells GTK to call 'on_socket_read' whenever there is data to read
|
||||
Glib::signal_io().connect(
|
||||
sigc::mem_fun(*this, &HyprlandService::on_socket_read),
|
||||
m_fd,
|
||||
Glib::IOCondition::IO_IN | Glib::IOCondition::IO_HUP | Glib::IOCondition::IO_ERR);
|
||||
}
|
||||
|
||||
bool HyprlandService::on_socket_read(Glib::IOCondition condition)
|
||||
{
|
||||
// Handle disconnection or errors
|
||||
auto error_mask = Glib::IOCondition::IO_HUP | Glib::IOCondition::IO_ERR;
|
||||
|
||||
// 2. Perform the bitwise AND, then cast to int to check if non-zero
|
||||
if (static_cast<int>(condition & error_mask) != 0)
|
||||
{
|
||||
std::cerr << "[Hyprland] Socket disconnected." << std::endl;
|
||||
close(m_fd);
|
||||
m_fd = -1;
|
||||
return false;
|
||||
}
|
||||
// Read data
|
||||
char buffer[4096];
|
||||
ssize_t bytes_read = read(m_fd, buffer, sizeof(buffer) - 1);
|
||||
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
buffer[bytes_read] = '\0';
|
||||
m_buffer.append(buffer);
|
||||
|
||||
// Process line by line
|
||||
size_t pos = 0;
|
||||
while ((pos = m_buffer.find('\n')) != std::string::npos)
|
||||
{
|
||||
std::string line = m_buffer.substr(0, pos);
|
||||
parse_message(line);
|
||||
m_buffer.erase(0, pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Continue listening
|
||||
}
|
||||
|
||||
void HyprlandService::parse_message(const std::string &line)
|
||||
{
|
||||
// Hyprland events look like: "event>>data"
|
||||
// Example: "workspace>>1" or "activewindow>>550a12,firefox"
|
||||
size_t split = line.find(">>");
|
||||
if (split != std::string::npos)
|
||||
{
|
||||
std::string event_name = line.substr(0, split);
|
||||
std::string event_data = line.substr(split + 2);
|
||||
|
||||
// Emit the signal
|
||||
on_event.emit(event_name, event_data);
|
||||
}
|
||||
}
|
||||
|
||||
std::string HyprlandService::get_socket_path()
|
||||
{
|
||||
const char *sig = std::getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
const char *runtime = std::getenv("XDG_RUNTIME_DIR");
|
||||
|
||||
if (!sig || !runtime)
|
||||
{
|
||||
std::cerr << "[Hyprland] Environment variables missing!" << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
// Path format: $XDG_RUNTIME_DIR/hypr/$SIGNATURE/.socket2.sock
|
||||
return std::string(runtime) + "/hypr/" + sig + "/.socket2.sock";
|
||||
}
|
||||
Reference in New Issue
Block a user