This commit is contained in:
Vaxry 2024-07-19 16:27:43 +02:00
parent c788a59dac
commit 518213b4c0
9 changed files with 195 additions and 168 deletions

View file

@ -4,6 +4,7 @@
#include <fstream> #include <fstream>
#include <signal.h> #include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/poll.h>
#include "render/Egl.hpp" #include "render/Egl.hpp"
#include "protocols/wayland.hpp" #include "protocols/wayland.hpp"
@ -21,15 +22,11 @@ static void handleGlobal(CCWlRegistry* registry, uint32_t name, const char* inte
} else if (strcmp(interface, wl_shm_interface.name) == 0) { } else if (strcmp(interface, wl_shm_interface.name) == 0) {
g_pHyprpaper->m_pSHM = makeShared<CCWlShm>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_shm_interface, 1)); g_pHyprpaper->m_pSHM = makeShared<CCWlShm>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_shm_interface, 1));
} else if (strcmp(interface, wl_output_interface.name) == 0) { } else if (strcmp(interface, wl_output_interface.name) == 0) {
g_pHyprpaper->m_mtTickMutex.lock();
const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique<SMonitor>()).get(); const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique<SMonitor>()).get();
PMONITOR->wayland_name = name; PMONITOR->wayland_name = name;
PMONITOR->name = ""; PMONITOR->name = "";
PMONITOR->output = makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_output_interface, 4)); PMONITOR->output = makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_output_interface, 4));
PMONITOR->registerListeners(); PMONITOR->registerListeners();
g_pHyprpaper->m_mtTickMutex.unlock();
} else if (strcmp(interface, wl_seat_interface.name) == 0) { } else if (strcmp(interface, wl_seat_interface.name) == 0) {
g_pHyprpaper->createSeat(makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_seat_interface, 1))); g_pHyprpaper->createSeat(makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_seat_interface, 1)));
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
@ -124,18 +121,66 @@ void CHyprpaper::init() {
if (std::any_cast<Hyprlang::INT>(g_pConfigManager->config->getConfigValue("ipc"))) if (std::any_cast<Hyprlang::INT>(g_pConfigManager->config->getConfigValue("ipc")))
g_pIPCSocket->initialize(); g_pIPCSocket->initialize();
do { pollfd pollFDs[] = {
std::lock_guard<std::mutex> lg(m_mtTickMutex); {
.fd = wl_display_get_fd(m_sDisplay),
.events = POLLIN,
},
{
.fd = g_pIPCSocket->fd,
.events = POLLIN,
},
};
tick(true); tick(true);
} while (wl_display_dispatch(m_sDisplay) != -1);
while (1) {
int ret = poll(pollFDs, 2, 5000 /* 5 seconds, reasonable. Just in case we need to terminate and the signal fails */);
if (ret < 0) {
if (errno == EINTR)
continue;
Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
exit(1);
}
for (size_t i = 0; i < 2; ++i) {
if (pollFDs[i].revents & POLLHUP) {
Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i);
exit(1);
}
}
if (ret != 0) {
if (pollFDs[0].revents & POLLIN) { // wayland
wl_display_flush(m_sDisplay);
if (wl_display_prepare_read(m_sDisplay) == 0) {
wl_display_read_events(m_sDisplay);
wl_display_dispatch_pending(m_sDisplay);
} else
wl_display_dispatch(m_sDisplay);
}
if (pollFDs[1].revents & POLLIN) { // socket
if (g_pIPCSocket->parseRequest())
tick(true);
}
// finalize wayland dispatching. Dispatch pending on the queue
int ret2 = 0;
do {
ret2 = wl_display_dispatch_pending(m_sDisplay);
wl_display_flush(m_sDisplay);
} while (ret2 > 0);
}
}
unlockSingleInstance(); unlockSingleInstance();
} }
void CHyprpaper::tick(bool force) { void CHyprpaper::tick(bool force) {
bool reload = g_pIPCSocket && g_pIPCSocket->mainThreadParseRequest(); if (!force)
if (!reload && !force)
return; return;
preloadAllWallpapersFromConfig(); preloadAllWallpapersFromConfig();
@ -388,7 +433,7 @@ void CHyprpaper::ensureMonitorHasActiveWallpaper(SMonitor* pMonitor) {
} }
void CHyprpaper::createLSForMonitor(SMonitor* pMonitor) { void CHyprpaper::createLSForMonitor(SMonitor* pMonitor) {
pMonitor->pCurrentLayerSurface = pMonitor->layerSurfaces.emplace_back(std::make_unique<CLayerSurface>(pMonitor)).get(); pMonitor->pCurrentLayerSurface = pMonitor->layerSurfaces.emplace_back(makeShared<CLayerSurface>(pMonitor));
} }
bool CHyprpaper::lockSingleInstance() { bool CHyprpaper::lockSingleInstance() {

View file

@ -74,8 +74,6 @@ class CHyprpaper {
bool lockSingleInstance(); // fails on multi-instance bool lockSingleInstance(); // fails on multi-instance
void unlockSingleInstance(); void unlockSingleInstance();
std::mutex m_mtTickMutex;
SMonitor* m_pLastMonitor = nullptr; SMonitor* m_pLastMonitor = nullptr;
private: private:

View file

@ -8,7 +8,6 @@ void SMonitor::registerListeners() {
output->setDone([this](CCWlOutput* r) { output->setDone([this](CCWlOutput* r) {
readyForLS = true; readyForLS = true;
std::lock_guard<std::mutex> lg(g_pHyprpaper->m_mtTickMutex);
if (g_pConfigManager) // don't tick if this is the first roundtrip if (g_pConfigManager) // don't tick if this is the first roundtrip
g_pHyprpaper->tick(true); g_pHyprpaper->tick(true);
}); });

View file

@ -24,8 +24,8 @@ struct SMonitor {
bool wantsACK = false; bool wantsACK = false;
bool initialized = false; bool initialized = false;
std::vector<std::unique_ptr<CLayerSurface>> layerSurfaces; std::vector<SP<CLayerSurface>> layerSurfaces;
CLayerSurface* pCurrentLayerSurface = nullptr; SP<CLayerSurface> pCurrentLayerSurface = nullptr;
void registerListeners(); void registerListeners();
}; };

View file

@ -15,10 +15,9 @@
#include <thread> #include <thread>
void CIPCSocket::initialize() { void CIPCSocket::initialize() {
std::thread([&]() { fd = socket(AF_UNIX, SOCK_STREAM, 0);
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
if (SOCKET < 0) { if (fd < 0) {
Debug::log(ERR, "Couldn't start the hyprpaper Socket. (1) IPC will not work."); Debug::log(ERR, "Couldn't start the hyprpaper Socket. (1) IPC will not work.");
return; return;
} }
@ -40,130 +39,110 @@ void CIPCSocket::initialize() {
strcpy(SERVERADDRESS.sun_path, socketPath.c_str()); strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)); if (bind(fd, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
Debug::log(ERR, "Couldn't bind the hyprpaper Socket. IPC will not work.");
fd = -1;
return;
}
// 10 max queued. // 10 max queued.
listen(SOCKET, 10); listen(fd, 10);
Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), fd);
}
CIPCSocket::~CIPCSocket() {
if (fd >= 0)
close(fd);
}
bool CIPCSocket::parseRequest() {
sockaddr_in clientAddress = {}; sockaddr_in clientAddress = {};
socklen_t clientSize = sizeof(clientAddress); socklen_t clientSize = sizeof(clientAddress);
char readBuffer[1024] = {0}; char readBuffer[1024] = {0};
Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), SOCKET); const auto ACCEPTEDCONNECTION = accept(fd, (sockaddr*)&clientAddress, &clientSize);
while (1) {
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
if (ACCEPTEDCONNECTION < 0) { if (ACCEPTEDCONNECTION < 0) {
Debug::log(ERR, "Couldn't listen on the hyprpaper Socket. (3) IPC will not work."); Debug::log(ERR, "Couldn't listen on the hyprpaper Socket. (3)");
break; return false;
} else { } else {
do {
Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION); Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION);
std::lock_guard<std::mutex> lg(g_pHyprpaper->m_mtTickMutex); std::string body = "";
do {
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0'; body += std::string{readBuffer, messageSize};
if (messageSize == 0) if (messageSize < 1024)
break; break;
std::string request(readBuffer);
m_szRequest = request;
m_bRequestReady = true;
g_pHyprpaper->tick(true);
while (!m_bReplyReady) { // wait for Hyprpaper to finish processing the request
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
write(ACCEPTEDCONNECTION, m_szReply.c_str(), m_szReply.length());
m_bReplyReady = false;
m_szReply = "";
} while (1); } while (1);
auto reply = processRequest(body);
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
Debug::log(LOG, "Closing Accepted Connection"); Debug::log(LOG, "Closing Accepted Connection");
close(ACCEPTEDCONNECTION); close(ACCEPTEDCONNECTION);
} }
}
close(SOCKET);
}).detach();
}
bool CIPCSocket::mainThreadParseRequest() {
if (!m_bRequestReady)
return false;
std::string copy = m_szRequest;
if (copy == "")
return false;
// now we can work on the copy
Debug::log(LOG, "Received a request: %s", copy.c_str());
// set default reply
m_szReply = "ok";
m_bReplyReady = true;
m_bRequestReady = false;
// config commands
if (copy.find("wallpaper") == 0 || copy.find("preload") == 0 || copy.find("unload") == 0 || copy.find("reload") == 0) {
const auto RESULT = g_pConfigManager->config->parseDynamic(copy.substr(0, copy.find_first_of(' ')).c_str(), copy.substr(copy.find_first_of(' ') + 1).c_str());
if (RESULT.error) {
m_szReply = RESULT.getError();
return false;
}
return true; return true;
} }
if (copy.find("listloaded") == 0) { std::string CIPCSocket::processRequest(const std::string& body) {
std::string reply = "ok";
Debug::log(LOG, "Received a request: %s", body.c_str());
// config commands
if (body.find("wallpaper") == 0 || body.find("preload") == 0 || body.find("unload") == 0 || body.find("reload") == 0) {
const auto RESULT = g_pConfigManager->config->parseDynamic(body.substr(0, body.find_first_of(' ')).c_str(), body.substr(body.find_first_of(' ') + 1).c_str());
if (RESULT.error)
reply = RESULT.getError();
return reply;
}
if (body.find("listloaded") == 0) {
const auto numWallpapersLoaded = g_pHyprpaper->m_mWallpaperTargets.size(); const auto numWallpapersLoaded = g_pHyprpaper->m_mWallpaperTargets.size();
Debug::log(LOG, "numWallpapersLoaded: %d", numWallpapersLoaded); Debug::log(LOG, "numWallpapersLoaded: %d", numWallpapersLoaded);
if (numWallpapersLoaded == 0) { if (numWallpapersLoaded == 0)
m_szReply = "no wallpapers loaded"; return "no wallpapers loaded";
return false;
}
m_szReply = ""; reply = "";
long unsigned int i = 0; long unsigned int i = 0;
for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) { for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) {
m_szReply += name; reply += name;
i++; i++;
if (i < numWallpapersLoaded) if (i < numWallpapersLoaded)
m_szReply += '\n'; // dont add newline on last entry reply += '\n'; // dont add newline on last entry
} }
return true; return reply;
} }
if (copy.find("listactive") == 0) { if (body.find("listactive") == 0) {
const auto numWallpapersActive = g_pHyprpaper->m_mMonitorActiveWallpapers.size(); const auto numWallpapersActive = g_pHyprpaper->m_mMonitorActiveWallpapers.size();
Debug::log(LOG, "numWallpapersActive: %d", numWallpapersActive); Debug::log(LOG, "numWallpapersActive: %d", numWallpapersActive);
if (numWallpapersActive == 0) { if (numWallpapersActive == 0)
m_szReply = "no wallpapers active"; return "no wallpapers active";
return false;
}
m_szReply = ""; reply = "";
long unsigned int i = 0; long unsigned int i = 0;
for (auto& [mon, path1] : g_pHyprpaper->m_mMonitorActiveWallpapers) { for (auto& [mon, path1] : g_pHyprpaper->m_mMonitorActiveWallpapers) {
m_szReply += mon + " = " + path1; reply += mon + " = " + path1;
i++; i++;
if (i < numWallpapersActive) if (i < numWallpapersActive)
m_szReply += '\n'; // dont add newline on last entry reply += '\n'; // dont add newline on last entry
} }
return true; return reply;
} }
m_szReply = "invalid command"; return "invalid command";
return false;
} }

View file

@ -5,17 +5,16 @@
class CIPCSocket { class CIPCSocket {
public: public:
~CIPCSocket();
void initialize(); void initialize();
bool mainThreadParseRequest(); bool parseRequest();
int fd = -1;
private: private:
std::mutex m_mtRequestMutex; std::string processRequest(const std::string& body);
std::string m_szRequest = "";
std::string m_szReply = "";
bool m_bRequestReady = false;
bool m_bReplyReady = false;
}; };
inline std::unique_ptr<CIPCSocket> g_pIPCSocket; inline std::unique_ptr<CIPCSocket> g_pIPCSocket;

View file

@ -47,16 +47,18 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) {
m_pMonitor->initialized = true; m_pMonitor->initialized = true;
Debug::log(LOG, "configure for %s", m_pMonitor->name.c_str()); Debug::log(LOG, "configure for %s", m_pMonitor->name.c_str());
g_pHyprpaper->tick(true);
}); });
pLayerSurface->setClosed([this](CCZwlrLayerSurfaceV1* r) { pLayerSurface->setClosed([this](CCZwlrLayerSurfaceV1* r) {
for (auto& m : g_pHyprpaper->m_vMonitors) { for (auto& m : g_pHyprpaper->m_vMonitors) {
std::erase_if(m->layerSurfaces, [&](const auto& other) { return other.get() == this; }); std::erase_if(m->layerSurfaces, [&](const auto& other) { return other.get() == this; });
if (m->pCurrentLayerSurface == this) { if (m->pCurrentLayerSurface.get() == this) {
if (m->layerSurfaces.empty()) { if (m->layerSurfaces.empty()) {
m->pCurrentLayerSurface = nullptr; m->pCurrentLayerSurface = nullptr;
} else { } else {
m->pCurrentLayerSurface = m->layerSurfaces.begin()->get(); m->pCurrentLayerSurface = *m->layerSurfaces.begin();
g_pHyprpaper->recheckMonitor(m.get()); g_pHyprpaper->recheckMonitor(m.get());
} }
} }
@ -75,7 +77,6 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) {
if (fScale != SCALE) { if (fScale != SCALE) {
fScale = SCALE; fScale = SCALE;
std::lock_guard<std::mutex> lg(g_pHyprpaper->m_mtTickMutex);
m_pMonitor->wantsReload = true; m_pMonitor->wantsReload = true;
g_pHyprpaper->tick(true); g_pHyprpaper->tick(true);
} }
@ -92,6 +93,8 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) {
CLayerSurface::~CLayerSurface() { CLayerSurface::~CLayerSurface() {
// hyprwayland-scanner will send the destructors automatically. Neat. // hyprwayland-scanner will send the destructors automatically. Neat.
pLayerSurface->sendDestroy();
pLayerSurface.reset(); pLayerSurface.reset();
pFractionalScaleInfo.reset(); pFractionalScaleInfo.reset();
pViewport.reset(); pViewport.reset();

View file

@ -188,8 +188,8 @@ void CRenderer::renderWallpaperForMonitor(SMonitor* pMonitor) {
pMonitor->pCurrentLayerSurface->pSurface->sendSetOpaqueRegion(opaqueRegion.get()); pMonitor->pCurrentLayerSurface->pSurface->sendSetOpaqueRegion(opaqueRegion.get());
if (pMonitor->pCurrentLayerSurface->pFractionalScaleInfo) { if (pMonitor->pCurrentLayerSurface->pFractionalScaleInfo) {
Debug::log(LOG, "Submitting viewport dest size %ix%i for %x", static_cast<int>(std::round(pMonitor->size.x)), static_cast<int>(std::round(pMonitor->size.y)), Debug::log(LOG, "Submitting viewport dest size %ix%i for %lx", static_cast<int>(std::round(pMonitor->size.x)), static_cast<int>(std::round(pMonitor->size.y)),
pMonitor->pCurrentLayerSurface); pMonitor->pCurrentLayerSurface.get());
pMonitor->pCurrentLayerSurface->pViewport->sendSetDestination(static_cast<int>(std::round(pMonitor->size.x)), static_cast<int>(std::round(pMonitor->size.y))); pMonitor->pCurrentLayerSurface->pViewport->sendSetDestination(static_cast<int>(std::round(pMonitor->size.x)), static_cast<int>(std::round(pMonitor->size.y)));
} }
pMonitor->pCurrentLayerSurface->pSurface->sendCommit(); pMonitor->pCurrentLayerSurface->pSurface->sendCommit();
@ -198,7 +198,7 @@ void CRenderer::renderWallpaperForMonitor(SMonitor* pMonitor) {
// check if we dont need to remove a wallpaper // check if we dont need to remove a wallpaper
if (pMonitor->layerSurfaces.size() > 1) { if (pMonitor->layerSurfaces.size() > 1) {
for (auto it = pMonitor->layerSurfaces.begin(); it != pMonitor->layerSurfaces.end(); it++) { for (auto it = pMonitor->layerSurfaces.begin(); it != pMonitor->layerSurfaces.end(); it++) {
if (pMonitor->pCurrentLayerSurface != it->get()) { if (pMonitor->pCurrentLayerSurface != *it) {
pMonitor->layerSurfaces.erase(it); pMonitor->layerSurfaces.erase(it);
break; break;
} }
@ -309,7 +309,7 @@ void CRenderer::renderGpu(SMonitor* pMonitor, SP<CBuffer> buf) {
origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - DIMENSIONS.x) / 2.0 / scale; origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - DIMENSIONS.x) / 2.0 / scale;
} }
renderTexture(PWALLPAPERTARGET->gpu.textureID, CBox{origin, PWALLPAPERTARGET->m_vSize * scale}, buf->pixelSize); renderTexture(PWALLPAPERTARGET->gpu.textureID, CBox{origin * scale, PWALLPAPERTARGET->m_vSize * scale}, buf->pixelSize);
// then, any decoration we got from cairo // then, any decoration we got from cairo
renderTexture(fromTex.texid, {{}, buf->pixelSize}, buf->pixelSize); renderTexture(fromTex.texid, {{}, buf->pixelSize}, buf->pixelSize);
@ -328,7 +328,7 @@ void CRenderer::renderGpu(SMonitor* pMonitor, SP<CBuffer> buf) {
} }
void CRenderer::renderTexture(GLuint texid, const CBox& box, const Vector2D& viewport) { void CRenderer::renderTexture(GLuint texid, const CBox& box, const Vector2D& viewport) {
CBox renderBox = {{}, viewport}; CBox renderBox = box;
float mtx[9]; float mtx[9];
float base[9]; float base[9];

View file

@ -6,6 +6,8 @@
#include "Renderer.hpp" #include "Renderer.hpp"
CWallpaperTarget::~CWallpaperTarget() { CWallpaperTarget::~CWallpaperTarget() {
if (g_pEGL)
g_pEGL->makeCurrent(EGL_NO_SURFACE);
if (cpu.cairoSurface) if (cpu.cairoSurface)
cairo_surface_destroy(cpu.cairoSurface); cairo_surface_destroy(cpu.cairoSurface);
if (gpu.textureID) if (gpu.textureID)
@ -69,6 +71,8 @@ void CWallpaperTarget::create(const std::string& path) {
Debug::log(LOG, "GPU mode, uploading the preloaded image into VRAM and deleting from RAM"); Debug::log(LOG, "GPU mode, uploading the preloaded image into VRAM and deleting from RAM");
g_pEGL->makeCurrent(EGL_NO_SURFACE);
auto tex = g_pRenderer->glTex(cairo_image_surface_get_data(CAIROSURFACE), m_vSize); auto tex = g_pRenderer->glTex(cairo_image_surface_get_data(CAIROSURFACE), m_vSize);
gpu.textureID = tex.texid; gpu.textureID = tex.texid;