mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-10-05 17:46:28 +00:00
core: begin using CFileDescriptor from hyprutils (#9122)
* config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
This commit is contained in:
@@ -5,27 +5,24 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) {
|
CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) {
|
||||||
if (m_inotifyFd < 0) {
|
if (!m_inotifyFd.isValid()) {
|
||||||
Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded");
|
Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FLAGS = fcntl(m_inotifyFd, F_GETFL, 0);
|
// TODO: make CFileDescriptor take F_GETFL, F_SETFL
|
||||||
if (fcntl(m_inotifyFd, F_SETFL, FLAGS | O_NONBLOCK) < 0) {
|
const int FLAGS = fcntl(m_inotifyFd.get(), F_GETFL, 0);
|
||||||
|
if (fcntl(m_inotifyFd.get(), F_SETFL, FLAGS | O_NONBLOCK) < 0) {
|
||||||
Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded");
|
Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded");
|
||||||
close(m_inotifyFd);
|
m_inotifyFd.reset();
|
||||||
m_inotifyFd = -1;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CConfigWatcher::~CConfigWatcher() {
|
CFileDescriptor& CConfigWatcher::getInotifyFD() {
|
||||||
if (m_inotifyFd >= 0)
|
|
||||||
close(m_inotifyFd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CConfigWatcher::getInotifyFD() {
|
|
||||||
return m_inotifyFd;
|
return m_inotifyFd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +35,7 @@ void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
|
|||||||
|
|
||||||
// cleanup old paths
|
// cleanup old paths
|
||||||
for (auto& watch : m_watches) {
|
for (auto& watch : m_watches) {
|
||||||
inotify_rm_watch(m_inotifyFd, watch.wd);
|
inotify_rm_watch(m_inotifyFd.get(), watch.wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_watches.clear();
|
m_watches.clear();
|
||||||
@@ -46,7 +43,7 @@ void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
|
|||||||
// add new paths
|
// add new paths
|
||||||
for (const auto& path : paths) {
|
for (const auto& path : paths) {
|
||||||
m_watches.emplace_back(SInotifyWatch{
|
m_watches.emplace_back(SInotifyWatch{
|
||||||
.wd = inotify_add_watch(m_inotifyFd, path.c_str(), IN_MODIFY),
|
.wd = inotify_add_watch(m_inotifyFd.get(), path.c_str(), IN_MODIFY),
|
||||||
.file = path,
|
.file = path,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -58,7 +55,7 @@ void CConfigWatcher::setOnChange(const std::function<void(const SConfigWatchEven
|
|||||||
|
|
||||||
void CConfigWatcher::onInotifyEvent() {
|
void CConfigWatcher::onInotifyEvent() {
|
||||||
inotify_event ev;
|
inotify_event ev;
|
||||||
while (read(m_inotifyFd, &ev, sizeof(ev)) > 0) {
|
while (read(m_inotifyFd.get(), &ev, sizeof(ev)) > 0) {
|
||||||
const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; });
|
const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; });
|
||||||
|
|
||||||
if (WD == m_watches.end()) {
|
if (WD == m_watches.end()) {
|
||||||
|
@@ -3,20 +3,21 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CConfigWatcher {
|
class CConfigWatcher {
|
||||||
public:
|
public:
|
||||||
CConfigWatcher();
|
CConfigWatcher();
|
||||||
~CConfigWatcher();
|
~CConfigWatcher() = default;
|
||||||
|
|
||||||
struct SConfigWatchEvent {
|
struct SConfigWatchEvent {
|
||||||
std::string file;
|
std::string file;
|
||||||
};
|
};
|
||||||
|
|
||||||
int getInotifyFD();
|
Hyprutils::OS::CFileDescriptor& getInotifyFD();
|
||||||
void setWatchList(const std::vector<std::string>& paths);
|
void setWatchList(const std::vector<std::string>& paths);
|
||||||
void setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn);
|
void setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn);
|
||||||
void onInotifyEvent();
|
void onInotifyEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SInotifyWatch {
|
struct SInotifyWatch {
|
||||||
@@ -26,7 +27,7 @@ class CConfigWatcher {
|
|||||||
|
|
||||||
std::function<void(const SConfigWatchEvent&)> m_watchCallback;
|
std::function<void(const SConfigWatchEvent&)> m_watchCallback;
|
||||||
std::vector<SInotifyWatch> m_watches;
|
std::vector<SInotifyWatch> m_watches;
|
||||||
int m_inotifyFd = -1;
|
Hyprutils::OS::CFileDescriptor m_inotifyFd;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UP<CConfigWatcher> g_pConfigWatcher = makeUnique<CConfigWatcher>();
|
inline UP<CConfigWatcher> g_pConfigWatcher = makeUnique<CConfigWatcher>();
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
#include <aquamarine/input/Input.hpp>
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
#include "../config/ConfigDataValues.hpp"
|
#include "../config/ConfigDataValues.hpp"
|
||||||
@@ -1680,8 +1681,6 @@ CHyprCtl::CHyprCtl() {
|
|||||||
CHyprCtl::~CHyprCtl() {
|
CHyprCtl::~CHyprCtl() {
|
||||||
if (m_eventSource)
|
if (m_eventSource)
|
||||||
wl_event_source_remove(m_eventSource);
|
wl_event_source_remove(m_eventSource);
|
||||||
if (m_iSocketFD >= 0)
|
|
||||||
close(m_iSocketFD);
|
|
||||||
if (!m_socketPath.empty())
|
if (!m_socketPath.empty())
|
||||||
unlink(m_socketPath.c_str());
|
unlink(m_socketPath.c_str());
|
||||||
}
|
}
|
||||||
@@ -1840,10 +1839,13 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!g_pHyprCtl->m_iSocketFD.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
sockaddr_in clientAddress;
|
sockaddr_in clientAddress;
|
||||||
socklen_t clientSize = sizeof(clientAddress);
|
socklen_t clientSize = sizeof(clientAddress);
|
||||||
|
|
||||||
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
const auto ACCEPTEDCONNECTION = accept4(g_pHyprCtl->m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||||
|
|
||||||
std::array<char, 1024> readBuffer;
|
std::array<char, 1024> readBuffer;
|
||||||
|
|
||||||
@@ -1900,9 +1902,9 @@ static int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CHyprCtl::startHyprCtlSocket() {
|
void CHyprCtl::startHyprCtlSocket() {
|
||||||
m_iSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
m_iSocketFD = CFileDescriptor{socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)};
|
||||||
|
|
||||||
if (m_iSocketFD < 0) {
|
if (!m_iSocketFD.isValid()) {
|
||||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1913,15 +1915,15 @@ void CHyprCtl::startHyprCtlSocket() {
|
|||||||
|
|
||||||
strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str());
|
strcpy(SERVERADDRESS.sun_path, m_socketPath.c_str());
|
||||||
|
|
||||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 max queued.
|
// 10 max queued.
|
||||||
listen(m_iSocketFD, 10);
|
listen(m_iSocketFD.get(), 10);
|
||||||
|
|
||||||
Debug::log(LOG, "Hypr socket started at {}", m_socketPath);
|
Debug::log(LOG, "Hypr socket started at {}", m_socketPath);
|
||||||
|
|
||||||
m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
m_eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "../helpers/MiscFunctions.hpp"
|
#include "../helpers/MiscFunctions.hpp"
|
||||||
#include "../desktop/Window.hpp"
|
#include "../desktop/Window.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
// exposed for main.cpp
|
// exposed for main.cpp
|
||||||
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
|
||||||
@@ -14,12 +15,12 @@ class CHyprCtl {
|
|||||||
CHyprCtl();
|
CHyprCtl();
|
||||||
~CHyprCtl();
|
~CHyprCtl();
|
||||||
|
|
||||||
std::string makeDynamicCall(const std::string& input);
|
std::string makeDynamicCall(const std::string& input);
|
||||||
SP<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
SP<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||||
void unregisterCommand(const SP<SHyprCtlCommand>& cmd);
|
void unregisterCommand(const SP<SHyprCtlCommand>& cmd);
|
||||||
std::string getReply(std::string);
|
std::string getReply(std::string);
|
||||||
|
|
||||||
int m_iSocketFD = -1;
|
Hyprutils::OS::CFileDescriptor m_iSocketFD;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool all = false;
|
bool all = false;
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#include <aquamarine/input/Input.hpp>
|
#include <aquamarine/input/Input.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#define LED_COUNT 3
|
#define LED_COUNT 3
|
||||||
|
|
||||||
constexpr static std::array<const char*, 8> MODNAMES = {
|
constexpr static std::array<const char*, 8> MODNAMES = {
|
||||||
@@ -41,9 +43,6 @@ void IKeyboard::clearManuallyAllocd() {
|
|||||||
if (xkbKeymap)
|
if (xkbKeymap)
|
||||||
xkb_keymap_unref(xkbKeymap);
|
xkb_keymap_unref(xkbKeymap);
|
||||||
|
|
||||||
if (xkbKeymapFD >= 0)
|
|
||||||
close(xkbKeymapFD);
|
|
||||||
|
|
||||||
if (xkbSymState)
|
if (xkbSymState)
|
||||||
xkb_state_unref(xkbSymState);
|
xkb_state_unref(xkbSymState);
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ void IKeyboard::clearManuallyAllocd() {
|
|||||||
xkbKeymap = nullptr;
|
xkbKeymap = nullptr;
|
||||||
xkbState = nullptr;
|
xkbState = nullptr;
|
||||||
xkbStaticState = nullptr;
|
xkbStaticState = nullptr;
|
||||||
xkbKeymapFD = -1;
|
xkbKeymapFD.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||||
@@ -147,31 +146,30 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
|||||||
void IKeyboard::updateKeymapFD() {
|
void IKeyboard::updateKeymapFD() {
|
||||||
Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName);
|
Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName);
|
||||||
|
|
||||||
if (xkbKeymapFD >= 0)
|
if (xkbKeymapFD.isValid())
|
||||||
close(xkbKeymapFD);
|
xkbKeymapFD.reset();
|
||||||
xkbKeymapFD = -1;
|
|
||||||
|
|
||||||
auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||||
xkbKeymapString = cKeymapStr;
|
xkbKeymapString = cKeymapStr;
|
||||||
free(cKeymapStr);
|
free(cKeymapStr);
|
||||||
|
|
||||||
int rw, ro;
|
CFileDescriptor rw, ro;
|
||||||
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro))
|
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, rw, ro))
|
||||||
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
|
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
|
||||||
else {
|
else {
|
||||||
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0);
|
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw.get(), 0);
|
||||||
close(rw);
|
rw.reset();
|
||||||
if (keymapFDDest == MAP_FAILED) {
|
if (keymapFDDest == MAP_FAILED) {
|
||||||
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
|
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
|
||||||
close(ro);
|
ro.reset();
|
||||||
} else {
|
} else {
|
||||||
memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length());
|
memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length());
|
||||||
munmap(keymapFDDest, xkbKeymapString.length() + 1);
|
munmap(keymapFDDest, xkbKeymapString.length() + 1);
|
||||||
xkbKeymapFD = ro;
|
xkbKeymapFD = std::move(ro);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD);
|
Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
AQUAMARINE_FORWARD(IKeyboard);
|
AQUAMARINE_FORWARD(IKeyboard);
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ class IKeyboard : public IHID {
|
|||||||
|
|
||||||
std::string xkbFilePath = "";
|
std::string xkbFilePath = "";
|
||||||
std::string xkbKeymapString = "";
|
std::string xkbKeymapString = "";
|
||||||
int xkbKeymapFD = -1;
|
Hyprutils::OS::CFileDescriptor xkbKeymapFD;
|
||||||
|
|
||||||
SStringRuleNames currentRules;
|
SStringRuleNames currentRules;
|
||||||
int repeatRate = 0;
|
int repeatRate = 0;
|
||||||
|
@@ -836,50 +836,48 @@ bool envEnabled(const std::string& env) {
|
|||||||
return std::string(ENV) == "1";
|
return std::string(ENV) == "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, std::string> openExclusiveShm() {
|
std::pair<CFileDescriptor, std::string> openExclusiveShm() {
|
||||||
// Only absolute paths can be shared across different shm_open() calls
|
// Only absolute paths can be shared across different shm_open() calls
|
||||||
std::string name = "/" + g_pTokenManager->getRandomUUID();
|
std::string name = "/" + g_pTokenManager->getRandomUUID();
|
||||||
|
|
||||||
for (size_t i = 0; i < 69; ++i) {
|
for (size_t i = 0; i < 69; ++i) {
|
||||||
int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
CFileDescriptor fd{shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)};
|
||||||
if (fd >= 0)
|
if (fd.isValid())
|
||||||
return {fd, name};
|
return {std::move(fd), name};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {-1, ""};
|
return {{}, ""};
|
||||||
}
|
}
|
||||||
|
|
||||||
int allocateSHMFile(size_t len) {
|
CFileDescriptor allocateSHMFile(size_t len) {
|
||||||
auto [fd, name] = openExclusiveShm();
|
auto [fd, name] = openExclusiveShm();
|
||||||
if (fd < 0)
|
if (!fd.isValid())
|
||||||
return -1;
|
return {};
|
||||||
|
|
||||||
shm_unlink(name.c_str());
|
shm_unlink(name.c_str());
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
do {
|
do {
|
||||||
ret = ftruncate(fd, len);
|
ret = ftruncate(fd.get(), len);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
close(fd);
|
return {};
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return std::move(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) {
|
bool allocateSHMFilePair(size_t size, CFileDescriptor& rw_fd_ptr, CFileDescriptor& ro_fd_ptr) {
|
||||||
auto [fd, name] = openExclusiveShm();
|
auto [fd, name] = openExclusiveShm();
|
||||||
if (fd < 0) {
|
if (!fd.isValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLOEXEC is guaranteed to be set by shm_open
|
// CLOEXEC is guaranteed to be set by shm_open
|
||||||
int ro_fd = shm_open(name.c_str(), O_RDONLY, 0);
|
CFileDescriptor ro_fd{shm_open(name.c_str(), O_RDONLY, 0)};
|
||||||
if (ro_fd < 0) {
|
if (!ro_fd.isValid()) {
|
||||||
shm_unlink(name.c_str());
|
shm_unlink(name.c_str());
|
||||||
close(fd);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,24 +885,20 @@ bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) {
|
|||||||
|
|
||||||
// Make sure the file cannot be re-opened in read-write mode (e.g. via
|
// Make sure the file cannot be re-opened in read-write mode (e.g. via
|
||||||
// "/proc/self/fd/" on Linux)
|
// "/proc/self/fd/" on Linux)
|
||||||
if (fchmod(fd, 0) != 0) {
|
if (fchmod(fd.get(), 0) != 0) {
|
||||||
close(fd);
|
|
||||||
close(ro_fd);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
do {
|
do {
|
||||||
ret = ftruncate(fd, size);
|
ret = ftruncate(fd.get(), size);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
close(fd);
|
|
||||||
close(ro_fd);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*rw_fd_ptr = fd;
|
rw_fd_ptr = std::move(fd);
|
||||||
*ro_fd_ptr = ro_fd;
|
ro_fd_ptr = std::move(ro_fd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
#include "../SharedDefs.hpp"
|
#include "../SharedDefs.hpp"
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
|
|
||||||
@@ -35,8 +36,8 @@ double normalizeAngleRad(double ang);
|
|||||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||||
void throwError(const std::string& err);
|
void throwError(const std::string& err);
|
||||||
bool envEnabled(const std::string& env);
|
bool envEnabled(const std::string& env);
|
||||||
int allocateSHMFile(size_t len);
|
Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len);
|
||||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
|
bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr);
|
||||||
float stringToPercentage(const std::string& VALUE, const float REL);
|
float stringToPercentage(const std::string& VALUE, const float REL);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
using namespace Hyprutils::Utils;
|
using namespace Hyprutils::Utils;
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
static int ratHandler(void* data) {
|
static int ratHandler(void* data) {
|
||||||
g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock());
|
g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock());
|
||||||
@@ -1301,19 +1302,15 @@ bool CMonitor::attemptDirectScanout() {
|
|||||||
|
|
||||||
// wait for the explicit fence if present, and if kms explicit is allowed
|
// wait for the explicit fence if present, and if kms explicit is allowed
|
||||||
bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled;
|
bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled;
|
||||||
int explicitWaitFD = -1;
|
CFileDescriptor explicitWaitFD;
|
||||||
if (DOEXPLICIT) {
|
if (DOEXPLICIT) {
|
||||||
explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint);
|
explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint);
|
||||||
if (explicitWaitFD < 0)
|
if (!explicitWaitFD.isValid())
|
||||||
Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd");
|
Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd");
|
||||||
}
|
}
|
||||||
DOEXPLICIT = DOEXPLICIT && explicitWaitFD >= 0;
|
DOEXPLICIT = DOEXPLICIT && explicitWaitFD.isValid();
|
||||||
|
|
||||||
auto cleanup = CScopeGuard([explicitWaitFD, this]() {
|
auto cleanup = CScopeGuard([this]() { output->state->resetExplicitFences(); });
|
||||||
output->state->resetExplicitFences();
|
|
||||||
if (explicitWaitFD >= 0)
|
|
||||||
close(explicitWaitFD);
|
|
||||||
});
|
|
||||||
|
|
||||||
timespec now;
|
timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
@@ -1323,8 +1320,8 @@ bool CMonitor::attemptDirectScanout() {
|
|||||||
output->state->resetExplicitFences();
|
output->state->resetExplicitFences();
|
||||||
|
|
||||||
if (DOEXPLICIT) {
|
if (DOEXPLICIT) {
|
||||||
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD);
|
Debug::log(TRACE, "attemptDirectScanout: setting IN_FENCE for aq to {}", explicitWaitFD.get());
|
||||||
output->state->setExplicitInFence(explicitWaitFD);
|
output->state->setExplicitInFence(explicitWaitFD.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = output->commit();
|
bool ok = output->commit();
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "DamageRing.hpp"
|
#include "DamageRing.hpp"
|
||||||
#include <aquamarine/output/Output.hpp>
|
#include <aquamarine/output/Output.hpp>
|
||||||
#include <aquamarine/allocator/Swapchain.hpp>
|
#include <aquamarine/allocator/Swapchain.hpp>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
// Enum for the different types of auto directions, e.g. auto-left, auto-up.
|
// Enum for the different types of auto directions, e.g. auto-left, auto-up.
|
||||||
enum eAutoDirs : uint8_t {
|
enum eAutoDirs : uint8_t {
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
SP<CSyncTimeline> CSyncTimeline::create(int drmFD_) {
|
SP<CSyncTimeline> CSyncTimeline::create(int drmFD_) {
|
||||||
auto timeline = SP<CSyncTimeline>(new CSyncTimeline);
|
auto timeline = SP<CSyncTimeline>(new CSyncTimeline);
|
||||||
@@ -85,10 +86,9 @@ bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t poin
|
|||||||
auto w = makeShared<SWaiter>();
|
auto w = makeShared<SWaiter>();
|
||||||
w->fn = waiter;
|
w->fn = waiter;
|
||||||
w->timeline = self;
|
w->timeline = self;
|
||||||
|
w->eventFd = CFileDescriptor{eventfd(0, EFD_CLOEXEC)};
|
||||||
|
|
||||||
int eventFD = eventfd(0, EFD_CLOEXEC);
|
if (!w->eventFd.isValid()) {
|
||||||
|
|
||||||
if (eventFD < 0) {
|
|
||||||
Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd");
|
Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -97,19 +97,17 @@ bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t poin
|
|||||||
.handle = handle,
|
.handle = handle,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
.point = point,
|
.point = point,
|
||||||
.fd = eventFD,
|
.fd = w->eventFd.get(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) {
|
if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) {
|
||||||
Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed");
|
Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed");
|
||||||
close(eventFD);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get());
|
w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, w->eventFd.get(), WL_EVENT_READABLE, ::handleWaiterFD, w.get());
|
||||||
if (!w->source) {
|
if (!w->source) {
|
||||||
Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed");
|
Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed");
|
||||||
close(eventFD);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,32 +124,32 @@ void CSyncTimeline::removeWaiter(SWaiter* w) {
|
|||||||
std::erase_if(waiters, [w](const auto& e) { return e.get() == w; });
|
std::erase_if(waiters, [w](const auto& e) { return e.get() == w; });
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSyncTimeline::exportAsSyncFileFD(uint64_t src) {
|
CFileDescriptor CSyncTimeline::exportAsSyncFileFD(uint64_t src) {
|
||||||
int sync = -1;
|
int sync = -1;
|
||||||
|
|
||||||
uint32_t syncHandle = 0;
|
uint32_t syncHandle = 0;
|
||||||
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
||||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed");
|
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed");
|
||||||
return -1;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) {
|
if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) {
|
||||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed");
|
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed");
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return -1;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) {
|
if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) {
|
||||||
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed");
|
Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed");
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return -1;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return sync;
|
return CFileDescriptor{sync};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) {
|
bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, CFileDescriptor& fd) {
|
||||||
uint32_t syncHandle = 0;
|
uint32_t syncHandle = 0;
|
||||||
|
|
||||||
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
if (drmSyncobjCreate(drmFD, 0, &syncHandle)) {
|
||||||
@@ -159,7 +157,7 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) {
|
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd.get())) {
|
||||||
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
|
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return false;
|
return false;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
#include "../memory/Memory.hpp"
|
#include "../memory/Memory.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -20,26 +21,27 @@ class CSyncTimeline {
|
|||||||
~CSyncTimeline();
|
~CSyncTimeline();
|
||||||
|
|
||||||
struct SWaiter {
|
struct SWaiter {
|
||||||
std::function<void()> fn;
|
std::function<void()> fn;
|
||||||
wl_event_source* source = nullptr;
|
wl_event_source* source = nullptr;
|
||||||
WP<CSyncTimeline> timeline;
|
WP<CSyncTimeline> timeline;
|
||||||
|
Hyprutils::OS::CFileDescriptor eventFd;
|
||||||
};
|
};
|
||||||
|
|
||||||
// check if the timeline point has been signaled
|
// check if the timeline point has been signaled
|
||||||
// flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
|
// flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
|
||||||
// std::nullopt on fail
|
// std::nullopt on fail
|
||||||
std::optional<bool> check(uint64_t point, uint32_t flags);
|
std::optional<bool> check(uint64_t point, uint32_t flags);
|
||||||
|
|
||||||
bool addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags);
|
bool addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags);
|
||||||
void removeWaiter(SWaiter*);
|
void removeWaiter(SWaiter*);
|
||||||
int exportAsSyncFileFD(uint64_t src);
|
Hyprutils::OS::CFileDescriptor exportAsSyncFileFD(uint64_t src);
|
||||||
bool importFromSyncFileFD(uint64_t dst, int fd);
|
bool importFromSyncFileFD(uint64_t dst, Hyprutils::OS::CFileDescriptor& fd);
|
||||||
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
||||||
void signal(uint64_t point);
|
void signal(uint64_t point);
|
||||||
|
|
||||||
int drmFD = -1;
|
int drmFD = -1;
|
||||||
uint32_t handle = 0;
|
uint32_t handle = 0;
|
||||||
WP<CSyncTimeline> self;
|
WP<CSyncTimeline> self;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CSyncTimeline() = default;
|
CSyncTimeline() = default;
|
||||||
|
@@ -9,9 +9,10 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) {
|
CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) {
|
||||||
if (m_iSocketFD < 0) {
|
if (!m_iSocketFD.isValid()) {
|
||||||
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
Debug::log(ERR, "Couldn't start the Hyprland Socket 2. (1) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -25,31 +26,27 @@ CEventManager::CEventManager() : m_iSocketFD(socket(AF_UNIX, SOCK_STREAM | SOCK_
|
|||||||
|
|
||||||
strncpy(SERVERADDRESS.sun_path, PATH.c_str(), sizeof(SERVERADDRESS.sun_path) - 1);
|
strncpy(SERVERADDRESS.sun_path, PATH.c_str(), sizeof(SERVERADDRESS.sun_path) - 1);
|
||||||
|
|
||||||
if (bind(m_iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
if (bind(m_iSocketFD.get(), (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
|
||||||
Debug::log(ERR, "Couldn't bind the Hyprland Socket 2. (3) IPC will not work.");
|
Debug::log(ERR, "Couldn't bind the Hyprland Socket 2. (3) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 max queued.
|
// 10 max queued.
|
||||||
if (listen(m_iSocketFD, 10) < 0) {
|
if (listen(m_iSocketFD.get(), 10) < 0) {
|
||||||
Debug::log(ERR, "Couldn't listen on the Hyprland Socket 2. (4) IPC will not work.");
|
Debug::log(ERR, "Couldn't listen on the Hyprland Socket 2. (4) IPC will not work.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD, WL_EVENT_READABLE, onClientEvent, nullptr);
|
m_pEventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, m_iSocketFD.get(), WL_EVENT_READABLE, onClientEvent, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
CEventManager::~CEventManager() {
|
CEventManager::~CEventManager() {
|
||||||
for (const auto& client : m_vClients) {
|
for (const auto& client : m_vClients) {
|
||||||
wl_event_source_remove(client.eventSource);
|
wl_event_source_remove(client.eventSource);
|
||||||
close(client.fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pEventSource != nullptr)
|
if (m_pEventSource != nullptr)
|
||||||
wl_event_source_remove(m_pEventSource);
|
wl_event_source_remove(m_pEventSource);
|
||||||
|
|
||||||
if (m_iSocketFD >= 0)
|
|
||||||
close(m_iSocketFD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CEventManager::onServerEvent(int fd, uint32_t mask, void* data) {
|
int CEventManager::onServerEvent(int fd, uint32_t mask, void* data) {
|
||||||
@@ -66,33 +63,31 @@ int CEventManager::onServerEvent(int fd, uint32_t mask) {
|
|||||||
|
|
||||||
wl_event_source_remove(m_pEventSource);
|
wl_event_source_remove(m_pEventSource);
|
||||||
m_pEventSource = nullptr;
|
m_pEventSource = nullptr;
|
||||||
close(fd);
|
m_iSocketFD.reset();
|
||||||
m_iSocketFD = -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_in clientAddress;
|
sockaddr_in clientAddress;
|
||||||
socklen_t clientSize = sizeof(clientAddress);
|
socklen_t clientSize = sizeof(clientAddress);
|
||||||
const auto ACCEPTEDCONNECTION = accept4(m_iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK);
|
CFileDescriptor ACCEPTEDCONNECTION{accept4(m_iSocketFD.get(), (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC | SOCK_NONBLOCK)};
|
||||||
if (ACCEPTEDCONNECTION < 0) {
|
if (!ACCEPTEDCONNECTION.isValid()) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
Debug::log(ERR, "Socket2 failed receiving connection, errno: {}", errno);
|
Debug::log(ERR, "Socket2 failed receiving connection, errno: {}", errno);
|
||||||
wl_event_source_remove(m_pEventSource);
|
wl_event_source_remove(m_pEventSource);
|
||||||
m_pEventSource = nullptr;
|
m_pEventSource = nullptr;
|
||||||
close(fd);
|
m_iSocketFD.reset();
|
||||||
m_iSocketFD = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION);
|
Debug::log(LOG, "Socket2 accepted a new client at FD {}", ACCEPTEDCONNECTION.get());
|
||||||
|
|
||||||
// add to event loop so we can close it when we need to
|
// add to event loop so we can close it when we need to
|
||||||
auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, 0, onServerEvent, nullptr);
|
auto* eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION.get(), 0, onServerEvent, nullptr);
|
||||||
m_vClients.emplace_back(SClient{
|
m_vClients.emplace_back(SClient{
|
||||||
ACCEPTEDCONNECTION,
|
std::move(ACCEPTEDCONNECTION),
|
||||||
{},
|
{},
|
||||||
eventSource,
|
eventSource,
|
||||||
});
|
});
|
||||||
@@ -113,7 +108,7 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) {
|
|||||||
// send all queued events
|
// send all queued events
|
||||||
while (!CLIENTIT->events.empty()) {
|
while (!CLIENTIT->events.empty()) {
|
||||||
const auto& event = CLIENTIT->events.front();
|
const auto& event = CLIENTIT->events.front();
|
||||||
if (write(CLIENTIT->fd, event->c_str(), event->length()) < 0)
|
if (write(CLIENTIT->fd.get(), event->c_str(), event->length()) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
CLIENTIT->events.erase(CLIENTIT->events.begin());
|
CLIENTIT->events.erase(CLIENTIT->events.begin());
|
||||||
@@ -128,13 +123,12 @@ int CEventManager::onClientEvent(int fd, uint32_t mask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CEventManager::SClient>::iterator CEventManager::findClientByFD(int fd) {
|
std::vector<CEventManager::SClient>::iterator CEventManager::findClientByFD(int fd) {
|
||||||
return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd == fd; });
|
return std::find_if(m_vClients.begin(), m_vClients.end(), [fd](const auto& client) { return client.fd.get() == fd; });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CEventManager::SClient>::iterator CEventManager::removeClientByFD(int fd) {
|
std::vector<CEventManager::SClient>::iterator CEventManager::removeClientByFD(int fd) {
|
||||||
const auto CLIENTIT = findClientByFD(fd);
|
const auto CLIENTIT = findClientByFD(fd);
|
||||||
wl_event_source_remove(CLIENTIT->eventSource);
|
wl_event_source_remove(CLIENTIT->eventSource);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return m_vClients.erase(CLIENTIT);
|
return m_vClients.erase(CLIENTIT);
|
||||||
}
|
}
|
||||||
@@ -157,11 +151,11 @@ void CEventManager::postEvent(const SHyprIPCEvent& event) {
|
|||||||
for (auto it = m_vClients.begin(); it != m_vClients.end();) {
|
for (auto it = m_vClients.begin(); it != m_vClients.end();) {
|
||||||
// try to send the event immediately if the queue is empty
|
// try to send the event immediately if the queue is empty
|
||||||
const auto QUEUESIZE = it->events.size();
|
const auto QUEUESIZE = it->events.size();
|
||||||
if (QUEUESIZE > 0 || write(it->fd, sharedEvent->c_str(), sharedEvent->length()) < 0) {
|
if (QUEUESIZE > 0 || write(it->fd.get(), sharedEvent->c_str(), sharedEvent->length()) < 0) {
|
||||||
if (QUEUESIZE >= MAX_QUEUED_EVENTS) {
|
if (QUEUESIZE >= MAX_QUEUED_EVENTS) {
|
||||||
// too many events queued, remove the client
|
// too many events queued, remove the client
|
||||||
Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd);
|
Debug::log(ERR, "Socket2 fd {} overflowed event queue, removing", it->fd.get());
|
||||||
it = removeClientByFD(it->fd);
|
it = removeClientByFD(it->fd.get());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/memory/Memory.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
@@ -26,19 +26,19 @@ class CEventManager {
|
|||||||
int onClientEvent(int fd, uint32_t mask);
|
int onClientEvent(int fd, uint32_t mask);
|
||||||
|
|
||||||
struct SClient {
|
struct SClient {
|
||||||
int fd = -1;
|
Hyprutils::OS::CFileDescriptor fd;
|
||||||
std::vector<SP<std::string>> events;
|
std::vector<SP<std::string>> events;
|
||||||
wl_event_source* eventSource = nullptr;
|
wl_event_source* eventSource = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<SClient>::iterator findClientByFD(int fd);
|
std::vector<SClient>::iterator findClientByFD(int fd);
|
||||||
std::vector<SClient>::iterator removeClientByFD(int fd);
|
std::vector<SClient>::iterator removeClientByFD(int fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_iSocketFD = -1;
|
Hyprutils::OS::CFileDescriptor m_iSocketFD;
|
||||||
wl_event_source* m_pEventSource = nullptr;
|
wl_event_source* m_pEventSource = nullptr;
|
||||||
|
|
||||||
std::vector<SClient> m_vClients;
|
std::vector<SClient> m_vClients;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UP<CEventManager> g_pEventManager;
|
inline UP<CEventManager> g_pEventManager;
|
||||||
|
@@ -28,7 +28,9 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -853,19 +855,18 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
|||||||
const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
||||||
|
|
||||||
// vtnr is bugged for some reason.
|
// vtnr is bugged for some reason.
|
||||||
unsigned int ttynum = 0;
|
unsigned int ttynum = 0;
|
||||||
int fd;
|
Hyprutils::OS::CFileDescriptor fd{open("/dev/tty", O_RDONLY | O_NOCTTY)};
|
||||||
if ((fd = open("/dev/tty", O_RDONLY | O_NOCTTY)) >= 0) {
|
if (fd.isValid()) {
|
||||||
#if defined(VT_GETSTATE)
|
#if defined(VT_GETSTATE)
|
||||||
struct vt_stat st;
|
struct vt_stat st;
|
||||||
if (!ioctl(fd, VT_GETSTATE, &st))
|
if (!ioctl(fd.get(), VT_GETSTATE, &st))
|
||||||
ttynum = st.v_active;
|
ttynum = st.v_active;
|
||||||
#elif defined(VT_GETACTIVE)
|
#elif defined(VT_GETACTIVE)
|
||||||
int vt;
|
int vt;
|
||||||
if (!ioctl(fd, VT_GETACTIVE, &vt))
|
if (!ioctl(fd.get(), VT_GETACTIVE, &vt))
|
||||||
ttynum = vt;
|
ttynum = vt;
|
||||||
#endif
|
#endif
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ttynum == TTY)
|
if (ttynum == TTY)
|
||||||
@@ -944,11 +945,11 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
|||||||
Debug::log(LOG, "Unable to create pipe for fork");
|
Debug::log(LOG, "Unable to create pipe for fork");
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t child, grandchild;
|
CFileDescriptor pipeSock[2] = {CFileDescriptor{socket[0]}, CFileDescriptor{socket[1]}};
|
||||||
|
|
||||||
|
pid_t child, grandchild;
|
||||||
child = fork();
|
child = fork();
|
||||||
if (child < 0) {
|
if (child < 0) {
|
||||||
close(socket[0]);
|
|
||||||
close(socket[1]);
|
|
||||||
Debug::log(LOG, "Fail to create the first fork");
|
Debug::log(LOG, "Fail to create the first fork");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -967,22 +968,16 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
|
|||||||
setenv(e.first.c_str(), e.second.c_str(), 1);
|
setenv(e.first.c_str(), e.second.c_str(), 1);
|
||||||
}
|
}
|
||||||
setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1);
|
setenv("WAYLAND_DISPLAY", g_pCompositor->m_szWLDisplaySocket.c_str(), 1);
|
||||||
close(socket[0]);
|
|
||||||
close(socket[1]);
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||||
// exit grandchild
|
// exit grandchild
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
close(socket[0]);
|
write(pipeSock[1].get(), &grandchild, sizeof(grandchild));
|
||||||
write(socket[1], &grandchild, sizeof(grandchild));
|
|
||||||
close(socket[1]);
|
|
||||||
// exit child
|
// exit child
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
// run in parent
|
// run in parent
|
||||||
close(socket[1]);
|
read(pipeSock[0].get(), &grandchild, sizeof(grandchild));
|
||||||
read(socket[0], &grandchild, sizeof(grandchild));
|
|
||||||
close(socket[0]);
|
|
||||||
// clear child and leave grandchild to init
|
// clear child and leave grandchild to init
|
||||||
waitpid(child, nullptr, 0);
|
waitpid(child, nullptr, 0);
|
||||||
if (grandchild < 0) {
|
if (grandchild < 0) {
|
||||||
|
@@ -11,11 +11,12 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <aquamarine/backend/Backend.hpp>
|
#include <aquamarine/backend/Backend.hpp>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#define TIMESPEC_NSEC_PER_SEC 1000000000L
|
#define TIMESPEC_NSEC_PER_SEC 1000000000L
|
||||||
|
|
||||||
CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) {
|
CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) {
|
||||||
m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
m_sTimers.timerfd = CFileDescriptor{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)};
|
||||||
m_sWayland.loop = wlEventLoop;
|
m_sWayland.loop = wlEventLoop;
|
||||||
m_sWayland.display = display;
|
m_sWayland.display = display;
|
||||||
}
|
}
|
||||||
@@ -31,8 +32,6 @@ CEventLoopManager::~CEventLoopManager() {
|
|||||||
wl_event_source_remove(m_sIdle.eventSource);
|
wl_event_source_remove(m_sIdle.eventSource);
|
||||||
if (m_configWatcherInotifySource)
|
if (m_configWatcherInotifySource)
|
||||||
wl_event_source_remove(m_configWatcherInotifySource);
|
wl_event_source_remove(m_configWatcherInotifySource);
|
||||||
if (m_sTimers.timerfd >= 0)
|
|
||||||
close(m_sTimers.timerfd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int timerWrite(int fd, uint32_t mask, void* data) {
|
static int timerWrite(int fd, uint32_t mask, void* data) {
|
||||||
@@ -52,10 +51,10 @@ static int configWatcherWrite(int fd, uint32_t mask, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::enterLoop() {
|
void CEventLoopManager::enterLoop() {
|
||||||
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr);
|
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd.get(), WL_EVENT_READABLE, timerWrite, nullptr);
|
||||||
|
|
||||||
if (const auto FD = g_pConfigWatcher->getInotifyFD(); FD >= 0)
|
if (const auto& FD = g_pConfigWatcher->getInotifyFD(); FD.isValid())
|
||||||
m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD, WL_EVENT_READABLE, configWatcherWrite, nullptr);
|
m_configWatcherInotifySource = wl_event_loop_add_fd(m_sWayland.loop, FD.get(), WL_EVENT_READABLE, configWatcherWrite, nullptr);
|
||||||
|
|
||||||
syncPollFDs();
|
syncPollFDs();
|
||||||
m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); });
|
m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); });
|
||||||
@@ -120,7 +119,7 @@ void CEventLoopManager::nudgeTimers() {
|
|||||||
|
|
||||||
itimerspec ts = {.it_value = now};
|
itimerspec ts = {.it_value = now};
|
||||||
|
|
||||||
timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr);
|
timerfd_settime(m_sTimers.timerfd.get(), TFD_TIMER_ABSTIME, &ts, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::doLater(const std::function<void()>& fn) {
|
void CEventLoopManager::doLater(const std::function<void()>& fn) {
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include "helpers/signal/Signal.hpp"
|
#include "helpers/signal/Signal.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
#include "EventLoopTimer.hpp"
|
#include "EventLoopTimer.hpp"
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ class CEventLoopManager {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::vector<SP<CEventLoopTimer>> timers;
|
std::vector<SP<CEventLoopTimer>> timers;
|
||||||
int timerfd = -1;
|
Hyprutils::OS::CFileDescriptor timerfd;
|
||||||
} m_sTimers;
|
} m_sTimers;
|
||||||
|
|
||||||
SIdleData m_sIdle;
|
SIdleData m_sIdle;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||||
#include <aquamarine/backend/DRM.hpp>
|
#include <aquamarine/backend/DRM.hpp>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CDRMLeaseResource::CDRMLeaseResource(SP<CWpDrmLeaseV1> resource_, SP<CDRMLeaseRequestResource> request) : resource(resource_) {
|
CDRMLeaseResource::CDRMLeaseResource(SP<CWpDrmLeaseV1> resource_, SP<CDRMLeaseRequestResource> request) : resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -185,15 +186,14 @@ CDRMLeaseDeviceResource::CDRMLeaseDeviceResource(SP<CWpDrmLeaseDeviceV1> resourc
|
|||||||
RESOURCE->parent = self;
|
RESOURCE->parent = self;
|
||||||
});
|
});
|
||||||
|
|
||||||
int fd = ((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD();
|
CFileDescriptor fd{((Aquamarine::CDRMBackend*)PROTO::lease->primaryDevice->backend.get())->getNonMasterFD()};
|
||||||
if (fd < 0) {
|
if (!fd.isValid()) {
|
||||||
LOGM(ERR, "Failed to dup fd in lease");
|
LOGM(ERR, "Failed to dup fd in lease");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGM(LOG, "Sending DRMFD {} to new lease device", fd);
|
LOGM(LOG, "Sending DRMFD {} to new lease device", fd.get());
|
||||||
resource->sendDrmFd(fd);
|
resource->sendDrmFd(fd.get());
|
||||||
close(fd);
|
|
||||||
|
|
||||||
for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) {
|
for (auto const& m : PROTO::lease->primaryDevice->offeredOutputs) {
|
||||||
if (m)
|
if (m)
|
||||||
@@ -231,16 +231,15 @@ void CDRMLeaseDeviceResource::sendConnector(PHLMONITOR monitor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CDRMLeaseDevice::CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend) : backend(drmBackend) {
|
CDRMLeaseDevice::CDRMLeaseDevice(SP<Aquamarine::CDRMBackend> drmBackend) : backend(drmBackend) {
|
||||||
auto drm = (Aquamarine::CDRMBackend*)drmBackend.get();
|
auto drm = (Aquamarine::CDRMBackend*)drmBackend.get();
|
||||||
|
|
||||||
auto fd = drm->getNonMasterFD();
|
CFileDescriptor fd{drm->getNonMasterFD()};
|
||||||
|
|
||||||
if (fd < 0) {
|
if (!fd.isValid()) {
|
||||||
LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName);
|
LOGM(ERR, "Failed to dup fd for drm node {}", drm->gpuName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
|
||||||
success = true;
|
success = true;
|
||||||
name = drm->gpuName;
|
name = drm->gpuName;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "drm-lease-v1.hpp"
|
#include "drm-lease-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu)
|
TODO: this protocol is not made for systems with multiple DRM nodes (e.g. multigpu)
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
|
CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -103,7 +104,7 @@ bool CDRMSyncobjSurfaceResource::good() {
|
|||||||
return resource->resource();
|
return resource->resource();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, int fd_) : fd(fd_), resource(resource_) {
|
CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, CFileDescriptor fd_) : fd(std::move(fd_)), resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTi
|
|||||||
resource->setOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
|
resource->setOnDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
|
||||||
resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
|
resource->setDestroy([this](CWpLinuxDrmSyncobjTimelineV1* r) { PROTO::sync->destroyResource(this); });
|
||||||
|
|
||||||
timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd);
|
timeline = CSyncTimeline::create(PROTO::sync->drmFD, fd.get());
|
||||||
|
|
||||||
if (!timeline) {
|
if (!timeline) {
|
||||||
resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing");
|
resource->error(WP_LINUX_DRM_SYNCOBJ_MANAGER_V1_ERROR_INVALID_TIMELINE, "Timeline failed importing");
|
||||||
@@ -120,11 +121,6 @@ CDRMSyncobjTimelineResource::CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CDRMSyncobjTimelineResource::~CDRMSyncobjTimelineResource() {
|
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
SP<CDRMSyncobjTimelineResource> CDRMSyncobjTimelineResource::fromResource(wl_resource* res) {
|
SP<CDRMSyncobjTimelineResource> CDRMSyncobjTimelineResource::fromResource(wl_resource* res) {
|
||||||
auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data());
|
auto data = (CDRMSyncobjTimelineResource*)(((CWpLinuxDrmSyncobjTimelineV1*)wl_resource_get_user_data(res))->data());
|
||||||
return data ? data->self.lock() : nullptr;
|
return data ? data->self.lock() : nullptr;
|
||||||
@@ -171,7 +167,7 @@ CDRMSyncobjManagerResource::CDRMSyncobjManagerResource(SP<CWpLinuxDrmSyncobjMana
|
|||||||
});
|
});
|
||||||
|
|
||||||
resource->setImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) {
|
resource->setImportTimeline([this](CWpLinuxDrmSyncobjManagerV1* r, uint32_t id, int32_t fd) {
|
||||||
auto RESOURCE = makeShared<CDRMSyncobjTimelineResource>(makeShared<CWpLinuxDrmSyncobjTimelineV1>(resource->client(), resource->version(), id), fd);
|
auto RESOURCE = makeShared<CDRMSyncobjTimelineResource>(makeShared<CWpLinuxDrmSyncobjTimelineV1>(resource->client(), resource->version(), id), CFileDescriptor{fd});
|
||||||
if UNLIKELY (!RESOURCE->good()) {
|
if UNLIKELY (!RESOURCE->good()) {
|
||||||
resource->noMemory();
|
resource->noMemory();
|
||||||
return;
|
return;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "linux-drm-syncobj-v1.hpp"
|
#include "linux-drm-syncobj-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
class CDRMSyncobjTimelineResource;
|
class CDRMSyncobjTimelineResource;
|
||||||
@@ -32,14 +33,14 @@ class CDRMSyncobjSurfaceResource {
|
|||||||
|
|
||||||
class CDRMSyncobjTimelineResource {
|
class CDRMSyncobjTimelineResource {
|
||||||
public:
|
public:
|
||||||
CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, int fd_);
|
CDRMSyncobjTimelineResource(SP<CWpLinuxDrmSyncobjTimelineV1> resource_, Hyprutils::OS::CFileDescriptor fd_);
|
||||||
~CDRMSyncobjTimelineResource();
|
~CDRMSyncobjTimelineResource() = default;
|
||||||
static SP<CDRMSyncobjTimelineResource> fromResource(wl_resource*);
|
static SP<CDRMSyncobjTimelineResource> fromResource(wl_resource*);
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
WP<CDRMSyncobjTimelineResource> self;
|
WP<CDRMSyncobjTimelineResource> self;
|
||||||
int fd = -1;
|
Hyprutils::OS::CFileDescriptor fd;
|
||||||
SP<CSyncTimeline> timeline;
|
SP<CSyncTimeline> timeline;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../managers/SeatManager.hpp"
|
#include "../managers/SeatManager.hpp"
|
||||||
#include "core/Seat.hpp"
|
#include "core/Seat.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CWLRDataOffer::CWLRDataOffer(SP<CZwlrDataControlOfferV1> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
CWLRDataOffer::CWLRDataOffer(SP<CZwlrDataControlOfferV1> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -11,21 +12,20 @@ CWLRDataOffer::CWLRDataOffer(SP<CZwlrDataControlOfferV1> resource_, SP<IDataSour
|
|||||||
resource->setOnDestroy([this](CZwlrDataControlOfferV1* r) { PROTO::dataWlr->destroyResource(this); });
|
resource->setOnDestroy([this](CZwlrDataControlOfferV1* r) { PROTO::dataWlr->destroyResource(this); });
|
||||||
|
|
||||||
resource->setReceive([this](CZwlrDataControlOfferV1* r, const char* mime, int32_t fd) {
|
resource->setReceive([this](CZwlrDataControlOfferV1* r, const char* mime, int32_t fd) {
|
||||||
|
CFileDescriptor sendFd{fd};
|
||||||
if (!source) {
|
if (!source) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead) {
|
if (dead) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get());
|
LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get());
|
||||||
|
|
||||||
source->send(mime, fd);
|
source->send(mime, std::move(sendFd));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,15 +77,13 @@ std::vector<std::string> CWLRDataSource::mimes() {
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLRDataSource::send(const std::string& mime, uint32_t fd) {
|
void CWLRDataSource::send(const std::string& mime, CFileDescriptor fd) {
|
||||||
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
||||||
LOGM(ERR, "Compositor/App bug: CWLRDataSource::sendAskSend with non-existent mime");
|
LOGM(ERR, "Compositor/App bug: CWLRDataSource::sendAskSend with non-existent mime");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource->sendSend(mime.c_str(), fd);
|
resource->sendSend(mime.c_str(), fd.get());
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLRDataSource::accepted(const std::string& mime) {
|
void CWLRDataSource::accepted(const std::string& mime) {
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-data-control-unstable-v1.hpp"
|
#include "wlr-data-control-unstable-v1.hpp"
|
||||||
#include "types/DataDevice.hpp"
|
#include "types/DataDevice.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CWLRDataControlManagerResource;
|
class CWLRDataControlManagerResource;
|
||||||
class CWLRDataSource;
|
class CWLRDataSource;
|
||||||
@@ -38,7 +39,7 @@ class CWLRDataSource : public IDataSource {
|
|||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes();
|
virtual std::vector<std::string> mimes();
|
||||||
virtual void send(const std::string& mime, uint32_t fd);
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd);
|
||||||
virtual void accepted(const std::string& mime);
|
virtual void accepted(const std::string& mime);
|
||||||
virtual void cancelled();
|
virtual void cancelled();
|
||||||
virtual void error(uint32_t code, const std::string& msg);
|
virtual void error(uint32_t code, const std::string& msg);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "../helpers/Monitor.hpp"
|
#include "../helpers/Monitor.hpp"
|
||||||
#include "../protocols/core/Output.hpp"
|
#include "../protocols/core/Output.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* output) : resource(resource_) {
|
CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* output) : resource(resource_) {
|
||||||
if UNLIKELY (!resource_->resource())
|
if UNLIKELY (!resource_->resource())
|
||||||
@@ -46,34 +47,33 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
|
|||||||
resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); });
|
resource->setOnDestroy([this](CZwlrGammaControlV1* gamma) { PROTO::gamma->destroyGammaControl(this); });
|
||||||
|
|
||||||
resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) {
|
resource->setSetGamma([this](CZwlrGammaControlV1* gamma, int32_t fd) {
|
||||||
|
CFileDescriptor gammaFd{fd};
|
||||||
if UNLIKELY (!pMonitor) {
|
if UNLIKELY (!pMonitor) {
|
||||||
LOGM(ERR, "setGamma for a dead monitor");
|
LOGM(ERR, "setGamma for a dead monitor");
|
||||||
resource->sendFailed();
|
resource->sendFailed();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGM(LOG, "setGamma for {}", pMonitor->szName);
|
LOGM(LOG, "setGamma for {}", pMonitor->szName);
|
||||||
|
|
||||||
int fdFlags = fcntl(fd, F_GETFL, 0);
|
// TODO: make CFileDescriptor getflags use F_GETFL
|
||||||
|
int fdFlags = fcntl(gammaFd.get(), F_GETFL, 0);
|
||||||
if UNLIKELY (fdFlags < 0) {
|
if UNLIKELY (fdFlags < 0) {
|
||||||
LOGM(ERR, "Failed to get fd flags");
|
LOGM(ERR, "Failed to get fd flags");
|
||||||
resource->sendFailed();
|
resource->sendFailed();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if UNLIKELY (fcntl(fd, F_SETFL, fdFlags | O_NONBLOCK) < 0) {
|
// TODO: make CFileDescriptor setflags use F_SETFL
|
||||||
|
if UNLIKELY (fcntl(gammaFd.get(), F_SETFL, fdFlags | O_NONBLOCK) < 0) {
|
||||||
LOGM(ERR, "Failed to set fd flags");
|
LOGM(ERR, "Failed to set fd flags");
|
||||||
resource->sendFailed();
|
resource->sendFailed();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t readBytes = pread(fd, gammaTable.data(), gammaTable.size() * sizeof(uint16_t), 0);
|
ssize_t readBytes = pread(gammaFd.get(), gammaTable.data(), gammaTable.size() * sizeof(uint16_t), 0);
|
||||||
if (readBytes < 0 || (size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) {
|
if (readBytes < 0 || (size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) {
|
||||||
LOGM(ERR, "Failed to read bytes");
|
LOGM(ERR, "Failed to read bytes");
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if ((size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) {
|
if ((size_t)readBytes != gammaTable.size() * sizeof(uint16_t)) {
|
||||||
gamma->error(ZWLR_GAMMA_CONTROL_V1_ERROR_INVALID_GAMMA, "Gamma ramps size mismatch");
|
gamma->error(ZWLR_GAMMA_CONTROL_V1_ERROR_INVALID_GAMMA, "Gamma ramps size mismatch");
|
||||||
@@ -85,7 +85,6 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
|
|||||||
}
|
}
|
||||||
|
|
||||||
gammaTableSet = true;
|
gammaTableSet = true;
|
||||||
close(fd);
|
|
||||||
|
|
||||||
// translate the table to AQ format
|
// translate the table to AQ format
|
||||||
std::vector<uint16_t> red, green, blue;
|
std::vector<uint16_t> red, green, blue;
|
||||||
|
@@ -33,25 +33,22 @@ void CInputMethodKeyboardGrabV2::sendKeyboardData(SP<IKeyboard> keyboard) {
|
|||||||
|
|
||||||
pLastKeyboard = keyboard;
|
pLastKeyboard = keyboard;
|
||||||
|
|
||||||
int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1);
|
auto keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1);
|
||||||
if UNLIKELY (keymapFD < 0) {
|
if UNLIKELY (!keymapFD.isValid()) {
|
||||||
LOGM(ERR, "Failed to create a keymap file for keyboard grab");
|
LOGM(ERR, "Failed to create a keymap file for keyboard grab");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0);
|
void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD.get(), 0);
|
||||||
if UNLIKELY (data == MAP_FAILED) {
|
if UNLIKELY (data == MAP_FAILED) {
|
||||||
LOGM(ERR, "Failed to mmap a keymap file for keyboard grab");
|
LOGM(ERR, "Failed to mmap a keymap file for keyboard grab");
|
||||||
close(keymapFD);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length());
|
memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length());
|
||||||
munmap(data, keyboard->xkbKeymapString.length() + 1);
|
munmap(data, keyboard->xkbKeymapString.length() + 1);
|
||||||
|
|
||||||
resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1);
|
resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD.get(), keyboard->xkbKeymapString.length() + 1);
|
||||||
|
|
||||||
close(keymapFD);
|
|
||||||
|
|
||||||
sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group);
|
sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group);
|
||||||
|
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
#include "../render/OpenGL.hpp"
|
#include "../render/OpenGL.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
static std::optional<dev_t> devIDFromFD(int fd) {
|
static std::optional<dev_t> devIDFromFD(int fd) {
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
if (fstat(fd, &stat) != 0)
|
if (fstat(fd, &stat) != 0)
|
||||||
@@ -77,29 +79,21 @@ CDMABUFFormatTable::CDMABUFFormatTable(SDMABUFTranche _rendererTranche, std::vec
|
|||||||
|
|
||||||
tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry);
|
tableSize = formatsVec.size() * sizeof(SDMABUFFormatTableEntry);
|
||||||
|
|
||||||
int fds[2] = {0};
|
CFileDescriptor fds[2];
|
||||||
allocateSHMFilePair(tableSize, &fds[0], &fds[1]);
|
allocateSHMFilePair(tableSize, fds[0], fds[1]);
|
||||||
|
|
||||||
auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0], 0);
|
auto arr = (SDMABUFFormatTableEntry*)mmap(nullptr, tableSize, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0].get(), 0);
|
||||||
|
|
||||||
if (arr == MAP_FAILED) {
|
if (arr == MAP_FAILED) {
|
||||||
LOGM(ERR, "mmap failed");
|
LOGM(ERR, "mmap failed");
|
||||||
close(fds[0]);
|
|
||||||
close(fds[1]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fds[0]);
|
|
||||||
|
|
||||||
std::copy(formatsVec.begin(), formatsVec.end(), arr);
|
std::copy(formatsVec.begin(), formatsVec.end(), arr);
|
||||||
|
|
||||||
munmap(arr, tableSize);
|
munmap(arr, tableSize);
|
||||||
|
|
||||||
tableFD = fds[1];
|
tableFD = std::move(fds[1]);
|
||||||
}
|
|
||||||
|
|
||||||
CDMABUFFormatTable::~CDMABUFFormatTable() {
|
|
||||||
close(tableFD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) {
|
CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) {
|
||||||
@@ -234,18 +228,18 @@ void CLinuxDMABUFParamsResource::create(uint32_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CLinuxDMABUFParamsResource::commence() {
|
bool CLinuxDMABUFParamsResource::commence() {
|
||||||
if (PROTO::linuxDma->mainDeviceFD < 0)
|
if (!PROTO::linuxDma->mainDeviceFD.isValid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (int i = 0; i < attrs->planes; i++) {
|
for (int i = 0; i < attrs->planes; i++) {
|
||||||
uint32_t handle = 0;
|
uint32_t handle = 0;
|
||||||
|
|
||||||
if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD, attrs->fds.at(i), &handle)) {
|
if (drmPrimeFDToHandle(PROTO::linuxDma->mainDeviceFD.get(), attrs->fds.at(i), &handle)) {
|
||||||
LOGM(ERR, "Failed to import dmabuf fd");
|
LOGM(ERR, "Failed to import dmabuf fd");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drmCloseBufferHandle(PROTO::linuxDma->mainDeviceFD, handle)) {
|
if (drmCloseBufferHandle(PROTO::linuxDma->mainDeviceFD.get(), handle)) {
|
||||||
LOGM(ERR, "Failed to close dmabuf handle");
|
LOGM(ERR, "Failed to close dmabuf handle");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -303,7 +297,7 @@ CLinuxDMABUFFeedbackResource::CLinuxDMABUFFeedbackResource(SP<CZwpLinuxDmabufFee
|
|||||||
resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
|
resource->setDestroy([this](CZwpLinuxDmabufFeedbackV1* r) { PROTO::linuxDma->destroyResource(this); });
|
||||||
|
|
||||||
auto& formatTable = PROTO::linuxDma->formatTable;
|
auto& formatTable = PROTO::linuxDma->formatTable;
|
||||||
resource->sendFormatTable(formatTable->tableFD, formatTable->tableSize);
|
resource->sendFormatTable(formatTable->tableFD.get(), formatTable->tableSize);
|
||||||
sendDefaultFeedback();
|
sendDefaultFeedback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,9 +466,9 @@ CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const
|
|||||||
|
|
||||||
if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
|
if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
|
||||||
const char* name = device->nodes[DRM_NODE_RENDER];
|
const char* name = device->nodes[DRM_NODE_RENDER];
|
||||||
mainDeviceFD = open(name, O_RDWR | O_CLOEXEC);
|
mainDeviceFD = CFileDescriptor{open(name, O_RDWR | O_CLOEXEC)};
|
||||||
drmFreeDevice(&device);
|
drmFreeDevice(&device);
|
||||||
if (mainDeviceFD < 0) {
|
if (!mainDeviceFD.isValid()) {
|
||||||
LOGM(ERR, "failed to open drm dev, disabling linux dmabuf");
|
LOGM(ERR, "failed to open drm dev, disabling linux dmabuf");
|
||||||
removeGlobal();
|
removeGlobal();
|
||||||
return;
|
return;
|
||||||
@@ -496,7 +490,7 @@ void CLinuxDMABufV1Protocol::resetFormatTable() {
|
|||||||
auto newFormatTable = makeUnique<CDMABUFFormatTable>(formatTable->rendererTranche, formatTable->monitorTranches);
|
auto newFormatTable = makeUnique<CDMABUFFormatTable>(formatTable->rendererTranche, formatTable->monitorTranches);
|
||||||
|
|
||||||
for (auto const& feedback : m_vFeedbacks) {
|
for (auto const& feedback : m_vFeedbacks) {
|
||||||
feedback->resource->sendFormatTable(newFormatTable->tableFD, newFormatTable->tableSize);
|
feedback->resource->sendFormatTable(newFormatTable->tableFD.get(), newFormatTable->tableSize);
|
||||||
if (feedback->lastFeedbackWasScanout) {
|
if (feedback->lastFeedbackWasScanout) {
|
||||||
PHLMONITOR mon;
|
PHLMONITOR mon;
|
||||||
auto HLSurface = CWLSurface::fromResource(feedback->surface);
|
auto HLSurface = CWLSurface::fromResource(feedback->surface);
|
||||||
@@ -519,11 +513,6 @@ void CLinuxDMABufV1Protocol::resetFormatTable() {
|
|||||||
formatTable = std::move(newFormatTable);
|
formatTable = std::move(newFormatTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLinuxDMABufV1Protocol::~CLinuxDMABufV1Protocol() {
|
|
||||||
if (mainDeviceFD >= 0)
|
|
||||||
close(mainDeviceFD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CLinuxDMABufV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
void CLinuxDMABufV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CLinuxDMABUFResource>(makeShared<CZwpLinuxDmabufV1>(client, ver, id)));
|
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CLinuxDMABUFResource>(makeShared<CZwpLinuxDmabufV1>(client, ver, id)));
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include "../helpers/Format.hpp"
|
#include "../helpers/Format.hpp"
|
||||||
#include "../helpers/Monitor.hpp"
|
#include "../helpers/Monitor.hpp"
|
||||||
#include <aquamarine/buffer/Buffer.hpp>
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CDMABuffer;
|
class CDMABuffer;
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
@@ -48,9 +49,9 @@ struct SDMABUFTranche {
|
|||||||
class CDMABUFFormatTable {
|
class CDMABUFFormatTable {
|
||||||
public:
|
public:
|
||||||
CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector<std::pair<PHLMONITORREF, SDMABUFTranche>> tranches);
|
CDMABUFFormatTable(SDMABUFTranche rendererTranche, std::vector<std::pair<PHLMONITORREF, SDMABUFTranche>> tranches);
|
||||||
~CDMABUFFormatTable();
|
~CDMABUFFormatTable() = default;
|
||||||
|
|
||||||
int tableFD = -1;
|
Hyprutils::OS::CFileDescriptor tableFD;
|
||||||
size_t tableSize = 0;
|
size_t tableSize = 0;
|
||||||
SDMABUFTranche rendererTranche;
|
SDMABUFTranche rendererTranche;
|
||||||
std::vector<std::pair<PHLMONITORREF, SDMABUFTranche>> monitorTranches;
|
std::vector<std::pair<PHLMONITORREF, SDMABUFTranche>> monitorTranches;
|
||||||
@@ -107,7 +108,7 @@ class CLinuxDMABUFResource {
|
|||||||
class CLinuxDMABufV1Protocol : public IWaylandProtocol {
|
class CLinuxDMABufV1Protocol : public IWaylandProtocol {
|
||||||
public:
|
public:
|
||||||
CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name);
|
CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||||
~CLinuxDMABufV1Protocol();
|
~CLinuxDMABufV1Protocol() = default;
|
||||||
|
|
||||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||||
void updateScanoutTranche(SP<CWLSurfaceResource> surface, PHLMONITOR pMonitor);
|
void updateScanoutTranche(SP<CWLSurfaceResource> surface, PHLMONITOR pMonitor);
|
||||||
@@ -128,7 +129,7 @@ class CLinuxDMABufV1Protocol : public IWaylandProtocol {
|
|||||||
|
|
||||||
UP<CDMABUFFormatTable> formatTable;
|
UP<CDMABUFFormatTable> formatTable;
|
||||||
dev_t mainDevice;
|
dev_t mainDevice;
|
||||||
int mainDeviceFD = -1;
|
Hyprutils::OS::CFileDescriptor mainDeviceFD;
|
||||||
|
|
||||||
friend class CLinuxDMABUFResource;
|
friend class CLinuxDMABUFResource;
|
||||||
friend class CLinuxDMABUFFeedbackResource;
|
friend class CLinuxDMABUFFeedbackResource;
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "../managers/SeatManager.hpp"
|
#include "../managers/SeatManager.hpp"
|
||||||
#include "core/Seat.hpp"
|
#include "core/Seat.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CPrimarySelectionOffer::CPrimarySelectionOffer(SP<CZwpPrimarySelectionOfferV1> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
CPrimarySelectionOffer::CPrimarySelectionOffer(SP<CZwpPrimarySelectionOfferV1> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -12,21 +13,20 @@ CPrimarySelectionOffer::CPrimarySelectionOffer(SP<CZwpPrimarySelectionOfferV1> r
|
|||||||
resource->setOnDestroy([this](CZwpPrimarySelectionOfferV1* r) { PROTO::primarySelection->destroyResource(this); });
|
resource->setOnDestroy([this](CZwpPrimarySelectionOfferV1* r) { PROTO::primarySelection->destroyResource(this); });
|
||||||
|
|
||||||
resource->setReceive([this](CZwpPrimarySelectionOfferV1* r, const char* mime, int32_t fd) {
|
resource->setReceive([this](CZwpPrimarySelectionOfferV1* r, const char* mime, int32_t fd) {
|
||||||
|
CFileDescriptor sendFd{fd};
|
||||||
if (!source) {
|
if (!source) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead) {
|
if (dead) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get());
|
LOGM(LOG, "Offer {:x} asks to send data from source {:x}", (uintptr_t)this, (uintptr_t)source.get());
|
||||||
|
|
||||||
source->send(mime, fd);
|
source->send(mime, std::move(sendFd));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,15 +78,13 @@ std::vector<std::string> CPrimarySelectionSource::mimes() {
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrimarySelectionSource::send(const std::string& mime, uint32_t fd) {
|
void CPrimarySelectionSource::send(const std::string& mime, CFileDescriptor fd) {
|
||||||
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
||||||
LOGM(ERR, "Compositor/App bug: CPrimarySelectionSource::sendAskSend with non-existent mime");
|
LOGM(ERR, "Compositor/App bug: CPrimarySelectionSource::sendAskSend with non-existent mime");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource->sendSend(mime.c_str(), fd);
|
resource->sendSend(mime.c_str(), fd.get());
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrimarySelectionSource::accepted(const std::string& mime) {
|
void CPrimarySelectionSource::accepted(const std::string& mime) {
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "primary-selection-unstable-v1.hpp"
|
#include "primary-selection-unstable-v1.hpp"
|
||||||
#include "types/DataDevice.hpp"
|
#include "types/DataDevice.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CPrimarySelectionOffer;
|
class CPrimarySelectionOffer;
|
||||||
class CPrimarySelectionSource;
|
class CPrimarySelectionSource;
|
||||||
@@ -38,7 +39,7 @@ class CPrimarySelectionSource : public IDataSource {
|
|||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes();
|
virtual std::vector<std::string> mimes();
|
||||||
virtual void send(const std::string& mime, uint32_t fd);
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd);
|
||||||
virtual void accepted(const std::string& mime);
|
virtual void accepted(const std::string& mime);
|
||||||
virtual void cancelled();
|
virtual void cancelled();
|
||||||
virtual void error(uint32_t code, const std::string& msg);
|
virtual void error(uint32_t code, const std::string& msg);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "SecurityContext.hpp"
|
#include "SecurityContext.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
static int onListenFdEvent(int fd, uint32_t mask, void* data) {
|
static int onListenFdEvent(int fd, uint32_t mask, void* data) {
|
||||||
auto sc = (CSecurityContext*)data;
|
auto sc = (CSecurityContext*)data;
|
||||||
@@ -14,8 +15,8 @@ static int onCloseFdEvent(int fd, uint32_t mask, void* data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SP<CSecurityContextSandboxedClient> CSecurityContextSandboxedClient::create(int clientFD_) {
|
SP<CSecurityContextSandboxedClient> CSecurityContextSandboxedClient::create(CFileDescriptor clientFD_) {
|
||||||
auto p = SP<CSecurityContextSandboxedClient>(new CSecurityContextSandboxedClient(clientFD_));
|
auto p = SP<CSecurityContextSandboxedClient>(new CSecurityContextSandboxedClient(std::move(clientFD_)));
|
||||||
if (!p->client)
|
if (!p->client)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return p;
|
return p;
|
||||||
@@ -27,8 +28,8 @@ static void onSecurityContextClientDestroy(wl_listener* l, void* d) {
|
|||||||
client->onDestroy();
|
client->onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_) : clientFD(clientFD_) {
|
CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(CFileDescriptor clientFD_) : clientFD(std::move(clientFD_)) {
|
||||||
client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD);
|
client = wl_client_create(g_pCompositor->m_sWLDisplay, clientFD.get());
|
||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -41,7 +42,6 @@ CSecurityContextSandboxedClient::CSecurityContextSandboxedClient(int clientFD_)
|
|||||||
CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() {
|
CSecurityContextSandboxedClient::~CSecurityContextSandboxedClient() {
|
||||||
wl_list_remove(&destroyListener.listener.link);
|
wl_list_remove(&destroyListener.listener.link);
|
||||||
wl_list_init(&destroyListener.listener.link);
|
wl_list_init(&destroyListener.listener.link);
|
||||||
close(clientFD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSecurityContextSandboxedClient::onDestroy() {
|
void CSecurityContextSandboxedClient::onDestroy() {
|
||||||
@@ -113,8 +113,8 @@ CSecurityContext::CSecurityContext(SP<CWpSecurityContextV1> resource_, int liste
|
|||||||
|
|
||||||
LOGM(LOG, "security_context at 0x{:x} commits", (uintptr_t)this);
|
LOGM(LOG, "security_context at 0x{:x} commits", (uintptr_t)this);
|
||||||
|
|
||||||
listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD, WL_EVENT_READABLE, ::onListenFdEvent, this);
|
listenSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, listenFD.get(), WL_EVENT_READABLE, ::onListenFdEvent, this);
|
||||||
closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD, 0, ::onCloseFdEvent, this);
|
closeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, closeFD.get(), 0, ::onCloseFdEvent, this);
|
||||||
|
|
||||||
if (!listenSource || !closeSource) {
|
if (!listenSource || !closeSource) {
|
||||||
r->noMemory();
|
r->noMemory();
|
||||||
@@ -144,16 +144,15 @@ void CSecurityContext::onListen(uint32_t mask) {
|
|||||||
if (!(mask & WL_EVENT_READABLE))
|
if (!(mask & WL_EVENT_READABLE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int clientFD = accept(listenFD, nullptr, nullptr);
|
CFileDescriptor clientFD{accept(listenFD.get(), nullptr, nullptr)};
|
||||||
if UNLIKELY (clientFD < 0) {
|
if UNLIKELY (!clientFD.isValid()) {
|
||||||
LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this);
|
LOGM(ERR, "security_context at 0x{:x} couldn't accept", (uintptr_t)this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newClient = CSecurityContextSandboxedClient::create(clientFD);
|
auto newClient = CSecurityContextSandboxedClient::create(std::move(clientFD));
|
||||||
if UNLIKELY (!newClient) {
|
if UNLIKELY (!newClient) {
|
||||||
LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this);
|
LOGM(ERR, "security_context at 0x{:x} couldn't create a client", (uintptr_t)this);
|
||||||
close(clientFD);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,19 +4,20 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "security-context-v1.hpp"
|
#include "security-context-v1.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CSecurityContext {
|
class CSecurityContext {
|
||||||
public:
|
public:
|
||||||
CSecurityContext(SP<CWpSecurityContextV1> resource_, int listenFD_, int closeFD_);
|
CSecurityContext(SP<CWpSecurityContextV1> resource_, int listenFD_, int closeFD_);
|
||||||
~CSecurityContext();
|
~CSecurityContext();
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
std::string sandboxEngine, appID, instanceID;
|
std::string sandboxEngine, appID, instanceID;
|
||||||
int listenFD = -1, closeFD = -1;
|
Hyprutils::OS::CFileDescriptor listenFD, closeFD;
|
||||||
|
|
||||||
void onListen(uint32_t mask);
|
void onListen(uint32_t mask);
|
||||||
void onClose(uint32_t mask);
|
void onClose(uint32_t mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CWpSecurityContextV1> resource;
|
SP<CWpSecurityContextV1> resource;
|
||||||
@@ -44,7 +45,7 @@ struct SCSecurityContextSandboxedClientDestroyWrapper {
|
|||||||
|
|
||||||
class CSecurityContextSandboxedClient {
|
class CSecurityContextSandboxedClient {
|
||||||
public:
|
public:
|
||||||
static SP<CSecurityContextSandboxedClient> create(int clientFD);
|
static SP<CSecurityContextSandboxedClient> create(Hyprutils::OS::CFileDescriptor clientFD);
|
||||||
~CSecurityContextSandboxedClient();
|
~CSecurityContextSandboxedClient();
|
||||||
|
|
||||||
void onDestroy();
|
void onDestroy();
|
||||||
@@ -52,10 +53,10 @@ class CSecurityContextSandboxedClient {
|
|||||||
SCSecurityContextSandboxedClientDestroyWrapper destroyListener;
|
SCSecurityContextSandboxedClientDestroyWrapper destroyListener;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CSecurityContextSandboxedClient(int clientFD_);
|
CSecurityContextSandboxedClient(Hyprutils::OS::CFileDescriptor clientFD_);
|
||||||
|
|
||||||
wl_client* client = nullptr;
|
wl_client* client = nullptr;
|
||||||
int clientFD = -1;
|
Hyprutils::OS::CFileDescriptor clientFD;
|
||||||
|
|
||||||
friend class CSecurityContextProtocol;
|
friend class CSecurityContextProtocol;
|
||||||
friend class CSecurityContext;
|
friend class CSecurityContext;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "VirtualKeyboard.hpp"
|
#include "VirtualKeyboard.hpp"
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include "../devices/IKeyboard.hpp"
|
#include "../devices/IKeyboard.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
|
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -51,20 +52,19 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
|||||||
});
|
});
|
||||||
|
|
||||||
resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) {
|
resource->setKeymap([this](CZwpVirtualKeyboardV1* r, uint32_t fmt, int32_t fd, uint32_t len) {
|
||||||
auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
auto xkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
CFileDescriptor keymapFd{fd};
|
||||||
if UNLIKELY (!xkbContext) {
|
if UNLIKELY (!xkbContext) {
|
||||||
LOGM(ERR, "xkbContext creation failed");
|
LOGM(ERR, "xkbContext creation failed");
|
||||||
r->noMemory();
|
r->noMemory();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
auto keymapData = mmap(nullptr, len, PROT_READ, MAP_PRIVATE, keymapFd.get(), 0);
|
||||||
if UNLIKELY (keymapData == MAP_FAILED) {
|
if UNLIKELY (keymapData == MAP_FAILED) {
|
||||||
LOGM(ERR, "keymapData alloc failed");
|
LOGM(ERR, "keymapData alloc failed");
|
||||||
xkb_context_unref(xkbContext);
|
xkb_context_unref(xkbContext);
|
||||||
r->noMemory();
|
r->noMemory();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,6 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
|||||||
LOGM(ERR, "xkbKeymap creation failed");
|
LOGM(ERR, "xkbKeymap creation failed");
|
||||||
xkb_context_unref(xkbContext);
|
xkb_context_unref(xkbContext);
|
||||||
r->noMemory();
|
r->noMemory();
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +85,6 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
|||||||
|
|
||||||
xkb_keymap_unref(xkbKeymap);
|
xkb_keymap_unref(xkbKeymap);
|
||||||
xkb_context_unref(xkbContext);
|
xkb_context_unref(xkbContext);
|
||||||
close(fd);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
name = "hl-virtual-keyboard";
|
name = "hl-virtual-keyboard";
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "virtual-keyboard-unstable-v1.hpp"
|
#include "virtual-keyboard-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CVirtualKeyboardV1Resource {
|
class CVirtualKeyboardV1Resource {
|
||||||
public:
|
public:
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
#include "../../managers/HookSystemManager.hpp"
|
#include "../../managers/HookSystemManager.hpp"
|
||||||
#include "../../helpers/Monitor.hpp"
|
#include "../../helpers/Monitor.hpp"
|
||||||
#include "../../render/Renderer.hpp"
|
#include "../../render/Renderer.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataSource> source_) : source(source_), resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
@@ -39,15 +40,14 @@ CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataS
|
|||||||
});
|
});
|
||||||
|
|
||||||
resource->setReceive([this](CWlDataOffer* r, const char* mime, uint32_t fd) {
|
resource->setReceive([this](CWlDataOffer* r, const char* mime, uint32_t fd) {
|
||||||
|
CFileDescriptor sendFd{fd};
|
||||||
if (!source) {
|
if (!source) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
LOGM(WARN, "Possible bug: Receive on an offer w/o a source");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead) {
|
if (dead) {
|
||||||
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
LOGM(WARN, "Possible bug: Receive on an offer that's dead");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataS
|
|||||||
source->accepted(mime ? mime : "");
|
source->accepted(mime ? mime : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
source->send(mime ? mime : "", fd);
|
source->send(mime ? mime : "", std::move(sendFd));
|
||||||
|
|
||||||
recvd = true;
|
recvd = true;
|
||||||
|
|
||||||
@@ -182,15 +182,13 @@ std::vector<std::string> CWLDataSourceResource::mimes() {
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLDataSourceResource::send(const std::string& mime, uint32_t fd) {
|
void CWLDataSourceResource::send(const std::string& mime, CFileDescriptor fd) {
|
||||||
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
if (std::find(mimeTypes.begin(), mimeTypes.end(), mime) == mimeTypes.end()) {
|
||||||
LOGM(ERR, "Compositor/App bug: CWLDataSourceResource::sendAskSend with non-existent mime");
|
LOGM(ERR, "Compositor/App bug: CWLDataSourceResource::sendAskSend with non-existent mime");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource->sendSend(mime.c_str(), fd);
|
resource->sendSend(mime.c_str(), fd.get());
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLDataSourceResource::cancelled() {
|
void CWLDataSourceResource::cancelled() {
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "../../helpers/signal/Signal.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
#include "../../helpers/math/Math.hpp"
|
#include "../../helpers/math/Math.hpp"
|
||||||
#include "../types/DataDevice.hpp"
|
#include "../types/DataDevice.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CWLDataDeviceResource;
|
class CWLDataDeviceResource;
|
||||||
class CWLDataDeviceManagerResource;
|
class CWLDataDeviceManagerResource;
|
||||||
@@ -63,7 +64,7 @@ class CWLDataSourceResource : public IDataSource {
|
|||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes();
|
virtual std::vector<std::string> mimes();
|
||||||
virtual void send(const std::string& mime, uint32_t fd);
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd);
|
||||||
virtual void accepted(const std::string& mime);
|
virtual void accepted(const std::string& mime);
|
||||||
virtual void cancelled();
|
virtual void cancelled();
|
||||||
virtual bool hasDnd();
|
virtual bool hasDnd();
|
||||||
|
@@ -321,35 +321,18 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
|
|||||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD))
|
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string_view keymap;
|
std::string_view keymap = keyboard->xkbKeymapString;
|
||||||
int fd;
|
Hyprutils::OS::CFileDescriptor& fd = keyboard->xkbKeymapFD;
|
||||||
uint32_t size;
|
uint32_t size = keyboard->xkbKeymapString.length() + 1;
|
||||||
if (keyboard) {
|
|
||||||
keymap = keyboard->xkbKeymapString;
|
|
||||||
fd = keyboard->xkbKeymapFD;
|
|
||||||
size = keyboard->xkbKeymapString.length() + 1;
|
|
||||||
} else {
|
|
||||||
fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0) {
|
|
||||||
LOGM(ERR, "Failed to open /dev/null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keymap == lastKeymap) {
|
if (keymap == lastKeymap)
|
||||||
if (!keyboard)
|
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
lastKeymap = keymap;
|
lastKeymap = keymap;
|
||||||
|
|
||||||
const wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP;
|
const wl_keyboard_keymap_format format = keyboard ? WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 : WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP;
|
||||||
|
|
||||||
resource->sendKeymap(format, fd, size);
|
resource->sendKeymap(format, fd.get(), size);
|
||||||
|
|
||||||
if (!keyboard)
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) {
|
void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) {
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "../types/WLBuffer.hpp"
|
#include "../types/WLBuffer.hpp"
|
||||||
#include "../../helpers/Format.hpp"
|
#include "../../helpers/Format.hpp"
|
||||||
#include "../../render/Renderer.hpp"
|
#include "../../render/Renderer.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CWLSHMBuffer::CWLSHMBuffer(SP<CWLSHMPoolResource> pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) {
|
CWLSHMBuffer::CWLSHMBuffer(SP<CWLSHMPoolResource> pool_, uint32_t id, int32_t offset_, const Vector2D& size_, int32_t stride_, uint32_t fmt_) {
|
||||||
if UNLIKELY (!pool_->pool->data)
|
if UNLIKELY (!pool_->pool->data)
|
||||||
@@ -51,7 +52,7 @@ bool CWLSHMBuffer::isSynchronous() {
|
|||||||
Aquamarine::SSHMAttrs CWLSHMBuffer::shm() {
|
Aquamarine::SSHMAttrs CWLSHMBuffer::shm() {
|
||||||
Aquamarine::SSHMAttrs attrs;
|
Aquamarine::SSHMAttrs attrs;
|
||||||
attrs.success = true;
|
attrs.success = true;
|
||||||
attrs.fd = pool->fd;
|
attrs.fd = pool->fd.get();
|
||||||
attrs.format = NFormatUtils::shmToDRM(fmt);
|
attrs.format = NFormatUtils::shmToDRM(fmt);
|
||||||
attrs.size = size;
|
attrs.size = size;
|
||||||
attrs.stride = stride;
|
attrs.stride = stride;
|
||||||
@@ -75,13 +76,12 @@ void CWLSHMBuffer::update(const CRegion& damage) {
|
|||||||
texture->update(NFormatUtils::shmToDRM(fmt), (uint8_t*)pool->data + offset, stride, damage);
|
texture->update(NFormatUtils::shmToDRM(fmt), (uint8_t*)pool->data + offset, stride, damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSHMPool::CSHMPool(int fd_, size_t size_) : fd(fd_), size(size_), data(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) {
|
CSHMPool::CSHMPool(CFileDescriptor fd_, size_t size_) : fd(std::move(fd_)), size(size_), data(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSHMPool::~CSHMPool() {
|
CSHMPool::~CSHMPool() {
|
||||||
munmap(data, size);
|
munmap(data, size);
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSHMPool::resize(size_t size_) {
|
void CSHMPool::resize(size_t size_) {
|
||||||
@@ -90,23 +90,23 @@ void CSHMPool::resize(size_t size_) {
|
|||||||
if (data)
|
if (data)
|
||||||
munmap(data, size);
|
munmap(data, size);
|
||||||
size = size_;
|
size = size_;
|
||||||
data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
|
||||||
|
|
||||||
if UNLIKELY (data == MAP_FAILED)
|
if UNLIKELY (data == MAP_FAILED)
|
||||||
LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd);
|
LOGM(ERR, "Couldn't mmap {} bytes from fd {} of shm client", size, fd.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shmIsSizeValid(int fd, size_t size) {
|
static int shmIsSizeValid(CFileDescriptor& fd, size_t size) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if UNLIKELY (fstat(fd, &st) == -1) {
|
if UNLIKELY (fstat(fd.get(), &st) == -1) {
|
||||||
LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd);
|
LOGM(ERR, "Couldn't get stat for fd {} of shm client", fd.get());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (size_t)st.st_size >= size;
|
return (size_t)st.st_size >= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWLSHMPoolResource::CWLSHMPoolResource(SP<CWlShmPool> resource_, int fd_, size_t size_) : resource(resource_) {
|
CWLSHMPoolResource::CWLSHMPoolResource(SP<CWlShmPool> resource_, CFileDescriptor fd_, size_t size_) : resource(resource_) {
|
||||||
if UNLIKELY (!good())
|
if UNLIKELY (!good())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ CWLSHMPoolResource::CWLSHMPoolResource(SP<CWlShmPool> resource_, int fd_, size_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = makeShared<CSHMPool>(fd_, size_);
|
pool = makeShared<CSHMPool>(std::move(fd_), size_);
|
||||||
|
|
||||||
resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); });
|
resource->setDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); });
|
||||||
resource->setOnDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); });
|
resource->setOnDestroy([this](CWlShmPool* r) { PROTO::shm->destroyResource(this); });
|
||||||
@@ -176,7 +176,8 @@ CWLSHMResource::CWLSHMResource(SP<CWlShm> resource_) : resource(resource_) {
|
|||||||
resource->setOnDestroy([this](CWlShm* r) { PROTO::shm->destroyResource(this); });
|
resource->setOnDestroy([this](CWlShm* r) { PROTO::shm->destroyResource(this); });
|
||||||
|
|
||||||
resource->setCreatePool([](CWlShm* r, uint32_t id, int32_t fd, int32_t size) {
|
resource->setCreatePool([](CWlShm* r, uint32_t id, int32_t fd, int32_t size) {
|
||||||
const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared<CWLSHMPoolResource>(makeShared<CWlShmPool>(r->client(), r->version(), id), fd, size));
|
CFileDescriptor poolFd{fd};
|
||||||
|
const auto RESOURCE = PROTO::shm->m_vPools.emplace_back(makeShared<CWLSHMPoolResource>(makeShared<CWlShmPool>(r->client(), r->version(), id), std::move(poolFd), size));
|
||||||
|
|
||||||
if UNLIKELY (!RESOURCE->good()) {
|
if UNLIKELY (!RESOURCE->good()) {
|
||||||
r->noMemory();
|
r->noMemory();
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
- wl_buffer with shm
|
- wl_buffer with shm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "../WaylandProtocol.hpp"
|
#include "../WaylandProtocol.hpp"
|
||||||
@@ -18,14 +20,14 @@ class CWLSHMPoolResource;
|
|||||||
|
|
||||||
class CSHMPool {
|
class CSHMPool {
|
||||||
public:
|
public:
|
||||||
CSHMPool(int fd, size_t size);
|
CSHMPool(Hyprutils::OS::CFileDescriptor fd, size_t size);
|
||||||
~CSHMPool();
|
~CSHMPool();
|
||||||
|
|
||||||
int fd = 0;
|
Hyprutils::OS::CFileDescriptor fd;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
|
|
||||||
void resize(size_t size);
|
void resize(size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWLSHMBuffer : public IHLBuffer {
|
class CWLSHMBuffer : public IHLBuffer {
|
||||||
@@ -57,7 +59,7 @@ class CWLSHMBuffer : public IHLBuffer {
|
|||||||
|
|
||||||
class CWLSHMPoolResource {
|
class CWLSHMPoolResource {
|
||||||
public:
|
public:
|
||||||
CWLSHMPoolResource(SP<CWlShmPool> resource_, int fd, size_t size);
|
CWLSHMPoolResource(SP<CWlShmPool> resource_, Hyprutils::OS::CFileDescriptor fd, size_t size);
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <wayland-server-protocol.h>
|
#include <wayland-server-protocol.h>
|
||||||
#include "../../helpers/memory/Memory.hpp"
|
#include "../../helpers/memory/Memory.hpp"
|
||||||
#include "../../helpers/math/Math.hpp"
|
#include "../../helpers/math/Math.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
class CWLDataOfferResource;
|
class CWLDataOfferResource;
|
||||||
class CX11DataOffer;
|
class CX11DataOffer;
|
||||||
@@ -24,10 +25,10 @@ class IDataSource {
|
|||||||
IDataSource() = default;
|
IDataSource() = default;
|
||||||
virtual ~IDataSource() = default;
|
virtual ~IDataSource() = default;
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes() = 0;
|
virtual std::vector<std::string> mimes() = 0;
|
||||||
virtual void send(const std::string& mime, uint32_t fd) = 0;
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd) = 0;
|
||||||
virtual void accepted(const std::string& mime) = 0;
|
virtual void accepted(const std::string& mime) = 0;
|
||||||
virtual void cancelled() = 0;
|
virtual void cancelled() = 0;
|
||||||
virtual bool hasDnd();
|
virtual bool hasDnd();
|
||||||
virtual bool dndDone();
|
virtual bool dndDone();
|
||||||
virtual void sendDndFinished();
|
virtual void sendDndFinished();
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
const std::vector<const char*> ASSET_PATHS = {
|
const std::vector<const char*> ASSET_PATHS = {
|
||||||
#ifdef DATAROOTDIR
|
#ifdef DATAROOTDIR
|
||||||
@@ -301,11 +302,11 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_iDRMFD(g_pCompositor->m_iDRMFD) {
|
|||||||
Debug::log(WARN, "EGL: EXT_platform_device or EGL_EXT_device_query not supported, using gbm");
|
Debug::log(WARN, "EGL: EXT_platform_device or EGL_EXT_device_query not supported, using gbm");
|
||||||
if (EGLEXTENSIONS.contains("KHR_platform_gbm")) {
|
if (EGLEXTENSIONS.contains("KHR_platform_gbm")) {
|
||||||
success = true;
|
success = true;
|
||||||
m_iGBMFD = openRenderNode(m_iDRMFD);
|
m_iGBMFD = CFileDescriptor{openRenderNode(m_iDRMFD)};
|
||||||
if (m_iGBMFD < 0)
|
if (!m_iGBMFD.isValid())
|
||||||
RASSERT(false, "Couldn't open a gbm fd");
|
RASSERT(false, "Couldn't open a gbm fd");
|
||||||
|
|
||||||
m_pGbmDevice = gbm_create_device(m_iGBMFD);
|
m_pGbmDevice = gbm_create_device(m_iGBMFD.get());
|
||||||
if (!m_pGbmDevice)
|
if (!m_pGbmDevice)
|
||||||
RASSERT(false, "Couldn't open a gbm device");
|
RASSERT(false, "Couldn't open a gbm device");
|
||||||
|
|
||||||
@@ -371,9 +372,6 @@ CHyprOpenGLImpl::~CHyprOpenGLImpl() {
|
|||||||
|
|
||||||
if (m_pGbmDevice)
|
if (m_pGbmDevice)
|
||||||
gbm_device_destroy(m_pGbmDevice);
|
gbm_device_destroy(m_pGbmDevice);
|
||||||
|
|
||||||
if (m_iGBMFD >= 0)
|
|
||||||
close(m_iGBMFD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::vector<uint64_t>> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
std::optional<std::vector<uint64_t>> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
||||||
@@ -2954,29 +2952,28 @@ std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
|||||||
return drmFormats;
|
return drmFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(CFileDescriptor fenceFD) {
|
||||||
std::vector<EGLint> attribs;
|
std::vector<EGLint> attribs;
|
||||||
int dupFd = -1;
|
CFileDescriptor dupFd;
|
||||||
if (fenceFD > 0) {
|
if (fenceFD.isValid()) {
|
||||||
dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0);
|
dupFd = fenceFD.duplicate();
|
||||||
if (dupFd < 0) {
|
if (!dupFd.isValid()) {
|
||||||
Debug::log(ERR, "createEGLSync: dup failed");
|
Debug::log(ERR, "createEGLSync: dup failed");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// reserve number of elements to avoid reallocations
|
// reserve number of elements to avoid reallocations
|
||||||
attribs.reserve(3);
|
attribs.reserve(3);
|
||||||
attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
|
attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
|
||||||
attribs.push_back(dupFd);
|
attribs.push_back(dupFd.get());
|
||||||
attribs.push_back(EGL_NONE);
|
attribs.push_back(EGL_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
|
EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
|
||||||
if (sync == EGL_NO_SYNC_KHR) {
|
if (sync == EGL_NO_SYNC_KHR) {
|
||||||
Debug::log(ERR, "eglCreateSyncKHR failed");
|
Debug::log(ERR, "eglCreateSyncKHR failed");
|
||||||
if (dupFd >= 0)
|
|
||||||
close(dupFd);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
} else
|
||||||
|
dupFd.take(); // eglCreateSyncKHR only takes ownership on success
|
||||||
|
|
||||||
// we need to flush otherwise we might not get a valid fd
|
// we need to flush otherwise we might not get a valid fd
|
||||||
glFlush();
|
glFlush();
|
||||||
@@ -2989,19 +2986,18 @@ SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
|||||||
|
|
||||||
auto eglsync = SP<CEGLSync>(new CEGLSync);
|
auto eglsync = SP<CEGLSync>(new CEGLSync);
|
||||||
eglsync->sync = sync;
|
eglsync->sync = sync;
|
||||||
eglsync->m_iFd = fd;
|
eglsync->m_iFd = CFileDescriptor{fd};
|
||||||
return eglsync;
|
return eglsync;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprOpenGLImpl::waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point) {
|
bool CHyprOpenGLImpl::waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point) {
|
||||||
int fd = timeline->exportAsSyncFileFD(point);
|
auto fd = timeline->exportAsSyncFileFD(point);
|
||||||
if (fd < 0) {
|
if (!fd.isValid()) {
|
||||||
Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline");
|
Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sync = g_pHyprOpenGL->createEGLSync(fd);
|
auto sync = g_pHyprOpenGL->createEGLSync(std::move(fd));
|
||||||
close(fd);
|
|
||||||
if (!sync) {
|
if (!sync) {
|
||||||
Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline");
|
Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline");
|
||||||
return false;
|
return false;
|
||||||
@@ -3082,12 +3078,9 @@ CEGLSync::~CEGLSync() {
|
|||||||
|
|
||||||
if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE)
|
if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE)
|
||||||
Debug::log(ERR, "eglDestroySyncKHR failed");
|
Debug::log(ERR, "eglDestroySyncKHR failed");
|
||||||
|
|
||||||
if (m_iFd >= 0)
|
|
||||||
close(m_iFd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CEGLSync::fd() {
|
CFileDescriptor& CEGLSync::fd() {
|
||||||
return m_iFd;
|
return m_iFd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
#include <aquamarine/buffer/Buffer.hpp>
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
#include "../debug/TracyDefines.hpp"
|
#include "../debug/TracyDefines.hpp"
|
||||||
|
|
||||||
@@ -146,15 +147,15 @@ class CEGLSync {
|
|||||||
public:
|
public:
|
||||||
~CEGLSync();
|
~CEGLSync();
|
||||||
|
|
||||||
EGLSyncKHR sync = nullptr;
|
EGLSyncKHR sync = nullptr;
|
||||||
|
|
||||||
int fd();
|
Hyprutils::OS::CFileDescriptor& fd();
|
||||||
bool wait();
|
bool wait();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CEGLSync() = default;
|
CEGLSync() = default;
|
||||||
|
|
||||||
int m_iFd = -1;
|
Hyprutils::OS::CFileDescriptor m_iFd;
|
||||||
|
|
||||||
friend class CHyprOpenGLImpl;
|
friend class CHyprOpenGLImpl;
|
||||||
};
|
};
|
||||||
@@ -228,14 +229,14 @@ class CHyprOpenGLImpl {
|
|||||||
uint32_t getPreferredReadFormat(PHLMONITOR pMonitor);
|
uint32_t getPreferredReadFormat(PHLMONITOR pMonitor);
|
||||||
std::vector<SDRMFormat> getDRMFormats();
|
std::vector<SDRMFormat> getDRMFormats();
|
||||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||||
SP<CEGLSync> createEGLSync(int fenceFD);
|
SP<CEGLSync> createEGLSync(Hyprutils::OS::CFileDescriptor fenceFD);
|
||||||
bool waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point);
|
bool waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point);
|
||||||
|
|
||||||
SCurrentRenderData m_RenderData;
|
SCurrentRenderData m_RenderData;
|
||||||
|
|
||||||
GLint m_iCurrentOutputFb = 0;
|
GLint m_iCurrentOutputFb = 0;
|
||||||
|
|
||||||
int m_iGBMFD = -1;
|
Hyprutils::OS::CFileDescriptor m_iGBMFD;
|
||||||
gbm_device* m_pGbmDevice = nullptr;
|
gbm_device* m_pGbmDevice = nullptr;
|
||||||
EGLContext m_pEglContext = nullptr;
|
EGLContext m_pEglContext = nullptr;
|
||||||
EGLDisplay m_pEglDisplay = nullptr;
|
EGLDisplay m_pEglDisplay = nullptr;
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
using namespace Hyprutils::Utils;
|
using namespace Hyprutils::Utils;
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
@@ -1462,10 +1463,10 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, Aquamar
|
|||||||
bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
||||||
// apply timelines for explicit sync
|
// apply timelines for explicit sync
|
||||||
// save inFD otherwise reset will reset it
|
// save inFD otherwise reset will reset it
|
||||||
auto inFD = pMonitor->output->state->state().explicitInFence;
|
CFileDescriptor inFD{pMonitor->output->state->state().explicitInFence};
|
||||||
pMonitor->output->state->resetExplicitFences();
|
pMonitor->output->state->resetExplicitFences();
|
||||||
if (inFD >= 0)
|
if (inFD.isValid())
|
||||||
pMonitor->output->state->setExplicitInFence(inFD);
|
pMonitor->output->state->setExplicitInFence(inFD.get());
|
||||||
|
|
||||||
static auto PHDR = CConfigValue<Hyprlang::INT>("experimental:hdr");
|
static auto PHDR = CConfigValue<Hyprlang::INT>("experimental:hdr");
|
||||||
|
|
||||||
@@ -1515,7 +1516,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
|||||||
|
|
||||||
bool ok = pMonitor->state.commit();
|
bool ok = pMonitor->state.commit();
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (inFD >= 0) {
|
if (inFD.isValid()) {
|
||||||
Debug::log(TRACE, "Monitor state commit failed, retrying without a fence");
|
Debug::log(TRACE, "Monitor state commit failed, retrying without a fence");
|
||||||
pMonitor->output->state->resetExplicitFences();
|
pMonitor->output->state->resetExplicitFences();
|
||||||
ok = pMonitor->state.commit();
|
ok = pMonitor->state.commit();
|
||||||
@@ -1534,11 +1535,8 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
|||||||
if (!explicitOptions.explicitEnabled)
|
if (!explicitOptions.explicitEnabled)
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
if (inFD >= 0)
|
|
||||||
close(inFD);
|
|
||||||
|
|
||||||
Debug::log(TRACE, "Explicit: {} presented", explicitPresented.size());
|
Debug::log(TRACE, "Explicit: {} presented", explicitPresented.size());
|
||||||
auto sync = g_pHyprOpenGL->createEGLSync(-1);
|
auto sync = g_pHyprOpenGL->createEGLSync({});
|
||||||
|
|
||||||
if (!sync)
|
if (!sync)
|
||||||
Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed");
|
Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed");
|
||||||
@@ -2272,7 +2270,7 @@ void CHyprRenderer::endRender() {
|
|||||||
auto explicitOptions = getExplicitSyncSettings();
|
auto explicitOptions = getExplicitSyncSettings();
|
||||||
|
|
||||||
if (PMONITOR->inTimeline && explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) {
|
if (PMONITOR->inTimeline && explicitOptions.explicitEnabled && explicitOptions.explicitKMSEnabled) {
|
||||||
auto sync = g_pHyprOpenGL->createEGLSync(-1);
|
auto sync = g_pHyprOpenGL->createEGLSync({});
|
||||||
if (!sync) {
|
if (!sync) {
|
||||||
Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender");
|
Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender");
|
||||||
return;
|
return;
|
||||||
@@ -2285,12 +2283,12 @@ void CHyprRenderer::endRender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto fd = PMONITOR->inTimeline->exportAsSyncFileFD(PMONITOR->commitSeq);
|
auto fd = PMONITOR->inTimeline->exportAsSyncFileFD(PMONITOR->commitSeq);
|
||||||
if (fd <= 0) {
|
if (!fd.isValid()) {
|
||||||
Debug::log(ERR, "renderer: couldn't export from sync timeline in endRender");
|
Debug::log(ERR, "renderer: couldn't export from sync timeline in endRender");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PMONITOR->output->state->setExplicitInFence(fd);
|
PMONITOR->output->state->setExplicitInFence(fd.take());
|
||||||
} else {
|
} else {
|
||||||
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
||||||
glFinish();
|
glFinish();
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
#include "../managers/XWaylandManager.hpp"
|
#include "../managers/XWaylandManager.hpp"
|
||||||
#include "../desktop/WLSurface.hpp"
|
#include "../desktop/WLSurface.hpp"
|
||||||
|
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#ifndef NO_XWAYLAND
|
#ifndef NO_XWAYLAND
|
||||||
static xcb_atom_t dndActionToAtom(uint32_t actions) {
|
static xcb_atom_t dndActionToAtom(uint32_t actions) {
|
||||||
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
||||||
@@ -172,7 +174,7 @@ std::vector<std::string> CX11DataSource::mimes() {
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CX11DataSource::send(const std::string& mime, uint32_t fd) {
|
void CX11DataSource::send(const std::string& mime, CFileDescriptor fd) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "../protocols/types/DataDevice.hpp"
|
#include "../protocols/types/DataDevice.hpp"
|
||||||
#include <wayland-server-protocol.h>
|
#include <wayland-server-protocol.h>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
#define XDND_VERSION 5
|
#define XDND_VERSION 5
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class CX11DataSource : public IDataSource {
|
|||||||
~CX11DataSource() = default;
|
~CX11DataSource() = default;
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes();
|
virtual std::vector<std::string> mimes();
|
||||||
virtual void send(const std::string& mime, uint32_t fd);
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd);
|
||||||
virtual void accepted(const std::string& mime);
|
virtual void accepted(const std::string& mime);
|
||||||
virtual void cancelled();
|
virtual void cancelled();
|
||||||
virtual bool hasDnd();
|
virtual bool hasDnd();
|
||||||
|
@@ -24,70 +24,41 @@
|
|||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../managers/CursorManager.hpp"
|
#include "../managers/CursorManager.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
constexpr int SOCKET_DIR_PERMISSIONS = 0755;
|
constexpr int SOCKET_DIR_PERMISSIONS = 0755;
|
||||||
constexpr int SOCKET_BACKLOG = 1;
|
constexpr int SOCKET_BACKLOG = 1;
|
||||||
constexpr int MAX_SOCKET_RETRIES = 32;
|
constexpr int MAX_SOCKET_RETRIES = 32;
|
||||||
constexpr int LOCK_FILE_MODE = 0444;
|
constexpr int LOCK_FILE_MODE = 0444;
|
||||||
|
|
||||||
static bool setCloseOnExec(int fd, bool cloexec) {
|
static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t path_size) {
|
||||||
int flags = fcntl(fd, F_GETFD);
|
socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1;
|
||||||
if (flags == -1) {
|
CFileDescriptor fd{socket(AF_UNIX, SOCK_STREAM, 0)};
|
||||||
Debug::log(ERR, "fcntl failed");
|
if (!fd.isValid()) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cloexec)
|
|
||||||
flags = flags | FD_CLOEXEC;
|
|
||||||
else
|
|
||||||
flags = flags & ~FD_CLOEXEC;
|
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFD, flags) == -1) {
|
|
||||||
Debug::log(ERR, "fcntl failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanUpSocket(int fd, const char* path) {
|
|
||||||
close(fd);
|
|
||||||
if (path[0])
|
|
||||||
unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void closeSocketSafely(int& fd) {
|
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int createSocket(struct sockaddr_un* addr, size_t path_size) {
|
|
||||||
socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1;
|
|
||||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (fd < 0) {
|
|
||||||
Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
||||||
return -1;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setCloseOnExec(fd, true)) {
|
if (!fd.setFlags(fd.getFlags() | FD_CLOEXEC)) {
|
||||||
close(fd);
|
return {};
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr->sun_path[0])
|
if (addr->sun_path[0])
|
||||||
unlink(addr->sun_path);
|
unlink(addr->sun_path);
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr*)addr, size) < 0) {
|
if (bind(fd.get(), (struct sockaddr*)addr, size) < 0) {
|
||||||
Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
||||||
cleanUpSocket(fd, addr->sun_path);
|
if (addr->sun_path[0])
|
||||||
return -1;
|
unlink(addr->sun_path);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(fd, SOCKET_BACKLOG) < 0) {
|
if (listen(fd.get(), SOCKET_BACKLOG) < 0) {
|
||||||
Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
|
||||||
cleanUpSocket(fd, addr->sun_path);
|
if (addr->sun_path[0])
|
||||||
return -1;
|
unlink(addr->sun_path);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -141,7 +112,7 @@ static std::string getSocketPath(int display, bool isLinux) {
|
|||||||
return std::format("/tmp/.X11-unix/X{}_", display);
|
return std::format("/tmp/.X11-unix/X{}_", display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool openSockets(std::array<int, 2>& sockets, int display) {
|
static bool openSockets(std::array<CFileDescriptor, 2>& sockets, int display) {
|
||||||
if (!ensureSocketDirExists())
|
if (!ensureSocketDirExists())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -151,17 +122,16 @@ static bool openSockets(std::array<int, 2>& sockets, int display) {
|
|||||||
path = getSocketPath(display, false);
|
path = getSocketPath(display, false);
|
||||||
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
|
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
|
||||||
|
|
||||||
sockets[0] = createSocket(&addr, path.length());
|
sockets[0] = CFileDescriptor{createSocket(&addr, path.length())};
|
||||||
if (sockets[0] < 0)
|
if (!sockets[0].isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
path = getSocketPath(display, true);
|
path = getSocketPath(display, true);
|
||||||
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
|
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
|
||||||
|
|
||||||
sockets[1] = createSocket(&addr, path.length());
|
sockets[1] = CFileDescriptor{createSocket(&addr, path.length())};
|
||||||
if (sockets[1] < 0) {
|
if (!sockets[1].isValid()) {
|
||||||
close(sockets[0]);
|
sockets[0].reset();
|
||||||
sockets[0] = -1;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +144,8 @@ static void startServer(void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int xwaylandReady(int fd, uint32_t mask, void* data) {
|
static int xwaylandReady(int fd, uint32_t mask, void* data) {
|
||||||
return g_pXWayland->pServer->ready(fd, mask);
|
CFileDescriptor xwlFd{fd};
|
||||||
|
return g_pXWayland->pServer->ready(std::move(xwlFd), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool safeRemove(const std::string& path) {
|
static bool safeRemove(const std::string& path) {
|
||||||
@@ -186,38 +157,34 @@ static bool safeRemove(const std::string& path) {
|
|||||||
|
|
||||||
bool CXWaylandServer::tryOpenSockets() {
|
bool CXWaylandServer::tryOpenSockets() {
|
||||||
for (size_t i = 0; i <= MAX_SOCKET_RETRIES; ++i) {
|
for (size_t i = 0; i <= MAX_SOCKET_RETRIES; ++i) {
|
||||||
std::string lockPath = std::format("/tmp/.X{}-lock", i);
|
std::string lockPath = std::format("/tmp/.X{}-lock", i);
|
||||||
|
|
||||||
int fd = open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE);
|
CFileDescriptor fd{open(lockPath.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, LOCK_FILE_MODE)};
|
||||||
if (fd >= 0) {
|
if (fd.isValid()) {
|
||||||
// we managed to open the lock
|
// we managed to open the lock
|
||||||
if (!openSockets(xFDs, i)) {
|
if (!openSockets(xFDs, i)) {
|
||||||
safeRemove(lockPath);
|
safeRemove(lockPath);
|
||||||
close(fd);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string pidStr = std::to_string(getpid());
|
const std::string pidStr = std::to_string(getpid());
|
||||||
if (write(fd, pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) {
|
if (write(fd.get(), pidStr.c_str(), pidStr.length()) != (long)pidStr.length()) {
|
||||||
safeRemove(lockPath);
|
safeRemove(lockPath);
|
||||||
close(fd);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
|
||||||
display = i;
|
display = i;
|
||||||
displayName = std::format(":{}", display);
|
displayName = std::format(":{}", display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(lockPath.c_str(), O_RDONLY | O_CLOEXEC);
|
fd = CFileDescriptor{open(lockPath.c_str(), O_RDONLY | O_CLOEXEC)};
|
||||||
|
|
||||||
if (fd < 0)
|
if (!fd.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char pidstr[12] = {0};
|
char pidstr[12] = {0};
|
||||||
read(fd, pidstr, sizeof(pidstr) - 1);
|
read(fd.get(), pidstr, sizeof(pidstr) - 1);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
int32_t pid = 0;
|
int32_t pid = 0;
|
||||||
try {
|
try {
|
||||||
@@ -249,9 +216,6 @@ CXWaylandServer::~CXWaylandServer() {
|
|||||||
if (display < 0)
|
if (display < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
closeSocketSafely(xFDs[0]);
|
|
||||||
closeSocketSafely(xFDs[1]);
|
|
||||||
|
|
||||||
std::string lockPath = std::format("/tmp/.X{}-lock", display);
|
std::string lockPath = std::format("/tmp/.X{}-lock", display);
|
||||||
safeRemove(lockPath);
|
safeRemove(lockPath);
|
||||||
|
|
||||||
@@ -277,21 +241,11 @@ void CXWaylandServer::die() {
|
|||||||
if (pipeSource)
|
if (pipeSource)
|
||||||
wl_event_source_remove(pipeSource);
|
wl_event_source_remove(pipeSource);
|
||||||
|
|
||||||
if (pipeFd >= 0)
|
|
||||||
close(pipeFd);
|
|
||||||
|
|
||||||
closeSocketSafely(waylandFDs[0]);
|
|
||||||
closeSocketSafely(waylandFDs[1]);
|
|
||||||
closeSocketSafely(xwmFDs[0]);
|
|
||||||
closeSocketSafely(xwmFDs[1]);
|
|
||||||
|
|
||||||
// possible crash. Better to leak a bit.
|
// possible crash. Better to leak a bit.
|
||||||
//if (xwaylandClient)
|
//if (xwaylandClient)
|
||||||
// wl_client_destroy(xwaylandClient);
|
// wl_client_destroy(xwaylandClient);
|
||||||
|
|
||||||
xwaylandClient = nullptr;
|
xwaylandClient = nullptr;
|
||||||
waylandFDs = {-1, -1};
|
|
||||||
xwmFDs = {-1, -1};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CXWaylandServer::create() {
|
bool CXWaylandServer::create() {
|
||||||
@@ -307,15 +261,17 @@ bool CXWaylandServer::create() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWaylandServer::runXWayland(int notifyFD) {
|
void CXWaylandServer::runXWayland(CFileDescriptor& notifyFD) {
|
||||||
if (!setCloseOnExec(xFDs[0], false) || !setCloseOnExec(xFDs[1], false) || !setCloseOnExec(waylandFDs[1], false) || !setCloseOnExec(xwmFDs[1], false)) {
|
if (!xFDs[0].setFlags(xFDs[0].getFlags() & ~FD_CLOEXEC) || !xFDs[1].setFlags(xFDs[1].getFlags() & ~FD_CLOEXEC) ||
|
||||||
|
!waylandFDs[1].setFlags(waylandFDs[1].getFlags() & ~FD_CLOEXEC) || !xwmFDs[1].setFlags(xwmFDs[1].getFlags() & ~FD_CLOEXEC)) {
|
||||||
Debug::log(ERR, "Failed to unset cloexec on fds");
|
Debug::log(ERR, "Failed to unset cloexec on fds");
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cmd = std::format("Xwayland {} -rootless -core -listenfd {} -listenfd {} -displayfd {} -wm {}", displayName, xFDs[0], xFDs[1], notifyFD, xwmFDs[1]);
|
auto cmd =
|
||||||
|
std::format("Xwayland {} -rootless -core -listenfd {} -listenfd {} -displayfd {} -wm {}", displayName, xFDs[0].get(), xFDs[1].get(), notifyFD.get(), xwmFDs[1].get());
|
||||||
|
|
||||||
auto waylandSocket = std::format("{}", waylandFDs[1]);
|
auto waylandSocket = std::format("{}", waylandFDs[1].get());
|
||||||
setenv("WAYLAND_SOCKET", waylandSocket.c_str(), true);
|
setenv("WAYLAND_SOCKET", waylandSocket.c_str(), true);
|
||||||
|
|
||||||
Debug::log(LOG, "Starting XWayland with \"{}\", bon voyage!", cmd);
|
Debug::log(LOG, "Starting XWayland with \"{}\", bon voyage!", cmd);
|
||||||
@@ -327,40 +283,46 @@ void CXWaylandServer::runXWayland(int notifyFD) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CXWaylandServer::start() {
|
bool CXWaylandServer::start() {
|
||||||
idleSource = nullptr;
|
idleSource = nullptr;
|
||||||
|
int wlPair[2] = {-1, -1};
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, waylandFDs.data()) != 0) {
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, wlPair) != 0) {
|
||||||
Debug::log(ERR, "socketpair failed (1)");
|
Debug::log(ERR, "socketpair failed (1)");
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
waylandFDs[0] = CFileDescriptor{wlPair[0]};
|
||||||
|
waylandFDs[1] = CFileDescriptor{wlPair[1]};
|
||||||
|
|
||||||
if (!setCloseOnExec(waylandFDs[0], true) || !setCloseOnExec(waylandFDs[1], true)) {
|
if (!waylandFDs[0].setFlags(waylandFDs[0].getFlags() | FD_CLOEXEC) || !waylandFDs[1].setFlags(waylandFDs[1].getFlags() | FD_CLOEXEC)) {
|
||||||
Debug::log(ERR, "set_cloexec failed (1)");
|
Debug::log(ERR, "set_cloexec failed (1)");
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, xwmFDs.data()) != 0) {
|
int xwmPair[2] = {-1, -1};
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, xwmPair) != 0) {
|
||||||
Debug::log(ERR, "socketpair failed (2)");
|
Debug::log(ERR, "socketpair failed (2)");
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setCloseOnExec(xwmFDs[0], true) || !setCloseOnExec(xwmFDs[1], true)) {
|
xwmFDs[0] = CFileDescriptor{xwmPair[0]};
|
||||||
|
xwmFDs[1] = CFileDescriptor{xwmPair[1]};
|
||||||
|
|
||||||
|
if (!xwmFDs[0].setFlags(xwmFDs[0].getFlags() | FD_CLOEXEC) || !xwmFDs[1].setFlags(xwmFDs[1].getFlags() | FD_CLOEXEC)) {
|
||||||
Debug::log(ERR, "set_cloexec failed (2)");
|
Debug::log(ERR, "set_cloexec failed (2)");
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
xwaylandClient = wl_client_create(g_pCompositor->m_sWLDisplay, waylandFDs[0]);
|
xwaylandClient = wl_client_create(g_pCompositor->m_sWLDisplay, waylandFDs[0].get());
|
||||||
if (!xwaylandClient) {
|
if (!xwaylandClient) {
|
||||||
Debug::log(ERR, "wl_client_create failed");
|
Debug::log(ERR, "wl_client_create failed");
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
waylandFDs[0] = -1;
|
waylandFDs[0].take(); // does this leak?
|
||||||
|
|
||||||
int notify[2] = {-1, -1};
|
int notify[2] = {-1, -1};
|
||||||
if (pipe(notify) < 0) {
|
if (pipe(notify) < 0) {
|
||||||
@@ -369,22 +331,20 @@ bool CXWaylandServer::start() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setCloseOnExec(notify[0], true)) {
|
CFileDescriptor notifyFds[2] = {CFileDescriptor{notify[0]}, CFileDescriptor{notify[1]}};
|
||||||
|
|
||||||
|
if (!notifyFds[0].setFlags(notifyFds[0].getFlags() | FD_CLOEXEC)) {
|
||||||
Debug::log(ERR, "set_cloexec failed (3)");
|
Debug::log(ERR, "set_cloexec failed (3)");
|
||||||
close(notify[0]);
|
|
||||||
close(notify[1]);
|
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notify[0], WL_EVENT_READABLE, ::xwaylandReady, nullptr);
|
pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notifyFds[0].get(), WL_EVENT_READABLE, ::xwaylandReady, nullptr);
|
||||||
pipeFd = notify[0];
|
pipeFd = std::move(notifyFds[0]);
|
||||||
|
|
||||||
serverPID = fork();
|
serverPID = fork();
|
||||||
if (serverPID < 0) {
|
if (serverPID < 0) {
|
||||||
Debug::log(ERR, "fork failed");
|
Debug::log(ERR, "fork failed");
|
||||||
close(notify[0]);
|
|
||||||
close(notify[1]);
|
|
||||||
die();
|
die();
|
||||||
return false;
|
return false;
|
||||||
} else if (serverPID == 0) {
|
} else if (serverPID == 0) {
|
||||||
@@ -393,25 +353,19 @@ bool CXWaylandServer::start() {
|
|||||||
Debug::log(ERR, "second fork failed");
|
Debug::log(ERR, "second fork failed");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
} else if (pid == 0)
|
} else if (pid == 0)
|
||||||
runXWayland(notify[1]);
|
runXWayland(notifyFds[1]);
|
||||||
|
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(notify[1]);
|
|
||||||
close(waylandFDs[1]);
|
|
||||||
closeSocketSafely(xwmFDs[1]);
|
|
||||||
waylandFDs[1] = -1;
|
|
||||||
xwmFDs[1] = -1;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CXWaylandServer::ready(int fd, uint32_t mask) {
|
int CXWaylandServer::ready(CFileDescriptor fd, uint32_t mask) {
|
||||||
if (mask & WL_EVENT_READABLE) {
|
if (mask & WL_EVENT_READABLE) {
|
||||||
// xwayland writes twice
|
// xwayland writes twice
|
||||||
char buf[64];
|
char buf[64];
|
||||||
ssize_t n = read(fd, buf, sizeof(buf));
|
ssize_t n = read(fd.get(), buf, sizeof(buf));
|
||||||
if (n < 0 && errno != EINTR) {
|
if (n < 0 && errno != EINTR) {
|
||||||
Debug::log(ERR, "Xwayland: read from displayFd failed");
|
Debug::log(ERR, "Xwayland: read from displayFd failed");
|
||||||
mask = 0;
|
mask = 0;
|
||||||
@@ -436,7 +390,6 @@ int CXWaylandServer::ready(int fd, uint32_t mask) {
|
|||||||
|
|
||||||
Debug::log(LOG, "XWayland is ready");
|
Debug::log(LOG, "XWayland is ready");
|
||||||
|
|
||||||
close(fd);
|
|
||||||
wl_event_source_remove(pipeSource);
|
wl_event_source_remove(pipeSource);
|
||||||
pipeSource = nullptr;
|
pipeSource = nullptr;
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
struct wl_event_source;
|
struct wl_event_source;
|
||||||
@@ -19,7 +20,7 @@ class CXWaylandServer {
|
|||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
// called on ready
|
// called on ready
|
||||||
int ready(int fd, uint32_t mask);
|
int ready(Hyprutils::OS::CFileDescriptor fd, uint32_t mask);
|
||||||
|
|
||||||
void die();
|
void die();
|
||||||
|
|
||||||
@@ -30,20 +31,20 @@ class CXWaylandServer {
|
|||||||
wl_client* xwaylandClient = nullptr;
|
wl_client* xwaylandClient = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool tryOpenSockets();
|
bool tryOpenSockets();
|
||||||
void runXWayland(int notifyFD);
|
void runXWayland(Hyprutils::OS::CFileDescriptor& notifyFD);
|
||||||
|
|
||||||
pid_t serverPID = 0;
|
pid_t serverPID = 0;
|
||||||
|
|
||||||
std::string displayName;
|
std::string displayName;
|
||||||
int display = -1;
|
int display = -1;
|
||||||
std::array<int, 2> xFDs = {-1, -1};
|
std::array<Hyprutils::OS::CFileDescriptor, 2> xFDs;
|
||||||
std::array<wl_event_source*, 2> xFDReadEvents = {nullptr, nullptr};
|
std::array<wl_event_source*, 2> xFDReadEvents = {nullptr, nullptr};
|
||||||
wl_event_source* idleSource = nullptr;
|
wl_event_source* idleSource = nullptr;
|
||||||
wl_event_source* pipeSource = nullptr;
|
wl_event_source* pipeSource = nullptr;
|
||||||
int pipeFd = -1;
|
Hyprutils::OS::CFileDescriptor pipeFd;
|
||||||
std::array<int, 2> xwmFDs = {-1, -1};
|
std::array<Hyprutils::OS::CFileDescriptor, 2> xwmFDs;
|
||||||
std::array<int, 2> waylandFDs = {-1, -1};
|
std::array<Hyprutils::OS::CFileDescriptor, 2> waylandFDs;
|
||||||
|
|
||||||
friend class CXWM;
|
friend class CXWM;
|
||||||
};
|
};
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "XDataSource.hpp"
|
#include "XDataSource.hpp"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
CXDataSource::CXDataSource(SXSelection& sel_) : selection(sel_) {
|
CXDataSource::CXDataSource(SXSelection& sel_) : selection(sel_) {
|
||||||
xcb_get_property_cookie_t cookie = xcb_get_property(g_pXWayland->pWM->connection,
|
xcb_get_property_cookie_t cookie = xcb_get_property(g_pXWayland->pWM->connection,
|
||||||
@@ -47,7 +48,7 @@ std::vector<std::string> CXDataSource::mimes() {
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXDataSource::send(const std::string& mime, uint32_t fd) {
|
void CXDataSource::send(const std::string& mime, CFileDescriptor fd) {
|
||||||
xcb_atom_t mimeAtom = 0;
|
xcb_atom_t mimeAtom = 0;
|
||||||
|
|
||||||
if (mime == "text/plain")
|
if (mime == "text/plain")
|
||||||
@@ -65,11 +66,10 @@ void CXDataSource::send(const std::string& mime, uint32_t fd) {
|
|||||||
|
|
||||||
if (!mimeAtom) {
|
if (!mimeAtom) {
|
||||||
Debug::log(ERR, "[XDataSource] mime atom not found");
|
Debug::log(ERR, "[XDataSource] mime atom not found");
|
||||||
close(fd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd);
|
Debug::log(LOG, "[XDataSource] send with mime {} to fd {}", mime, fd.get());
|
||||||
|
|
||||||
selection.transfer = makeUnique<SXTransfer>(selection);
|
selection.transfer = makeUnique<SXTransfer>(selection);
|
||||||
selection.transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection);
|
selection.transfer->incomingWindow = xcb_generate_id(g_pXWayland->pWM->connection);
|
||||||
@@ -81,8 +81,9 @@ void CXDataSource::send(const std::string& mime, uint32_t fd) {
|
|||||||
|
|
||||||
xcb_flush(g_pXWayland->pWM->connection);
|
xcb_flush(g_pXWayland->pWM->connection);
|
||||||
|
|
||||||
fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK);
|
//TODO: make CFileDescriptor setflags take SETFL aswell
|
||||||
selection.transfer->wlFD = fd;
|
fcntl(fd.get(), F_SETFL, O_WRONLY | O_NONBLOCK);
|
||||||
|
selection.transfer->wlFD = std::move(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXDataSource::accepted(const std::string& mime) {
|
void CXDataSource::accepted(const std::string& mime) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../protocols/types/DataDevice.hpp"
|
#include "../protocols/types/DataDevice.hpp"
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
struct SXSelection;
|
struct SXSelection;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ class CXDataSource : public IDataSource {
|
|||||||
CXDataSource(SXSelection&);
|
CXDataSource(SXSelection&);
|
||||||
|
|
||||||
virtual std::vector<std::string> mimes();
|
virtual std::vector<std::string> mimes();
|
||||||
virtual void send(const std::string& mime, uint32_t fd);
|
virtual void send(const std::string& mime, Hyprutils::OS::CFileDescriptor fd);
|
||||||
virtual void accepted(const std::string& mime);
|
virtual void accepted(const std::string& mime);
|
||||||
virtual void cancelled();
|
virtual void cancelled();
|
||||||
virtual void error(uint32_t code, const std::string& msg);
|
virtual void error(uint32_t code, const std::string& msg);
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include "../managers/SeatManager.hpp"
|
#include "../managers/SeatManager.hpp"
|
||||||
#include "../protocols/XWaylandShell.hpp"
|
#include "../protocols/XWaylandShell.hpp"
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
|
using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f
|
#define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f
|
||||||
#define INCR_CHUNK_SIZE (64 * 1024)
|
#define INCR_CHUNK_SIZE (64 * 1024)
|
||||||
@@ -883,7 +884,7 @@ void CXWM::getRenderFormat() {
|
|||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) {
|
CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0].get()) {
|
||||||
|
|
||||||
if (connection.hasError()) {
|
if (connection.hasError()) {
|
||||||
Debug::log(ERR, "[xwm] Couldn't start, error {}", connection.hasError());
|
Debug::log(ERR, "[xwm] Couldn't start, error {}", connection.hasError());
|
||||||
@@ -901,7 +902,7 @@ CXWM::CXWM() : connection(g_pXWayland->pServer->xwmFDs[0]) {
|
|||||||
xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(xcb_get_setup(connection));
|
xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(xcb_get_setup(connection));
|
||||||
screen = screen_iterator.data;
|
screen = screen_iterator.data;
|
||||||
|
|
||||||
eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, g_pXWayland->pServer->xwmFDs[0], WL_EVENT_READABLE, ::onX11Event, nullptr);
|
eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, g_pXWayland->pServer->xwmFDs[0].get(), WL_EVENT_READABLE, ::onX11Event, nullptr);
|
||||||
wl_event_source_check(eventSource);
|
wl_event_source_check(eventSource);
|
||||||
|
|
||||||
gatherResources();
|
gatherResources();
|
||||||
@@ -1180,13 +1181,12 @@ void CXWM::getTransferData(SXSelection& sel) {
|
|||||||
|
|
||||||
if (sel.transfer->propertyReply->type == HYPRATOMS["INCR"]) {
|
if (sel.transfer->propertyReply->type == HYPRATOMS["INCR"]) {
|
||||||
Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :(");
|
Debug::log(ERR, "[xwm] Transfer is INCR, which we don't support :(");
|
||||||
close(sel.transfer->wlFD);
|
|
||||||
sel.transfer.reset();
|
sel.transfer.reset();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
sel.onWrite();
|
sel.onWrite();
|
||||||
if (sel.transfer)
|
if (sel.transfer)
|
||||||
sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD, WL_EVENT_WRITABLE, ::writeDataSource, &sel);
|
sel.transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, sel.transfer->wlFD.get(), WL_EVENT_WRITABLE, ::writeDataSource, &sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1361,13 +1361,13 @@ bool SXSelection::sendData(xcb_selection_request_event_t* e, std::string mime) {
|
|||||||
// the wayland client might not expect a non-blocking fd
|
// the wayland client might not expect a non-blocking fd
|
||||||
// fcntl(p[1], F_SETFL, O_NONBLOCK);
|
// fcntl(p[1], F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
transfer->wlFD = p[0];
|
transfer->wlFD = CFileDescriptor{p[0]};
|
||||||
|
|
||||||
Debug::log(LOG, "[xwm] sending wayland selection to xwayland with mime {}, target {}, fds {} {}", mime, e->target, p[0], p[1]);
|
Debug::log(LOG, "[xwm] sending wayland selection to xwayland with mime {}, target {}, fds {} {}", mime, e->target, p[0], p[1]);
|
||||||
|
|
||||||
selection->send(mime, p[1]);
|
selection->send(mime, CFileDescriptor{p[1]});
|
||||||
|
|
||||||
transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, transfer->wlFD, WL_EVENT_READABLE, ::readDataSource, this);
|
transfer->eventSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, transfer->wlFD.get(), WL_EVENT_READABLE, ::readDataSource, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1376,10 +1376,9 @@ int SXSelection::onWrite() {
|
|||||||
char* property = (char*)xcb_get_property_value(transfer->propertyReply);
|
char* property = (char*)xcb_get_property_value(transfer->propertyReply);
|
||||||
int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart;
|
int remainder = xcb_get_property_value_length(transfer->propertyReply) - transfer->propertyStart;
|
||||||
|
|
||||||
ssize_t len = write(transfer->wlFD, property + transfer->propertyStart, remainder);
|
ssize_t len = write(transfer->wlFD.get(), property + transfer->propertyStart, remainder);
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
Debug::log(ERR, "[xwm] write died in transfer get");
|
Debug::log(ERR, "[xwm] write died in transfer get");
|
||||||
close(transfer->wlFD);
|
|
||||||
transfer.reset();
|
transfer.reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1389,7 +1388,6 @@ int SXSelection::onWrite() {
|
|||||||
Debug::log(LOG, "[xwm] wl client read partially: len {}", len);
|
Debug::log(LOG, "[xwm] wl client read partially: len {}", len);
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len);
|
Debug::log(LOG, "[xwm] cb transfer to wl client complete, read {} bytes", len);
|
||||||
close(transfer->wlFD);
|
|
||||||
transfer.reset();
|
transfer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1397,8 +1395,6 @@ int SXSelection::onWrite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SXTransfer::~SXTransfer() {
|
SXTransfer::~SXTransfer() {
|
||||||
if (wlFD)
|
|
||||||
close(wlFD);
|
|
||||||
if (eventSource)
|
if (eventSource)
|
||||||
wl_event_source_remove(eventSource);
|
wl_event_source_remove(eventSource);
|
||||||
if (incomingWindow)
|
if (incomingWindow)
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
#include <xcb/composite.h>
|
#include <xcb/composite.h>
|
||||||
#include <xcb/xcb_errors.h>
|
#include <xcb/xcb_errors.h>
|
||||||
|
#include <hyprutils/os/FileDescriptor.hpp>
|
||||||
|
|
||||||
struct wl_event_source;
|
struct wl_event_source;
|
||||||
class CXWaylandSurfaceResource;
|
class CXWaylandSurfaceResource;
|
||||||
@@ -18,25 +19,25 @@ struct SXSelection;
|
|||||||
struct SXTransfer {
|
struct SXTransfer {
|
||||||
~SXTransfer();
|
~SXTransfer();
|
||||||
|
|
||||||
SXSelection& selection;
|
SXSelection& selection;
|
||||||
bool out = true;
|
bool out = true;
|
||||||
|
|
||||||
bool incremental = false;
|
bool incremental = false;
|
||||||
bool flushOnDelete = false;
|
bool flushOnDelete = false;
|
||||||
bool propertySet = false;
|
bool propertySet = false;
|
||||||
|
|
||||||
int wlFD = -1;
|
Hyprutils::OS::CFileDescriptor wlFD;
|
||||||
wl_event_source* eventSource = nullptr;
|
wl_event_source* eventSource = nullptr;
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
xcb_selection_request_event_t request;
|
xcb_selection_request_event_t request;
|
||||||
|
|
||||||
int propertyStart;
|
int propertyStart;
|
||||||
xcb_get_property_reply_t* propertyReply;
|
xcb_get_property_reply_t* propertyReply;
|
||||||
xcb_window_t incomingWindow;
|
xcb_window_t incomingWindow;
|
||||||
|
|
||||||
bool getIncomingSelectionProp(bool erase);
|
bool getIncomingSelectionProp(bool erase);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SXSelection {
|
struct SXSelection {
|
||||||
|
Reference in New Issue
Block a user