diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9665ec37..0af5723d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -108,6 +108,7 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat"); + addWLSignal(&m_sSeat.seat->events.start_drag, &Events::listen_startDrag, &m_sSeat, "Seat"); addWLSignal(&m_sWLRLayerShell->events.new_surface, &Events::listen_newLayerSurface, m_sWLRLayerShell, "LayerShell"); addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout"); addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr"); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 450394f9..7b5b8a3f 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -73,7 +73,7 @@ std::string layersRequest() { result += getFormat("\tLayer level %i:\n", layerLevel); for (auto& layer : level) { - result += getFormat("\t\tLayer %x -> %s: xywh: %i %i %i %i\n", layer, (layer->layerSurface ? layer->layerSurface->_namespace : "null"), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height); + result += getFormat("\t\tLayer %x: xywh: %i %i %i %i\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height); } layerLevel++; diff --git a/src/events/Events.hpp b/src/events/Events.hpp index fa80b4e2..4e8246fe 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -87,6 +87,12 @@ namespace Events { // Drag & Drop LISTENER(requestDrag); LISTENER(startDrag); + DYNLISTENFUNC(destroyDrag); + + DYNLISTENFUNC(mapDragIcon); + DYNLISTENFUNC(unmapDragIcon); + DYNLISTENFUNC(destroyDragIcon); + DYNLISTENFUNC(commitDragIcon); // Inhibit LISTENER(InhibitActivate); diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 7bd08a57..99dad9bc 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -78,7 +78,67 @@ void Events::listener_requestDrag(wl_listener* listener, void* data) { } void Events::listener_startDrag(wl_listener* listener, void* data) { - // TODO: draw the drag icon + + if (g_pInputManager->m_sDrag.drag) + return; // don't handle multiple drags + + g_pInputManager->m_sDrag.drag = (wlr_drag*)data; + + wlr_drag* wlrDrag = (wlr_drag*)data; + + Debug::log(LOG, "Started drag %x", wlrDrag); + + wlrDrag->data = data; + + g_pInputManager->m_sDrag.hyprListener_destroy.initCallback(&wlrDrag->events.destroy, &Events::listener_destroyDrag, &g_pInputManager->m_sDrag, "Drag"); + + if (wlrDrag->icon) { + Debug::log(LOG, "Drag started with an icon %x", wlrDrag->icon); + + g_pInputManager->m_sDrag.dragIcon = wlrDrag->icon; + wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon; + + g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon"); + g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon"); + g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon"); + g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag, "DragIcon"); + } +} + +void Events::listener_destroyDrag(void* owner, void* data) { + Debug::log(LOG, "Drag destroyed."); + + g_pInputManager->m_sDrag.drag = nullptr; + g_pInputManager->m_sDrag.dragIcon = nullptr; + g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback(); + + g_pInputManager->refocus(); +} + +void Events::listener_mapDragIcon(void* owner, void* data) { + Debug::log(LOG, "Drag icon mapped."); + g_pInputManager->m_sDrag.iconMapped = true; +} + +void Events::listener_unmapDragIcon(void* owner, void* data) { + Debug::log(LOG, "Drag icon unmapped."); + g_pInputManager->m_sDrag.iconMapped = false; +} + +void Events::listener_destroyDragIcon(void* owner, void* data) { + Debug::log(LOG, "Drag icon destroyed."); + + g_pInputManager->m_sDrag.dragIcon = nullptr; + g_pInputManager->m_sDrag.hyprListener_commitIcon.removeCallback(); + g_pInputManager->m_sDrag.hyprListener_destroyIcon.removeCallback(); + g_pInputManager->m_sDrag.hyprListener_mapIcon.removeCallback(); + g_pInputManager->m_sDrag.hyprListener_unmapIcon.removeCallback(); +} + +void Events::listener_commitDragIcon(void* owner, void* data) { + g_pInputManager->updateDragIcon(); + + Debug::log(LOG, "Drag icon committed."); } void Events::listener_InhibitActivate(wl_listener* listener, void* data) { diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 985e62af..a42b15dd 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -77,4 +77,23 @@ struct SXDGPopup { struct SSeat { wlr_seat* seat = nullptr; wl_client* exclusiveClient = nullptr; +}; + +struct SDrag { + wlr_drag* drag = nullptr; + + DYNLISTENER(destroy); + + // Icon + + bool iconMapped = false; + + wlr_drag_icon* dragIcon = nullptr; + + Vector2D pos; + + DYNLISTENER(destroyIcon); + DYNLISTENER(mapIcon); + DYNLISTENER(unmapIcon); + DYNLISTENER(commitIcon); }; \ No newline at end of file diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index 0610da81..1c9b4335 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -1,6 +1,7 @@ #include "WLListener.hpp" #include "MiscFunctions.hpp" #include +#include "../debug/Log.hpp" void handleWrapped(wl_listener* listener, void* data) { CHyprWLListener* pListener = wl_container_of(listener, pListener, m_sListener); @@ -22,6 +23,7 @@ CHyprWLListener::~CHyprWLListener() { void CHyprWLListener::removeCallback() { if (m_bIsConnected) { + Debug::log(LOG, "Callback %x -> %x, %s removed.", m_pCallback, m_pOwner, m_szAuthor.c_str()); wl_list_remove(&m_sListener.link); wl_list_init(&m_sListener.link); } diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp index 0718bfcc..10b1ad95 100644 --- a/src/managers/InputManager.cpp +++ b/src/managers/InputManager.cpp @@ -20,11 +20,18 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) { void CInputManager::mouseMoveUnified(uint32_t time) { + // update stuff + updateDragIcon(); + + + // focus wlr_surface* foundSurface = nullptr; Vector2D mouseCoords = getMouseCoordsInternal(); + const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); if (PMONITOR) g_pCompositor->m_pLastMonitor = PMONITOR; + Vector2D surfaceCoords; Vector2D surfacePos = Vector2D(-1337, -1337); @@ -255,4 +262,19 @@ void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) { void CInputManager::refocus() { mouseMoveUnified(0); +} + +void CInputManager::updateDragIcon() { + if (!g_pInputManager->m_sDrag.dragIcon) + return; + + switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) { + case WLR_DRAG_GRAB_KEYBOARD: + break; + case WLR_DRAG_GRAB_KEYBOARD_POINTER: + g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal(); + break; + default: + break; + } } \ No newline at end of file diff --git a/src/managers/InputManager.hpp b/src/managers/InputManager.hpp index f0abe183..6775abee 100644 --- a/src/managers/InputManager.hpp +++ b/src/managers/InputManager.hpp @@ -24,11 +24,15 @@ public: void setKeyboardLayout(); + void updateDragIcon(); + // for dragging floating windows CWindow* currentlyDraggedWindow = nullptr; int dragButton = -1; + SDrag m_sDrag; + private: std::list m_lKeyboards; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7eda6296..a7babdd9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -78,6 +78,8 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, SWor renderWindow(&w, pMonitor, time, true); } + + renderDragIcon(pMonitor, time); } void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) { @@ -167,6 +169,8 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) { SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y}; wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata); } + + renderDragIcon(PMONITOR, time); } void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) { @@ -461,4 +465,16 @@ void CHyprRenderer::damageSurface(SMonitor* pMonitor, double x, double y, wlr_su }; wlr_surface_for_each_surface(pSurface, damageSurfaceIter, &renderData); +} + +void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) { + if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface)) + return; + + SRenderData renderdata = {pMonitor->output, time, g_pInputManager->m_sDrag.pos.x, g_pInputManager->m_sDrag.pos.y}; + renderdata.surface = g_pInputManager->m_sDrag.dragIcon->surface; + renderdata.w = g_pInputManager->m_sDrag.dragIcon->surface->current.width; + renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height; + + wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata); } \ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 2d7d8eb9..fce5b357 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -19,6 +19,7 @@ private: void drawBorderForWindow(CWindow*, SMonitor*); void renderWorkspaceWithFullscreenWindow(SMonitor*, SWorkspace*, timespec*); void renderWindow(CWindow*, SMonitor*, timespec*, bool); + void renderDragIcon(SMonitor*, timespec*); }; inline std::unique_ptr g_pHyprRenderer;