2022-03-16 21:37:21 +01:00
|
|
|
#include "Compositor.hpp"
|
|
|
|
|
|
|
|
CCompositor::CCompositor() {
|
2022-03-18 23:52:36 +01:00
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_sWLDisplay = wl_display_create();
|
|
|
|
|
|
|
|
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
|
|
|
|
|
|
|
|
if (!m_sWLRBackend) {
|
|
|
|
Debug::log(CRIT, "m_sWLRBackend was NULL!");
|
|
|
|
RIP("m_sWLRBackend NULL!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend);
|
|
|
|
|
|
|
|
if (!m_sWLRRenderer) {
|
|
|
|
Debug::log(CRIT, "m_sWLRRenderer was NULL!");
|
|
|
|
RIP("m_sWLRRenderer NULL!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-03-17 19:03:15 +01:00
|
|
|
wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay);
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer);
|
|
|
|
|
|
|
|
if (!m_sWLRAllocator) {
|
|
|
|
Debug::log(CRIT, "m_sWLRAllocator was NULL!");
|
|
|
|
RIP("m_sWLRAllocator NULL!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, m_sWLRRenderer);
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay);
|
|
|
|
m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay);
|
|
|
|
|
2022-03-19 14:09:11 +01:00
|
|
|
wlr_export_dmabuf_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_screencopy_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_data_control_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_gamma_control_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
|
|
|
|
wlr_viewporter_create(m_sWLDisplay);
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_sWLROutputLayout = wlr_output_layout_create();
|
|
|
|
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRScene = wlr_scene_create();
|
|
|
|
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
m_sWLRCursor = wlr_cursor_create();
|
|
|
|
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
|
|
|
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, 24);
|
|
|
|
wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRSeat = wlr_seat_create(m_sWLDisplay, "seat0");
|
|
|
|
|
2022-03-17 20:22:29 +01:00
|
|
|
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
|
|
|
|
2022-03-18 20:42:49 +01:00
|
|
|
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
|
2022-03-19 13:54:24 +01:00
|
|
|
|
|
|
|
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay);
|
|
|
|
|
|
|
|
wlr_server_decoration_manager_set_default_mode(wlr_server_decoration_manager_create(m_sWLDisplay), WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
|
|
|
wlr_xdg_decoration_manager_v1_create(m_sWLDisplay);
|
|
|
|
|
|
|
|
wlr_xdg_output_manager_v1_create(m_sWLDisplay, m_sWLROutputLayout);
|
|
|
|
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2022-03-17 15:53:45 +01:00
|
|
|
CCompositor::~CCompositor() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-03-18 23:52:36 +01:00
|
|
|
void CCompositor::initAllSignals() {
|
|
|
|
wl_signal_add(&m_sWLRBackend->events.new_output, &Events::listen_newOutput);
|
|
|
|
wl_signal_add(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGSurface);
|
|
|
|
wl_signal_add(&m_sWLRCursor->events.motion, &Events::listen_mouseMove);
|
|
|
|
wl_signal_add(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute);
|
|
|
|
wl_signal_add(&m_sWLRCursor->events.button, &Events::listen_mouseButton);
|
|
|
|
wl_signal_add(&m_sWLRCursor->events.axis, &Events::listen_mouseAxis);
|
|
|
|
wl_signal_add(&m_sWLRCursor->events.frame, &Events::listen_mouseFrame);
|
|
|
|
wl_signal_add(&m_sWLRBackend->events.new_input, &Events::listen_newInput);
|
|
|
|
wl_signal_add(&m_sWLRSeat->events.request_set_cursor, &Events::listen_requestMouse);
|
|
|
|
wl_signal_add(&m_sWLRSeat->events.request_set_selection, &Events::listen_requestSetSel);
|
2022-03-19 13:54:24 +01:00
|
|
|
wl_signal_add(&m_sWLRLayerShell->events.new_surface, &Events::listen_newLayerSurface);
|
|
|
|
wl_signal_add(&m_sWLROutputLayout->events.change, &Events::listen_change);
|
2022-03-19 14:09:11 +01:00
|
|
|
wl_signal_add(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply);
|
|
|
|
wl_signal_add(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest);
|
2022-03-18 23:52:36 +01:00
|
|
|
}
|
2022-03-17 17:08:54 +01:00
|
|
|
|
2022-03-18 23:52:36 +01:00
|
|
|
void CCompositor::startCompositor() {
|
2022-03-17 17:08:54 +01:00
|
|
|
// Init all the managers BEFORE we start with the wayland server so that ALL of the stuff is initialized
|
|
|
|
// properly and we dont get any bad mem reads.
|
|
|
|
//
|
2022-03-19 17:48:18 +01:00
|
|
|
Debug::log(LOG, "Creating the KeybindManager!");
|
|
|
|
g_pKeybindManager = std::make_unique<CKeybindManager>();
|
|
|
|
|
2022-03-18 20:03:39 +01:00
|
|
|
Debug::log(LOG, "Creating the ConfigManager!");
|
2022-03-17 17:08:54 +01:00
|
|
|
g_pConfigManager = std::make_unique<CConfigManager>();
|
|
|
|
|
2022-03-18 20:03:39 +01:00
|
|
|
Debug::log(LOG, "Creating the ThreadManager!");
|
|
|
|
g_pThreadManager = std::make_unique<CThreadManager>();
|
2022-03-17 17:08:54 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the InputManager!");
|
|
|
|
g_pInputManager = std::make_unique<CInputManager>();
|
2022-03-17 20:22:29 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the HyprRenderer!");
|
|
|
|
g_pHyprRenderer = std::make_unique<CHyprRenderer>();
|
2022-03-18 20:03:39 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the XWaylandManager!");
|
|
|
|
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
|
2022-03-19 15:59:53 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the LayoutManager!");
|
|
|
|
g_pLayoutManager = std::make_unique<CLayoutManager>();
|
2022-03-17 17:08:54 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2022-03-18 23:52:36 +01:00
|
|
|
initAllSignals();
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_szWLDisplaySocket = wl_display_add_socket_auto(m_sWLDisplay);
|
|
|
|
|
|
|
|
if (!m_szWLDisplaySocket) {
|
|
|
|
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
|
2022-03-17 19:03:15 +01:00
|
|
|
wlr_backend_destroy(m_sWLRBackend);
|
2022-03-16 21:37:21 +01:00
|
|
|
RIP("m_szWLDisplaySocket NULL!");
|
|
|
|
}
|
|
|
|
|
|
|
|
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
|
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
2022-03-17 15:53:45 +01:00
|
|
|
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
if (!wlr_backend_start(m_sWLRBackend)) {
|
|
|
|
Debug::log(CRIT, "Backend did not start!");
|
2022-03-17 19:03:15 +01:00
|
|
|
wlr_backend_destroy(m_sWLRBackend);
|
|
|
|
wl_display_destroy(m_sWLDisplay);
|
2022-03-16 21:37:21 +01:00
|
|
|
RIP("Backend did not start!");
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_xcursor_manager_set_cursor_image(m_sWLRXCursorMgr, "left_ptr", m_sWLRCursor);
|
|
|
|
|
|
|
|
// This blocks until we are done.
|
|
|
|
Debug::log(LOG, "Hyprland is ready, running the event loop!");
|
|
|
|
wl_display_run(m_sWLDisplay);
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SMonitor* CCompositor::getMonitorFromID(const int& id) {
|
2022-03-18 22:35:51 +01:00
|
|
|
for (auto& m : m_lMonitors) {
|
2022-03-20 11:23:36 +01:00
|
|
|
if (m.ID == (uint64_t)id) {
|
2022-03-17 20:22:29 +01:00
|
|
|
return &m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SMonitor* CCompositor::getMonitorFromCursor() {
|
2022-03-19 20:30:21 +01:00
|
|
|
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
|
2022-03-17 20:22:29 +01:00
|
|
|
const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, COORDS.x, COORDS.y);
|
|
|
|
|
|
|
|
if (!OUTPUT) {
|
2022-03-19 20:30:21 +01:00
|
|
|
Debug::log(WARN, "getMonitorFromCursor: cursor outside monitors??");
|
2022-03-18 22:35:51 +01:00
|
|
|
return &m_lMonitors.front();
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
for (auto& m : m_lMonitors) {
|
2022-03-17 20:22:29 +01:00
|
|
|
if (m.output == OUTPUT)
|
|
|
|
return &m;
|
|
|
|
}
|
|
|
|
|
2022-03-19 20:30:21 +01:00
|
|
|
Debug::log(LOG, "Monitor not in list??");
|
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
return &m_lMonitors.front();
|
|
|
|
}
|
|
|
|
|
2022-03-20 11:22:55 +01:00
|
|
|
SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
|
|
|
|
const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, point.x, point.y);
|
|
|
|
|
|
|
|
if (!OUTPUT) {
|
|
|
|
Debug::log(WARN, "getMonitorFromVector: vector outside monitors??");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return getMonitorFromOutput(OUTPUT);
|
|
|
|
}
|
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
|
2022-03-18 23:16:15 +01:00
|
|
|
if (windowExists(pWindow))
|
|
|
|
m_lWindows.remove(*pWindow);
|
2022-03-18 22:53:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCompositor::windowExists(CWindow* pWindow) {
|
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
if (&w == pWindow)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
2022-03-19 20:30:21 +01:00
|
|
|
const auto PMONITOR = getMonitorFromCursor();
|
2022-03-18 22:53:27 +01:00
|
|
|
for (auto& w : m_lWindows) {
|
2022-03-19 15:59:53 +01:00
|
|
|
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, pos.x, pos.y)) // TODO: workspaces
|
2022-03-18 22:53:27 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-19 17:48:18 +01:00
|
|
|
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
2022-03-19 20:30:21 +01:00
|
|
|
const auto PMONITOR = getMonitorFromCursor();
|
2022-03-20 11:14:24 +01:00
|
|
|
// first loop over floating cuz they're above
|
|
|
|
// TODO: make an actual Z-system
|
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) // TODO: workspaces
|
2022-03-20 11:14:24 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
2022-03-19 20:30:21 +01:00
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, pos.x, pos.y)) // TODO: workspaces
|
2022-03-19 20:30:21 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWindow* CCompositor::windowFromCursor() {
|
|
|
|
const auto PMONITOR = getMonitorFromCursor();
|
2022-03-20 11:14:24 +01:00
|
|
|
|
|
|
|
// first loop over floating cuz they're above
|
|
|
|
// TODO: make an actual Z-system
|
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) // TODO: workspaces
|
2022-03-20 11:14:24 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
2022-03-19 17:48:18 +01:00
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) // TODO: workspaces
|
2022-03-19 17:48:18 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-20 11:14:24 +01:00
|
|
|
CWindow* CCompositor::windowFloatingFromCursor() {
|
|
|
|
const auto PMONITOR = getMonitorFromCursor();
|
|
|
|
for (auto& w : m_lWindows) {
|
|
|
|
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
|
2022-03-20 11:22:55 +01:00
|
|
|
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) // TODO: workspaces
|
2022-03-20 11:14:24 +01:00
|
|
|
return &w;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-19 20:56:19 +01:00
|
|
|
SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
|
|
|
for (auto& m : m_lMonitors) {
|
|
|
|
if (m.output == out) {
|
|
|
|
return &m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-18 22:53:27 +01:00
|
|
|
void CCompositor::focusWindow(CWindow* pWindow) {
|
|
|
|
|
|
|
|
if (!pWindow) {
|
|
|
|
wlr_seat_keyboard_notify_clear_focus(m_sWLRSeat);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
|
|
|
|
|
|
|
|
if (m_sWLRSeat->keyboard_state.focused_surface == PWINDOWSURFACE)
|
|
|
|
return; // Don't focus when already focused on this.
|
|
|
|
|
2022-03-19 10:53:39 +01:00
|
|
|
// Unfocus last window
|
|
|
|
if (m_pLastFocus && windowValidMapped(m_pLastFocus))
|
|
|
|
g_pXWaylandManager->activateSurface(g_pXWaylandManager->getWindowSurface(m_pLastFocus), false);
|
|
|
|
|
2022-03-18 22:53:27 +01:00
|
|
|
const auto KEYBOARD = wlr_seat_get_keyboard(m_sWLRSeat);
|
|
|
|
wlr_seat_keyboard_notify_enter(m_sWLRSeat, PWINDOWSURFACE, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
|
|
|
|
|
|
|
|
g_pXWaylandManager->activateSurface(PWINDOWSURFACE, true);
|
|
|
|
|
|
|
|
m_pLastFocus = pWindow;
|
2022-03-18 23:06:45 +01:00
|
|
|
|
2022-03-19 11:27:19 +01:00
|
|
|
Debug::log(LOG, "Set keyboard %x focus to %x, with name: %s", KEYBOARD, pWindow, pWindow->m_szTitle.c_str());
|
2022-03-18 23:16:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCompositor::windowValidMapped(CWindow* pWindow) {
|
|
|
|
if (!windowExists(pWindow))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (pWindow->m_bIsX11 && !pWindow->m_bMappedX11)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!g_pXWaylandManager->getWindowSurface(pWindow))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2022-03-20 12:11:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SLayerSurface* CCompositor::getLayerForPopup(SLayerPopup* pPopup) {
|
|
|
|
auto CurrentPopup = pPopup;
|
|
|
|
while (CurrentPopup->parentPopup != nullptr) {
|
|
|
|
for (auto& p : g_pCompositor->m_lLayerPopups) {
|
|
|
|
if (p.popup == CurrentPopup->parentPopup) {
|
|
|
|
CurrentPopup = &p;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CurrentPopup->parentSurface;
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|