mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 10:05:59 +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
|
.TP
|
||||||
\f[B]-c\f[R], \f[B]--config\f[R]
|
\f[B]-c\f[R], \f[B]--config\f[R]
|
||||||
Specify config file to use.
|
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
|
.SH BUGS
|
||||||
.TP
|
.TP
|
||||||
Submit bug reports and request features online at:
|
Submit bug reports and request features online at:
|
||||||
|
|
|
@ -41,6 +41,12 @@ OPTIONS
|
||||||
**-c**, **--config**
|
**-c**, **--config**
|
||||||
Specify config file to use.
|
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
|
BUGS
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
@ -533,19 +534,28 @@ void CCompositor::prepareFallbackOutput() {
|
||||||
wlr_headless_add_output(headless, 1920, 1080);
|
wlr_headless_add_output(headless, 1920, 1080);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::startCompositor() {
|
void CCompositor::startCompositor(std::string socketName, int socketFd) {
|
||||||
initAllSignals();
|
initAllSignals();
|
||||||
|
|
||||||
// get socket, avoid using 0
|
if (!socketName.empty() && socketFd != -1) {
|
||||||
for (int candidate = 1; candidate <= 32; candidate++) {
|
fcntl(socketFd, F_SETFD, FD_CLOEXEC);
|
||||||
const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
|
const auto RETVAL = wl_display_add_socket_fd(m_sWLDisplay, socketFd);
|
||||||
const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str());
|
|
||||||
if (RETVAL >= 0) {
|
if (RETVAL >= 0) {
|
||||||
m_szWLDisplaySocket = CANDIDATESTR;
|
m_szWLDisplaySocket = socketName;
|
||||||
Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL);
|
Debug::log(LOG, "wl_display_add_socket_fd for {} succeeded with {}", socketName, RETVAL);
|
||||||
break;
|
} else
|
||||||
} else {
|
Debug::log(WARN, "wl_display_add_socket_fd for {} returned {}: skipping", socketName, RETVAL);
|
||||||
Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate);
|
} 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;
|
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||||
|
|
||||||
void initServer();
|
void initServer();
|
||||||
void startCompositor();
|
void startCompositor(std::string socketName, int socketFd);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
void createLockFile();
|
void createLockFile();
|
||||||
void removeLockFile();
|
void removeLockFile();
|
||||||
|
|
44
src/main.cpp
44
src/main.cpp
|
@ -4,6 +4,7 @@
|
||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
#include "init/initHelpers.hpp"
|
#include "init/initHelpers.hpp"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -16,6 +17,8 @@ void help() {
|
||||||
std::cout << "\nArguments:\n";
|
std::cout << "\nArguments:\n";
|
||||||
std::cout << " --help -h - Show this message again\n";
|
std::cout << " --help -h - Show this message again\n";
|
||||||
std::cout << " --config FILE -c FILE - Specify config file to use\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";
|
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
|
// parse some args
|
||||||
std::string configPath;
|
std::string configPath;
|
||||||
|
std::string socketName;
|
||||||
|
int socketFd = -1;
|
||||||
bool ignoreSudo = false;
|
bool ignoreSudo = false;
|
||||||
|
|
||||||
std::vector<std::string> args{argv + 1, argv + argc};
|
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";
|
std::cout << "[ WARNING ] Running Hyprland with superuser privileges might damage your system\n";
|
||||||
|
|
||||||
ignoreSudo = true;
|
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) {
|
} else if (it->compare("-c") == 0 || it->compare("--config") == 0) {
|
||||||
if (std::next(it) == args.end()) {
|
if (std::next(it) == args.end()) {
|
||||||
help();
|
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";
|
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";
|
std::cout << "Welcome to Hyprland!\n";
|
||||||
|
|
||||||
// let's init the compositor.
|
// let's init the compositor.
|
||||||
|
@ -113,7 +155,7 @@ int main(int argc, char** argv) {
|
||||||
Debug::log(LOG, "Hyprland init finished.");
|
Debug::log(LOG, "Hyprland init finished.");
|
||||||
|
|
||||||
// If all's good to go, start.
|
// If all's good to go, start.
|
||||||
g_pCompositor->startCompositor();
|
g_pCompositor->startCompositor(socketName, socketFd);
|
||||||
|
|
||||||
g_pCompositor->m_bIsShuttingDown = true;
|
g_pCompositor->m_bIsShuttingDown = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue