Hyprland/src/events/Windows.cpp

537 lines
24 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 21:46:27 +02:00
void addViewCoords(void* pWindow, int* x, int* y) {
const auto PWINDOW = (CWindow*)pWindow;
*x += PWINDOW->m_vRealPosition.goalv().x;
*y += PWINDOW->m_vRealPosition.goalv().y;
2022-06-22 15:45:56 +02:00
if (!PWINDOW->m_bIsX11) {
wlr_box geom;
wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom);
*x -= geom.x;
*y -= geom.y;
}
2022-03-27 21:46:27 +02:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
2022-05-31 14:01:00 +02:00
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
2022-03-21 15:17:04 +01:00
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
2022-05-31 14:01:00 +02:00
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
2022-03-22 20:53:11 +01:00
PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false;
2022-04-18 13:10:58 +02:00
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
2022-04-23 14:16:02 +02:00
PWINDOW->m_fAlpha = 255.f;
2022-03-21 15:17:04 +01:00
2022-06-30 15:44:26 +02:00
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
// Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
2022-05-29 11:24:42 +02:00
// Foreign Toplevel
PWINDOW->m_phForeignToplevel = wlr_foreign_toplevel_handle_v1_create(g_pCompositor->m_sWLRToplevelMgr);
// TODO: handle foreign events (requests)
wlr_foreign_toplevel_handle_v1_set_app_id(PWINDOW->m_phForeignToplevel, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
2022-03-22 21:28:57 +01:00
// checks if the window wants borders and sets the appriopriate flag
g_pXWaylandManager->checkBorders(PWINDOW);
2022-03-21 17:00:17 +01:00
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(PWINDOW);
if (!PWINDOWSURFACE) {
2022-06-30 15:44:26 +02:00
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
2022-03-21 17:00:17 +01:00
return;
}
2022-05-26 19:05:32 +02:00
if (g_pXWaylandManager->shouldBeFloated(PWINDOW)) {
2022-03-21 17:24:41 +01:00
PWINDOW->m_bIsFloating = true;
2022-05-26 19:05:32 +02:00
PWINDOW->m_bRequestsFloat = true;
}
if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true;
if (PWORKSPACE->m_bDefaultPseudo) {
PWINDOW->m_bIsPseudotiled = true;
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
}
2022-03-24 18:22:01 +01:00
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
2022-06-26 12:12:29 +02:00
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
}
2022-03-24 18:22:01 +01:00
// window rules
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
std::string requestedWorkspace = "";
bool workspaceSilent = false;
2022-06-26 12:12:29 +02:00
bool requestsFullscreen = false;
2022-03-24 18:22:01 +01:00
for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) {
try {
const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
2022-03-24 18:22:01 +01:00
if (MONITORSTR == "unset") {
PWINDOW->m_iMonitorID = PMONITOR->ID;
} else {
const long int MONITOR = std::stoi(MONITORSTR);
2022-06-30 15:44:26 +02:00
if (MONITOR >= (long int)g_pCompositor->m_vMonitors.size() || MONITOR < (long int)0)
PWINDOW->m_iMonitorID = 0;
else
PWINDOW->m_iMonitorID = MONITOR;
}
2022-03-24 18:22:01 +01:00
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
2022-03-24 19:05:25 +01:00
2022-04-21 17:17:47 +02:00
Debug::log(ERR, "Rule monitor, applying to window %x -> mon: %i, workspace: %i", PWINDOW, PWINDOW->m_iMonitorID, PWINDOW->m_iWorkspaceID);
} catch (std::exception& e) {
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
2022-03-24 18:22:01 +01:00
}
2022-04-21 17:17:47 +02:00
} else if (r.szRule.find("workspace") == 0) {
// check if it isnt unset
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
2022-04-21 17:17:47 +02:00
if (WORKSPACERQ == "unset") {
requestedWorkspace = "";
} else {
requestedWorkspace = WORKSPACERQ;
}
2022-04-21 17:17:47 +02:00
2022-07-04 19:58:51 +02:00
if (requestedWorkspace == "special") {
requestedWorkspace = "";
workspaceSilent = false;
Debug::log(LOG, "windowrule=workspace special is not allowed!");
continue;
}
2022-04-21 17:17:47 +02:00
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
2022-03-24 18:22:01 +01:00
} else if (r.szRule.find("float") == 0) {
PWINDOW->m_bIsFloating = true;
} else if (r.szRule.find("tile") == 0) {
PWINDOW->m_bIsFloating = false;
2022-04-02 20:04:32 +02:00
} else if (r.szRule.find("pseudo") == 0) {
PWINDOW->m_bIsPseudotiled = true;
2022-05-14 14:37:57 +02:00
} else if (r.szRule.find("nofocus") == 0) {
PWINDOW->m_bNoFocus = true;
2022-06-24 22:28:54 +02:00
} else if (r.szRule == "noblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur = true;
2022-06-26 12:12:29 +02:00
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
2022-05-28 17:48:01 +02:00
} else if (r.szRule.find("rounding") == 0) {
try {
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
} catch (std::exception& e) {
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
2022-04-22 14:37:38 +02:00
} else if (r.szRule.find("opacity") == 0) {
try {
2022-05-31 17:35:50 +02:00
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
if (alphaPart.contains(' ')) {
2022-05-31 17:35:50 +02:00
// we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
} else {
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart);
}
2022-04-22 14:37:38 +02:00
} catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
2022-05-15 14:18:31 +02:00
} else if (r.szRule.find("animation") == 0) {
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
PWINDOW->m_sAdditionalConfigData.animationStyle = STYLE;
2022-03-24 18:22:01 +01:00
}
}
if (requestedWorkspace != "") {
// process requested workspace
if (requestedWorkspace.contains(' ')) {
// check for silent
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
if (!workspaceSilent) {
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
}
}
2022-03-24 18:22:01 +01:00
if (PWINDOW->m_bIsFloating) {
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true;
2022-03-24 18:22:01 +01:00
// size and move rules
for (auto& r : WINDOWRULES) {
if (r.szRule.find("size") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
2022-03-24 18:22:01 +01:00
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
2022-04-23 14:16:02 +02:00
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
2022-03-24 18:22:01 +01:00
} catch (...) {
Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} else if (r.szRule.find("move") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
2022-03-24 18:22:01 +01:00
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
2022-04-23 14:16:02 +02:00
PWINDOW->m_vRealPosition = Vector2D(POSX, POSY) + PMONITOR->vecPosition;
2022-03-24 18:22:01 +01:00
} catch (...) {
Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
}
}
2022-04-02 20:04:32 +02:00
// set the pseudo size to the GOAL of our current size
// because the windows are animated on RealSize
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv();
2022-03-21 17:24:41 +01:00
}
2022-04-02 20:04:32 +02:00
else {
2022-03-21 15:17:04 +01:00
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
2022-03-24 18:22:01 +01:00
2022-04-02 20:04:32 +02:00
// Set the pseudo size here too so that it doesnt end up being 0x0
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
2022-04-02 20:04:32 +02:00
}
2022-03-24 18:22:01 +01:00
2022-06-26 20:08:19 +02:00
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
2022-05-14 14:37:57 +02:00
g_pCompositor->focusWindow(PWINDOW);
2022-03-21 15:17:04 +01:00
2022-03-28 21:16:23 +02:00
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
2022-03-28 17:51:03 +02:00
if (!PWINDOW->m_bIsX11) {
2022-03-28 22:31:39 +02:00
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xdg->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
2022-03-28 17:51:03 +02:00
} else {
2022-03-28 22:31:39 +02:00
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
2022-03-28 17:51:03 +02:00
}
2022-05-14 16:43:30 +02:00
// do the animation thing
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
2022-05-14 16:43:30 +02:00
if (workspaceSilent) {
// move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) {
2022-07-04 12:03:09 +02:00
if (requestedWorkspace != "special")
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
else
g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
}
2022-06-26 12:12:29 +02:00
if (requestsFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
}
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
2022-06-26 12:12:29 +02:00
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
}
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
2022-06-28 15:30:46 +02:00
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_unmapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
2022-06-28 12:24:21 +02:00
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
2022-03-24 21:34:24 +01:00
2022-03-28 17:51:03 +02:00
if (!PWINDOW->m_bIsX11) {
2022-03-28 22:31:39 +02:00
Debug::log(LOG, "Unregistered late callbacks XDG: %x %x %x %x", &PWINDOW->hyprListener_commitWindow.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link, &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_newPopupXDG.m_sListener.link);
PWINDOW->hyprListener_commitWindow.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
PWINDOW->hyprListener_newPopupXDG.removeCallback();
2022-03-28 17:51:03 +02:00
} else {
2022-03-28 22:31:39 +02:00
Debug::log(LOG, "Unregistered late callbacks XWL: %x %x %x %x", &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_activateX11.m_sListener.link, &PWINDOW->hyprListener_configureX11.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link);
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
PWINDOW->hyprListener_activateX11.removeCallback();
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
2022-03-28 17:51:03 +02:00
}
2022-06-27 22:34:37 +02:00
if (PWINDOW->m_bIsFullscreen) {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
}
2022-04-24 16:41:01 +02:00
// Allow the renderer to catch the last frame.
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
2022-04-02 18:57:09 +02:00
if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr;
2022-03-21 15:17:04 +01:00
g_pCompositor->m_pLastFocus = nullptr;
2022-04-02 18:57:09 +02:00
}
2022-03-21 15:17:04 +01:00
2022-04-23 14:16:02 +02:00
PWINDOW->m_fAlpha = 0.f;
2022-03-22 20:04:39 +01:00
PWINDOW->m_bMappedX11 = false;
2022-03-21 19:18:33 +01:00
// remove the fullscreen window status from workspace if we closed it
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && PWINDOW->m_bIsFullscreen)
PWORKSPACE->m_bHasFullscreenWindow = false;
2022-03-21 19:18:33 +01:00
2022-03-21 15:17:04 +01:00
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
2022-03-22 22:22:59 +01:00
// do this after onWindowRemoved because otherwise it'll think the window is invalid
PWINDOW->m_bIsMapped = false;
2022-03-21 19:28:43 +01:00
// refocus on a new window
2022-03-27 17:25:20 +02:00
g_pInputManager->refocus();
2022-03-27 21:46:27 +02:00
2022-04-02 18:57:09 +02:00
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW);
2022-03-27 21:46:27 +02:00
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
2022-03-27 22:34:02 +02:00
2022-03-27 21:46:27 +02:00
PWINDOW->m_pSurfaceTree = nullptr;
2022-04-05 19:28:10 +02:00
PWINDOW->m_bFadingOut = true;
2022-06-30 15:44:26 +02:00
g_pCompositor->m_vWindowsFadingOut.emplace_back(PWINDOW);
2022-04-14 17:00:35 +02:00
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
2022-06-30 20:02:04 +02:00
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing
2022-06-30 20:02:04 +02:00
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
2022-05-29 11:24:42 +02:00
// Destroy Foreign Toplevel
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
PWINDOW->m_phForeignToplevel = nullptr;
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_commitWindow(void* owner, void* data) {
2022-04-05 18:29:58 +02:00
CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
2022-03-21 15:17:04 +01:00
2022-07-04 15:58:12 +02:00
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
2022-03-28 22:31:39 +02:00
// Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_destroyWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
Debug::log(LOG, "Window %x destroyed, queueing. (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
if (PWINDOW->m_bIsX11)
Debug::log(LOG, "XWayland class raw: %s", PWINDOW->m_uSurface.xwayland->_class);
2022-03-24 21:34:24 +01:00
2022-04-02 18:57:09 +02:00
if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr;
2022-03-21 15:17:04 +01:00
g_pCompositor->m_pLastFocus = nullptr;
2022-04-02 18:57:09 +02:00
}
2022-03-21 15:17:04 +01:00
2022-04-10 16:19:49 +02:00
PWINDOW->hyprListener_mapWindow.removeCallback();
PWINDOW->hyprListener_unmapWindow.removeCallback();
PWINDOW->hyprListener_destroyWindow.removeCallback();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
if (PWINDOW->m_pSurfaceTree) {
Debug::log(LOG, "Destroying Subsurface tree of %x in destroyWindow", PWINDOW);
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
PWINDOW->m_pSurfaceTree = nullptr;
}
PWINDOW->m_bReadyToDelete = true;
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_setTitleWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
2022-03-22 17:31:19 +01:00
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
2022-03-24 21:34:24 +01:00
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
2022-04-05 22:28:06 +02:00
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
2022-05-26 21:24:52 +02:00
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
2022-05-29 11:24:42 +02:00
if (PWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
2022-04-05 22:28:06 +02:00
Debug::log(LOG, "Window %x set title to %s", PWINDOW, PWINDOW->m_szTitle.c_str());
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_fullscreenWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
2022-05-20 15:02:51 +02:00
if (!PWINDOW->m_bIsX11) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
2022-06-27 19:08:14 +02:00
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
2022-05-20 15:02:51 +02:00
} else {
2022-06-27 19:08:14 +02:00
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
2022-05-20 15:02:51 +02:00
}
2022-04-07 17:07:42 +02:00
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
2022-03-21 15:17:04 +01:00
}
2022-03-28 22:31:39 +02:00
void Events::listener_activate(void* owner, void* data) {
2022-03-21 15:17:04 +01:00
// TODO
}
2022-03-28 22:31:39 +02:00
void Events::listener_activateX11(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
if (PWINDOW->m_iX11Type == 1 /* Managed */) {
wlr_xwayland_surface_activate(PWINDOW->m_uSurface.xwayland, 1);
}
}
2022-03-28 22:31:39 +02:00
void Events::listener_configureX11(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
2022-03-21 15:17:04 +01:00
2022-04-05 18:29:58 +02:00
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
2022-03-21 15:17:04 +01:00
const auto E = (wlr_xwayland_surface_configure_event*)data;
g_pHyprRenderer->damageWindow(PWINDOW);
2022-03-21 15:17:04 +01:00
2022-04-05 18:29:58 +02:00
if (!PWINDOW->m_bIsFloating) {
2022-04-23 14:16:02 +02:00
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.vec());
2022-04-05 18:29:58 +02:00
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
return;
}
if (!PWINDOW->m_uSurface.xwayland->mapped) {
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
2022-04-05 18:29:58 +02:00
return;
}
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y));
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
2022-04-05 18:29:58 +02:00
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
g_pCompositor->moveWindowToTop(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true;
2022-04-05 18:29:58 +02:00
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
2022-03-21 16:13:43 +01:00
}
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)data;
2022-06-28 12:24:21 +02:00
Debug::log(LOG, "New XWayland Surface created (class %s).", XWSURFACE->_class);
2022-06-28 12:46:32 +02:00
if (XWSURFACE->parent)
Debug::log(LOG, "Window parent data: %s at %x", XWSURFACE->parent->_class, XWSURFACE->parent);
2022-03-24 21:34:24 +01:00
2022-06-30 15:44:26 +02:00
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
2022-03-21 16:13:43 +01:00
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
2022-06-30 15:44:26 +02:00
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
2022-03-28 22:31:39 +02:00
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XWSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_unmapWindow.initCallback(&XWSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window");
2022-03-21 16:13:43 +01:00
}
void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
// A window got opened
const auto XDGSURFACE = (wlr_xdg_surface*)data;
2022-06-28 12:24:21 +02:00
Debug::log(LOG, "New XDG Surface created. (class: %s)", XDGSURFACE->toplevel->app_id);
2022-03-24 21:34:24 +01:00
2022-03-21 16:13:43 +01:00
if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; // TODO: handle?
2022-06-30 15:44:26 +02:00
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
2022-03-21 16:13:43 +01:00
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
2022-03-28 22:31:39 +02:00
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
PNEWWINDOW->hyprListener_unmapWindow.initCallback(&XDGSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XDG Window");
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XDGSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XDG Window");
2022-03-27 22:34:02 +02:00
}
void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
const auto WLRDECO = (wlr_xdg_toplevel_decoration_v1*)data;
wlr_xdg_toplevel_decoration_v1_set_mode(WLRDECO, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}