mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-05 04:45:59 +01:00
Core: Move to aquamarine
This commit is contained in:
parent
cc98594c3a
commit
930e7bb0c8
75 changed files with 1882 additions and 2027 deletions
|
@ -109,6 +109,7 @@ endif()
|
||||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||||
|
|
||||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||||
|
aquamarine
|
||||||
xkbcommon uuid
|
xkbcommon uuid
|
||||||
wayland-server wayland-client wayland-cursor wayland-protocols
|
wayland-server wayland-client wayland-cursor wayland-protocols
|
||||||
cairo pango pangocairo pixman-1
|
cairo pango pangocairo pixman-1
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -88,7 +88,7 @@ asan:
|
||||||
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
||||||
|
|
||||||
rm -rf ./wayland
|
rm -rf ./wayland
|
||||||
git reset --hard
|
#git reset --hard
|
||||||
|
|
||||||
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
||||||
@read patchvar
|
@read patchvar
|
||||||
|
|
|
@ -25,12 +25,15 @@
|
||||||
#include "xwayland/XWayland.hpp"
|
#include "xwayland/XWayland.hpp"
|
||||||
|
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
using namespace Hyprutils::String;
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
using namespace Aquamarine;
|
||||||
|
|
||||||
int handleCritSignal(int signo, void* data) {
|
int handleCritSignal(int signo, void* data) {
|
||||||
Debug::log(LOG, "Hyprland received signal {}", signo);
|
Debug::log(LOG, "Hyprland received signal {}", signo);
|
||||||
|
|
||||||
|
@ -71,6 +74,23 @@ void handleUserSignal(int sig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case Aquamarine::eBackendLogLevel::AQ_LOG_TRACE: return TRACE;
|
||||||
|
case Aquamarine::eBackendLogLevel::AQ_LOG_DEBUG: return LOG;
|
||||||
|
case Aquamarine::eBackendLogLevel::AQ_LOG_ERROR: return ERR;
|
||||||
|
case Aquamarine::eBackendLogLevel::AQ_LOG_WARNING: return WARN;
|
||||||
|
case Aquamarine::eBackendLogLevel::AQ_LOG_CRITICAL: return CRIT;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aqLog(Aquamarine::eBackendLogLevel level, std::string msg) {
|
||||||
|
Debug::log(aqLevelToHl(level), "[AQ] {}", msg);
|
||||||
|
}
|
||||||
|
|
||||||
void CCompositor::bumpNofile() {
|
void CCompositor::bumpNofile() {
|
||||||
if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile))
|
if (!getrlimit(RLIMIT_NOFILE, &m_sOriginalNofile))
|
||||||
Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max);
|
Debug::log(LOG, "Old rlimit: soft -> {}, hard -> {}", m_sOriginalNofile.rlim_cur, m_sOriginalNofile.rlim_max);
|
||||||
|
@ -179,6 +199,9 @@ void CCompositor::setRandomSplash() {
|
||||||
m_szCurrentSplash = SPLASHES[distribution(engine)];
|
m_szCurrentSplash = SPLASHES[distribution(engine)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<SP<Aquamarine::IOutput>> pendingOutputs;
|
||||||
|
|
||||||
|
//
|
||||||
void CCompositor::initServer() {
|
void CCompositor::initServer() {
|
||||||
|
|
||||||
m_sWLDisplay = wl_display_create();
|
m_sWLDisplay = wl_display_create();
|
||||||
|
@ -199,102 +222,91 @@ void CCompositor::initServer() {
|
||||||
if (envEnabled("HYPRLAND_TRACE"))
|
if (envEnabled("HYPRLAND_TRACE"))
|
||||||
Debug::trace = true;
|
Debug::trace = true;
|
||||||
|
|
||||||
wlr_log_init(WLR_INFO, NULL);
|
Aquamarine::SBackendOptions options;
|
||||||
|
options.logFunction = aqLog;
|
||||||
|
|
||||||
if (envEnabled("HYPRLAND_LOG_WLR"))
|
std::vector<Aquamarine::SBackendImplementationOptions> implementations;
|
||||||
wlr_log_init(WLR_DEBUG, Debug::wlrLog);
|
Aquamarine::SBackendImplementationOptions waylandOptions;
|
||||||
else
|
waylandOptions.backendType = Aquamarine::eBackendType::AQ_BACKEND_WAYLAND;
|
||||||
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
waylandOptions.backendRequestMode = Aquamarine::eBackendRequestMode::AQ_BACKEND_REQUEST_IF_AVAILABLE;
|
||||||
|
implementations.emplace_back(waylandOptions);
|
||||||
|
|
||||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession);
|
m_pAqBackend = CBackend::create(implementations, options);
|
||||||
|
|
||||||
if (!m_sWLRBackend) {
|
if (!m_pAqBackend) {
|
||||||
Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
Debug::log(CRIT,
|
||||||
throwError("wlr_backend_autocreate() failed!");
|
"m_pAqBackend was null! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a Wayland "
|
||||||
|
"session, NOT an X11 one.");
|
||||||
|
throwError("CBackend::create() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHeadlessOnly = true;
|
// TODO: headless only
|
||||||
wlr_multi_for_each_backend(
|
|
||||||
m_sWLRBackend,
|
|
||||||
[](wlr_backend* backend, void* isHeadlessOnly) {
|
|
||||||
if (!wlr_backend_is_headless(backend) && !wlr_backend_is_libinput(backend))
|
|
||||||
*(bool*)isHeadlessOnly = false;
|
|
||||||
},
|
|
||||||
&isHeadlessOnly);
|
|
||||||
|
|
||||||
if (isHeadlessOnly) {
|
initAllSignals();
|
||||||
m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend); // TODO: remove this, it's barely needed now.
|
|
||||||
} else {
|
if (!m_pAqBackend->start()) {
|
||||||
m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
|
Debug::log(CRIT,
|
||||||
if (m_iDRMFD < 0) {
|
"m_pAqBackend couldn't start! This usually means aquamarine could not find a GPU or enountered some issues. Make sure you're running either on a tty or on a "
|
||||||
Debug::log(CRIT, "Couldn't query the DRM FD!");
|
"Wayland session, NOT an X11 one.");
|
||||||
throwError("wlr_backend_get_drm_fd() failed!");
|
throwError("CBackend::create() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
|
m_bInitialized = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_sWLRRenderer) {
|
m_iDRMFD = m_pAqBackend->drmFD();
|
||||||
Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
|
||||||
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer);
|
|
||||||
|
|
||||||
if (!m_sWLRAllocator) {
|
|
||||||
Debug::log(CRIT, "m_sWLRAllocator was NULL!");
|
|
||||||
throwError("wlr_allocator_autocreate() failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer);
|
|
||||||
|
|
||||||
if (!m_sWLREGL) {
|
|
||||||
Debug::log(CRIT, "m_sWLREGL was NULL!");
|
|
||||||
throwError("wlr_gles2_renderer_get_egl() failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
initManagers(STAGE_BASICINIT);
|
initManagers(STAGE_BASICINIT);
|
||||||
|
|
||||||
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
|
|
||||||
if (!m_sWRLDRMLeaseMgr) {
|
|
||||||
Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager");
|
|
||||||
Debug::log(INFO, "VR will not be available");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
|
||||||
|
|
||||||
if (!m_sWLRHeadlessBackend) {
|
|
||||||
Debug::log(CRIT, "Couldn't create the headless backend");
|
|
||||||
throwError("wlr_headless_backend_create() failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend);
|
|
||||||
|
|
||||||
initManagers(STAGE_LATE);
|
initManagers(STAGE_LATE);
|
||||||
|
|
||||||
|
for (auto& o : pendingOutputs) {
|
||||||
|
onNewMonitor(o);
|
||||||
|
}
|
||||||
|
pendingOutputs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::initAllSignals() {
|
void CCompositor::initAllSignals() {
|
||||||
addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend");
|
m_pAqBackend->events.newOutput.registerStaticListener(
|
||||||
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
|
[this](void* p, std::any data) {
|
||||||
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
|
auto output = std::any_cast<SP<Aquamarine::IOutput>>(data);
|
||||||
|
Debug::log(LOG, "New aquamarine output with name {}", output->name);
|
||||||
|
if (m_bInitialized)
|
||||||
|
onNewMonitor(output);
|
||||||
|
else
|
||||||
|
pendingOutputs.emplace_back(output);
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
|
||||||
if (m_sWRLDRMLeaseMgr)
|
m_pAqBackend->events.newPointer.registerStaticListener(
|
||||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
[](void* data, std::any d) {
|
||||||
|
auto dev = std::any_cast<SP<Aquamarine::IPointer>>(d);
|
||||||
|
Debug::log(LOG, "New aquamarine pointer with name {}", dev->getName());
|
||||||
|
g_pInputManager->newMouse(dev);
|
||||||
|
g_pInputManager->updateCapabilities();
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
|
||||||
if (m_sWLRSession)
|
m_pAqBackend->events.newKeyboard.registerStaticListener(
|
||||||
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
[](void* data, std::any d) {
|
||||||
|
auto dev = std::any_cast<SP<Aquamarine::IKeyboard>>(d);
|
||||||
|
Debug::log(LOG, "New aquamarine keyboard with name {}", dev->getName());
|
||||||
|
g_pInputManager->newKeyboard(dev);
|
||||||
|
g_pInputManager->updateCapabilities();
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
m_pAqBackend->events.newTouch.registerStaticListener(
|
||||||
|
[](void* data, std::any d) {
|
||||||
|
auto dev = std::any_cast<SP<Aquamarine::ITouch>>(d);
|
||||||
|
Debug::log(LOG, "New aquamarine touch with name {}", dev->getName());
|
||||||
|
g_pInputManager->newTouchDevice(dev);
|
||||||
|
g_pInputManager->updateCapabilities();
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::removeAllSignals() {
|
void CCompositor::removeAllSignals() {
|
||||||
removeWLSignal(&Events::listen_newOutput);
|
;
|
||||||
removeWLSignal(&Events::listen_newInput);
|
|
||||||
removeWLSignal(&Events::listen_RendererDestroy);
|
|
||||||
|
|
||||||
if (m_sWRLDRMLeaseMgr)
|
|
||||||
removeWLSignal(&Events::listen_leaseRequest);
|
|
||||||
|
|
||||||
if (m_sWLRSession)
|
|
||||||
removeWLSignal(&Events::listen_sessionActive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::cleanEnvironment() {
|
void CCompositor::cleanEnvironment() {
|
||||||
|
@ -308,7 +320,7 @@ void CCompositor::cleanEnvironment() {
|
||||||
unsetenv("XDG_BACKEND");
|
unsetenv("XDG_BACKEND");
|
||||||
unsetenv("XDG_CURRENT_DESKTOP");
|
unsetenv("XDG_CURRENT_DESKTOP");
|
||||||
|
|
||||||
if (m_sWLRSession) {
|
if (false /* TODO: */) {
|
||||||
const auto CMD =
|
const auto CMD =
|
||||||
#ifdef USES_SYSTEMD
|
#ifdef USES_SYSTEMD
|
||||||
"systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
"systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
||||||
|
@ -351,7 +363,7 @@ void CCompositor::cleanup() {
|
||||||
for (auto& m : m_vMonitors) {
|
for (auto& m : m_vMonitors) {
|
||||||
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
||||||
|
|
||||||
wlr_output_state_set_enabled(m->state.wlr(), false);
|
m->output->state->setEnabled(false);
|
||||||
m->state.commit();
|
m->state.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,14 +400,8 @@ void CCompositor::cleanup() {
|
||||||
g_pHyprCtl.reset();
|
g_pHyprCtl.reset();
|
||||||
g_pEventLoopManager.reset();
|
g_pEventLoopManager.reset();
|
||||||
|
|
||||||
if (m_sWLRRenderer)
|
if (m_pAqBackend)
|
||||||
wlr_renderer_destroy(m_sWLRRenderer);
|
m_pAqBackend.reset();
|
||||||
|
|
||||||
if (m_sWLRAllocator)
|
|
||||||
wlr_allocator_destroy(m_sWLRAllocator);
|
|
||||||
|
|
||||||
if (m_sWLRBackend)
|
|
||||||
wlr_backend_destroy(m_sWLRBackend);
|
|
||||||
|
|
||||||
if (m_critSigSource)
|
if (m_critSigSource)
|
||||||
wl_event_source_remove(m_critSigSource);
|
wl_event_source_remove(m_critSigSource);
|
||||||
|
@ -441,6 +447,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||||
|
|
||||||
Debug::log(LOG, "Creating the PointerManager!");
|
Debug::log(LOG, "Creating the PointerManager!");
|
||||||
g_pPointerManager = std::make_unique<CPointerManager>();
|
g_pPointerManager = std::make_unique<CPointerManager>();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating the EventManager!");
|
||||||
|
g_pEventManager = std::make_unique<CEventManager>();
|
||||||
} break;
|
} break;
|
||||||
case STAGE_BASICINIT: {
|
case STAGE_BASICINIT: {
|
||||||
Debug::log(LOG, "Creating the CHyprOpenGLImpl!");
|
Debug::log(LOG, "Creating the CHyprOpenGLImpl!");
|
||||||
|
@ -471,9 +480,6 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||||
Debug::log(LOG, "Creating the SessionLockManager!");
|
Debug::log(LOG, "Creating the SessionLockManager!");
|
||||||
g_pSessionLockManager = std::make_unique<CSessionLockManager>();
|
g_pSessionLockManager = std::make_unique<CSessionLockManager>();
|
||||||
|
|
||||||
Debug::log(LOG, "Creating the EventManager!");
|
|
||||||
g_pEventManager = std::make_unique<CEventManager>();
|
|
||||||
|
|
||||||
Debug::log(LOG, "Creating the HyprDebugOverlay!");
|
Debug::log(LOG, "Creating the HyprDebugOverlay!");
|
||||||
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
|
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
|
||||||
|
|
||||||
|
@ -515,27 +521,26 @@ void CCompositor::removeLockFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::prepareFallbackOutput() {
|
void CCompositor::prepareFallbackOutput() {
|
||||||
// create a backup monitor
|
// TODO:
|
||||||
wlr_backend* headless = nullptr;
|
// // create a backup monitor
|
||||||
wlr_multi_for_each_backend(
|
// wlr_backend* headless = nullptr;
|
||||||
m_sWLRBackend,
|
// wlr_multi_for_each_backend(
|
||||||
[](wlr_backend* b, void* data) {
|
// m_sWLRBackend,
|
||||||
if (wlr_backend_is_headless(b))
|
// [](wlr_backend* b, void* data) {
|
||||||
*((wlr_backend**)data) = b;
|
// if (wlr_backend_is_headless(b))
|
||||||
},
|
// *((wlr_backend**)data) = b;
|
||||||
&headless);
|
// },
|
||||||
|
// &headless);
|
||||||
|
|
||||||
if (!headless) {
|
// if (!headless) {
|
||||||
Debug::log(WARN, "Unsafe state will be ineffective, no fallback output");
|
// Debug::log(WARN, "Unsafe state will be ineffective, no fallback output");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
wlr_headless_add_output(headless, 1920, 1080);
|
// wlr_headless_add_output(headless, 1920, 1080);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::startCompositor() {
|
void CCompositor::startCompositor() {
|
||||||
initAllSignals();
|
|
||||||
|
|
||||||
// get socket, avoid using 0
|
// get socket, avoid using 0
|
||||||
for (int candidate = 1; candidate <= 32; candidate++) {
|
for (int candidate = 1; candidate <= 32; candidate++) {
|
||||||
const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
|
const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
|
||||||
|
@ -558,7 +563,6 @@ void CCompositor::startCompositor() {
|
||||||
|
|
||||||
if (m_szWLDisplaySocket.empty()) {
|
if (m_szWLDisplaySocket.empty()) {
|
||||||
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
|
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
|
||||||
wlr_backend_destroy(m_sWLRBackend);
|
|
||||||
throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)");
|
throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +570,8 @@ void CCompositor::startCompositor() {
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) {
|
// TODO:
|
||||||
|
if (false /* Session-less Hyprland usually means a nest, don't update the env in that case */) {
|
||||||
const auto CMD =
|
const auto CMD =
|
||||||
#ifdef USES_SYSTEMD
|
#ifdef USES_SYSTEMD
|
||||||
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
||||||
|
@ -578,13 +583,6 @@ void CCompositor::startCompositor() {
|
||||||
|
|
||||||
Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket);
|
Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket);
|
||||||
|
|
||||||
if (!wlr_backend_start(m_sWLRBackend)) {
|
|
||||||
Debug::log(CRIT, "Backend did not start!");
|
|
||||||
wlr_backend_destroy(m_sWLRBackend);
|
|
||||||
wl_display_destroy(m_sWLDisplay);
|
|
||||||
throwError("The backend could not start!");
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareFallbackOutput();
|
prepareFallbackOutput();
|
||||||
|
|
||||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||||
|
@ -871,7 +869,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
|
||||||
return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y};
|
return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
CMonitor* CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) {
|
||||||
for (auto& m : m_vMonitors) {
|
for (auto& m : m_vMonitors) {
|
||||||
if (m->output == out) {
|
if (m->output == out) {
|
||||||
return m.get();
|
return m.get();
|
||||||
|
@ -881,7 +879,7 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) {
|
CMonitor* CCompositor::getRealMonitorFromOutput(SP<Aquamarine::IOutput> out) {
|
||||||
for (auto& m : m_vRealMonitors) {
|
for (auto& m : m_vRealMonitors) {
|
||||||
if (m->output == out) {
|
if (m->output == out) {
|
||||||
return m.get();
|
return m.get();
|
||||||
|
@ -2281,8 +2279,9 @@ void CCompositor::updateWorkspaceSpecialRenderData(const int& id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) {
|
void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) {
|
||||||
if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive)
|
// FIXME:
|
||||||
return;
|
// if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive)
|
||||||
|
// return;
|
||||||
|
|
||||||
if (!pMonitor->m_bEnabled)
|
if (!pMonitor->m_bEnabled)
|
||||||
return;
|
return;
|
||||||
|
@ -2290,7 +2289,7 @@ void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) {
|
||||||
if (pMonitor->renderingActive)
|
if (pMonitor->renderingActive)
|
||||||
pMonitor->pendingFrame = true;
|
pMonitor->pendingFrame = true;
|
||||||
|
|
||||||
wlr_output_schedule_frame(pMonitor->output);
|
pMonitor->output->scheduleFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
|
PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||||
|
@ -2806,3 +2805,80 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitorName) {
|
||||||
|
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
|
||||||
|
static auto firstMonitorAdded = std::chrono::system_clock::now();
|
||||||
|
static bool cursorDefaultDone = false;
|
||||||
|
static bool firstLaunch = true;
|
||||||
|
|
||||||
|
const auto POS = PNEWMONITOR->middle();
|
||||||
|
|
||||||
|
// by default, cursor should be set to first monitor detected
|
||||||
|
// this is needed as a default if the monitor given in config above doesn't exist
|
||||||
|
if (firstLaunch) {
|
||||||
|
firstLaunch = false;
|
||||||
|
g_pCompositor->warpCursorTo(POS, true);
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// after 10s, don't set cursor to default monitor
|
||||||
|
auto timePassedSec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - firstMonitorAdded);
|
||||||
|
if (timePassedSec.count() > 10) {
|
||||||
|
cursorDefaultDone = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*PCURSORMONITOR == monitorName) {
|
||||||
|
cursorDefaultDone = true;
|
||||||
|
g_pCompositor->warpCursorTo(POS, true);
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
|
||||||
|
// add it to real
|
||||||
|
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>());
|
||||||
|
if (std::string("HEADLESS-1") == output->name)
|
||||||
|
g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get();
|
||||||
|
|
||||||
|
PNEWMONITOR->szName = output->name;
|
||||||
|
PNEWMONITOR->output = output;
|
||||||
|
PNEWMONITOR->self = PNEWMONITOR;
|
||||||
|
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false;
|
||||||
|
PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name);
|
||||||
|
PNEWMONITOR->isUnsafeFallback = FALLBACK;
|
||||||
|
|
||||||
|
EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR);
|
||||||
|
|
||||||
|
if (!FALLBACK)
|
||||||
|
PNEWMONITOR->onConnect(false);
|
||||||
|
|
||||||
|
if (!PNEWMONITOR->m_bEnabled || FALLBACK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ready to process if we have a real monitor
|
||||||
|
|
||||||
|
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
||||||
|
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get();
|
||||||
|
|
||||||
|
g_pCompositor->m_bReadyToProcess = true;
|
||||||
|
|
||||||
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get());
|
||||||
|
|
||||||
|
checkDefaultCursorWarp(PNEWMONITOR, output->name);
|
||||||
|
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||||
|
w->m_iLastSurfaceMonitorID = -1;
|
||||||
|
w->updateSurfaceScaleTransformDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageMonitor(PNEWMONITOR.get());
|
||||||
|
Events::listener_monitorFrame(PNEWMONITOR.get(), nullptr);
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include "plugins/PluginSystem.hpp"
|
#include "plugins/PluginSystem.hpp"
|
||||||
#include "helpers/Watchdog.hpp"
|
#include "helpers/Watchdog.hpp"
|
||||||
|
|
||||||
|
#include <aquamarine/backend/Backend.hpp>
|
||||||
|
#include <aquamarine/output/Output.hpp>
|
||||||
|
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
|
|
||||||
enum eManagersInitStage {
|
enum eManagersInitStage {
|
||||||
|
@ -43,22 +46,11 @@ class CCompositor {
|
||||||
CCompositor();
|
CCompositor();
|
||||||
~CCompositor();
|
~CCompositor();
|
||||||
|
|
||||||
// ------------------ WLR BASICS ------------------ //
|
|
||||||
wl_display* m_sWLDisplay;
|
wl_display* m_sWLDisplay;
|
||||||
wl_event_loop* m_sWLEventLoop;
|
wl_event_loop* m_sWLEventLoop;
|
||||||
wlr_backend* m_sWLRBackend;
|
int m_iDRMFD = -1;
|
||||||
wlr_session* m_sWLRSession;
|
bool m_bInitialized = false;
|
||||||
wlr_renderer* m_sWLRRenderer;
|
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||||
wlr_allocator* m_sWLRAllocator;
|
|
||||||
wlr_compositor* m_sWLRCompositor;
|
|
||||||
wlr_subcompositor* m_sWLRSubCompositor;
|
|
||||||
wlr_drm* m_sWRLDRM;
|
|
||||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
|
||||||
wlr_egl* m_sWLREGL;
|
|
||||||
int m_iDRMFD;
|
|
||||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
|
||||||
wlr_backend* m_sWLRHeadlessBackend;
|
|
||||||
// ------------------------------------------------- //
|
|
||||||
|
|
||||||
std::string m_szHyprTempDataRoot = "";
|
std::string m_szHyprTempDataRoot = "";
|
||||||
|
|
||||||
|
@ -116,8 +108,8 @@ class CCompositor {
|
||||||
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
|
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
|
||||||
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
|
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
|
||||||
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
|
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
|
||||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
CMonitor* getMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||||
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
CMonitor* getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||||
|
@ -182,6 +174,7 @@ class CCompositor {
|
||||||
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
|
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
|
||||||
void updateSuspendedStates();
|
void updateSuspendedStates();
|
||||||
PHLWINDOW windowForCPointer(CWindow*);
|
PHLWINDOW windowForCPointer(CWindow*);
|
||||||
|
void onNewMonitor(SP<Aquamarine::IOutput> output);
|
||||||
|
|
||||||
std::string explicitConfigPath;
|
std::string explicitConfigPath;
|
||||||
|
|
||||||
|
|
|
@ -1279,7 +1279,7 @@ void CConfigManager::dispatchExecOnce() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// update dbus env
|
// update dbus env
|
||||||
if (g_pCompositor->m_sWLRSession)
|
if (g_pCompositor->m_pAqBackend->hasSession())
|
||||||
handleRawExec("",
|
handleRawExec("",
|
||||||
#ifdef USES_SYSTEMD
|
#ifdef USES_SYSTEMD
|
||||||
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
|
||||||
|
@ -1404,7 +1404,8 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
||||||
|
|
||||||
if (USEVRR == 0) {
|
if (USEVRR == 0) {
|
||||||
if (m->vrrActive) {
|
if (m->vrrActive) {
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
|
||||||
|
m->output->state->setAdaptiveSync(false);
|
||||||
|
|
||||||
if (!m->state.commit())
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
||||||
|
@ -1413,11 +1414,11 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
||||||
return;
|
return;
|
||||||
} else if (USEVRR == 1) {
|
} else if (USEVRR == 1) {
|
||||||
if (!m->vrrActive) {
|
if (!m->vrrActive) {
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1);
|
m->output->state->setAdaptiveSync(true);
|
||||||
|
|
||||||
if (!m->state.test()) {
|
if (!m->state.test()) {
|
||||||
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
m->output->state->setAdaptiveSync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m->state.commit())
|
if (!m->state.commit())
|
||||||
|
@ -1436,19 +1437,19 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
|
||||||
|
|
||||||
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
const auto WORKSPACEFULL = PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
|
|
||||||
if (WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED) {
|
if (WORKSPACEFULL) {
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 1);
|
m->output->state->setAdaptiveSync(true);
|
||||||
|
|
||||||
if (!m->state.test()) {
|
if (!m->state.test()) {
|
||||||
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
Debug::log(LOG, "Pending output {} does not accept VRR.", m->output->name);
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
m->output->state->setAdaptiveSync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m->state.commit())
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> true", m->output->name);
|
||||||
|
|
||||||
} else if (!WORKSPACEFULL && m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) {
|
} else if (!WORKSPACEFULL) {
|
||||||
wlr_output_state_set_adaptive_sync_enabled(m->state.wlr(), 0);
|
m->output->state->setAdaptiveSync(false);
|
||||||
|
|
||||||
if (!m->state.commit())
|
if (!m->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
Debug::log(ERR, "Couldn't commit output {} in ensureVRR -> false", m->output->name);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
#include "../config/ConfigDataValues.hpp"
|
#include "../config/ConfigDataValues.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
@ -53,18 +54,11 @@ static std::string formatToString(uint32_t drmFormat) {
|
||||||
static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) {
|
static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
for (auto& m : pMonitor->output->modes) {
|
||||||
wlr_output_mode* mode;
|
|
||||||
|
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
|
||||||
|
|
||||||
if (format == FORMAT_NORMAL)
|
if (format == FORMAT_NORMAL)
|
||||||
result += std::format("{}x{}@{:.2f}Hz ", mode->width, mode->height, mode->refresh / 1000.0);
|
result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0);
|
||||||
else
|
else
|
||||||
result += std::format("\"{}x{}@{:.2f}Hz\",", mode->width, mode->height, mode->refresh / 1000.0);
|
result += std::format("\"{}x{}@{:.2f}Hz\",", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0);
|
||||||
}
|
|
||||||
|
|
||||||
result.pop_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -120,14 +114,13 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
"currentFormat": "{}",
|
"currentFormat": "{}",
|
||||||
"availableModes": [{}]
|
"availableModes": [{}]
|
||||||
}},)#",
|
}},)#",
|
||||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make ? m->output->make : ""),
|
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szShortDescription), escapeJSONStrings(m->output->make), escapeJSONStrings(m->output->model),
|
||||||
escapeJSONStrings(m->output->model ? m->output->model : ""), escapeJSONStrings(m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x,
|
escapeJSONStrings(m->output->serial), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||||
(int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspaceID(),
|
m->activeWorkspaceID(), (!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(),
|
||||||
(!m->activeWorkspace ? "" : escapeJSONStrings(m->activeWorkspace->m_szName)), m->activeSpecialWorkspaceID(),
|
|
||||||
escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
escapeJSONStrings(m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||||
(m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"),
|
(m->dpmsStatus ? "true" : "false"), (m->output->state->state().adaptiveSync ? "true" : "false"), (m->tearingState.activelyTearing ? "true" : "false"),
|
||||||
(m->tearingState.activelyTearing ? "true" : "false"), (m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
|
(m->m_bEnabled ? "false" : "true"), formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
|
||||||
}
|
}
|
||||||
|
|
||||||
trimTrailingComma(result);
|
trimTrailingComma(result);
|
||||||
|
@ -138,16 +131,16 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
if (!m->output || m->ID == -1ull)
|
if (!m->output || m->ID == -1ull)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
result += std::format(
|
result +=
|
||||||
"Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
|
||||||
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
|
||||||
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n",
|
||||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
|
||||||
(m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspaceID(),
|
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
|
||||||
(!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""),
|
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x,
|
||||||
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform,
|
||||||
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED),
|
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, m->output->state->state().adaptiveSync, m->tearingState.activelyTearing,
|
||||||
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
|
!m->m_bEnabled, formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,8 +539,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
"defaultSpeed": {:.5f}
|
"defaultSpeed": {:.5f}
|
||||||
}},)#",
|
}},)#",
|
||||||
(uintptr_t)m.get(), escapeJSONStrings(m->hlName),
|
(uintptr_t)m.get(), escapeJSONStrings(m->hlName),
|
||||||
wlr_input_device_is_libinput(&m->wlr()->base) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) :
|
m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f);
|
||||||
0.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trimTrailingComma(result);
|
trimTrailingComma(result);
|
||||||
|
@ -648,9 +640,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
for (auto& m : g_pInputManager->m_vPointers) {
|
for (auto& m : g_pInputManager->m_vPointers) {
|
||||||
result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName,
|
result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName,
|
||||||
(wlr_input_device_is_libinput(&m->wlr()->base) ?
|
(m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f));
|
||||||
libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) :
|
|
||||||
0.f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result += "\n\nKeyboards:\n";
|
result += "\n\nKeyboards:\n";
|
||||||
|
@ -1119,24 +1109,22 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ
|
||||||
if (PKEYBOARD == g_pInputManager->m_vKeyboards.end())
|
if (PKEYBOARD == g_pInputManager->m_vKeyboards.end())
|
||||||
return "device not found";
|
return "device not found";
|
||||||
|
|
||||||
const auto PWLRKEYBOARD = (*PKEYBOARD)->wlr();
|
const auto KEEB = *PKEYBOARD;
|
||||||
const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap);
|
|
||||||
|
const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap);
|
||||||
xkb_layout_index_t activeLayout = 0;
|
xkb_layout_index_t activeLayout = 0;
|
||||||
while (activeLayout < LAYOUTS) {
|
while (activeLayout < LAYOUTS) {
|
||||||
if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1)
|
if (xkb_state_layout_index_is_active(KEEB->xkbTranslationState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
activeLayout++;
|
activeLayout++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CMD == "next") {
|
if (CMD == "next")
|
||||||
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
|
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1);
|
||||||
activeLayout > LAYOUTS ? 0 : activeLayout + 1);
|
else if (CMD == "prev")
|
||||||
} else if (CMD == "prev") {
|
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
|
||||||
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
|
else {
|
||||||
activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
int requestedLayout = 0;
|
int requestedLayout = 0;
|
||||||
try {
|
try {
|
||||||
requestedLayout = std::stoi(CMD);
|
requestedLayout = std::stoi(CMD);
|
||||||
|
@ -1146,7 +1134,7 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ
|
||||||
return "layout idx out of range of " + std::to_string(LAYOUTS);
|
return "layout idx out of range of " + std::to_string(LAYOUTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout);
|
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
|
@ -1389,26 +1377,26 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) {
|
// static bool addOutput(wlr_backend* backend, const std::string& type, const std::string& name) {
|
||||||
wlr_output* output = nullptr;
|
// wlr_output* output = nullptr;
|
||||||
|
|
||||||
if (type.empty() || type == "auto") {
|
// if (type.empty() || type == "auto") {
|
||||||
if (wlr_backend_is_wl(backend))
|
// if (wlr_backend_is_wl(backend))
|
||||||
output = wlr_wl_output_create(backend);
|
// output = wlr_wl_output_create(backend);
|
||||||
else if (wlr_backend_is_headless(backend))
|
// else if (wlr_backend_is_headless(backend))
|
||||||
output = wlr_headless_add_output(backend, 1920, 1080);
|
// output = wlr_headless_add_output(backend, 1920, 1080);
|
||||||
} else {
|
// } else {
|
||||||
if (wlr_backend_is_wl(backend) && type == "wayland")
|
// if (wlr_backend_is_wl(backend) && type == "wayland")
|
||||||
output = wlr_wl_output_create(backend);
|
// output = wlr_wl_output_create(backend);
|
||||||
else if (wlr_backend_is_headless(backend) && type == "headless")
|
// else if (wlr_backend_is_headless(backend) && type == "headless")
|
||||||
output = wlr_headless_add_output(backend, 1920, 1080);
|
// output = wlr_headless_add_output(backend, 1920, 1080);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (output && !name.empty())
|
// if (output && !name.empty())
|
||||||
g_pCompositor->getMonitorFromOutput(output)->szName = name;
|
// g_pCompositor->getMonitorFromOutput(output)->szName = name;
|
||||||
|
|
||||||
return output != nullptr;
|
// return output != nullptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
struct outputData {
|
struct outputData {
|
||||||
std::string type;
|
std::string type;
|
||||||
|
@ -1422,8 +1410,8 @@ void createOutputIter(wlr_backend* backend, void* data) {
|
||||||
if (DATA->added)
|
if (DATA->added)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (addOutput(backend, DATA->type, DATA->name))
|
// if (addOutput(backend, DATA->type, DATA->name))
|
||||||
DATA->added = true;
|
// DATA->added = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
@ -1434,13 +1422,15 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
||||||
|
|
||||||
const auto MODE = vars[1];
|
const auto MODE = vars[1];
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
|
||||||
if (MODE == "create" || MODE == "add") {
|
if (MODE == "create" || MODE == "add") {
|
||||||
if (g_pCompositor->getMonitorFromName(vars[3]))
|
if (g_pCompositor->getMonitorFromName(vars[3]))
|
||||||
return "A real monitor already uses that name.";
|
return "A real monitor already uses that name.";
|
||||||
|
|
||||||
outputData result{vars[2], vars[3], false};
|
outputData result{vars[2], vars[3], false};
|
||||||
|
|
||||||
wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result);
|
// wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result);
|
||||||
|
|
||||||
if (!result.added)
|
if (!result.added)
|
||||||
return "no backend replied to the request";
|
return "no backend replied to the request";
|
||||||
|
@ -1454,7 +1444,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
|
||||||
if (!PMONITOR->createdByUser)
|
if (!PMONITOR->createdByUser)
|
||||||
return "cannot remove a real display. Use the monitor keyword.";
|
return "cannot remove a real display. Use the monitor keyword.";
|
||||||
|
|
||||||
wlr_output_destroy(PMONITOR->output);
|
//wlr_output_destroy(PMONITOR->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
|
|
|
@ -2,7 +2,16 @@
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/varlist/VarList.hpp"
|
#include "../helpers/varlist/VarList.hpp"
|
||||||
#include "../managers/input/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
|
constexpr static std::array<const char*, 8> MODNAMES = {
|
||||||
|
XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static std::array<const char*, 3> LEDNAMES = {XKB_LED_NAME_NUM, XKB_LED_NAME_CAPS, XKB_LED_NAME_SCROLL};
|
||||||
|
|
||||||
|
//
|
||||||
uint32_t IKeyboard::getCapabilities() {
|
uint32_t IKeyboard::getCapabilities() {
|
||||||
return HID_INPUT_CAPABILITY_KEYBOARD;
|
return HID_INPUT_CAPABILITY_KEYBOARD;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +23,130 @@ eHIDType IKeyboard::getType() {
|
||||||
IKeyboard::~IKeyboard() {
|
IKeyboard::~IKeyboard() {
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
|
|
||||||
if (!xkbTranslationState)
|
clearManuallyAllocd();
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
void IKeyboard::clearManuallyAllocd() {
|
||||||
|
if (xkbTranslationState)
|
||||||
xkb_state_unref(xkbTranslationState);
|
xkb_state_unref(xkbTranslationState);
|
||||||
|
|
||||||
|
if (xkbInternalTranslationState)
|
||||||
|
xkb_state_unref(xkbInternalTranslationState);
|
||||||
|
|
||||||
|
if (xkbKeymap)
|
||||||
|
xkb_keymap_unref(xkbKeymap);
|
||||||
|
|
||||||
|
if (xkbKeymapFD >= 0)
|
||||||
|
close(xkbKeymapFD);
|
||||||
|
|
||||||
|
xkbKeymap = nullptr;
|
||||||
xkbTranslationState = nullptr;
|
xkbTranslationState = nullptr;
|
||||||
|
xkbKeymapFD = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
|
||||||
|
currentRules = rules;
|
||||||
|
xkb_rule_names XKBRULES = {
|
||||||
|
.rules = rules.rules.c_str(),
|
||||||
|
.model = rules.model.c_str(),
|
||||||
|
.layout = rules.layout.c_str(),
|
||||||
|
.variant = rules.variant.c_str(),
|
||||||
|
.options = rules.options.c_str(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
|
if (!CONTEXT) {
|
||||||
|
Debug::log(ERR, "setKeymap: CONTEXT null??");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearManuallyAllocd();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model,
|
||||||
|
rules.options);
|
||||||
|
|
||||||
|
if (!xkbFilePath.empty()) {
|
||||||
|
auto path = absolutePath(xkbFilePath, g_pConfigManager->configCurrentPath);
|
||||||
|
|
||||||
|
if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE)
|
||||||
|
Debug::log(ERR, "Cannot open input:kb_file= file for reading");
|
||||||
|
else {
|
||||||
|
xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
fclose(KEYMAPFILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xkbKeymap)
|
||||||
|
xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
if (!xkbKeymap) {
|
||||||
|
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant +
|
||||||
|
", options: " + rules.options + ", layout: " + rules.layout + " )");
|
||||||
|
|
||||||
|
Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model,
|
||||||
|
rules.options);
|
||||||
|
memset(&XKBRULES, 0, sizeof(XKBRULES));
|
||||||
|
|
||||||
|
currentRules.rules = "";
|
||||||
|
currentRules.model = "";
|
||||||
|
currentRules.variant = "";
|
||||||
|
currentRules.options = "";
|
||||||
|
currentRules.layout = "us";
|
||||||
|
|
||||||
|
xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set internal translation state
|
||||||
|
// demo sunao ni ienai
|
||||||
|
xkbInternalTranslationState = xkb_state_new(xkbKeymap);
|
||||||
|
|
||||||
|
updateXKBTranslationState();
|
||||||
|
|
||||||
|
const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default");
|
||||||
|
|
||||||
|
if (NUMLOCKON == 1) {
|
||||||
|
// lock numlock
|
||||||
|
const auto IDX = xkb_map_mod_get_index(xkbKeymap, XKB_MOD_NAME_NUM);
|
||||||
|
|
||||||
|
if (IDX != XKB_MOD_INVALID)
|
||||||
|
modifiersState.locked |= (uint32_t)1 << IDX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifiersState.locked != 0)
|
||||||
|
keyboardEvents.modifiers.emit(SModifiersEvent{.locked = modifiersState.locked});
|
||||||
|
|
||||||
|
for (size_t i = 0; i < LEDNAMES.size(); ++i) {
|
||||||
|
ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i));
|
||||||
|
Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), modIndexes.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MODNAMES.size(); ++i) {
|
||||||
|
modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i));
|
||||||
|
Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||||
|
xkbKeymapString = cKeymapStr;
|
||||||
|
free(cKeymapStr);
|
||||||
|
|
||||||
|
int rw, ro;
|
||||||
|
if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro))
|
||||||
|
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
|
||||||
|
else {
|
||||||
|
auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0);
|
||||||
|
close(rw);
|
||||||
|
if (keymapFDDest == MAP_FAILED) {
|
||||||
|
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
|
||||||
|
close(ro);
|
||||||
|
} else {
|
||||||
|
memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length());
|
||||||
|
munmap(keymapFDDest, xkbKeymapString.length() + 1);
|
||||||
|
xkbKeymapFD = ro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_context_unref(CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
|
@ -32,9 +160,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto WLRKB = wlr();
|
const auto KEYMAP = xkbKeymap;
|
||||||
const auto KEYMAP = WLRKB->keymap;
|
const auto STATE = xkbInternalTranslationState;
|
||||||
const auto STATE = WLRKB->xkb_state;
|
|
||||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||||
|
|
||||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
@ -101,9 +228,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IKeyboard::getActiveLayout() {
|
std::string IKeyboard::getActiveLayout() {
|
||||||
const auto WLRKB = wlr();
|
const auto KEYMAP = xkbKeymap;
|
||||||
const auto KEYMAP = WLRKB->keymap;
|
const auto STATE = xkbTranslationState;
|
||||||
const auto STATE = WLRKB->xkb_state;
|
|
||||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
||||||
|
@ -120,14 +246,12 @@ std::string IKeyboard::getActiveLayout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IKeyboard::updateLEDs() {
|
void IKeyboard::updateLEDs() {
|
||||||
auto keyboard = wlr();
|
if (xkbTranslationState == nullptr)
|
||||||
|
|
||||||
if (!keyboard || keyboard->xkb_state == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t leds = 0;
|
uint32_t leds = 0;
|
||||||
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
|
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
|
||||||
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i]))
|
if (xkb_state_led_index_is_active(xkbTranslationState, ledIndexes.at(i)))
|
||||||
leds |= (1 << i);
|
leds |= (1 << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +259,62 @@ void IKeyboard::updateLEDs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IKeyboard::updateLEDs(uint32_t leds) {
|
void IKeyboard::updateLEDs(uint32_t leds) {
|
||||||
auto keyboard = wlr();
|
if (!xkbTranslationState)
|
||||||
|
|
||||||
if (!keyboard || keyboard->xkb_state == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock()))
|
if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_keyboard_led_update(keyboard, leds);
|
if (!aq())
|
||||||
|
return;
|
||||||
|
|
||||||
|
aq()->updateLEDs(leds);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t IKeyboard::getModifiers() {
|
||||||
|
uint32_t modMask = modifiersState.depressed | modifiersState.latched;
|
||||||
|
uint32_t mods = 0;
|
||||||
|
for (size_t i = 0; i < modIndexes.size(); ++i) {
|
||||||
|
if (modIndexes.at(i) == XKB_MOD_INVALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(modMask & (1 << modIndexes.at(i))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mods |= (1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
|
||||||
|
if (!xkbTranslationState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xkb_state_update_mask(xkbTranslationState, depressed, latched, locked, 0, 0, group);
|
||||||
|
|
||||||
|
if (!updateModifiersState())
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKeyboard::updateModifiersState() {
|
||||||
|
if (!xkbTranslationState)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto depressed = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_DEPRESSED);
|
||||||
|
auto latched = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LATCHED);
|
||||||
|
auto locked = xkb_state_serialize_mods(xkbTranslationState, XKB_STATE_MODS_LOCKED);
|
||||||
|
auto group = xkb_state_serialize_layout(xkbTranslationState, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||||
|
|
||||||
|
if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
modifiersState.depressed = depressed;
|
||||||
|
modifiersState.latched = latched;
|
||||||
|
modifiersState.locked = locked;
|
||||||
|
modifiersState.group = group;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
struct wlr_keyboard;
|
AQUAMARINE_FORWARD(IKeyboard);
|
||||||
|
|
||||||
class IKeyboard : public IHID {
|
class IKeyboard : public IHID {
|
||||||
public:
|
public:
|
||||||
|
@ -15,7 +15,7 @@ class IKeyboard : public IHID {
|
||||||
virtual uint32_t getCapabilities();
|
virtual uint32_t getCapabilities();
|
||||||
virtual eHIDType getType();
|
virtual eHIDType getType();
|
||||||
virtual bool isVirtual() = 0;
|
virtual bool isVirtual() = 0;
|
||||||
virtual wlr_keyboard* wlr() = 0;
|
virtual SP<Aquamarine::IKeyboard> aq() = 0;
|
||||||
|
|
||||||
struct SKeyEvent {
|
struct SKeyEvent {
|
||||||
uint32_t timeMs = 0;
|
uint32_t timeMs = 0;
|
||||||
|
@ -24,6 +24,17 @@ class IKeyboard : public IHID {
|
||||||
wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED;
|
wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SKeymapEvent {
|
||||||
|
xkb_keymap* keymap = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SModifiersEvent {
|
||||||
|
uint32_t depressed = 0;
|
||||||
|
uint32_t latched = 0;
|
||||||
|
uint32_t locked = 0;
|
||||||
|
uint32_t group = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CSignal key;
|
CSignal key;
|
||||||
CSignal modifiers;
|
CSignal modifiers;
|
||||||
|
@ -39,19 +50,33 @@ class IKeyboard : public IHID {
|
||||||
std::string rules = "";
|
std::string rules = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void setKeymap(const SStringRuleNames& rules);
|
||||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||||
std::string getActiveLayout();
|
std::string getActiveLayout();
|
||||||
void updateLEDs();
|
void updateLEDs();
|
||||||
void updateLEDs(uint32_t leds);
|
void updateLEDs(uint32_t leds);
|
||||||
|
uint32_t getModifiers();
|
||||||
|
void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||||
|
|
||||||
bool active = false;
|
bool active = false;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
|
||||||
xkb_layout_index_t activeLayout = 0;
|
xkb_layout_index_t activeLayout = 0;
|
||||||
xkb_state* xkbTranslationState = nullptr;
|
xkb_state * xkbTranslationState = nullptr, *xkbInternalTranslationState = nullptr;
|
||||||
|
xkb_keymap* xkbKeymap = nullptr;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t depressed = 0, latched = 0, locked = 0, group = 0;
|
||||||
|
} modifiersState;
|
||||||
|
|
||||||
|
std::array<xkb_led_index_t, 3> ledIndexes;
|
||||||
|
std::array<xkb_mod_index_t, 8> modIndexes;
|
||||||
|
uint32_t leds = 0;
|
||||||
|
|
||||||
std::string hlName = "";
|
std::string hlName = "";
|
||||||
std::string xkbFilePath = "";
|
std::string xkbFilePath = "";
|
||||||
|
std::string xkbKeymapString = "";
|
||||||
|
int xkbKeymapFD = -1;
|
||||||
|
|
||||||
SStringRuleNames currentRules;
|
SStringRuleNames currentRules;
|
||||||
int repeatRate = 0;
|
int repeatRate = 0;
|
||||||
|
@ -60,4 +85,8 @@ class IKeyboard : public IHID {
|
||||||
bool resolveBindsBySym = false;
|
bool resolveBindsBySym = false;
|
||||||
|
|
||||||
WP<IKeyboard> self;
|
WP<IKeyboard> self;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void clearManuallyAllocd();
|
||||||
|
bool updateModifiersState(); // rets whether changed
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
#include "../helpers/math/Math.hpp"
|
#include "../helpers/math/Math.hpp"
|
||||||
|
|
||||||
struct wlr_pointer;
|
AQUAMARINE_FORWARD(IPointer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Base class for a pointer.
|
Base class for a pointer.
|
||||||
|
@ -15,7 +15,7 @@ class IPointer : public IHID {
|
||||||
virtual uint32_t getCapabilities();
|
virtual uint32_t getCapabilities();
|
||||||
virtual eHIDType getType();
|
virtual eHIDType getType();
|
||||||
virtual bool isVirtual() = 0;
|
virtual bool isVirtual() = 0;
|
||||||
virtual wlr_pointer* wlr() = 0;
|
virtual SP<Aquamarine::IPointer> aq() = 0;
|
||||||
|
|
||||||
struct SMotionEvent {
|
struct SMotionEvent {
|
||||||
uint32_t timeMs = 0;
|
uint32_t timeMs = 0;
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
#include "../macros.hpp"
|
#include "../macros.hpp"
|
||||||
#include "../helpers/math/Math.hpp"
|
#include "../helpers/math/Math.hpp"
|
||||||
|
|
||||||
struct wlr_touch;
|
AQUAMARINE_FORWARD(ITouch);
|
||||||
|
|
||||||
class ITouch : public IHID {
|
class ITouch : public IHID {
|
||||||
public:
|
public:
|
||||||
virtual uint32_t getCapabilities();
|
virtual uint32_t getCapabilities();
|
||||||
virtual eHIDType getType();
|
virtual eHIDType getType();
|
||||||
virtual bool isVirtual() = 0;
|
virtual bool isVirtual() = 0;
|
||||||
virtual wlr_touch* wlr() = 0;
|
virtual SP<Aquamarine::ITouch> aq() = 0;
|
||||||
|
|
||||||
struct SDownEvent {
|
struct SDownEvent {
|
||||||
uint32_t timeMs = 0;
|
uint32_t timeMs = 0;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "Keyboard.hpp"
|
#include "Keyboard.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
SP<CKeyboard> CKeyboard::create(wlr_keyboard* keeb) {
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
|
SP<CKeyboard> CKeyboard::create(SP<Aquamarine::IKeyboard> keeb) {
|
||||||
SP<CKeyboard> pKeeb = SP<CKeyboard>(new CKeyboard(keeb));
|
SP<CKeyboard> pKeeb = SP<CKeyboard>(new CKeyboard(keeb));
|
||||||
|
|
||||||
pKeeb->self = pKeeb;
|
pKeeb->self = pKeeb;
|
||||||
|
@ -13,52 +15,41 @@ bool CKeyboard::isVirtual() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard* CKeyboard::wlr() {
|
SP<Aquamarine::IKeyboard> CKeyboard::aq() {
|
||||||
return keyboard;
|
return keyboard.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) {
|
CKeyboard::CKeyboard(SP<Aquamarine::IKeyboard> keeb) : keyboard(keeb) {
|
||||||
if (!keeb)
|
if (!keeb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// clang-format off
|
listeners.destroy = keeb->events.destroy.registerListener([this](std::any d) {
|
||||||
hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) {
|
keyboard.reset();
|
||||||
disconnectCallbacks();
|
|
||||||
keyboard = nullptr;
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}, this, "CKeyboard");
|
});
|
||||||
|
|
||||||
hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) {
|
listeners.key = keeb->events.key.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_keyboard_key_event*)data;
|
auto E = std::any_cast<Aquamarine::IKeyboard::SKeyEvent>(d);
|
||||||
|
|
||||||
keyboardEvents.key.emit(SKeyEvent{
|
keyboardEvents.key.emit(SKeyEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.keycode = E->keycode,
|
.keycode = E.key,
|
||||||
.updateMods = E->update_state,
|
.state = E.pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED,
|
||||||
.state = E->state,
|
});
|
||||||
});
|
});
|
||||||
}, this, "CKeyboard");
|
|
||||||
|
|
||||||
hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) {
|
listeners.modifiers = keeb->events.modifiers.registerListener([this](std::any d) {
|
||||||
keyboardEvents.keymap.emit();
|
auto E = std::any_cast<Aquamarine::IKeyboard::SModifiersEvent>(d);
|
||||||
}, this, "CKeyboard");
|
|
||||||
|
|
||||||
hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) {
|
updateModifiers(E.depressed, E.latched, E.locked, E.group);
|
||||||
keyboardEvents.modifiers.emit();
|
|
||||||
}, this, "CKeyboard");
|
|
||||||
|
|
||||||
hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) {
|
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||||
keyboardEvents.repeatInfo.emit();
|
.depressed = modifiersState.depressed,
|
||||||
}, this, "CKeyboard");
|
.latched = modifiersState.latched,
|
||||||
// clang-format on
|
.locked = modifiersState.locked,
|
||||||
|
.group = modifiersState.group,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN";
|
deviceName = keeb->getName();
|
||||||
}
|
|
||||||
|
|
||||||
void CKeyboard::disconnectCallbacks() {
|
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
hyprListener_key.removeCallback();
|
|
||||||
hyprListener_keymap.removeCallback();
|
|
||||||
hyprListener_repeatInfo.removeCallback();
|
|
||||||
hyprListener_modifiers.removeCallback();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,21 +4,19 @@
|
||||||
|
|
||||||
class CKeyboard : public IKeyboard {
|
class CKeyboard : public IKeyboard {
|
||||||
public:
|
public:
|
||||||
static SP<CKeyboard> create(wlr_keyboard* keeb);
|
static SP<CKeyboard> create(SP<Aquamarine::IKeyboard> keeb);
|
||||||
|
|
||||||
virtual bool isVirtual();
|
virtual bool isVirtual();
|
||||||
virtual wlr_keyboard* wlr();
|
virtual SP<Aquamarine::IKeyboard> aq();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CKeyboard(wlr_keyboard* keeb);
|
CKeyboard(SP<Aquamarine::IKeyboard> keeb);
|
||||||
|
|
||||||
wlr_keyboard* keyboard = nullptr;
|
WP<Aquamarine::IKeyboard> keyboard;
|
||||||
|
|
||||||
void disconnectCallbacks();
|
struct {
|
||||||
|
CHyprSignalListener destroy;
|
||||||
DYNLISTENER(destroy);
|
CHyprSignalListener key;
|
||||||
DYNLISTENER(key);
|
CHyprSignalListener modifiers;
|
||||||
DYNLISTENER(modifiers);
|
} listeners;
|
||||||
DYNLISTENER(keymap);
|
|
||||||
DYNLISTENER(repeatInfo);
|
|
||||||
};
|
};
|
|
@ -1,7 +1,8 @@
|
||||||
#include "Mouse.hpp"
|
#include "Mouse.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
SP<CMouse> CMouse::create(wlr_pointer* mouse) {
|
SP<CMouse> CMouse::create(SP<Aquamarine::IPointer> mouse) {
|
||||||
SP<CMouse> pMouse = SP<CMouse>(new CMouse(mouse));
|
SP<CMouse> pMouse = SP<CMouse>(new CMouse(mouse));
|
||||||
|
|
||||||
pMouse->self = pMouse;
|
pMouse->self = pMouse;
|
||||||
|
@ -9,166 +10,143 @@ SP<CMouse> CMouse::create(wlr_pointer* mouse) {
|
||||||
return pMouse;
|
return pMouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) {
|
CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
|
||||||
if (!mouse)
|
if (!mouse)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// clang-format off
|
listeners.destroy = mouse->events.destroy.registerListener([this](std::any d) {
|
||||||
hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) {
|
mouse.reset();
|
||||||
disconnectCallbacks();
|
|
||||||
mouse = nullptr;
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}, this, "CMouse");
|
});
|
||||||
|
|
||||||
hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) {
|
listeners.motion = mouse->events.move.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_motion_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SMoveEvent>(d);
|
||||||
|
|
||||||
pointerEvents.motion.emit(SMotionEvent{
|
pointerEvents.motion.emit(SMotionEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.delta = {E->delta_x, E->delta_y},
|
.delta = E.delta,
|
||||||
.unaccel = {E->unaccel_dx, E->unaccel_dy},
|
.unaccel = E.unaccel,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) {
|
listeners.motionAbsolute = mouse->events.warp.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_motion_absolute_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SWarpEvent>(d);
|
||||||
|
|
||||||
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
|
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.absolute = {E->x, E->y},
|
.absolute = E.absolute,
|
||||||
.device = self.lock(),
|
.device = self.lock(),
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
});
|
||||||
|
|
||||||
hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) {
|
listeners.button = mouse->events.button.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_button_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SButtonEvent>(d);
|
||||||
|
|
||||||
pointerEvents.button.emit(SButtonEvent{
|
pointerEvents.button.emit(SButtonEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.button = E->button,
|
.button = E.button,
|
||||||
.state = (wl_pointer_button_state)E->state,
|
.state = E.pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) {
|
listeners.axis = mouse->events.axis.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_axis_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SAxisEvent>(d);
|
||||||
|
|
||||||
pointerEvents.axis.emit(SAxisEvent{
|
pointerEvents.axis.emit(SAxisEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.source = E->source,
|
.source = (wl_pointer_axis_source)E.source,
|
||||||
.axis = E->orientation,
|
.axis = (wl_pointer_axis)E.axis,
|
||||||
.relativeDirection = E->relative_direction,
|
.relativeDirection = (wl_pointer_axis_relative_direction)E.direction,
|
||||||
.delta = E->delta,
|
.delta = E.delta,
|
||||||
.deltaDiscrete = E->delta_discrete,
|
.deltaDiscrete = E.discrete,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) {
|
listeners.frame = mouse->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); });
|
||||||
pointerEvents.frame.emit();
|
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) {
|
listeners.swipeBegin = mouse->events.swipeBegin.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_swipe_begin_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SSwipeBeginEvent>(d);
|
||||||
|
|
||||||
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
|
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.fingers = E->fingers,
|
.fingers = E.fingers,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) {
|
listeners.swipeEnd = mouse->events.swipeEnd.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_swipe_end_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SSwipeEndEvent>(d);
|
||||||
|
|
||||||
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
|
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.cancelled = E->cancelled,
|
.cancelled = E.cancelled,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) {
|
listeners.swipeUpdate = mouse->events.swipeUpdate.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_swipe_update_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SSwipeUpdateEvent>(d);
|
||||||
|
|
||||||
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
|
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.fingers = E->fingers,
|
.fingers = E.fingers,
|
||||||
.delta = {E->dx, E->dy},
|
.delta = E.delta,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) {
|
listeners.pinchBegin = mouse->events.pinchBegin.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_pinch_begin_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SPinchBeginEvent>(d);
|
||||||
|
|
||||||
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
|
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.fingers = E->fingers,
|
.fingers = E.fingers,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) {
|
listeners.pinchEnd = mouse->events.pinchEnd.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_pinch_end_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SPinchEndEvent>(d);
|
||||||
|
|
||||||
pointerEvents.pinchEnd.emit(SPinchEndEvent{
|
pointerEvents.pinchEnd.emit(SPinchEndEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.cancelled = E->cancelled,
|
.cancelled = E.cancelled,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) {
|
listeners.pinchUpdate = mouse->events.pinchUpdate.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_pinch_update_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SPinchUpdateEvent>(d);
|
||||||
|
|
||||||
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
|
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.fingers = E->fingers,
|
.fingers = E.fingers,
|
||||||
.delta = {E->dx, E->dy},
|
.delta = E.delta,
|
||||||
.scale = E->scale,
|
.scale = E.scale,
|
||||||
.rotation = E->rotation,
|
.rotation = E.rotation,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) {
|
listeners.holdBegin = mouse->events.holdBegin.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_hold_begin_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SHoldBeginEvent>(d);
|
||||||
|
|
||||||
pointerEvents.holdBegin.emit(SHoldBeginEvent{
|
pointerEvents.holdBegin.emit(SHoldBeginEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.fingers = E->fingers,
|
.fingers = E.fingers,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) {
|
listeners.holdEnd = mouse->events.holdEnd.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_pointer_hold_end_event*)data;
|
auto E = std::any_cast<Aquamarine::IPointer::SHoldEndEvent>(d);
|
||||||
|
|
||||||
pointerEvents.holdEnd.emit(SHoldEndEvent{
|
pointerEvents.holdEnd.emit(SHoldEndEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.cancelled = E->cancelled,
|
.cancelled = E.cancelled,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CMouse");
|
|
||||||
|
|
||||||
// clang-format on
|
deviceName = mouse->getName();
|
||||||
|
|
||||||
deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMouse::disconnectCallbacks() {
|
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
hyprListener_motion.removeCallback();
|
|
||||||
hyprListener_motionAbsolute.removeCallback();
|
|
||||||
hyprListener_button.removeCallback();
|
|
||||||
hyprListener_axis.removeCallback();
|
|
||||||
hyprListener_frame.removeCallback();
|
|
||||||
hyprListener_swipeBegin.removeCallback();
|
|
||||||
hyprListener_swipeEnd.removeCallback();
|
|
||||||
hyprListener_swipeUpdate.removeCallback();
|
|
||||||
hyprListener_pinchBegin.removeCallback();
|
|
||||||
hyprListener_pinchEnd.removeCallback();
|
|
||||||
hyprListener_pinchUpdate.removeCallback();
|
|
||||||
hyprListener_holdBegin.removeCallback();
|
|
||||||
hyprListener_holdEnd.removeCallback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMouse::isVirtual() {
|
bool CMouse::isVirtual() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_pointer* CMouse::wlr() {
|
SP<Aquamarine::IPointer> CMouse::aq() {
|
||||||
return mouse;
|
return mouse.lock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,33 +4,34 @@
|
||||||
|
|
||||||
class CMouse : public IPointer {
|
class CMouse : public IPointer {
|
||||||
public:
|
public:
|
||||||
static SP<CMouse> create(wlr_pointer* mouse);
|
static SP<CMouse> create(SP<Aquamarine::IPointer> mouse);
|
||||||
|
|
||||||
virtual bool isVirtual();
|
virtual bool isVirtual();
|
||||||
virtual wlr_pointer* wlr();
|
virtual SP<Aquamarine::IPointer> aq();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CMouse(wlr_pointer* mouse);
|
CMouse(SP<Aquamarine::IPointer> mouse);
|
||||||
|
|
||||||
wlr_pointer* mouse = nullptr;
|
WP<Aquamarine::IPointer> mouse;
|
||||||
|
|
||||||
void disconnectCallbacks();
|
struct {
|
||||||
|
CHyprSignalListener destroy;
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
CHyprSignalListener motion;
|
||||||
DYNLISTENER(motion);
|
CHyprSignalListener motionAbsolute;
|
||||||
DYNLISTENER(motionAbsolute);
|
CHyprSignalListener button;
|
||||||
DYNLISTENER(button);
|
CHyprSignalListener axis;
|
||||||
DYNLISTENER(axis);
|
CHyprSignalListener frame;
|
||||||
DYNLISTENER(frame);
|
|
||||||
|
|
||||||
DYNLISTENER(swipeBegin);
|
CHyprSignalListener swipeBegin;
|
||||||
DYNLISTENER(swipeEnd);
|
CHyprSignalListener swipeEnd;
|
||||||
DYNLISTENER(swipeUpdate);
|
CHyprSignalListener swipeUpdate;
|
||||||
|
|
||||||
DYNLISTENER(pinchBegin);
|
CHyprSignalListener pinchBegin;
|
||||||
DYNLISTENER(pinchEnd);
|
CHyprSignalListener pinchEnd;
|
||||||
DYNLISTENER(pinchUpdate);
|
CHyprSignalListener pinchUpdate;
|
||||||
|
|
||||||
DYNLISTENER(holdBegin);
|
CHyprSignalListener holdBegin;
|
||||||
DYNLISTENER(holdEnd);
|
CHyprSignalListener holdEnd;
|
||||||
|
} listeners;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "TouchDevice.hpp"
|
#include "TouchDevice.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
SP<CTouchDevice> CTouchDevice::create(wlr_touch* touch) {
|
SP<CTouchDevice> CTouchDevice::create(SP<Aquamarine::ITouch> touch) {
|
||||||
SP<CTouchDevice> pTouch = SP<CTouchDevice>(new CTouchDevice(touch));
|
SP<CTouchDevice> pTouch = SP<CTouchDevice>(new CTouchDevice(touch));
|
||||||
|
|
||||||
pTouch->self = pTouch;
|
pTouch->self = pTouch;
|
||||||
|
@ -9,78 +10,63 @@ SP<CTouchDevice> CTouchDevice::create(wlr_touch* touch) {
|
||||||
return pTouch;
|
return pTouch;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTouchDevice::CTouchDevice(wlr_touch* touch_) : touch(touch_) {
|
CTouchDevice::CTouchDevice(SP<Aquamarine::ITouch> touch_) : touch(touch_) {
|
||||||
if (!touch)
|
if (!touch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// clang-format off
|
listeners.destroy = touch->events.destroy.registerListener([this](std::any d) {
|
||||||
hyprListener_destroy.initCallback(&touch->base.events.destroy, [this] (void* owner, void* data) {
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
disconnectCallbacks();
|
touch.reset();
|
||||||
touch = nullptr;
|
});
|
||||||
}, this, "CTouchDevice");
|
|
||||||
|
|
||||||
hyprListener_down.initCallback(&touch->events.down, [this] (void* owner, void* data) {
|
listeners.down = touch->events.down.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_touch_down_event*)data;
|
auto E = std::any_cast<Aquamarine::ITouch::SDownEvent>(d);
|
||||||
|
|
||||||
touchEvents.down.emit(SDownEvent{
|
touchEvents.down.emit(SDownEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.touchID = E->touch_id,
|
.touchID = E.touchID,
|
||||||
.pos = {E->x, E->y},
|
.pos = E.pos,
|
||||||
.device = self.lock(),
|
.device = self.lock(),
|
||||||
});
|
});
|
||||||
}, this, "CTouchDevice");
|
});
|
||||||
|
|
||||||
hyprListener_up.initCallback(&touch->events.up, [this] (void* owner, void* data) {
|
listeners.up = touch->events.up.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_touch_up_event*)data;
|
auto E = std::any_cast<Aquamarine::ITouch::SUpEvent>(d);
|
||||||
|
|
||||||
touchEvents.up.emit(SUpEvent{
|
touchEvents.up.emit(SUpEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.touchID = E->touch_id
|
.touchID = E.touchID,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CTouchDevice");
|
|
||||||
|
|
||||||
hyprListener_motion.initCallback(&touch->events.motion, [this] (void* owner, void* data) {
|
listeners.motion = touch->events.move.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_touch_motion_event*)data;
|
auto E = std::any_cast<Aquamarine::ITouch::SMotionEvent>(d);
|
||||||
|
|
||||||
touchEvents.motion.emit(SMotionEvent{
|
touchEvents.motion.emit(SMotionEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.touchID = E->touch_id,
|
.touchID = E.touchID,
|
||||||
.pos = {E->x, E->y},
|
.pos = E.pos,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CTouchDevice");
|
|
||||||
|
|
||||||
hyprListener_cancel.initCallback(&touch->events.cancel, [this] (void* owner, void* data) {
|
listeners.cancel = touch->events.cancel.registerListener([this](std::any d) {
|
||||||
auto E = (wlr_touch_cancel_event*)data;
|
auto E = std::any_cast<Aquamarine::ITouch::SCancelEvent>(d);
|
||||||
|
|
||||||
touchEvents.cancel.emit(SCancelEvent{
|
touchEvents.cancel.emit(SCancelEvent{
|
||||||
.timeMs = E->time_msec,
|
.timeMs = E.timeMs,
|
||||||
.touchID = E->touch_id
|
.touchID = E.touchID,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, this, "CTouchDevice");
|
|
||||||
|
|
||||||
hyprListener_frame.initCallback(&touch->events.frame, [this] (void* owner, void* data) {
|
listeners.frame = touch->events.frame.registerListener([this](std::any d) { touchEvents.frame.emit(); });
|
||||||
touchEvents.frame.emit();
|
|
||||||
}, this, "CTouchDevice");
|
|
||||||
|
|
||||||
// clang-format on
|
deviceName = touch->getName();
|
||||||
|
|
||||||
deviceName = touch->base.name ? touch->base.name : "UNKNOWN";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTouchDevice::isVirtual() {
|
bool CTouchDevice::isVirtual() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_touch* CTouchDevice::wlr() {
|
SP<Aquamarine::ITouch> CTouchDevice::aq() {
|
||||||
return touch;
|
return touch.lock();
|
||||||
}
|
|
||||||
|
|
||||||
void CTouchDevice::disconnectCallbacks() {
|
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
hyprListener_down.removeCallback();
|
|
||||||
hyprListener_up.removeCallback();
|
|
||||||
hyprListener_motion.removeCallback();
|
|
||||||
hyprListener_cancel.removeCallback();
|
|
||||||
hyprListener_frame.removeCallback();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,22 @@
|
||||||
|
|
||||||
class CTouchDevice : public ITouch {
|
class CTouchDevice : public ITouch {
|
||||||
public:
|
public:
|
||||||
static SP<CTouchDevice> create(wlr_touch* touch);
|
static SP<CTouchDevice> create(SP<Aquamarine::ITouch> touch);
|
||||||
|
|
||||||
virtual bool isVirtual();
|
virtual bool isVirtual();
|
||||||
virtual wlr_touch* wlr();
|
virtual SP<Aquamarine::ITouch> aq();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CTouchDevice(wlr_touch* touch);
|
CTouchDevice(SP<Aquamarine::ITouch> touch);
|
||||||
|
|
||||||
wlr_touch* touch = nullptr;
|
WP<Aquamarine::ITouch> touch;
|
||||||
|
|
||||||
void disconnectCallbacks();
|
struct {
|
||||||
|
CHyprSignalListener destroy;
|
||||||
DYNLISTENER(destroy);
|
CHyprSignalListener down;
|
||||||
DYNLISTENER(down);
|
CHyprSignalListener up;
|
||||||
DYNLISTENER(up);
|
CHyprSignalListener motion;
|
||||||
DYNLISTENER(motion);
|
CHyprSignalListener cancel;
|
||||||
DYNLISTENER(cancel);
|
CHyprSignalListener frame;
|
||||||
DYNLISTENER(frame);
|
} listeners;
|
||||||
};
|
};
|
|
@ -14,58 +14,37 @@ CVirtualKeyboard::CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb_) : keybo
|
||||||
if (!keeb_)
|
if (!keeb_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto keeb = keeb_->wlr();
|
listeners.destroy = keeb_->events.destroy.registerListener([this](std::any d) {
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) {
|
|
||||||
disconnectCallbacks();
|
|
||||||
keyboard.reset();
|
keyboard.reset();
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}, this, "CVirtualKeyboard");
|
|
||||||
|
|
||||||
hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_keyboard_key_event*)data;
|
|
||||||
|
|
||||||
keyboardEvents.key.emit(SKeyEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.keycode = E->keycode,
|
|
||||||
.updateMods = E->update_state,
|
|
||||||
.state = E->state,
|
|
||||||
});
|
});
|
||||||
}, this, "CVirtualKeyboard");
|
|
||||||
|
|
||||||
hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) {
|
listeners.key = keeb_->events.key.registerListener([this](std::any d) { keyboardEvents.key.emit(d); });
|
||||||
keyboardEvents.keymap.emit();
|
listeners.modifiers = keeb_->events.modifiers.registerListener([this](std::any d) {
|
||||||
}, this, "CVirtualKeyboard");
|
auto E = std::any_cast<SModifiersEvent>(d);
|
||||||
|
updateModifiers(E.depressed, E.latched, E.locked, E.group);
|
||||||
|
keyboardEvents.modifiers.emit(SModifiersEvent{
|
||||||
|
.depressed = modifiersState.depressed,
|
||||||
|
.latched = modifiersState.latched,
|
||||||
|
.locked = modifiersState.locked,
|
||||||
|
.group = modifiersState.group,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) {
|
||||||
|
auto E = std::any_cast<SKeymapEvent>(d);
|
||||||
|
xkbKeymap = xkb_keymap_ref(E.keymap);
|
||||||
|
keyboardEvents.keymap.emit(d);
|
||||||
|
});
|
||||||
|
|
||||||
hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) {
|
deviceName = keeb_->name;
|
||||||
keyboardEvents.modifiers.emit();
|
|
||||||
}, this, "CVirtualKeyboard");
|
|
||||||
|
|
||||||
hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) {
|
|
||||||
keyboardEvents.repeatInfo.emit();
|
|
||||||
}, this, "CVirtualKeyboard");
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVirtualKeyboard::isVirtual() {
|
bool CVirtualKeyboard::isVirtual() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard* CVirtualKeyboard::wlr() {
|
SP<Aquamarine::IKeyboard> CVirtualKeyboard::aq() {
|
||||||
if (keyboard.expired())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return keyboard->wlr();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVirtualKeyboard::disconnectCallbacks() {
|
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
hyprListener_key.removeCallback();
|
|
||||||
hyprListener_keymap.removeCallback();
|
|
||||||
hyprListener_repeatInfo.removeCallback();
|
|
||||||
hyprListener_modifiers.removeCallback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_client* CVirtualKeyboard::getClient() {
|
wl_client* CVirtualKeyboard::getClient() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ class CVirtualKeyboard : public IKeyboard {
|
||||||
static SP<CVirtualKeyboard> create(SP<CVirtualKeyboardV1Resource> keeb);
|
static SP<CVirtualKeyboard> create(SP<CVirtualKeyboardV1Resource> keeb);
|
||||||
|
|
||||||
virtual bool isVirtual();
|
virtual bool isVirtual();
|
||||||
virtual wlr_keyboard* wlr();
|
virtual SP<Aquamarine::IKeyboard> aq();
|
||||||
|
|
||||||
wl_client* getClient();
|
wl_client* getClient();
|
||||||
|
|
||||||
|
@ -18,11 +18,10 @@ class CVirtualKeyboard : public IKeyboard {
|
||||||
|
|
||||||
WP<CVirtualKeyboardV1Resource> keyboard;
|
WP<CVirtualKeyboardV1Resource> keyboard;
|
||||||
|
|
||||||
void disconnectCallbacks();
|
struct {
|
||||||
|
CHyprSignalListener destroy;
|
||||||
DYNLISTENER(destroy);
|
CHyprSignalListener key;
|
||||||
DYNLISTENER(key);
|
CHyprSignalListener modifiers;
|
||||||
DYNLISTENER(modifiers);
|
CHyprSignalListener keymap;
|
||||||
DYNLISTENER(keymap);
|
} listeners;
|
||||||
DYNLISTENER(repeatInfo);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "VirtualPointer.hpp"
|
#include "VirtualPointer.hpp"
|
||||||
#include "../protocols/VirtualPointer.hpp"
|
#include "../protocols/VirtualPointer.hpp"
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
SP<CVirtualPointer> CVirtualPointer::create(SP<CVirtualPointerV1Resource> resource) {
|
SP<CVirtualPointer> CVirtualPointer::create(SP<CVirtualPointerV1Resource> resource) {
|
||||||
SP<CVirtualPointer> pPointer = SP<CVirtualPointer>(new CVirtualPointer(resource));
|
SP<CVirtualPointer> pPointer = SP<CVirtualPointer>(new CVirtualPointer(resource));
|
||||||
|
@ -13,165 +14,32 @@ CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : point
|
||||||
if (!resource->good())
|
if (!resource->good())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto mouse = resource->wlr();
|
listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) {
|
||||||
|
pointer.reset();
|
||||||
// clang-format off
|
|
||||||
hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) {
|
|
||||||
disconnectCallbacks();
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_motion_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.motion.emit(SMotionEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.delta = {E->delta_x, E->delta_y},
|
|
||||||
.unaccel = {E->unaccel_dx, E->unaccel_dy},
|
|
||||||
});
|
});
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) {
|
listeners.motion = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); });
|
||||||
auto E = (wlr_pointer_motion_absolute_event*)data;
|
listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) { pointerEvents.motionAbsolute.emit(d); });
|
||||||
|
listeners.button = pointer->events.button.registerListener([this](std::any d) { pointerEvents.button.emit(d); });
|
||||||
|
listeners.axis = pointer->events.axis.registerListener([this](std::any d) { pointerEvents.axis.emit(d); });
|
||||||
|
listeners.frame = pointer->events.frame.registerListener([this](std::any d) { pointerEvents.frame.emit(); });
|
||||||
|
listeners.swipeBegin = pointer->events.swipeBegin.registerListener([this](std::any d) { pointerEvents.swipeBegin.emit(d); });
|
||||||
|
listeners.swipeEnd = pointer->events.swipeEnd.registerListener([this](std::any d) { pointerEvents.swipeEnd.emit(d); });
|
||||||
|
listeners.swipeUpdate = pointer->events.swipeUpdate.registerListener([this](std::any d) { pointerEvents.swipeUpdate.emit(d); });
|
||||||
|
listeners.pinchBegin = pointer->events.pinchBegin.registerListener([this](std::any d) { pointerEvents.pinchBegin.emit(d); });
|
||||||
|
listeners.pinchEnd = pointer->events.pinchEnd.registerListener([this](std::any d) { pointerEvents.pinchEnd.emit(d); });
|
||||||
|
listeners.pinchUpdate = pointer->events.pinchUpdate.registerListener([this](std::any d) { pointerEvents.pinchUpdate.emit(d); });
|
||||||
|
listeners.holdBegin = pointer->events.holdBegin.registerListener([this](std::any d) { pointerEvents.holdBegin.emit(d); });
|
||||||
|
listeners.holdEnd = pointer->events.holdEnd.registerListener([this](std::any d) { pointerEvents.holdEnd.emit(d); });
|
||||||
|
|
||||||
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
|
deviceName = pointer->name;
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.absolute = {E->x, E->y},
|
|
||||||
.device = self.lock(),
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_button_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.button.emit(SButtonEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.button = E->button,
|
|
||||||
.state = (wl_pointer_button_state)E->state,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_axis_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.axis.emit(SAxisEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.source = E->source,
|
|
||||||
.axis = E->orientation,
|
|
||||||
.relativeDirection = E->relative_direction,
|
|
||||||
.delta = E->delta,
|
|
||||||
.deltaDiscrete = E->delta_discrete,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_frame.initCallback(&mouse->events.frame, [this] (void* owner, void* data) {
|
|
||||||
pointerEvents.frame.emit();
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_swipe_begin_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.fingers = E->fingers,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_swipe_end_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.cancelled = E->cancelled,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_swipe_update_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.fingers = E->fingers,
|
|
||||||
.delta = {E->dx, E->dy},
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_pinch_begin_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.fingers = E->fingers,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_pinch_end_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.pinchEnd.emit(SPinchEndEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.cancelled = E->cancelled,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_pinch_update_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.fingers = E->fingers,
|
|
||||||
.delta = {E->dx, E->dy},
|
|
||||||
.scale = E->scale,
|
|
||||||
.rotation = E->rotation,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_hold_begin_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.holdBegin.emit(SHoldBeginEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.fingers = E->fingers,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) {
|
|
||||||
auto E = (wlr_pointer_hold_end_event*)data;
|
|
||||||
|
|
||||||
pointerEvents.holdEnd.emit(SHoldEndEvent{
|
|
||||||
.timeMs = E->time_msec,
|
|
||||||
.cancelled = E->cancelled,
|
|
||||||
});
|
|
||||||
}, this, "CVirtualPointer");
|
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVirtualPointer::isVirtual() {
|
bool CVirtualPointer::isVirtual() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVirtualPointer::disconnectCallbacks() {
|
SP<Aquamarine::IPointer> CVirtualPointer::aq() {
|
||||||
hyprListener_destroy.removeCallback();
|
|
||||||
hyprListener_motion.removeCallback();
|
|
||||||
hyprListener_motionAbsolute.removeCallback();
|
|
||||||
hyprListener_button.removeCallback();
|
|
||||||
hyprListener_axis.removeCallback();
|
|
||||||
hyprListener_frame.removeCallback();
|
|
||||||
hyprListener_swipeBegin.removeCallback();
|
|
||||||
hyprListener_swipeEnd.removeCallback();
|
|
||||||
hyprListener_swipeUpdate.removeCallback();
|
|
||||||
hyprListener_pinchBegin.removeCallback();
|
|
||||||
hyprListener_pinchEnd.removeCallback();
|
|
||||||
hyprListener_pinchUpdate.removeCallback();
|
|
||||||
hyprListener_holdBegin.removeCallback();
|
|
||||||
hyprListener_holdEnd.removeCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_pointer* CVirtualPointer::wlr() {
|
|
||||||
if (pointer.expired())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return pointer->wlr();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,30 +9,31 @@ class CVirtualPointer : public IPointer {
|
||||||
static SP<CVirtualPointer> create(SP<CVirtualPointerV1Resource> resource);
|
static SP<CVirtualPointer> create(SP<CVirtualPointerV1Resource> resource);
|
||||||
|
|
||||||
virtual bool isVirtual();
|
virtual bool isVirtual();
|
||||||
virtual wlr_pointer* wlr();
|
virtual SP<Aquamarine::IPointer> aq();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CVirtualPointer(SP<CVirtualPointerV1Resource>);
|
CVirtualPointer(SP<CVirtualPointerV1Resource>);
|
||||||
|
|
||||||
WP<CVirtualPointerV1Resource> pointer;
|
WP<CVirtualPointerV1Resource> pointer;
|
||||||
|
|
||||||
void disconnectCallbacks();
|
struct {
|
||||||
|
CHyprSignalListener destroy;
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
CHyprSignalListener motion;
|
||||||
DYNLISTENER(motion);
|
CHyprSignalListener motionAbsolute;
|
||||||
DYNLISTENER(motionAbsolute);
|
CHyprSignalListener button;
|
||||||
DYNLISTENER(button);
|
CHyprSignalListener axis;
|
||||||
DYNLISTENER(axis);
|
CHyprSignalListener frame;
|
||||||
DYNLISTENER(frame);
|
|
||||||
|
|
||||||
DYNLISTENER(swipeBegin);
|
CHyprSignalListener swipeBegin;
|
||||||
DYNLISTENER(swipeEnd);
|
CHyprSignalListener swipeEnd;
|
||||||
DYNLISTENER(swipeUpdate);
|
CHyprSignalListener swipeUpdate;
|
||||||
|
|
||||||
DYNLISTENER(pinchBegin);
|
CHyprSignalListener pinchBegin;
|
||||||
DYNLISTENER(pinchEnd);
|
CHyprSignalListener pinchEnd;
|
||||||
DYNLISTENER(pinchUpdate);
|
CHyprSignalListener pinchUpdate;
|
||||||
|
|
||||||
DYNLISTENER(holdBegin);
|
CHyprSignalListener holdBegin;
|
||||||
DYNLISTENER(holdEnd);
|
CHyprSignalListener holdEnd;
|
||||||
|
} listeners;
|
||||||
};
|
};
|
|
@ -21,15 +21,15 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
||||||
switch (DEVICE->type) {
|
switch (DEVICE->type) {
|
||||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||||
Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name);
|
Debug::log(LOG, "Attached a keyboard with name {}", DEVICE->name);
|
||||||
g_pInputManager->newKeyboard(DEVICE);
|
//g_pInputManager->newKeyboard(DEVICE);
|
||||||
break;
|
break;
|
||||||
case WLR_INPUT_DEVICE_POINTER:
|
case WLR_INPUT_DEVICE_POINTER:
|
||||||
Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name);
|
Debug::log(LOG, "Attached a mouse with name {}", DEVICE->name);
|
||||||
g_pInputManager->newMouse(DEVICE);
|
//g_pInputManager->newMouse(DEVICE);
|
||||||
break;
|
break;
|
||||||
case WLR_INPUT_DEVICE_TOUCH:
|
case WLR_INPUT_DEVICE_TOUCH:
|
||||||
Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name);
|
Debug::log(LOG, "Attached a touch device with name {}", DEVICE->name);
|
||||||
g_pInputManager->newTouchDevice(DEVICE);
|
// g_pInputManager->newTouchDevice(DEVICE);
|
||||||
break;
|
break;
|
||||||
case WLR_INPUT_DEVICE_TABLET:
|
case WLR_INPUT_DEVICE_TABLET:
|
||||||
Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name);
|
Debug::log(LOG, "Attached a tablet with name {}", DEVICE->name);
|
||||||
|
|
|
@ -16,88 +16,6 @@
|
||||||
// //
|
// //
|
||||||
// --------------------------------------------------------- //
|
// --------------------------------------------------------- //
|
||||||
|
|
||||||
static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitorName) {
|
|
||||||
|
|
||||||
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
|
|
||||||
static auto firstMonitorAdded = std::chrono::steady_clock::now();
|
|
||||||
static bool cursorDefaultDone = false;
|
|
||||||
static bool firstLaunch = true;
|
|
||||||
|
|
||||||
const auto POS = PNEWMONITOR->middle();
|
|
||||||
|
|
||||||
// by default, cursor should be set to first monitor detected
|
|
||||||
// this is needed as a default if the monitor given in config above doesn't exist
|
|
||||||
if (firstLaunch) {
|
|
||||||
firstLaunch = false;
|
|
||||||
g_pCompositor->warpCursorTo(POS, true);
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// after 10s, don't set cursor to default monitor
|
|
||||||
auto timePassedSec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - firstMonitorAdded);
|
|
||||||
if (timePassedSec.count() > 10) {
|
|
||||||
cursorDefaultDone = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*PCURSORMONITOR == monitorName) {
|
|
||||||
cursorDefaultDone = true;
|
|
||||||
g_pCompositor->warpCursorTo(POS, true);
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|
||||||
// new monitor added, let's accommodate for that.
|
|
||||||
const auto OUTPUT = (wlr_output*)data;
|
|
||||||
|
|
||||||
if (!OUTPUT->name) {
|
|
||||||
Debug::log(ERR, "New monitor has no name?? Ignoring");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add it to real
|
|
||||||
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>());
|
|
||||||
if (std::string("HEADLESS-1") == OUTPUT->name)
|
|
||||||
g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get();
|
|
||||||
|
|
||||||
PNEWMONITOR->output = OUTPUT;
|
|
||||||
PNEWMONITOR->self = PNEWMONITOR;
|
|
||||||
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false;
|
|
||||||
PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
|
||||||
PNEWMONITOR->isUnsafeFallback = FALLBACK;
|
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR);
|
|
||||||
|
|
||||||
if (!FALLBACK)
|
|
||||||
PNEWMONITOR->onConnect(false);
|
|
||||||
|
|
||||||
if (!PNEWMONITOR->m_bEnabled || FALLBACK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// ready to process if we have a real monitor
|
|
||||||
|
|
||||||
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
|
||||||
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR.get();
|
|
||||||
|
|
||||||
g_pCompositor->m_bReadyToProcess = true;
|
|
||||||
|
|
||||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get());
|
|
||||||
|
|
||||||
checkDefaultCursorWarp(PNEWMONITOR, OUTPUT->name);
|
|
||||||
|
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
|
||||||
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
|
||||||
w->m_iLastSurfaceMonitorID = -1;
|
|
||||||
w->updateSurfaceScaleTransformDetails();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_monitorFrame(void* owner, void* data) {
|
void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
if (g_pCompositor->m_bExitTriggered) {
|
if (g_pCompositor->m_bExitTriggered) {
|
||||||
// Only signal cleanup once
|
// Only signal cleanup once
|
||||||
|
@ -108,18 +26,19 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
|
|
||||||
CMonitor* const PMONITOR = (CMonitor*)owner;
|
CMonitor* const PMONITOR = (CMonitor*)owner;
|
||||||
|
|
||||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
// FIXME:
|
||||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
// if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||||
|
// Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||||
|
|
||||||
if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) {
|
// if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) {
|
||||||
return m->output != g_pCompositor->m_pUnsafeOutput->output;
|
// return m->output != g_pCompositor->m_pUnsafeOutput->output;
|
||||||
})) {
|
// })) {
|
||||||
// restore from unsafe state
|
// // restore from unsafe state
|
||||||
g_pCompositor->leaveUnsafeState();
|
// g_pCompositor->leaveUnsafeState();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return; // cannot draw on session inactive (different tty)
|
// return; // cannot draw on session inactive (different tty)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!PMONITOR->m_bEnabled)
|
if (!PMONITOR->m_bEnabled)
|
||||||
return;
|
return;
|
||||||
|
@ -172,12 +91,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
const auto OUTPUT = (wlr_output*)data;
|
|
||||||
|
|
||||||
CMonitor* pMonitor = nullptr;
|
CMonitor* pMonitor = nullptr;
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||||
if (m->output == OUTPUT) {
|
if (m->output == pMonitor->output) {
|
||||||
pMonitor = m.get();
|
pMonitor = m.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -188,9 +105,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
|
|
||||||
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
||||||
|
|
||||||
if (pMonitor->output->idle_frame)
|
|
||||||
wl_event_source_remove(pMonitor->output->idle_frame);
|
|
||||||
|
|
||||||
pMonitor->onDisconnect(true);
|
pMonitor->onDisconnect(true);
|
||||||
|
|
||||||
pMonitor->output = nullptr;
|
pMonitor->output = nullptr;
|
||||||
|
@ -202,20 +116,20 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorStateRequest(void* owner, void* data) {
|
void Events::listener_monitorStateRequest(void* owner, void* data) {
|
||||||
const auto PMONITOR = (CMonitor*)owner;
|
// const auto PMONITOR = (CMonitor*)owner;
|
||||||
const auto E = (wlr_output_event_request_state*)data;
|
// const auto E = (wlr_output_event_request_state*)data;
|
||||||
|
|
||||||
if (!PMONITOR->createdByUser)
|
// if (!PMONITOR->createdByUser)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
|
// const auto SIZE = E->state->mode ? Vector2D{E->state->mode->width, E->state->mode->height} : Vector2D{E->state->custom_mode.width, E->state->custom_mode.height};
|
||||||
|
|
||||||
PMONITOR->forceSize = SIZE;
|
// PMONITOR->forceSize = SIZE;
|
||||||
|
|
||||||
SMonitorRule rule = PMONITOR->activeMonitorRule;
|
// SMonitorRule rule = PMONITOR->activeMonitorRule;
|
||||||
rule.resolution = SIZE;
|
// rule.resolution = SIZE;
|
||||||
|
|
||||||
g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
|
// g_pHyprRenderer->applyMonitorRule(PMONITOR, &rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDamage(void* owner, void* data) {
|
void Events::listener_monitorDamage(void* owner, void* data) {
|
||||||
|
@ -234,11 +148,9 @@ void Events::listener_monitorNeedsFrame(void* owner, void* data) {
|
||||||
void Events::listener_monitorCommit(void* owner, void* data) {
|
void Events::listener_monitorCommit(void* owner, void* data) {
|
||||||
const auto PMONITOR = (CMonitor*)owner;
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
|
|
||||||
const auto E = (wlr_output_event_commit*)data;
|
if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER
|
||||||
|
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR);
|
||||||
if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR);
|
||||||
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
|
|
||||||
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct SPixelFormat {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDRMFormat {
|
struct SDRMFormat {
|
||||||
uint32_t format = 0;
|
DRMFormat format = 0; /* DRM_FORMAT_INVALID */
|
||||||
std::vector<uint64_t> mods;
|
std::vector<uint64_t> mods;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../devices/ITouch.hpp"
|
#include "../devices/ITouch.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/PresentationTime.hpp"
|
#include "../protocols/PresentationTime.hpp"
|
||||||
|
#include "../protocols/core/Output.hpp"
|
||||||
#include "../managers/PointerManager.hpp"
|
#include "../managers/PointerManager.hpp"
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
@ -21,14 +22,6 @@ CMonitor::CMonitor() : state(this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitor::~CMonitor() {
|
CMonitor::~CMonitor() {
|
||||||
hyprListener_monitorDestroy.removeCallback();
|
|
||||||
hyprListener_monitorFrame.removeCallback();
|
|
||||||
hyprListener_monitorStateRequest.removeCallback();
|
|
||||||
hyprListener_monitorDamage.removeCallback();
|
|
||||||
hyprListener_monitorNeedsFrame.removeCallback();
|
|
||||||
hyprListener_monitorCommit.removeCallback();
|
|
||||||
hyprListener_monitorBind.removeCallback();
|
|
||||||
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,43 +33,48 @@ static void onPresented(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::onConnect(bool noRule) {
|
void CMonitor::onConnect(bool noRule) {
|
||||||
hyprListener_monitorDestroy.removeCallback();
|
|
||||||
hyprListener_monitorFrame.removeCallback();
|
|
||||||
hyprListener_monitorStateRequest.removeCallback();
|
|
||||||
hyprListener_monitorDamage.removeCallback();
|
|
||||||
hyprListener_monitorNeedsFrame.removeCallback();
|
|
||||||
hyprListener_monitorCommit.removeCallback();
|
|
||||||
hyprListener_monitorBind.removeCallback();
|
|
||||||
hyprListener_monitorPresented.removeCallback();
|
|
||||||
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this, "CMonitor");
|
|
||||||
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this, "CMonitor");
|
|
||||||
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this, "CMonitor");
|
|
||||||
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this, "CMonitor");
|
|
||||||
hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this, "CMonitor");
|
|
||||||
hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this, "CMonitor");
|
|
||||||
hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this, "CMonitor");
|
|
||||||
hyprListener_monitorPresented.initCallback(&output->events.present, ::onPresented, this, "CMonitor");
|
|
||||||
|
|
||||||
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); });
|
||||||
|
listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); });
|
||||||
|
listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); });
|
||||||
|
listeners.needsFrame = output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this); });
|
||||||
|
|
||||||
|
listeners.state = output->events.state.registerListener([this](std::any d) {
|
||||||
|
if (!createdByUser)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto E = std::any_cast<Aquamarine::IOutput::SStateEvent>(d);
|
||||||
|
|
||||||
|
const auto SIZE = E.size;
|
||||||
|
|
||||||
|
forceSize = SIZE;
|
||||||
|
|
||||||
|
SMonitorRule rule = activeMonitorRule;
|
||||||
|
rule.resolution = SIZE;
|
||||||
|
|
||||||
|
g_pHyprRenderer->applyMonitorRule(this, &rule);
|
||||||
|
});
|
||||||
|
|
||||||
|
tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
|
||||||
|
|
||||||
if (m_bEnabled) {
|
if (m_bEnabled) {
|
||||||
wlr_output_state_set_enabled(state.wlr(), true);
|
output->state->setEnabled(true);
|
||||||
state.commit();
|
state.commit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
szName = output->name;
|
szName = output->name;
|
||||||
|
|
||||||
szDescription = output->description ? output->description : "";
|
szDescription = output->description;
|
||||||
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
||||||
std::erase(szDescription, ',');
|
std::erase(szDescription, ',');
|
||||||
|
|
||||||
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
// field is backwards-compatible with intended usage of `szDescription` but excludes the parenthesized DRM node name suffix
|
||||||
szShortDescription = trim(std::format("{} {} {}", output->make ? output->make : "", output->model ? output->model : "", output->serial ? output->serial : ""));
|
szShortDescription = trim(std::format("{} {} {}", output->make, output->model, output->serial));
|
||||||
std::erase(szShortDescription, ',');
|
std::erase(szShortDescription, ',');
|
||||||
|
|
||||||
if (!wlr_backend_is_drm(output->backend))
|
if (output->getBackend()->type() != Aquamarine::AQ_BACKEND_DRM)
|
||||||
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
createdByUser = true; // should be true. WL and Headless backends should be addable / removable
|
||||||
|
|
||||||
// get monitor rule that matches
|
// get monitor rule that matches
|
||||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(*this);
|
||||||
|
@ -84,56 +82,26 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
// if it's disabled, disable and ignore
|
// if it's disabled, disable and ignore
|
||||||
if (monitorRule.disabled) {
|
if (monitorRule.disabled) {
|
||||||
|
|
||||||
wlr_output_state_set_scale(state.wlr(), 1);
|
output->state->setEnabled(false);
|
||||||
wlr_output_state_set_transform(state.wlr(), WL_OUTPUT_TRANSFORM_NORMAL);
|
|
||||||
|
|
||||||
auto PREFSTATE = wlr_output_preferred_mode(output);
|
|
||||||
|
|
||||||
if (!PREFSTATE) {
|
|
||||||
wlr_output_mode* mode;
|
|
||||||
|
|
||||||
wl_list_for_each(mode, &output->modes, link) {
|
|
||||||
wlr_output_state_set_mode(state.wlr(), mode);
|
|
||||||
|
|
||||||
if (!wlr_output_test_state(output, state.wlr()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
PREFSTATE = mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PREFSTATE)
|
|
||||||
wlr_output_state_set_mode(state.wlr(), PREFSTATE);
|
|
||||||
else
|
|
||||||
Debug::log(WARN, "No mode found for disabled output {}", output->name);
|
|
||||||
|
|
||||||
wlr_output_state_set_enabled(state.wlr(), 0);
|
|
||||||
|
|
||||||
if (!state.commit())
|
if (!state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
Debug::log(ERR, "Couldn't commit disabled state on output {}", output->name);
|
||||||
|
|
||||||
m_bEnabled = false;
|
m_bEnabled = false;
|
||||||
|
|
||||||
hyprListener_monitorFrame.removeCallback();
|
listeners.frame.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output->non_desktop) {
|
if (output->nonDesktop) {
|
||||||
Debug::log(LOG, "Not configuring non-desktop output");
|
Debug::log(LOG, "Not configuring non-desktop output");
|
||||||
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
|
// TODO:
|
||||||
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
|
// if (g_pCompositor->m_sWRLDRMLeaseMgr) {
|
||||||
}
|
// wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
|
||||||
|
// }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bRenderingInitPassed) {
|
|
||||||
output->allocator = nullptr;
|
|
||||||
output->renderer = nullptr;
|
|
||||||
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
|
||||||
m_bRenderingInitPassed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SP<CMonitor>* thisWrapper = nullptr;
|
SP<CMonitor>* thisWrapper = nullptr;
|
||||||
|
|
||||||
// find the wrap
|
// find the wrap
|
||||||
|
@ -151,7 +119,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
m_bEnabled = true;
|
m_bEnabled = true;
|
||||||
|
|
||||||
wlr_output_state_set_enabled(state.wlr(), 1);
|
output->state->setEnabled(true);
|
||||||
|
|
||||||
// set mode, also applies
|
// set mode, also applies
|
||||||
if (!noRule)
|
if (!noRule)
|
||||||
|
@ -261,12 +229,10 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hyprListener_monitorFrame.removeCallback();
|
listeners.frame.reset();
|
||||||
hyprListener_monitorPresented.removeCallback();
|
listeners.presented.reset();
|
||||||
hyprListener_monitorDamage.removeCallback();
|
listeners.needsFrame.reset();
|
||||||
hyprListener_monitorNeedsFrame.removeCallback();
|
listeners.commit.reset();
|
||||||
hyprListener_monitorCommit.removeCallback();
|
|
||||||
hyprListener_monitorBind.removeCallback();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
||||||
|
@ -316,10 +282,10 @@ void CMonitor::onDisconnect(bool destroy) {
|
||||||
activeWorkspace->m_bVisible = false;
|
activeWorkspace->m_bVisible = false;
|
||||||
activeWorkspace.reset();
|
activeWorkspace.reset();
|
||||||
|
|
||||||
wlr_output_state_set_enabled(state.wlr(), false);
|
output->state->setEnabled(false);
|
||||||
|
|
||||||
if (!state.commit())
|
if (!state.commit())
|
||||||
Debug::log(WARN, "wlr_output_commit_state failed in CMonitor::onDisconnect");
|
Debug::log(WARN, "state.commit() failed in CMonitor::onDisconnect");
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor.get() == this)
|
if (g_pCompositor->m_pLastMonitor.get() == this)
|
||||||
g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput);
|
g_pCompositor->setActiveMonitor(BACKUPMON ? BACKUPMON : g_pCompositor->m_pUnsafeOutput);
|
||||||
|
@ -369,8 +335,8 @@ bool CMonitor::shouldSkipScheduleFrameOnMouseEvent() {
|
||||||
static auto PMINRR = CConfigValue<Hyprlang::INT>("cursor:min_refresh_rate");
|
static auto PMINRR = CConfigValue<Hyprlang::INT>("cursor:min_refresh_rate");
|
||||||
|
|
||||||
// skip scheduling extra frames for fullsreen apps with vrr
|
// skip scheduling extra frames for fullsreen apps with vrr
|
||||||
bool shouldSkip = *PNOBREAK && output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow &&
|
bool shouldSkip =
|
||||||
activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL;
|
*PNOBREAK && output->state->state().adaptiveSync && activeWorkspace && activeWorkspace->m_bHasFullscreenWindow && activeWorkspace->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||||
|
|
||||||
// keep requested minimum refresh rate
|
// keep requested minimum refresh rate
|
||||||
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) {
|
if (shouldSkip && *PMINRR && lastPresentationTimer.getMillis() > 1000 / *PMINRR) {
|
||||||
|
@ -563,7 +529,7 @@ float CMonitor::getDefaultScale() {
|
||||||
static constexpr double MMPERINCH = 25.4;
|
static constexpr double MMPERINCH = 25.4;
|
||||||
|
|
||||||
const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2));
|
const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2));
|
||||||
const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2));
|
const auto DIAGONALIN = sqrt(pow(output->physicalSize.x / MMPERINCH, 2) + pow(output->physicalSize.y / MMPERINCH, 2));
|
||||||
|
|
||||||
const auto PPI = DIAGONALPX / DIAGONALIN;
|
const auto PPI = DIAGONALPX / DIAGONALIN;
|
||||||
|
|
||||||
|
@ -784,31 +750,35 @@ CBox CMonitor::logicalBox() {
|
||||||
return {vecPosition, vecSize};
|
return {vecPosition, vecSize};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void onDoneSource(void* data) {
|
||||||
|
auto pMonitor = (CMonitor*)data;
|
||||||
|
|
||||||
|
if (!PROTO::outputs.contains(pMonitor->szName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PROTO::outputs.at(pMonitor->szName)->sendDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitor::scheduleDone() {
|
||||||
|
if (doneSource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
doneSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, ::onDoneSource, this);
|
||||||
|
}
|
||||||
|
|
||||||
CMonitorState::CMonitorState(CMonitor* owner) {
|
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||||
m_pOwner = owner;
|
m_pOwner = owner;
|
||||||
wlr_output_state_init(&m_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMonitorState::~CMonitorState() {
|
CMonitorState::~CMonitorState() {
|
||||||
wlr_output_state_finish(&m_state);
|
;
|
||||||
}
|
|
||||||
|
|
||||||
wlr_output_state* CMonitorState::wlr() {
|
|
||||||
return &m_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMonitorState::clear() {
|
|
||||||
wlr_output_state_finish(&m_state);
|
|
||||||
m_state = {0};
|
|
||||||
wlr_output_state_init(&m_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitorState::commit() {
|
bool CMonitorState::commit() {
|
||||||
bool ret = wlr_output_commit_state(m_pOwner->output, &m_state);
|
bool ret = m_pOwner->output->commit();
|
||||||
clear();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitorState::test() {
|
bool CMonitorState::test() {
|
||||||
return wlr_output_test_state(m_pOwner->output, &m_state);
|
return m_pOwner->output->test();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include "signal/Signal.hpp"
|
#include "signal/Signal.hpp"
|
||||||
#include "DamageRing.hpp"
|
#include "DamageRing.hpp"
|
||||||
|
#include <aquamarine/output/Output.hpp>
|
||||||
|
#include <aquamarine/allocator/Swapchain.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 {
|
enum eAutoDirs {
|
||||||
|
@ -45,14 +47,10 @@ class CMonitorState {
|
||||||
CMonitorState(CMonitor* owner);
|
CMonitorState(CMonitor* owner);
|
||||||
~CMonitorState();
|
~CMonitorState();
|
||||||
|
|
||||||
wlr_output_state* wlr();
|
|
||||||
void clear();
|
|
||||||
// commit() will also clear()
|
|
||||||
bool commit();
|
bool commit();
|
||||||
bool test();
|
bool test();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wlr_output_state m_state = {0};
|
|
||||||
CMonitor* m_pOwner;
|
CMonitor* m_pOwner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,7 +85,7 @@ class CMonitor {
|
||||||
CMonitorState state;
|
CMonitorState state;
|
||||||
CDamageRing damage;
|
CDamageRing damage;
|
||||||
|
|
||||||
wlr_output* output = nullptr;
|
SP<Aquamarine::IOutput> output;
|
||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
int framesToSkip = 0;
|
int framesToSkip = 0;
|
||||||
int forceFullFrames = 0;
|
int forceFullFrames = 0;
|
||||||
|
@ -97,7 +95,8 @@ class CMonitor {
|
||||||
float xwaylandScale = 1.f;
|
float xwaylandScale = 1.f;
|
||||||
std::array<float, 9> projMatrix = {0};
|
std::array<float, 9> projMatrix = {0};
|
||||||
std::optional<Vector2D> forceSize;
|
std::optional<Vector2D> forceSize;
|
||||||
wlr_output_mode* currentMode = nullptr;
|
SP<Aquamarine::SOutputMode> currentMode;
|
||||||
|
SP<Aquamarine::CSwapchain> cursorSwapchain;
|
||||||
|
|
||||||
bool dpmsStatus = true;
|
bool dpmsStatus = true;
|
||||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||||
|
@ -143,15 +142,6 @@ class CMonitor {
|
||||||
|
|
||||||
std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers;
|
std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers;
|
||||||
|
|
||||||
DYNLISTENER(monitorFrame);
|
|
||||||
DYNLISTENER(monitorDestroy);
|
|
||||||
DYNLISTENER(monitorStateRequest);
|
|
||||||
DYNLISTENER(monitorDamage);
|
|
||||||
DYNLISTENER(monitorNeedsFrame);
|
|
||||||
DYNLISTENER(monitorCommit);
|
|
||||||
DYNLISTENER(monitorBind);
|
|
||||||
DYNLISTENER(monitorPresented);
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void onConnect(bool noRule);
|
void onConnect(bool noRule);
|
||||||
void onDisconnect(bool destroy = false);
|
void onDisconnect(bool destroy = false);
|
||||||
|
@ -173,6 +163,7 @@ class CMonitor {
|
||||||
int64_t activeWorkspaceID();
|
int64_t activeWorkspaceID();
|
||||||
int64_t activeSpecialWorkspaceID();
|
int64_t activeSpecialWorkspaceID();
|
||||||
CBox logicalBox();
|
CBox logicalBox();
|
||||||
|
void scheduleDone();
|
||||||
|
|
||||||
bool m_bEnabled = false;
|
bool m_bEnabled = false;
|
||||||
bool m_bRenderingInitPassed = false;
|
bool m_bRenderingInitPassed = false;
|
||||||
|
@ -186,4 +177,15 @@ class CMonitor {
|
||||||
private:
|
private:
|
||||||
void setupDefaultWS(const SMonitorRule&);
|
void setupDefaultWS(const SMonitorRule&);
|
||||||
int findAvailableDefaultWS();
|
int findAvailableDefaultWS();
|
||||||
|
|
||||||
|
wl_event_source* doneSource = nullptr;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CHyprSignalListener frame;
|
||||||
|
CHyprSignalListener destroy;
|
||||||
|
CHyprSignalListener state;
|
||||||
|
CHyprSignalListener needsFrame;
|
||||||
|
CHyprSignalListener presented;
|
||||||
|
CHyprSignalListener commit;
|
||||||
|
} listeners;
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,3 +106,8 @@
|
||||||
class name; \
|
class name; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AQUAMARINE_FORWARD(name) \
|
||||||
|
namespace Aquamarine { \
|
||||||
|
class name; \
|
||||||
|
}
|
||||||
|
|
|
@ -67,54 +67,61 @@ void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) {
|
||||||
std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; });
|
std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; });
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) {
|
CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||||
CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base);
|
surface = surf;
|
||||||
g_pCursorManager->dropBufferRef(buffer->parent);
|
size = size_;
|
||||||
|
stride = cairo_image_surface_get_stride(surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) {
|
CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData_, const Vector2D& size_, const Vector2D& hot_) : hotspot(hot_) {
|
||||||
CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base);
|
pixelData = pixelData_;
|
||||||
|
size = size_;
|
||||||
if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE)
|
stride = 4 * size_.x;
|
||||||
return false;
|
|
||||||
|
|
||||||
*data = buffer->pixelData ? buffer->pixelData : cairo_image_surface_get_data(buffer->surface);
|
|
||||||
*stride = buffer->stride;
|
|
||||||
*format = DRM_FORMAT_ARGB8888;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
static const wlr_buffer_impl bufferImpl = {
|
|
||||||
.destroy = cursorBufferDestroy,
|
|
||||||
.begin_data_ptr_access = cursorBufferBeginDataPtr,
|
|
||||||
.end_data_ptr_access = cursorBufferEndDataPtr,
|
|
||||||
};
|
|
||||||
|
|
||||||
CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) {
|
|
||||||
wlrBuffer.surface = surf;
|
|
||||||
wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y);
|
|
||||||
wlrBuffer.parent = this;
|
|
||||||
wlrBuffer.stride = cairo_image_surface_get_stride(surf);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCursorManager::CCursorBuffer::CCursorBuffer(uint8_t* pixelData, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) {
|
|
||||||
wlrBuffer.pixelData = pixelData;
|
|
||||||
wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y);
|
|
||||||
wlrBuffer.parent = this;
|
|
||||||
wlrBuffer.stride = 4 * size_.x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CCursorManager::CCursorBuffer::~CCursorBuffer() {
|
CCursorManager::CCursorBuffer::~CCursorBuffer() {
|
||||||
; // will be freed in .destroy
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_buffer* CCursorManager::getCursorBuffer() {
|
Aquamarine::eBufferCapability CCursorManager::CCursorBuffer::caps() {
|
||||||
return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr;
|
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Aquamarine::eBufferType CCursorManager::CCursorBuffer::type() {
|
||||||
|
return Aquamarine::eBufferType::BUFFER_TYPE_SHM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::CCursorBuffer::update(const Hyprutils::Math::CRegion& damage) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCursorManager::CCursorBuffer::isSynchronous() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCursorManager::CCursorBuffer::good() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Aquamarine::SSHMAttrs CCursorManager::CCursorBuffer::shm() {
|
||||||
|
Aquamarine::SSHMAttrs attrs;
|
||||||
|
attrs.success = true;
|
||||||
|
attrs.format = DRM_FORMAT_ARGB8888;
|
||||||
|
attrs.size = size;
|
||||||
|
attrs.stride = stride;
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<uint8_t*, uint32_t, size_t> CCursorManager::CCursorBuffer::beginDataPtr(uint32_t flags) {
|
||||||
|
return {pixelData ? pixelData : cairo_image_surface_get_data(surface), DRM_FORMAT_ARGB8888, stride};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::CCursorBuffer::endDataPtr() {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<Aquamarine::IBuffer> CCursorManager::getCursorBuffer() {
|
||||||
|
return !m_vCursorBuffers.empty() ? m_vCursorBuffers.back() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot) {
|
void CCursorManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot) {
|
||||||
|
@ -150,11 +157,11 @@ void CCursorManager::setXCursor(const std::string& name) {
|
||||||
auto image = xcursor->images[0];
|
auto image = xcursor->images[0];
|
||||||
|
|
||||||
m_vCursorBuffers.emplace_back(
|
m_vCursorBuffers.emplace_back(
|
||||||
std::make_unique<CCursorBuffer>(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y}));
|
makeShared<CCursorBuffer>(image->buffer, Vector2D{(int)image->width, (int)image->height}, Vector2D{(double)image->hotspot_x, (double)image->hotspot_y}));
|
||||||
|
|
||||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale);
|
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{(double)image->hotspot_x, (double)image->hotspot_y} / scale, scale);
|
||||||
if (m_vCursorBuffers.size() > 1)
|
if (m_vCursorBuffers.size() > 1)
|
||||||
wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base);
|
dropBufferRef(m_vCursorBuffers.at(0).get());
|
||||||
|
|
||||||
m_bOurBufferConnected = true;
|
m_bOurBufferConnected = true;
|
||||||
}
|
}
|
||||||
|
@ -196,14 +203,14 @@ void CCursorManager::setCursorFromName(const std::string& name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface,
|
m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface,
|
||||||
Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
||||||
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}));
|
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}));
|
||||||
|
|
||||||
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale,
|
g_pPointerManager->setCursorBuffer(getCursorBuffer(), Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY} / m_fCursorScale,
|
||||||
m_fCursorScale);
|
m_fCursorScale);
|
||||||
if (m_vCursorBuffers.size() > 1)
|
if (m_vCursorBuffers.size() > 1)
|
||||||
wlr_buffer_drop(&m_vCursorBuffers.front()->wlrBuffer.base);
|
dropBufferRef(m_vCursorBuffers.at(0).get());
|
||||||
|
|
||||||
m_bOurBufferConnected = true;
|
m_bOurBufferConnected = true;
|
||||||
|
|
||||||
|
@ -225,7 +232,7 @@ void CCursorManager::tickAnimatedCursor() {
|
||||||
if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size())
|
if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size())
|
||||||
m_iCurrentAnimationFrame = 0;
|
m_iCurrentAnimationFrame = 0;
|
||||||
|
|
||||||
m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(
|
m_vCursorBuffers.emplace_back(makeShared<CCursorBuffer>(
|
||||||
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface,
|
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface,
|
||||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
||||||
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}));
|
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}));
|
||||||
|
|
|
@ -7,16 +7,17 @@
|
||||||
#include "../helpers/math/Math.hpp"
|
#include "../helpers/math/Math.hpp"
|
||||||
#include "../helpers/memory/Memory.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
struct wlr_buffer;
|
|
||||||
struct wlr_xcursor_manager;
|
struct wlr_xcursor_manager;
|
||||||
class CWLSurface;
|
class CWLSurface;
|
||||||
|
|
||||||
|
AQUAMARINE_FORWARD(IBuffer);
|
||||||
|
|
||||||
class CCursorManager {
|
class CCursorManager {
|
||||||
public:
|
public:
|
||||||
CCursorManager();
|
CCursorManager();
|
||||||
~CCursorManager();
|
~CCursorManager();
|
||||||
|
|
||||||
wlr_buffer* getCursorBuffer();
|
SP<Aquamarine::IBuffer> getCursorBuffer();
|
||||||
|
|
||||||
void setCursorFromName(const std::string& name);
|
void setCursorFromName(const std::string& name);
|
||||||
void setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot);
|
void setCursorSurface(SP<CWLSurface> surf, const Vector2D& hotspot);
|
||||||
|
@ -29,24 +30,26 @@ class CCursorManager {
|
||||||
|
|
||||||
void tickAnimatedCursor();
|
void tickAnimatedCursor();
|
||||||
|
|
||||||
class CCursorBuffer {
|
class CCursorBuffer : public Aquamarine::IBuffer {
|
||||||
public:
|
public:
|
||||||
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
||||||
CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot);
|
CCursorBuffer(uint8_t* pixelData, const Vector2D& size, const Vector2D& hotspot);
|
||||||
~CCursorBuffer();
|
~CCursorBuffer();
|
||||||
|
|
||||||
struct SCursorWlrBuffer {
|
virtual Aquamarine::eBufferCapability caps();
|
||||||
wlr_buffer base;
|
virtual Aquamarine::eBufferType type();
|
||||||
cairo_surface_t* surface = nullptr;
|
virtual void update(const Hyprutils::Math::CRegion& damage);
|
||||||
bool dropped = false;
|
virtual bool isSynchronous(); // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||||
CCursorBuffer* parent = nullptr;
|
virtual bool good();
|
||||||
uint8_t* pixelData = nullptr;
|
virtual Aquamarine::SSHMAttrs shm();
|
||||||
size_t stride = 0;
|
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||||
} wlrBuffer;
|
virtual void endDataPtr();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2D size;
|
|
||||||
Vector2D hotspot;
|
Vector2D hotspot;
|
||||||
|
cairo_surface_t* surface = nullptr;
|
||||||
|
uint8_t* pixelData = nullptr;
|
||||||
|
size_t stride = 0;
|
||||||
|
|
||||||
friend class CCursorManager;
|
friend class CCursorManager;
|
||||||
};
|
};
|
||||||
|
@ -56,7 +59,7 @@ class CCursorManager {
|
||||||
bool m_bOurBufferConnected = false;
|
bool m_bOurBufferConnected = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<CCursorBuffer>> m_vCursorBuffers;
|
std::vector<SP<CCursorBuffer>> m_vCursorBuffers;
|
||||||
|
|
||||||
std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor;
|
std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor;
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||||
const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput
|
const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput
|
||||||
|
|
||||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE);
|
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE);
|
||||||
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE);
|
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbInternalTranslationState, KEYCODE);
|
||||||
|
|
||||||
if (handleInternalKeybinds(internalKeysym))
|
if (handleInternalKeybinds(internalKeysym))
|
||||||
return true;
|
return true;
|
||||||
|
@ -554,7 +554,7 @@ int repeatKeyHandler(void* data) {
|
||||||
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
|
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
|
||||||
DISPATCHER->second((*ppActiveKeybind)->arg);
|
DISPATCHER->second((*ppActiveKeybind)->arg);
|
||||||
|
|
||||||
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->wlr()->repeat_info.rate);
|
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pSeatManager->keyboard->repeatRate);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +786,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||||
// beyond this point, return true to not handle anything else.
|
// beyond this point, return true to not handle anything else.
|
||||||
// we'll avoid printing shit to active windows.
|
// we'll avoid printing shit to active windows.
|
||||||
|
|
||||||
if (g_pCompositor->m_sWLRSession) {
|
if (g_pCompositor->m_pAqBackend->hasSession()) {
|
||||||
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.
|
||||||
|
@ -810,7 +810,8 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||||
|
|
||||||
Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY);
|
Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY);
|
||||||
|
|
||||||
wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY);
|
// FIXME:
|
||||||
|
//wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2121,7 +2122,7 @@ void CKeybindManager::sendshortcut(std::string args) {
|
||||||
const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY);
|
const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY);
|
||||||
|
|
||||||
if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) {
|
if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) {
|
||||||
xkb_keymap* km = KB->wlr()->keymap;
|
xkb_keymap* km = KB->xkbKeymap;
|
||||||
xkb_state* ks = KB->xkbTranslationState;
|
xkb_state* ks = KB->xkbTranslationState;
|
||||||
|
|
||||||
xkb_keycode_t keycode_min, keycode_max;
|
xkb_keycode_t keycode_min, keycode_max;
|
||||||
|
@ -2260,7 +2261,7 @@ void CKeybindManager::dpms(std::string arg) {
|
||||||
if (!port.empty() && m->szName != port)
|
if (!port.empty() && m->szName != port)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wlr_output_state_set_enabled(m->state.wlr(), enable);
|
m->output->state->setEnabled(enable);
|
||||||
|
|
||||||
m->dpmsStatus = enable;
|
m->dpmsStatus = enable;
|
||||||
|
|
||||||
|
|
|
@ -10,128 +10,26 @@
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
|
||||||
// TODO: make nicer
|
static Aquamarine::SDRMFormat pickCursorFormat(SP<Aquamarine::IOutput> output) {
|
||||||
// this will come with the eventual rewrite of wlr_drm, etc...
|
|
||||||
static bool wlr_drm_format_intersect(wlr_drm_format* dst, const wlr_drm_format* a, const wlr_drm_format* b) {
|
|
||||||
ASSERT(a->format == b->format);
|
|
||||||
|
|
||||||
size_t capacity = a->len < b->len ? a->len : b->len;
|
const auto fmts = output->getBackend()->getCursorFormats();
|
||||||
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * capacity);
|
|
||||||
if (!modifiers)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct wlr_drm_format fmt = {
|
if (fmts.empty())
|
||||||
.format = a->format,
|
return {};
|
||||||
.len = 0,
|
|
||||||
.capacity = capacity,
|
|
||||||
.modifiers = modifiers,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < a->len; i++) {
|
// try to use common formats in their order
|
||||||
for (size_t j = 0; j < b->len; j++) {
|
std::vector<uint32_t> PREFERRED_FORMATS = {DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888};
|
||||||
if (a->modifiers[i] == b->modifiers[j]) {
|
|
||||||
ASSERT(fmt.len < fmt.capacity);
|
|
||||||
fmt.modifiers[fmt.len++] = a->modifiers[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_drm_format_finish(dst);
|
for (auto& pf : PREFERRED_FORMATS) {
|
||||||
*dst = fmt;
|
for (auto& fmt : fmts) {
|
||||||
return true;
|
if (pf != fmt.drmFormat)
|
||||||
}
|
continue;
|
||||||
|
|
||||||
static bool wlr_drm_format_copy(wlr_drm_format* dst, const wlr_drm_format* src) {
|
return fmt;
|
||||||
ASSERT(src->len <= src->capacity);
|
|
||||||
|
|
||||||
uint64_t* modifiers = (uint64_t*)malloc(sizeof(*modifiers) * src->len);
|
|
||||||
if (!modifiers)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
memcpy(modifiers, src->modifiers, sizeof(*modifiers) * src->len);
|
|
||||||
|
|
||||||
wlr_drm_format_finish(dst);
|
|
||||||
dst->capacity = src->len;
|
|
||||||
dst->len = src->len;
|
|
||||||
dst->format = src->format;
|
|
||||||
dst->modifiers = modifiers;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const wlr_drm_format_set* wlr_renderer_get_render_formats(wlr_renderer* r) {
|
|
||||||
if (!r->impl->get_render_formats)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return r->impl->get_render_formats(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool output_pick_format(wlr_output* output, const wlr_drm_format_set* display_formats, wlr_drm_format* format, uint32_t fmt) {
|
|
||||||
|
|
||||||
const wlr_drm_format_set* render_formats = wlr_renderer_get_render_formats(g_pCompositor->m_sWLRRenderer);
|
|
||||||
if (render_formats == NULL) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to get render formats");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wlr_drm_format* render_format = wlr_drm_format_set_get(render_formats, fmt);
|
|
||||||
if (render_format == NULL) {
|
|
||||||
wlr_log(WLR_DEBUG, "Renderer doesn't support format 0x%" PRIX32, fmt);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display_formats != NULL) {
|
|
||||||
const wlr_drm_format* display_format = wlr_drm_format_set_get(display_formats, fmt);
|
|
||||||
if (display_format == NULL) {
|
|
||||||
wlr_log(WLR_DEBUG, "Output doesn't support format 0x%" PRIX32, fmt);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!wlr_drm_format_intersect(format, display_format, render_format)) {
|
|
||||||
wlr_log(WLR_DEBUG,
|
|
||||||
"Failed to intersect display and render "
|
|
||||||
"modifiers for format 0x%" PRIX32 " on output %s",
|
|
||||||
fmt, output->name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The output can display any format
|
|
||||||
if (!wlr_drm_format_copy(format, render_format))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format->len == 0) {
|
|
||||||
wlr_drm_format_finish(format);
|
|
||||||
wlr_log(WLR_DEBUG, "Failed to pick output format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool output_pick_cursor_format(struct wlr_output* output, struct wlr_drm_format* format) {
|
|
||||||
struct wlr_allocator* allocator = output->allocator;
|
|
||||||
ASSERT(allocator != NULL);
|
|
||||||
|
|
||||||
const struct wlr_drm_format_set* display_formats = NULL;
|
|
||||||
if (output->impl->get_cursor_formats) {
|
|
||||||
display_formats = output->impl->get_cursor_formats(output, allocator->buffer_caps);
|
|
||||||
if (display_formats == NULL) {
|
|
||||||
wlr_log(WLR_DEBUG, "Failed to get cursor display formats");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: taken from https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4596/diffs#diff-content-e3ea164da86650995728d70bd118f6aa8c386797
|
return fmts.at(0);
|
||||||
// If this fails to find a shared modifier try to use a linear
|
|
||||||
// modifier. This avoids a scenario where the hardware cannot render to
|
|
||||||
// linear textures but only linear textures are supported for cursors,
|
|
||||||
// as is the case with Nvidia and VmWare GPUs
|
|
||||||
if (!output_pick_format(output, display_formats, format, DRM_FORMAT_ARGB8888)) {
|
|
||||||
// Clear the format as output_pick_format doesn't zero it
|
|
||||||
memset(format, 0, sizeof(*format));
|
|
||||||
return output_pick_format(output, NULL, format, DRM_FORMAT_ARGB8888);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CPointerManager::CPointerManager() {
|
CPointerManager::CPointerManager() {
|
||||||
|
@ -201,6 +99,11 @@ void CPointerManager::unlockSoftwareForMonitor(SP<CMonitor> mon) {
|
||||||
updateCursorBackend();
|
updateCursorBackend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPointerManager::softwareLockedFor(SP<CMonitor> mon) {
|
||||||
|
auto state = stateFor(mon);
|
||||||
|
return state->softwareLocks > 0 || state->hardwareFailed;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2D CPointerManager::position() {
|
Vector2D CPointerManager::position() {
|
||||||
return pointerPos;
|
return pointerPos;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +119,7 @@ SP<CPointerManager::SMonitorPointerState> CPointerManager::stateFor(SP<CMonitor>
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale) {
|
void CPointerManager::setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale) {
|
||||||
damageIfSoftware();
|
damageIfSoftware();
|
||||||
if (buf == currentCursorImage.pBuffer) {
|
if (buf == currentCursorImage.pBuffer) {
|
||||||
if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) {
|
if (hotspot != currentCursorImage.hotspot || scale != currentCursorImage.scale) {
|
||||||
|
@ -232,11 +135,8 @@ void CPointerManager::setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot,
|
||||||
resetCursorImage(false);
|
resetCursorImage(false);
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
currentCursorImage.size = {buf->width, buf->height};
|
currentCursorImage.size = buf->size;
|
||||||
currentCursorImage.pBuffer = wlr_buffer_lock(buf);
|
currentCursorImage.pBuffer = buf;
|
||||||
|
|
||||||
currentCursorImage.hyprListener_destroyBuffer.initCallback(
|
|
||||||
&buf->events.destroy, [this](void* owner, void* data) { resetCursorImage(); }, this, "CPointerManager");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentCursorImage.hotspot = hotspot;
|
currentCursorImage.hotspot = hotspot;
|
||||||
|
@ -318,8 +218,8 @@ void CPointerManager::recheckEnteredOutputs() {
|
||||||
// if we are using hw cursors, prevent
|
// if we are using hw cursors, prevent
|
||||||
// the cursor from being stuck at the last point.
|
// the cursor from being stuck at the last point.
|
||||||
// if we are leaving it, move it to narnia.
|
// if we are leaving it, move it to narnia.
|
||||||
if (!s->hardwareFailed && s->monitor->output->impl->move_cursor)
|
if (!s->hardwareFailed && (s->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
|
||||||
s->monitor->output->impl->move_cursor(s->monitor->output, -1337, -420);
|
s->monitor->output->moveCursor({-1337, -420});
|
||||||
|
|
||||||
if (!currentCursorImage.surface)
|
if (!currentCursorImage.surface)
|
||||||
continue;
|
continue;
|
||||||
|
@ -340,16 +240,11 @@ void CPointerManager::resetCursorImage(bool apply) {
|
||||||
currentCursorImage.destroySurface.reset();
|
currentCursorImage.destroySurface.reset();
|
||||||
currentCursorImage.commitSurface.reset();
|
currentCursorImage.commitSurface.reset();
|
||||||
currentCursorImage.surface.reset();
|
currentCursorImage.surface.reset();
|
||||||
} else if (currentCursorImage.pBuffer) {
|
} else if (currentCursorImage.pBuffer)
|
||||||
wlr_buffer_unlock(currentCursorImage.pBuffer);
|
|
||||||
currentCursorImage.hyprListener_destroyBuffer.removeCallback();
|
|
||||||
currentCursorImage.pBuffer = nullptr;
|
currentCursorImage.pBuffer = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (currentCursorImage.pBufferTexture) {
|
if (currentCursorImage.bufferTex)
|
||||||
wlr_texture_destroy(currentCursorImage.pBufferTexture);
|
currentCursorImage.bufferTex = nullptr;
|
||||||
currentCursorImage.pBufferTexture = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentCursorImage.scale = 1.F;
|
currentCursorImage.scale = 1.F;
|
||||||
currentCursorImage.hotspot = {0, 0};
|
currentCursorImage.hotspot = {0, 0};
|
||||||
|
@ -371,9 +266,8 @@ void CPointerManager::resetCursorImage(bool apply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ms->cursorFrontBuffer) {
|
if (ms->cursorFrontBuffer) {
|
||||||
if (ms->monitor->output->impl->set_cursor)
|
if (ms->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER)
|
||||||
ms->monitor->output->impl->set_cursor(ms->monitor->output, nullptr, 0, 0);
|
ms->monitor->output->setCursor(nullptr, {});
|
||||||
wlr_buffer_unlock(ms->cursorFrontBuffer);
|
|
||||||
ms->cursorFrontBuffer = nullptr;
|
ms->cursorFrontBuffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,18 +313,18 @@ void CPointerManager::onCursorMoved() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto CURSORPOS = getCursorPosForMonitor(m);
|
const auto CURSORPOS = getCursorPosForMonitor(m);
|
||||||
m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y);
|
m->output->moveCursor(CURSORPOS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) {
|
bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerState> state) {
|
||||||
auto output = state->monitor->output;
|
auto output = state->monitor->output;
|
||||||
|
|
||||||
if (!output->impl->set_cursor)
|
if (!(output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock());
|
const auto CURSORPOS = getCursorPosForMonitor(state->monitor.lock());
|
||||||
state->monitor->output->impl->move_cursor(state->monitor->output, CURSORPOS.x, CURSORPOS.y);
|
state->monitor->output->moveCursor(CURSORPOS);
|
||||||
|
|
||||||
auto texture = getCurrentCursorTexture();
|
auto texture = getCurrentCursorTexture();
|
||||||
|
|
||||||
|
@ -460,64 +354,68 @@ bool CPointerManager::attemptHardwareCursor(SP<CPointerManager::SMonitorPointerS
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf) {
|
bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf) {
|
||||||
if (!state->monitor->output->impl->set_cursor)
|
if (!(state->monitor->output->getBackend()->capabilities() & Aquamarine::IBackendImplementation::eBackendCapabilities::AQ_BACKEND_CAPABILITY_POINTER))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto HOTSPOT = transformedHotspot(state->monitor.lock());
|
const auto HOTSPOT = transformedHotspot(state->monitor.lock());
|
||||||
|
|
||||||
Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT);
|
Debug::log(TRACE, "[pointer] hw transformed hotspot for {}: {}", state->monitor->szName, HOTSPOT);
|
||||||
|
|
||||||
if (!state->monitor->output->impl->set_cursor(state->monitor->output, buf, HOTSPOT.x, HOTSPOT.y))
|
if (!state->monitor->output->setCursor(buf, HOTSPOT))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wlr_buffer_unlock(state->cursorFrontBuffer);
|
|
||||||
state->cursorFrontBuffer = buf;
|
state->cursorFrontBuffer = buf;
|
||||||
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(state->monitor.get());
|
g_pCompositor->scheduleFrameForMonitor(state->monitor.get());
|
||||||
|
|
||||||
if (buf)
|
|
||||||
wlr_buffer_lock(buf);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
|
SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
|
||||||
auto output = state->monitor->output;
|
auto output = state->monitor->output;
|
||||||
|
|
||||||
int w = currentCursorImage.size.x, h = currentCursorImage.size.y;
|
auto maxSize = output->maxCursorSize();
|
||||||
if (output->impl->get_cursor_size) {
|
|
||||||
output->impl->get_cursor_size(output, &w, &h);
|
|
||||||
|
|
||||||
if (w < currentCursorImage.size.x || h < currentCursorImage.size.y) {
|
auto cursorSize = currentCursorImage.size;
|
||||||
Debug::log(TRACE, "hardware cursor too big! {} > {}x{}", currentCursorImage.size, w, h);
|
|
||||||
|
if (cursorSize == Vector2D{})
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// error
|
||||||
|
if (maxSize == Vector2D{})
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (maxSize != Vector2D{-1, -1}) {
|
||||||
|
if (cursorSize.x < maxSize.x || cursorSize.y < maxSize.y) {
|
||||||
|
Debug::log(TRACE, "hardware cursor too big! {} > {}", currentCursorImage.size, maxSize);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w <= 0 || h <= 0) {
|
if (!state->monitor->cursorSwapchain || cursorSize != state->monitor->cursorSwapchain->currentOptions().size) {
|
||||||
Debug::log(TRACE, "hw cursor for output {} failed the size checks ({}x{} is invalid)", state->monitor->szName, w, h);
|
auto format = pickCursorFormat(output);
|
||||||
|
|
||||||
|
if (format.drmFormat == DRM_FORMAT_INVALID) {
|
||||||
|
Debug::log(TRACE, "Failed to pick an output format for hw cursor");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!output->cursor_swapchain || Vector2D{w, h} != Vector2D{output->cursor_swapchain->width, output->cursor_swapchain->height}) {
|
if (!state->monitor->cursorSwapchain)
|
||||||
wlr_drm_format fmt = {0};
|
state->monitor->cursorSwapchain = makeShared<Aquamarine::CSwapchain>(g_pCompositor->m_pAqBackend->allocator);
|
||||||
if (!output_pick_cursor_format(output, &fmt)) {
|
|
||||||
Debug::log(TRACE, "Failed to pick cursor format");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_swapchain_destroy(output->cursor_swapchain);
|
auto options = state->monitor->cursorSwapchain->currentOptions();
|
||||||
output->cursor_swapchain = wlr_swapchain_create(output->allocator, w, h, &fmt);
|
options.size = cursorSize;
|
||||||
wlr_drm_format_finish(&fmt);
|
options.length = 2;
|
||||||
|
options.format = format.drmFormat;
|
||||||
|
|
||||||
if (!output->cursor_swapchain) {
|
if (!state->monitor->cursorSwapchain->reconfigure(options)) {
|
||||||
Debug::log(TRACE, "Failed to create cursor swapchain");
|
Debug::log(TRACE, "Failed to reconfigure cursor swapchain");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_buffer* buf = wlr_swapchain_acquire(output->cursor_swapchain, nullptr);
|
auto buf = state->monitor->cursorSwapchain->next(nullptr);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain");
|
Debug::log(TRACE, "Failed to acquire a buffer from the cursor swapchain");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -526,16 +424,16 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo
|
||||||
CRegion damage = {0, 0, INT16_MAX, INT16_MAX};
|
CRegion damage = {0, 0, INT16_MAX, INT16_MAX};
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get(); // has to be set cuz allocs
|
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor.get();
|
||||||
|
|
||||||
const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, DRM_FORMAT_ARGB8888);
|
const auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
|
||||||
RBO->bind();
|
RBO->bind();
|
||||||
|
|
||||||
g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO);
|
g_pHyprOpenGL->beginSimple(state->monitor.get(), damage, RBO);
|
||||||
g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F});
|
g_pHyprOpenGL->clear(CColor{0.F, 0.F, 0.F, 0.F});
|
||||||
|
|
||||||
CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()};
|
CBox xbox = {{}, Vector2D{currentCursorImage.size / currentCursorImage.scale * state->monitor->scale}.round()};
|
||||||
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, Vector2D{w, h},
|
Debug::log(TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->szName, currentCursorImage.size, cursorSize,
|
||||||
currentCursorImage.scale, state->monitor->scale, xbox.size());
|
currentCursorImage.scale, state->monitor->scale, xbox.size());
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
|
g_pHyprOpenGL->renderTexture(texture, &xbox, 1.F);
|
||||||
|
@ -546,8 +444,6 @@ wlr_buffer* CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPo
|
||||||
|
|
||||||
g_pHyprRenderer->onRenderbufferDestroy(RBO);
|
g_pHyprRenderer->onRenderbufferDestroy(RBO);
|
||||||
|
|
||||||
wlr_buffer_unlock(buf);
|
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,11 +490,12 @@ Vector2D CPointerManager::getCursorPosForMonitor(SP<CMonitor> pMonitor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CPointerManager::transformedHotspot(SP<CMonitor> pMonitor) {
|
Vector2D CPointerManager::transformedHotspot(SP<CMonitor> pMonitor) {
|
||||||
if (!pMonitor->output->cursor_swapchain)
|
if (!pMonitor->cursorSwapchain)
|
||||||
return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors
|
return {}; // doesn't matter, we have no hw cursor, and this is only for hw cursors
|
||||||
|
|
||||||
return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}}
|
return CBox{currentCursorImage.hotspot * pMonitor->scale, {0, 0}}
|
||||||
.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->output->cursor_swapchain->width, pMonitor->output->cursor_swapchain->height)
|
.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->cursorSwapchain->currentOptions().size.x,
|
||||||
|
pMonitor->cursorSwapchain->currentOptions().size.y)
|
||||||
.pos();
|
.pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,10 +697,8 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (currentCursorImage.pBuffer) {
|
if (currentCursorImage.pBuffer) {
|
||||||
if (!currentCursorImage.pBufferTexture) {
|
if (!currentCursorImage.bufferTex)
|
||||||
currentCursorImage.pBufferTexture = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, currentCursorImage.pBuffer);
|
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBuffer);
|
||||||
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBufferTexture);
|
|
||||||
}
|
|
||||||
return currentCursorImage.bufferTex;
|
return currentCursorImage.bufferTex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
struct wlr_input_device;
|
|
||||||
class IHID;
|
class IHID;
|
||||||
class CTexture;
|
class CTexture;
|
||||||
|
|
||||||
|
AQUAMARINE_FORWARD(IBuffer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The naming here is a bit confusing.
|
The naming here is a bit confusing.
|
||||||
CPointerManager manages the _position_ and _displaying_ of the cursor,
|
CPointerManager manages the _position_ and _displaying_ of the cursor,
|
||||||
|
@ -37,7 +38,7 @@ class CPointerManager {
|
||||||
void move(const Vector2D& deltaLogical);
|
void move(const Vector2D& deltaLogical);
|
||||||
void warpAbsolute(Vector2D abs, SP<IHID> dev);
|
void warpAbsolute(Vector2D abs, SP<IHID> dev);
|
||||||
|
|
||||||
void setCursorBuffer(wlr_buffer* buf, const Vector2D& hotspot, const float& scale);
|
void setCursorBuffer(SP<Aquamarine::IBuffer> buf, const Vector2D& hotspot, const float& scale);
|
||||||
void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot);
|
void setCursorSurface(SP<CWLSurface> buf, const Vector2D& hotspot);
|
||||||
void resetCursorImage(bool apply = true);
|
void resetCursorImage(bool apply = true);
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ class CPointerManager {
|
||||||
void unlockSoftwareForMonitor(CMonitor* pMonitor);
|
void unlockSoftwareForMonitor(CMonitor* pMonitor);
|
||||||
void lockSoftwareAll();
|
void lockSoftwareAll();
|
||||||
void unlockSoftwareAll();
|
void unlockSoftwareAll();
|
||||||
|
bool softwareLockedFor(SP<CMonitor> pMonitor);
|
||||||
|
|
||||||
void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */);
|
void renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec* now, CRegion& damage /* logical */, std::optional<Vector2D> overridePos = {} /* monitor-local */);
|
||||||
|
|
||||||
|
@ -135,10 +137,9 @@ class CPointerManager {
|
||||||
} currentMonitorLayout;
|
} currentMonitorLayout;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
wlr_buffer* pBuffer = nullptr;
|
SP<Aquamarine::IBuffer> pBuffer;
|
||||||
SP<CTexture> bufferTex;
|
SP<CTexture> bufferTex;
|
||||||
WP<CWLSurface> surface;
|
WP<CWLSurface> surface;
|
||||||
wlr_texture* pBufferTexture = nullptr;
|
|
||||||
|
|
||||||
Vector2D hotspot;
|
Vector2D hotspot;
|
||||||
Vector2D size;
|
Vector2D size;
|
||||||
|
@ -146,17 +147,13 @@ class CPointerManager {
|
||||||
|
|
||||||
CHyprSignalListener destroySurface;
|
CHyprSignalListener destroySurface;
|
||||||
CHyprSignalListener commitSurface;
|
CHyprSignalListener commitSurface;
|
||||||
DYNLISTENER(destroyBuffer);
|
|
||||||
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
||||||
|
|
||||||
Vector2D pointerPos = {0, 0};
|
Vector2D pointerPos = {0, 0};
|
||||||
|
|
||||||
struct SMonitorPointerState {
|
struct SMonitorPointerState {
|
||||||
SMonitorPointerState(SP<CMonitor> m) : monitor(m) {}
|
SMonitorPointerState(SP<CMonitor> m) : monitor(m) {}
|
||||||
~SMonitorPointerState() {
|
~SMonitorPointerState() {}
|
||||||
if (cursorFrontBuffer)
|
|
||||||
wlr_buffer_unlock(cursorFrontBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
WP<CMonitor> monitor;
|
WP<CMonitor> monitor;
|
||||||
|
|
||||||
|
@ -166,14 +163,14 @@ class CPointerManager {
|
||||||
bool entered = false;
|
bool entered = false;
|
||||||
bool hwApplied = false;
|
bool hwApplied = false;
|
||||||
|
|
||||||
wlr_buffer* cursorFrontBuffer = nullptr;
|
SP<Aquamarine::IBuffer> cursorFrontBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<SP<SMonitorPointerState>> monitorStates;
|
std::vector<SP<SMonitorPointerState>> monitorStates;
|
||||||
SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
|
SP<SMonitorPointerState> stateFor(SP<CMonitor> mon);
|
||||||
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
|
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
|
||||||
wlr_buffer* renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture);
|
SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture);
|
||||||
bool setHWCursorBuffer(SP<SMonitorPointerState> state, wlr_buffer* buf);
|
bool setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
SP<HOOK_CALLBACK_FN> monitorAdded;
|
SP<HOOK_CALLBACK_FN> monitorAdded;
|
||||||
|
|
|
@ -94,8 +94,8 @@ void CSeatManager::setKeyboard(SP<IKeyboard> KEEB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::updateActiveKeyboardData() {
|
void CSeatManager::updateActiveKeyboardData() {
|
||||||
if (keyboard && keyboard->wlr())
|
if (keyboard)
|
||||||
PROTO::seat->updateRepeatInfo(keyboard->wlr()->repeat_info.rate, keyboard->wlr()->repeat_info.delay);
|
PROTO::seat->updateRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay);
|
||||||
PROTO::seat->updateKeymap();
|
PROTO::seat->updateKeymap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) {
|
||||||
if (state.keyboardFocus == surf)
|
if (state.keyboardFocus == surf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!keyboard || !keyboard->wlr()) {
|
if (!keyboard) {
|
||||||
Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set");
|
Debug::log(ERR, "BUG THIS: setKeyboardFocus without a valid keyboard set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
k->sendEnter(surf);
|
k->sendEnter(surf);
|
||||||
k->sendMods(keyboard->wlr()->modifiers.depressed, keyboard->wlr()->modifiers.latched, keyboard->wlr()->modifiers.locked, keyboard->wlr()->modifiers.group);
|
k->sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ void CSeatManager::setPointerFocus(SP<CWLSurfaceResource> surf, const Vector2D&
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mouse || !mouse->wlr()) {
|
if (!mouse) {
|
||||||
Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set");
|
Debug::log(ERR, "BUG THIS: setPointerFocus without a valid mouse set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "EventLoopManager.hpp"
|
#include "EventLoopManager.hpp"
|
||||||
#include "../../debug/Log.hpp"
|
#include "../../debug/Log.hpp"
|
||||||
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -25,9 +26,19 @@ static int timerWrite(int fd, uint32_t mask, void* data) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aquamarineFDWrite(int fd, uint32_t mask, void* data) {
|
||||||
|
g_pCompositor->m_pAqBackend->dispatchEventsAsync();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
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, WL_EVENT_READABLE, timerWrite, nullptr);
|
||||||
|
|
||||||
|
auto aqFDs = g_pCompositor->m_pAqBackend->getPollFDs();
|
||||||
|
for (auto& fd : aqFDs) {
|
||||||
|
m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd, WL_EVENT_READABLE, aquamarineFDWrite, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
wl_display_run(m_sWayland.display);
|
wl_display_run(m_sWayland.display);
|
||||||
|
|
||||||
Debug::log(LOG, "Kicked off the event loop! :(");
|
Debug::log(LOG, "Kicked off the event loop! :(");
|
||||||
|
|
|
@ -36,6 +36,7 @@ class CEventLoopManager {
|
||||||
wl_event_loop* loop = nullptr;
|
wl_event_loop* loop = nullptr;
|
||||||
wl_display* display = nullptr;
|
wl_display* display = nullptr;
|
||||||
wl_event_source* eventSource = nullptr;
|
wl_event_source* eventSource = nullptr;
|
||||||
|
std::vector<wl_event_source*> aqEventSources;
|
||||||
} m_sWayland;
|
} m_sWayland;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "../../managers/PointerManager.hpp"
|
#include "../../managers/PointerManager.hpp"
|
||||||
#include "../../managers/SeatManager.hpp"
|
#include "../../managers/SeatManager.hpp"
|
||||||
|
|
||||||
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
||||||
CInputManager::CInputManager() {
|
CInputManager::CInputManager() {
|
||||||
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
|
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
|
||||||
if (!cursorImageUnlocked())
|
if (!cursorImageUnlocked())
|
||||||
|
@ -189,7 +191,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
|
|
||||||
bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent();
|
bool skipFrameSchedule = PMONITOR->shouldSkipScheduleFrameOnMouseEvent();
|
||||||
|
|
||||||
if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0 && !skipFrameSchedule)
|
if (!PMONITOR->solitaryClient.lock() && g_pHyprRenderer->shouldRenderCursor() && g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) && !skipFrameSchedule)
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||||
|
|
||||||
PHLWINDOW forcedFocus = m_pForcedFocus.lock();
|
PHLWINDOW forcedFocus = m_pForcedFocus.lock();
|
||||||
|
@ -372,7 +374,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
foundSurface =
|
foundSurface =
|
||||||
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastMonitor->output->software_cursor_locks > 0 && !skipFrameSchedule)
|
if (g_pPointerManager->softwareLockedFor(PMONITOR->self.lock()) > 0 && !skipFrameSchedule)
|
||||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_pLastMonitor.get());
|
||||||
|
|
||||||
// grabs
|
// grabs
|
||||||
|
@ -807,8 +809,8 @@ Vector2D CInputManager::getMouseCoordsInternal() {
|
||||||
return g_pPointerManager->position();
|
return g_pPointerManager->position();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
void CInputManager::newKeyboard(SP<Aquamarine::IKeyboard> keyboard) {
|
||||||
const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard)));
|
const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(keyboard));
|
||||||
|
|
||||||
setupKeyboard(PNEWKEYBOARD);
|
setupKeyboard(PNEWKEYBOARD);
|
||||||
|
|
||||||
|
@ -820,14 +822,14 @@ void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keyboard)
|
||||||
|
|
||||||
setupKeyboard(PNEWKEYBOARD);
|
setupKeyboard(PNEWKEYBOARD);
|
||||||
|
|
||||||
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard->wlr());
|
Debug::log(LOG, "New virtual keyboard created at {:x}", (uintptr_t)PNEWKEYBOARD.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
|
||||||
m_vHIDs.push_back(keeb);
|
m_vHIDs.push_back(keeb);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name);
|
keeb->hlName = getNameForNewDevice(keeb->deviceName);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "Keyboard had no name???"); // logic error
|
Debug::log(ERR, "Keyboard had no name???"); // logic error
|
||||||
}
|
}
|
||||||
|
@ -926,83 +928,12 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
|
||||||
// we can ignore those and just apply
|
// we can ignore those and just apply
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
|
pKeyboard->repeatRate = std::max(0, REPEATRATE);
|
||||||
|
pKeyboard->repeatDelay = std::max(0, REPEATDELAY);
|
||||||
pKeyboard->repeatDelay = REPEATDELAY;
|
|
||||||
pKeyboard->repeatRate = REPEATRATE;
|
|
||||||
pKeyboard->numlockOn = NUMLOCKON;
|
pKeyboard->numlockOn = NUMLOCKON;
|
||||||
pKeyboard->xkbFilePath = FILEPATH;
|
pKeyboard->xkbFilePath = FILEPATH;
|
||||||
|
|
||||||
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
|
pKeyboard->setKeymap(IKeyboard::SStringRuleNames{LAYOUT, MODEL, VARIANT, OPTIONS, RULES});
|
||||||
|
|
||||||
pKeyboard->currentRules.rules = RULES;
|
|
||||||
pKeyboard->currentRules.model = MODEL;
|
|
||||||
pKeyboard->currentRules.variant = VARIANT;
|
|
||||||
pKeyboard->currentRules.options = OPTIONS;
|
|
||||||
pKeyboard->currentRules.layout = LAYOUT;
|
|
||||||
|
|
||||||
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
||||||
|
|
||||||
if (!CONTEXT) {
|
|
||||||
Debug::log(ERR, "applyConfigToKeyboard: CONTEXT null??");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model,
|
|
||||||
rules.options);
|
|
||||||
|
|
||||||
xkb_keymap* KEYMAP = NULL;
|
|
||||||
|
|
||||||
if (!FILEPATH.empty()) {
|
|
||||||
auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath);
|
|
||||||
|
|
||||||
if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE)
|
|
||||||
Debug::log(ERR, "Cannot open input:kb_file= file for reading");
|
|
||||||
else {
|
|
||||||
KEYMAP = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
fclose(KEYMAPFILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!KEYMAP)
|
|
||||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
|
|
||||||
if (!KEYMAP) {
|
|
||||||
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
|
|
||||||
", layout: " + LAYOUT + " )");
|
|
||||||
|
|
||||||
Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model,
|
|
||||||
rules.options);
|
|
||||||
memset(&rules, 0, sizeof(rules));
|
|
||||||
|
|
||||||
pKeyboard->currentRules.rules = "";
|
|
||||||
pKeyboard->currentRules.model = "";
|
|
||||||
pKeyboard->currentRules.variant = "";
|
|
||||||
pKeyboard->currentRules.options = "";
|
|
||||||
pKeyboard->currentRules.layout = "us";
|
|
||||||
|
|
||||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP);
|
|
||||||
|
|
||||||
pKeyboard->updateXKBTranslationState();
|
|
||||||
|
|
||||||
wlr_keyboard_modifiers wlrMods = {0};
|
|
||||||
|
|
||||||
if (NUMLOCKON == 1) {
|
|
||||||
// lock numlock
|
|
||||||
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
|
|
||||||
|
|
||||||
if (IDX != XKB_MOD_INVALID)
|
|
||||||
wlrMods.locked |= (uint32_t)1 << IDX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlrMods.locked != 0)
|
|
||||||
wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0);
|
|
||||||
|
|
||||||
xkb_keymap_unref(KEYMAP);
|
|
||||||
xkb_context_unref(CONTEXT);
|
|
||||||
|
|
||||||
const auto LAYOUTSTR = pKeyboard->getActiveLayout();
|
const auto LAYOUTSTR = pKeyboard->getActiveLayout();
|
||||||
|
|
||||||
|
@ -1017,11 +948,11 @@ void CInputManager::newVirtualMouse(SP<CVirtualPointerV1Resource> mouse) {
|
||||||
|
|
||||||
setupMouse(PMOUSE);
|
setupMouse(PMOUSE);
|
||||||
|
|
||||||
Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr());
|
Debug::log(LOG, "New virtual mouse created");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::newMouse(wlr_input_device* mouse) {
|
void CInputManager::newMouse(SP<Aquamarine::IPointer> mouse) {
|
||||||
const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse)));
|
const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(mouse));
|
||||||
|
|
||||||
setupMouse(PMOUSE);
|
setupMouse(PMOUSE);
|
||||||
|
|
||||||
|
@ -1032,13 +963,13 @@ void CInputManager::setupMouse(SP<IPointer> mauz) {
|
||||||
m_vHIDs.push_back(mauz);
|
m_vHIDs.push_back(mauz);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name);
|
mauz->hlName = getNameForNewDevice(mauz->deviceName);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "Mouse had no name???"); // logic error
|
Debug::log(ERR, "Mouse had no name???"); // logic error
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wlr_input_device_is_libinput(&mauz->wlr()->base)) {
|
if (mauz->aq() && mauz->aq()->getLibinputHandle()) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base);
|
const auto LIBINPUTDEV = mauz->aq()->getLibinputHandle();
|
||||||
|
|
||||||
Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV),
|
Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV),
|
||||||
libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV),
|
libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV),
|
||||||
|
@ -1084,8 +1015,8 @@ void CInputManager::setPointerConfigs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wlr_input_device_is_libinput(&m->wlr()->base)) {
|
if (m->aq() && m->aq()->getLibinputHandle()) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base);
|
const auto LIBINPUTDEV = m->aq()->getLibinputHandle();
|
||||||
|
|
||||||
double touchw = 0, touchh = 0;
|
double touchw = 0, touchh = 0;
|
||||||
const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
|
const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
|
||||||
|
@ -1234,7 +1165,7 @@ void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) {
|
||||||
if (m_vKeyboards.size() > 0) {
|
if (m_vKeyboards.size() > 0) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto& k : m_vKeyboards | std::views::reverse) {
|
for (auto& k : m_vKeyboards | std::views::reverse) {
|
||||||
if (!k->wlr())
|
if (!k)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_pSeatManager->setKeyboard(k);
|
g_pSeatManager->setKeyboard(k);
|
||||||
|
@ -1294,23 +1225,19 @@ void CInputManager::destroyTabletPad(SP<CTabletPad> pad) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
|
void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
|
||||||
if (!pKeyboard)
|
if (!pKeyboard || !pKeyboard->xkbTranslationState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto keyboard = pKeyboard->wlr();
|
// FIXME:
|
||||||
|
// uint32_t leds = 0;
|
||||||
|
// for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
|
||||||
|
// if (xkb_state_led_index_is_active(pKeyboard->xkbTranslationState, keyboard->led_indexes[i]))
|
||||||
|
// leds |= (1 << i);
|
||||||
|
// }
|
||||||
|
|
||||||
if (!keyboard || keyboard->xkb_state == nullptr)
|
// for (auto& k : m_vKeyboards) {
|
||||||
return;
|
// k->updateLEDs(leds);
|
||||||
|
// }
|
||||||
uint32_t leds = 0;
|
|
||||||
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
|
|
||||||
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i]))
|
|
||||||
leds |= (1 << i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& k : m_vKeyboards) {
|
|
||||||
k->updateLEDs(leds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
|
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
|
||||||
|
@ -1338,7 +1265,7 @@ void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
|
||||||
const auto IME = m_sIMERelay.m_pIME.lock();
|
const auto IME = m_sIMERelay.m_pIME.lock();
|
||||||
|
|
||||||
if (IME && IME->hasGrab() && !DISALLOWACTION) {
|
if (IME && IME->hasGrab() && !DISALLOWACTION) {
|
||||||
IME->setKeyboard(pKeyboard->wlr());
|
IME->setKeyboard(pKeyboard);
|
||||||
IME->sendKey(e.timeMs, e.keycode, e.state);
|
IME->sendKey(e.timeMs, e.keycode, e.state);
|
||||||
} else {
|
} else {
|
||||||
g_pSeatManager->setKeyboard(pKeyboard);
|
g_pSeatManager->setKeyboard(pKeyboard);
|
||||||
|
@ -1356,15 +1283,14 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) {
|
||||||
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);
|
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);
|
||||||
|
|
||||||
const auto ALLMODS = accumulateModsFromAllKBs();
|
const auto ALLMODS = accumulateModsFromAllKBs();
|
||||||
const auto PWLRKB = pKeyboard->wlr();
|
|
||||||
|
|
||||||
auto MODS = PWLRKB->modifiers;
|
auto MODS = pKeyboard->modifiersState;
|
||||||
MODS.depressed = ALLMODS;
|
MODS.depressed = ALLMODS;
|
||||||
|
|
||||||
const auto IME = m_sIMERelay.m_pIME.lock();
|
const auto IME = m_sIMERelay.m_pIME.lock();
|
||||||
|
|
||||||
if (IME && IME->hasGrab() && !DISALLOWACTION) {
|
if (IME && IME->hasGrab() && !DISALLOWACTION) {
|
||||||
IME->setKeyboard(PWLRKB);
|
IME->setKeyboard(pKeyboard);
|
||||||
IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
|
IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
|
||||||
} else {
|
} else {
|
||||||
g_pSeatManager->setKeyboard(pKeyboard);
|
g_pSeatManager->setKeyboard(pKeyboard);
|
||||||
|
@ -1373,8 +1299,8 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) {
|
||||||
|
|
||||||
updateKeyboardsLeds(pKeyboard);
|
updateKeyboardsLeds(pKeyboard);
|
||||||
|
|
||||||
if (PWLRKB->modifiers.group != pKeyboard->activeLayout) {
|
if (pKeyboard->modifiersState.group != pKeyboard->activeLayout) {
|
||||||
pKeyboard->activeLayout = PWLRKB->modifiers.group;
|
pKeyboard->activeLayout = pKeyboard->modifiersState.group;
|
||||||
|
|
||||||
const auto LAYOUT = pKeyboard->getActiveLayout();
|
const auto LAYOUT = pKeyboard->getActiveLayout();
|
||||||
|
|
||||||
|
@ -1488,10 +1414,10 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
|
||||||
if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb))
|
if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!kb->enabled || !kb->wlr())
|
if (!kb->enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
finalMask |= wlr_keyboard_get_modifiers(kb->wlr());
|
finalMask |= kb->getModifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalMask;
|
return finalMask;
|
||||||
|
@ -1507,12 +1433,12 @@ void CInputManager::disableAllKeyboards(bool virt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
void CInputManager::newTouchDevice(SP<Aquamarine::ITouch> pDevice) {
|
||||||
const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice)));
|
const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(pDevice));
|
||||||
m_vHIDs.push_back(PNEWDEV);
|
m_vHIDs.push_back(PNEWDEV);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PNEWDEV->hlName = getNameForNewDevice(pDevice->name);
|
PNEWDEV->hlName = getNameForNewDevice(PNEWDEV->deviceName);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "Touch Device had no name???"); // logic error
|
Debug::log(ERR, "Touch Device had no name???"); // logic error
|
||||||
}
|
}
|
||||||
|
@ -1536,8 +1462,8 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||||
|
|
||||||
void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
|
void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
|
||||||
auto setConfig = [&](SP<ITouch> PTOUCHDEV) -> void {
|
auto setConfig = [&](SP<ITouch> PTOUCHDEV) -> void {
|
||||||
if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) {
|
if (dev->aq() && dev->aq()->getLibinputHandle()) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base);
|
const auto LIBINPUTDEV = dev->aq()->getLibinputHandle();
|
||||||
|
|
||||||
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled");
|
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled");
|
||||||
const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||||
|
@ -1553,11 +1479,12 @@ void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
|
||||||
bool bound = !output.empty() && output != STRVAL_EMPTY;
|
bool bound = !output.empty() && output != STRVAL_EMPTY;
|
||||||
const bool AUTODETECT = output == "[[Auto]]";
|
const bool AUTODETECT = output == "[[Auto]]";
|
||||||
if (!bound && AUTODETECT) {
|
if (!bound && AUTODETECT) {
|
||||||
const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name;
|
// FIXME:
|
||||||
if (DEFAULTOUTPUT) {
|
// const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name;
|
||||||
output = DEFAULTOUTPUT;
|
// if (DEFAULTOUTPUT) {
|
||||||
bound = true;
|
// output = DEFAULTOUTPUT;
|
||||||
}
|
// bound = true;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
PTOUCHDEV->boundOutput = bound ? output : "";
|
PTOUCHDEV->boundOutput = bound ? output : "";
|
||||||
const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr;
|
const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr;
|
||||||
|
|
|
@ -18,6 +18,10 @@ class CVirtualKeyboardV1Resource;
|
||||||
class CVirtualPointerV1Resource;
|
class CVirtualPointerV1Resource;
|
||||||
class IKeyboard;
|
class IKeyboard;
|
||||||
|
|
||||||
|
AQUAMARINE_FORWARD(IPointer);
|
||||||
|
AQUAMARINE_FORWARD(IKeyboard);
|
||||||
|
AQUAMARINE_FORWARD(ITouch);
|
||||||
|
|
||||||
enum eClickBehaviorMode {
|
enum eClickBehaviorMode {
|
||||||
CLICKMODE_DEFAULT = 0,
|
CLICKMODE_DEFAULT = 0,
|
||||||
CLICKMODE_KILL
|
CLICKMODE_KILL
|
||||||
|
@ -82,11 +86,11 @@ class CInputManager {
|
||||||
void onKeyboardKey(std::any, SP<IKeyboard>);
|
void onKeyboardKey(std::any, SP<IKeyboard>);
|
||||||
void onKeyboardMod(SP<IKeyboard>);
|
void onKeyboardMod(SP<IKeyboard>);
|
||||||
|
|
||||||
void newKeyboard(wlr_input_device*);
|
void newKeyboard(SP<Aquamarine::IKeyboard>);
|
||||||
void newVirtualKeyboard(SP<CVirtualKeyboardV1Resource>);
|
void newVirtualKeyboard(SP<CVirtualKeyboardV1Resource>);
|
||||||
void newMouse(wlr_input_device*);
|
void newMouse(SP<Aquamarine::IPointer>);
|
||||||
void newVirtualMouse(SP<CVirtualPointerV1Resource>);
|
void newVirtualMouse(SP<CVirtualPointerV1Resource>);
|
||||||
void newTouchDevice(wlr_input_device*);
|
void newTouchDevice(SP<Aquamarine::ITouch>);
|
||||||
void newSwitch(wlr_input_device*);
|
void newSwitch(wlr_input_device*);
|
||||||
void newTabletTool(wlr_tablet_tool*);
|
void newTabletTool(wlr_tablet_tool*);
|
||||||
void newTabletPad(wlr_input_device*);
|
void newTabletPad(wlr_input_device*);
|
||||||
|
|
|
@ -34,7 +34,7 @@ CGammaControl::CGammaControl(SP<CZwlrGammaControlV1> resource_, wl_resource* out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gammaSize = wlr_output_get_gamma_size(pMonitor->output);
|
gammaSize = pMonitor->output->getGammaSize();
|
||||||
|
|
||||||
if (gammaSize <= 0) {
|
if (gammaSize <= 0) {
|
||||||
LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName);
|
LOGM(ERR, "Output {} doesn't support gamma", pMonitor->szName);
|
||||||
|
@ -95,7 +95,7 @@ CGammaControl::~CGammaControl() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// reset the LUT if the client dies for whatever reason and doesn't unset the gamma
|
// reset the LUT if the client dies for whatever reason and doesn't unset the gamma
|
||||||
wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
|
pMonitor->output->state->setGammaLut({});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGammaControl::good() {
|
bool CGammaControl::good() {
|
||||||
|
@ -109,19 +109,15 @@ void CGammaControl::applyToMonitor() {
|
||||||
LOGM(LOG, "setting to monitor {}", pMonitor->szName);
|
LOGM(LOG, "setting to monitor {}", pMonitor->szName);
|
||||||
|
|
||||||
if (!gammaTableSet) {
|
if (!gammaTableSet) {
|
||||||
wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
|
pMonitor->output->state->setGammaLut({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t* red = &gammaTable.at(0);
|
pMonitor->output->state->setGammaLut(gammaTable);
|
||||||
uint16_t* green = &gammaTable.at(gammaSize);
|
|
||||||
uint16_t* blue = &gammaTable.at(gammaSize * 2);
|
|
||||||
|
|
||||||
wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), gammaSize, red, green, blue);
|
|
||||||
|
|
||||||
if (!pMonitor->state.test()) {
|
if (!pMonitor->state.test()) {
|
||||||
LOGM(LOG, "setting to monitor {} failed", pMonitor->szName);
|
LOGM(LOG, "setting to monitor {} failed", pMonitor->szName);
|
||||||
wlr_output_state_set_gamma_lut(pMonitor->state.wlr(), 0, nullptr, nullptr, nullptr);
|
pMonitor->output->state->setGammaLut({});
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(pMonitor);
|
g_pHyprRenderer->damageMonitor(pMonitor);
|
||||||
|
|
|
@ -19,7 +19,7 @@ CInputMethodKeyboardGrabV2::CInputMethodKeyboardGrabV2(SP<CZwpInputMethodKeyboar
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendKeyboardData(g_pSeatManager->keyboard->wlr());
|
sendKeyboardData(g_pSeatManager->keyboard.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() {
|
CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() {
|
||||||
|
@ -27,37 +27,36 @@ CInputMethodKeyboardGrabV2::~CInputMethodKeyboardGrabV2() {
|
||||||
std::erase_if(owner->grabs, [](const auto& g) { return g.expired(); });
|
std::erase_if(owner->grabs, [](const auto& g) { return g.expired(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputMethodKeyboardGrabV2::sendKeyboardData(wlr_keyboard* keyboard) {
|
void CInputMethodKeyboardGrabV2::sendKeyboardData(SP<IKeyboard> keyboard) {
|
||||||
|
|
||||||
if (keyboard == pLastKeyboard)
|
if (keyboard == pLastKeyboard)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pLastKeyboard = keyboard;
|
pLastKeyboard = keyboard;
|
||||||
|
|
||||||
int keymapFD = allocateSHMFile(keyboard->keymap_size);
|
int keymapFD = allocateSHMFile(keyboard->xkbKeymapString.length() + 1);
|
||||||
if (keymapFD < 0) {
|
if (keymapFD < 0) {
|
||||||
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->keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0);
|
void* data = mmap(nullptr, keyboard->xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD, 0);
|
||||||
if (data == MAP_FAILED) {
|
if (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);
|
close(keymapFD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, keyboard->keymap_string, keyboard->keymap_size);
|
memcpy(data, keyboard->xkbKeymapString.c_str(), keyboard->xkbKeymapString.length());
|
||||||
munmap(data, keyboard->keymap_size);
|
munmap(data, keyboard->xkbKeymapString.length() + 1);
|
||||||
|
|
||||||
resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->keymap_size);
|
resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD, keyboard->xkbKeymapString.length() + 1);
|
||||||
|
|
||||||
close(keymapFD);
|
close(keymapFD);
|
||||||
|
|
||||||
const auto MODS = keyboard->modifiers;
|
sendMods(keyboard->modifiersState.depressed, keyboard->modifiersState.latched, keyboard->modifiersState.locked, keyboard->modifiersState.group);
|
||||||
sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
|
|
||||||
|
|
||||||
resource->sendRepeatInfo(keyboard->repeat_info.rate, keyboard->repeat_info.delay);
|
resource->sendRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) {
|
void CInputMethodKeyboardGrabV2::sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state) {
|
||||||
|
@ -316,7 +315,7 @@ void CInputMethodV2::sendMods(uint32_t depressed, uint32_t latched, uint32_t loc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputMethodV2::setKeyboard(wlr_keyboard* keyboard) {
|
void CInputMethodV2::setKeyboard(SP<IKeyboard> keyboard) {
|
||||||
for (auto& gw : grabs) {
|
for (auto& gw : grabs) {
|
||||||
auto g = gw.lock();
|
auto g = gw.lock();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
class CInputMethodKeyboardGrabV2;
|
class CInputMethodKeyboardGrabV2;
|
||||||
class CInputMethodPopupV2;
|
class CInputMethodPopupV2;
|
||||||
|
class IKeyboard;
|
||||||
|
|
||||||
class CInputMethodV2 {
|
class CInputMethodV2 {
|
||||||
public:
|
public:
|
||||||
|
@ -58,7 +59,7 @@ class CInputMethodV2 {
|
||||||
bool hasGrab();
|
bool hasGrab();
|
||||||
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
|
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
|
||||||
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||||
void setKeyboard(wlr_keyboard* keyboard);
|
void setKeyboard(SP<IKeyboard> keyboard);
|
||||||
|
|
||||||
wl_client* client();
|
wl_client* client();
|
||||||
wl_client* grabClient();
|
wl_client* grabClient();
|
||||||
|
@ -90,13 +91,13 @@ class CInputMethodKeyboardGrabV2 {
|
||||||
|
|
||||||
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
|
void sendKey(uint32_t time, uint32_t key, wl_keyboard_key_state state);
|
||||||
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
void sendMods(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group);
|
||||||
void sendKeyboardData(wlr_keyboard* keyboard);
|
void sendKeyboardData(SP<IKeyboard> keyboard);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CZwpInputMethodKeyboardGrabV2> resource;
|
SP<CZwpInputMethodKeyboardGrabV2> resource;
|
||||||
WP<CInputMethodV2> owner;
|
WP<CInputMethodV2> owner;
|
||||||
|
|
||||||
wlr_keyboard* pLastKeyboard = nullptr; // READ-ONLY
|
WP<IKeyboard> pLastKeyboard;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CInputMethodPopupV2 {
|
class CInputMethodPopupV2 {
|
||||||
|
|
|
@ -73,7 +73,7 @@ CCompiledDMABUFFeedback::~CCompiledDMABUFFeedback() {
|
||||||
close(tableFD);
|
close(tableFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs) {
|
CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs) {
|
||||||
buffer = makeShared<CDMABuffer>(id, client, attrs);
|
buffer = makeShared<CDMABuffer>(id, client, attrs);
|
||||||
|
|
||||||
buffer->resource->buffer = buffer;
|
buffer->resource->buffer = buffer;
|
||||||
|
@ -103,7 +103,7 @@ CLinuxDMABBUFParamsResource::CLinuxDMABBUFParamsResource(SP<CZwpLinuxBufferParam
|
||||||
resource->setOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
|
resource->setOnDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
|
||||||
resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
|
resource->setDestroy([this](CZwpLinuxBufferParamsV1* r) { PROTO::linuxDma->destroyResource(this); });
|
||||||
|
|
||||||
attrs = makeShared<SDMABUFAttrs>();
|
attrs = makeShared<Aquamarine::SDMABUFAttrs>();
|
||||||
|
|
||||||
attrs->success = true;
|
attrs->success = true;
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ void CLinuxDMABUFResource::sendMods() {
|
||||||
|
|
||||||
CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
CLinuxDMABufV1Protocol::CLinuxDMABufV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) {
|
static auto P = g_pHookSystem->hookDynamic("ready", [this](void* self, SCallbackInfo& info, std::any d) {
|
||||||
int rendererFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
|
int rendererFD = g_pCompositor->m_iDRMFD;
|
||||||
auto dev = devIDFromFD(rendererFD);
|
auto dev = devIDFromFD(rendererFD);
|
||||||
|
|
||||||
if (!dev.has_value()) {
|
if (!dev.has_value()) {
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
#include "wayland.hpp"
|
#include "wayland.hpp"
|
||||||
#include "linux-dmabuf-v1.hpp"
|
#include "linux-dmabuf-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
|
||||||
class CDMABuffer;
|
class CDMABuffer;
|
||||||
struct SDRMFormat;
|
struct SDRMFormat;
|
||||||
struct SDMABUFAttrs;
|
|
||||||
class CWLSurfaceResource;
|
class CWLSurfaceResource;
|
||||||
|
|
||||||
class CLinuxDMABuffer {
|
class CLinuxDMABuffer {
|
||||||
public:
|
public:
|
||||||
CLinuxDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
|
CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
|
||||||
~CLinuxDMABuffer();
|
~CLinuxDMABuffer();
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
@ -69,7 +69,7 @@ class CLinuxDMABBUFParamsResource {
|
||||||
bool good();
|
bool good();
|
||||||
void create(uint32_t id); // 0 means not immed
|
void create(uint32_t id); // 0 means not immed
|
||||||
|
|
||||||
SP<SDMABUFAttrs> attrs;
|
SP<Aquamarine::SDMABUFAttrs> attrs;
|
||||||
WP<CLinuxDMABuffer> createdBuffer;
|
WP<CLinuxDMABuffer> createdBuffer;
|
||||||
bool used = false;
|
bool used = false;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define LOGM PROTO::mesaDRM->protoLog
|
#define LOGM PROTO::mesaDRM->protoLog
|
||||||
|
|
||||||
CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs_) {
|
CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs_) {
|
||||||
LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes);
|
LOGM(LOG, "Creating a Mesa dmabuf, with id {}: size {}, fmt {}, planes {}", id, attrs_.size, attrs_.format, attrs_.planes);
|
||||||
for (int i = 0; i < attrs_.planes; ++i) {
|
for (int i = 0; i < attrs_.planes; ++i) {
|
||||||
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]);
|
LOGM(LOG, " | plane {}: mod {} fd {} stride {} offset {}", i, attrs_.modifier, attrs_.fds[i], attrs_.strides[i], attrs_.offsets[i]);
|
||||||
|
@ -60,7 +60,7 @@ CMesaDRMResource::CMesaDRMResource(SP<CWlDrm> resource_) : resource(resource_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDMABUFAttrs attrs;
|
Aquamarine::SDMABUFAttrs attrs;
|
||||||
attrs.success = true;
|
attrs.success = true;
|
||||||
attrs.size = {w, h};
|
attrs.size = {w, h};
|
||||||
attrs.modifier = DRM_FORMAT_MOD_INVALID;
|
attrs.modifier = DRM_FORMAT_MOD_INVALID;
|
||||||
|
@ -97,7 +97,7 @@ bool CMesaDRMResource::good() {
|
||||||
|
|
||||||
CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
CMesaDRMProtocol::CMesaDRMProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
drmDevice* dev = nullptr;
|
drmDevice* dev = nullptr;
|
||||||
int drmFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
|
int drmFD = g_pCompositor->m_iDRMFD;
|
||||||
if (drmGetDevice2(drmFD, 0, &dev) != 0) {
|
if (drmGetDevice2(drmFD, 0, &dev) != 0) {
|
||||||
LOGM(ERR, "Failed to get device");
|
LOGM(ERR, "Failed to get device");
|
||||||
PROTO::mesaDRM.reset();
|
PROTO::mesaDRM.reset();
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
class CMesaDRMBufferResource {
|
class CMesaDRMBufferResource {
|
||||||
public:
|
public:
|
||||||
CMesaDRMBufferResource(uint32_t id, wl_client* client, SDMABUFAttrs attrs);
|
CMesaDRMBufferResource(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs attrs);
|
||||||
~CMesaDRMBufferResource();
|
~CMesaDRMBufferResource();
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
using namespace Aquamarine;
|
||||||
|
|
||||||
#define LOGM PROTO::outputManagement->protoLog
|
#define LOGM PROTO::outputManagement->protoLog
|
||||||
|
|
||||||
COutputManager::COutputManager(SP<CZwlrOutputManagerV1> resource_) : resource(resource_) {
|
COutputManager::COutputManager(SP<CZwlrOutputManagerV1> resource_) : resource(resource_) {
|
||||||
|
@ -123,8 +125,8 @@ void COutputHead::sendAllData() {
|
||||||
|
|
||||||
resource->sendName(pMonitor->szName.c_str());
|
resource->sendName(pMonitor->szName.c_str());
|
||||||
resource->sendDescription(pMonitor->szDescription.c_str());
|
resource->sendDescription(pMonitor->szDescription.c_str());
|
||||||
if (pMonitor->output->phys_width > 0 && pMonitor->output->phys_height > 0)
|
if (pMonitor->output->physicalSize.x > 0 && pMonitor->output->physicalSize.y > 0)
|
||||||
resource->sendPhysicalSize(pMonitor->output->phys_width, pMonitor->output->phys_height);
|
resource->sendPhysicalSize(pMonitor->output->physicalSize.x, pMonitor->output->physicalSize.y);
|
||||||
resource->sendEnabled(pMonitor->m_bEnabled);
|
resource->sendEnabled(pMonitor->m_bEnabled);
|
||||||
|
|
||||||
if (pMonitor->m_bEnabled) {
|
if (pMonitor->m_bEnabled) {
|
||||||
|
@ -133,12 +135,12 @@ void COutputHead::sendAllData() {
|
||||||
resource->sendScale(wl_fixed_from_double(pMonitor->scale));
|
resource->sendScale(wl_fixed_from_double(pMonitor->scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pMonitor->output->make && VERSION >= 2)
|
if (!pMonitor->output->make.empty() && VERSION >= 2)
|
||||||
resource->sendMake(pMonitor->output->make);
|
resource->sendMake(pMonitor->output->make.c_str());
|
||||||
if (pMonitor->output->model && VERSION >= 2)
|
if (!pMonitor->output->model.empty() && VERSION >= 2)
|
||||||
resource->sendModel(pMonitor->output->model);
|
resource->sendModel(pMonitor->output->model.c_str());
|
||||||
if (pMonitor->output->serial && VERSION >= 2)
|
if (!pMonitor->output->serial.empty() && VERSION >= 2)
|
||||||
resource->sendSerialNumber(pMonitor->output->serial);
|
resource->sendSerialNumber(pMonitor->output->serial.c_str());
|
||||||
|
|
||||||
if (VERSION >= 4)
|
if (VERSION >= 4)
|
||||||
resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED);
|
resource->sendAdaptiveSync(pMonitor->vrrActive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED);
|
||||||
|
@ -146,12 +148,12 @@ void COutputHead::sendAllData() {
|
||||||
// send all available modes
|
// send all available modes
|
||||||
|
|
||||||
if (modes.empty()) {
|
if (modes.empty()) {
|
||||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
if (!pMonitor->output->modes.empty()) {
|
||||||
wlr_output_mode* mode;
|
for (auto& m : pMonitor->output->modes) {
|
||||||
|
makeAndSendNewMode(m);
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
|
||||||
makeAndSendNewMode(mode);
|
|
||||||
}
|
}
|
||||||
|
} else if (pMonitor->output->state->state().customMode) {
|
||||||
|
makeAndSendNewMode(pMonitor->output->state->state().customMode);
|
||||||
} else
|
} else
|
||||||
makeAndSendNewMode(nullptr);
|
makeAndSendNewMode(nullptr);
|
||||||
}
|
}
|
||||||
|
@ -164,9 +166,9 @@ void COutputHead::sendAllData() {
|
||||||
if (!m)
|
if (!m)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m->mode == pMonitor->currentMode) {
|
if (m->mode == pMonitor->output->state->state().mode) {
|
||||||
if (m->mode)
|
if (m->mode)
|
||||||
LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh);
|
LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate);
|
||||||
else
|
else
|
||||||
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
|
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
|
||||||
resource->sendCurrentMode(m->resource.get());
|
resource->sendCurrentMode(m->resource.get());
|
||||||
|
@ -197,7 +199,7 @@ void COutputHead::updateMode() {
|
||||||
|
|
||||||
if (m->mode == pMonitor->currentMode) {
|
if (m->mode == pMonitor->currentMode) {
|
||||||
if (m->mode)
|
if (m->mode)
|
||||||
LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->width, m->mode->height, m->mode->refresh);
|
LOGM(LOG, " | sending current mode for {}: {}x{}@{}", pMonitor->szName, m->mode->pixelSize.x, m->mode->pixelSize.y, m->mode->refreshRate);
|
||||||
else
|
else
|
||||||
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
|
LOGM(LOG, " | sending current mode for {}: null (fake)", pMonitor->szName);
|
||||||
resource->sendCurrentMode(m->resource.get());
|
resource->sendCurrentMode(m->resource.get());
|
||||||
|
@ -207,7 +209,7 @@ void COutputHead::updateMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void COutputHead::makeAndSendNewMode(wlr_output_mode* mode) {
|
void COutputHead::makeAndSendNewMode(SP<Aquamarine::SOutputMode> mode) {
|
||||||
const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared<COutputMode>(makeShared<CZwlrOutputModeV1>(resource->client(), resource->version(), 0), mode));
|
const auto RESOURCE = PROTO::outputManagement->m_vModes.emplace_back(makeShared<COutputMode>(makeShared<CZwlrOutputModeV1>(resource->client(), resource->version(), 0), mode));
|
||||||
|
|
||||||
if (!RESOURCE->good()) {
|
if (!RESOURCE->good()) {
|
||||||
|
@ -225,7 +227,7 @@ CMonitor* COutputHead::monitor() {
|
||||||
return pMonitor;
|
return pMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
COutputMode::COutputMode(SP<CZwlrOutputModeV1> resource_, wlr_output_mode* mode_) : resource(resource_), mode(mode_) {
|
COutputMode::COutputMode(SP<CZwlrOutputModeV1> resource_, SP<Aquamarine::SOutputMode> mode_) : resource(resource_), mode(mode_) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -237,11 +239,11 @@ void COutputMode::sendAllData() {
|
||||||
if (!mode)
|
if (!mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->width, mode->height, mode->refresh, mode->preferred);
|
LOGM(LOG, " | sending mode {}x{}@{}mHz, pref: {}", mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate, mode->preferred);
|
||||||
|
|
||||||
resource->sendSize(mode->width, mode->height);
|
resource->sendSize(mode->pixelSize.x, mode->pixelSize.y);
|
||||||
if (mode->refresh > 0)
|
if (mode->refreshRate > 0)
|
||||||
resource->sendRefresh(mode->refresh);
|
resource->sendRefresh(mode->refreshRate);
|
||||||
if (mode->preferred)
|
if (mode->preferred)
|
||||||
resource->sendPreferred();
|
resource->sendPreferred();
|
||||||
}
|
}
|
||||||
|
@ -250,8 +252,8 @@ bool COutputMode::good() {
|
||||||
return resource->resource();
|
return resource->resource();
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_mode* COutputMode::getMode() {
|
SP<Aquamarine::SOutputMode> COutputMode::getMode() {
|
||||||
return mode;
|
return mode.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resource_, SP<COutputManager> owner_) : resource(resource_), owner(owner_) {
|
COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resource_, SP<COutputManager> owner_) : resource(resource_), owner(owner_) {
|
||||||
|
@ -364,8 +366,8 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
|
||||||
newRule.disabled = false;
|
newRule.disabled = false;
|
||||||
|
|
||||||
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
|
if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
|
||||||
newRule.resolution = {head->state.mode->getMode()->width, head->state.mode->getMode()->height};
|
newRule.resolution = head->state.mode->getMode()->pixelSize;
|
||||||
newRule.refreshRate = head->state.mode->getMode()->refresh / 1000.F;
|
newRule.refreshRate = head->state.mode->getMode()->refreshRate / 1000.F;
|
||||||
} else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
} else if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_CUSTOM_MODE) {
|
||||||
newRule.resolution = head->state.customMode.size;
|
newRule.resolution = head->state.customMode.size;
|
||||||
newRule.refreshRate = head->state.customMode.refresh / 1000.F;
|
newRule.refreshRate = head->state.customMode.refresh / 1000.F;
|
||||||
|
@ -425,7 +427,7 @@ COutputConfigurationHead::COutputConfigurationHead(SP<CZwlrOutputConfigurationHe
|
||||||
committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
|
committedProperties |= OUTPUT_HEAD_COMMITTED_MODE;
|
||||||
state.mode = MODE;
|
state.mode = MODE;
|
||||||
|
|
||||||
LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->width, MODE->getMode()->height, MODE->getMode()->refresh);
|
LOGM(LOG, " | configHead for {}: set mode to {}x{}@{}", pMonitor->szName, MODE->getMode()->pixelSize.x, MODE->getMode()->pixelSize.y, MODE->getMode()->refreshRate);
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setSetCustomMode([this](CZwlrOutputConfigurationHeadV1* r, int32_t w, int32_t h, int32_t refresh) {
|
resource->setSetCustomMode([this](CZwlrOutputConfigurationHeadV1* r, int32_t w, int32_t h, int32_t refresh) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-output-management-unstable-v1.hpp"
|
#include "wlr-output-management-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include <aquamarine/output/Output.hpp>
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
|
@ -34,15 +35,15 @@ class COutputManager {
|
||||||
|
|
||||||
class COutputMode {
|
class COutputMode {
|
||||||
public:
|
public:
|
||||||
COutputMode(SP<CZwlrOutputModeV1> resource_, wlr_output_mode* mode_);
|
COutputMode(SP<CZwlrOutputModeV1> resource_, SP<Aquamarine::SOutputMode> mode_);
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
wlr_output_mode* getMode();
|
SP<Aquamarine::SOutputMode> getMode();
|
||||||
void sendAllData();
|
void sendAllData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CZwlrOutputModeV1> resource;
|
SP<CZwlrOutputModeV1> resource;
|
||||||
wlr_output_mode* mode = nullptr;
|
WP<Aquamarine::SOutputMode> mode;
|
||||||
|
|
||||||
friend class COutputHead;
|
friend class COutputHead;
|
||||||
friend class COutputManagementProtocol;
|
friend class COutputManagementProtocol;
|
||||||
|
@ -61,7 +62,7 @@ class COutputHead {
|
||||||
SP<CZwlrOutputHeadV1> resource;
|
SP<CZwlrOutputHeadV1> resource;
|
||||||
CMonitor* pMonitor = nullptr;
|
CMonitor* pMonitor = nullptr;
|
||||||
|
|
||||||
void makeAndSendNewMode(wlr_output_mode* mode);
|
void makeAndSendNewMode(SP<Aquamarine::SOutputMode> mode);
|
||||||
void sendCurrentMode();
|
void sendCurrentMode();
|
||||||
|
|
||||||
std::vector<WP<COutputMode>> modes;
|
std::vector<WP<COutputMode>> modes;
|
||||||
|
|
|
@ -17,7 +17,7 @@ COutputPower::COutputPower(SP<CZwlrOutputPowerV1> resource_, CMonitor* pMonitor_
|
||||||
|
|
||||||
pMonitor->dpmsStatus = mode == ZWLR_OUTPUT_POWER_V1_MODE_ON;
|
pMonitor->dpmsStatus = mode == ZWLR_OUTPUT_POWER_V1_MODE_ON;
|
||||||
|
|
||||||
wlr_output_state_set_enabled(pMonitor->state.wlr(), pMonitor->dpmsStatus);
|
pMonitor->output->state->setEnabled(mode == ZWLR_OUTPUT_POWER_V1_MODE_ON);
|
||||||
|
|
||||||
if (!pMonitor->state.commit())
|
if (!pMonitor->state.commit())
|
||||||
LOGM(ERR, "Couldn't set dpms to {} for {}", pMonitor->dpmsStatus, pMonitor->szName);
|
LOGM(ERR, "Couldn't set dpms to {} for {}", pMonitor->dpmsStatus, pMonitor->szName);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "../helpers/Monitor.hpp"
|
#include "../helpers/Monitor.hpp"
|
||||||
#include "../managers/HookSystemManager.hpp"
|
#include "../managers/HookSystemManager.hpp"
|
||||||
#include "core/Compositor.hpp"
|
#include "core/Compositor.hpp"
|
||||||
|
#include "core/Output.hpp"
|
||||||
|
|
||||||
#define LOGM PROTO::presentation->protoLog
|
#define LOGM PROTO::presentation->protoLog
|
||||||
|
|
||||||
|
@ -42,12 +43,10 @@ bool CPresentationFeedback::good() {
|
||||||
|
|
||||||
void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) {
|
void CPresentationFeedback::sendQueued(SP<CQueuedPresentationData> data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) {
|
||||||
auto client = resource->client();
|
auto client = resource->client();
|
||||||
wl_resource* res;
|
|
||||||
wl_resource_for_each(res, &data->pMonitor->output->resources) {
|
if (PROTO::outputs.contains(data->pMonitor->szName)) {
|
||||||
if (client == wl_resource_get_client(res)) {
|
if (auto outputResource = PROTO::outputs.at(data->pMonitor->szName)->outputResourceFrom(client); outputResource)
|
||||||
resource->sendSyncOutput(res);
|
resource->sendSyncOutput(outputResource->getResource()->resource());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
|
@ -266,20 +266,17 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PFRAME->pMonitor->output->allocator && (PFRAME->pMonitor->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) {
|
PFRAME->dmabufFormat = PFRAME->pMonitor->output->state->state().drmFormat;
|
||||||
PFRAME->dmabufFormat = PFRAME->pMonitor->output->render_format;
|
|
||||||
} else {
|
|
||||||
PFRAME->dmabufFormat = DRM_FORMAT_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (box.width == 0 && box.height == 0)
|
if (box.width == 0 && box.height == 0)
|
||||||
PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)};
|
PFRAME->box = {0, 0, (int)(PFRAME->pMonitor->vecSize.x), (int)(PFRAME->pMonitor->vecSize.y)};
|
||||||
else {
|
else {
|
||||||
PFRAME->box = box;
|
PFRAME->box = box;
|
||||||
}
|
}
|
||||||
int ow, oh;
|
|
||||||
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
|
PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), PFRAME->pMonitor->vecTransformedSize.x, PFRAME->pMonitor->vecTransformedSize.y)
|
||||||
PFRAME->box.transform(wlTransformToHyprutils(PFRAME->pMonitor->transform), ow, oh).scale(PFRAME->pMonitor->scale).round();
|
.scale(PFRAME->pMonitor->scale)
|
||||||
|
.round();
|
||||||
|
|
||||||
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
|
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
|
||||||
|
|
||||||
|
@ -383,10 +380,10 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||||
g_pHyprRenderer->damageMonitor(PFRAME->pMonitor);
|
g_pHyprRenderer->damageMonitor(PFRAME->pMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
|
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor) {
|
||||||
m_pLastMonitorBackBuffer = e->state->buffer;
|
m_pLastMonitorBackBuffer = pMonitor->output->state->state().buffer;
|
||||||
shareAllFrames(pMonitor);
|
shareAllFrames(pMonitor);
|
||||||
m_pLastMonitorBackBuffer = nullptr;
|
m_pLastMonitorBackBuffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) {
|
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) {
|
||||||
|
@ -473,11 +470,7 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
|
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
|
||||||
wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
|
auto TEXTURE = makeShared<CTexture>(m_pLastMonitorBackBuffer);
|
||||||
if (!sourceTex)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto TEXTURE = makeShared<CTexture>(sourceTex);
|
|
||||||
|
|
||||||
auto shm = frame->buffer->shm();
|
auto shm = frame->buffer->shm();
|
||||||
auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm
|
auto [pixelData, fmt, bufLen] = frame->buffer->beginDataPtr(0); // no need for end, cuz it's shm
|
||||||
|
@ -489,10 +482,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
|
||||||
CFramebuffer fb;
|
CFramebuffer fb;
|
||||||
fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat);
|
fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat);
|
||||||
|
|
||||||
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true)) {
|
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb, true))
|
||||||
wlr_texture_destroy(sourceTex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y});
|
CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y});
|
||||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||||
|
@ -510,7 +501,6 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
|
||||||
const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format);
|
const auto PFORMAT = FormatUtils::getPixelFormatFromDRM(shm.format);
|
||||||
if (!PFORMAT) {
|
if (!PFORMAT) {
|
||||||
g_pHyprRenderer->endRender();
|
g_pHyprRenderer->endRender();
|
||||||
wlr_texture_destroy(sourceTex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,27 +529,20 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
|
||||||
|
|
||||||
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
||||||
|
|
||||||
wlr_texture_destroy(sourceTex);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||||
wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
|
auto TEXTURE = makeShared<CTexture>(m_pLastMonitorBackBuffer);
|
||||||
if (!sourceTex)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto TEXTURE = makeShared<CTexture>(sourceTex);
|
|
||||||
|
|
||||||
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
||||||
|
|
||||||
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true))
|
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer.lock(), nullptr, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CBox monbox =
|
CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}
|
||||||
CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}
|
|
||||||
.translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
|
.translate({-frame->box.x, -frame->box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
|
||||||
.transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->output->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
|
.transform(wlTransformToHyprutils(wlr_output_transform_invert(frame->pMonitor->transform)), frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
|
||||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||||
g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1);
|
g_pHyprOpenGL->renderTexture(TEXTURE, &monbox, 1);
|
||||||
|
@ -569,7 +552,5 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||||
g_pHyprOpenGL->m_RenderData.blockScreenShader = true;
|
g_pHyprOpenGL->m_RenderData.blockScreenShader = true;
|
||||||
g_pHyprRenderer->endRender();
|
g_pHyprRenderer->endRender();
|
||||||
|
|
||||||
wlr_texture_destroy(sourceTex);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "../managers/eventLoop/EventLoopTimer.hpp"
|
#include "../managers/eventLoop/EventLoopTimer.hpp"
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
class IWLBuffer;
|
class IHLBuffer;
|
||||||
|
|
||||||
enum eClientOwners {
|
enum eClientOwners {
|
||||||
CLIENT_SCREENCOPY = 0,
|
CLIENT_SCREENCOPY = 0,
|
||||||
|
@ -56,7 +56,7 @@ struct SScreencopyFrame {
|
||||||
|
|
||||||
bool bufferDMA = false;
|
bool bufferDMA = false;
|
||||||
|
|
||||||
WP<IWLBuffer> buffer;
|
WP<IHLBuffer> buffer;
|
||||||
|
|
||||||
CMonitor* pMonitor = nullptr;
|
CMonitor* pMonitor = nullptr;
|
||||||
PHLWINDOWREF pWindow;
|
PHLWINDOWREF pWindow;
|
||||||
|
@ -79,7 +79,7 @@ class CScreencopyProtocolManager {
|
||||||
|
|
||||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
||||||
|
|
||||||
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
|
void onOutputCommit(CMonitor* pMonitor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wl_global* m_pGlobal = nullptr;
|
wl_global* m_pGlobal = nullptr;
|
||||||
|
@ -93,7 +93,7 @@ class CScreencopyProtocolManager {
|
||||||
|
|
||||||
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
|
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
|
||||||
|
|
||||||
wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
|
SP<Aquamarine::IBuffer> m_pLastMonitorBackBuffer;
|
||||||
|
|
||||||
void shareAllFrames(CMonitor* pMonitor);
|
void shareAllFrames(CMonitor* pMonitor);
|
||||||
void shareFrame(SScreencopyFrame* frame);
|
void shareFrame(SScreencopyFrame* frame);
|
||||||
|
|
|
@ -193,16 +193,11 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PMONITOR->output->allocator && (PMONITOR->output->allocator->buffer_caps & WLR_BUFFER_CAP_DMABUF)) {
|
PFRAME->dmabufFormat = PMONITOR->output->state->state().drmFormat;
|
||||||
PFRAME->dmabufFormat = PMONITOR->output->render_format;
|
|
||||||
} else {
|
|
||||||
PFRAME->dmabufFormat = DRM_FORMAT_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)};
|
PFRAME->box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)};
|
||||||
int ow, oh;
|
|
||||||
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
|
PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round();
|
||||||
PFRAME->box.transform(wlTransformToHyprutils(PMONITOR->transform), ow, oh).round();
|
|
||||||
|
|
||||||
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
|
PFRAME->shmStride = FormatUtils::minStride(PSHMINFO, PFRAME->box.w);
|
||||||
|
|
||||||
|
@ -289,12 +284,10 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||||
m_vFramesAwaitingWrite.emplace_back(PFRAME);
|
m_vFramesAwaitingWrite.emplace_back(PFRAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
|
void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor) {
|
||||||
if (m_vFramesAwaitingWrite.empty())
|
if (m_vFramesAwaitingWrite.empty())
|
||||||
return; // nothing to share
|
return; // nothing to share
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output);
|
|
||||||
|
|
||||||
std::vector<SScreencopyFrame*> framesToRemove;
|
std::vector<SScreencopyFrame*> framesToRemove;
|
||||||
|
|
||||||
// share frame if correct output
|
// share frame if correct output
|
||||||
|
@ -306,7 +299,7 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PMONITOR != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID))
|
if (pMonitor != g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y};
|
CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y};
|
||||||
|
|
|
@ -21,7 +21,7 @@ class CToplevelExportProtocolManager {
|
||||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage);
|
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage);
|
||||||
void displayDestroy();
|
void displayDestroy();
|
||||||
void onWindowUnmap(PHLWINDOW pWindow);
|
void onWindowUnmap(PHLWINDOW pWindow);
|
||||||
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
|
void onOutputCommit(CMonitor* pMonitor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wl_global* m_pGlobal = nullptr;
|
wl_global* m_pGlobal = nullptr;
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#include "VirtualKeyboard.hpp"
|
#include "VirtualKeyboard.hpp"
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include "../devices/IKeyboard.hpp"
|
||||||
|
|
||||||
#define LOGM PROTO::virtualKeyboard->protoLog
|
#define LOGM PROTO::virtualKeyboard->protoLog
|
||||||
|
|
||||||
static const struct wlr_keyboard_impl virtualKeyboardImpl = {
|
|
||||||
.name = "virtual-keyboard",
|
|
||||||
};
|
|
||||||
|
|
||||||
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
|
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return;
|
return;
|
||||||
|
@ -28,13 +25,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard_key_event event = {
|
events.key.emit(IKeyboard::SKeyEvent{
|
||||||
.time_msec = timeMs,
|
.timeMs = timeMs,
|
||||||
.keycode = key,
|
.keycode = key,
|
||||||
.update_state = false,
|
|
||||||
.state = (wl_keyboard_key_state)state,
|
.state = (wl_keyboard_key_state)state,
|
||||||
};
|
});
|
||||||
wlr_keyboard_notify_key(&keyboard, &event);
|
|
||||||
|
const bool CONTAINS = std::find(pressed.begin(), pressed.end(), key) != pressed.end();
|
||||||
|
if (state && !CONTAINS)
|
||||||
|
pressed.emplace_back(key);
|
||||||
|
else if (!state && CONTAINS)
|
||||||
|
std::erase(pressed, key);
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
|
resource->setModifiers([this](CZwpVirtualKeyboardV1* r, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) {
|
||||||
|
@ -43,7 +44,12 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard_notify_modifiers(&keyboard, depressed, latched, locked, group);
|
events.modifiers.emit(IKeyboard::SModifiersEvent{
|
||||||
|
.depressed = depressed,
|
||||||
|
.latched = latched,
|
||||||
|
.locked = locked,
|
||||||
|
.group = group,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -75,7 +81,9 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard_set_keymap(&keyboard, xkbKeymap);
|
events.keymap.emit(IKeyboard::SKeymapEvent{
|
||||||
|
.keymap = xkbKeymap,
|
||||||
|
});
|
||||||
hasKeymap = true;
|
hasKeymap = true;
|
||||||
|
|
||||||
xkb_keymap_unref(xkbKeymap);
|
xkb_keymap_unref(xkbKeymap);
|
||||||
|
@ -83,22 +91,17 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
|
||||||
close(fd);
|
close(fd);
|
||||||
});
|
});
|
||||||
|
|
||||||
wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard");
|
name = "hl-virtual-keyboard";
|
||||||
}
|
}
|
||||||
|
|
||||||
CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() {
|
CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() {
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
wlr_keyboard_finish(&keyboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVirtualKeyboardV1Resource::good() {
|
bool CVirtualKeyboardV1Resource::good() {
|
||||||
return resource->resource();
|
return resource->resource();
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_keyboard* CVirtualKeyboardV1Resource::wlr() {
|
|
||||||
return &keyboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_client* CVirtualKeyboardV1Resource::client() {
|
wl_client* CVirtualKeyboardV1Resource::client() {
|
||||||
return resource->resource() ? resource->client() : nullptr;
|
return resource->resource() ? resource->client() : nullptr;
|
||||||
}
|
}
|
||||||
|
@ -106,17 +109,16 @@ wl_client* CVirtualKeyboardV1Resource::client() {
|
||||||
void CVirtualKeyboardV1Resource::releasePressed() {
|
void CVirtualKeyboardV1Resource::releasePressed() {
|
||||||
timespec now;
|
timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
size_t keycodesNum = keyboard.num_keycodes;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < keycodesNum; ++i) {
|
for (auto& p : pressed) {
|
||||||
struct wlr_keyboard_key_event event = {
|
events.key.emit(IKeyboard::SKeyEvent{
|
||||||
.time_msec = (now.tv_sec * 1000 + now.tv_nsec / 1000000),
|
.timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000,
|
||||||
.keycode = keyboard.keycodes[keycodesNum - i - 1],
|
.keycode = p,
|
||||||
.update_state = false,
|
|
||||||
.state = WL_KEYBOARD_KEY_STATE_RELEASED,
|
.state = WL_KEYBOARD_KEY_STATE_RELEASED,
|
||||||
};
|
});
|
||||||
wlr_keyboard_notify_key(&keyboard, &event); // updates num_keycodes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pressed.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
CVirtualKeyboardProtocol::CVirtualKeyboardProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
|
|
|
@ -14,19 +14,24 @@ class CVirtualKeyboardV1Resource {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CSignal destroy;
|
CSignal destroy;
|
||||||
|
CSignal key;
|
||||||
|
CSignal modifiers;
|
||||||
|
CSignal keymap;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
wlr_keyboard* wlr();
|
|
||||||
wl_client* client();
|
wl_client* client();
|
||||||
|
|
||||||
|
std::string name = "";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CZwpVirtualKeyboardV1> resource;
|
SP<CZwpVirtualKeyboardV1> resource;
|
||||||
wlr_keyboard keyboard;
|
|
||||||
|
|
||||||
void releasePressed();
|
void releasePressed();
|
||||||
|
|
||||||
bool hasKeymap = false;
|
bool hasKeymap = false;
|
||||||
|
|
||||||
|
std::vector<uint32_t> pressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CVirtualKeyboardProtocol : public IWaylandProtocol {
|
class CVirtualKeyboardProtocol : public IWaylandProtocol {
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
#define LOGM PROTO::virtualPointer->protoLog
|
#define LOGM PROTO::virtualPointer->protoLog
|
||||||
|
|
||||||
static const wlr_pointer_impl pointerImpl = {
|
|
||||||
.name = "virtual-pointer-v1",
|
|
||||||
};
|
|
||||||
|
|
||||||
CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
|
CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return;
|
return;
|
||||||
|
@ -19,41 +15,30 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
|
||||||
PROTO::virtualPointer->destroyResource(this);
|
PROTO::virtualPointer->destroyResource(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource");
|
|
||||||
|
|
||||||
resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) {
|
resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) {
|
||||||
wlr_pointer_motion_event event = {
|
events.move.emit(IPointer::SMotionEvent{
|
||||||
.pointer = &pointer,
|
.timeMs = timeMs,
|
||||||
.time_msec = timeMs,
|
.delta = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
|
||||||
.delta_x = wl_fixed_to_double(dx),
|
.unaccel = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
|
||||||
.delta_y = wl_fixed_to_double(dy),
|
});
|
||||||
.unaccel_dx = wl_fixed_to_double(dx),
|
|
||||||
.unaccel_dy = wl_fixed_to_double(dy),
|
|
||||||
};
|
|
||||||
wl_signal_emit_mutable(&pointer.events.motion, &event);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) {
|
resource->setMotionAbsolute([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t x, uint32_t y, uint32_t xExtent, uint32_t yExtent) {
|
||||||
if (!xExtent || !yExtent)
|
if (!xExtent || !yExtent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_pointer_motion_absolute_event event = {
|
events.warp.emit(IPointer::SMotionAbsoluteEvent{
|
||||||
.pointer = &pointer,
|
.timeMs = timeMs,
|
||||||
.time_msec = timeMs,
|
.absolute = {(double)x / xExtent, (double)y / yExtent},
|
||||||
.x = (double)x / xExtent,
|
});
|
||||||
.y = (double)y / yExtent,
|
|
||||||
};
|
|
||||||
wl_signal_emit_mutable(&pointer.events.motion_absolute, &event);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) {
|
resource->setButton([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t button, uint32_t state) {
|
||||||
struct wlr_pointer_button_event event = {
|
events.button.emit(IPointer::SButtonEvent{
|
||||||
.pointer = &pointer,
|
.timeMs = timeMs,
|
||||||
.time_msec = timeMs,
|
|
||||||
.button = button,
|
.button = button,
|
||||||
.state = (wl_pointer_button_state)state,
|
.state = (wl_pointer_button_state)state,
|
||||||
};
|
});
|
||||||
wl_signal_emit_mutable(&pointer.events.button, &event);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) {
|
resource->setAxis([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value) {
|
||||||
|
@ -63,18 +48,18 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
|
||||||
}
|
}
|
||||||
|
|
||||||
axis = axis_;
|
axis = axis_;
|
||||||
axisEvents[axis] = wlr_pointer_axis_event{.pointer = &pointer, .time_msec = timeMs, .orientation = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)};
|
axisEvents[axis] = IPointer::SAxisEvent{.timeMs = timeMs, .axis = (wl_pointer_axis)axis, .delta = wl_fixed_to_double(value)};
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setFrame([this](CZwlrVirtualPointerV1* r) {
|
resource->setFrame([this](CZwlrVirtualPointerV1* r) {
|
||||||
for (auto& e : axisEvents) {
|
for (auto& e : axisEvents) {
|
||||||
if (!e.pointer)
|
if (!e.timeMs)
|
||||||
continue;
|
continue;
|
||||||
wl_signal_emit_mutable(&pointer.events.axis, &e);
|
events.axis.emit(e);
|
||||||
e.pointer = nullptr;
|
e.timeMs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_emit_mutable(&pointer.events.frame, &pointer);
|
events.frame.emit();
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; });
|
resource->setAxisSource([this](CZwlrVirtualPointerV1* r, uint32_t source) { axisEvents[axis].source = (wl_pointer_axis_source)source; });
|
||||||
|
@ -86,11 +71,10 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
|
||||||
}
|
}
|
||||||
|
|
||||||
axis = axis_;
|
axis = axis_;
|
||||||
axisEvents[axis].pointer = &pointer;
|
axisEvents[axis].timeMs = timeMs;
|
||||||
axisEvents[axis].time_msec = timeMs;
|
axisEvents[axis].axis = (wl_pointer_axis)axis;
|
||||||
axisEvents[axis].orientation = (wl_pointer_axis)axis;
|
|
||||||
axisEvents[axis].delta = 0;
|
axisEvents[axis].delta = 0;
|
||||||
axisEvents[axis].delta_discrete = 0;
|
axisEvents[axis].deltaDiscrete = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) {
|
resource->setAxisDiscrete([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, uint32_t axis_, wl_fixed_t value, int32_t discrete) {
|
||||||
|
@ -100,16 +84,14 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
|
||||||
}
|
}
|
||||||
|
|
||||||
axis = axis_;
|
axis = axis_;
|
||||||
axisEvents[axis].pointer = &pointer;
|
axisEvents[axis].timeMs = timeMs;
|
||||||
axisEvents[axis].time_msec = timeMs;
|
axisEvents[axis].axis = (wl_pointer_axis)axis;
|
||||||
axisEvents[axis].orientation = (wl_pointer_axis)axis;
|
|
||||||
axisEvents[axis].delta = wl_fixed_to_double(value);
|
axisEvents[axis].delta = wl_fixed_to_double(value);
|
||||||
axisEvents[axis].delta_discrete = discrete * 120;
|
axisEvents[axis].deltaDiscrete = discrete * 120;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CVirtualPointerV1Resource::~CVirtualPointerV1Resource() {
|
CVirtualPointerV1Resource::~CVirtualPointerV1Resource() {
|
||||||
wlr_pointer_finish(&pointer);
|
|
||||||
events.destroy.emit();
|
events.destroy.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,10 +99,6 @@ bool CVirtualPointerV1Resource::good() {
|
||||||
return resource->resource();
|
return resource->resource();
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_pointer* CVirtualPointerV1Resource::wlr() {
|
|
||||||
return &pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_client* CVirtualPointerV1Resource::client() {
|
wl_client* CVirtualPointerV1Resource::client() {
|
||||||
return resource->client();
|
return resource->client();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "WaylandProtocol.hpp"
|
#include "WaylandProtocol.hpp"
|
||||||
#include "wlr-virtual-pointer-unstable-v1.hpp"
|
#include "wlr-virtual-pointer-unstable-v1.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
#include "../devices/IPointer.hpp"
|
||||||
|
|
||||||
class CVirtualPointerV1Resource {
|
class CVirtualPointerV1Resource {
|
||||||
public:
|
public:
|
||||||
|
@ -15,19 +16,35 @@ class CVirtualPointerV1Resource {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CSignal destroy;
|
CSignal destroy;
|
||||||
|
CSignal move;
|
||||||
|
CSignal warp;
|
||||||
|
CSignal button;
|
||||||
|
CSignal axis;
|
||||||
|
CSignal frame;
|
||||||
|
|
||||||
|
CSignal swipeBegin;
|
||||||
|
CSignal swipeUpdate;
|
||||||
|
CSignal swipeEnd;
|
||||||
|
|
||||||
|
CSignal pinchBegin;
|
||||||
|
CSignal pinchUpdate;
|
||||||
|
CSignal pinchEnd;
|
||||||
|
|
||||||
|
CSignal holdBegin;
|
||||||
|
CSignal holdEnd;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
bool good();
|
bool good();
|
||||||
wlr_pointer* wlr();
|
|
||||||
wl_client* client();
|
wl_client* client();
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CZwlrVirtualPointerV1> resource;
|
SP<CZwlrVirtualPointerV1> resource;
|
||||||
wlr_pointer pointer;
|
|
||||||
|
|
||||||
uint32_t axis = 0;
|
uint32_t axis = 0;
|
||||||
|
|
||||||
std::array<wlr_pointer_axis_event, 2> axisEvents;
|
std::array<IPointer::SAxisEvent, 2> axisEvents;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CVirtualPointerProtocol : public IWaylandProtocol {
|
class CVirtualPointerProtocol : public IWaylandProtocol {
|
||||||
|
|
|
@ -75,8 +75,8 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(CZxdgOutputManagerV1* mgr, uint32
|
||||||
|
|
||||||
if (XDGVER >= OUTPUT_NAME_SINCE_VERSION)
|
if (XDGVER >= OUTPUT_NAME_SINCE_VERSION)
|
||||||
pXDGOutput->resource->sendName(PMONITOR->szName.c_str());
|
pXDGOutput->resource->sendName(PMONITOR->szName.c_str());
|
||||||
if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && PMONITOR->output->description)
|
if (XDGVER >= OUTPUT_DESCRIPTION_SINCE_VERSION && !PMONITOR->output->description.empty())
|
||||||
pXDGOutput->resource->sendDescription(PMONITOR->output->description);
|
pXDGOutput->resource->sendDescription(PMONITOR->output->description.c_str());
|
||||||
|
|
||||||
pXDGOutput->sendDetails();
|
pXDGOutput->sendDetails();
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ void CXDGOutputProtocol::updateAllOutputs() {
|
||||||
|
|
||||||
o->sendDetails();
|
o->sendDetails();
|
||||||
|
|
||||||
wlr_output_schedule_done(o->monitor->output);
|
o->monitor->scheduleDone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ class CWLSurfaceResource {
|
||||||
CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */;
|
CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
SP<IWLBuffer> buffer;
|
SP<IHLBuffer> buffer;
|
||||||
SP<CTexture> texture;
|
SP<CTexture> texture;
|
||||||
Vector2D offset;
|
Vector2D offset;
|
||||||
Vector2D size;
|
Vector2D size;
|
||||||
|
|
|
@ -21,8 +21,8 @@ CWLOutputResource::CWLOutputResource(SP<CWlOutput> resource_, SP<CMonitor> pMoni
|
||||||
PROTO::outputs.at(monitor->szName)->destroyResource(this);
|
PROTO::outputs.at(monitor->szName)->destroyResource(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->sendGeometry(0, 0, monitor->output->phys_width, monitor->output->phys_height, monitor->output->subpixel, monitor->output->make ? monitor->output->make : "null",
|
resource->sendGeometry(0, 0, monitor->output->physicalSize.x, monitor->output->physicalSize.y, (wl_output_subpixel)monitor->output->subpixel, monitor->output->make.c_str(),
|
||||||
monitor->output->model ? monitor->output->model : "null", monitor->transform);
|
monitor->output->model.c_str(), monitor->transform);
|
||||||
if (resource->version() >= 4) {
|
if (resource->version() >= 4) {
|
||||||
resource->sendName(monitor->szName.c_str());
|
resource->sendName(monitor->szName.c_str());
|
||||||
resource->sendDescription(monitor->szDescription.c_str());
|
resource->sendDescription(monitor->szDescription.c_str());
|
||||||
|
@ -115,3 +115,9 @@ void CWLOutputProtocol::remove() {
|
||||||
bool CWLOutputProtocol::isDefunct() {
|
bool CWLOutputProtocol::isDefunct() {
|
||||||
return defunct;
|
return defunct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWLOutputProtocol::sendDone() {
|
||||||
|
for (auto& r : m_vOutputs) {
|
||||||
|
r->resource->sendDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ class CWLOutputResource {
|
||||||
private:
|
private:
|
||||||
SP<CWlOutput> resource;
|
SP<CWlOutput> resource;
|
||||||
wl_client* pClient = nullptr;
|
wl_client* pClient = nullptr;
|
||||||
|
|
||||||
|
friend class CWLOutputProtocol;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWLOutputProtocol : public IWaylandProtocol {
|
class CWLOutputProtocol : public IWaylandProtocol {
|
||||||
|
@ -35,6 +37,7 @@ class CWLOutputProtocol : public IWaylandProtocol {
|
||||||
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);
|
||||||
|
|
||||||
SP<CWLOutputResource> outputResourceFrom(wl_client* client);
|
SP<CWLOutputResource> outputResourceFrom(wl_client* client);
|
||||||
|
void sendDone();
|
||||||
|
|
||||||
WP<CMonitor> monitor;
|
WP<CMonitor> monitor;
|
||||||
|
|
||||||
|
|
|
@ -254,8 +254,8 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
|
||||||
int fd;
|
int fd;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
if (keyboard) {
|
if (keyboard) {
|
||||||
fd = keyboard->wlr()->keymap_fd;
|
fd = keyboard->xkbKeymapFD;
|
||||||
size = keyboard->wlr()->keymap_size;
|
size = keyboard->xkbKeymapString.length() + 1;
|
||||||
} else {
|
} else {
|
||||||
fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
|
@ -41,20 +41,20 @@ CWLSHMBuffer::~CWLSHMBuffer() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
eBufferCapability CWLSHMBuffer::caps() {
|
Aquamarine::eBufferCapability CWLSHMBuffer::caps() {
|
||||||
return BUFFER_CAPABILITY_DATAPTR;
|
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
eBufferType CWLSHMBuffer::type() {
|
Aquamarine::eBufferType CWLSHMBuffer::type() {
|
||||||
return BUFFER_TYPE_SHM;
|
return Aquamarine::eBufferType::BUFFER_TYPE_SHM;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWLSHMBuffer::isSynchronous() {
|
bool CWLSHMBuffer::isSynchronous() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSHMAttrs CWLSHMBuffer::shm() {
|
Aquamarine::SSHMAttrs CWLSHMBuffer::shm() {
|
||||||
SSHMAttrs attrs;
|
Aquamarine::SSHMAttrs attrs;
|
||||||
attrs.success = true;
|
attrs.success = true;
|
||||||
attrs.fd = pool->fd;
|
attrs.fd = pool->fd;
|
||||||
attrs.format = FormatUtils::shmToDRM(fmt);
|
attrs.format = FormatUtils::shmToDRM(fmt);
|
||||||
|
@ -189,11 +189,10 @@ CWLSHMProtocol::CWLSHMProtocol(const wl_interface* iface, const int& ver, const
|
||||||
void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
void CWLSHMProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
if (shmFormats.empty()) {
|
if (shmFormats.empty()) {
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const uint32_t* formats = wlr_renderer_get_shm_texture_formats(g_pCompositor->m_sWLRRenderer, &len);
|
// TODO: support 10 bit shm
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
shmFormats.push_back(WL_SHM_FORMAT_ARGB8888);
|
||||||
shmFormats.push_back(FormatUtils::drmToShm(formats[i]));
|
shmFormats.push_back(WL_SHM_FORMAT_XRGB8888);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CWLSHMResource>(makeShared<CWlShm>(client, ver, id)));
|
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CWLSHMResource>(makeShared<CWlShm>(client, ver, id)));
|
||||||
|
|
|
@ -29,16 +29,16 @@ class CSHMPool {
|
||||||
void resize(size_t size);
|
void resize(size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWLSHMBuffer : public IWLBuffer {
|
class CWLSHMBuffer : public IHLBuffer {
|
||||||
public:
|
public:
|
||||||
CWLSHMBuffer(SP<CWLSHMPoolResource> pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt);
|
CWLSHMBuffer(SP<CWLSHMPoolResource> pool, uint32_t id, int32_t offset, const Vector2D& size, int32_t stride, uint32_t fmt);
|
||||||
virtual ~CWLSHMBuffer();
|
virtual ~CWLSHMBuffer();
|
||||||
|
|
||||||
virtual eBufferCapability caps();
|
virtual Aquamarine::eBufferCapability caps();
|
||||||
virtual eBufferType type();
|
virtual Aquamarine::eBufferType type();
|
||||||
virtual void update(const CRegion& damage);
|
virtual void update(const CRegion& damage);
|
||||||
virtual bool isSynchronous();
|
virtual bool isSynchronous();
|
||||||
virtual SSHMAttrs shm();
|
virtual Aquamarine::SSHMAttrs shm();
|
||||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||||
virtual void endDataPtr();
|
virtual void endDataPtr();
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,5 @@
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
#include "WLBuffer.hpp"
|
|
||||||
|
|
||||||
SDMABUFAttrs IWLBuffer::dmabuf() {
|
void IHLBuffer::sendRelease() {
|
||||||
return SDMABUFAttrs{};
|
resource->sendRelease();
|
||||||
}
|
|
||||||
|
|
||||||
SSHMAttrs IWLBuffer::shm() {
|
|
||||||
return SSHMAttrs{};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<uint8_t*, uint32_t, size_t> IWLBuffer::beginDataPtr(uint32_t flags) {
|
|
||||||
return {nullptr, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWLBuffer::endDataPtr() {
|
|
||||||
; // empty
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWLBuffer::sendRelease() {
|
|
||||||
if (!resource || !resource->resource)
|
|
||||||
return;
|
|
||||||
resource->resource->sendRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWLBuffer::lock() {
|
|
||||||
locks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWLBuffer::unlock() {
|
|
||||||
locks--;
|
|
||||||
|
|
||||||
ASSERT(locks >= 0);
|
|
||||||
|
|
||||||
if (locks <= 0)
|
|
||||||
sendRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IWLBuffer::locked() {
|
|
||||||
return locks;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,75 +1,24 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../defines.hpp"
|
#include "../../defines.hpp"
|
||||||
#include "../../helpers/signal/Signal.hpp"
|
|
||||||
#include "../../render/Texture.hpp"
|
#include "../../render/Texture.hpp"
|
||||||
|
#include "./WLBuffer.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
enum eBufferCapability {
|
class IHLBuffer : public Aquamarine::IBuffer {
|
||||||
BUFFER_CAPABILITY_DATAPTR = (1 << 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eBufferType {
|
|
||||||
BUFFER_TYPE_DMABUF = 0,
|
|
||||||
BUFFER_TYPE_SHM,
|
|
||||||
BUFFER_TYPE_MISC,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CWLBufferResource;
|
|
||||||
|
|
||||||
struct SDMABUFAttrs {
|
|
||||||
bool success = false;
|
|
||||||
Vector2D size;
|
|
||||||
uint32_t format = 0; // fourcc
|
|
||||||
uint64_t modifier = 0;
|
|
||||||
|
|
||||||
int planes = 1;
|
|
||||||
std::array<uint32_t, 4> offsets = {0};
|
|
||||||
std::array<uint32_t, 4> strides = {0};
|
|
||||||
std::array<int, 4> fds = {-1, -1, -1, -1};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SSHMAttrs {
|
|
||||||
bool success = false;
|
|
||||||
int fd = 0;
|
|
||||||
uint32_t format = 0;
|
|
||||||
Vector2D size;
|
|
||||||
int stride = 0;
|
|
||||||
int64_t offset = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IWLBuffer {
|
|
||||||
public:
|
public:
|
||||||
virtual ~IWLBuffer() {
|
virtual ~IHLBuffer() {
|
||||||
;
|
;
|
||||||
};
|
}
|
||||||
|
virtual Aquamarine::eBufferCapability caps() = 0;
|
||||||
virtual eBufferCapability caps() = 0;
|
virtual Aquamarine::eBufferType type() = 0;
|
||||||
virtual eBufferType type() = 0;
|
|
||||||
virtual void update(const CRegion& damage) = 0;
|
virtual void update(const CRegion& damage) = 0;
|
||||||
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
|
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||||
virtual SDMABUFAttrs dmabuf();
|
virtual bool good() = 0;
|
||||||
virtual SSHMAttrs shm();
|
|
||||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
|
||||||
virtual void endDataPtr();
|
|
||||||
virtual void sendRelease();
|
virtual void sendRelease();
|
||||||
virtual void lock();
|
|
||||||
virtual void unlock();
|
|
||||||
virtual bool locked();
|
|
||||||
|
|
||||||
Vector2D size;
|
|
||||||
bool opaque = false;
|
|
||||||
|
|
||||||
SP<CWLBufferResource> resource;
|
|
||||||
|
|
||||||
SP<CTexture> texture;
|
SP<CTexture> texture;
|
||||||
|
bool opaque = false;
|
||||||
struct {
|
SP<CWLBufferResource> resource;
|
||||||
CSignal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int locks = 0;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "../../render/Renderer.hpp"
|
#include "../../render/Renderer.hpp"
|
||||||
#include "../../helpers/Format.hpp"
|
#include "../../helpers/Format.hpp"
|
||||||
|
|
||||||
CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_) : attrs(attrs_) {
|
CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : attrs(attrs_) {
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
|
|
||||||
listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) {
|
listeners.resourceDestroy = events.destroy.registerListener([this](std::any d) {
|
||||||
|
@ -31,12 +31,12 @@ CDMABuffer::~CDMABuffer() {
|
||||||
closeFDs();
|
closeFDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
eBufferCapability CDMABuffer::caps() {
|
Aquamarine::eBufferCapability CDMABuffer::caps() {
|
||||||
return BUFFER_CAPABILITY_DATAPTR;
|
return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
eBufferType CDMABuffer::type() {
|
Aquamarine::eBufferType CDMABuffer::type() {
|
||||||
return BUFFER_TYPE_DMABUF;
|
return Aquamarine::eBufferType::BUFFER_TYPE_DMABUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDMABuffer::update(const CRegion& damage) {
|
void CDMABuffer::update(const CRegion& damage) {
|
||||||
|
@ -47,7 +47,7 @@ bool CDMABuffer::isSynchronous() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDMABUFAttrs CDMABuffer::dmabuf() {
|
Aquamarine::SDMABUFAttrs CDMABuffer::dmabuf() {
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
|
|
||||||
class CDMABuffer : public IWLBuffer {
|
class CDMABuffer : public IHLBuffer {
|
||||||
public:
|
public:
|
||||||
CDMABuffer(uint32_t id, wl_client* client, SDMABUFAttrs const& attrs_);
|
CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_);
|
||||||
virtual ~CDMABuffer();
|
virtual ~CDMABuffer();
|
||||||
|
|
||||||
virtual eBufferCapability caps();
|
virtual Aquamarine::eBufferCapability caps();
|
||||||
virtual eBufferType type();
|
virtual Aquamarine::eBufferType type();
|
||||||
virtual bool isSynchronous();
|
virtual bool isSynchronous();
|
||||||
virtual void update(const CRegion& damage);
|
virtual void update(const CRegion& damage);
|
||||||
virtual SDMABUFAttrs dmabuf();
|
virtual Aquamarine::SDMABUFAttrs dmabuf();
|
||||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||||
virtual void endDataPtr();
|
virtual void endDataPtr();
|
||||||
bool good();
|
bool good();
|
||||||
|
@ -21,7 +21,7 @@ class CDMABuffer : public IWLBuffer {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDMABUFAttrs attrs;
|
Aquamarine::SDMABUFAttrs attrs;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CHyprSignalListener resourceDestroy;
|
CHyprSignalListener resourceDestroy;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "wayland.hpp"
|
#include "wayland.hpp"
|
||||||
#include "../../helpers/signal/Signal.hpp"
|
#include "../../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
class IWLBuffer;
|
class IHLBuffer;
|
||||||
|
|
||||||
class CWLBufferResource {
|
class CWLBufferResource {
|
||||||
public:
|
public:
|
||||||
|
@ -18,7 +18,7 @@ class CWLBufferResource {
|
||||||
void sendRelease();
|
void sendRelease();
|
||||||
wl_resource* getResource();
|
wl_resource* getResource();
|
||||||
|
|
||||||
WP<IWLBuffer> buffer;
|
WP<IHLBuffer> buffer;
|
||||||
|
|
||||||
WP<CWLBufferResource> self;
|
WP<CWLBufferResource> self;
|
||||||
|
|
||||||
|
@ -27,5 +27,5 @@ class CWLBufferResource {
|
||||||
|
|
||||||
SP<CWlBuffer> resource;
|
SP<CWlBuffer> resource;
|
||||||
|
|
||||||
friend class IWLBuffer;
|
friend class IHLBuffer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
inline void loadGLProc(void* pProc, const char* name) {
|
inline void loadGLProc(void* pProc, const char* name) {
|
||||||
void* proc = (void*)eglGetProcAddress(name);
|
void* proc = (void*)eglGetProcAddress(name);
|
||||||
|
@ -19,17 +21,198 @@ inline void loadGLProc(void* pProc, const char* name) {
|
||||||
*(void**)pProc = proc;
|
*(void**)pProc = proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum LogLevel eglLogToLevel(EGLint type) {
|
||||||
|
switch (type) {
|
||||||
|
case EGL_DEBUG_MSG_CRITICAL_KHR: return CRIT;
|
||||||
|
case EGL_DEBUG_MSG_ERROR_KHR: return ERR;
|
||||||
|
case EGL_DEBUG_MSG_WARN_KHR: return WARN;
|
||||||
|
case EGL_DEBUG_MSG_INFO_KHR: return LOG;
|
||||||
|
default: return LOG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* eglErrorToString(EGLint error) {
|
||||||
|
switch (error) {
|
||||||
|
case EGL_SUCCESS: return "EGL_SUCCESS";
|
||||||
|
case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
|
||||||
|
case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
|
||||||
|
case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
|
||||||
|
case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
|
||||||
|
case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
|
||||||
|
case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
|
||||||
|
case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
|
||||||
|
case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
|
||||||
|
case EGL_BAD_DEVICE_EXT: return "EGL_BAD_DEVICE_EXT";
|
||||||
|
case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
|
||||||
|
case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
|
||||||
|
case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
|
||||||
|
case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
|
||||||
|
case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eglLog(EGLenum error, const char* command, EGLint type, EGLLabelKHR thread, EGLLabelKHR obj, const char* msg) {
|
||||||
|
Debug::log(eglLogToLevel(type), "[EGL] Command {} errored out with {} (0x{}): {}", command, eglErrorToString(error), error, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int openRenderNode(int drmFd) {
|
||||||
|
char* renderName = drmGetRenderDeviceNameFromFd(drmFd);
|
||||||
|
if (renderName == NULL) {
|
||||||
|
// This can happen on split render/display platforms, fallback to
|
||||||
|
// primary node
|
||||||
|
renderName = drmGetPrimaryDeviceNameFromFd(drmFd);
|
||||||
|
if (renderName == NULL) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "drmGetPrimaryDeviceNameFromFd failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wlr_log(WLR_DEBUG,
|
||||||
|
"DRM device '%s' has no render node, "
|
||||||
|
"falling back to primary node",
|
||||||
|
renderName);
|
||||||
|
|
||||||
|
drmVersion* render_version = drmGetVersion(drmFd);
|
||||||
|
if (render_version != NULL && render_version->name != NULL) {
|
||||||
|
wlr_log(WLR_DEBUG, "DRM device version.name '%s'", render_version->name);
|
||||||
|
if (strcmp(render_version->name, "evdi") == 0) {
|
||||||
|
free(renderName);
|
||||||
|
renderName = (char*)malloc(sizeof(char) * 15);
|
||||||
|
strcpy(renderName, "/dev/dri/card0");
|
||||||
|
}
|
||||||
|
drmFreeVersion(render_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(WLR_DEBUG, "open_render_node() DRM device '%s'", renderName);
|
||||||
|
|
||||||
|
int render_fd = open(renderName, O_RDWR | O_CLOEXEC);
|
||||||
|
if (render_fd < 0) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Failed to open DRM node '%s'", renderName);
|
||||||
|
}
|
||||||
|
free(renderName);
|
||||||
|
return render_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::initEGL(bool gbm) {
|
||||||
|
std::vector<EGLint> attrs;
|
||||||
|
if (m_sExts.KHR_display_reference) {
|
||||||
|
attrs.push_back(EGL_TRACK_REFERENCES_KHR);
|
||||||
|
attrs.push_back(EGL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs.push_back(EGL_NONE);
|
||||||
|
|
||||||
|
m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : nullptr, attrs.data());
|
||||||
|
if (m_pEglDisplay == EGL_NO_DISPLAY)
|
||||||
|
RASSERT(false, "EGL: failed to create a platform display");
|
||||||
|
|
||||||
|
attrs.clear();
|
||||||
|
|
||||||
|
EGLint major, minor;
|
||||||
|
if (eglInitialize(m_pEglDisplay, &major, &minor) == EGL_FALSE)
|
||||||
|
RASSERT(false, "EGL: failed to initialize a platform display");
|
||||||
|
|
||||||
|
const std::string EGLEXTENSIONS = (const char*)eglQueryString(m_pEglDisplay, EGL_EXTENSIONS);
|
||||||
|
|
||||||
|
m_sExts.IMG_context_priority = EGLEXTENSIONS.contains("IMG_context_priority");
|
||||||
|
m_sExts.EXT_create_context_robustness = EGLEXTENSIONS.contains("EXT_create_context_robustness");
|
||||||
|
m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import");
|
||||||
|
m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers");
|
||||||
|
|
||||||
|
if (m_sExts.IMG_context_priority) {
|
||||||
|
Debug::log(LOG, "EGL: IMG_context_priority supported, requesting high");
|
||||||
|
attrs.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
|
||||||
|
attrs.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_sExts.EXT_create_context_robustness) {
|
||||||
|
Debug::log(LOG, "EGL: EXT_create_context_robustness supported, requesting lose on reset");
|
||||||
|
attrs.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
|
||||||
|
attrs.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
|
||||||
|
attrs.push_back(3);
|
||||||
|
attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
|
||||||
|
attrs.push_back(2);
|
||||||
|
attrs.push_back(EGL_CONTEXT_OPENGL_DEBUG);
|
||||||
|
attrs.push_back(ISDEBUG ? EGL_TRUE : EGL_FALSE);
|
||||||
|
|
||||||
|
attrs.push_back(EGL_NONE);
|
||||||
|
|
||||||
|
m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data());
|
||||||
|
if (m_pEglContext == EGL_NO_CONTEXT)
|
||||||
|
RASSERT(false, "EGL: failed to create a context");
|
||||||
|
|
||||||
|
if (m_sExts.IMG_context_priority) {
|
||||||
|
EGLint priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
|
||||||
|
eglQueryContext(m_pEglDisplay, m_pEglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &priority);
|
||||||
|
if (priority != EGL_CONTEXT_PRIORITY_HIGH_IMG)
|
||||||
|
Debug::log(ERR, "EGL: Failed to obtain a high priority context");
|
||||||
|
else
|
||||||
|
Debug::log(LOG, "EGL: Got a high priority context");
|
||||||
|
}
|
||||||
|
|
||||||
|
eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_pEglContext);
|
||||||
|
}
|
||||||
|
|
||||||
CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)),
|
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
"Couldn't unset current EGL!");
|
|
||||||
|
|
||||||
auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
|
Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::count(EGLEXTENSIONS.begin(), EGLEXTENSIONS.end(), ' '), EGLEXTENSIONS);
|
||||||
const std::string EGLEXTENSIONS = (const char*)eglQueryString(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_EXTENSIONS);
|
|
||||||
|
|
||||||
RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!");
|
|
||||||
|
|
||||||
m_iDRMFD = g_pCompositor->m_iDRMFD;
|
m_iDRMFD = g_pCompositor->m_iDRMFD;
|
||||||
|
|
||||||
|
m_sExts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference");
|
||||||
|
|
||||||
|
loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES");
|
||||||
|
loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR");
|
||||||
|
loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR");
|
||||||
|
loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT");
|
||||||
|
loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT");
|
||||||
|
loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
|
||||||
|
loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR");
|
||||||
|
loadGLProc(&m_sProc.eglGetPlatformDisplayEXT, "eglGetPlatformDisplayEXT");
|
||||||
|
|
||||||
|
if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_enumeration"))
|
||||||
|
loadGLProc(&m_sProc.eglQueryDevicesEXT, "eglQueryDevicesEXT");
|
||||||
|
|
||||||
|
if (EGLEXTENSIONS.contains("EGL_EXT_device_base") || EGLEXTENSIONS.contains("EGL_EXT_device_query")) {
|
||||||
|
loadGLProc(&m_sProc.eglQueryDeviceStringEXT, "eglQueryDeviceStringEXT");
|
||||||
|
loadGLProc(&m_sProc.eglQueryDisplayAttribEXT, "eglQueryDisplayAttribEXT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EGLEXTENSIONS.contains("EGL_KHR_debug")) {
|
||||||
|
loadGLProc(&m_sProc.eglDebugMessageControlKHR, "eglDebugMessageControlKHR");
|
||||||
|
static const EGLAttrib debugAttrs[] = {
|
||||||
|
EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE, EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE, EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE, EGL_NONE,
|
||||||
|
};
|
||||||
|
m_sProc.eglDebugMessageControlKHR(::eglLog, debugAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to EGL's opengl ES API. This means your gpu driver f'd up. This is not a hyprland issue.");
|
||||||
|
|
||||||
|
// if (m_sProc.eglQueryDevicesEXT) {
|
||||||
|
// // TODO:
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (EGLEXTENSIONS.contains("KHR_platform_gbm")) {
|
||||||
|
m_iGBMFD = openRenderNode(m_iDRMFD);
|
||||||
|
if (m_iGBMFD < 0)
|
||||||
|
RASSERT(false, "Couldn't open a gbm fd");
|
||||||
|
|
||||||
|
m_pGbmDevice = gbm_create_device(m_iGBMFD);
|
||||||
|
if (!m_pGbmDevice)
|
||||||
|
RASSERT(false, "Couldn't open a gbm device");
|
||||||
|
|
||||||
|
initEGL(true);
|
||||||
|
} else
|
||||||
|
RASSERT(false, "EGL does not support KHR_platform_gbm, this is an issue with your gpu driver.");
|
||||||
|
|
||||||
|
auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
|
||||||
|
RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!");
|
||||||
|
|
||||||
m_szExtensions = EXTENSIONS;
|
m_szExtensions = EXTENSIONS;
|
||||||
|
|
||||||
Debug::log(LOG, "Creating the Hypr OpenGL Renderer!");
|
Debug::log(LOG, "Creating the Hypr OpenGL Renderer!");
|
||||||
|
@ -38,16 +221,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||||
Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER));
|
Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER));
|
||||||
Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions);
|
Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions);
|
||||||
|
|
||||||
loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES");
|
|
||||||
loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR");
|
|
||||||
loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR");
|
|
||||||
loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT");
|
|
||||||
loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT");
|
|
||||||
loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
|
|
||||||
|
|
||||||
m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
|
m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
|
||||||
m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import");
|
|
||||||
m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers");
|
|
||||||
|
|
||||||
RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required");
|
RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required");
|
||||||
|
|
||||||
|
@ -74,7 +248,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||||
|
|
||||||
static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
|
static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
|
||||||
|
|
||||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
|
RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
|
||||||
|
|
||||||
m_tGlobalTimer.reset();
|
m_tGlobalTimer.reset();
|
||||||
}
|
}
|
||||||
|
@ -86,7 +260,7 @@ std::optional<std::vector<uint64_t>> CHyprOpenGLImpl::getModsForFormat(EGLint fo
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
EGLint len = 0;
|
EGLint len = 0;
|
||||||
if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) {
|
if (!m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, 0, nullptr, nullptr, &len)) {
|
||||||
Debug::log(ERR, "EGL: Failed to query mods");
|
Debug::log(ERR, "EGL: Failed to query mods");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +274,7 @@ std::optional<std::vector<uint64_t>> CHyprOpenGLImpl::getModsForFormat(EGLint fo
|
||||||
mods.resize(len);
|
mods.resize(len);
|
||||||
external.resize(len);
|
external.resize(len);
|
||||||
|
|
||||||
m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len);
|
m_sProc.eglQueryDmaBufModifiersEXT(m_pEglDisplay, format, len, mods.data(), external.data(), &len);
|
||||||
|
|
||||||
std::vector<uint64_t> result;
|
std::vector<uint64_t> result;
|
||||||
bool linearIsExternal = false;
|
bool linearIsExternal = false;
|
||||||
|
@ -139,9 +313,9 @@ void CHyprOpenGLImpl::initDRMFormats() {
|
||||||
Debug::log(WARN, "EGL: No mod support");
|
Debug::log(WARN, "EGL: No mod support");
|
||||||
} else {
|
} else {
|
||||||
EGLint len = 0;
|
EGLint len = 0;
|
||||||
m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), 0, nullptr, &len);
|
m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, 0, nullptr, &len);
|
||||||
formats.resize(len);
|
formats.resize(len);
|
||||||
m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), len, formats.data(), &len);
|
m_sProc.eglQueryDmaBufFormatsEXT(m_pEglDisplay, len, formats.data(), &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formats.size() == 0) {
|
if (formats.size() == 0) {
|
||||||
|
@ -209,7 +383,7 @@ void CHyprOpenGLImpl::initDRMFormats() {
|
||||||
drmFormats = dmaFormats;
|
drmFormats = dmaFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) {
|
EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attrs) {
|
||||||
std::vector<uint32_t> attribs;
|
std::vector<uint32_t> attribs;
|
||||||
|
|
||||||
attribs.push_back(EGL_WIDTH);
|
attribs.push_back(EGL_WIDTH);
|
||||||
|
@ -251,7 +425,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) {
|
||||||
|
|
||||||
attribs.push_back(EGL_NONE);
|
attribs.push_back(EGL_NONE);
|
||||||
|
|
||||||
EGLImageKHR image = m_sProc.eglCreateImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data());
|
EGLImageKHR image = m_sProc.eglCreateImageKHR(m_pEglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data());
|
||||||
if (image == EGL_NO_IMAGE_KHR) {
|
if (image == EGL_NO_IMAGE_KHR) {
|
||||||
Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError());
|
Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError());
|
||||||
return EGL_NO_IMAGE_KHR;
|
return EGL_NO_IMAGE_KHR;
|
||||||
|
@ -913,11 +1087,8 @@ void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) {
|
||||||
CBox newBox = *pBox;
|
CBox newBox = *pBox;
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
int w, h;
|
|
||||||
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
|
||||||
|
|
||||||
const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform));
|
const auto TR = wlTransformToHyprutils(wlr_output_transform_invert(m_RenderData.pMonitor->transform));
|
||||||
newBox.transform(TR, w, h);
|
newBox.transform(TR, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
||||||
|
@ -2472,6 +2643,9 @@ void CHyprOpenGLImpl::clearWithTex() {
|
||||||
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
|
|
||||||
|
if (!g_pHyprOpenGL)
|
||||||
|
return;
|
||||||
|
|
||||||
auto RESIT = g_pHyprOpenGL->m_mMonitorRenderResources.find(pMonitor);
|
auto RESIT = g_pHyprOpenGL->m_mMonitorRenderResources.find(pMonitor);
|
||||||
if (RESIT != g_pHyprOpenGL->m_mMonitorRenderResources.end()) {
|
if (RESIT != g_pHyprOpenGL->m_mMonitorRenderResources.end()) {
|
||||||
RESIT->second.mirrorFB.release();
|
RESIT->second.mirrorFB.release();
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
#include "Renderbuffer.hpp"
|
#include "Renderbuffer.hpp"
|
||||||
|
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
|
||||||
#include "../debug/TracyDefines.hpp"
|
#include "../debug/TracyDefines.hpp"
|
||||||
|
|
||||||
|
struct gbm_device;
|
||||||
class CHyprRenderer;
|
class CHyprRenderer;
|
||||||
|
|
||||||
inline const float fullVerts[] = {
|
inline const float fullVerts[] = {
|
||||||
|
@ -182,12 +184,17 @@ class CHyprOpenGLImpl {
|
||||||
|
|
||||||
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
|
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
|
||||||
std::vector<SDRMFormat> getDRMFormats();
|
std::vector<SDRMFormat> getDRMFormats();
|
||||||
EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs);
|
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||||
|
|
||||||
SCurrentRenderData m_RenderData;
|
SCurrentRenderData m_RenderData;
|
||||||
|
|
||||||
GLint m_iCurrentOutputFb = 0;
|
GLint m_iCurrentOutputFb = 0;
|
||||||
|
|
||||||
|
int m_iGBMFD = -1;
|
||||||
|
gbm_device* m_pGbmDevice = nullptr;
|
||||||
|
EGLContext m_pEglContext = nullptr;
|
||||||
|
EGLDisplay m_pEglDisplay = nullptr;
|
||||||
|
|
||||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||||
|
|
||||||
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
|
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
|
||||||
|
@ -205,12 +212,20 @@ class CHyprOpenGLImpl {
|
||||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
||||||
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
|
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
|
||||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||||
|
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr;
|
||||||
|
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr;
|
||||||
|
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr;
|
||||||
|
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr;
|
||||||
|
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr;
|
||||||
} m_sProc;
|
} m_sProc;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool EXT_read_format_bgra = false;
|
bool EXT_read_format_bgra = false;
|
||||||
bool EXT_image_dma_buf_import = false;
|
bool EXT_image_dma_buf_import = false;
|
||||||
bool EXT_image_dma_buf_import_modifiers = false;
|
bool EXT_image_dma_buf_import_modifiers = false;
|
||||||
|
bool KHR_display_reference = false;
|
||||||
|
bool IMG_context_priority = false;
|
||||||
|
bool EXT_create_context_robustness = false;
|
||||||
} m_sExts;
|
} m_sExts;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -220,7 +235,7 @@ class CHyprOpenGLImpl {
|
||||||
std::vector<SDRMFormat> drmFormats;
|
std::vector<SDRMFormat> drmFormats;
|
||||||
bool m_bHasModifiers = false;
|
bool m_bHasModifiers = false;
|
||||||
|
|
||||||
int m_iDRMFD;
|
int m_iDRMFD = -1;
|
||||||
std::string m_szExtensions;
|
std::string m_szExtensions;
|
||||||
|
|
||||||
bool m_bFakeFrame = false;
|
bool m_bFakeFrame = false;
|
||||||
|
@ -238,6 +253,7 @@ class CHyprOpenGLImpl {
|
||||||
void createBGTextureForMonitor(CMonitor*);
|
void createBGTextureForMonitor(CMonitor*);
|
||||||
void initShaders();
|
void initShaders();
|
||||||
void initDRMFormats();
|
void initDRMFormats();
|
||||||
|
void initEGL(bool gbm);
|
||||||
|
|
||||||
//
|
//
|
||||||
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||||
|
|
|
@ -15,54 +15,10 @@ CRenderbuffer::~CRenderbuffer() {
|
||||||
m_sFramebuffer.release();
|
m_sFramebuffer.release();
|
||||||
glDeleteRenderbuffers(1, &m_iRBO);
|
glDeleteRenderbuffers(1, &m_iRBO);
|
||||||
|
|
||||||
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage);
|
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_iImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer), m_uDrmFormat(format) {
|
CRenderbuffer::CRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) {
|
||||||
|
|
||||||
// EVIL, but we can't include a hidden header because nixos is fucking special
|
|
||||||
static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*);
|
|
||||||
static bool symbolFound = false;
|
|
||||||
if (!symbolFound) {
|
|
||||||
PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast<EGLImageKHR (*)(wlr_egl*, wlr_dmabuf_attributes*, bool*)>(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf"));
|
|
||||||
|
|
||||||
symbolFound = true;
|
|
||||||
|
|
||||||
RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!");
|
|
||||||
|
|
||||||
Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF);
|
|
||||||
}
|
|
||||||
// end evil hack
|
|
||||||
|
|
||||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
|
||||||
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf))
|
|
||||||
throw std::runtime_error("wlr_buffer_get_dmabuf failed");
|
|
||||||
|
|
||||||
bool externalOnly;
|
|
||||||
m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly);
|
|
||||||
if (m_iImage == EGL_NO_IMAGE_KHR)
|
|
||||||
throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed");
|
|
||||||
|
|
||||||
glGenRenderbuffers(1, &m_iRBO);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
|
||||||
g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
|
|
||||||
glGenFramebuffers(1, &m_sFramebuffer.m_iFb);
|
|
||||||
m_sFramebuffer.m_vSize = {buffer->width, buffer->height};
|
|
||||||
m_sFramebuffer.bind();
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO);
|
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
||||||
throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
hyprListener_destroyBuffer.initCallback(
|
|
||||||
&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
CRenderbuffer::CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) {
|
|
||||||
auto dma = buffer->dmabuf();
|
auto dma = buffer->dmabuf();
|
||||||
|
|
||||||
m_iImage = g_pHyprOpenGL->createEGLImage(dma);
|
m_iImage = g_pHyprOpenGL->createEGLImage(dma);
|
||||||
|
@ -83,6 +39,8 @@ CRenderbuffer::CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format) : m_pHLBuffe
|
||||||
throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
|
throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
listeners.destroyBuffer = buffer->events.destroy.registerListener([this](std::any d) { g_pHyprRenderer->onRenderbufferDestroy(this); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderbuffer::bind() {
|
void CRenderbuffer::bind() {
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
|
||||||
class CMonitor;
|
class CMonitor;
|
||||||
class IWLBuffer;
|
|
||||||
|
|
||||||
class CRenderbuffer {
|
class CRenderbuffer {
|
||||||
public:
|
public:
|
||||||
CRenderbuffer(wlr_buffer* buffer, uint32_t format);
|
CRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||||
CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format);
|
|
||||||
~CRenderbuffer();
|
~CRenderbuffer();
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
|
@ -17,14 +16,15 @@ class CRenderbuffer {
|
||||||
CFramebuffer* getFB();
|
CFramebuffer* getFB();
|
||||||
uint32_t getFormat();
|
uint32_t getFormat();
|
||||||
|
|
||||||
wlr_buffer* m_pWlrBuffer = nullptr;
|
WP<Aquamarine::IBuffer> m_pHLBuffer;
|
||||||
WP<IWLBuffer> m_pHLBuffer = {};
|
|
||||||
|
|
||||||
DYNLISTENER(destroyBuffer);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EGLImageKHR m_iImage = 0;
|
EGLImageKHR m_iImage = 0;
|
||||||
GLuint m_iRBO = 0;
|
GLuint m_iRBO = 0;
|
||||||
CFramebuffer m_sFramebuffer;
|
CFramebuffer m_sFramebuffer;
|
||||||
uint32_t m_uDrmFormat = 0;
|
uint32_t m_uDrmFormat = 0;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CHyprSignalListener destroyBuffer;
|
||||||
|
} listeners;
|
||||||
};
|
};
|
|
@ -25,22 +25,23 @@ static int cursorTicker(void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprRenderer::CHyprRenderer() {
|
CHyprRenderer::CHyprRenderer() {
|
||||||
if (g_pCompositor->m_sWLRSession) {
|
if (g_pCompositor->m_pAqBackend->hasSession()) {
|
||||||
wlr_device* dev;
|
// wlr_device* dev;
|
||||||
wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) {
|
// FIXME:
|
||||||
const auto DRMV = drmGetVersion(dev->fd);
|
// wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) {
|
||||||
|
// const auto DRMV = drmGetVersion(dev->fd);
|
||||||
|
|
||||||
std::string name = std::string{DRMV->name, DRMV->name_len};
|
// std::string name = std::string{DRMV->name, DRMV->name_len};
|
||||||
std::transform(name.begin(), name.end(), name.begin(), tolower);
|
// std::transform(name.begin(), name.end(), name.begin(), tolower);
|
||||||
|
|
||||||
if (name.contains("nvidia"))
|
// if (name.contains("nvidia"))
|
||||||
m_bNvidia = true;
|
// m_bNvidia = true;
|
||||||
|
|
||||||
Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
// Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
||||||
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
// std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
||||||
|
|
||||||
drmFreeVersion(DRMV);
|
// drmFreeVersion(DRMV);
|
||||||
}
|
// }
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks");
|
Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks");
|
||||||
|
|
||||||
|
@ -1246,7 +1247,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
// check the damage
|
// check the damage
|
||||||
bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged();
|
bool hasChanged = /*pMonitor->output->needs_frame ||*/ pMonitor->damage.hasChanged();
|
||||||
|
|
||||||
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0)
|
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -1292,7 +1293,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
CRegion damage, finalDamage;
|
CRegion damage, finalDamage;
|
||||||
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
|
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
|
||||||
Debug::log(ERR, "renderer: couldn't beginRender()!");
|
Debug::log(ERR, "renderer: couldn't beginRender()!");
|
||||||
pMonitor->state.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1395,7 +1395,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
if (!pMonitor->mirrors.empty()) {
|
if (!pMonitor->mirrors.empty()) {
|
||||||
CRegion frameDamage{};
|
CRegion frameDamage{};
|
||||||
|
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform);
|
const auto TRANSFORM = wlr_output_transform_invert(pMonitor->transform);
|
||||||
wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
|
wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
|
||||||
|
|
||||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
|
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
|
||||||
|
@ -1411,7 +1411,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("render", RENDER_POST);
|
EMIT_HOOK_EVENT("render", RENDER_POST);
|
||||||
|
|
||||||
pMonitor->state.wlr()->tearing_page_flip = shouldTear;
|
pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
|
||||||
|
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
|
||||||
|
|
||||||
if (!pMonitor->state.commit()) {
|
if (!pMonitor->state.commit()) {
|
||||||
pMonitor->damage.damageEntire();
|
pMonitor->damage.damageEntire();
|
||||||
|
@ -1866,7 +1867,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't touch VR headsets
|
// don't touch VR headsets
|
||||||
if (pMonitor->output->non_desktop)
|
if (pMonitor->output->nonDesktop)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!pMonitor->m_bEnabled) {
|
if (!pMonitor->m_bEnabled) {
|
||||||
|
@ -1907,38 +1908,36 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
pMonitor->scale = DEFAULTSCALE;
|
pMonitor->scale = DEFAULTSCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
|
|
||||||
pMonitor->setScale = pMonitor->scale;
|
pMonitor->setScale = pMonitor->scale;
|
||||||
|
|
||||||
wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform);
|
|
||||||
pMonitor->transform = RULE->transform;
|
pMonitor->transform = RULE->transform;
|
||||||
|
pMonitor->output->state->setFormat(DRM_FORMAT_XBGR8888);
|
||||||
|
|
||||||
const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000;
|
const auto WLRREFRESHRATE = pMonitor->output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0;
|
||||||
|
|
||||||
// loop over modes and choose an appropriate one.
|
// loop over modes and choose an appropriate one.
|
||||||
if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
|
if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
|
||||||
if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
|
if (!pMonitor->output->modes.empty() && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
|
||||||
wlr_output_mode* mode;
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
for (auto& mode : pMonitor->output->modes) {
|
||||||
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
|
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
|
||||||
if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) &&
|
if (DELTALESSTHAN(mode->pixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(mode->pixelSize.y, RULE->resolution.y, 1) &&
|
||||||
DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) {
|
DELTALESSTHAN(mode->refreshRate / 1000.f, RULE->refreshRate, 1)) {
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
pMonitor->output->state->setMode(mode);
|
||||||
|
|
||||||
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
if (!pMonitor->state.test()) {
|
||||||
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y,
|
||||||
|
mode->refreshRate / 1000.f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
|
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
|
(float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate);
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
pMonitor->refreshRate = mode->refresh / 1000.f;
|
pMonitor->refreshRate = mode->refreshRate / 1000.f;
|
||||||
pMonitor->vecSize = Vector2D(mode->width, mode->height);
|
pMonitor->vecSize = mode->pixelSize;
|
||||||
pMonitor->currentMode = mode;
|
pMonitor->currentMode = mode;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1946,14 +1945,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
|
pMonitor->output->state->setCustomMode(makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE}));
|
||||||
pMonitor->vecSize = RULE->resolution;
|
pMonitor->vecSize = RULE->resolution;
|
||||||
pMonitor->refreshRate = RULE->refreshRate;
|
pMonitor->refreshRate = RULE->refreshRate;
|
||||||
|
|
||||||
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
if (!pMonitor->state.test()) {
|
||||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||||
|
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = pMonitor->output->preferredMode();
|
||||||
|
|
||||||
if (!PREFERREDMODE) {
|
if (!PREFERREDMODE) {
|
||||||
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution,
|
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution,
|
||||||
|
@ -1962,13 +1961,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
pMonitor->output->state->setMode(PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
(float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
|
||||||
|
|
||||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
|
||||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
pMonitor->vecSize = PREFERREDMODE->pixelSize;
|
||||||
pMonitor->currentMode = PREFERREDMODE;
|
pMonitor->currentMode = PREFERREDMODE;
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
|
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
|
||||||
|
@ -1979,30 +1978,30 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
|
|
||||||
if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
|
if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
|
||||||
if (!wlr_output_is_drm(pMonitor->output)) {
|
if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) {
|
||||||
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
|
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
|
||||||
fail = true;
|
fail = true;
|
||||||
} else {
|
} else {
|
||||||
auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
|
// FIXME:
|
||||||
if (mode) {
|
// auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
// if (mode) {
|
||||||
pMonitor->customDrmMode = RULE->drmMode;
|
// wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
||||||
} else {
|
// pMonitor->customDrmMode = RULE->drmMode;
|
||||||
Debug::log(ERR, "wlr_drm_connector_add_mode failed");
|
// } else {
|
||||||
fail = true;
|
// Debug::log(ERR, "wlr_drm_connector_add_mode failed");
|
||||||
}
|
// fail = true;
|
||||||
}
|
// }
|
||||||
} else {
|
|
||||||
wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
|
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
pMonitor->output->state->setCustomMode(makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE}));
|
||||||
|
|
||||||
pMonitor->vecSize = RULE->resolution;
|
pMonitor->vecSize = RULE->resolution;
|
||||||
pMonitor->refreshRate = RULE->refreshRate;
|
pMonitor->refreshRate = RULE->refreshRate;
|
||||||
|
|
||||||
if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
if (fail || !pMonitor->state.test()) {
|
||||||
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
||||||
|
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = pMonitor->output->preferredMode();
|
||||||
|
|
||||||
if (!PREFERREDMODE) {
|
if (!PREFERREDMODE) {
|
||||||
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution,
|
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution,
|
||||||
|
@ -2011,21 +2010,19 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
pMonitor->output->state->setMode(PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
(float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
|
||||||
|
|
||||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
|
||||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
pMonitor->vecSize = PREFERREDMODE->pixelSize;
|
||||||
pMonitor->customDrmMode = {};
|
pMonitor->customDrmMode = {};
|
||||||
} else {
|
} else
|
||||||
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
|
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if (RULE->resolution != Vector2D()) {
|
} else if (RULE->resolution != Vector2D()) {
|
||||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
if (!pMonitor->output->modes.empty()) {
|
||||||
wlr_output_mode* mode;
|
|
||||||
float currentWidth = 0;
|
float currentWidth = 0;
|
||||||
float currentHeight = 0;
|
float currentHeight = 0;
|
||||||
float currentRefresh = 0;
|
float currentRefresh = 0;
|
||||||
|
@ -2033,26 +2030,27 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
|
|
||||||
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
|
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
|
||||||
if (RULE->resolution == Vector2D(-1, -1)) {
|
if (RULE->resolution == Vector2D(-1, -1)) {
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
for (auto& mode : pMonitor->output->modes) {
|
||||||
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
|
if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) ||
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
mode->refreshRate > (currentRefresh + 3000.f)) {
|
||||||
if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
pMonitor->output->state->setMode(mode);
|
||||||
currentWidth = mode->width;
|
if (pMonitor->state.test()) {
|
||||||
currentHeight = mode->height;
|
currentWidth = mode->pixelSize.x;
|
||||||
currentRefresh = mode->refresh;
|
currentHeight = mode->pixelSize.y;
|
||||||
|
currentRefresh = mode->refreshRate;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
for (auto& mode : pMonitor->output->modes) {
|
||||||
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) ||
|
if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) ||
|
||||||
(mode->width > currentWidth && mode->height > currentHeight)) {
|
(mode->pixelSize.x > currentWidth && mode->pixelSize.y > currentHeight)) {
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
pMonitor->output->state->setMode(mode);
|
||||||
if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
if (pMonitor->state.test()) {
|
||||||
currentWidth = mode->width;
|
currentWidth = mode->pixelSize.x;
|
||||||
currentHeight = mode->height;
|
currentHeight = mode->pixelSize.y;
|
||||||
currentRefresh = mode->refresh;
|
currentRefresh = mode->refreshRate;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2060,10 +2058,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
if (pMonitor->output->state->state().mode)
|
||||||
Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
|
(float)RULE->refreshRate, pMonitor->output->state->state().mode->pixelSize.x, pMonitor->output->state->state().mode->pixelSize.y,
|
||||||
|
pMonitor->output->state->state().mode->refreshRate / 1000.f);
|
||||||
|
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = pMonitor->output->preferredMode();
|
||||||
|
|
||||||
if (!PREFERREDMODE) {
|
if (!PREFERREDMODE) {
|
||||||
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate);
|
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate);
|
||||||
|
@ -2071,13 +2071,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
pMonitor->output->state->setMode(PREFERREDMODE);
|
||||||
|
|
||||||
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
|
(float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
|
||||||
|
|
||||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
|
||||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
pMonitor->vecSize = PREFERREDMODE->pixelSize;
|
||||||
pMonitor->currentMode = PREFERREDMODE;
|
pMonitor->currentMode = PREFERREDMODE;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -2088,27 +2088,26 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
const auto PREFERREDMODE = pMonitor->output->preferredMode();
|
||||||
|
|
||||||
if (!PREFERREDMODE) {
|
if (!PREFERREDMODE) {
|
||||||
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name);
|
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name);
|
||||||
|
|
||||||
if (!wl_list_empty(&pMonitor->output->modes)) {
|
if (!pMonitor->output->modes.empty()) {
|
||||||
wlr_output_mode* mode;
|
for (auto& mode : pMonitor->output->modes) {
|
||||||
|
pMonitor->output->state->setMode(mode);
|
||||||
|
|
||||||
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
if (!pMonitor->state.test()) {
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
|
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y,
|
||||||
|
mode->refreshRate / 1000.f);
|
||||||
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
|
||||||
Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
|
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
|
||||||
(float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
|
(float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate);
|
||||||
|
|
||||||
pMonitor->refreshRate = mode->refresh / 1000.f;
|
pMonitor->refreshRate = mode->refreshRate / 1000.f;
|
||||||
pMonitor->vecSize = Vector2D(mode->width, mode->height);
|
pMonitor->vecSize = mode->pixelSize;
|
||||||
pMonitor->currentMode = mode;
|
pMonitor->currentMode = mode;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -2116,17 +2115,17 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Preferred is valid
|
// Preferred is valid
|
||||||
wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
|
pMonitor->output->state->setMode(PREFERREDMODE);
|
||||||
|
|
||||||
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
pMonitor->vecSize = PREFERREDMODE->pixelSize;
|
||||||
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
|
||||||
pMonitor->currentMode = PREFERREDMODE;
|
pMonitor->currentMode = PREFERREDMODE;
|
||||||
|
|
||||||
Debug::log(LOG, "Setting preferred mode for {}", pMonitor->output->name);
|
Debug::log(LOG, "Setting preferred mode for {}", pMonitor->output->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pMonitor->vrrActive = pMonitor->state.wlr()->adaptive_sync_enabled // disabled here, will be tested in CConfigManager::ensureVRR()
|
pMonitor->vrrActive = pMonitor->output->state->state().adaptiveSync // disabled here, will be tested in CConfigManager::ensureVRR()
|
||||||
|| pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
|
|| pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
|
||||||
|
|
||||||
pMonitor->vecPixelSize = pMonitor->vecSize;
|
pMonitor->vecPixelSize = pMonitor->vecSize;
|
||||||
|
@ -2142,10 +2141,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
double scaleZero = searchScale / 120.0;
|
double scaleZero = searchScale / 120.0;
|
||||||
|
|
||||||
Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero;
|
Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero;
|
||||||
if (logicalZero == logicalZero.round()) {
|
if (logicalZero == logicalZero.round())
|
||||||
pMonitor->scale = scaleZero;
|
pMonitor->scale = scaleZero;
|
||||||
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
|
else {
|
||||||
} else {
|
|
||||||
for (size_t i = 1; i < 90; ++i) {
|
for (size_t i = 1; i < 90; ++i) {
|
||||||
double scaleUp = (searchScale + i) / 120.0;
|
double scaleUp = (searchScale + i) / 120.0;
|
||||||
double scaleDown = (searchScale - i) / 120.0;
|
double scaleDown = (searchScale - i) / 120.0;
|
||||||
|
@ -2182,12 +2180,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
} else
|
} else
|
||||||
pMonitor->scale = searchScale;
|
pMonitor->scale = searchScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for wlroots, that likes flooring, we have to do this.
|
|
||||||
double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale);
|
|
||||||
logicalX += 0.1;
|
|
||||||
|
|
||||||
wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->vecPixelSize.x / logicalX);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2206,9 +2198,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
pMonitor->drmFormat = DRM_FORMAT_INVALID;
|
pMonitor->drmFormat = DRM_FORMAT_INVALID;
|
||||||
|
|
||||||
for (auto& fmt : formats[(int)!RULE->enable10bit]) {
|
for (auto& fmt : formats[(int)!RULE->enable10bit]) {
|
||||||
wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second);
|
pMonitor->output->state->setFormat(fmt.second);
|
||||||
|
|
||||||
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
|
if (!pMonitor->state.test()) {
|
||||||
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
|
Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
|
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
|
||||||
|
@ -2222,17 +2214,18 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
|
|
||||||
pMonitor->enabled10bit = set10bit;
|
pMonitor->enabled10bit = set10bit;
|
||||||
|
|
||||||
|
pMonitor->output->scheduleFrame();
|
||||||
|
|
||||||
if (!pMonitor->state.commit())
|
if (!pMonitor->state.commit())
|
||||||
Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name);
|
Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name);
|
||||||
|
|
||||||
int x, y;
|
Vector2D xfmd = pMonitor->transform % 2 == 1 ? Vector2D{pMonitor->vecPixelSize.y, pMonitor->vecPixelSize.x} : pMonitor->vecPixelSize;
|
||||||
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
pMonitor->vecSize = (xfmd / pMonitor->scale).round();
|
||||||
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).round();
|
pMonitor->vecTransformedSize = xfmd;
|
||||||
pMonitor->vecTransformedSize = Vector2D(x, y);
|
|
||||||
|
|
||||||
if (pMonitor->createdByUser) {
|
if (pMonitor->createdByUser) {
|
||||||
CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||||
transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
|
transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
|
||||||
|
|
||||||
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
|
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
|
||||||
}
|
}
|
||||||
|
@ -2257,9 +2250,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||||
// updato us
|
// updato us
|
||||||
arrangeLayersForMonitor(pMonitor->ID);
|
arrangeLayersForMonitor(pMonitor->ID);
|
||||||
|
|
||||||
// frame skip
|
|
||||||
pMonitor->framesToSkip = 1;
|
|
||||||
|
|
||||||
// reload to fix mirrors
|
// reload to fix mirrors
|
||||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
|
|
||||||
|
@ -2326,7 +2316,7 @@ void CHyprRenderer::ensureCursorRenderingMode() {
|
||||||
Debug::log(LOG, "Hiding the cursor (hl-mandated)");
|
Debug::log(LOG, "Hiding the cursor (hl-mandated)");
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
if (m->output->software_cursor_locks == 0)
|
if (!g_pPointerManager->softwareLockedFor(m))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
||||||
|
@ -2338,7 +2328,7 @@ void CHyprRenderer::ensureCursorRenderingMode() {
|
||||||
Debug::log(LOG, "Showing the cursor (hl-mandated)");
|
Debug::log(LOG, "Showing the cursor (hl-mandated)");
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
if (m->output->software_cursor_locks == 0)
|
if (!g_pPointerManager->softwareLockedFor(m))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
||||||
|
@ -2567,16 +2557,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
|
||||||
pMonitor->solitaryClient = PCANDIDATE;
|
pMonitor->solitaryClient = PCANDIDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) {
|
CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||||
auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; });
|
|
||||||
|
|
||||||
if (it != m_vRenderbuffers.end())
|
|
||||||
return it->get();
|
|
||||||
|
|
||||||
return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt) {
|
|
||||||
auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
|
auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
|
||||||
|
|
||||||
if (it != m_vRenderbuffers.end())
|
if (it != m_vRenderbuffers.end())
|
||||||
|
@ -2586,18 +2567,21 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::makeEGLCurrent() {
|
void CHyprRenderer::makeEGLCurrent() {
|
||||||
if (!g_pCompositor)
|
if (!g_pCompositor || !g_pHyprOpenGL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL))
|
if (eglGetCurrentContext() != g_pHyprOpenGL->m_pEglContext)
|
||||||
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL));
|
eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, g_pHyprOpenGL->m_pEglContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::unsetEGL() {
|
void CHyprRenderer::unsetEGL() {
|
||||||
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
if (!g_pHyprOpenGL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IWLBuffer> buffer, CFramebuffer* fb, bool simple) {
|
bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IHLBuffer> buffer, CFramebuffer* fb, bool simple) {
|
||||||
|
|
||||||
makeEGLCurrent();
|
makeEGLCurrent();
|
||||||
|
|
||||||
|
@ -2618,27 +2602,18 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
|
||||||
int bufferAge = 0;
|
int bufferAge = 0;
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) {
|
m_pCurrentBuffer = pMonitor->output->swapchain->next(&bufferAge);
|
||||||
Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName);
|
if (!m_pCurrentBuffer) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge);
|
|
||||||
if (!m_pCurrentWlrBuffer) {
|
|
||||||
Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName);
|
Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
m_pCurrentHLBuffer = buffer;
|
m_pCurrentBuffer = buffer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (m_pCurrentWlrBuffer)
|
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->drmFormat);
|
||||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
|
|
||||||
else
|
|
||||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat);
|
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName);
|
Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName);
|
||||||
wlr_buffer_unlock(m_pCurrentWlrBuffer);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2676,17 +2651,13 @@ void CHyprRenderer::endRender() {
|
||||||
else
|
else
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
if (m_eRenderMode == RENDER_MODE_NORMAL)
|
||||||
wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer);
|
PMONITOR->output->state->setBuffer(m_pCurrentBuffer);
|
||||||
unsetEGL(); // flush the context
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_buffer_unlock(m_pCurrentWlrBuffer);
|
|
||||||
|
|
||||||
m_pCurrentRenderbuffer->unbind();
|
m_pCurrentRenderbuffer->unbind();
|
||||||
|
|
||||||
m_pCurrentRenderbuffer = nullptr;
|
m_pCurrentRenderbuffer = nullptr;
|
||||||
m_pCurrentWlrBuffer = nullptr;
|
m_pCurrentBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
|
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct SMonitorRule;
|
||||||
class CWorkspace;
|
class CWorkspace;
|
||||||
class CWindow;
|
class CWindow;
|
||||||
class CInputPopup;
|
class CInputPopup;
|
||||||
class IWLBuffer;
|
class IHLBuffer;
|
||||||
|
|
||||||
// TODO: add fuller damage tracking for updating only parts of a window
|
// TODO: add fuller damage tracking for updating only parts of a window
|
||||||
enum DAMAGETRACKINGMODES {
|
enum DAMAGETRACKINGMODES {
|
||||||
|
@ -76,7 +76,7 @@ class CHyprRenderer {
|
||||||
|
|
||||||
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
||||||
// otherwise, it will be the one used.
|
// otherwise, it will be the one used.
|
||||||
bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IWLBuffer> buffer = {}, CFramebuffer* fb = nullptr, bool simple = false);
|
bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IHLBuffer> buffer = {}, CFramebuffer* fb = nullptr, bool simple = false);
|
||||||
void endRender();
|
void endRender();
|
||||||
|
|
||||||
bool m_bBlockSurfaceFeedback = false;
|
bool m_bBlockSurfaceFeedback = false;
|
||||||
|
@ -122,8 +122,7 @@ class CHyprRenderer {
|
||||||
bool m_bCursorHidden = false;
|
bool m_bCursorHidden = false;
|
||||||
bool m_bCursorHasSurface = false;
|
bool m_bCursorHasSurface = false;
|
||||||
CRenderbuffer* m_pCurrentRenderbuffer = nullptr;
|
CRenderbuffer* m_pCurrentRenderbuffer = nullptr;
|
||||||
wlr_buffer* m_pCurrentWlrBuffer = nullptr;
|
SP<Aquamarine::IBuffer> m_pCurrentBuffer;
|
||||||
WP<IWLBuffer> m_pCurrentHLBuffer = {};
|
|
||||||
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
||||||
|
|
||||||
bool m_bNvidia = false;
|
bool m_bNvidia = false;
|
||||||
|
@ -134,8 +133,7 @@ class CHyprRenderer {
|
||||||
bool hiddenOnKeyboard = false;
|
bool hiddenOnKeyboard = false;
|
||||||
} m_sCursorHiddenConditions;
|
} m_sCursorHiddenConditions;
|
||||||
|
|
||||||
CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt);
|
CRenderbuffer* getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt);
|
||||||
CRenderbuffer* getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt);
|
|
||||||
std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers;
|
std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers;
|
||||||
|
|
||||||
friend class CHyprOpenGLImpl;
|
friend class CHyprOpenGLImpl;
|
||||||
|
|
|
@ -17,6 +17,62 @@ CTexture::~CTexture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
||||||
|
createFromShm(drmFormat, pixels, stride, size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTexture::CTexture(wlr_texture* tex) {
|
||||||
|
RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!");
|
||||||
|
wlr_gles2_texture_attribs attrs;
|
||||||
|
wlr_gles2_texture_get_attribs(tex, &attrs);
|
||||||
|
|
||||||
|
m_iTarget = attrs.target;
|
||||||
|
m_iTexID = attrs.tex;
|
||||||
|
m_bNonOwning = true;
|
||||||
|
|
||||||
|
if (m_iTarget == GL_TEXTURE_2D)
|
||||||
|
m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
||||||
|
else
|
||||||
|
m_iType = TEXTURE_EXTERNAL;
|
||||||
|
|
||||||
|
m_vSize = Vector2D((int)tex->width, (int)tex->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||||
|
createFromDma(attrs, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer) {
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto attrs = buffer->dmabuf();
|
||||||
|
|
||||||
|
if (!attrs.success) {
|
||||||
|
// attempt shm
|
||||||
|
auto shm = buffer->shm();
|
||||||
|
|
||||||
|
if (!shm.success) {
|
||||||
|
Debug::log(ERR, "Cannot create a texture: buffer has no dmabuf or shm");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0);
|
||||||
|
|
||||||
|
createFromShm(fmt, pixelData, bufLen, shm.size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto image = g_pHyprOpenGL->createEGLImage(buffer->dmabuf());
|
||||||
|
|
||||||
|
if (!image) {
|
||||||
|
Debug::log(ERR, "Cannot create a texture: failed to create an EGLImage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createFromDma(attrs, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
|
|
||||||
const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
|
const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||||
|
@ -41,24 +97,7 @@ CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const V
|
||||||
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
CTexture::CTexture(wlr_texture* tex) {
|
void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||||
RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!");
|
|
||||||
wlr_gles2_texture_attribs attrs;
|
|
||||||
wlr_gles2_texture_get_attribs(tex, &attrs);
|
|
||||||
|
|
||||||
m_iTarget = attrs.target;
|
|
||||||
m_iTexID = attrs.tex;
|
|
||||||
m_bNonOwning = true;
|
|
||||||
|
|
||||||
if (m_iTarget == GL_TEXTURE_2D)
|
|
||||||
m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
|
||||||
else
|
|
||||||
m_iType = TEXTURE_EXTERNAL;
|
|
||||||
|
|
||||||
m_vSize = Vector2D((int)tex->width, (int)tex->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) {
|
|
||||||
if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) {
|
if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) {
|
||||||
Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
|
Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
|
||||||
return;
|
return;
|
||||||
|
@ -119,7 +158,7 @@ void CTexture::destroyTexture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pEglImage)
|
if (m_pEglImage)
|
||||||
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_pEglImage);
|
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(g_pHyprOpenGL->m_pEglDisplay, m_pEglImage);
|
||||||
m_pEglImage = nullptr;
|
m_pEglImage = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
#include <aquamarine/buffer/Buffer.hpp>
|
||||||
|
|
||||||
class IWLBuffer;
|
class IHLBuffer;
|
||||||
struct SDMABUFAttrs;
|
|
||||||
HYPRUTILS_FORWARD(Math, CRegion);
|
HYPRUTILS_FORWARD(Math, CRegion);
|
||||||
|
|
||||||
enum TEXTURETYPE {
|
enum TEXTURETYPE {
|
||||||
|
@ -25,8 +25,9 @@ class CTexture {
|
||||||
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
||||||
CTexture(wlr_texture*);
|
CTexture(wlr_texture*);
|
||||||
|
|
||||||
|
CTexture(const SP<Aquamarine::IBuffer> buffer);
|
||||||
// this ctor takes ownership of the eglImage.
|
// this ctor takes ownership of the eglImage.
|
||||||
CTexture(const SDMABUFAttrs&, void* image);
|
CTexture(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||||
~CTexture();
|
~CTexture();
|
||||||
|
|
||||||
void destroyTexture();
|
void destroyTexture();
|
||||||
|
@ -39,4 +40,8 @@ class CTexture {
|
||||||
Vector2D m_vSize;
|
Vector2D m_vSize;
|
||||||
void* m_pEglImage = nullptr;
|
void* m_pEglImage = nullptr;
|
||||||
bool m_bNonOwning = false; // wlr
|
bool m_bNonOwning = false; // wlr
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
||||||
|
void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||||
};
|
};
|
Loading…
Reference in a new issue