aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFerdinand Bachmann <[email protected]>2024-07-20 00:37:20 +0200
committerGitHub <[email protected]>2024-07-20 00:37:20 +0200
commitefccf25fcc72b416c63ff540703d9f061f39a7f2 (patch)
treeea08e70802dbf4f94d3d7c7bf7e90b03e97b3a84
parent8e15f91c2417c8f05d69a93f1294185ccc5f8f3e (diff)
downloadHyprland-efccf25fcc72b416c63ff540703d9f061f39a7f2.tar.gz
Hyprland-efccf25fcc72b416c63ff540703d9f061f39a7f2.zip
compositor: implement wayland socket handover (#6930)
* compositor: implement wayland socket handover This commit implements the compositor side of the Wayland socket handover protocol as described in the [KDE Wiki]. The CLI options are chosen so that they are compatible with Kwin. [KDE Wiki]: https://invent.kde.org/plasma/kwin/-/wikis/Restarting * main: verify that --wayland-fd is a valid file descriptor * main: fail if only one of --socket and --wayland-fd is passed
-rw-r--r--docs/Hyprland.14
-rw-r--r--docs/Hyprland.1.rst6
-rw-r--r--src/Compositor.cpp30
-rw-r--r--src/Compositor.hpp2
-rw-r--r--src/main.cpp44
5 files changed, 74 insertions, 12 deletions
diff --git a/docs/Hyprland.1 b/docs/Hyprland.1
index f43d2c5d..5ef24fd5 100644
--- a/docs/Hyprland.1
+++ b/docs/Hyprland.1
@@ -32,6 +32,10 @@ Show command usage.
.TP
\f[B]-c\f[R], \f[B]--config\f[R]
Specify config file to use.
+\f[B]--socket\f[R]
+Sets the Wayland socket name (for Wayland socket handover)
+\f[B]--wayland-fd\f[R]
+Sets the Wayland socket file descriptor (for Wayland socket handover)
.SH BUGS
.TP
Submit bug reports and request features online at:
diff --git a/docs/Hyprland.1.rst b/docs/Hyprland.1.rst
index 54126501..c73b4343 100644
--- a/docs/Hyprland.1.rst
+++ b/docs/Hyprland.1.rst
@@ -41,6 +41,12 @@ OPTIONS
**-c**, **--config**
Specify config file to use.
+**--socket**
+ Sets the Wayland socket name (for Wayland socket handover)
+
+**--wayland-fd**
+ Sets the Wayland socket file descriptor (for Wayland socket handover)
+
BUGS
====
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index d1c51075..7ffccf36 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -27,6 +27,7 @@
#include <hyprutils/string/String.hpp>
using namespace Hyprutils::String;
+#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
@@ -533,19 +534,28 @@ void CCompositor::prepareFallbackOutput() {
wlr_headless_add_output(headless, 1920, 1080);
}
-void CCompositor::startCompositor() {
+void CCompositor::startCompositor(std::string socketName, int socketFd) {
initAllSignals();
- // get socket, avoid using 0
- for (int candidate = 1; candidate <= 32; candidate++) {
- const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
- const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str());
+ if (!socketName.empty() && socketFd != -1) {
+ fcntl(socketFd, F_SETFD, FD_CLOEXEC);
+ const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd);
if (RETVAL >= 0) {
- m_szWLDisplaySocket = CANDIDATESTR;
- Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL);
- break;
- } else {
- Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate);
+ m_szWLDisplaySocket = socketName;
+ Debug::log(LOG, "wl_display_add_socket_fd for {} succeeded with {}", socketName, RETVAL);
+ } else
+ Debug::log(WARN, "wl_display_add_socket_fd for {} returned {}: skipping", socketName, RETVAL);
+ } else {
+ // get socket, avoid using 0
+ for (int candidate = 1; candidate <= 32; candidate++) {
+ const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
+ const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str());
+ if (RETVAL >= 0) {
+ m_szWLDisplaySocket = CANDIDATESTR;
+ Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL);
+ break;
+ } else
+ Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate);
}
}
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 17db2c8b..4aec323f 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -78,7 +78,7 @@ class CCompositor {
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
void initServer();
- void startCompositor();
+ void startCompositor(std::string socketName, int socketFd);
void cleanup();
void createLockFile();
void removeLockFile();
diff --git a/src/main.cpp b/src/main.cpp
index 7e6fee02..1ac3ab8b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,6 +4,7 @@
#include "config/ConfigManager.hpp"
#include "init/initHelpers.hpp"
+#include <fcntl.h>
#include <iostream>
#include <iterator>
#include <vector>
@@ -16,6 +17,8 @@ void help() {
std::cout << "\nArguments:\n";
std::cout << " --help -h - Show this message again\n";
std::cout << " --config FILE -c FILE - Specify config file to use\n";
+ std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n";
+ std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n";
std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n";
}
@@ -37,6 +40,8 @@ int main(int argc, char** argv) {
// parse some args
std::string configPath;
+ std::string socketName;
+ int socketFd = -1;
bool ignoreSudo = false;
std::vector<std::string> args{argv + 1, argv + argc};
@@ -46,6 +51,36 @@ int main(int argc, char** argv) {
std::cout << "[ WARNING ] Running Hyprland with superuser privileges might damage your system\n";
ignoreSudo = true;
+ } else if (it->compare("--socket") == 0) {
+ if (std::next(it) == args.end()) {
+ help();
+
+ return 1;
+ }
+
+ socketName = *std::next(it);
+ it++;
+ } else if (it->compare("--wayland-fd") == 0) {
+ if (std::next(it) == args.end()) {
+ help();
+
+ return 1;
+ }
+
+ try {
+ socketFd = std::stoi(std::next(it)->c_str());
+
+ // check if socketFd is a valid file descriptor
+ if (fcntl(socketFd, F_GETFD) == -1)
+ throw std::exception();
+ } catch (...) {
+ std::cerr << "[ ERROR ] Invalid Wayland FD!\n";
+ help();
+
+ return 1;
+ }
+
+ it++;
} else if (it->compare("-c") == 0 || it->compare("--config") == 0) {
if (std::next(it) == args.end()) {
help();
@@ -93,6 +128,13 @@ int main(int argc, char** argv) {
std::cout << "Superuser privileges check is omitted. I hope you know what you're doing.\n";
}
+ if (socketName.empty() ^ (socketFd == -1)) {
+ std::cerr << "[ ERROR ] Hyprland was launched with only one of --socket and --wayland-fd.\n";
+ std::cerr << " Hint: Pass both --socket and --wayland-fd to perform Wayland socket handover.\n";
+
+ return 1;
+ }
+
std::cout << "Welcome to Hyprland!\n";
// let's init the compositor.
@@ -113,7 +155,7 @@ int main(int argc, char** argv) {
Debug::log(LOG, "Hyprland init finished.");
// If all's good to go, start.
- g_pCompositor->startCompositor();
+ g_pCompositor->startCompositor(socketName, socketFd);
g_pCompositor->m_bIsShuttingDown = true;