mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-22 11:09:49 +01:00
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
This commit is contained in:
parent
8e15f91c24
commit
efccf25fcc
5 changed files with 74 additions and 12 deletions
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
====
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
44
src/main.cpp
44
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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue