diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fbf98eb9..8d81e1c9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -76,17 +76,20 @@ void CCompositor::startCompositor() { // 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. // - Debug::log(LOG, "Creating the config manager!"); + Debug::log(LOG, "Creating the ConfigManager!"); g_pConfigManager = std::make_unique(); - Debug::log(LOG, "Creating the ManagerThread!"); - g_pManagerThread = std::make_unique(); + Debug::log(LOG, "Creating the ThreadManager!"); + g_pThreadManager = std::make_unique(); Debug::log(LOG, "Creating the InputManager!"); g_pInputManager = std::make_unique(); Debug::log(LOG, "Creating the HyprRenderer!"); g_pHyprRenderer = std::make_unique(); + + Debug::log(LOG, "Creating the XWaylandManager!"); + g_pXWaylandManager = std::make_unique(); // // diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 068ae1c8..c46aae11 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -7,8 +7,9 @@ #include "debug/Log.hpp" #include "events/Events.hpp" #include "config/ConfigManager.hpp" -#include "ManagerThread.hpp" -#include "input/InputManager.hpp" +#include "managers/ThreadManager.hpp" +#include "managers/XWaylandManager.hpp" +#include "managers/InputManager.hpp" #include "helpers/Monitor.hpp" #include "Window.hpp" #include "render/Renderer.hpp" diff --git a/src/ManagerThread.hpp b/src/ManagerThread.hpp deleted file mode 100644 index 80856fe4..00000000 --- a/src/ManagerThread.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "defines.hpp" -#include -#include "Compositor.hpp" - -class CManagerThread { -public: - CManagerThread(); - ~CManagerThread(); - -private: - - void handle(); - - std::thread* m_tMainThread; -}; - -inline std::unique_ptr g_pManagerThread; \ No newline at end of file diff --git a/src/Window.hpp b/src/Window.hpp index b6a70af4..d262efb4 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -37,4 +37,12 @@ public: bool m_bIsFloating = false; bool m_bIsFullscreen = false; uint64_t m_iMonitorID = -1; + + // XWayland stuff + bool m_bIsX11 = false; + uint64_t m_iX11Type = 0; + DYNLISTENER(activateX11); + DYNLISTENER(configureX11); + // + }; \ No newline at end of file diff --git a/src/events/Events.cpp b/src/events/Events.cpp index 34a3fbb1..f320bd4e 100644 --- a/src/events/Events.cpp +++ b/src/events/Events.cpp @@ -2,7 +2,7 @@ #include "../Compositor.hpp" #include "../helpers/WLClasses.hpp" -#include "../input/InputManager.hpp" +#include "../managers/InputManager.hpp" #include "../render/Renderer.hpp" void Events::listener_activate(wl_listener* listener, void* data) { @@ -157,7 +157,7 @@ void Events::listener_mapWindow(wl_listener* listener, void* data) { PWINDOW->m_iMonitorID = PMONITOR->ID; // test - wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, PMONITOR->vecSize.x, PMONITOR->vecSize.y); + g_pXWaylandManager->setWindowSize(PWINDOW, PMONITOR->vecSize); Debug::log(LOG, "Map request dispatched."); } @@ -198,6 +198,68 @@ void Events::listener_keyboardDestroy(wl_listener* listener, void* data) { } +void Events::listener_activateX11(wl_listener* listener, void* data) { + CWindow* PWINDOW = wl_container_of(listener, PWINDOW, listen_mapWindow); + + if (PWINDOW->m_iX11Type == 1 /* Managed */) { + wlr_xwayland_surface_activate(PWINDOW->m_uSurface.xwayland, 1); + } +} + +void Events::listener_configureX11(wl_listener* listener, void* data) { + CWindow* PWINDOW = wl_container_of(listener, PWINDOW, listen_mapWindow); + + const auto E = (wlr_xwayland_surface_configure_event*)data; + + // TODO: ignore if tiled? + wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); +} + +void Events::listener_readyXWayland(wl_listener* listener, void* data) { + const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL); + const auto ERR = xcb_connection_has_error(XCBCONNECTION); + if (ERR) { + Debug::log(LogLevel::ERR, "xcb_connection_has_error failed with %i", ERR); + return; + } + + // TODO: atoms + + wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sWLRSeat); + + const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1); + if (XCURSOR) { + wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width, XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y); + } + + xcb_disconnect(XCBCONNECTION); +} + +void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { + +} + +void Events::listener_createX11(wl_listener* listener, void* data) { + const auto XWSURFACE = (wlr_xwayland_surface*)data; + + g_pCompositor->m_vWindows.push_back(CWindow()); + const auto PNEWWINDOW = &g_pCompositor->m_vWindows.back(); + + PNEWWINDOW->m_uSurface.xwayland = XWSURFACE; + PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1; + PNEWWINDOW->m_bIsX11 = true; + + wl_signal_add(&XWSURFACE->events.map, &PNEWWINDOW->listen_mapWindow); + wl_signal_add(&XWSURFACE->events.unmap, &PNEWWINDOW->listen_unmapWindow); + wl_signal_add(&XWSURFACE->events.request_activate, &PNEWWINDOW->listen_activateX11); + wl_signal_add(&XWSURFACE->events.request_configure, &PNEWWINDOW->listen_configureX11); + wl_signal_add(&XWSURFACE->events.set_title, &PNEWWINDOW->listen_setTitleWindow); + wl_signal_add(&XWSURFACE->events.destroy, &PNEWWINDOW->listen_destroyWindow); + wl_signal_add(&XWSURFACE->events.request_fullscreen, &PNEWWINDOW->listen_fullscreenWindow); + + Debug::log(LOG, "New XWayland Surface created."); +} + void Events::listener_keyboardKey(wl_listener* listener, void* data) { g_pInputManager->onKeyboardKey((wlr_event_keyboard_key*)data); } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 2319d671..1f335571 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -2,25 +2,32 @@ #include "../defines.hpp" namespace Events { - LISTENER(activate); + // Monitor events LISTENER(change); LISTENER(newOutput); + // Layer events LISTENER(newLayerSurface); LISTENER(destroyLayerSurface); LISTENER(mapLayerSurface); LISTENER(unmapLayerSurface); LISTENER(commitLayerSurface); + // Surface XDG (window) LISTENER(newXDGSurface); + // Window events LISTENER(commitWindow); LISTENER(mapWindow); LISTENER(unmapWindow); LISTENER(destroyWindow); LISTENER(setTitleWindow); LISTENER(fullscreenWindow); + LISTENER(activateX11); + LISTENER(configureX11); + LISTENER(createX11); + // Input events LISTENER(mouseMove); LISTENER(mouseMoveAbsolute); LISTENER(mouseButton); @@ -33,13 +40,21 @@ namespace Events { LISTENER(keyboardMod); LISTENER(keyboardDestroy); + // Various LISTENER(requestMouse); LISTENER(requestSetSel); LISTENER(requestSetPrimarySel); + LISTENER(activate); + // outputMgr LISTENER(outputMgrApply); LISTENER(outputMgrTest); + // Monitor part 2 the sequel LISTENER(monitorFrame); LISTENER(monitorDestroy); + + // XWayland + LISTENER(readyXWayland); + LISTENER(surfaceXWayland); }; \ No newline at end of file diff --git a/src/input/InputManager.cpp b/src/managers/InputManager.cpp similarity index 100% rename from src/input/InputManager.cpp rename to src/managers/InputManager.cpp diff --git a/src/input/InputManager.hpp b/src/managers/InputManager.hpp similarity index 100% rename from src/input/InputManager.hpp rename to src/managers/InputManager.hpp diff --git a/src/ManagerThread.cpp b/src/managers/ThreadManager.cpp similarity index 74% rename from src/ManagerThread.cpp rename to src/managers/ThreadManager.cpp index 15c41354..003cb947 100644 --- a/src/ManagerThread.cpp +++ b/src/managers/ThreadManager.cpp @@ -1,6 +1,6 @@ -#include "ManagerThread.hpp" +#include "ThreadManager.hpp" -CManagerThread::CManagerThread() { +CThreadManager::CThreadManager() { m_tMainThread = new std::thread([&]() { // Call the handle method. this->handle(); @@ -9,11 +9,11 @@ CManagerThread::CManagerThread() { m_tMainThread->detach(); // detach and continue. } -CManagerThread::~CManagerThread() { +CThreadManager::~CThreadManager() { // } -void CManagerThread::handle() { +void CThreadManager::handle() { g_pConfigManager->init(); diff --git a/src/managers/ThreadManager.hpp b/src/managers/ThreadManager.hpp new file mode 100644 index 00000000..40ed88d6 --- /dev/null +++ b/src/managers/ThreadManager.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "../defines.hpp" +#include +#include "../Compositor.hpp" + +class CThreadManager { +public: + CThreadManager(); + ~CThreadManager(); + +private: + + void handle(); + + std::thread* m_tMainThread; +}; + +inline std::unique_ptr g_pThreadManager; \ No newline at end of file diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp new file mode 100644 index 00000000..5a0a38aa --- /dev/null +++ b/src/managers/XWaylandManager.cpp @@ -0,0 +1,84 @@ +#include "XWaylandManager.hpp" +#include "../Compositor.hpp" +#include "../events/Events.hpp" + +CHyprXWaylandManager::CHyprXWaylandManager() { + m_sWLRXWayland = wlr_xwayland_create(g_pCompositor->m_sWLDisplay, g_pCompositor->m_sWLRCompositor, 1); + + if (!m_sWLRXWayland) { + Debug::log(ERR, "Couldn't start up the XWaylandManager because wlr_xwayland_create returned a nullptr!"); + return; + } + + wl_signal_add(&m_sWLRXWayland->events.ready, &Events::listen_readyXWayland); + wl_signal_add(&m_sWLRXWayland->events.new_surface, &Events::listen_surfaceXWayland); + + setenv("DISPLAY", m_sWLRXWayland->display_name, 1); + + Debug::log(LOG, "CHyprXWaylandManager started on display %s", m_sWLRXWayland->display_name); +} + +CHyprXWaylandManager::~CHyprXWaylandManager() { + +} + +wlr_surface* CHyprXWaylandManager::getWindowSurface(CWindow* pWindow) { + if (pWindow->m_bIsX11) + return pWindow->m_uSurface.xwayland->surface; + + return pWindow->m_uSurface.xdg->surface; +} + +void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) { + if (wlr_surface_is_xdg_surface(pSurface)) + wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(pSurface)->toplevel, activate); + + else if (wlr_surface_is_xwayland_surface(pSurface)) + wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate); +} + +void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) { + if (pWindow->m_bIsX11) { + pbox->x = pWindow->m_uSurface.xwayland->x; + pbox->y = pWindow->m_uSurface.xwayland->y; + pbox->width = pWindow->m_uSurface.xwayland->width; + pbox->height = pWindow->m_uSurface.xwayland->height; + } else { + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox); + } +} + +std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) { + if (pWindow->m_bIsX11) + return pWindow->m_uSurface.xwayland->title; + + return pWindow->m_uSurface.xdg->toplevel->title; +} + +void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) { + if (pWindow->m_bIsX11) { + wlr_xwayland_surface_close(pWindow->m_uSurface.xwayland); + } else { + wlr_xdg_toplevel_send_close(pWindow->m_uSurface.xdg->toplevel); + } +} + +void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) { + if (pWindow->m_bIsX11) + wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vPosition.x, pWindow->m_vPosition.y, size.x, size.y); + + else + wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); +} + +void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { + if (!pWindow->m_bIsX11) + wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez); +} + +wlr_surface* CHyprXWaylandManager::surfaceAt(CWindow* pWindow, const Vector2D& client, Vector2D& server) { + if (pWindow->m_bIsX11) + return wlr_surface_surface_at(pWindow->m_uSurface.xwayland->surface, client.x, client.y, &server.x, &server.y); + + return wlr_xdg_surface_surface_at(pWindow->m_uSurface.xdg, client.x, client.y, &server.x, &server.y); +} \ No newline at end of file diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp new file mode 100644 index 00000000..e439c9fb --- /dev/null +++ b/src/managers/XWaylandManager.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "../defines.hpp" +#include "../Window.hpp" + +class CHyprXWaylandManager { +public: + CHyprXWaylandManager(); + ~CHyprXWaylandManager(); + + wlr_xwayland* m_sWLRXWayland; + + wlr_surface* getWindowSurface(CWindow*); + void activateSurface(wlr_surface*, bool); + void getGeometryForWindow(CWindow*, wlr_box*); + std::string getTitle(CWindow*); + void sendCloseWindow(CWindow*); + void setWindowSize(CWindow*, const Vector2D&); + void setWindowStyleTiled(CWindow*, uint32_t); + wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&); +}; + +inline std::unique_ptr g_pXWaylandManager; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 623b9c07..a62da514 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -40,6 +40,9 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { for (auto& w : g_pCompositor->m_vWindows) { + if (w.m_bIsX11) + continue; + 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)) @@ -54,4 +57,19 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { 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); } + + for (auto& w : g_pCompositor->m_vWindows) { + + if (!w.m_bIsX11) + continue; + + wlr_box geometry = { w.m_uSurface.xwayland->x, w.m_uSurface.xwayland->y, w.m_uSurface.xwayland->width, w.m_uSurface.xwayland->height }; + + if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geometry)) + continue; + + SRenderData renderdata = {PMONITOR->output, time, w.m_vSize.x, w.m_vSize.y}; + + wlr_surface_for_each_surface(w.m_uSurface.xwayland->surface, renderSurface, &renderdata); + } }