From bc937e3e711e53774e2c9fa26d13125427f6378b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 17 Mar 2022 20:22:29 +0100 Subject: [PATCH] Renderer --- CMakeLists.txt | 2 +- src/Compositor.cpp | 32 ++++++++++++++++++++++ src/Compositor.hpp | 9 +++++++ src/ManagerThread.cpp | 2 +- src/Window.cpp | 0 src/Window.hpp | 40 +++++++++++++++++++++++++++ src/defines.hpp | 4 ++- src/events/Events.cpp | 55 ++++++++++++++++++++++++++++++++----- src/events/Events.hpp | 9 +++++++ src/helpers/WLClasses.hpp | 9 ++++++- src/render/Renderer.cpp | 57 +++++++++++++++++++++++++++++++++++++++ src/render/Renderer.hpp | 13 +++++++++ 12 files changed, 222 insertions(+), 10 deletions(-) create mode 100644 src/Window.cpp create mode 100644 src/Window.hpp create mode 100644 src/render/Renderer.cpp create mode 100644 src/render/Renderer.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ce8492be..8dc05823 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ message(STATUS "Configuring Hyprland!") include_directories(.) add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE ) -add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value) +add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers) find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7a535b5d..fbf98eb9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -62,6 +62,8 @@ CCompositor::CCompositor() { wl_signal_add(&m_sWLRSeat->events.request_set_cursor, &Events::listen_requestMouse); wl_signal_add(&m_sWLRSeat->events.request_set_selection, &Events::listen_requestSetSel); + m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend); + // TODO: XWayland } @@ -82,6 +84,9 @@ void CCompositor::startCompositor() { Debug::log(LOG, "Creating the InputManager!"); g_pInputManager = std::make_unique(); + + Debug::log(LOG, "Creating the HyprRenderer!"); + g_pHyprRenderer = std::make_unique(); // // @@ -111,4 +116,31 @@ void CCompositor::startCompositor() { // This blocks until we are done. Debug::log(LOG, "Hyprland is ready, running the event loop!"); wl_display_run(m_sWLDisplay); +} + +SMonitor* CCompositor::getMonitorFromID(const int& id) { + for (auto& m : m_vMonitors) { + if (m.ID == id) { + return &m; + } + } + + return nullptr; +} + +SMonitor* CCompositor::getMonitorFromCursor() { + const auto COORDS = g_pInputManager->getMouseCoordsInternal(); + const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, COORDS.x, COORDS.y); + + if (!OUTPUT) { + Debug::log(WARN, "getMonitorFromCursor: cursour outside monitors??"); + return &m_vMonitors[0]; + } + + for (auto& m : m_vMonitors) { + if (m.output == OUTPUT) + return &m; + } + + return &m_vMonitors[0]; } \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index e43f87fe..068ae1c8 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -10,6 +10,8 @@ #include "ManagerThread.hpp" #include "input/InputManager.hpp" #include "helpers/Monitor.hpp" +#include "Window.hpp" +#include "render/Renderer.hpp" class CCompositor { public: @@ -42,8 +44,15 @@ public: const char* m_szWLDisplaySocket; std::deque m_vMonitors; + std::deque m_vWindows; void startCompositor(); + + + // ------------------------------------------------- // + + SMonitor* getMonitorFromID(const int&); + SMonitor* getMonitorFromCursor(); }; diff --git a/src/ManagerThread.cpp b/src/ManagerThread.cpp index 6dfa46de..15c41354 100644 --- a/src/ManagerThread.cpp +++ b/src/ManagerThread.cpp @@ -1,7 +1,7 @@ #include "ManagerThread.hpp" CManagerThread::CManagerThread() { - m_tMainThread = new std::thread([=]() { + m_tMainThread = new std::thread([&]() { // Call the handle method. this->handle(); }); diff --git a/src/Window.cpp b/src/Window.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Window.hpp b/src/Window.hpp new file mode 100644 index 00000000..b6a70af4 --- /dev/null +++ b/src/Window.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "defines.hpp" +#include "events/Events.hpp" + + +class CWindow { +public: + + DYNLISTENER(commitWindow); + DYNLISTENER(mapWindow); + DYNLISTENER(unmapWindow); + DYNLISTENER(destroyWindow); + DYNLISTENER(setTitleWindow); + DYNLISTENER(fullscreenWindow); + + union { + wlr_xdg_surface* xdg; + wlr_xwayland_surface* xwayland; + } m_uSurface; + + // TODO: XWayland + + // this is the position and size of the "bounding box" + Vector2D m_vPosition = Vector2D(0,0); + Vector2D m_vSize = Vector2D(0,0); + + // this is the position and size of the goal placement + Vector2D m_vEffectivePosition = Vector2D(0,0); + Vector2D m_vEffectiveSize = Vector2D(0,0); + + // this is the real position and size used to draw the thing + Vector2D m_vRealPosition = Vector2D(0,0); + Vector2D m_vRealSize = Vector2D(0,0); + + uint64_t m_iTags = 0; + bool m_bIsFloating = false; + bool m_bIsFullscreen = false; + uint64_t m_iMonitorID = -1; +}; \ No newline at end of file diff --git a/src/defines.hpp b/src/defines.hpp index 6b92292a..94807ac1 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -9,4 +9,6 @@ #define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } #define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name }; -#define DYNLISTENER(name) wl_listener listen_##name = { .notify = Events::listener_##name }; \ No newline at end of file +#define DYNLISTENER(name) wl_listener listen_##name = { .notify = Events::listener_##name }; + +#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2)) \ No newline at end of file diff --git a/src/events/Events.cpp b/src/events/Events.cpp index 072e8519..f223b9d4 100644 --- a/src/events/Events.cpp +++ b/src/events/Events.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../helpers/WLClasses.hpp" #include "../input/InputManager.hpp" +#include "../render/Renderer.hpp" void Events::listener_activate(wl_listener* listener, void* data) { // TODO @@ -60,8 +61,8 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { g_pCompositor->m_vMonitors.push_back(newMonitor); // - wl_signal_add(&OUTPUT->events.frame, &g_pCompositor->m_vMonitors[g_pCompositor->m_vMonitors.size() - 1].listen_monitorFrame); - wl_signal_add(&OUTPUT->events.destroy, &g_pCompositor->m_vMonitors[g_pCompositor->m_vMonitors.size() - 1].listen_monitorDestroy); + wl_signal_add(&OUTPUT->events.frame, &g_pCompositor->m_vMonitors.back().listen_monitorFrame); + wl_signal_add(&OUTPUT->events.destroy, &g_pCompositor->m_vMonitors.back().listen_monitorDestroy); wlr_output_enable(OUTPUT, 1); if (!wlr_output_commit(OUTPUT)) { @@ -80,7 +81,6 @@ void Events::listener_monitorFrame(wl_listener* listener, void* data) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); const float bgcol[4] = {0.1f,0.1f,0.1f,1.f}; - const float rectcol[4] = {0.69f,0.1f,0.69f,1.f}; if (!wlr_output_attach_render(PMONITOR->output, nullptr)) return; @@ -88,7 +88,7 @@ void Events::listener_monitorFrame(wl_listener* listener, void* data) { wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecSize.x, PMONITOR->vecSize.y); wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, bgcol); - // TODO: render clients + g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now); wlr_output_render_software_cursors(PMONITOR->output, NULL); @@ -118,7 +118,6 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) { const auto PMONITOR = (SMonitor*)WLRLAYERSURFACE->output->data; PMONITOR->m_dLayerSurfaces.push_back(SLayerSurface()); SLayerSurface* layerSurface = &PMONITOR->m_dLayerSurfaces[PMONITOR->m_dLayerSurfaces.size() - 1]; - wlr_layer_surface_v1_state oldState; if (!WLRLAYERSURFACE->output) { WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors[0].output; // TODO: current mon @@ -151,6 +150,35 @@ void Events::listener_commitLayerSurface(wl_listener* listener, void* data) { } +void Events::listener_mapWindow(wl_listener* listener, void* data) { + CWindow* PWINDOW = wl_container_of(listener, PWINDOW, listen_mapWindow); + + const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); + PWINDOW->m_iMonitorID = PMONITOR->ID; + + // test + wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, PMONITOR->vecSize.x, PMONITOR->vecSize.y); +} + +void Events::listener_unmapWindow(wl_listener* listener, void* data) { + +} + +void Events::listener_commitWindow(wl_listener* listener, void* data) { + +} + +void Events::listener_destroyWindow(wl_listener* listener, void* data) { + +} + +void Events::listener_setTitleWindow(wl_listener* listener, void* data) { + +} + +void Events::listener_fullscreenWindow(wl_listener* listener, void* data) { + +} void Events::listener_mouseAxis(wl_listener* listener, void* data) { // TODO: @@ -200,7 +228,22 @@ void Events::listener_newKeyboard(wl_listener* listener, void* data) { } void Events::listener_newXDGSurface(wl_listener* listener, void* data) { - + // A window got opened + const auto XDGSURFACE = (wlr_xdg_surface*)data; + + if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) + return; // TODO: handle? + + g_pCompositor->m_vWindows.push_back(CWindow()); + const auto PNEWWINDOW = &g_pCompositor->m_vWindows.back(); + PNEWWINDOW->m_uSurface.xdg = XDGSURFACE; + + wl_signal_add(&XDGSURFACE->surface->events.commit, &PNEWWINDOW->listen_commitWindow); + wl_signal_add(&XDGSURFACE->events.map, &PNEWWINDOW->listen_mapWindow); + wl_signal_add(&XDGSURFACE->events.unmap, &PNEWWINDOW->listen_unmapWindow); + wl_signal_add(&XDGSURFACE->events.destroy, &PNEWWINDOW->listen_destroyWindow); + wl_signal_add(&XDGSURFACE->toplevel->events.set_title, &PNEWWINDOW->listen_setTitleWindow); + wl_signal_add(&XDGSURFACE->toplevel->events.request_fullscreen, &PNEWWINDOW->listen_fullscreenWindow); } void Events::listener_outputMgrApply(wl_listener* listener, void* data) { diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 2049db09..b4a7d052 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -5,13 +5,22 @@ namespace Events { LISTENER(activate); LISTENER(change); LISTENER(newOutput); + LISTENER(newLayerSurface); LISTENER(destroyLayerSurface); LISTENER(mapLayerSurface); LISTENER(unmapLayerSurface); LISTENER(commitLayerSurface); + LISTENER(newXDGSurface); + LISTENER(commitWindow); + LISTENER(mapWindow); + LISTENER(unmapWindow); + LISTENER(destroyWindow); + LISTENER(setTitleWindow); + LISTENER(fullscreenWindow); + LISTENER(mouseMove); LISTENER(mouseMoveAbsolute); LISTENER(mouseButton); diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 37f44e5c..09878f54 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -15,4 +15,11 @@ struct SLayerSurface { wlr_box geometry; zwlr_layer_shell_v1_layer layer; -}; \ No newline at end of file +}; + +struct SRenderData { + wlr_output* output; + timespec* when; + int x; + int y; +}; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp new file mode 100644 index 00000000..623b9c07 --- /dev/null +++ b/src/render/Renderer.cpp @@ -0,0 +1,57 @@ +#include "Renderer.hpp" +#include "../Compositor.hpp" + +void scaleBox(wlr_box* box, float scale) { + box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale); + box->height = std::round((box->y + box->height) * scale) - std::round(box->y * scale); + box->x = std::round(box->x * scale); + box->y = std::round(box->y * scale); +} + +void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { + const auto TEXTURE = wlr_surface_get_texture(surface); + const auto RDATA = (SRenderData*)data; + + if (!TEXTURE) + return; + + double outputX = 0, outputY = 0; + wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY); + + wlr_box windowBox = {outputX + RDATA->x + x, outputY + RDATA->y + y, surface->current.width, surface->current.height}; + scaleBox(&windowBox, RDATA->output->scale); + + const auto TRANSFORM = wlr_output_transform_invert(surface->current.transform); + float matrix[9]; + wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, RDATA->output->transform_matrix); + + wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, TEXTURE, matrix, 1); // TODO: fadein/out + + wlr_surface_send_frame_done(surface, RDATA->when); + + wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output); +} + +void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(ID); + + if (!PMONITOR) + return; + + for (auto& w : g_pCompositor->m_vWindows) { + + const wlr_box geom = { w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y }; + + if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geom)) + continue; + + // render the bad boy + + wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &w.m_vPosition.x, &w.m_vPosition.y); + + SRenderData renderdata = {PMONITOR->output, time, w.m_vSize.x, w.m_vSize.y}; + + wlr_surface_for_each_surface(w.m_uSurface.xdg->surface, renderSurface, &renderdata); + wlr_xdg_surface_for_each_popup_surface(w.m_uSurface.xdg, renderSurface, &renderdata); + } +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp new file mode 100644 index 00000000..ae7e5476 --- /dev/null +++ b/src/render/Renderer.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "../defines.hpp" + +class CHyprRenderer { +public: + + void renderAllClientsForMonitor(const int&, timespec*); + +private: +}; + +inline std::unique_ptr g_pHyprRenderer;