Hyprland/src/Compositor.cpp

474 lines
15 KiB
C++
Raw Normal View History

2022-03-16 23:37:21 +03:00
#include "Compositor.hpp"
CCompositor::CCompositor() {
2022-03-20 18:51:14 +03:00
unlink("/tmp/hypr/hyprland.log");
unlink("/tmp/hypr/hyprlandd.log");
unlink("/tmp/hypr/.hyprlandrq");
2022-03-19 01:52:36 +03:00
system("mkdir -p /tmp/hypr");
2022-03-16 23:37:21 +03: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 21:03:15 +03:00
wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay);
2022-03-16 23:37:21 +03: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 21:03:15 +03:00
m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay);
m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay);
2022-03-19 16:09:11 +03: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 23:37:21 +03:00
m_sWLROutputLayout = wlr_output_layout_create();
2022-03-17 21:03:15 +03:00
m_sWLRScene = wlr_scene_create();
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
2022-03-16 23:37:21 +03:00
2022-03-17 21:03:15 +03:00
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay);
2022-03-16 23:37:21 +03:00
m_sWLRCursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
2022-03-17 21:03:15 +03:00
m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, 24);
wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1);
2022-03-16 23:37:21 +03:00
2022-03-22 20:29:13 +03:00
m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0");
2022-03-17 21:03:15 +03:00
2022-03-17 22:22:29 +03:00
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
2022-03-18 22:42:49 +03:00
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
2022-03-19 15:54:24 +03: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-22 20:29:13 +03:00
m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay);
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
2022-03-16 23:37:21 +03:00
}
2022-03-17 17:53:45 +03:00
CCompositor::~CCompositor() {
}
2022-03-19 01:52:36 +03: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);
2022-03-22 20:29:13 +03:00
wl_signal_add(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse);
wl_signal_add(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel);
wl_signal_add(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag);
2022-03-19 15:54:24 +03: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 16:09:11 +03:00
wl_signal_add(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply);
wl_signal_add(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest);
2022-03-22 20:29:13 +03:00
wl_signal_add(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate);
wl_signal_add(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate);
2022-03-19 01:52:36 +03:00
}
2022-03-17 19:08:54 +03:00
2022-03-19 01:52:36 +03:00
void CCompositor::startCompositor() {
2022-03-17 19:08:54 +03: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 19:48:18 +03:00
Debug::log(LOG, "Creating the KeybindManager!");
g_pKeybindManager = std::make_unique<CKeybindManager>();
2022-03-18 22:03:39 +03:00
Debug::log(LOG, "Creating the ConfigManager!");
2022-03-17 19:08:54 +03:00
g_pConfigManager = std::make_unique<CConfigManager>();
2022-03-18 22:03:39 +03:00
Debug::log(LOG, "Creating the ThreadManager!");
g_pThreadManager = std::make_unique<CThreadManager>();
2022-03-17 19:08:54 +03:00
Debug::log(LOG, "Creating the InputManager!");
g_pInputManager = std::make_unique<CInputManager>();
2022-03-17 22:22:29 +03:00
Debug::log(LOG, "Creating the HyprRenderer!");
g_pHyprRenderer = std::make_unique<CHyprRenderer>();
2022-03-18 22:03:39 +03:00
Debug::log(LOG, "Creating the XWaylandManager!");
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
Debug::log(LOG, "Creating the LayoutManager!");
g_pLayoutManager = std::make_unique<CLayoutManager>();
2022-03-24 00:01:59 +03:00
Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = std::make_unique<CAnimationManager>();
2022-03-17 19:08:54 +03:00
//
//
2022-03-19 01:52:36 +03:00
initAllSignals();
2022-03-16 23:37:21 +03:00
m_szWLDisplaySocket = wl_display_add_socket_auto(m_sWLDisplay);
if (!m_szWLDisplaySocket) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
2022-03-17 21:03:15 +03:00
wlr_backend_destroy(m_sWLRBackend);
2022-03-16 23:37:21 +03:00
RIP("m_szWLDisplaySocket NULL!");
}
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
signal(SIGPIPE, SIG_IGN);
2022-03-17 17:53:45 +03:00
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket);
2022-03-16 23:37:21 +03:00
if (!wlr_backend_start(m_sWLRBackend)) {
Debug::log(CRIT, "Backend did not start!");
2022-03-17 21:03:15 +03:00
wlr_backend_destroy(m_sWLRBackend);
wl_display_destroy(m_sWLDisplay);
2022-03-16 23:37:21 +03: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 22:22:29 +03:00
}
SMonitor* CCompositor::getMonitorFromID(const int& id) {
2022-03-19 00:35:51 +03:00
for (auto& m : m_lMonitors) {
2022-03-20 13:23:36 +03:00
if (m.ID == (uint64_t)id) {
2022-03-17 22:22:29 +03:00
return &m;
}
}
return nullptr;
}
SMonitor* CCompositor::getMonitorFromCursor() {
2022-03-19 22:30:21 +03:00
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
2022-03-17 22:22:29 +03:00
const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, COORDS.x, COORDS.y);
if (!OUTPUT) {
2022-03-19 22:30:21 +03:00
Debug::log(WARN, "getMonitorFromCursor: cursor outside monitors??");
2022-03-19 00:35:51 +03:00
return &m_lMonitors.front();
2022-03-17 22:22:29 +03:00
}
2022-03-19 00:35:51 +03:00
for (auto& m : m_lMonitors) {
2022-03-17 22:22:29 +03:00
if (m.output == OUTPUT)
return &m;
}
2022-03-19 22:30:21 +03:00
Debug::log(LOG, "Monitor not in list??");
2022-03-19 00:35:51 +03:00
return &m_lMonitors.front();
}
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-19 00:35:51 +03:00
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
2022-03-19 01:16:15 +03:00
if (windowExists(pWindow))
m_lWindows.remove(*pWindow);
2022-03-19 00:53:27 +03: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-20 17:55:47 +03:00
const auto PMONITOR = getMonitorFromVector(pos);
// first loop over floating cuz they're above
// TODO: make an actual Z-system
2022-03-19 00:53:27 +03:00
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsFloating && isWorkspaceVisible(w.m_iWorkspaceID))
return &w;
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && PMONITOR->activeWorkspace == w.m_iWorkspaceID)
2022-03-19 00:53:27 +03:00
return &w;
}
return nullptr;
}
2022-03-20 20:31:58 +03:00
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating)
return &w;
}
return nullptr;
}
2022-03-19 19:48:18 +03:00
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
2022-03-20 17:55:47 +03:00
const auto PMONITOR = getMonitorFromVector(pos);
2022-03-20 13:14:24 +03: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-22 22:53:11 +03:00
if (w.m_bIsFloating && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && isWorkspaceVisible(w.m_iWorkspaceID))
2022-03-20 13:14:24 +03:00
return &w;
}
2022-03-19 22:30:21 +03: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-22 20:29:13 +03:00
if (!w.m_bIsFloating && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace)
2022-03-19 22:30:21 +03:00
return &w;
}
return nullptr;
}
CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
2022-03-20 13:14:24 +03: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};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating && isWorkspaceVisible(w.m_iWorkspaceID))
2022-03-20 13:14:24 +03:00
return &w;
}
2022-03-19 19:48:18 +03: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 17:55:47 +03:00
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace)
2022-03-19 19:48:18 +03:00
return &w;
}
return nullptr;
}
2022-03-20 13:14:24 +03:00
CWindow* CCompositor::windowFloatingFromCursor() {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating && isWorkspaceVisible(w.m_iWorkspaceID))
2022-03-20 13:14:24 +03:00
return &w;
}
return nullptr;
}
2022-03-19 22:56:19 +03:00
SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
for (auto& m : m_lMonitors) {
if (m.output == out) {
return &m;
}
}
return nullptr;
}
2022-03-19 00:53:27 +03:00
void CCompositor::focusWindow(CWindow* pWindow) {
if (!pWindow) {
2022-03-22 20:29:13 +03:00
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
2022-03-19 00:53:27 +03:00
return;
}
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
2022-03-20 16:36:55 +03:00
focusSurface(PWINDOWSURFACE);
2022-03-19 00:53:27 +03:00
2022-03-20 16:36:55 +03:00
Debug::log(LOG, "Set keyboard focus to %x, with name: %s", pWindow, pWindow->m_szTitle.c_str());
}
void CCompositor::focusSurface(wlr_surface* pSurface) {
2022-03-22 20:29:13 +03:00
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface)
2022-03-20 16:36:55 +03:00
return; // Don't focus when already focused on this.
// Unfocus last surface
2022-03-22 23:28:57 +03:00
if (m_pLastFocus && !wlr_surface_is_xwayland_surface(m_pLastFocus))
2022-03-20 16:36:55 +03:00
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
2022-03-19 12:53:39 +03:00
2022-03-22 20:29:13 +03:00
const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat);
wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
2022-03-19 00:53:27 +03:00
2022-03-20 16:36:55 +03:00
m_pLastFocus = pSurface;
2022-03-19 01:06:45 +03:00
2022-03-20 16:36:55 +03:00
g_pXWaylandManager->activateSurface(pSurface, true);
2022-03-19 01:16:15 +03:00
}
bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (!windowExists(pWindow))
return false;
if (pWindow->m_bIsX11 && !pWindow->m_bMappedX11)
return false;
2022-03-22 22:53:11 +03:00
if (!pWindow->m_bIsMapped)
return false;
2022-03-19 01:16:15 +03:00
if (!g_pXWaylandManager->getWindowSurface(pWindow))
return false;
return true;
2022-03-20 14:11:57 +03: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;
}
}
}
2022-03-20 16:00:46 +03:00
2022-03-20 14:11:57 +03:00
return CurrentPopup->parentSurface;
2022-03-20 16:00:46 +03:00
}
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
for (auto& p : m_lXDGPopups) {
if (p.popup == popup)
return p.parentWindow;
}
2022-03-20 16:36:55 +03:00
return nullptr;
}
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
for (auto& l : *layerSurfaces) {
if (!l->layerSurface->mapped)
continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at(l->layerSurface, pos.x - l->geometry.x, pos.y - l->geometry.y, &sCoords->x, &sCoords->y);
if (SURFACEAT)
return SURFACEAT;
}
return nullptr;
}
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
for (auto& w : m_lWindows) {
if (g_pXWaylandManager->getWindowSurface(&w) == pSurface)
return &w;
}
2022-03-20 17:55:47 +03:00
return nullptr;
}
2022-03-21 21:18:33 +03:00
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == ID && w.m_bIsFullscreen)
return &w;
}
return nullptr;
}
2022-03-20 17:55:47 +03:00
bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) {
if (m.activeWorkspace == w)
return true;
}
return false;
}
SWorkspace* CCompositor::getWorkspaceByID(const int& id) {
for (auto& w : m_lWorkspaces) {
if (w.ID == id)
return &w;
}
return nullptr;
}
void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
if (getWindowsOnWorkspace(it->ID) == 0 && !isWorkspaceVisible(it->ID))
it = m_lWorkspaces.erase(it);
}
}
int CCompositor::getWindowsOnWorkspace(const int& id) {
int no = 0;
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id)
no++;
}
return no;
}
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id)
return &w;
}
2022-03-20 16:00:46 +03:00
return nullptr;
}
void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
const auto ISVISIBLE = isWorkspaceVisible(id);
2022-03-21 21:18:33 +03:00
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id) {
// moveXWaylandWindow only moves XWayland windows
// so there is no need to check here
// if the window is XWayland or not.
2022-03-21 21:18:33 +03:00
if (ISVISIBLE && (!PWORKSPACE->hasFullscreenWindow || w.m_bIsFullscreen))
g_pXWaylandManager->moveXWaylandWindow(&w, w.m_vRealPosition);
else
g_pXWaylandManager->moveXWaylandWindow(&w, Vector2D(42069,42069));
}
}
2022-03-22 20:29:13 +03:00
}
bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
2022-03-22 23:59:14 +03:00
return !m_sSeat.exclusiveClient || (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource));
2022-03-16 23:37:21 +03:00
}