mirror of https://github.com/hyprwm/Hyprland
rework popups completely
This commit is contained in:
parent
4c3b9ae207
commit
ad36a9dc9e
|
@ -365,20 +365,6 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) {
|
|||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CurrentPopup->parentSurface;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
||||
for (auto& p : m_lXDGPopups) {
|
||||
if (p.popup == popup)
|
||||
|
|
|
@ -53,7 +53,6 @@ public:
|
|||
|
||||
std::list<SMonitor> m_lMonitors;
|
||||
std::list<CWindow> m_lWindows;
|
||||
std::list<SLayerPopup> m_lLayerPopups;
|
||||
std::list<SXDGPopup> m_lXDGPopups;
|
||||
std::list<SWorkspace> m_lWorkspaces;
|
||||
std::list<SSubsurface> m_lSubsurfaces;
|
||||
|
@ -82,7 +81,6 @@ public:
|
|||
CWindow* windowFromCursor();
|
||||
CWindow* windowFloatingFromCursor();
|
||||
SMonitor* getMonitorFromOutput(wlr_output*);
|
||||
SLayerSurface* getLayerForPopup(SLayerPopup*);
|
||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
||||
CWindow* getWindowFromSurface(wlr_surface*);
|
||||
bool isWorkspaceVisible(const int&);
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
DYNLISTENER(setTitleWindow);
|
||||
DYNLISTENER(fullscreenWindow);
|
||||
DYNLISTENER(newPopupXDG);
|
||||
DYNLISTENER(newSubsurfaceWindow);
|
||||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
union {
|
||||
wlr_xdg_surface* xdg;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "includes.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define ISDEBUG true
|
||||
|
@ -10,6 +11,7 @@
|
|||
|
||||
#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 };
|
||||
#define DYNMULTILISTENER(name) wl_listener listen_##name;
|
||||
|
||||
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
|
||||
|
||||
|
@ -22,4 +24,8 @@
|
|||
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
||||
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
||||
|
||||
#define HYPRATOM(name) {name, 0}
|
||||
#define HYPRATOM(name) {name, 0}
|
||||
|
||||
#define RASSERT(expr, reason) if (expr) { Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %s in %s", reason, __LINE__, __FILE__); RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info.");}
|
||||
|
||||
#define ASSERT(expr) RASSERT(expr, "?")
|
|
@ -1,6 +1,12 @@
|
|||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
|
||||
//
|
||||
// LISTEN_NAME -> the wl_listener
|
||||
//
|
||||
// LISTENER_NAME -> the wl_listener.notify function
|
||||
//
|
||||
|
||||
namespace Events {
|
||||
// Monitor events
|
||||
LISTENER(change);
|
||||
|
@ -14,19 +20,15 @@ namespace Events {
|
|||
LISTENER(commitLayerSurface);
|
||||
|
||||
// Subsurfaces
|
||||
LISTENER(newSubsurface);
|
||||
LISTENER(newSubsurfaceNode);
|
||||
LISTENER(destroySubsurfaceNode);
|
||||
LISTENER(mapSubsurface);
|
||||
LISTENER(unmapSubsurface);
|
||||
LISTENER(destroySubsurface);
|
||||
LISTENER(commitSubsurface);
|
||||
|
||||
// Popups
|
||||
LISTENER(newPopup);
|
||||
LISTENER(newPopupFromPopup);
|
||||
LISTENER(mapPopup);
|
||||
LISTENER(unmapPopup);
|
||||
LISTENER(destroyPopup);
|
||||
LISTENER(commitPopup);
|
||||
LISTENER(newPopup); // LayerSurface
|
||||
|
||||
LISTENER(newPopupXDG);
|
||||
LISTENER(mapPopupXDG);
|
||||
|
@ -49,7 +51,7 @@ namespace Events {
|
|||
LISTENER(configureX11);
|
||||
|
||||
// Window subsurfaces
|
||||
LISTENER(newSubsurfaceWindow);
|
||||
// LISTENER(newSubsurfaceWindow);
|
||||
|
||||
// Input events
|
||||
LISTENER(mouseMove);
|
||||
|
|
|
@ -44,7 +44,6 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
|||
wl_signal_add(&WLRLAYERSURFACE->events.map, &layerSurface->listen_mapLayerSurface);
|
||||
wl_signal_add(&WLRLAYERSURFACE->events.unmap, &layerSurface->listen_unmapLayerSurface);
|
||||
wl_signal_add(&WLRLAYERSURFACE->events.new_popup, &layerSurface->listen_newPopup);
|
||||
wl_signal_add(&WLRLAYERSURFACE->surface->events.new_subsurface, &layerSurface->listen_newSubsurface);
|
||||
|
||||
layerSurface->layerSurface = WLRLAYERSURFACE;
|
||||
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
||||
|
@ -108,6 +107,8 @@ void Events::listener_mapLayerSurface(wl_listener* listener, void* data) {
|
|||
|
||||
if (layersurface->layerSurface->current.keyboard_interactive)
|
||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||
|
||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||
}
|
||||
|
||||
void Events::listener_unmapLayerSurface(wl_listener* listener, void* data) {
|
||||
|
@ -152,82 +153,6 @@ void Events::listener_commitLayerSurface(wl_listener* listener, void* data) {
|
|||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
//
|
||||
// Subsurfaces
|
||||
//
|
||||
|
||||
void createSubsurface(wlr_subsurface* pSubSurface, SLayerSurface* pLayerSurface) {
|
||||
if (!pSubSurface || !pLayerSurface)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Subsurface %x created", pSubSurface);
|
||||
|
||||
g_pCompositor->m_lSubsurfaces.push_back(SSubsurface());
|
||||
const auto PNEWSUBSURFACE = &g_pCompositor->m_lSubsurfaces.back();
|
||||
|
||||
PNEWSUBSURFACE->subsurface = pSubSurface;
|
||||
PNEWSUBSURFACE->pParentSurface = pLayerSurface;
|
||||
|
||||
wl_signal_add(&pSubSurface->events.map, &PNEWSUBSURFACE->listen_mapSubsurface);
|
||||
wl_signal_add(&pSubSurface->events.unmap, &PNEWSUBSURFACE->listen_unmapSubsurface);
|
||||
wl_signal_add(&pSubSurface->events.destroy, &PNEWSUBSURFACE->listen_destroySubsurface);
|
||||
wl_signal_add(&pSubSurface->surface->events.commit, &PNEWSUBSURFACE->listen_commitSubsurface);
|
||||
}
|
||||
|
||||
void damageSubsurface(SSubsurface* subSurface, bool all = false) {
|
||||
if (!subSurface->pParentSurface->layerSurface->output)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(subSurface->pParentSurface->layerSurface->output);
|
||||
|
||||
if (!PMONITOR)
|
||||
return; // wut?
|
||||
|
||||
int x = subSurface->subsurface->current.x + subSurface->pParentSurface->geometry.x;
|
||||
int y = subSurface->subsurface->current.y + subSurface->pParentSurface->geometry.y;
|
||||
|
||||
g_pHyprRenderer->damageSurface(PMONITOR, x, y, subSurface->subsurface->surface, &all);
|
||||
}
|
||||
|
||||
void Events::listener_newSubsurface(wl_listener* listener, void* data) {
|
||||
SLayerSurface* layersurface = wl_container_of(listener, layersurface, listen_newSubsurface);
|
||||
|
||||
createSubsurface((wlr_subsurface*)data, layersurface);
|
||||
}
|
||||
|
||||
void Events::listener_mapSubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_mapSubsurface);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x mapped", subsurface);
|
||||
|
||||
damageSubsurface(subsurface, true);
|
||||
}
|
||||
|
||||
void Events::listener_unmapSubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_unmapSubsurface);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x unmapped", subsurface);
|
||||
|
||||
damageSubsurface(subsurface, true);
|
||||
}
|
||||
|
||||
void Events::listener_commitSubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_commitSubsurface);
|
||||
|
||||
damageSubsurface(subsurface, false);
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_destroySubsurface);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
|
||||
|
||||
wl_list_remove(&subsurface->listen_mapSubsurface.link);
|
||||
wl_list_remove(&subsurface->listen_unmapSubsurface.link);
|
||||
wl_list_remove(&subsurface->listen_destroySubsurface.link);
|
||||
wl_list_remove(&subsurface->listen_commitSubsurface.link);
|
||||
|
||||
g_pCompositor->m_lSubsurfaces.remove(*subsurface);
|
||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||
}
|
|
@ -15,32 +15,49 @@
|
|||
// //
|
||||
// --------------------------------------------- //
|
||||
|
||||
void createNewPopup(wlr_xdg_popup* popup, void* parent, bool parentIsLayer) {
|
||||
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||
SXDGPopup *const PPOPUP = (SXDGPopup*)pPopup;
|
||||
|
||||
if (!popup)
|
||||
return;
|
||||
int px = 0;
|
||||
int py = 0;
|
||||
|
||||
g_pCompositor->m_lLayerPopups.push_back(SLayerPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lLayerPopups.back();
|
||||
auto curPopup = PPOPUP;
|
||||
while (true) {
|
||||
px += curPopup->popup->geometry.x;
|
||||
py += curPopup->popup->geometry.y;
|
||||
|
||||
PNEWPOPUP->popup = popup;
|
||||
if (parentIsLayer)
|
||||
PNEWPOPUP->parentSurface = (SLayerSurface*)parent;
|
||||
else
|
||||
PNEWPOPUP->parentPopup = (wlr_xdg_popup*)parent;
|
||||
if (curPopup->parentPopup) {
|
||||
curPopup = curPopup->parentPopup;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_signal_add(&popup->base->events.map, &PNEWPOPUP->listen_mapPopup);
|
||||
wl_signal_add(&popup->base->events.unmap, &PNEWPOPUP->listen_unmapPopup);
|
||||
wl_signal_add(&popup->base->events.destroy, &PNEWPOPUP->listen_destroyPopup);
|
||||
wl_signal_add(&popup->base->events.new_popup, &PNEWPOPUP->listen_newPopupFromPopup);
|
||||
wl_signal_add(&popup->base->surface->events.commit, &PNEWPOPUP->listen_commitPopup);
|
||||
px += *PPOPUP->lx;
|
||||
py += *PPOPUP->ly;
|
||||
|
||||
const auto PLAYER = g_pCompositor->getLayerForPopup(PNEWPOPUP);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(PLAYER->layerSurface->output);
|
||||
*x += px;
|
||||
*y += py;
|
||||
}
|
||||
|
||||
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
pHyprPopup->popup = popup;
|
||||
|
||||
pHyprPopup->listen_mapPopupXDG.notify = Events::listener_mapPopupXDG;
|
||||
pHyprPopup->listen_unmapPopupXDG.notify = Events::listener_unmapPopupXDG;
|
||||
pHyprPopup->listen_destroyPopupXDG.notify = Events::listener_destroyPopupXDG;
|
||||
pHyprPopup->listen_newPopupFromPopupXDG.notify = Events::listener_newPopupXDG;
|
||||
|
||||
wl_signal_add(&popup->base->events.map, &pHyprPopup->listen_mapPopupXDG);
|
||||
wl_signal_add(&popup->base->events.unmap, &pHyprPopup->listen_unmapPopupXDG);
|
||||
wl_signal_add(&popup->base->surface->events.destroy, &pHyprPopup->listen_destroyPopupXDG);
|
||||
wl_signal_add(&popup->base->events.new_popup, &pHyprPopup->listen_newPopupFromPopupXDG);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x, .y = PMONITOR->vecPosition.y, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(PNEWPOPUP->popup, &box);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
}
|
||||
|
||||
void Events::listener_newPopup(wl_listener* listener, void* data) {
|
||||
|
@ -50,81 +67,13 @@ void Events::listener_newPopup(wl_listener* listener, void* data) {
|
|||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
createNewPopup(WLRPOPUP, layersurface, true);
|
||||
}
|
||||
|
||||
void Events::listener_newPopupFromPopup(wl_listener* listener, void* data) {
|
||||
SLayerPopup* layerPopup = wl_container_of(listener, layerPopup, listen_newPopupFromPopup);
|
||||
|
||||
Debug::log(LOG, "New layer popup created from popup %x", layerPopup);
|
||||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
createNewPopup(WLRPOPUP, layerPopup, true);
|
||||
}
|
||||
|
||||
void Events::listener_destroyPopup(wl_listener* listener, void* data) {
|
||||
SLayerPopup* layerPopup = wl_container_of(listener, layerPopup, listen_destroyPopup);
|
||||
|
||||
Debug::log(LOG, "Destroyed popup %x", layerPopup);
|
||||
|
||||
wl_list_remove(&layerPopup->listen_mapPopup.link);
|
||||
wl_list_remove(&layerPopup->listen_unmapPopup.link);
|
||||
wl_list_remove(&layerPopup->listen_destroyPopup.link);
|
||||
wl_list_remove(&layerPopup->listen_commitPopup.link);
|
||||
|
||||
g_pCompositor->m_lLayerPopups.remove(*layerPopup);
|
||||
}
|
||||
|
||||
void Events::listener_mapPopup(wl_listener* listener, void* data) {
|
||||
SLayerPopup* layerPopup = wl_container_of(listener, layerPopup, listen_mapPopup);
|
||||
|
||||
Debug::log(LOG, "Mapped popup %x", layerPopup);
|
||||
|
||||
const auto PLAYER = g_pCompositor->getLayerForPopup(layerPopup);
|
||||
|
||||
wlr_surface_send_enter(layerPopup->popup->base->surface, PLAYER->layerSurface->output);
|
||||
}
|
||||
|
||||
void Events::listener_unmapPopup(wl_listener* listener, void* data) {
|
||||
SLayerPopup* layerPopup = wl_container_of(listener, layerPopup, listen_unmapPopup);
|
||||
|
||||
Debug::log(LOG, "LayerPopup %x unmapped", layerPopup);
|
||||
}
|
||||
|
||||
void Events::listener_commitPopup(wl_listener* listener, void* data) {
|
||||
SLayerPopup* layerPopup = wl_container_of(listener, layerPopup, listen_commitPopup);
|
||||
|
||||
}
|
||||
|
||||
void createNewPopupXDG(wlr_xdg_popup* popup, void* parent, bool parentIsWindow) {
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "New XDG Popup %x created", popup);
|
||||
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
|
||||
PNEWPOPUP->popup = popup;
|
||||
if (parentIsWindow)
|
||||
PNEWPOPUP->parentWindow = (CWindow*)parent;
|
||||
else {
|
||||
PNEWPOPUP->parentPopup = (wlr_xdg_popup*)parent;
|
||||
PNEWPOPUP->parentWindow = g_pCompositor->getWindowForPopup((wlr_xdg_popup*)parent);
|
||||
}
|
||||
|
||||
|
||||
wl_signal_add(&popup->base->events.map, &PNEWPOPUP->listen_mapPopupXDG);
|
||||
wl_signal_add(&popup->base->events.unmap, &PNEWPOPUP->listen_unmapPopupXDG);
|
||||
wl_signal_add(&popup->base->events.destroy, &PNEWPOPUP->listen_destroyPopupXDG);
|
||||
wl_signal_add(&popup->base->events.new_popup, &PNEWPOPUP->listen_newPopupFromPopupXDG);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PNEWPOPUP->parentWindow->m_iMonitorID);
|
||||
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x, .y = PMONITOR->vecPosition.y, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(PNEWPOPUP->popup, &box);
|
||||
PNEWPOPUP->popup = WLRPOPUP;
|
||||
PNEWPOPUP->lx = &layersurface->position.x;
|
||||
PNEWPOPUP->ly = &layersurface->position.y;
|
||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_newPopupXDG(wl_listener* listener, void* data) {
|
||||
|
@ -134,7 +83,13 @@ void Events::listener_newPopupXDG(wl_listener* listener, void* data) {
|
|||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
createNewPopupXDG(WLRPOPUP, PWINDOW, true);
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
|
||||
PNEWPOPUP->popup = WLRPOPUP;
|
||||
PNEWPOPUP->lx = &PWINDOW->m_vEffectivePosition.x;
|
||||
PNEWPOPUP->ly = &PWINDOW->m_vEffectivePosition.y;
|
||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_newPopupFromPopupXDG(wl_listener* listener, void* data) {
|
||||
|
@ -144,15 +99,32 @@ void Events::listener_newPopupFromPopupXDG(wl_listener* listener, void* data) {
|
|||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
createNewPopupXDG(WLRPOPUP, PPOPUP, true);
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
|
||||
PNEWPOPUP->popup = WLRPOPUP;
|
||||
PNEWPOPUP->parentPopup = PPOPUP;
|
||||
PNEWPOPUP->lx = PPOPUP->lx;
|
||||
PNEWPOPUP->ly = PPOPUP->ly;
|
||||
|
||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_mapPopupXDG(wl_listener* listener, void* data) {
|
||||
SXDGPopup* PPOPUP = wl_container_of(listener, PPOPUP, listen_mapPopupXDG);
|
||||
|
||||
Debug::log(LOG, "New XDG Popup mapped");
|
||||
|
||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP);
|
||||
}
|
||||
|
||||
void Events::listener_unmapPopupXDG(wl_listener* listener, void* data) {
|
||||
SXDGPopup* PPOPUP = wl_container_of(listener, PPOPUP, listen_unmapPopupXDG);
|
||||
Debug::log(LOG, "XDG Popup unmapped");
|
||||
|
||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
||||
|
||||
PPOPUP->pSurfaceTree = nullptr;
|
||||
}
|
||||
|
||||
void Events::listener_destroyPopupXDG(wl_listener* listener, void* data) {
|
||||
|
@ -160,9 +132,10 @@ void Events::listener_destroyPopupXDG(wl_listener* listener, void* data) {
|
|||
|
||||
Debug::log(LOG, "Destroyed popup XDG %x", PPOPUP);
|
||||
|
||||
wl_list_remove(&PPOPUP->listen_mapPopupXDG.link);
|
||||
wl_list_remove(&PPOPUP->listen_unmapPopupXDG.link);
|
||||
wl_list_remove(&PPOPUP->listen_destroyPopupXDG.link);
|
||||
if (PPOPUP->pSurfaceTree) {
|
||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
||||
PPOPUP->pSurfaceTree = nullptr;
|
||||
}
|
||||
|
||||
g_pCompositor->m_lXDGPopups.remove(*PPOPUP);
|
||||
}
|
|
@ -34,7 +34,7 @@ void Events::listener_mapWindow(wl_listener* listener, void* data) {
|
|||
return;
|
||||
}
|
||||
|
||||
wl_signal_add(&PWINDOWSURFACE->events.new_subsurface, &PWINDOW->listen_newSubsurfaceWindow);
|
||||
// wl_signal_add(&PWINDOWSURFACE->events.new_subsurface, &PWINDOW->listen_newSubsurfaceWindow);
|
||||
|
||||
if (g_pXWaylandManager->shouldBeFloated(PWINDOW))
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
|
@ -131,11 +131,7 @@ void Events::listener_unmapWindow(wl_listener* listener, void* data) {
|
|||
PWINDOW->m_bIsMapped = false;
|
||||
|
||||
// refocus on a new window
|
||||
// TODO: investigate.
|
||||
// If a parent window has focus, any popups (XWayland) will be broken (they will disappear instantly)
|
||||
// This might be way more sinister in nature and have a problem more deeply
|
||||
// rooted in the code.
|
||||
// g_pInputManager->refocus();
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
void Events::listener_commitWindow(wl_listener* listener, void* data) {
|
||||
|
@ -152,25 +148,8 @@ void Events::listener_destroyWindow(wl_listener* listener, void* data) {
|
|||
if (g_pXWaylandManager->getWindowSurface(PWINDOW) == g_pCompositor->m_pLastFocus)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
|
||||
// TODO:
|
||||
// We sometimes get invalid pointers here (stack ones)
|
||||
// this obviously means we tainted wlroots.
|
||||
// Investigate
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
wl_list_remove(&PWINDOW->listen_mapWindow.link);
|
||||
wl_list_remove(&PWINDOW->listen_unmapWindow.link);
|
||||
wl_list_remove(&PWINDOW->listen_destroyWindow.link);
|
||||
wl_list_remove(&PWINDOW->listen_setTitleWindow.link);
|
||||
wl_list_remove(&PWINDOW->listen_fullscreenWindow.link);
|
||||
if (PWINDOW->m_bIsX11) {
|
||||
wl_list_remove(&PWINDOW->listen_activateX11.link);
|
||||
wl_list_remove(&PWINDOW->listen_configureX11.link);
|
||||
} else {
|
||||
wl_list_remove(&PWINDOW->listen_commitWindow.link);
|
||||
}
|
||||
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
|
||||
}
|
||||
|
||||
|
@ -254,31 +233,5 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
|
|||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// Subsurfaces
|
||||
//
|
||||
|
||||
void createSubsurface(CWindow* pWindow, wlr_subsurface* pSubsurface) {
|
||||
if (!pWindow || !pSubsurface)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "New Window Subsurface %x created", pSubsurface);
|
||||
|
||||
g_pCompositor->m_lSubsurfaces.push_back(SSubsurface());
|
||||
const auto PNEWSUBSURFACE = &g_pCompositor->m_lSubsurfaces.back();
|
||||
|
||||
wl_signal_add(&pSubsurface->events.destroy, &PNEWSUBSURFACE->listen_destroySubsurface);
|
||||
wl_signal_add(&pSubsurface->events.map, &PNEWSUBSURFACE->listen_mapSubsurface);
|
||||
wl_signal_add(&pSubsurface->events.unmap, &PNEWSUBSURFACE->listen_unmapSubsurface);
|
||||
wl_signal_add(&pSubsurface->surface->events.commit, &PNEWSUBSURFACE->listen_commitSubsurface);
|
||||
}
|
||||
|
||||
void Events::listener_newSubsurfaceWindow(wl_listener* listener, void* data) {
|
||||
CWindow* PWINDOW = wl_container_of(listener, PWINDOW, listen_newSubsurfaceWindow);
|
||||
|
||||
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
||||
|
||||
createSubsurface(PWINDOW, PSUBSURFACE);
|
||||
}
|
||||
wl_signal_add(&XDGSURFACE->events.new_popup, &PNEWWINDOW->listen_newPopupXDG);
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
#include "SubsurfaceTree.hpp"
|
||||
#include "../events/Events.hpp"
|
||||
|
||||
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
||||
*lx += node->pSurface->sx;
|
||||
*ly += node->pSurface->sy;
|
||||
|
||||
if (node->offsetfn) {
|
||||
// This is the root node
|
||||
RASSERT(!node->pSubsurface, "Node had no subsurface!");
|
||||
node->offsetfn(node->globalOffsetData, lx, ly);
|
||||
} else {
|
||||
RASSERT(node->pSubsurface, "Node had no subsurface!");
|
||||
|
||||
*lx += node->pSubsurface->pSubsurface->current.x;
|
||||
*ly += node->pSubsurface->pSubsurface->current.y;
|
||||
|
||||
addSurfaceGlobalOffset(node->pParent, lx, ly);
|
||||
}
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
|
||||
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
|
||||
|
||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
|
||||
|
||||
PNODE->pSurface = pSurface;
|
||||
|
||||
PNODE->listen_newSubsurface.notify = Events::listener_newSubsurfaceNode;
|
||||
PNODE->listen_commit.notify = Events::listener_commitSubsurface;
|
||||
PNODE->listen_destroy.notify = Events::listener_destroySubsurfaceNode;
|
||||
|
||||
wl_signal_add(&pSurface->events.commit, &PNODE->listen_commit);
|
||||
wl_signal_add(&pSurface->events.destroy, &PNODE->listen_destroy);
|
||||
wl_signal_add(&pSurface->events.new_subsurface, &PNODE->listen_newSubsurface);
|
||||
|
||||
return PNODE;
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) {
|
||||
const auto PNODE = createTree(surface);
|
||||
PNODE->pParent = pParent;
|
||||
PNODE->pSubsurface = pSubsurface;
|
||||
|
||||
return PNODE;
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) {
|
||||
const auto PNODE = createTree(pSurface);
|
||||
PNODE->offsetfn = fn;
|
||||
PNODE->globalOffsetData = data;
|
||||
|
||||
return PNODE;
|
||||
}
|
||||
|
||||
void destroySubsurface(SSubsurface* pSubsurface);
|
||||
|
||||
void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
||||
for (auto& c : pNode->childSubsurfaces)
|
||||
destroySubsurface(&c);
|
||||
|
||||
pNode->childSubsurfaces.clear();
|
||||
|
||||
wl_list_remove(&pNode->listen_newSubsurface.link);
|
||||
wl_list_remove(&pNode->listen_commit.link);
|
||||
wl_list_remove(&pNode->listen_destroy.link);
|
||||
|
||||
Debug::log(LOG, "SurfaceTree Node removed");
|
||||
}
|
||||
|
||||
void destroySubsurface(SSubsurface* pSubsurface) {
|
||||
if (pSubsurface->pChild) {
|
||||
SubsurfaceTree::destroySurfaceTree(pSubsurface->pChild);
|
||||
pSubsurface->pChild = nullptr;
|
||||
}
|
||||
|
||||
wl_list_remove(&pSubsurface->listen_map.link);
|
||||
wl_list_remove(&pSubsurface->listen_unmap.link);
|
||||
wl_list_remove(&pSubsurface->listen_destroy.link);
|
||||
}
|
||||
|
||||
//
|
||||
// Subsurface listeners
|
||||
//
|
||||
|
||||
void Events::listener_newSubsurfaceNode(wl_listener* listener, void* data) {
|
||||
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_newSubsurface);
|
||||
|
||||
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
||||
|
||||
pNode->childSubsurfaces.push_back(SSubsurface());
|
||||
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.back();
|
||||
|
||||
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
|
||||
|
||||
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
|
||||
PNEWSUBSURFACE->pParent = pNode;
|
||||
|
||||
PNEWSUBSURFACE->listen_map.notify = Events::listener_mapSubsurface;
|
||||
PNEWSUBSURFACE->listen_unmap.notify = Events::listener_unmapSubsurface;
|
||||
PNEWSUBSURFACE->listen_destroy.notify = Events::listener_destroySubsurface;
|
||||
|
||||
wl_signal_add(&PSUBSURFACE->events.map, &PNEWSUBSURFACE->listen_map);
|
||||
wl_signal_add(&PSUBSURFACE->events.unmap, &PNEWSUBSURFACE->listen_unmap);
|
||||
wl_signal_add(&PSUBSURFACE->events.destroy, &PNEWSUBSURFACE->listen_destroy);
|
||||
}
|
||||
|
||||
void Events::listener_mapSubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_map);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
||||
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface);
|
||||
}
|
||||
|
||||
void Events::listener_unmapSubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_unmap);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x unmapped", subsurface);
|
||||
|
||||
if (subsurface->pChild) {
|
||||
const auto PNODE = subsurface->pChild;
|
||||
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {0};
|
||||
wlr_surface_get_extends(PNODE->pSurface, &extents);
|
||||
|
||||
extents.x += lx;
|
||||
extents.y += ly;
|
||||
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
subsurface->pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_commitSubsurface(wl_listener* listener, void* data) {
|
||||
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_commit);
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurface(wl_listener* listener, void* data) {
|
||||
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_destroy);
|
||||
|
||||
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
|
||||
|
||||
subsurface->pParent->childSubsurfaces.remove(*subsurface);
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurfaceNode(wl_listener* listener, void* data) {
|
||||
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_destroy);
|
||||
|
||||
Debug::log(LOG, "Subsurface Node %x destroyed", pNode);
|
||||
|
||||
for (auto& c : pNode->childSubsurfaces)
|
||||
destroySubsurface(&c);
|
||||
|
||||
wl_list_remove(&pNode->listen_newSubsurface.link);
|
||||
wl_list_remove(&pNode->listen_commit.link);
|
||||
wl_list_remove(&pNode->listen_destroy.link);
|
||||
|
||||
SubsurfaceTree::surfaceTreeNodes.remove(*pNode);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include <list>
|
||||
|
||||
struct SSubsurface;
|
||||
|
||||
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
|
||||
|
||||
struct SSurfaceTreeNode {
|
||||
wlr_surface* pSurface = nullptr;
|
||||
|
||||
DYNMULTILISTENER(newSubsurface);
|
||||
DYNMULTILISTENER(commit);
|
||||
DYNMULTILISTENER(destroy);
|
||||
|
||||
SSurfaceTreeNode* pParent = nullptr;
|
||||
SSubsurface* pSubsurface = nullptr;
|
||||
|
||||
std::list<SSubsurface> childSubsurfaces;
|
||||
|
||||
applyGlobalOffsetFn offsetfn;
|
||||
void *globalOffsetData;
|
||||
|
||||
bool operator==(const SSurfaceTreeNode& rhs) {
|
||||
return pSurface == rhs.pSurface;
|
||||
}
|
||||
};
|
||||
|
||||
struct SSubsurface {
|
||||
wlr_subsurface* pSubsurface = nullptr;
|
||||
|
||||
SSurfaceTreeNode* pParent = nullptr;
|
||||
SSurfaceTreeNode* pChild = nullptr;
|
||||
|
||||
DYNMULTILISTENER(map);
|
||||
DYNMULTILISTENER(unmap);
|
||||
DYNMULTILISTENER(destroy);
|
||||
|
||||
bool operator==(const SSubsurface& rhs) {
|
||||
return pSubsurface == rhs.pSubsurface;
|
||||
}
|
||||
};
|
||||
|
||||
namespace SubsurfaceTree {
|
||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*);
|
||||
void destroySurfaceTree(SSurfaceTreeNode*);
|
||||
|
||||
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
||||
};
|
|
@ -4,6 +4,7 @@
|
|||
#include "../defines.hpp"
|
||||
#include "../../wlr-layer-shell-unstable-v1-protocol.h"
|
||||
#include "../Window.hpp"
|
||||
#include "SubsurfaceTree.hpp"
|
||||
|
||||
struct SLayerSurface {
|
||||
wlr_layer_surface_v1* layerSurface;
|
||||
|
@ -14,9 +15,9 @@ struct SLayerSurface {
|
|||
DYNLISTENER(unmapLayerSurface);
|
||||
DYNLISTENER(commitLayerSurface);
|
||||
DYNLISTENER(newPopup);
|
||||
DYNLISTENER(newSubsurface);
|
||||
|
||||
wlr_box geometry;
|
||||
Vector2D position;
|
||||
zwlr_layer_shell_v1_layer layer;
|
||||
|
||||
int monitorID = -1;
|
||||
|
@ -28,22 +29,6 @@ struct SLayerSurface {
|
|||
}
|
||||
};
|
||||
|
||||
struct SSubsurface {
|
||||
wlr_subsurface* subsurface = nullptr;
|
||||
SLayerSurface* pParentSurface = nullptr;
|
||||
|
||||
DYNLISTENER(mapSubsurface);
|
||||
DYNLISTENER(unmapSubsurface);
|
||||
DYNLISTENER(destroySubsurface);
|
||||
DYNLISTENER(commitSubsurface);
|
||||
DYNLISTENER(newSubsurface);
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SSubsurface& rhs) {
|
||||
return subsurface == rhs.subsurface && pParentSurface == rhs.pParentSurface;
|
||||
}
|
||||
};
|
||||
|
||||
struct SRenderData {
|
||||
wlr_output* output;
|
||||
timespec* when;
|
||||
|
@ -68,26 +53,9 @@ struct SKeyboard {
|
|||
}
|
||||
};
|
||||
|
||||
struct SLayerPopup {
|
||||
wlr_xdg_popup* popup = nullptr;
|
||||
SLayerSurface* parentSurface = nullptr;
|
||||
wlr_xdg_popup* parentPopup = nullptr;
|
||||
|
||||
DYNLISTENER(mapPopup);
|
||||
DYNLISTENER(destroyPopup);
|
||||
DYNLISTENER(unmapPopup);
|
||||
DYNLISTENER(commitPopup);
|
||||
DYNLISTENER(newPopupFromPopup);
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerPopup& rhs) {
|
||||
return popup == rhs.popup;
|
||||
}
|
||||
};
|
||||
|
||||
struct SXDGPopup {
|
||||
CWindow* parentWindow = nullptr;
|
||||
wlr_xdg_popup* parentPopup = nullptr;
|
||||
SXDGPopup* parentPopup = nullptr;
|
||||
wlr_xdg_popup* popup = nullptr;
|
||||
|
||||
DYNLISTENER(newPopupFromPopupXDG);
|
||||
|
@ -95,6 +63,11 @@ struct SXDGPopup {
|
|||
DYNLISTENER(mapPopupXDG);
|
||||
DYNLISTENER(unmapPopupXDG);
|
||||
|
||||
double* lx;
|
||||
double* ly;
|
||||
|
||||
SSurfaceTreeNode* pSurfaceTree = nullptr;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SXDGPopup& rhs) {
|
||||
return popup == rhs.popup;
|
||||
|
|
Loading…
Reference in New Issue