Hyprland/src/events/Popups.cpp

265 lines
9.6 KiB
C++
Raw Normal View History

2022-03-21 15:17:04 +01:00
#include "Events.hpp"
#include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp"
2022-06-09 12:46:55 +02:00
#include "../managers/input/InputManager.hpp"
2022-03-21 15:17:04 +01:00
#include "../render/Renderer.hpp"
// --------------------------------------------- //
// _____ ____ _____ _ _ _____ _____ //
// | __ \ / __ \| __ \| | | | __ \ / ____| //
// | |__) | | | | |__) | | | | |__) | (___ //
// | ___/| | | | ___/| | | | ___/ \___ \ //
// | | | |__| | | | |__| | | ____) | //
// |_| \____/|_| \____/|_| |_____/ //
// //
// --------------------------------------------- //
2022-03-27 17:25:20 +02:00
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup;
2022-03-27 17:25:20 +02:00
auto curPopup = PPOPUP;
int px = 0;
int py = 0;
2022-03-27 17:25:20 +02:00
while (true) {
2022-05-27 16:03:24 +02:00
px += curPopup->popup->current.geometry.x;
py += curPopup->popup->current.geometry.y;
2022-03-27 17:25:20 +02:00
if (curPopup == PPOPUP && PPOPUP->parentWindow) {
px -= curPopup->popup->base->current.geometry.x;
py -= curPopup->popup->base->current.geometry.y;
}
if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) {
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region);
2022-08-30 19:21:45 +02:00
px -= EXTENTSSURFACE->x1;
py -= EXTENTSSURFACE->y1;
}
2022-03-27 17:25:20 +02:00
if (curPopup->parentPopup) {
curPopup = curPopup->parentPopup;
} else {
break;
}
}
2022-04-02 13:41:15 +02:00
px += PPOPUP->lx;
py += PPOPUP->ly;
2022-03-21 15:17:04 +01:00
2022-03-27 17:25:20 +02:00
*x += px;
*y += py;
}
2022-03-21 15:17:04 +01:00
2022-03-27 17:25:20 +02:00
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
pHyprPopup->popup = popup;
2022-03-21 15:17:04 +01:00
2022-07-26 22:45:59 +02:00
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
2023-06-03 12:20:23 +02:00
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->surface->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->surface->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
2022-03-28 22:31:39 +02:00
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
2022-07-28 11:37:27 +02:00
pHyprPopup->hyprListener_commitPopupXDG.initCallback(&popup->base->surface->events.commit, &Events::listener_commitPopupXDG, pHyprPopup, "HyprPopup");
pHyprPopup->hyprListener_repositionPopupXDG.initCallback(&popup->events.reposition, &Events::listener_repositionPopupXDG, pHyprPopup, "HyprPopup");
2022-03-21 15:17:04 +01:00
2022-03-27 17:25:20 +02:00
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
2022-03-21 15:17:04 +01:00
CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
2022-03-21 15:17:04 +01:00
wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr());
2022-04-02 13:41:15 +02:00
pHyprPopup->monitor = PMONITOR;
2022-04-07 16:42:16 +02:00
Debug::log(LOG, "Popup: Unconstrained from lx ly: {:j5}, pHyprPopup lx ly: {:.5f} {:.5f}", PMONITOR->vecPosition, (float)pHyprPopup->lx, (float)pHyprPopup->ly);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_newPopup(void* owner, void* data) {
SLayerSurface* layersurface = (SLayerSurface*)owner;
2022-03-21 15:17:04 +01:00
2022-03-31 21:58:33 +02:00
ASSERT(layersurface);
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "New layer popup created from surface {:x}", (uintptr_t)layersurface);
2022-03-24 21:34:24 +01:00
2022-03-21 15:17:04 +01:00
const auto WLRPOPUP = (wlr_xdg_popup*)data;
2022-06-30 15:44:26 +02:00
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
2022-03-21 15:17:04 +01:00
2022-04-02 13:41:15 +02:00
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
2023-03-20 16:00:58 +01:00
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = layersurface->position.x;
PNEWPOPUP->ly = layersurface->position.y;
PNEWPOPUP->monitor = PMONITOR;
PNEWPOPUP->parentLS = layersurface;
2022-03-27 17:25:20 +02:00
createNewPopup(WLRPOPUP, PNEWPOPUP);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_newPopupXDG(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
2022-03-31 21:58:33 +02:00
ASSERT(PWINDOW);
2022-07-08 11:24:07 +02:00
if (!PWINDOW->m_bIsMapped)
return;
Debug::log(LOG, "New layer popup created from XDG window {}", PWINDOW);
2022-03-24 21:34:24 +01:00
2022-03-21 15:17:04 +01:00
const auto WLRPOPUP = (wlr_xdg_popup*)data;
2022-06-30 15:44:26 +02:00
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
2022-03-27 17:25:20 +02:00
2022-04-02 13:41:15 +02:00
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
2022-03-31 21:55:21 +02:00
PNEWPOPUP->parentWindow = PWINDOW;
PNEWPOPUP->monitor = PMONITOR;
2022-03-27 17:25:20 +02:00
createNewPopup(WLRPOPUP, PNEWPOPUP);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2022-03-21 15:17:04 +01:00
2022-03-31 21:58:33 +02:00
ASSERT(PPOPUP);
2022-09-25 20:07:48 +02:00
2022-03-31 21:58:33 +02:00
if (PPOPUP->parentWindow)
Debug::log(LOG, "New popup created from XDG Window popup {:x} -> {}", (uintptr_t)PPOPUP, PPOPUP->parentWindow);
2022-03-31 21:58:33 +02:00
else
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "New popup created from Non-Window popup {:x}", (uintptr_t)PPOPUP);
2022-03-24 21:34:24 +01:00
2022-03-21 15:17:04 +01:00
const auto WLRPOPUP = (wlr_xdg_popup*)data;
2022-06-30 15:44:26 +02:00
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
2022-03-27 17:25:20 +02:00
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP;
PNEWPOPUP->lx = PPOPUP->lx;
PNEWPOPUP->ly = PPOPUP->ly;
2022-03-31 21:58:33 +02:00
PNEWPOPUP->parentWindow = PPOPUP->parentWindow;
PNEWPOPUP->monitor = PPOPUP->monitor;
2022-03-27 17:25:20 +02:00
createNewPopup(WLRPOPUP, PNEWPOPUP);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_mapPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2022-03-27 17:25:20 +02:00
2022-03-31 21:58:33 +02:00
ASSERT(PPOPUP);
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "New XDG Popup mapped at {} {}", (int)PPOPUP->lx, (int)PPOPUP->ly);
2022-03-27 17:25:20 +02:00
2023-03-20 16:00:58 +01:00
if (PPOPUP->parentWindow)
PPOPUP->parentWindow->m_lPopupSurfaces.emplace_back(PPOPUP->popup->base->surface);
else if (PPOPUP->parentLS)
PPOPUP->parentLS->popupSurfaces.emplace_back(PPOPUP->popup->base->surface);
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
2022-03-28 21:16:23 +02:00
2022-07-28 11:37:27 +02:00
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
CBox extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
extents.applyFromWlr();
2022-08-12 17:04:26 +02:00
2022-08-23 16:52:36 +02:00
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
2022-07-28 11:37:27 +02:00
if (PPOPUP->monitor) {
g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform);
}
2023-04-12 19:00:01 +02:00
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree);
2022-03-21 15:17:04 +01:00
}
void Events::listener_repositionPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "XDG Popup {:x} asks for a reposition", (uintptr_t)PPOPUP);
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
CBox extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
extents.applyFromWlr();
PPOPUP->lastPos = {lx - extents.x, ly - extents.y};
PPOPUP->repositionRequested = true;
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x,
PMONITOR->vecSize.y};
wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr());
}
2022-03-28 22:31:39 +02:00
void Events::listener_unmapPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2022-03-24 21:34:24 +01:00
Debug::log(LOG, "XDG Popup unmapped");
2022-03-27 17:25:20 +02:00
2022-03-31 21:58:33 +02:00
ASSERT(PPOPUP);
2023-04-07 13:54:11 +02:00
if (PPOPUP->popup->base->surface == g_pCompositor->m_pLastFocus)
g_pInputManager->releaseAllMouseButtons();
2022-03-27 17:25:20 +02:00
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
2022-07-28 11:37:27 +02:00
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
CBox extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
extents.applyFromWlr();
2022-08-12 17:04:26 +02:00
2022-08-23 16:52:36 +02:00
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
2022-07-28 11:37:27 +02:00
2023-03-23 01:22:28 +01:00
if (PPOPUP->parentWindow)
std::erase(PPOPUP->parentWindow->m_lPopupSurfaces, PPOPUP->popup->base->surface);
else if (PPOPUP->parentLS)
std::erase(PPOPUP->parentLS->popupSurfaces, PPOPUP->popup->base->surface);
2022-03-27 17:25:20 +02:00
PPOPUP->pSurfaceTree = nullptr;
g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface
2022-03-21 15:17:04 +01:00
}
2022-07-28 11:37:27 +02:00
void Events::listener_commitPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2023-07-15 18:27:21 +02:00
if (g_pCompositor->windowValidMapped(PPOPUP->parentWindow)) {
PPOPUP->lx = PPOPUP->parentWindow->m_vRealPosition.vec().x;
PPOPUP->ly = PPOPUP->parentWindow->m_vRealPosition.vec().y;
}
int lx = 0, ly = 0;
2022-07-28 11:37:27 +02:00
addPopupGlobalCoords(PPOPUP, &lx, &ly);
CBox extents;
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
extents.applyFromWlr();
if (PPOPUP->repositionRequested)
g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2);
PPOPUP->repositionRequested = false;
2022-07-28 11:37:27 +02:00
g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
}
2022-03-28 22:31:39 +02:00
void Events::listener_destroyPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
2022-03-21 15:17:04 +01:00
2022-03-31 21:58:33 +02:00
ASSERT(PPOPUP);
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Destroyed popup XDG {:x}", (uintptr_t)PPOPUP);
2022-03-24 21:34:24 +01:00
2022-03-27 17:25:20 +02:00
if (PPOPUP->pSurfaceTree) {
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
PPOPUP->pSurfaceTree = nullptr;
}
2022-03-21 15:17:04 +01:00
std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; });
2022-09-25 20:07:48 +02:00
}