mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 10:45:59 +01:00
xdg-shell: move to new impl
This commit is contained in:
parent
121d3a7213
commit
0cfdde3d1a
24 changed files with 1352 additions and 421 deletions
|
@ -110,7 +110,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||||
wayland-server wayland-client wayland-cursor wayland-protocols
|
wayland-server wayland-client wayland-cursor wayland-protocols
|
||||||
cairo pango pangocairo pixman-1
|
cairo pango pangocairo pixman-1
|
||||||
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
||||||
hyprwayland-scanner>=0.3.6 hyprlang>=0.3.2 hyprcursor>=0.1.7
|
hyprwayland-scanner>=0.3.7 hyprlang>=0.3.2 hyprcursor>=0.1.7
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||||
|
@ -260,7 +260,6 @@ target_link_libraries(Hyprland
|
||||||
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
|
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
|
||||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true)
|
protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true)
|
||||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
|
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
|
||||||
protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
|
||||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
||||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||||
|
|
||||||
|
@ -292,6 +291,7 @@ protocolNew("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1
|
||||||
protocolNew("staging/ext-session-lock/ext-session-lock-v1.xml" "ext-session-lock-v1" false)
|
protocolNew("staging/ext-session-lock/ext-session-lock-v1.xml" "ext-session-lock-v1" false)
|
||||||
protocolNew("stable/tablet/tablet-v2.xml" "tablet-v2" false)
|
protocolNew("stable/tablet/tablet-v2.xml" "tablet-v2" false)
|
||||||
protocolNew("stable/presentation-time/presentation-time.xml" "presentation-time" false)
|
protocolNew("stable/presentation-time/presentation-time.xml" "presentation-time" false)
|
||||||
|
protocolNew("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
||||||
|
|
||||||
protocolWayland()
|
protocolWayland()
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ new_protocols = [
|
||||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||||
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
||||||
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
||||||
|
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||||
]
|
]
|
||||||
|
|
||||||
wl_protos_src = []
|
wl_protos_src = []
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "protocols/FractionalScale.hpp"
|
#include "protocols/FractionalScale.hpp"
|
||||||
#include "protocols/PointerConstraints.hpp"
|
#include "protocols/PointerConstraints.hpp"
|
||||||
#include "protocols/LayerShell.hpp"
|
#include "protocols/LayerShell.hpp"
|
||||||
|
#include "protocols/XDGShell.hpp"
|
||||||
#include "desktop/LayerSurface.hpp"
|
#include "desktop/LayerSurface.hpp"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -229,8 +230,6 @@ void CCompositor::initServer() {
|
||||||
// wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
|
// wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
|
||||||
wlr_viewporter_create(m_sWLDisplay);
|
wlr_viewporter_create(m_sWLDisplay);
|
||||||
|
|
||||||
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 6);
|
|
||||||
|
|
||||||
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
|
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
|
||||||
if (!m_sWRLDRMLeaseMgr) {
|
if (!m_sWRLDRMLeaseMgr) {
|
||||||
Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager");
|
Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager");
|
||||||
|
@ -253,7 +252,6 @@ void CCompositor::initServer() {
|
||||||
|
|
||||||
void CCompositor::initAllSignals() {
|
void CCompositor::initAllSignals() {
|
||||||
addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend");
|
addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend");
|
||||||
addWLSignal(&m_sWLRXDGShell->events.new_toplevel, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell");
|
|
||||||
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
|
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
|
||||||
// addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &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.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat");
|
||||||
|
@ -271,7 +269,6 @@ void CCompositor::initAllSignals() {
|
||||||
|
|
||||||
void CCompositor::removeAllSignals() {
|
void CCompositor::removeAllSignals() {
|
||||||
removeWLSignal(&Events::listen_newOutput);
|
removeWLSignal(&Events::listen_newOutput);
|
||||||
removeWLSignal(&Events::listen_newXDGToplevel);
|
|
||||||
removeWLSignal(&Events::listen_newInput);
|
removeWLSignal(&Events::listen_newInput);
|
||||||
removeWLSignal(&Events::listen_requestSetSel);
|
removeWLSignal(&Events::listen_requestSetSel);
|
||||||
removeWLSignal(&Events::listen_requestDrag);
|
removeWLSignal(&Events::listen_requestDrag);
|
||||||
|
@ -805,22 +802,28 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW p
|
||||||
|
|
||||||
RASSERT(!pWindow->m_bIsX11, "Cannot call vectorWindowToSurface on an X11 window!");
|
RASSERT(!pWindow->m_bIsX11, "Cannot call vectorWindowToSurface on an X11 window!");
|
||||||
|
|
||||||
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
double subx, suby;
|
||||||
|
|
||||||
double subx, suby;
|
CBox geom = pWindow->m_pXDGSurface->current.geometry;
|
||||||
|
|
||||||
// calc for oversized windows... fucking bullshit, again.
|
// try popups first
|
||||||
CBox geom;
|
const auto PPOPUP = pWindow->m_pPopupHead->at(pos);
|
||||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
|
||||||
geom.applyFromWlr();
|
|
||||||
|
|
||||||
const auto PFOUND =
|
wlr_surface* found = PPOPUP ? PPOPUP->m_sWLSurface.wlr() : nullptr;
|
||||||
wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx, &suby);
|
|
||||||
|
|
||||||
if (PFOUND) {
|
if (!PPOPUP)
|
||||||
|
found = wlr_surface_surface_at(pWindow->m_pWLSurface.wlr(), pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx,
|
||||||
|
&suby);
|
||||||
|
else {
|
||||||
|
const auto OFF = PPOPUP->coordsRelativeToParent();
|
||||||
|
subx = pos.x - OFF.x + geom.x - pWindow->m_vRealPosition.goal().x;
|
||||||
|
suby = pos.y - OFF.y + geom.y - pWindow->m_vRealPosition.goal().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
sl.x = subx;
|
sl.x = subx;
|
||||||
sl.y = suby;
|
sl.y = suby;
|
||||||
return PFOUND;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
sl.x = pos.x - pWindow->m_vRealPosition.value().x;
|
sl.x = pos.x - pWindow->m_vRealPosition.value().x;
|
||||||
|
@ -829,7 +832,7 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, PHLWINDOW p
|
||||||
sl.x += geom.x;
|
sl.x += geom.x;
|
||||||
sl.y += geom.y;
|
sl.y += geom.y;
|
||||||
|
|
||||||
return PSURFACE->surface;
|
return pWindow->m_pWLSurface.wlr();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, wlr_surface* pSurface) {
|
Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindow, wlr_surface* pSurface) {
|
||||||
|
@ -839,12 +842,14 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
|
||||||
if (pWindow->m_bIsX11)
|
if (pWindow->m_bIsX11)
|
||||||
return vec - pWindow->m_vRealPosition.goal();
|
return vec - pWindow->m_vRealPosition.goal();
|
||||||
|
|
||||||
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
const auto PPOPUP = pWindow->m_pPopupHead->at(vec);
|
||||||
|
if (PPOPUP)
|
||||||
|
return vec - PPOPUP->coordsGlobal();
|
||||||
|
|
||||||
std::tuple<wlr_surface*, int, int> iterData = {pSurface, -1337, -1337};
|
std::tuple<wlr_surface*, int, int> iterData = {pSurface, -1337, -1337};
|
||||||
|
|
||||||
wlr_xdg_surface_for_each_surface(
|
wlr_surface_for_each_surface(
|
||||||
PSURFACE,
|
pWindow->m_pWLSurface.wlr(),
|
||||||
[](wlr_surface* surf, int x, int y, void* data) {
|
[](wlr_surface* surf, int x, int y, void* data) {
|
||||||
const auto PDATA = (std::tuple<wlr_surface*, int, int>*)data;
|
const auto PDATA = (std::tuple<wlr_surface*, int, int>*)data;
|
||||||
if (surf == std::get<0>(*PDATA)) {
|
if (surf == std::get<0>(*PDATA)) {
|
||||||
|
@ -854,9 +859,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
|
||||||
},
|
},
|
||||||
&iterData);
|
&iterData);
|
||||||
|
|
||||||
CBox geom = {};
|
CBox geom = pWindow->m_pXDGSurface->current.geometry;
|
||||||
wlr_xdg_surface_get_geometry(PSURFACE, geom.pWlr());
|
|
||||||
geom.applyFromWlr();
|
|
||||||
|
|
||||||
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
||||||
return vec - pWindow->m_vRealPosition.goal();
|
return vec - pWindow->m_vRealPosition.goal();
|
||||||
|
@ -993,7 +996,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, wlr_surface* pSurface) {
|
||||||
pWindow->m_bIsUrgent = false;
|
pWindow->m_bIsUrgent = false;
|
||||||
|
|
||||||
// Send an event
|
// Send an event
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle});
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", pWindow->m_szClass + "," + pWindow->m_szTitle});
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)pWindow.get())});
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)pWindow.get())});
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("activeWindow", pWindow);
|
EMIT_HOOK_EVENT("activeWindow", pWindow);
|
||||||
|
@ -2310,7 +2313,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case MODE_CLASS_REGEX: {
|
case MODE_CLASS_REGEX: {
|
||||||
const auto windowClass = g_pXWaylandManager->getAppIDClass(w);
|
const auto windowClass = w->m_szClass;
|
||||||
if (!std::regex_search(windowClass, regexCheck))
|
if (!std::regex_search(windowClass, regexCheck))
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
@ -2322,7 +2325,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MODE_TITLE_REGEX: {
|
case MODE_TITLE_REGEX: {
|
||||||
const auto windowTitle = g_pXWaylandManager->getTitle(w);
|
const auto windowTitle = w->m_szTitle;
|
||||||
if (!std::regex_search(windowTitle, regexCheck))
|
if (!std::regex_search(windowTitle, regexCheck))
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -50,7 +50,6 @@ class CCompositor {
|
||||||
wlr_subcompositor* m_sWLRSubCompositor;
|
wlr_subcompositor* m_sWLRSubCompositor;
|
||||||
wlr_drm* m_sWRLDRM;
|
wlr_drm* m_sWRLDRM;
|
||||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||||
wlr_xdg_shell* m_sWLRXDGShell;
|
|
||||||
wlr_egl* m_sWLREGL;
|
wlr_egl* m_sWLREGL;
|
||||||
int m_iDRMFD;
|
int m_iDRMFD;
|
||||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
||||||
|
|
|
@ -1042,8 +1042,8 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
|
||||||
|
|
||||||
std::vector<SWindowRule> returns;
|
std::vector<SWindowRule> returns;
|
||||||
|
|
||||||
std::string title = g_pXWaylandManager->getTitle(pWindow);
|
std::string title = pWindow->m_szTitle;
|
||||||
std::string appidclass = g_pXWaylandManager->getAppIDClass(pWindow);
|
std::string appidclass = pWindow->m_szClass;
|
||||||
|
|
||||||
Debug::log(LOG, "Searching for matching rules for {} (title: {})", appidclass, title);
|
Debug::log(LOG, "Searching for matching rules for {} (title: {})", appidclass, title);
|
||||||
|
|
||||||
|
|
|
@ -210,10 +210,10 @@ static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||||
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||||
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
||||||
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (int64_t)w->m_iMonitorID,
|
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (int64_t)w->m_iMonitorID,
|
||||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w)), escapeJSONStrings(g_pXWaylandManager->getTitle(w)), escapeJSONStrings(w->m_szInitialClass),
|
escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(),
|
||||||
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
|
((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (w->m_bIsFullscreen ? "true" : "false"),
|
||||||
(w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0),
|
(w->m_bIsFullscreen ? (w->m_pWorkspace ? (int)w->m_pWorkspace->m_efFullscreenMode : 0) : 0), w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format),
|
||||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||||
} else {
|
} else {
|
||||||
return std::format("Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
return std::format("Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||||
|
@ -221,8 +221,8 @@ static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||||
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
|
||||||
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
||||||
(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w),
|
(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, w->m_szClass, w->m_szTitle, w->m_szInitialClass,
|
||||||
g_pXWaylandManager->getTitle(w), w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen,
|
w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen,
|
||||||
(w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), (int)w->m_bFakeFullscreenState, getGroupedData(w, format),
|
(w->m_bIsFullscreen ? (w->m_pWorkspace ? w->m_pWorkspace->m_efFullscreenMode : 0) : 0), (int)w->m_bFakeFullscreenState, getGroupedData(w, format),
|
||||||
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
|
CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
|
||||||
|
@ -12,14 +13,13 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) {
|
||||||
initAllSignals();
|
initAllSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR(popup) {
|
CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner), m_pResource(popup) {
|
||||||
m_pWLR->base->data = this;
|
m_sWLSurface.assign(popup->surface->surface, this);
|
||||||
m_sWLSurface.assign(popup->base->surface, this);
|
|
||||||
|
|
||||||
m_pLayerOwner = pOwner->m_pLayerOwner;
|
m_pLayerOwner = pOwner->m_pLayerOwner;
|
||||||
m_pWindowOwner = pOwner->m_pWindowOwner;
|
m_pWindowOwner = pOwner->m_pWindowOwner;
|
||||||
|
|
||||||
m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height};
|
m_vLastSize = popup->surface->current.geometry.size();
|
||||||
unconstrain();
|
unconstrain();
|
||||||
|
|
||||||
initAllSignals();
|
initAllSignals();
|
||||||
|
@ -27,71 +27,32 @@ CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR
|
||||||
|
|
||||||
CPopup::~CPopup() {
|
CPopup::~CPopup() {
|
||||||
m_sWLSurface.unassign();
|
m_sWLSurface.unassign();
|
||||||
if (m_pWLR)
|
|
||||||
m_pWLR->base->data = nullptr;
|
|
||||||
|
|
||||||
hyprListener_commitPopup.removeCallback();
|
|
||||||
hyprListener_repositionPopup.removeCallback();
|
|
||||||
hyprListener_mapPopup.removeCallback();
|
|
||||||
hyprListener_unmapPopup.removeCallback();
|
|
||||||
hyprListener_newPopup.removeCallback();
|
|
||||||
hyprListener_destroyPopup.removeCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onNewPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onNewPopup((wlr_xdg_popup*)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onMapPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onDestroyPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onUnmapPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onUnmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onCommitPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onRepositionPopup(void* owner, void* data) {
|
|
||||||
const auto POPUP = (CPopup*)owner;
|
|
||||||
POPUP->onReposition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::initAllSignals() {
|
void CPopup::initAllSignals() {
|
||||||
|
|
||||||
if (!m_pWLR) {
|
if (!m_pResource) {
|
||||||
if (!m_pWindowOwner.expired())
|
if (!m_pWindowOwner.expired())
|
||||||
hyprListener_newPopup.initCallback(&m_pWindowOwner->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head");
|
listeners.newPopup = m_pWindowOwner->m_pXDGSurface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<SP<CXDGPopupResource>>(d)); });
|
||||||
else if (!m_pLayerOwner.expired())
|
else if (!m_pLayerOwner.expired())
|
||||||
listeners.newPopup = m_pLayerOwner->layerSurface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<wlr_xdg_popup*>(d)); });
|
listeners.newPopup = m_pLayerOwner->layerSurface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<SP<CXDGPopupResource>>(d)); });
|
||||||
else
|
else
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hyprListener_repositionPopup.initCallback(&m_pWLR->events.reposition, ::onRepositionPopup, this, "CPopup");
|
listeners.reposition = m_pResource->events.reposition.registerListener([this](std::any d) { this->onReposition(); });
|
||||||
hyprListener_destroyPopup.initCallback(&m_pWLR->events.destroy, ::onDestroyPopup, this, "CPopup");
|
listeners.map = m_pResource->surface->events.map.registerListener([this](std::any d) { this->onMap(); });
|
||||||
hyprListener_mapPopup.initCallback(&m_sWLSurface.wlr()->events.map, ::onMapPopup, this, "CPopup");
|
listeners.unmap = m_pResource->surface->events.unmap.registerListener([this](std::any d) { this->onUnmap(); });
|
||||||
hyprListener_unmapPopup.initCallback(&m_sWLSurface.wlr()->events.unmap, ::onUnmapPopup, this, "CPopup");
|
listeners.destroy = m_pResource->surface->events.destroy.registerListener([this](std::any d) { this->onDestroy(); });
|
||||||
hyprListener_commitPopup.initCallback(&m_sWLSurface.wlr()->events.commit, ::onCommitPopup, this, "CPopup");
|
listeners.commit = m_pResource->surface->events.commit.registerListener([this](std::any d) { this->onCommit(); });
|
||||||
hyprListener_newPopup.initCallback(&m_pWLR->base->events.new_popup, ::onNewPopup, this, "CPopup");
|
listeners.newPopup = m_pResource->surface->events.newPopup.registerListener([this](std::any d) { this->onNewPopup(std::any_cast<SP<CXDGPopupResource>>(d)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onNewPopup(wlr_xdg_popup* popup) {
|
void CPopup::onNewPopup(SP<CXDGPopupResource> popup) {
|
||||||
const auto POPUP = m_vChildren.emplace_back(std::make_unique<CPopup>(popup, this)).get();
|
const auto POPUP = m_vChildren.emplace_back(std::make_unique<CPopup>(popup, this)).get();
|
||||||
Debug::log(LOG, "New popup at wlr {:x} and hl {:x}", (uintptr_t)popup, (uintptr_t)POPUP);
|
Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onDestroy() {
|
void CPopup::onDestroy() {
|
||||||
|
@ -104,7 +65,7 @@ void CPopup::onDestroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onMap() {
|
void CPopup::onMap() {
|
||||||
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
||||||
const auto COORDS = coordsGlobal();
|
const auto COORDS = coordsGlobal();
|
||||||
|
|
||||||
CBox box;
|
CBox box;
|
||||||
|
@ -126,7 +87,9 @@ void CPopup::onMap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onUnmap() {
|
void CPopup::onUnmap() {
|
||||||
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
if (!m_pResource || !m_pResource->surface)
|
||||||
|
return;
|
||||||
|
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
||||||
const auto COORDS = coordsGlobal();
|
const auto COORDS = coordsGlobal();
|
||||||
|
|
||||||
CBox box;
|
CBox box;
|
||||||
|
@ -140,16 +103,27 @@ void CPopup::onUnmap() {
|
||||||
|
|
||||||
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
||||||
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
|
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
|
||||||
|
|
||||||
|
// damage all children
|
||||||
|
breadthfirst(
|
||||||
|
[this](CPopup* p, void* data) {
|
||||||
|
if (!p->m_pResource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto box = CBox{p->coordsGlobal(), p->size()};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPopup::onCommit(bool ignoreSiblings) {
|
void CPopup::onCommit(bool ignoreSiblings) {
|
||||||
if (m_pWLR->base->initial_commit) {
|
if (m_pResource->surface->initialCommit) {
|
||||||
wlr_xdg_surface_schedule_configure(m_pWLR->base);
|
m_pResource->surface->scheduleConfigure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_pWindowOwner.expired() && (!m_pWindowOwner->m_bIsMapped || !m_pWindowOwner->m_pWorkspace->m_bVisible)) {
|
if (!m_pWindowOwner.expired() && (!m_pWindowOwner->m_bIsMapped || !m_pWindowOwner->m_pWorkspace->m_bVisible)) {
|
||||||
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
||||||
|
|
||||||
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
|
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
|
||||||
if (*PLOGDAMAGE)
|
if (*PLOGDAMAGE)
|
||||||
|
@ -157,16 +131,17 @@ void CPopup::onCommit(bool ignoreSiblings) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_pWLR->base->surface->mapped)
|
if (!m_pResource->surface->mapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto COORDS = coordsGlobal();
|
const auto COORDS = coordsGlobal();
|
||||||
const auto COORDSLOCAL = coordsRelativeToParent();
|
const auto COORDSLOCAL = coordsRelativeToParent();
|
||||||
|
|
||||||
if (m_vLastSize != Vector2D{m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height} || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) {
|
if (m_vLastSize != Vector2D{m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height} || m_bRequestedReposition ||
|
||||||
|
m_vLastPos != COORDSLOCAL) {
|
||||||
CBox box = {localToGlobal(m_vLastPos), m_vLastSize};
|
CBox box = {localToGlobal(m_vLastPos), m_vLastSize};
|
||||||
g_pHyprRenderer->damageBox(&box);
|
g_pHyprRenderer->damageBox(&box);
|
||||||
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
|
m_vLastSize = {m_pResource->surface->surface->current.width, m_pResource->surface->surface->current.height};
|
||||||
box = {COORDS, m_vLastSize};
|
box = {COORDS, m_vLastSize};
|
||||||
g_pHyprRenderer->damageBox(&box);
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
||||||
|
@ -202,20 +177,25 @@ void CPopup::unconstrain() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
wlr_xdg_popup_unconstrain_from_box(m_pWLR, box.pWlr());
|
m_pResource->applyPositioning(box, COORDS - PMONITOR->vecPosition);
|
||||||
|
wlr_surface_send_enter(m_pResource->surface->surface, PMONITOR->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CPopup::coordsRelativeToParent() {
|
Vector2D CPopup::coordsRelativeToParent() {
|
||||||
Vector2D offset;
|
Vector2D offset;
|
||||||
|
|
||||||
CPopup* current = this;
|
if (!m_pResource)
|
||||||
|
return {};
|
||||||
|
|
||||||
offset -= {m_pWLR->base->current.geometry.x, m_pWLR->base->current.geometry.y};
|
CPopup* current = this;
|
||||||
|
offset -= current->m_pResource->surface->current.geometry.pos();
|
||||||
|
|
||||||
while (current->m_pParent) {
|
offset -= m_pResource->surface->current.geometry.pos();
|
||||||
|
|
||||||
|
while (current->m_pParent && current->m_pResource) {
|
||||||
|
|
||||||
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
|
||||||
offset += {current->m_pWLR->current.geometry.x, current->m_pWLR->current.geometry.y};
|
offset += current->m_pResource->geometry.pos();
|
||||||
|
|
||||||
current = current->m_pParent;
|
current = current->m_pParent;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +289,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
|
||||||
breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
|
breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
|
||||||
|
|
||||||
for (auto& p : popups | std::views::reverse) {
|
for (auto& p : popups | std::views::reverse) {
|
||||||
if (!p->m_pWLR)
|
if (!p->m_pResource)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!allowsInput) {
|
if (!allowsInput) {
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "Subsurface.hpp"
|
#include "Subsurface.hpp"
|
||||||
#include "../helpers/signal/Listener.hpp"
|
#include "../helpers/signal/Listener.hpp"
|
||||||
|
|
||||||
|
class CXDGPopupResource;
|
||||||
|
|
||||||
class CPopup {
|
class CPopup {
|
||||||
public:
|
public:
|
||||||
// dummy head nodes
|
// dummy head nodes
|
||||||
|
@ -12,7 +14,7 @@ class CPopup {
|
||||||
CPopup(PHLLS pOwner);
|
CPopup(PHLLS pOwner);
|
||||||
|
|
||||||
// real nodes
|
// real nodes
|
||||||
CPopup(wlr_xdg_popup* popup, CPopup* pOwner);
|
CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner);
|
||||||
|
|
||||||
~CPopup();
|
~CPopup();
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ class CPopup {
|
||||||
|
|
||||||
Vector2D size();
|
Vector2D size();
|
||||||
|
|
||||||
void onNewPopup(wlr_xdg_popup* popup);
|
void onNewPopup(SP<CXDGPopupResource> popup);
|
||||||
void onDestroy();
|
void onDestroy();
|
||||||
void onMap();
|
void onMap();
|
||||||
void onUnmap();
|
void onUnmap();
|
||||||
|
@ -45,31 +47,28 @@ class CPopup {
|
||||||
PHLLSREF m_pLayerOwner;
|
PHLLSREF m_pLayerOwner;
|
||||||
|
|
||||||
// T2 owners
|
// T2 owners
|
||||||
CPopup* m_pParent = nullptr;
|
CPopup* m_pParent = nullptr;
|
||||||
|
|
||||||
wlr_xdg_popup* m_pWLR = nullptr;
|
WP<CXDGPopupResource> m_pResource;
|
||||||
|
|
||||||
Vector2D m_vLastSize = {};
|
Vector2D m_vLastSize = {};
|
||||||
Vector2D m_vLastPos = {};
|
Vector2D m_vLastPos = {};
|
||||||
|
|
||||||
bool m_bRequestedReposition = false;
|
bool m_bRequestedReposition = false;
|
||||||
|
|
||||||
bool m_bInert = false;
|
bool m_bInert = false;
|
||||||
|
|
||||||
//
|
//
|
||||||
std::vector<std::unique_ptr<CPopup>> m_vChildren;
|
std::vector<std::unique_ptr<CPopup>> m_vChildren;
|
||||||
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
|
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
|
||||||
|
|
||||||
// signals
|
|
||||||
DYNLISTENER(newPopup);
|
|
||||||
DYNLISTENER(destroyPopup);
|
|
||||||
DYNLISTENER(mapPopup);
|
|
||||||
DYNLISTENER(unmapPopup);
|
|
||||||
DYNLISTENER(commitPopup);
|
|
||||||
DYNLISTENER(repositionPopup);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
CHyprSignalListener newPopup;
|
CHyprSignalListener newPopup;
|
||||||
|
CHyprSignalListener destroy;
|
||||||
|
CHyprSignalListener map;
|
||||||
|
CHyprSignalListener unmap;
|
||||||
|
CHyprSignalListener commit;
|
||||||
|
CHyprSignalListener reposition;
|
||||||
} listeners;
|
} listeners;
|
||||||
|
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include <any>
|
#include <any>
|
||||||
#include "../managers/TokenManager.hpp"
|
#include "../managers/TokenManager.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
PHLWINDOW CWindow::create() {
|
PHLWINDOW CWindow::create() {
|
||||||
PHLWINDOW pWindow = SP<CWindow>(new CWindow);
|
PHLWINDOW pWindow = SP<CWindow>(new CWindow);
|
||||||
|
@ -27,6 +28,39 @@ PHLWINDOW CWindow::create() {
|
||||||
return pWindow;
|
return pWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
||||||
|
PHLWINDOW pWindow = SP<CWindow>(new CWindow(resource));
|
||||||
|
|
||||||
|
pWindow->m_pSelf = pWindow;
|
||||||
|
resource->toplevel->window = pWindow;
|
||||||
|
|
||||||
|
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
|
||||||
|
pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
|
||||||
|
pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
||||||
|
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
|
||||||
|
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
||||||
|
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
||||||
|
|
||||||
|
pWindow->m_pWLSurface.assign(pWindow->m_pXDGSurface->surface, pWindow);
|
||||||
|
|
||||||
|
return pWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_pXDGSurface(resource) {
|
||||||
|
listeners.map = m_pXDGSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); });
|
||||||
|
listeners.ack = m_pXDGSurface->events.ack.registerListener([this](std::any d) { onAck(std::any_cast<uint32_t>(d)); });
|
||||||
|
listeners.unmap = m_pXDGSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
|
||||||
|
listeners.destroy = m_pXDGSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); });
|
||||||
|
listeners.commit = m_pXDGSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); });
|
||||||
|
listeners.updateState = m_pXDGSurface->toplevel->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); });
|
||||||
|
listeners.updateMetadata = m_pXDGSurface->toplevel->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); });
|
||||||
|
}
|
||||||
|
|
||||||
CWindow::CWindow() {
|
CWindow::CWindow() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -74,21 +108,24 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||||
|
|
||||||
if (m_pWLSurface.exists() && !m_bIsX11) {
|
if (m_pWLSurface.exists() && !m_bIsX11 && m_pPopupHead) {
|
||||||
CBox surfaceExtents = {0, 0, 0, 0};
|
CBox surfaceExtents = {0, 0, 0, 0};
|
||||||
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
||||||
wlr_xdg_surface_for_each_popup_surface(
|
m_pPopupHead->breadthfirst(
|
||||||
m_uSurface.xdg,
|
[](CPopup* popup, void* data) {
|
||||||
[](wlr_surface* surf, int sx, int sy, void* data) {
|
if (!popup->m_sWLSurface.wlr())
|
||||||
|
return;
|
||||||
|
|
||||||
CBox* pSurfaceExtents = (CBox*)data;
|
CBox* pSurfaceExtents = (CBox*)data;
|
||||||
if (sx < pSurfaceExtents->x)
|
CBox surf = CBox{popup->coordsRelativeToParent(), popup->size()};
|
||||||
pSurfaceExtents->x = sx;
|
if (surf.x < pSurfaceExtents->x)
|
||||||
if (sy < pSurfaceExtents->y)
|
pSurfaceExtents->x = surf.x;
|
||||||
pSurfaceExtents->y = sy;
|
if (surf.y < pSurfaceExtents->y)
|
||||||
if (sx + surf->current.width > pSurfaceExtents->width)
|
pSurfaceExtents->y = surf.y;
|
||||||
pSurfaceExtents->width = sx + surf->current.width - pSurfaceExtents->x;
|
if (surf.x + surf.w > pSurfaceExtents->width)
|
||||||
if (sy + surf->current.height > pSurfaceExtents->height)
|
pSurfaceExtents->width = surf.x + surf.w - pSurfaceExtents->x;
|
||||||
pSurfaceExtents->height = sy + surf->current.height - pSurfaceExtents->y;
|
if (surf.y + surf.h > pSurfaceExtents->height)
|
||||||
|
pSurfaceExtents->height = surf.y + surf.h - pSurfaceExtents->y;
|
||||||
},
|
},
|
||||||
&surfaceExtents);
|
&surfaceExtents);
|
||||||
|
|
||||||
|
@ -258,10 +295,10 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor
|
||||||
pid_t CWindow::getPID() {
|
pid_t CWindow::getPID() {
|
||||||
pid_t PID = -1;
|
pid_t PID = -1;
|
||||||
if (!m_bIsX11) {
|
if (!m_bIsX11) {
|
||||||
if (!m_uSurface.xdg)
|
if (!m_pXDGSurface || !m_pXDGSurface->owner /* happens at unmap */)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
wl_client_get_credentials(m_pXDGSurface->owner->client(), &PID, nullptr, nullptr);
|
||||||
} else {
|
} else {
|
||||||
if (!m_uSurface.xwayland)
|
if (!m_uSurface.xwayland)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -511,8 +548,8 @@ void CWindow::onMap() {
|
||||||
|
|
||||||
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
|
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
|
||||||
|
|
||||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
if (m_bIsX11)
|
||||||
"CWindow");
|
hyprListener_unmapWindow.initCallback(&m_uSurface.xwayland->surface->events.unmap, &Events::listener_unmapWindow, this, "CWindow");
|
||||||
|
|
||||||
m_vReportedSize = m_vPendingReportedSize;
|
m_vReportedSize = m_vPendingReportedSize;
|
||||||
m_bAnimatingIn = true;
|
m_bAnimatingIn = true;
|
||||||
|
@ -793,26 +830,14 @@ bool CWindow::isInCurvedCorner(double x, double y) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
|
|
||||||
const auto DATA = (SExtensionFindingData*)data;
|
|
||||||
|
|
||||||
CBox box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
|
||||||
|
|
||||||
if (box.containsPoint(DATA->vec))
|
|
||||||
*DATA->found = surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks if the wayland window has a popup at pos
|
// checks if the wayland window has a popup at pos
|
||||||
bool CWindow::hasPopupAt(const Vector2D& pos) {
|
bool CWindow::hasPopupAt(const Vector2D& pos) {
|
||||||
if (m_bIsX11)
|
if (m_bIsX11)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wlr_surface* resultSurf = nullptr;
|
CPopup* popup = m_pPopupHead->at(pos);
|
||||||
Vector2D origin = m_vRealPosition.value();
|
|
||||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
|
||||||
wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data);
|
|
||||||
|
|
||||||
return resultSurf;
|
return popup && popup->m_sWLSurface.wlr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::applyGroupRules() {
|
void CWindow::applyGroupRules() {
|
||||||
|
@ -1096,11 +1121,11 @@ bool CWindow::opaque() {
|
||||||
if (m_bIsX11)
|
if (m_bIsX11)
|
||||||
return !m_uSurface.xwayland->has_alpha;
|
return !m_uSurface.xwayland->has_alpha;
|
||||||
|
|
||||||
if (m_uSurface.xdg->surface->opaque)
|
if (m_pXDGSurface->surface->opaque)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const auto EXTENTS = pixman_region32_extents(&m_uSurface.xdg->surface->opaque_region);
|
const auto EXTENTS = pixman_region32_extents(&m_pXDGSurface->surface->opaque_region);
|
||||||
if (EXTENTS->x2 - EXTENTS->x1 >= m_uSurface.xdg->surface->current.buffer_width && EXTENTS->y2 - EXTENTS->y1 >= m_uSurface.xdg->surface->current.buffer_height)
|
if (EXTENTS->x2 - EXTENTS->x1 >= m_pXDGSurface->surface->current.buffer_width && EXTENTS->y2 - EXTENTS->y1 >= m_pXDGSurface->surface->current.buffer_height)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1162,10 +1187,10 @@ void CWindow::setSuspended(bool suspend) {
|
||||||
if (suspend == m_bSuspended)
|
if (suspend == m_bSuspended)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_bIsX11)
|
if (m_bIsX11 || !m_pXDGSurface->toplevel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_xdg_toplevel_set_suspended(m_uSurface.xdg->toplevel, suspend);
|
m_pXDGSurface->toplevel->setSuspeneded(suspend);
|
||||||
m_bSuspended = suspend;
|
m_bSuspended = suspend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,12 +1246,21 @@ void CWindow::onWorkspaceAnimUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int CWindow::popupsCount() {
|
int CWindow::popupsCount() {
|
||||||
|
if (m_bIsX11)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int no = -1;
|
||||||
|
m_pPopupHead->breadthfirst([](CPopup* p, void* d) { *((int*)d) += 1; }, &no);
|
||||||
|
return no;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CWindow::surfacesCount() {
|
||||||
if (m_bIsX11)
|
if (m_bIsX11)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int no = 0;
|
int no = 0;
|
||||||
wlr_xdg_surface_for_each_popup_surface(
|
wlr_surface_for_each_surface(
|
||||||
m_uSurface.xdg, [](wlr_surface* s, int x, int y, void* data) { *(int*)data += 1; }, &no);
|
m_pWLSurface.wlr(), [](wlr_surface* surf, int x, int y, void* data) { *((int*)data) += 1; }, &no);
|
||||||
return no;
|
return no;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,6 +1312,9 @@ std::unordered_map<std::string, std::string> CWindow::getEnv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::activate(bool force) {
|
void CWindow::activate(bool force) {
|
||||||
|
if (g_pCompositor->m_pLastWindow == m_pSelf)
|
||||||
|
return;
|
||||||
|
|
||||||
static auto PFOCUSONACTIVATE = CConfigValue<Hyprlang::INT>("misc:focus_on_activate");
|
static auto PFOCUSONACTIVATE = CConfigValue<Hyprlang::INT>("misc:focus_on_activate");
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)this)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)this)});
|
||||||
|
@ -1295,3 +1332,98 @@ void CWindow::activate(bool force) {
|
||||||
g_pCompositor->focusWindow(m_pSelf.lock());
|
g_pCompositor->focusWindow(m_pSelf.lock());
|
||||||
g_pCompositor->warpCursorTo(middle());
|
g_pCompositor->warpCursorTo(middle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindow::onUpdateState() {
|
||||||
|
if (!m_pXDGSurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_pXDGSurface->toplevel->state.requestsFullscreen) {
|
||||||
|
bool fs = m_pXDGSurface->toplevel->state.requestsFullscreen.value();
|
||||||
|
|
||||||
|
if (fs != m_bIsFullscreen && m_pXDGSurface->mapped)
|
||||||
|
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_FULL);
|
||||||
|
|
||||||
|
if (!m_pXDGSurface->mapped)
|
||||||
|
m_bWantsInitialFullscreen = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pXDGSurface->toplevel->state.requestsMaximize) {
|
||||||
|
bool fs = m_pXDGSurface->toplevel->state.requestsMaximize.value();
|
||||||
|
|
||||||
|
if (fs != m_bIsFullscreen && m_pXDGSurface->mapped)
|
||||||
|
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_MAXIMIZED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::onUpdateMeta() {
|
||||||
|
const auto NEWTITLE = fetchTitle();
|
||||||
|
|
||||||
|
if (m_szTitle != NEWTITLE) {
|
||||||
|
m_szTitle = NEWTITLE;
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)this)});
|
||||||
|
EMIT_HOOK_EVENT("windowTitle", m_pSelf.lock());
|
||||||
|
|
||||||
|
if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", m_szClass + "," + m_szTitle});
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)this)});
|
||||||
|
EMIT_HOOK_EVENT("activeWindow", m_pSelf.lock());
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDynamicRules();
|
||||||
|
g_pCompositor->updateWindowAnimatedDecorationValues(m_pSelf.lock());
|
||||||
|
updateToplevel();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Window {:x} set title to {}", (uintptr_t)this, m_szTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto NEWCLASS = fetchClass();
|
||||||
|
if (m_szClass != NEWCLASS) {
|
||||||
|
m_szClass = NEWCLASS;
|
||||||
|
|
||||||
|
if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", m_szClass + "," + m_szTitle});
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)this)});
|
||||||
|
EMIT_HOOK_EVENT("activeWindow", m_pSelf.lock());
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDynamicRules();
|
||||||
|
g_pCompositor->updateWindowAnimatedDecorationValues(m_pSelf.lock());
|
||||||
|
updateToplevel();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Window {:x} set class to {}", (uintptr_t)this, m_szClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CWindow::fetchTitle() {
|
||||||
|
if (!m_bIsX11) {
|
||||||
|
if (m_pXDGSurface && m_pXDGSurface->toplevel)
|
||||||
|
return m_pXDGSurface->toplevel->state.title;
|
||||||
|
} else {
|
||||||
|
if (m_uSurface.xwayland && m_uSurface.xwayland->title)
|
||||||
|
return m_uSurface.xwayland->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CWindow::fetchClass() {
|
||||||
|
if (!m_bIsX11) {
|
||||||
|
if (m_pXDGSurface && m_pXDGSurface->toplevel)
|
||||||
|
return m_pXDGSurface->toplevel->state.appid;
|
||||||
|
} else {
|
||||||
|
if (m_uSurface.xwayland && m_uSurface.xwayland->_class)
|
||||||
|
return m_uSurface.xwayland->_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::onAck(uint32_t serial) {
|
||||||
|
const auto SERIAL = std::find_if(m_vPendingSizeAcks.rbegin(), m_vPendingSizeAcks.rend(), [serial](const auto& e) { return e.first == serial; });
|
||||||
|
|
||||||
|
if (SERIAL == m_vPendingSizeAcks.rend())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pPendingSizeAck = *SERIAL;
|
||||||
|
std::erase_if(m_vPendingSizeAcks, [&](const auto& el) { return el.first <= SERIAL->first; });
|
||||||
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
#include "DesktopTypes.hpp"
|
#include "DesktopTypes.hpp"
|
||||||
#include "../helpers/signal/Signal.hpp"
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
|
class CXDGSurfaceResource;
|
||||||
|
|
||||||
enum eIdleInhibitMode {
|
enum eIdleInhibitMode {
|
||||||
IDLEINHIBIT_NONE = 0,
|
IDLEINHIBIT_NONE = 0,
|
||||||
IDLEINHIBIT_ALWAYS,
|
IDLEINHIBIT_ALWAYS,
|
||||||
|
@ -196,9 +198,12 @@ struct SInitialWorkspaceToken {
|
||||||
|
|
||||||
class CWindow {
|
class CWindow {
|
||||||
public:
|
public:
|
||||||
|
static PHLWINDOW create(SP<CXDGSurfaceResource>);
|
||||||
|
// xwl
|
||||||
static PHLWINDOW create();
|
static PHLWINDOW create();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CWindow(SP<CXDGSurfaceResource> resource);
|
||||||
CWindow();
|
CWindow();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -233,9 +238,9 @@ class CWindow {
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
wlr_xdg_surface* xdg;
|
|
||||||
wlr_xwayland_surface* xwayland;
|
wlr_xwayland_surface* xwayland;
|
||||||
} m_uSurface;
|
} m_uSurface;
|
||||||
|
WP<CXDGSurfaceResource> m_pXDGSurface;
|
||||||
|
|
||||||
// this is the position and size of the "bounding box"
|
// this is the position and size of the "bounding box"
|
||||||
Vector2D m_vPosition = Vector2D(0, 0);
|
Vector2D m_vPosition = Vector2D(0, 0);
|
||||||
|
@ -271,6 +276,7 @@ class CWindow {
|
||||||
bool m_bWasMaximized = false;
|
bool m_bWasMaximized = false;
|
||||||
uint64_t m_iMonitorID = -1;
|
uint64_t m_iMonitorID = -1;
|
||||||
std::string m_szTitle = "";
|
std::string m_szTitle = "";
|
||||||
|
std::string m_szClass = "";
|
||||||
std::string m_szInitialTitle = "";
|
std::string m_szInitialTitle = "";
|
||||||
std::string m_szInitialClass = "";
|
std::string m_szInitialClass = "";
|
||||||
PHLWORKSPACE m_pWorkspace;
|
PHLWORKSPACE m_pWorkspace;
|
||||||
|
@ -385,7 +391,7 @@ class CWindow {
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const CWindow& rhs) {
|
bool operator==(const CWindow& rhs) {
|
||||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
return m_pXDGSurface == rhs.m_pXDGSurface && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
||||||
m_bFadingOut == rhs.m_bFadingOut;
|
m_bFadingOut == rhs.m_bFadingOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,6 +430,7 @@ class CWindow {
|
||||||
int workspaceID();
|
int workspaceID();
|
||||||
bool onSpecialWorkspace();
|
bool onSpecialWorkspace();
|
||||||
void activate(bool force = false);
|
void activate(bool force = false);
|
||||||
|
int surfacesCount();
|
||||||
|
|
||||||
int getRealBorderSize();
|
int getRealBorderSize();
|
||||||
void updateSpecialRenderData();
|
void updateSpecialRenderData();
|
||||||
|
@ -450,6 +457,13 @@ class CWindow {
|
||||||
void switchWithWindowInGroup(PHLWINDOW pWindow);
|
void switchWithWindowInGroup(PHLWINDOW pWindow);
|
||||||
void setAnimationsToMove();
|
void setAnimationsToMove();
|
||||||
void onWorkspaceAnimUpdate();
|
void onWorkspaceAnimUpdate();
|
||||||
|
void onUpdateState();
|
||||||
|
void onUpdateMeta();
|
||||||
|
std::string fetchTitle();
|
||||||
|
std::string fetchClass();
|
||||||
|
|
||||||
|
// listeners
|
||||||
|
void onAck(uint32_t serial);
|
||||||
|
|
||||||
//
|
//
|
||||||
std::unordered_map<std::string, std::string> getEnv();
|
std::unordered_map<std::string, std::string> getEnv();
|
||||||
|
@ -457,6 +471,17 @@ class CWindow {
|
||||||
//
|
//
|
||||||
PHLWINDOWREF m_pSelf;
|
PHLWINDOWREF m_pSelf;
|
||||||
|
|
||||||
|
// make private once we move listeners to inside CWindow
|
||||||
|
struct {
|
||||||
|
CHyprSignalListener map;
|
||||||
|
CHyprSignalListener ack;
|
||||||
|
CHyprSignalListener unmap;
|
||||||
|
CHyprSignalListener commit;
|
||||||
|
CHyprSignalListener destroy;
|
||||||
|
CHyprSignalListener updateState;
|
||||||
|
CHyprSignalListener updateMetadata;
|
||||||
|
} listeners;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For hidden windows and stuff
|
// For hidden windows and stuff
|
||||||
bool m_bHidden = false;
|
bool m_bHidden = false;
|
||||||
|
@ -520,7 +545,7 @@ struct std::formatter<PHLWINDOW, CharT> : std::formatter<CharT> {
|
||||||
if (formatMonitor)
|
if (formatMonitor)
|
||||||
std::format_to(out, ", monitor: {}", w->m_iMonitorID);
|
std::format_to(out, ", monitor: {}", w->m_iMonitorID);
|
||||||
if (formatClass)
|
if (formatClass)
|
||||||
std::format_to(out, ", class: {}", g_pXWaylandManager->getAppIDClass(w));
|
std::format_to(out, ", class: {}", w->m_szClass);
|
||||||
return std::format_to(out, "]");
|
return std::format_to(out, "]");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,9 +18,6 @@ namespace Events {
|
||||||
// Layer events
|
// Layer events
|
||||||
LISTENER(newLayerSurface);
|
LISTENER(newLayerSurface);
|
||||||
|
|
||||||
// Surface XDG (window)
|
|
||||||
LISTENER(newXDGToplevel);
|
|
||||||
|
|
||||||
// Window events
|
// Window events
|
||||||
DYNLISTENFUNC(commitWindow);
|
DYNLISTENFUNC(commitWindow);
|
||||||
DYNLISTENFUNC(mapWindow);
|
DYNLISTENFUNC(mapWindow);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------ //
|
// ------------------------------------------------------------ //
|
||||||
// __ _______ _ _ _____ ______ _______ //
|
// __ _______ _ _ _____ ______ _______ //
|
||||||
|
@ -25,11 +26,10 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
||||||
*y += PWINDOW->m_vRealPosition.goal().y;
|
*y += PWINDOW->m_vRealPosition.goal().y;
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
||||||
wlr_box geom;
|
Vector2D pos = PWINDOW->m_pXDGSurface->current.geometry.pos();
|
||||||
wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom);
|
|
||||||
|
|
||||||
*x -= geom.x;
|
*x -= pos.x;
|
||||||
*y -= geom.y;
|
*y -= pos.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,11 +67,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_bIsMapped = true;
|
PWINDOW->m_bIsMapped = true;
|
||||||
PWINDOW->m_bReadyToDelete = false;
|
PWINDOW->m_bReadyToDelete = false;
|
||||||
PWINDOW->m_bFadingOut = false;
|
PWINDOW->m_bFadingOut = false;
|
||||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
PWINDOW->m_szTitle = PWINDOW->fetchTitle();
|
||||||
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
|
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
|
||||||
PWINDOW->m_bFirstMap = true;
|
PWINDOW->m_bFirstMap = true;
|
||||||
PWINDOW->m_szInitialTitle = PWINDOW->m_szTitle;
|
PWINDOW->m_szInitialTitle = PWINDOW->m_szTitle;
|
||||||
PWINDOW->m_szInitialClass = g_pXWaylandManager->getAppIDClass(PWINDOW);
|
PWINDOW->m_szInitialClass = PWINDOW->fetchClass();
|
||||||
|
|
||||||
// check for token
|
// check for token
|
||||||
std::string requestedWorkspace = "";
|
std::string requestedWorkspace = "";
|
||||||
|
@ -111,9 +111,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
|
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
// Set all windows tiled regardless of anything
|
|
||||||
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
|
|
||||||
|
|
||||||
// checks if the window wants borders and sets the appropriate flag
|
// checks if the window wants borders and sets the appropriate flag
|
||||||
g_pXWaylandManager->checkBorders(PWINDOW);
|
g_pXWaylandManager->checkBorders(PWINDOW);
|
||||||
|
|
||||||
|
@ -146,10 +143,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// window rules
|
// window rules
|
||||||
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
|
||||||
(!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) ||
|
|
||||||
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
|
|
||||||
bool requestsFakeFullscreen = false;
|
bool requestsFakeFullscreen = false;
|
||||||
bool requestsMaximize = false;
|
bool requestsMaximize = false;
|
||||||
bool overridingNoFullscreen = false;
|
bool overridingNoFullscreen = false;
|
||||||
|
@ -508,19 +503,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
PWINDOW->m_fDimPercent.setValueAndWarp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11) {
|
if (PWINDOW->m_bIsX11) {
|
||||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW.get(), "XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW.get(),
|
|
||||||
"XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW.get(),
|
|
||||||
"XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_requestMove.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_move, &Events::listener_requestMove, PWINDOW.get(), "XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW.get(),
|
|
||||||
"XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW.get(),
|
|
||||||
"XDG Window Late");
|
|
||||||
PWINDOW->hyprListener_ackConfigure.initCallback(&PWINDOW->m_uSurface.xdg->events.ack_configure, &Events::listener_ackConfigure, PWINDOW.get(), "XDG Window Late");
|
|
||||||
} else {
|
|
||||||
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW.get(),
|
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW.get(),
|
||||||
"XWayland Window Late");
|
"XWayland Window Late");
|
||||||
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW.get(),
|
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW.get(),
|
||||||
|
@ -573,7 +556,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
if (*PSWALLOW && std::string{*PSWALLOWREGEX} != STRVAL_EMPTY) {
|
||||||
// don't swallow ourselves
|
// don't swallow ourselves
|
||||||
std::regex rgx(*PSWALLOWREGEX);
|
std::regex rgx(*PSWALLOWREGEX);
|
||||||
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
|
if (!std::regex_match(PWINDOW->m_szClass, rgx)) {
|
||||||
// check parent
|
// check parent
|
||||||
int ppid = getPPIDof(PWINDOW->getPID());
|
int ppid = getPPIDof(PWINDOW->getPID());
|
||||||
|
|
||||||
|
@ -615,12 +598,12 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finalFound) {
|
if (finalFound) {
|
||||||
bool valid = std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx);
|
bool valid = std::regex_match(PWINDOW->m_szClass, rgx);
|
||||||
|
|
||||||
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
if (std::string{*PSWALLOWEXREGEX} != STRVAL_EMPTY) {
|
||||||
std::regex exc(*PSWALLOWEXREGEX);
|
std::regex exc(*PSWALLOWEXREGEX);
|
||||||
|
|
||||||
valid = valid && !std::regex_match(g_pXWaylandManager->getTitle(finalFound), exc);
|
valid = valid && !std::regex_match(PWINDOW->m_szTitle, exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if it's the window we want & not exempt from getting swallowed
|
// check if it's the window we want & not exempt from getting swallowed
|
||||||
|
@ -644,7 +627,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal());
|
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal());
|
||||||
|
|
||||||
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, g_pXWaylandManager->getAppIDClass(PWINDOW), PWINDOW->m_szTitle)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)});
|
||||||
EMIT_HOOK_EVENT("openWindow", PWINDOW);
|
EMIT_HOOK_EVENT("openWindow", PWINDOW);
|
||||||
|
|
||||||
// apply data from default decos. Borders, shadows.
|
// apply data from default decos. Borders, shadows.
|
||||||
|
@ -705,15 +688,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW);
|
g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW);
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11) {
|
if (!PWINDOW->m_bIsX11) {
|
||||||
Debug::log(LOG, "Unregistered late callbacks XDG");
|
|
||||||
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
|
||||||
PWINDOW->hyprListener_requestMaximize.removeCallback();
|
|
||||||
PWINDOW->hyprListener_requestMinimize.removeCallback();
|
|
||||||
PWINDOW->hyprListener_requestMove.removeCallback();
|
|
||||||
PWINDOW->hyprListener_requestResize.removeCallback();
|
|
||||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
|
||||||
PWINDOW->hyprListener_ackConfigure.removeCallback();
|
|
||||||
} else {
|
|
||||||
Debug::log(LOG, "Unregistered late callbacks XWL");
|
Debug::log(LOG, "Unregistered late callbacks XWL");
|
||||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
||||||
PWINDOW->hyprListener_activateX11.removeCallback();
|
PWINDOW->hyprListener_activateX11.removeCallback();
|
||||||
|
@ -804,29 +778,15 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
PWINDOW->onUnmap();
|
PWINDOW->onUnmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_ackConfigure(void* owner, void* data) {
|
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
|
||||||
const auto E = (wlr_xdg_surface_configure*)data;
|
|
||||||
|
|
||||||
// find last matching serial
|
|
||||||
const auto SERIAL = std::find_if(PWINDOW->m_vPendingSizeAcks.rbegin(), PWINDOW->m_vPendingSizeAcks.rend(), [&](const auto& e) { return e.first == E->serial; });
|
|
||||||
|
|
||||||
if (SERIAL == PWINDOW->m_vPendingSizeAcks.rend())
|
|
||||||
return;
|
|
||||||
|
|
||||||
PWINDOW->m_pPendingSizeAck = *SERIAL;
|
|
||||||
std::erase_if(PWINDOW->m_vPendingSizeAcks, [&](const auto& el) { return el.first == SERIAL->first; });
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_commitWindow(void* owner, void* data) {
|
void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) {
|
if (!PWINDOW->m_bIsX11 && PWINDOW->m_pXDGSurface->initialCommit) {
|
||||||
Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(PWINDOW);
|
Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(PWINDOW);
|
||||||
|
|
||||||
Debug::log(LOG, "Layout predicts size {} for {}", predSize, PWINDOW);
|
Debug::log(LOG, "Layout predicts size {} for {}", predSize, PWINDOW);
|
||||||
|
|
||||||
wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, predSize.x, predSize.y);
|
PWINDOW->m_pXDGSurface->toplevel->setSize(predSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,8 +801,8 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11 && !PWINDOW->m_bIsFullscreen && PWINDOW->m_bIsFloating) {
|
if (!PWINDOW->m_bIsX11 && !PWINDOW->m_bIsFullscreen && PWINDOW->m_bIsFloating) {
|
||||||
const auto MINSIZE = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->current.min_width, PWINDOW->m_uSurface.xdg->toplevel->current.min_height};
|
const auto MINSIZE = PWINDOW->m_pXDGSurface->toplevel->current.minSize;
|
||||||
const auto MAXSIZE = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->current.max_width, PWINDOW->m_uSurface.xdg->toplevel->current.max_height};
|
const auto MAXSIZE = PWINDOW->m_pXDGSurface->toplevel->current.maxSize;
|
||||||
|
|
||||||
if (MAXSIZE > Vector2D{1, 1}) {
|
if (MAXSIZE > Vector2D{1, 1}) {
|
||||||
const auto REALSIZE = PWINDOW->m_vRealSize.goal();
|
const auto REALSIZE = PWINDOW->m_vRealSize.goal();
|
||||||
|
@ -861,7 +821,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
|
|
||||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0;
|
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + DELTA / 2.0;
|
||||||
PWINDOW->m_vRealSize = newSize;
|
PWINDOW->m_vRealSize = newSize;
|
||||||
g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true);
|
g_pXWaylandManager->setWindowSize(PWINDOW, newSize);
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -918,11 +878,13 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||||
PWINDOW->hyprListener_associateX11.removeCallback();
|
PWINDOW->hyprListener_associateX11.removeCallback();
|
||||||
PWINDOW->hyprListener_dissociateX11.removeCallback();
|
PWINDOW->hyprListener_dissociateX11.removeCallback();
|
||||||
|
|
||||||
|
PWINDOW->listeners = {};
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||||
|
|
||||||
PWINDOW->m_bReadyToDelete = true;
|
PWINDOW->m_bReadyToDelete = true;
|
||||||
|
|
||||||
PWINDOW->m_uSurface.xdg = nullptr;
|
PWINDOW->m_pXDGSurface.reset();
|
||||||
|
|
||||||
if (!PWINDOW->m_bFadingOut) {
|
if (!PWINDOW->m_bFadingOut) {
|
||||||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||||
|
@ -936,31 +898,14 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||||
if (!validMapped(PWINDOW))
|
if (!validMapped(PWINDOW))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto NEWTITLE = g_pXWaylandManager->getTitle(PWINDOW);
|
PWINDOW->onUpdateMeta();
|
||||||
|
|
||||||
if (NEWTITLE == PWINDOW->m_szTitle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PWINDOW->m_szTitle = NEWTITLE;
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)PWINDOW.get())});
|
|
||||||
EMIT_HOOK_EVENT("windowTitle", PWINDOW);
|
|
||||||
|
|
||||||
if (PWINDOW == g_pCompositor->m_pLastWindow.lock()) { // if it's the active, let's post an event to update others
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle});
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)PWINDOW.get())});
|
|
||||||
EMIT_HOOK_EVENT("activeWindow", PWINDOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
PWINDOW->updateDynamicRules();
|
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
|
||||||
PWINDOW->updateToplevel();
|
|
||||||
|
|
||||||
Debug::log(LOG, "Window {:x} set title to {}", PWINDOW, PWINDOW->m_szTitle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_fullscreenWindow(void* owner, void* data) {
|
void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
||||||
|
|
||||||
|
// x11 only
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsMapped) {
|
if (!PWINDOW->m_bIsMapped) {
|
||||||
PWINDOW->m_bWantsInitialFullscreen = true;
|
PWINDOW->m_bWantsInitialFullscreen = true;
|
||||||
return;
|
return;
|
||||||
|
@ -971,41 +916,13 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||||
|
|
||||||
bool requestedFullState = false;
|
bool requestedFullState = false;
|
||||||
|
|
||||||
if (!PWINDOW->m_bIsX11) {
|
if (!PWINDOW->m_uSurface.xwayland->surface->mapped)
|
||||||
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
|
return;
|
||||||
|
|
||||||
if (REQUESTED->fullscreen && PWINDOW->m_bIsFullscreen) {
|
if (!PWINDOW->m_bFakeFullscreenState)
|
||||||
const auto PWORKSPACE = PWINDOW->m_pWorkspace;
|
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
|
||||||
if (PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) {
|
|
||||||
// Store that we were maximized
|
|
||||||
PWINDOW->m_bWasMaximized = true;
|
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_MAXIMIZED);
|
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
|
|
||||||
} else
|
|
||||||
PWINDOW->m_bWasMaximized = false;
|
|
||||||
} else if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen && !PWINDOW->m_bFakeFullscreenState) {
|
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, REQUESTED->fullscreen, FULLSCREEN_FULL);
|
|
||||||
if (PWINDOW->m_bWasMaximized && !REQUESTED->fullscreen) {
|
|
||||||
// Was maximized before the fullscreen request, return now back to maximized instead of normal
|
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_MAXIMIZED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the maximize flag when we receive a de-fullscreen request
|
requestedFullState = PWINDOW->m_uSurface.xwayland->fullscreen;
|
||||||
PWINDOW->m_bWasMaximized &= REQUESTED->fullscreen;
|
|
||||||
|
|
||||||
requestedFullState = REQUESTED->fullscreen;
|
|
||||||
|
|
||||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
|
||||||
} else {
|
|
||||||
if (!PWINDOW->m_uSurface.xwayland->surface->mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!PWINDOW->m_bFakeFullscreenState)
|
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
|
|
||||||
|
|
||||||
requestedFullState = PWINDOW->m_uSurface.xwayland->fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!requestedFullState && PWINDOW->m_bFakeFullscreenState) {
|
if (!requestedFullState && PWINDOW->m_bFakeFullscreenState) {
|
||||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, false); // fixes for apps expecting a de-fullscreen (e.g. ff)
|
g_pXWaylandManager->setWindowFullscreen(PWINDOW, false); // fixes for apps expecting a de-fullscreen (e.g. ff)
|
||||||
|
@ -1177,7 +1094,7 @@ void Events::listener_associateX11(void* owner, void* data) {
|
||||||
PWINDOW->hyprListener_mapWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.map, &Events::listener_mapWindow, PWINDOW.get(), "XWayland Window");
|
PWINDOW->hyprListener_mapWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.map, &Events::listener_mapWindow, PWINDOW.get(), "XWayland Window");
|
||||||
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.commit, &Events::listener_commitWindow, PWINDOW.get(), "XWayland Window");
|
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.commit, &Events::listener_commitWindow, PWINDOW.get(), "XWayland Window");
|
||||||
|
|
||||||
PWINDOW->m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW);
|
PWINDOW->m_pWLSurface.assign(PWINDOW->m_uSurface.xwayland->surface, PWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_dissociateX11(void* owner, void* data) {
|
void Events::listener_dissociateX11(void* owner, void* data) {
|
||||||
|
@ -1211,23 +1128,6 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||||
PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW.get(), "XWayland Window");
|
PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW.get(), "XWayland Window");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newXDGToplevel(wl_listener* listener, void* data) {
|
|
||||||
// A window got opened
|
|
||||||
const auto XDGTOPLEVEL = (wlr_xdg_toplevel*)data;
|
|
||||||
const auto XDGSURFACE = XDGTOPLEVEL->base;
|
|
||||||
|
|
||||||
Debug::log(LOG, "New XDG Toplevel created. (class: {})", XDGSURFACE->toplevel->app_id ? XDGSURFACE->toplevel->app_id : "null");
|
|
||||||
|
|
||||||
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(CWindow::create());
|
|
||||||
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
|
|
||||||
|
|
||||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->surface->events.map, &Events::listener_mapWindow, PNEWWINDOW.get(), "XDG Window");
|
|
||||||
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XDGSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW.get(), "XDG Window");
|
|
||||||
PNEWWINDOW->hyprListener_commitWindow.initCallback(&XDGSURFACE->surface->events.commit, &Events::listener_commitWindow, PNEWWINDOW.get(), "XDG Window");
|
|
||||||
|
|
||||||
PNEWWINDOW->m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(PNEWWINDOW), PNEWWINDOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_requestMaximize(void* owner, void* data) {
|
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
||||||
|
|
||||||
|
@ -1240,7 +1140,6 @@ void Events::listener_requestMaximize(void* owner, void* data) {
|
||||||
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen,
|
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen,
|
||||||
FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
|
FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
|
||||||
|
|
||||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
|
||||||
} else {
|
} else {
|
||||||
if (!PWINDOW->m_bIsMapped || PWINDOW->m_iX11Type != 1)
|
if (!PWINDOW->m_bIsMapped || PWINDOW->m_iX11Type != 1)
|
||||||
return;
|
return;
|
||||||
|
@ -1269,17 +1168,3 @@ void Events::listener_requestMinimize(void* owner, void* data) {
|
||||||
EMIT_HOOK_EVENT("minimize", (std::vector<std::any>{PWINDOW, (int64_t)(1)}));
|
EMIT_HOOK_EVENT("minimize", (std::vector<std::any>{PWINDOW, (int64_t)(1)}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_requestMove(void* owner, void* data) {
|
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
|
||||||
|
|
||||||
// ignore
|
|
||||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_requestResize(void* owner, void* data) {
|
|
||||||
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
|
|
||||||
|
|
||||||
// ignore
|
|
||||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
|
||||||
}
|
|
||||||
|
|
|
@ -52,8 +52,6 @@ extern "C" {
|
||||||
#include <wlr/types/wlr_primary_selection.h>
|
#include <wlr/types/wlr_primary_selection.h>
|
||||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||||
#include <wlr/types/wlr_viewporter.h>
|
#include <wlr/types/wlr_viewporter.h>
|
||||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
|
||||||
#include <wlr/types/wlr_xdg_shell.h>
|
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include <wlr/types/wlr_damage_ring.h>
|
#include <wlr/types/wlr_damage_ring.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include "../desktop/Window.hpp"
|
#include "../desktop/Window.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||||
if (pWindow->m_bIsFloating) {
|
if (pWindow->m_bIsFloating) {
|
||||||
|
@ -140,8 +141,12 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
|
||||||
|
|
||||||
// TODO: detect a popup in a more consistent way.
|
// TODO: detect a popup in a more consistent way.
|
||||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) {
|
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) {
|
||||||
// if it's not, fall back to the center placement
|
// if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available
|
||||||
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
|
if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window))
|
||||||
|
pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition.goal() +
|
||||||
|
pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize.goal() / 2.F - desiredGeometry.size() / 2.F;
|
||||||
|
else
|
||||||
|
pWindow->m_vRealPosition = PMONITOR->vecPosition + desiredGeometry.size() / 2.F;
|
||||||
} else {
|
} else {
|
||||||
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
|
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
|
||||||
// most of these are popups
|
// most of these are popups
|
||||||
|
@ -693,7 +698,7 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
||||||
else
|
else
|
||||||
sizePredicted = predictSizeForNewWindowFloating(pWindow);
|
sizePredicted = predictSizeForNewWindowFloating(pWindow);
|
||||||
|
|
||||||
Vector2D maxSize = Vector2D{pWindow->m_uSurface.xdg->toplevel->pending.max_width, pWindow->m_uSurface.xdg->toplevel->pending.max_height};
|
Vector2D maxSize = pWindow->m_pXDGSurface->toplevel->pending.maxSize;
|
||||||
|
|
||||||
if ((maxSize.x > 0 && maxSize.x < sizePredicted.x) || (maxSize.y > 0 && maxSize.y < sizePredicted.y))
|
if ((maxSize.x > 0 && maxSize.x < sizePredicted.x) || (maxSize.y > 0 && maxSize.y < sizePredicted.y))
|
||||||
sizePredicted = {};
|
sizePredicted = {};
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/PresentationTime.hpp"
|
#include "../protocols/PresentationTime.hpp"
|
||||||
#include "../protocols/core/Seat.hpp"
|
#include "../protocols/core/Seat.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
CProtocolManager::CProtocolManager() {
|
CProtocolManager::CProtocolManager() {
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ CProtocolManager::CProtocolManager() {
|
||||||
PROTO::tablet = std::make_unique<CTabletV2Protocol>(&zwp_tablet_manager_v2_interface, 1, "TabletV2");
|
PROTO::tablet = std::make_unique<CTabletV2Protocol>(&zwp_tablet_manager_v2_interface, 1, "TabletV2");
|
||||||
PROTO::layerShell = std::make_unique<CLayerShellProtocol>(&zwlr_layer_shell_v1_interface, 5, "LayerShell");
|
PROTO::layerShell = std::make_unique<CLayerShellProtocol>(&zwlr_layer_shell_v1_interface, 5, "LayerShell");
|
||||||
PROTO::presentation = std::make_unique<CPresentationProtocol>(&wp_presentation_interface, 1, "Presentation");
|
PROTO::presentation = std::make_unique<CPresentationProtocol>(&wp_presentation_interface, 1, "Presentation");
|
||||||
|
PROTO::xdgShell = std::make_unique<CXDGShellProtocol>(&xdg_wm_base_interface, 6, "XDGShell");
|
||||||
|
|
||||||
// Old protocol implementations.
|
// Old protocol implementations.
|
||||||
// TODO: rewrite them to use hyprwayland-scanner.
|
// TODO: rewrite them to use hyprwayland-scanner.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../events/Events.hpp"
|
#include "../events/Events.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
#define OUTPUT_MANAGER_VERSION 3
|
#define OUTPUT_MANAGER_VERSION 3
|
||||||
#define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3
|
#define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3
|
||||||
|
@ -34,27 +35,32 @@ CHyprXWaylandManager::~CHyprXWaylandManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_surface* CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) {
|
wlr_surface* CHyprXWaylandManager::getWindowSurface(PHLWINDOW pWindow) {
|
||||||
if (pWindow->m_bIsX11)
|
return pWindow->m_pWLSurface.wlr();
|
||||||
return pWindow->m_uSurface.xwayland->surface;
|
|
||||||
|
|
||||||
return pWindow->m_uSurface.xdg->surface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) {
|
void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) {
|
||||||
if (!pSurface)
|
if (!pSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wlr_xdg_surface_try_from_wlr_surface(pSurface)) {
|
if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) {
|
||||||
if (const auto PSURF = wlr_xdg_surface_try_from_wlr_surface(pSurface); PSURF && PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
|
||||||
wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate);
|
|
||||||
|
|
||||||
} else if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) {
|
|
||||||
const auto XSURF = wlr_xwayland_surface_try_from_wlr_surface(pSurface);
|
const auto XSURF = wlr_xwayland_surface_try_from_wlr_surface(pSurface);
|
||||||
wlr_xwayland_surface_activate(XSURF, activate);
|
wlr_xwayland_surface_activate(XSURF, activate);
|
||||||
|
|
||||||
if (activate && !XSURF->override_redirect)
|
if (activate && !XSURF->override_redirect)
|
||||||
wlr_xwayland_surface_restack(XSURF, nullptr, XCB_STACK_MODE_ABOVE);
|
wlr_xwayland_surface_restack(XSURF, nullptr, XCB_STACK_MODE_ABOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// this cannot be nicely done until we rewrite wlr_surface
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (w->m_bIsX11 || !w->m_bIsMapped)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (w->m_pWLSurface.wlr() != pSurface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
w->m_pXDGSurface->toplevel->setActive(activate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
|
void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
|
||||||
|
@ -68,8 +74,8 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
|
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
|
||||||
} else
|
} else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel)
|
||||||
wlr_xdg_toplevel_set_activated(pWindow->m_uSurface.xdg->toplevel, activate);
|
pWindow->m_pXDGSurface->toplevel->setActive(activate);
|
||||||
|
|
||||||
if (activate) {
|
if (activate) {
|
||||||
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
|
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
|
||||||
|
@ -95,64 +101,15 @@ void CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow, CBox* pbox) {
|
||||||
pbox->width = pWindow->m_uSurface.xwayland->width;
|
pbox->width = pWindow->m_uSurface.xwayland->width;
|
||||||
pbox->height = pWindow->m_uSurface.xwayland->height;
|
pbox->height = pWindow->m_uSurface.xwayland->height;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (pWindow->m_pXDGSurface)
|
||||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox->pWlr());
|
*pbox = pWindow->m_pXDGSurface->current.geometry;
|
||||||
pbox->applyFromWlr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CHyprXWaylandManager::getTitle(PHLWINDOW pWindow) {
|
|
||||||
try {
|
|
||||||
if (pWindow->m_bIsX11) {
|
|
||||||
if (!pWindow->m_bIsMapped)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (pWindow->m_uSurface.xwayland && pWindow->m_uSurface.xwayland->title) {
|
|
||||||
return std::string(pWindow->m_uSurface.xwayland->title);
|
|
||||||
}
|
|
||||||
} else if (pWindow->m_uSurface.xdg) {
|
|
||||||
if (pWindow->m_bFadingOut || !pWindow->m_uSurface.xdg)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (pWindow->m_uSurface.xdg->toplevel && pWindow->m_uSurface.xdg->toplevel->title) {
|
|
||||||
return std::string(pWindow->m_uSurface.xdg->toplevel->title);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
} catch (...) { Debug::log(ERR, "Error in getTitle (probably null title)"); }
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CHyprXWaylandManager::getAppIDClass(PHLWINDOW pWindow) {
|
|
||||||
try {
|
|
||||||
if (pWindow->m_bIsX11) {
|
|
||||||
if (!pWindow->m_bIsMapped)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (pWindow->m_uSurface.xwayland && pWindow->m_uSurface.xwayland->_class) {
|
|
||||||
return std::string(pWindow->m_uSurface.xwayland->_class);
|
|
||||||
}
|
|
||||||
} else if (pWindow->m_uSurface.xdg) {
|
|
||||||
if (pWindow->m_bFadingOut || !pWindow->m_uSurface.xdg)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (pWindow->m_uSurface.xdg->toplevel && pWindow->m_uSurface.xdg->toplevel->app_id) {
|
|
||||||
return std::string(pWindow->m_uSurface.xdg->toplevel->app_id);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return "";
|
|
||||||
} catch (std::logic_error& e) { Debug::log(ERR, "Error in getAppIDClass: {}", e.what()); }
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprXWaylandManager::sendCloseWindow(PHLWINDOW pWindow) {
|
void CHyprXWaylandManager::sendCloseWindow(PHLWINDOW pWindow) {
|
||||||
if (pWindow->m_bIsX11)
|
if (pWindow->m_bIsX11)
|
||||||
wlr_xwayland_surface_close(pWindow->m_uSurface.xwayland);
|
wlr_xwayland_surface_close(pWindow->m_uSurface.xwayland);
|
||||||
else
|
else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel)
|
||||||
wlr_xdg_toplevel_send_close(pWindow->m_uSurface.xdg->toplevel);
|
pWindow->m_pXDGSurface->toplevel->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool force) {
|
void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool force) {
|
||||||
|
@ -189,23 +146,12 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool
|
||||||
|
|
||||||
if (pWindow->m_bIsX11)
|
if (pWindow->m_bIsX11)
|
||||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y);
|
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y);
|
||||||
else
|
else if (pWindow->m_pXDGSurface->toplevel)
|
||||||
pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y), size.floor()));
|
pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(pWindow->m_pXDGSurface->toplevel->setSize(size), size.floor()));
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprXWaylandManager::setWindowStyleTiled(PHLWINDOW pWindow, uint32_t edgez) {
|
|
||||||
if (pWindow->m_bIsX11)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez);
|
|
||||||
wlr_xdg_toplevel_set_maximized(pWindow->m_uSurface.xdg->toplevel, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_surface* CHyprXWaylandManager::surfaceAt(PHLWINDOW pWindow, const Vector2D& client, Vector2D& surface) {
|
wlr_surface* CHyprXWaylandManager::surfaceAt(PHLWINDOW pWindow, const Vector2D& client, Vector2D& surface) {
|
||||||
if (pWindow->m_bIsX11)
|
return wlr_surface_surface_at(pWindow->m_pWLSurface.wlr(), client.x, client.y, &surface.x, &surface.y);
|
||||||
return wlr_surface_surface_at(pWindow->m_uSurface.xwayland->surface, client.x, client.y, &surface.x, &surface.y);
|
|
||||||
|
|
||||||
return wlr_xdg_surface_surface_at(pWindow->m_uSurface.xdg, client.x, client.y, &surface.x, &surface.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) {
|
bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) {
|
||||||
|
@ -251,10 +197,10 @@ bool CHyprXWaylandManager::shouldBeFloated(PHLWINDOW pWindow, bool pending) {
|
||||||
if (SIZEHINTS && (pWindow->m_uSurface.xwayland->parent || ((SIZEHINTS->min_width == SIZEHINTS->max_width) && (SIZEHINTS->min_height == SIZEHINTS->max_height))))
|
if (SIZEHINTS && (pWindow->m_uSurface.xwayland->parent || ((SIZEHINTS->min_width == SIZEHINTS->max_width) && (SIZEHINTS->min_height == SIZEHINTS->max_height))))
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
const auto PSTATE = pending ? &pWindow->m_uSurface.xdg->toplevel->pending : &pWindow->m_uSurface.xdg->toplevel->current;
|
const auto PSTATE = pending ? &pWindow->m_pXDGSurface->toplevel->pending : &pWindow->m_pXDGSurface->toplevel->current;
|
||||||
|
|
||||||
if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) ||
|
if (pWindow->m_pXDGSurface->toplevel->parent ||
|
||||||
pWindow->m_uSurface.xdg->toplevel->parent)
|
(PSTATE->minSize.x != 0 && PSTATE->minSize.y != 0 && (PSTATE->minSize.x == PSTATE->maxSize.x || PSTATE->minSize.y == PSTATE->maxSize.y)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,20 +243,19 @@ void CHyprXWaylandManager::checkBorders(PHLWINDOW pWindow) {
|
||||||
void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscreen) {
|
void CHyprXWaylandManager::setWindowFullscreen(PHLWINDOW pWindow, bool fullscreen) {
|
||||||
if (pWindow->m_bIsX11)
|
if (pWindow->m_bIsX11)
|
||||||
wlr_xwayland_surface_set_fullscreen(pWindow->m_uSurface.xwayland, fullscreen);
|
wlr_xwayland_surface_set_fullscreen(pWindow->m_uSurface.xwayland, fullscreen);
|
||||||
else
|
else if (pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel)
|
||||||
wlr_xdg_toplevel_set_fullscreen(pWindow->m_uSurface.xdg->toplevel, fullscreen);
|
pWindow->m_pXDGSurface->toplevel->setFullscreen(fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) {
|
Vector2D CHyprXWaylandManager::getMaxSizeForWindow(PHLWINDOW pWindow) {
|
||||||
if (!validMapped(pWindow))
|
if (!validMapped(pWindow))
|
||||||
return Vector2D(99999, 99999);
|
return Vector2D(99999, 99999);
|
||||||
|
|
||||||
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel) ||
|
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel) || pWindow->m_sAdditionalConfigData.noMaxSize)
|
||||||
pWindow->m_sAdditionalConfigData.noMaxSize)
|
|
||||||
return Vector2D(99999, 99999);
|
return Vector2D(99999, 99999);
|
||||||
|
|
||||||
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height) :
|
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height) :
|
||||||
Vector2D(pWindow->m_uSurface.xdg->toplevel->current.max_width, pWindow->m_uSurface.xdg->toplevel->current.max_height);
|
pWindow->m_pXDGSurface->toplevel->current.maxSize;
|
||||||
|
|
||||||
if (MAXSIZE.x < 5)
|
if (MAXSIZE.x < 5)
|
||||||
MAXSIZE.x = 99999;
|
MAXSIZE.x = 99999;
|
||||||
|
@ -324,11 +269,11 @@ Vector2D CHyprXWaylandManager::getMinSizeForWindow(PHLWINDOW pWindow) {
|
||||||
if (!validMapped(pWindow))
|
if (!validMapped(pWindow))
|
||||||
return Vector2D(0, 0);
|
return Vector2D(0, 0);
|
||||||
|
|
||||||
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel))
|
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_pXDGSurface->toplevel))
|
||||||
return Vector2D(0, 0);
|
return Vector2D(0, 0);
|
||||||
|
|
||||||
auto MINSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->min_width, pWindow->m_uSurface.xwayland->size_hints->min_height) :
|
auto MINSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->min_width, pWindow->m_uSurface.xwayland->size_hints->min_height) :
|
||||||
Vector2D(pWindow->m_uSurface.xdg->toplevel->current.min_width, pWindow->m_uSurface.xdg->toplevel->current.min_height);
|
pWindow->m_pXDGSurface->toplevel->current.minSize;
|
||||||
|
|
||||||
MINSIZE = MINSIZE.clamp({1, 1});
|
MINSIZE = MINSIZE.clamp({1, 1});
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,8 @@ class CHyprXWaylandManager {
|
||||||
void activateSurface(wlr_surface*, bool);
|
void activateSurface(wlr_surface*, bool);
|
||||||
void activateWindow(PHLWINDOW, bool);
|
void activateWindow(PHLWINDOW, bool);
|
||||||
void getGeometryForWindow(PHLWINDOW, CBox*);
|
void getGeometryForWindow(PHLWINDOW, CBox*);
|
||||||
std::string getTitle(PHLWINDOW);
|
|
||||||
std::string getAppIDClass(PHLWINDOW);
|
|
||||||
void sendCloseWindow(PHLWINDOW);
|
void sendCloseWindow(PHLWINDOW);
|
||||||
void setWindowSize(PHLWINDOW, Vector2D, bool force = false);
|
void setWindowSize(PHLWINDOW, Vector2D, bool force = false);
|
||||||
void setWindowStyleTiled(PHLWINDOW, uint32_t);
|
|
||||||
void setWindowFullscreen(PHLWINDOW, bool);
|
void setWindowFullscreen(PHLWINDOW, bool);
|
||||||
wlr_surface* surfaceAt(PHLWINDOW, const Vector2D&, Vector2D&);
|
wlr_surface* surfaceAt(PHLWINDOW, const Vector2D&, Vector2D&);
|
||||||
bool shouldBeFloated(PHLWINDOW, bool pending = false);
|
bool shouldBeFloated(PHLWINDOW, bool pending = false);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../../protocols/VirtualPointer.hpp"
|
#include "../../protocols/VirtualPointer.hpp"
|
||||||
#include "../../protocols/LayerShell.hpp"
|
#include "../../protocols/LayerShell.hpp"
|
||||||
#include "../../protocols/core/Seat.hpp"
|
#include "../../protocols/core/Seat.hpp"
|
||||||
|
#include "../../protocols/XDGShell.hpp"
|
||||||
|
|
||||||
#include "../../devices/Mouse.hpp"
|
#include "../../devices/Mouse.hpp"
|
||||||
#include "../../devices/VirtualPointer.hpp"
|
#include "../../devices/VirtualPointer.hpp"
|
||||||
|
@ -387,10 +388,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
|
|
||||||
if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) {
|
if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) {
|
||||||
// calc for oversized windows... fucking bullshit.
|
// calc for oversized windows... fucking bullshit.
|
||||||
wlr_box geom;
|
CBox geom = pFoundWindow->m_pXDGSurface->current.geometry;
|
||||||
wlr_xdg_surface_get_geometry(pFoundWindow->m_uSurface.xdg, &geom);
|
|
||||||
|
|
||||||
surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y);
|
surfaceLocal = mouseCoords - surfacePos + geom.pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero
|
if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero
|
||||||
|
|
|
@ -91,7 +91,7 @@ void CForeignToplevelList::onClass(PHLWINDOW pWindow) {
|
||||||
if (!H || H->closed)
|
if (!H || H->closed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
H->resource->sendAppId(g_pXWaylandManager->getAppIDClass(pWindow).c_str());
|
H->resource->sendAppId(pWindow->m_szClass.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForeignToplevelList::onUnmap(PHLWINDOW pWindow) {
|
void CForeignToplevelList::onUnmap(PHLWINDOW pWindow) {
|
||||||
|
|
|
@ -195,7 +195,7 @@ void CForeignToplevelWlrManager::onMap(PHLWINDOW pWindow) {
|
||||||
|
|
||||||
LOGM(LOG, "Newly mapped window {:016x}", (uintptr_t)pWindow.get());
|
LOGM(LOG, "Newly mapped window {:016x}", (uintptr_t)pWindow.get());
|
||||||
resource->sendToplevel(NEWHANDLE->resource.get());
|
resource->sendToplevel(NEWHANDLE->resource.get());
|
||||||
NEWHANDLE->resource->sendAppId(g_pXWaylandManager->getAppIDClass(pWindow).c_str());
|
NEWHANDLE->resource->sendAppId(pWindow->m_szClass.c_str());
|
||||||
NEWHANDLE->resource->sendTitle(pWindow->m_szTitle.c_str());
|
NEWHANDLE->resource->sendTitle(pWindow->m_szTitle.c_str());
|
||||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR)
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR)
|
||||||
NEWHANDLE->sendMonitor(PMONITOR);
|
NEWHANDLE->sendMonitor(PMONITOR);
|
||||||
|
@ -231,7 +231,7 @@ void CForeignToplevelWlrManager::onClass(PHLWINDOW pWindow) {
|
||||||
if (!H || H->closed)
|
if (!H || H->closed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
H->resource->sendAppId(g_pXWaylandManager->getAppIDClass(pWindow).c_str());
|
H->resource->sendAppId(pWindow->m_szClass.c_str());
|
||||||
H->resource->sendDone();
|
H->resource->sendDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "LayerShell.hpp"
|
#include "LayerShell.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
#include "XDGShell.hpp"
|
||||||
|
|
||||||
#define LOGM PROTO::layerShell->protoLog
|
#define LOGM PROTO::layerShell->protoLog
|
||||||
|
|
||||||
|
@ -118,14 +119,14 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, wlr_
|
||||||
});
|
});
|
||||||
|
|
||||||
resource->setGetPopup([this](CZwlrLayerSurfaceV1* r, wl_resource* popup_) {
|
resource->setGetPopup([this](CZwlrLayerSurfaceV1* r, wl_resource* popup_) {
|
||||||
auto popup = wlr_xdg_popup_from_resource(popup_);
|
auto popup = CXDGPopupResource::fromResource(popup_);
|
||||||
|
|
||||||
if (popup->parent) {
|
if (popup->taken) {
|
||||||
r->error(-1, "Parent already exists!");
|
r->error(-1, "Parent already exists!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
popup->parent = surface;
|
popup->taken = true;
|
||||||
events.newPopup.emit(popup);
|
events.newPopup.emit(popup);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
697
src/protocols/XDGShell.cpp
Normal file
697
src/protocols/XDGShell.cpp
Normal file
|
@ -0,0 +1,697 @@
|
||||||
|
#include "XDGShell.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
#define LOGM PROTO::xdgShell->protoLog
|
||||||
|
|
||||||
|
CXDGPopupResource::CXDGPopupResource(SP<CXdgPopup> resource_, SP<CXDGSurfaceResource> owner_, SP<CXDGSurfaceResource> surface_, SP<CXDGPositionerResource> positioner) :
|
||||||
|
surface(surface_), parent(owner_), resource(resource_), positionerRules(positioner) {
|
||||||
|
if (!good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setData(this);
|
||||||
|
|
||||||
|
resource->setDestroy([this](CXdgPopup* r) {
|
||||||
|
if (surface && surface->mapped)
|
||||||
|
surface->events.unmap.emit();
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
resource->setOnDestroy([this](CXdgPopup* r) {
|
||||||
|
if (surface && surface->mapped)
|
||||||
|
surface->events.unmap.emit();
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setReposition([this](CXdgPopup* r, wl_resource* positionerRes, uint32_t token) {
|
||||||
|
LOGM(LOG, "Popup {:x} asks for reposition", (uintptr_t)this);
|
||||||
|
lastRepositionToken = token;
|
||||||
|
auto pos = CXDGPositionerResource::fromResource(positionerRes);
|
||||||
|
if (!pos)
|
||||||
|
return;
|
||||||
|
positionerRules = CXDGPositionerRules{pos};
|
||||||
|
events.reposition.emit();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGPopupResource::~CXDGPopupResource() {
|
||||||
|
events.destroy.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGPopupResource::applyPositioning(const CBox& box, const Vector2D& t1coord) {
|
||||||
|
CBox constraint = box.copy().translate(surface->pending.geometry.pos());
|
||||||
|
|
||||||
|
geometry = positionerRules.getPosition(constraint, accumulateParentOffset() + t1coord);
|
||||||
|
|
||||||
|
LOGM(LOG, "Popup {:x} gets unconstrained to {} {}", (uintptr_t)this, geometry.pos(), geometry.size());
|
||||||
|
|
||||||
|
configure(geometry);
|
||||||
|
|
||||||
|
if (lastRepositionToken)
|
||||||
|
repositioned();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CXDGPopupResource::accumulateParentOffset() {
|
||||||
|
SP<CXDGSurfaceResource> current = parent.lock();
|
||||||
|
Vector2D off;
|
||||||
|
while (current) {
|
||||||
|
off += current->current.geometry.pos();
|
||||||
|
if (current->popup) {
|
||||||
|
off += current->popup->geometry.pos();
|
||||||
|
current = current->popup->parent.lock();
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CXDGPopupResource> CXDGPopupResource::fromResource(wl_resource* res) {
|
||||||
|
auto data = (CXDGPopupResource*)(((CXdgPopup*)wl_resource_get_user_data(res))->data());
|
||||||
|
return data ? data->self.lock() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXDGPopupResource::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGPopupResource::configure(const CBox& box) {
|
||||||
|
resource->sendConfigure(box.x, box.y, box.w, box.h);
|
||||||
|
if (surface)
|
||||||
|
surface->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGPopupResource::done() {
|
||||||
|
resource->sendPopupDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGPopupResource::repositioned() {
|
||||||
|
if (!lastRepositionToken)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOGM(LOG, "repositioned: sending reposition token {}", lastRepositionToken);
|
||||||
|
|
||||||
|
resource->sendRepositioned(lastRepositionToken);
|
||||||
|
lastRepositionToken = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGToplevelResource::CXDGToplevelResource(SP<CXdgToplevel> resource_, SP<CXDGSurfaceResource> owner_) : owner(owner_), resource(resource_) {
|
||||||
|
if (!good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setData(this);
|
||||||
|
|
||||||
|
resource->setDestroy([this](CXdgToplevel* r) {
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
resource->setOnDestroy([this](CXdgToplevel* r) {
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (resource->version() >= 5) {
|
||||||
|
wl_array arr;
|
||||||
|
wl_array_init(&arr);
|
||||||
|
auto p = (uint32_t*)wl_array_add(&arr, sizeof(uint32_t));
|
||||||
|
*p = XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN;
|
||||||
|
p = (uint32_t*)wl_array_add(&arr, sizeof(uint32_t));
|
||||||
|
*p = XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE;
|
||||||
|
resource->sendWmCapabilities(&arr);
|
||||||
|
wl_array_release(&arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_LEFT);
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_RIGHT);
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_TOP);
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_TILED_BOTTOM);
|
||||||
|
|
||||||
|
resource->setSetTitle([this](CXdgToplevel* r, const char* t) {
|
||||||
|
state.title = t;
|
||||||
|
events.metadataChanged.emit();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetAppId([this](CXdgToplevel* r, const char* id) {
|
||||||
|
state.appid = id;
|
||||||
|
events.metadataChanged.emit();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetMaxSize([this](CXdgToplevel* r, int32_t x, int32_t y) {
|
||||||
|
pending.maxSize = {x, y};
|
||||||
|
events.sizeLimitsChanged.emit();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetMinSize([this](CXdgToplevel* r, int32_t x, int32_t y) {
|
||||||
|
pending.minSize = {x, y};
|
||||||
|
events.sizeLimitsChanged.emit();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetMaximized([this](CXdgToplevel* r) {
|
||||||
|
state.requestsMaximize = true;
|
||||||
|
events.stateChanged.emit();
|
||||||
|
state.requestsMaximize.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setUnsetMaximized([this](CXdgToplevel* r) {
|
||||||
|
state.requestsMaximize = false;
|
||||||
|
events.stateChanged.emit();
|
||||||
|
state.requestsMaximize.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetFullscreen([this](CXdgToplevel* r, wl_resource* output) {
|
||||||
|
state.requestsFullscreen = true;
|
||||||
|
events.stateChanged.emit();
|
||||||
|
state.requestsFullscreen.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setUnsetFullscreen([this](CXdgToplevel* r) {
|
||||||
|
state.requestsFullscreen = false;
|
||||||
|
events.stateChanged.emit();
|
||||||
|
state.requestsFullscreen.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetMinimized([this](CXdgToplevel* r) {
|
||||||
|
state.requestsMinimize = true;
|
||||||
|
events.stateChanged.emit();
|
||||||
|
state.requestsFullscreen.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetParent([this](CXdgToplevel* r, wl_resource* parentR) {
|
||||||
|
auto newp = parentR ? CXDGToplevelResource::fromResource(parentR) : nullptr;
|
||||||
|
parent = newp;
|
||||||
|
|
||||||
|
LOGM(LOG, "Toplevel {:x} sets parent to {:x}", (uintptr_t)this, (uintptr_t)newp.get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGToplevelResource::~CXDGToplevelResource() {
|
||||||
|
events.destroy.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CXDGToplevelResource> CXDGToplevelResource::fromResource(wl_resource* res) {
|
||||||
|
auto data = (CXDGToplevelResource*)(((CXdgToplevel*)wl_resource_get_user_data(res))->data());
|
||||||
|
return data ? data->self.lock() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXDGToplevelResource::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGToplevelResource::setSize(const Vector2D& size) {
|
||||||
|
pendingApply.size = size;
|
||||||
|
applyState();
|
||||||
|
return owner->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGToplevelResource::setMaximized(bool maximized) {
|
||||||
|
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_MAXIMIZED) != pendingApply.states.end();
|
||||||
|
|
||||||
|
if (maximized == set)
|
||||||
|
return owner->scheduledSerial;
|
||||||
|
|
||||||
|
if (maximized && !set)
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_MAXIMIZED);
|
||||||
|
else if (!maximized && set)
|
||||||
|
std::erase(pendingApply.states, XDG_TOPLEVEL_STATE_MAXIMIZED);
|
||||||
|
applyState();
|
||||||
|
return owner->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGToplevelResource::setFullscreen(bool fullscreen) {
|
||||||
|
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_FULLSCREEN) != pendingApply.states.end();
|
||||||
|
|
||||||
|
if (fullscreen == set)
|
||||||
|
return owner->scheduledSerial;
|
||||||
|
|
||||||
|
if (fullscreen && !set)
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_FULLSCREEN);
|
||||||
|
else if (!fullscreen && set)
|
||||||
|
std::erase(pendingApply.states, XDG_TOPLEVEL_STATE_FULLSCREEN);
|
||||||
|
applyState();
|
||||||
|
return owner->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGToplevelResource::setActive(bool active) {
|
||||||
|
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_ACTIVATED) != pendingApply.states.end();
|
||||||
|
|
||||||
|
if (active == set)
|
||||||
|
return owner->scheduledSerial;
|
||||||
|
|
||||||
|
if (active && !set)
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_ACTIVATED);
|
||||||
|
else if (!active && set)
|
||||||
|
std::erase(pendingApply.states, XDG_TOPLEVEL_STATE_ACTIVATED);
|
||||||
|
applyState();
|
||||||
|
return owner->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGToplevelResource::setSuspeneded(bool sus) {
|
||||||
|
bool set = std::find(pendingApply.states.begin(), pendingApply.states.end(), XDG_TOPLEVEL_STATE_SUSPENDED) != pendingApply.states.end();
|
||||||
|
|
||||||
|
if (sus == set)
|
||||||
|
return owner->scheduledSerial;
|
||||||
|
|
||||||
|
if (sus && !set)
|
||||||
|
pendingApply.states.push_back(XDG_TOPLEVEL_STATE_SUSPENDED);
|
||||||
|
else if (!sus && set)
|
||||||
|
std::erase(pendingApply.states, XDG_TOPLEVEL_STATE_SUSPENDED);
|
||||||
|
applyState();
|
||||||
|
return owner->scheduleConfigure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGToplevelResource::applyState() {
|
||||||
|
wl_array arr;
|
||||||
|
wl_array_init(&arr);
|
||||||
|
wl_array_add(&arr, pendingApply.states.size() * sizeof(int));
|
||||||
|
memcpy(arr.data, pendingApply.states.data(), pendingApply.states.size() * sizeof(int));
|
||||||
|
|
||||||
|
resource->sendConfigure(pendingApply.size.x, pendingApply.size.y, &arr);
|
||||||
|
|
||||||
|
wl_array_release(&arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGToplevelResource::close() {
|
||||||
|
resource->sendClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBase> owner_, wlr_surface* surface_) : owner(owner_), surface(surface_), resource(resource_) {
|
||||||
|
if (!good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setData(this);
|
||||||
|
|
||||||
|
resource->setDestroy([this](CXdgSurface* r) {
|
||||||
|
if (mapped)
|
||||||
|
events.unmap.emit();
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
resource->setOnDestroy([this](CXdgSurface* r) {
|
||||||
|
if (mapped)
|
||||||
|
events.unmap.emit();
|
||||||
|
events.destroy.emit();
|
||||||
|
PROTO::xdgShell->destroyResource(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
hyprListener_surfaceDestroy.initCallback(
|
||||||
|
&surface->events.destroy,
|
||||||
|
[this](void* owner, void* data) {
|
||||||
|
LOGM(WARN, "wl_surface destroyed before its xdg_surface role object");
|
||||||
|
hyprListener_surfaceDestroy.removeCallback();
|
||||||
|
hyprListener_surfaceCommit.removeCallback();
|
||||||
|
|
||||||
|
if (mapped)
|
||||||
|
events.unmap.emit();
|
||||||
|
|
||||||
|
mapped = false;
|
||||||
|
surface = nullptr;
|
||||||
|
events.destroy.emit();
|
||||||
|
},
|
||||||
|
nullptr, "CXDGSurfaceResource");
|
||||||
|
|
||||||
|
hyprListener_surfaceCommit.initCallback(
|
||||||
|
&surface->events.commit,
|
||||||
|
[this](void* owner, void* data) {
|
||||||
|
current = pending;
|
||||||
|
if (toplevel)
|
||||||
|
toplevel->current = toplevel->pending;
|
||||||
|
|
||||||
|
if (initialCommit && surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0) {
|
||||||
|
resource->error(-1, "Buffer attached before initial commit");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0 && !mapped) {
|
||||||
|
// this forces apps to not draw CSD.
|
||||||
|
if (toplevel)
|
||||||
|
toplevel->setMaximized(true);
|
||||||
|
|
||||||
|
mapped = true;
|
||||||
|
wlr_surface_map(surface);
|
||||||
|
events.map.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->pending.buffer_width <= 0 && surface->pending.buffer_height <= 0 && mapped) {
|
||||||
|
mapped = false;
|
||||||
|
wlr_surface_unmap(surface);
|
||||||
|
events.unmap.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.commit.emit();
|
||||||
|
initialCommit = false;
|
||||||
|
},
|
||||||
|
nullptr, "CXDGSurfaceResource");
|
||||||
|
|
||||||
|
resource->setGetToplevel([this](CXdgSurface* r, uint32_t id) {
|
||||||
|
const auto RESOURCE = PROTO::xdgShell->m_vToplevels.emplace_back(makeShared<CXDGToplevelResource>(makeShared<CXdgToplevel>(r->client(), r->version(), id), self.lock()));
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
r->noMemory();
|
||||||
|
PROTO::xdgShell->m_vToplevels.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toplevel = RESOURCE;
|
||||||
|
toplevel->self = RESOURCE;
|
||||||
|
|
||||||
|
LOGM(LOG, "xdg_surface {:x} gets a toplevel {:x}", (uintptr_t)owner.get(), (uintptr_t)RESOURCE.get());
|
||||||
|
|
||||||
|
g_pCompositor->m_vWindows.emplace_back(CWindow::create(self.lock()));
|
||||||
|
|
||||||
|
for (auto& p : popups) {
|
||||||
|
if (!p)
|
||||||
|
continue;
|
||||||
|
events.newPopup.emit(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setGetPopup([this](CXdgSurface* r, uint32_t id, wl_resource* parentXDG, wl_resource* positionerRes) {
|
||||||
|
auto parent = parentXDG ? CXDGSurfaceResource::fromResource(parentXDG) : nullptr;
|
||||||
|
auto positioner = CXDGPositionerResource::fromResource(positionerRes);
|
||||||
|
const auto RESOURCE =
|
||||||
|
PROTO::xdgShell->m_vPopups.emplace_back(makeShared<CXDGPopupResource>(makeShared<CXdgPopup>(r->client(), r->version(), id), parent, self.lock(), positioner));
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
r->noMemory();
|
||||||
|
PROTO::xdgShell->m_vPopups.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
popup = RESOURCE;
|
||||||
|
RESOURCE->self = RESOURCE;
|
||||||
|
|
||||||
|
LOGM(LOG, "xdg_surface {:x} gets a popup {:x} owner {:x}", (uintptr_t)self.get(), (uintptr_t)RESOURCE.get(), (uintptr_t)parent.get());
|
||||||
|
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent->popups.emplace_back(RESOURCE);
|
||||||
|
if (parent->mapped)
|
||||||
|
parent->events.newPopup.emit(RESOURCE);
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setAckConfigure([this](CXdgSurface* r, uint32_t serial) {
|
||||||
|
events.ack.emit(serial);
|
||||||
|
; // TODO: verify it
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetWindowGeometry([this](CXdgSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||||
|
LOGM(LOG, "xdg_surface {:x} requests geometry {}x{} {}x{}", (uintptr_t)this, x, y, w, h);
|
||||||
|
pending.geometry = {x, y, w, h};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGSurfaceResource::~CXDGSurfaceResource() {
|
||||||
|
events.destroy.emit();
|
||||||
|
if (configureSource)
|
||||||
|
wl_event_source_remove(configureSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXDGSurfaceResource::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CXDGSurfaceResource> CXDGSurfaceResource::fromResource(wl_resource* res) {
|
||||||
|
auto data = (CXDGSurfaceResource*)(((CXdgSurface*)wl_resource_get_user_data(res))->data());
|
||||||
|
return data ? data->self.lock() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onConfigure(void* data) {
|
||||||
|
((CXDGSurfaceResource*)data)->configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CXDGSurfaceResource::scheduleConfigure() {
|
||||||
|
if (configureSource)
|
||||||
|
return scheduledSerial;
|
||||||
|
|
||||||
|
configureSource = wl_event_loop_add_idle(g_pCompositor->m_sWLEventLoop, onConfigure, this);
|
||||||
|
scheduledSerial = wl_display_next_serial(g_pCompositor->m_sWLDisplay);
|
||||||
|
|
||||||
|
return scheduledSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGSurfaceResource::configure() {
|
||||||
|
configureSource = nullptr;
|
||||||
|
resource->sendConfigure(scheduledSerial);
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGPositionerResource::CXDGPositionerResource(SP<CXdgPositioner> resource_, SP<CXDGWMBase> owner_) : owner(owner_), resource(resource_) {
|
||||||
|
if (!good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setData(this);
|
||||||
|
|
||||||
|
resource->setDestroy([this](CXdgPositioner* r) { PROTO::xdgShell->destroyResource(this); });
|
||||||
|
resource->setOnDestroy([this](CXdgPositioner* r) { PROTO::xdgShell->destroyResource(this); });
|
||||||
|
|
||||||
|
resource->setSetSize([this](CXdgPositioner* r, int32_t x, int32_t y) {
|
||||||
|
if (x <= 0 || y <= 0) {
|
||||||
|
r->error(XDG_POSITIONER_ERROR_INVALID_INPUT, "Invalid size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.requestedSize = {x, y};
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetAnchorRect([this](CXdgPositioner* r, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||||
|
if (w <= 0 || h <= 0) {
|
||||||
|
r->error(XDG_POSITIONER_ERROR_INVALID_INPUT, "Invalid box");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.anchorRect = {x, y, w, h};
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setSetOffset([this](CXdgPositioner* r, int32_t x, int32_t y) { state.offset = {x, y}; });
|
||||||
|
|
||||||
|
resource->setSetAnchor([this](CXdgPositioner* r, xdgPositionerAnchor a) { state.anchor = a; });
|
||||||
|
|
||||||
|
resource->setSetGravity([this](CXdgPositioner* r, xdgPositionerGravity g) { state.gravity = g; });
|
||||||
|
|
||||||
|
resource->setSetConstraintAdjustment([this](CXdgPositioner* r, xdgPositionerConstraintAdjustment a) { state.constraintAdjustment = (uint32_t)a; });
|
||||||
|
|
||||||
|
// TODO: support this shit better. The current impl _works_, but is lacking and could be wrong in a few cases.
|
||||||
|
// doesn't matter _that_ much for now, though.
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CXDGPositionerResource> CXDGPositionerResource::fromResource(wl_resource* res) {
|
||||||
|
auto data = (CXDGPositionerResource*)(((CXdgPositioner*)wl_resource_get_user_data(res))->data());
|
||||||
|
return data ? data->self.lock() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXDGPositionerResource::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGPositionerRules::CXDGPositionerRules(SP<CXDGPositionerResource> positioner) {
|
||||||
|
state = positioner->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector2D pointForAnchor(const CBox& box, xdgPositionerAnchor anchor) {
|
||||||
|
switch (anchor) {
|
||||||
|
case XDG_POSITIONER_ANCHOR_TOP: return box.pos() + Vector2D{box.size().x / 2.F, 0};
|
||||||
|
case XDG_POSITIONER_ANCHOR_BOTTOM: return box.pos() + Vector2D{box.size().x / 2.F, box.size().y};
|
||||||
|
case XDG_POSITIONER_ANCHOR_LEFT: return box.pos() + Vector2D{0, box.size().y / 2.F};
|
||||||
|
case XDG_POSITIONER_ANCHOR_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y / 2.F};
|
||||||
|
case XDG_POSITIONER_ANCHOR_TOP_LEFT: return box.pos();
|
||||||
|
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: return box.pos() + Vector2D{0, box.size().y};
|
||||||
|
case XDG_POSITIONER_ANCHOR_TOP_RIGHT: return box.pos() + Vector2D{box.size().x, 0};
|
||||||
|
case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: return box.pos() + Vector2D{box.size().x, box.size().y};
|
||||||
|
default: return box.pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& parentCoord) {
|
||||||
|
|
||||||
|
Debug::log(LOG, "GetPosition with constraint {} {} and parent {}", constraint.pos(), constraint.size(), parentCoord);
|
||||||
|
|
||||||
|
CBox predictedBox = {parentCoord + constraint.pos() + pointForAnchor(state.anchorRect, state.anchor) + state.offset, state.requestedSize};
|
||||||
|
|
||||||
|
bool success = predictedBox.inside(constraint);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return predictedBox.translate(-parentCoord - constraint.pos());
|
||||||
|
|
||||||
|
if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)) {
|
||||||
|
// attempt to flip
|
||||||
|
const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X;
|
||||||
|
const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
|
||||||
|
|
||||||
|
CBox test = predictedBox;
|
||||||
|
success = true;
|
||||||
|
if (flipX && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}).expand(-1).inside(constraint))
|
||||||
|
test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0});
|
||||||
|
else if (flipY && test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint))
|
||||||
|
test.translate(Vector2D{0, -predictedBox.h - state.anchorRect.h});
|
||||||
|
else if (flipX && flipY && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint))
|
||||||
|
test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h});
|
||||||
|
else
|
||||||
|
success = false;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return test.translate(-parentCoord - constraint.pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)) {
|
||||||
|
// attempt to slide
|
||||||
|
const bool slideX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X;
|
||||||
|
const bool slideY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
|
||||||
|
|
||||||
|
//const bool gravityLeft = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT;
|
||||||
|
//const bool gravityTop = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_TOP || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_RIGHT;
|
||||||
|
|
||||||
|
const bool leftEdgeOut = predictedBox.x < constraint.x;
|
||||||
|
const bool topEdgeOut = predictedBox.y < constraint.y;
|
||||||
|
const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w;
|
||||||
|
const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h;
|
||||||
|
|
||||||
|
CBox test = predictedBox;
|
||||||
|
|
||||||
|
// TODO: this isn't truly conformant.
|
||||||
|
if (leftEdgeOut && slideX)
|
||||||
|
test.x = constraint.x;
|
||||||
|
if (rightEdgeOut && slideX)
|
||||||
|
test.x = constraint.x + constraint.w - predictedBox.w;
|
||||||
|
if (topEdgeOut && slideY)
|
||||||
|
test.y = constraint.y;
|
||||||
|
if (bottomEdgeOut && slideY)
|
||||||
|
test.y = constraint.y + constraint.h - predictedBox.y;
|
||||||
|
|
||||||
|
success = test.copy().expand(-1).inside(constraint);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return test.translate(-parentCoord - constraint.pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y)) {
|
||||||
|
const bool resizeX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X;
|
||||||
|
const bool resizeY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
|
||||||
|
|
||||||
|
const bool leftEdgeOut = predictedBox.x < constraint.x;
|
||||||
|
const bool topEdgeOut = predictedBox.y < constraint.y;
|
||||||
|
const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w;
|
||||||
|
const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h;
|
||||||
|
|
||||||
|
CBox test = predictedBox;
|
||||||
|
|
||||||
|
// TODO: this isn't truly conformant.
|
||||||
|
if (leftEdgeOut && resizeX) {
|
||||||
|
test.w = test.x + test.w - constraint.x;
|
||||||
|
test.x = constraint.x;
|
||||||
|
}
|
||||||
|
if (rightEdgeOut && resizeX)
|
||||||
|
test.w = -(constraint.w + constraint.x - test.w - test.x);
|
||||||
|
if (topEdgeOut && resizeY) {
|
||||||
|
test.h = test.y + test.h - constraint.y;
|
||||||
|
test.y = constraint.y;
|
||||||
|
}
|
||||||
|
if (bottomEdgeOut && resizeY)
|
||||||
|
test.h = -(constraint.h + constraint.y - test.h - test.y);
|
||||||
|
|
||||||
|
success = test.copy().expand(-1).inside(constraint);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return test.translate(parentCoord - constraint.pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGM(WARN, "Compositor/client bug: xdg_positioner couldn't find a place");
|
||||||
|
|
||||||
|
return predictedBox.translate(-parentCoord - constraint.pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGWMBase::CXDGWMBase(SP<CXdgWmBase> resource_) : resource(resource_) {
|
||||||
|
if (!good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setDestroy([this](CXdgWmBase* r) { PROTO::xdgShell->destroyResource(this); });
|
||||||
|
resource->setOnDestroy([this](CXdgWmBase* r) { PROTO::xdgShell->destroyResource(this); });
|
||||||
|
|
||||||
|
pClient = resource->client();
|
||||||
|
|
||||||
|
resource->setCreatePositioner([this](CXdgWmBase* r, uint32_t id) {
|
||||||
|
const auto RESOURCE =
|
||||||
|
PROTO::xdgShell->m_vPositioners.emplace_back(makeShared<CXDGPositionerResource>(makeShared<CXdgPositioner>(r->client(), r->version(), id), self.lock()));
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
r->noMemory();
|
||||||
|
PROTO::xdgShell->m_vPositioners.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RESOURCE->self = RESOURCE;
|
||||||
|
|
||||||
|
positioners.emplace_back(RESOURCE);
|
||||||
|
|
||||||
|
LOGM(LOG, "New xdg_positioner at {:x}", (uintptr_t)RESOURCE.get());
|
||||||
|
});
|
||||||
|
|
||||||
|
resource->setGetXdgSurface([this](CXdgWmBase* r, uint32_t id, wl_resource* surf) {
|
||||||
|
const auto RESOURCE = PROTO::xdgShell->m_vSurfaces.emplace_back(
|
||||||
|
makeShared<CXDGSurfaceResource>(makeShared<CXdgSurface>(r->client(), r->version(), id), self.lock(), wlr_surface_from_resource(surf)));
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
r->noMemory();
|
||||||
|
PROTO::xdgShell->m_vSurfaces.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RESOURCE->self = RESOURCE;
|
||||||
|
|
||||||
|
surfaces.emplace_back(RESOURCE);
|
||||||
|
|
||||||
|
LOGM(LOG, "New xdg_surface at {:x}", (uintptr_t)RESOURCE.get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXDGWMBase::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_client* CXDGWMBase::client() {
|
||||||
|
return pClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDGShellProtocol::CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
|
const auto RESOURCE = m_vWMBases.emplace_back(makeShared<CXDGWMBase>(makeShared<CXdgWmBase>(client, ver, id)));
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
m_vWMBases.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RESOURCE->self = RESOURCE;
|
||||||
|
|
||||||
|
LOGM(LOG, "New xdg_wm_base at {:x}", (uintptr_t)RESOURCE.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::destroyResource(CXDGWMBase* resource) {
|
||||||
|
std::erase_if(m_vWMBases, [&](const auto& other) { return other.get() == resource; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::destroyResource(CXDGPositionerResource* resource) {
|
||||||
|
std::erase_if(m_vPositioners, [&](const auto& other) { return other.get() == resource; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::destroyResource(CXDGSurfaceResource* resource) {
|
||||||
|
std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::destroyResource(CXDGToplevelResource* resource) {
|
||||||
|
std::erase_if(m_vToplevels, [&](const auto& other) { return other.get() == resource; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXDGShellProtocol::destroyResource(CXDGPopupResource* resource) {
|
||||||
|
std::erase_if(m_vPopups, [&](const auto& other) { return other.get() == resource; });
|
||||||
|
}
|
256
src/protocols/XDGShell.hpp
Normal file
256
src/protocols/XDGShell.hpp
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
#include "WaylandProtocol.hpp"
|
||||||
|
#include "xdg-shell.hpp"
|
||||||
|
#include "../helpers/Vector2D.hpp"
|
||||||
|
#include "../helpers/Box.hpp"
|
||||||
|
#include "../helpers/signal/Signal.hpp"
|
||||||
|
|
||||||
|
class CXDGWMBase;
|
||||||
|
class CXDGPositionerResource;
|
||||||
|
class CXDGSurfaceResource;
|
||||||
|
class CXDGToplevelResource;
|
||||||
|
class CXDGPopupResource;
|
||||||
|
class CSeatGrab;
|
||||||
|
|
||||||
|
struct SXDGPositionerState {
|
||||||
|
Vector2D requestedSize;
|
||||||
|
CBox anchorRect;
|
||||||
|
xdgPositionerAnchor anchor = XDG_POSITIONER_ANCHOR_NONE;
|
||||||
|
xdgPositionerGravity gravity = XDG_POSITIONER_GRAVITY_NONE;
|
||||||
|
uint32_t constraintAdjustment = 0;
|
||||||
|
Vector2D offset;
|
||||||
|
bool reactive = false;
|
||||||
|
Vector2D parentSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGPositionerRules {
|
||||||
|
public:
|
||||||
|
CXDGPositionerRules(SP<CXDGPositionerResource> positioner);
|
||||||
|
|
||||||
|
CBox getPosition(const CBox& constraint, const Vector2D& parentPos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SXDGPositionerState state;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGPopupResource {
|
||||||
|
public:
|
||||||
|
CXDGPopupResource(SP<CXdgPopup> resource_, SP<CXDGSurfaceResource> parent_, SP<CXDGSurfaceResource> surface_, SP<CXDGPositionerResource> positioner_);
|
||||||
|
~CXDGPopupResource();
|
||||||
|
|
||||||
|
static SP<CXDGPopupResource> fromResource(wl_resource*);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
|
||||||
|
void applyPositioning(const CBox& availableBox, const Vector2D& t1coord /* relative to box */);
|
||||||
|
|
||||||
|
WP<CXDGSurfaceResource> surface;
|
||||||
|
WP<CXDGSurfaceResource> parent;
|
||||||
|
WP<CXDGPopupResource> self;
|
||||||
|
|
||||||
|
bool taken = false;
|
||||||
|
|
||||||
|
CBox geometry;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CSignal reposition;
|
||||||
|
CSignal destroy; // only the role
|
||||||
|
} events;
|
||||||
|
|
||||||
|
// schedules a configure event
|
||||||
|
void configure(const CBox& box);
|
||||||
|
|
||||||
|
void done();
|
||||||
|
void repositioned();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CXdgPopup> resource;
|
||||||
|
|
||||||
|
uint32_t lastRepositionToken = 0;
|
||||||
|
|
||||||
|
Vector2D accumulateParentOffset();
|
||||||
|
|
||||||
|
CXDGPositionerRules positionerRules;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGToplevelResource {
|
||||||
|
public:
|
||||||
|
CXDGToplevelResource(SP<CXdgToplevel> resource_, SP<CXDGSurfaceResource> owner_);
|
||||||
|
~CXDGToplevelResource();
|
||||||
|
|
||||||
|
static SP<CXDGToplevelResource> fromResource(wl_resource*);
|
||||||
|
|
||||||
|
WP<CXDGSurfaceResource> owner;
|
||||||
|
WP<CXDGToplevelResource> self;
|
||||||
|
|
||||||
|
PHLWINDOWREF window;
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
|
||||||
|
// schedule a configure event
|
||||||
|
uint32_t setSize(const Vector2D& size);
|
||||||
|
uint32_t setMaximized(bool maximized);
|
||||||
|
uint32_t setFullscreen(bool fullscreen);
|
||||||
|
uint32_t setActive(bool active);
|
||||||
|
uint32_t setSuspeneded(bool sus);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CSignal sizeLimitsChanged;
|
||||||
|
CSignal stateChanged; // maximized, fs, minimized, etc.
|
||||||
|
CSignal metadataChanged; // title, appid
|
||||||
|
CSignal destroy; // only the role
|
||||||
|
} events;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
std::string title;
|
||||||
|
std::string appid;
|
||||||
|
|
||||||
|
// volatile state: is reset after the stateChanged signal fires
|
||||||
|
std::optional<bool> requestsMaximize;
|
||||||
|
std::optional<bool> requestsFullscreen;
|
||||||
|
std::optional<bool> requestsMinimize;
|
||||||
|
} state;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Vector2D size;
|
||||||
|
std::vector<xdgToplevelState> states;
|
||||||
|
} pendingApply;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Vector2D minSize = {1, 1};
|
||||||
|
Vector2D maxSize = {1337420, 694200};
|
||||||
|
} pending, current;
|
||||||
|
|
||||||
|
WP<CXDGToplevelResource> parent;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CXdgToplevel> resource;
|
||||||
|
void applyState();
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGSurfaceResource {
|
||||||
|
public:
|
||||||
|
CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBase> owner_, wlr_surface* surface_);
|
||||||
|
~CXDGSurfaceResource();
|
||||||
|
|
||||||
|
static SP<CXDGSurfaceResource> fromResource(wl_resource*);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
|
||||||
|
WP<CXDGWMBase> owner;
|
||||||
|
wlr_surface* surface = nullptr;
|
||||||
|
|
||||||
|
WP<CXDGToplevelResource> toplevel;
|
||||||
|
WP<CXDGPopupResource> popup;
|
||||||
|
|
||||||
|
WP<CXDGSurfaceResource> self;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CBox geometry;
|
||||||
|
} pending, current;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CSignal ack;
|
||||||
|
CSignal commit;
|
||||||
|
CSignal map;
|
||||||
|
CSignal unmap;
|
||||||
|
CSignal destroy;
|
||||||
|
CSignal newPopup; // SP<CXDGPopupResource>
|
||||||
|
} events;
|
||||||
|
|
||||||
|
bool initialCommit = true;
|
||||||
|
bool mapped = false;
|
||||||
|
|
||||||
|
uint32_t scheduleConfigure();
|
||||||
|
// do not call directly
|
||||||
|
void configure();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CXdgSurface> resource;
|
||||||
|
|
||||||
|
uint32_t lastConfigureSerial = 0;
|
||||||
|
uint32_t scheduledSerial = 0;
|
||||||
|
|
||||||
|
wl_event_source* configureSource = nullptr;
|
||||||
|
|
||||||
|
//
|
||||||
|
std::vector<WP<CXDGPopupResource>> popups;
|
||||||
|
|
||||||
|
DYNLISTENER(surfaceDestroy);
|
||||||
|
DYNLISTENER(surfaceCommit);
|
||||||
|
|
||||||
|
friend class CXDGPopupResource;
|
||||||
|
friend class CXDGToplevelResource;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGPositionerResource {
|
||||||
|
public:
|
||||||
|
CXDGPositionerResource(SP<CXdgPositioner> resource_, SP<CXDGWMBase> owner_);
|
||||||
|
|
||||||
|
static SP<CXDGPositionerResource> fromResource(wl_resource*);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
|
||||||
|
SXDGPositionerState state;
|
||||||
|
|
||||||
|
WP<CXDGWMBase> owner;
|
||||||
|
WP<CXDGPositionerResource> self;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CXdgPositioner> resource;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGWMBase {
|
||||||
|
public:
|
||||||
|
CXDGWMBase(SP<CXdgWmBase> resource_);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
wl_client* client();
|
||||||
|
|
||||||
|
std::vector<WP<CXDGPositionerResource>> positioners;
|
||||||
|
std::vector<WP<CXDGSurfaceResource>> surfaces;
|
||||||
|
|
||||||
|
WP<CXDGWMBase> self;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CXdgWmBase> resource;
|
||||||
|
wl_client* pClient = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CXDGShellProtocol : public IWaylandProtocol {
|
||||||
|
public:
|
||||||
|
CXDGShellProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||||
|
|
||||||
|
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void destroyResource(CXDGWMBase* resource);
|
||||||
|
void destroyResource(CXDGPositionerResource* resource);
|
||||||
|
void destroyResource(CXDGSurfaceResource* resource);
|
||||||
|
void destroyResource(CXDGToplevelResource* resource);
|
||||||
|
void destroyResource(CXDGPopupResource* resource);
|
||||||
|
|
||||||
|
//
|
||||||
|
std::vector<SP<CXDGWMBase>> m_vWMBases;
|
||||||
|
std::vector<SP<CXDGPositionerResource>> m_vPositioners;
|
||||||
|
std::vector<SP<CXDGSurfaceResource>> m_vSurfaces;
|
||||||
|
std::vector<SP<CXDGToplevelResource>> m_vToplevels;
|
||||||
|
std::vector<SP<CXDGPopupResource>> m_vPopups;
|
||||||
|
|
||||||
|
friend class CXDGWMBase;
|
||||||
|
friend class CXDGPositionerResource;
|
||||||
|
friend class CXDGSurfaceResource;
|
||||||
|
friend class CXDGToplevelResource;
|
||||||
|
friend class CXDGPopupResource;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace PROTO {
|
||||||
|
inline UP<CXDGShellProtocol> xdgShell;
|
||||||
|
};
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
#include "../protocols/SessionLock.hpp"
|
#include "../protocols/SessionLock.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
|
#include "../protocols/XDGShell.hpp"
|
||||||
#include "../protocols/PresentationTime.hpp"
|
#include "../protocols/PresentationTime.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -615,9 +616,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
||||||
|
|
||||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
||||||
if (!pWindow->m_bIsX11) {
|
if (!pWindow->m_bIsX11) {
|
||||||
CBox geom;
|
CBox geom = pWindow->m_pXDGSurface->current.geometry;
|
||||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
|
||||||
geom.applyFromWlr();
|
|
||||||
|
|
||||||
renderdata.x -= geom.x;
|
renderdata.x -= geom.x;
|
||||||
renderdata.y -= geom.y;
|
renderdata.y -= geom.y;
|
||||||
|
@ -643,7 +642,20 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
||||||
if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying())
|
if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying())
|
||||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||||
|
|
||||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
pWindow->m_pPopupHead->breadthfirst(
|
||||||
|
[](CPopup* popup, void* data) {
|
||||||
|
if (!popup->m_sWLSurface.wlr())
|
||||||
|
return;
|
||||||
|
auto pos = popup->coordsRelativeToParent();
|
||||||
|
auto rd = (SRenderData*)data;
|
||||||
|
Vector2D oldPos = {rd->x, rd->y};
|
||||||
|
rd->x += pos.x;
|
||||||
|
rd->y += pos.y;
|
||||||
|
wlr_surface_for_each_surface(popup->m_sWLSurface.wlr(), renderSurface, rd);
|
||||||
|
rd->x = oldPos.x;
|
||||||
|
rd->y = oldPos.y;
|
||||||
|
},
|
||||||
|
&renderdata);
|
||||||
|
|
||||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||||
|
|
||||||
|
@ -1000,9 +1012,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa
|
||||||
if (!main || !pWindow)
|
if (!main || !pWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox geom;
|
CBox geom = pWindow->m_pXDGSurface->current.geometry;
|
||||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
|
||||||
geom.applyFromWlr();
|
|
||||||
|
|
||||||
// ignore X and Y, adjust uv
|
// ignore X and Y, adjust uv
|
||||||
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) {
|
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) {
|
||||||
|
@ -2530,8 +2540,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
|
||||||
if (PCANDIDATE->m_bIsX11) {
|
if (PCANDIDATE->m_bIsX11) {
|
||||||
surfaceCount = 1;
|
surfaceCount = 1;
|
||||||
} else {
|
} else {
|
||||||
wlr_xdg_surface_for_each_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount);
|
surfaceCount = PCANDIDATE->popupsCount() + PCANDIDATE->surfacesCount();
|
||||||
wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surfaceCount > 1)
|
if (surfaceCount > 1)
|
||||||
|
|
Loading…
Reference in a new issue