Skip to content

Commit 518213b

Browse files
committed
fixez
1 parent c788a59 commit 518213b

9 files changed

Lines changed: 170 additions & 143 deletions

File tree

src/Hyprpaper.cpp

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <fstream>
55
#include <signal.h>
66
#include <sys/types.h>
7+
#include <sys/poll.h>
78
#include "render/Egl.hpp"
89

910
#include "protocols/wayland.hpp"
@@ -21,15 +22,11 @@ static void handleGlobal(CCWlRegistry* registry, uint32_t name, const char* inte
2122
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
2223
g_pHyprpaper->m_pSHM = makeShared<CCWlShm>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_shm_interface, 1));
2324
} else if (strcmp(interface, wl_output_interface.name) == 0) {
24-
g_pHyprpaper->m_mtTickMutex.lock();
25-
2625
const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique<SMonitor>()).get();
2726
PMONITOR->wayland_name = name;
2827
PMONITOR->name = "";
2928
PMONITOR->output = makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_output_interface, 4));
3029
PMONITOR->registerListeners();
31-
32-
g_pHyprpaper->m_mtTickMutex.unlock();
3330
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
3431
g_pHyprpaper->createSeat(makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)registry->resource(), name, &wl_seat_interface, 1)));
3532
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
@@ -124,18 +121,66 @@ void CHyprpaper::init() {
124121
if (std::any_cast<Hyprlang::INT>(g_pConfigManager->config->getConfigValue("ipc")))
125122
g_pIPCSocket->initialize();
126123

127-
do {
128-
std::lock_guard<std::mutex> lg(m_mtTickMutex);
129-
tick(true);
130-
} while (wl_display_dispatch(m_sDisplay) != -1);
124+
pollfd pollFDs[] = {
125+
{
126+
.fd = wl_display_get_fd(m_sDisplay),
127+
.events = POLLIN,
128+
},
129+
{
130+
.fd = g_pIPCSocket->fd,
131+
.events = POLLIN,
132+
},
133+
};
134+
135+
tick(true);
136+
137+
while (1) {
138+
int ret = poll(pollFDs, 2, 5000 /* 5 seconds, reasonable. Just in case we need to terminate and the signal fails */);
139+
140+
if (ret < 0) {
141+
if (errno == EINTR)
142+
continue;
143+
144+
Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
145+
exit(1);
146+
}
147+
148+
for (size_t i = 0; i < 2; ++i) {
149+
if (pollFDs[i].revents & POLLHUP) {
150+
Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i);
151+
exit(1);
152+
}
153+
}
154+
155+
if (ret != 0) {
156+
if (pollFDs[0].revents & POLLIN) { // wayland
157+
wl_display_flush(m_sDisplay);
158+
if (wl_display_prepare_read(m_sDisplay) == 0) {
159+
wl_display_read_events(m_sDisplay);
160+
wl_display_dispatch_pending(m_sDisplay);
161+
} else
162+
wl_display_dispatch(m_sDisplay);
163+
}
164+
165+
if (pollFDs[1].revents & POLLIN) { // socket
166+
if (g_pIPCSocket->parseRequest())
167+
tick(true);
168+
}
169+
170+
// finalize wayland dispatching. Dispatch pending on the queue
171+
int ret2 = 0;
172+
do {
173+
ret2 = wl_display_dispatch_pending(m_sDisplay);
174+
wl_display_flush(m_sDisplay);
175+
} while (ret2 > 0);
176+
}
177+
}
131178

132179
unlockSingleInstance();
133180
}
134181

135182
void CHyprpaper::tick(bool force) {
136-
bool reload = g_pIPCSocket && g_pIPCSocket->mainThreadParseRequest();
137-
138-
if (!reload && !force)
183+
if (!force)
139184
return;
140185

141186
preloadAllWallpapersFromConfig();
@@ -388,7 +433,7 @@ void CHyprpaper::ensureMonitorHasActiveWallpaper(SMonitor* pMonitor) {
388433
}
389434

390435
void CHyprpaper::createLSForMonitor(SMonitor* pMonitor) {
391-
pMonitor->pCurrentLayerSurface = pMonitor->layerSurfaces.emplace_back(std::make_unique<CLayerSurface>(pMonitor)).get();
436+
pMonitor->pCurrentLayerSurface = pMonitor->layerSurfaces.emplace_back(makeShared<CLayerSurface>(pMonitor));
392437
}
393438

394439
bool CHyprpaper::lockSingleInstance() {

src/Hyprpaper.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ class CHyprpaper {
7474
bool lockSingleInstance(); // fails on multi-instance
7575
void unlockSingleInstance();
7676

77-
std::mutex m_mtTickMutex;
78-
7977
SMonitor* m_pLastMonitor = nullptr;
8078

8179
private:

src/helpers/Monitor.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ void SMonitor::registerListeners() {
88

99
output->setDone([this](CCWlOutput* r) {
1010
readyForLS = true;
11-
std::lock_guard<std::mutex> lg(g_pHyprpaper->m_mtTickMutex);
1211
if (g_pConfigManager) // don't tick if this is the first roundtrip
1312
g_pHyprpaper->tick(true);
1413
});

src/helpers/Monitor.hpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66
class CCWlOutput;
77

88
struct SMonitor {
9-
std::string name = "";
10-
std::string description = "";
11-
SP<CCWlOutput> output;
12-
uint32_t wayland_name = 0;
13-
Vector2D size;
14-
int scale;
9+
std::string name = "";
10+
std::string description = "";
11+
SP<CCWlOutput> output;
12+
uint32_t wayland_name = 0;
13+
Vector2D size;
14+
int scale;
1515

16-
bool readyForLS = false;
17-
bool hasATarget = true;
16+
bool readyForLS = false;
17+
bool hasATarget = true;
1818

19-
bool wildcard = true;
19+
bool wildcard = true;
2020

21-
uint32_t configureSerial = 0;
21+
uint32_t configureSerial = 0;
2222

23-
bool wantsReload = false;
24-
bool wantsACK = false;
25-
bool initialized = false;
23+
bool wantsReload = false;
24+
bool wantsACK = false;
25+
bool initialized = false;
2626

27-
std::vector<std::unique_ptr<CLayerSurface>> layerSurfaces;
28-
CLayerSurface* pCurrentLayerSurface = nullptr;
27+
std::vector<SP<CLayerSurface>> layerSurfaces;
28+
SP<CLayerSurface> pCurrentLayerSurface = nullptr;
2929

30-
void registerListeners();
30+
void registerListeners();
3131
};

src/ipc/Socket.cpp

Lines changed: 76 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -15,155 +15,134 @@
1515
#include <thread>
1616

1717
void CIPCSocket::initialize() {
18-
std::thread([&]() {
19-
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
18+
fd = socket(AF_UNIX, SOCK_STREAM, 0);
2019

21-
if (SOCKET < 0) {
22-
Debug::log(ERR, "Couldn't start the hyprpaper Socket. (1) IPC will not work.");
23-
return;
24-
}
25-
26-
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
27-
28-
const auto HISenv = getenv("HYPRLAND_INSTANCE_SIGNATURE");
29-
const auto RUNTIMEdir = getenv("XDG_RUNTIME_DIR");
30-
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
20+
if (fd < 0) {
21+
Debug::log(ERR, "Couldn't start the hyprpaper Socket. (1) IPC will not work.");
22+
return;
23+
}
3124

32-
const auto USERDIR = RUNTIMEdir ? RUNTIMEdir + std::string{"/hypr/"} : "/run/user/" + USERID + "/hypr/";
25+
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
3326

34-
std::string socketPath = HISenv ? USERDIR + std::string(HISenv) + "/.hyprpaper.sock" : USERDIR + ".hyprpaper.sock";
27+
const auto HISenv = getenv("HYPRLAND_INSTANCE_SIGNATURE");
28+
const auto RUNTIMEdir = getenv("XDG_RUNTIME_DIR");
29+
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
3530

36-
if (!HISenv)
37-
mkdir(USERDIR.c_str(), S_IRWXU);
31+
const auto USERDIR = RUNTIMEdir ? RUNTIMEdir + std::string{"/hypr/"} : "/run/user/" + USERID + "/hypr/";
3832

39-
unlink(socketPath.c_str());
33+
std::string socketPath = HISenv ? USERDIR + std::string(HISenv) + "/.hyprpaper.sock" : USERDIR + ".hyprpaper.sock";
4034

41-
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
35+
if (!HISenv)
36+
mkdir(USERDIR.c_str(), S_IRWXU);
4237

43-
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
38+
unlink(socketPath.c_str());
4439

45-
// 10 max queued.
46-
listen(SOCKET, 10);
40+
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
4741

48-
sockaddr_in clientAddress = {};
49-
socklen_t clientSize = sizeof(clientAddress);
42+
if (bind(fd, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
43+
Debug::log(ERR, "Couldn't bind the hyprpaper Socket. IPC will not work.");
44+
fd = -1;
45+
return;
46+
}
5047

51-
char readBuffer[1024] = {0};
48+
// 10 max queued.
49+
listen(fd, 10);
5250

53-
Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), SOCKET);
54-
while (1) {
55-
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
56-
if (ACCEPTEDCONNECTION < 0) {
57-
Debug::log(ERR, "Couldn't listen on the hyprpaper Socket. (3) IPC will not work.");
58-
break;
59-
} else {
60-
do {
61-
Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION);
62-
std::lock_guard<std::mutex> lg(g_pHyprpaper->m_mtTickMutex);
63-
64-
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
65-
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
66-
if (messageSize == 0)
67-
break;
68-
std::string request(readBuffer);
69-
70-
m_szRequest = request;
71-
m_bRequestReady = true;
72-
73-
g_pHyprpaper->tick(true);
74-
while (!m_bReplyReady) { // wait for Hyprpaper to finish processing the request
75-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
76-
}
77-
write(ACCEPTEDCONNECTION, m_szReply.c_str(), m_szReply.length());
78-
m_bReplyReady = false;
79-
m_szReply = "";
80-
81-
} while (1);
82-
Debug::log(LOG, "Closing Accepted Connection");
83-
close(ACCEPTEDCONNECTION);
84-
}
85-
}
51+
Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), fd);
52+
}
8653

87-
close(SOCKET);
88-
}).detach();
54+
CIPCSocket::~CIPCSocket() {
55+
if (fd >= 0)
56+
close(fd);
8957
}
9058

91-
bool CIPCSocket::mainThreadParseRequest() {
59+
bool CIPCSocket::parseRequest() {
60+
sockaddr_in clientAddress = {};
61+
socklen_t clientSize = sizeof(clientAddress);
62+
63+
char readBuffer[1024] = {0};
9264

93-
if (!m_bRequestReady)
65+
const auto ACCEPTEDCONNECTION = accept(fd, (sockaddr*)&clientAddress, &clientSize);
66+
if (ACCEPTEDCONNECTION < 0) {
67+
Debug::log(ERR, "Couldn't listen on the hyprpaper Socket. (3)");
9468
return false;
69+
} else {
70+
71+
Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION);
72+
std::string body = "";
73+
do {
74+
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
75+
body += std::string{readBuffer, messageSize};
76+
if (messageSize < 1024)
77+
break;
78+
} while (1);
9579

96-
std::string copy = m_szRequest;
80+
auto reply = processRequest(body);
81+
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
9782

98-
if (copy == "")
99-
return false;
83+
Debug::log(LOG, "Closing Accepted Connection");
84+
close(ACCEPTEDCONNECTION);
85+
}
86+
87+
return true;
88+
}
10089

101-
// now we can work on the copy
90+
std::string CIPCSocket::processRequest(const std::string& body) {
10291

103-
Debug::log(LOG, "Received a request: %s", copy.c_str());
92+
std::string reply = "ok";
10493

105-
// set default reply
106-
m_szReply = "ok";
107-
m_bReplyReady = true;
108-
m_bRequestReady = false;
94+
Debug::log(LOG, "Received a request: %s", body.c_str());
10995

11096
// config commands
111-
if (copy.find("wallpaper") == 0 || copy.find("preload") == 0 || copy.find("unload") == 0 || copy.find("reload") == 0) {
97+
if (body.find("wallpaper") == 0 || body.find("preload") == 0 || body.find("unload") == 0 || body.find("reload") == 0) {
11298

113-
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());
99+
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());
114100

115-
if (RESULT.error) {
116-
m_szReply = RESULT.getError();
117-
return false;
118-
}
101+
if (RESULT.error)
102+
reply = RESULT.getError();
119103

120-
return true;
104+
return reply;
121105
}
122106

123-
if (copy.find("listloaded") == 0) {
107+
if (body.find("listloaded") == 0) {
124108

125109
const auto numWallpapersLoaded = g_pHyprpaper->m_mWallpaperTargets.size();
126110
Debug::log(LOG, "numWallpapersLoaded: %d", numWallpapersLoaded);
127111

128-
if (numWallpapersLoaded == 0) {
129-
m_szReply = "no wallpapers loaded";
130-
return false;
131-
}
112+
if (numWallpapersLoaded == 0)
113+
return "no wallpapers loaded";
132114

133-
m_szReply = "";
115+
reply = "";
134116
long unsigned int i = 0;
135117
for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) {
136-
m_szReply += name;
118+
reply += name;
137119
i++;
138120
if (i < numWallpapersLoaded)
139-
m_szReply += '\n'; // dont add newline on last entry
121+
reply += '\n'; // dont add newline on last entry
140122
}
141123

142-
return true;
124+
return reply;
143125
}
144126

145-
if (copy.find("listactive") == 0) {
127+
if (body.find("listactive") == 0) {
146128

147129
const auto numWallpapersActive = g_pHyprpaper->m_mMonitorActiveWallpapers.size();
148130
Debug::log(LOG, "numWallpapersActive: %d", numWallpapersActive);
149131

150-
if (numWallpapersActive == 0) {
151-
m_szReply = "no wallpapers active";
152-
return false;
153-
}
132+
if (numWallpapersActive == 0)
133+
return "no wallpapers active";
154134

155-
m_szReply = "";
135+
reply = "";
156136
long unsigned int i = 0;
157137
for (auto& [mon, path1] : g_pHyprpaper->m_mMonitorActiveWallpapers) {
158-
m_szReply += mon + " = " + path1;
138+
reply += mon + " = " + path1;
159139
i++;
160140
if (i < numWallpapersActive)
161-
m_szReply += '\n'; // dont add newline on last entry
141+
reply += '\n'; // dont add newline on last entry
162142
}
163143

164-
return true;
144+
return reply;
165145
}
166146

167-
m_szReply = "invalid command";
168-
return false;
147+
return "invalid command";
169148
}

0 commit comments

Comments
 (0)