mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-30 11:41:53 -07:00
Compare commits
62 Commits
v0.13.1bet
...
v0.14.0bet
Author | SHA1 | Date | |
---|---|---|---|
|
d3ffccd45f | ||
|
d49af1cc18 | ||
|
8b46d0b5a9 | ||
|
336883dda3 | ||
|
65ec8c7694 | ||
|
79c645f8cd | ||
|
d44cc9f112 | ||
|
1963da2d47 | ||
|
2b99dbb446 | ||
|
d24f31de51 | ||
|
8b11a2e1b1 | ||
|
b4bcba935d | ||
|
7f3750bd75 | ||
|
7a9423c782 | ||
|
6f98b3cbd8 | ||
|
2dd1661aec | ||
|
cde624ec6a | ||
|
b82621c4ec | ||
|
5b6c8d5b0f | ||
|
4dca2b945b | ||
|
a8943246a7 | ||
|
e42de0b778 | ||
|
5146165599 | ||
|
73e19aee6f | ||
|
3780361b95 | ||
|
ec6144e5da | ||
|
b6eaeffcf6 | ||
|
c24b45671a | ||
|
85c7aaf155 | ||
|
696253b348 | ||
|
abb6db9c37 | ||
|
18b483b8e1 | ||
|
7c809a3059 | ||
|
4070e1a148 | ||
|
dd61f88ed1 | ||
|
29626989e7 | ||
|
cf32d28082 | ||
|
5131a4acaf | ||
|
a72a39ebd5 | ||
|
151e013241 | ||
|
fa2d81b649 | ||
|
037d4ed422 | ||
|
9f82278d65 | ||
|
8e0f7b9b11 | ||
|
a96acc8fa4 | ||
|
5a146e9d90 | ||
|
da10022d84 | ||
|
e518adf1ac | ||
|
d8dbe26f31 | ||
|
e9f226797e | ||
|
7d4f0a3199 | ||
|
0062281092 | ||
|
81f267dff9 | ||
|
a09c614c2d | ||
|
b49d7007b5 | ||
|
864e227f5d | ||
|
82aa78916d | ||
|
f024d7114f | ||
|
8808d40008 | ||
|
d94fe3d063 | ||
|
f663fa209c | ||
|
9370c7aa8a |
@@ -29,8 +29,6 @@ input {
|
||||
}
|
||||
|
||||
general {
|
||||
main_mod=SUPER
|
||||
|
||||
gaps_in=5
|
||||
gaps_out=20
|
||||
border_size=2
|
||||
@@ -75,6 +73,10 @@ gestures {
|
||||
#windowrule=pseudo,abc
|
||||
#windowrule=monitor 0,xyz
|
||||
|
||||
# some nice mouse binds
|
||||
bindm=SUPER,mouse:272,movewindow
|
||||
bindm=SUPER,mouse:273,resizewindow
|
||||
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,C,killactive,
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1661931183,
|
||||
"narHash": "sha256-0+2KzcexiJCB3Il5t7cZAM2RXNRfm5/gMCwhcZJxLuQ=",
|
||||
"lastModified": 1663494472,
|
||||
"narHash": "sha256-fSowlaoXXWcAM8m9wA6u+eTJJtvruYHMA+Lb/tFi/qM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "97747d3209efde533f7b1b28f1be11619f556a06",
|
||||
"rev": "f677051b8dc0b5e2a9348941c99eea8c4b0ff28f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1661882030,
|
||||
"narHash": "sha256-Kw0MG4rXdTnbndVLLCNwkXDmNszwdQZmm7pwI1R3Kds=",
|
||||
"lastModified": 1663507239,
|
||||
"narHash": "sha256-LISZtkPVe8lQ2N8YwVe+KxCkXWLP9mdw6Q2kG93wE8A=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "fd0b0276c9ecc159549acff48b932b83ec3b4f12",
|
||||
"rev": "2ad25b1460400e66ea26bd6489b04072be7d9dbb",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
26
flake.nix
26
flake.nix
@@ -20,7 +20,31 @@
|
||||
"aarch64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
pkgsFor = nixpkgs.legacyPackages;
|
||||
pkgsFor = genSystems (system:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
(_: prev: {
|
||||
libdrm = prev.libdrm.overrideAttrs (old: rec {
|
||||
version = "2.4.113";
|
||||
src = prev.fetchurl {
|
||||
url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz";
|
||||
sha256 = "sha256-f9frKWf2O+tGBvItUOJ32ZNIDQXvdd2Iqb2OZ3Mj5eE=";
|
||||
};
|
||||
mesonFlags =
|
||||
[
|
||||
"-Dinstall-test-programs=true"
|
||||
"-Domap=enabled"
|
||||
"-Dcairo-tests=disabled"
|
||||
]
|
||||
++ lib.optionals prev.stdenv.hostPlatform.isAarch [
|
||||
"-Dtegra=enabled"
|
||||
"-Detnaviv=enabled"
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
});
|
||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||
(__substring 0 4 longDate)
|
||||
(__substring 4 2 longDate)
|
||||
|
@@ -67,6 +67,16 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
recommendedEnvironment = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
defaultText = lib.literalExpression "true";
|
||||
example = lib.literalExpression "false";
|
||||
description = ''
|
||||
Whether to set the recommended environment variables.
|
||||
'';
|
||||
};
|
||||
|
||||
imports = [
|
||||
(
|
||||
lib.mkRenamedOptionModule
|
||||
@@ -81,14 +91,10 @@ in {
|
||||
lib.optional (cfg.package != null) cfg.package
|
||||
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
|
||||
|
||||
home.sessionVariables = {
|
||||
CLUTTER_BACKEND = "wayland";
|
||||
home.sessionVariables = lib.mkIf cfg.recommendedEnvironment {
|
||||
GDK_BACKEND = "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
||||
MOZ_ENABLE_WAYLAND = "1";
|
||||
NIXOS_OZONE_WL = "1";
|
||||
QT_QPA_PLATFORM = "wayland;xcb";
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
||||
XCURSOR_SIZE = toString config.home.pointerCursor.size or "24";
|
||||
XDG_SESSION_TYPE = "wayland";
|
||||
};
|
||||
|
@@ -30,21 +30,28 @@ in {
|
||||
Hyprland package to use.
|
||||
'';
|
||||
};
|
||||
|
||||
recommendedEnvironment = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
defaultText = literalExpression "true";
|
||||
example = literalExpression "false";
|
||||
description = ''
|
||||
Whether to set the recommended environment variables.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment = {
|
||||
systemPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
sessionVariables = {
|
||||
CLUTTER_BACKEND = lib.mkDefault "wayland";
|
||||
GDK_BACKEND = lib.mkDefault "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = lib.mkDefault "1";
|
||||
MOZ_ENABLE_WAYLAND = lib.mkDefault "1";
|
||||
NIXOS_OZONE_WL = lib.mkDefault "1";
|
||||
QT_QPA_PLATFORM = lib.mkDefault "wayland;xcb";
|
||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = lib.mkDefault "1";
|
||||
XCURSOR_SIZE = lib.mkDefault "24";
|
||||
XDG_SESSION_TYPE = lib.mkDefault "wayland";
|
||||
|
||||
sessionVariables = mkIf cfg.recommendedEnvironment {
|
||||
GDK_BACKEND = "wayland";
|
||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
||||
NIXOS_OZONE_WL = "1";
|
||||
XCURSOR_SIZE = "24";
|
||||
XDG_SESSION_TYPE = "wayland";
|
||||
};
|
||||
};
|
||||
fonts.enableDefaultFonts = mkDefault true;
|
||||
|
@@ -245,7 +245,6 @@ void CCompositor::cleanup() {
|
||||
|
||||
// end threads
|
||||
g_pEventManager->m_tThread = std::thread();
|
||||
HyprCtl::tThread = std::thread();
|
||||
|
||||
m_vWorkspaces.clear();
|
||||
m_vWindows.clear();
|
||||
@@ -454,10 +453,17 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->m_bHidden && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -517,10 +523,29 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned windows on top of floating regardless
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus && (*w)->m_bPinned) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
return w->get();
|
||||
|
||||
if (!(*w)->m_bIsX11) {
|
||||
wlr_surface* resultSurf = nullptr;
|
||||
Vector2D origin = (*w)->m_vRealPosition.vec();
|
||||
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||
wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data);
|
||||
|
||||
if (resultSurf)
|
||||
return w->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus) {
|
||||
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus && !(*w)->m_bPinned) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
return w->get();
|
||||
|
||||
@@ -574,10 +599,17 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID))
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -593,7 +625,13 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->m_bHidden && (*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bPinned)
|
||||
return w->get();
|
||||
}
|
||||
|
||||
@@ -676,6 +714,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned)
|
||||
pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace;
|
||||
|
||||
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
g_pKeybindManager->changeworkspace("[internal]" + std::to_string(pWindow->m_iWorkspaceID));
|
||||
|
||||
@@ -785,7 +826,7 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
|
||||
|
||||
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
|
||||
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
|
||||
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
|
||||
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped) || (*it)->alpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
|
||||
@@ -1399,6 +1440,17 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
|
||||
}
|
||||
}
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pMonitorA->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = PWORKSPACEB->m_iID;
|
||||
}
|
||||
|
||||
if (w->m_iWorkspaceID == pMonitorB->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = PWORKSPACEA->m_iID;
|
||||
}
|
||||
}
|
||||
|
||||
pMonitorA->activeWorkspace = PWORKSPACEB->m_iID;
|
||||
pMonitorB->activeWorkspace = PWORKSPACEA->m_iID;
|
||||
|
||||
@@ -1431,6 +1483,9 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (name == "current")
|
||||
return g_pCompositor->m_pLastMonitor;
|
||||
|
||||
if (isDirection(name)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorInDirection(name[0]);
|
||||
return PMONITOR;
|
||||
@@ -1536,6 +1591,9 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : m_vWorkspaces) {
|
||||
if (w->m_iID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
@@ -1550,7 +1608,10 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
if (!windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
focusWindow(pWindow);
|
||||
if (pWindow->m_bPinned) {
|
||||
Debug::log(LOG, "Pinned windows cannot be fullscreen'd");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
|
||||
|
||||
@@ -1558,8 +1619,18 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
|
||||
// make all windows on the same workspace under the fullscreen window
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
|
||||
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID) {
|
||||
w->m_bCreatedOverFullscreen = false;
|
||||
if (w.get() != pWindow && !w->m_bFadingOut && !w->m_bPinned)
|
||||
w->m_fAlpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (!ls->fadingOut)
|
||||
ls->alpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
|
||||
@@ -1663,25 +1734,6 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wl_event_source* hyprCtlTickSource = nullptr;
|
||||
|
||||
int hyprCtlTick(void* data) {
|
||||
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
|
||||
|
||||
wl_event_source_timer_update(hyprCtlTickSource, 16); // tick it 60/s, should be enough.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CCompositor::startHyprCtlTick() {
|
||||
if (hyprCtlTickSource)
|
||||
return;
|
||||
|
||||
hyprCtlTickSource = wl_event_loop_add_timer(m_sWLEventLoop, hyprCtlTick, nullptr);
|
||||
|
||||
wl_event_source_timer_update(hyprCtlTickSource, 16);
|
||||
}
|
||||
|
||||
void CCompositor::warpCursorTo(const Vector2D& pos) {
|
||||
|
||||
// warpCursorTo should only be used for warps that
|
||||
|
@@ -166,11 +166,8 @@ public:
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
bool cursorOnReservedArea();
|
||||
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
void startHyprCtlTick();
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void setRandomSplash();
|
||||
|
@@ -97,8 +97,7 @@ void CWindow::updateWindowDecos() {
|
||||
pid_t CWindow::getPID() {
|
||||
pid_t PID = -1;
|
||||
if (!m_bIsX11) {
|
||||
const auto CLIENT = wl_resource_get_client(m_uSurface.xdg->resource);
|
||||
wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr);
|
||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
||||
} else {
|
||||
PID = m_uSurface.xwayland->pid;
|
||||
}
|
||||
@@ -212,10 +211,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
if (m_iWorkspaceID != workspaceID) {
|
||||
m_iWorkspaceID = workspaceID;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
if (PWORKSPACE) {
|
||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -119,6 +119,9 @@ public:
|
||||
// For hidden windows and stuff
|
||||
bool m_bHidden = false;
|
||||
|
||||
// For pinned (sticky) windows
|
||||
bool m_bPinned = false;
|
||||
|
||||
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
||||
CWindow* m_pLastCycledWindow = nullptr;
|
||||
|
||||
|
@@ -57,6 +57,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["misc:always_follow_on_dnd"].intValue = 1;
|
||||
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
|
||||
configValues["misc:animate_manual_resizes"].intValue = 0;
|
||||
configValues["misc:disable_autoreload"].intValue = 0;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -492,11 +493,16 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
|
||||
nextItem();
|
||||
|
||||
if (curitem != "") {
|
||||
// warning for old cfg
|
||||
Debug::log(ERR, "Error in parsing rule for %s, possibly old config!", newrule.name.c_str());
|
||||
parseError = "Error in setting monitor rule. Are you using the old syntax? Confront the wiki.";
|
||||
return;
|
||||
while (curitem != "") {
|
||||
if (curitem == "mirror") {
|
||||
nextItem();
|
||||
newrule.mirrorOf = curitem;
|
||||
nextItem();
|
||||
} else {
|
||||
Debug::log(ERR, "Config error: invalid monitor syntax");
|
||||
parseError = "invalid syntax at \"" + curitem + "\"";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
|
||||
@@ -652,6 +658,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
bool locked = false;
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
bool mouse = false;
|
||||
const auto ARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : ARGS) {
|
||||
@@ -661,6 +668,8 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
release = true;
|
||||
} else if (arg == 'e') {
|
||||
repeat = true;
|
||||
} else if (arg == 'm') {
|
||||
mouse = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
@@ -672,6 +681,11 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse && (repeat || release || locked)) {
|
||||
parseError = "flag m is exclusive";
|
||||
return;
|
||||
}
|
||||
|
||||
auto valueCopy = value;
|
||||
|
||||
const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(",")));
|
||||
@@ -681,10 +695,16 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
const auto KEY = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
|
||||
const auto HANDLER = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
auto HANDLER = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||
|
||||
const auto COMMAND = valueCopy;
|
||||
const auto COMMAND = mouse ? HANDLER : valueCopy;
|
||||
|
||||
if (mouse)
|
||||
HANDLER = "mouse";
|
||||
|
||||
// to lower
|
||||
std::transform(HANDLER.begin(), HANDLER.end(), HANDLER.begin(), ::tolower);
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(HANDLER);
|
||||
|
||||
@@ -707,11 +727,10 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
|
||||
@@ -739,6 +758,7 @@ bool windowRuleValid(const std::string& RULE) {
|
||||
&& RULE != "opaque"
|
||||
&& RULE != "forceinput"
|
||||
&& RULE != "fullscreen"
|
||||
&& RULE != "pin"
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("rounding") != 0
|
||||
&& RULE.find("workspace") != 0);
|
||||
@@ -911,6 +931,13 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::handleBindWS(const std::string& command, const std::string& value) {
|
||||
const auto WS = value.substr(0, value.find_first_of(','));
|
||||
const auto MON = value.substr(value.find_first_of(',') + 1);
|
||||
|
||||
boundWorkspaces.push_back({WS, MON});
|
||||
}
|
||||
|
||||
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE, bool dynamic) {
|
||||
if (dynamic) {
|
||||
parseError = "";
|
||||
@@ -939,6 +966,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
||||
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
|
||||
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
|
||||
else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE);
|
||||
else
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
|
||||
@@ -1050,6 +1078,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
configDynamicVars.clear();
|
||||
deviceConfigs.clear();
|
||||
m_dBlurLSNamespaces.clear();
|
||||
boundWorkspaces.clear();
|
||||
setDefaultAnimationVars(); // reset anims
|
||||
|
||||
// paths
|
||||
@@ -1433,6 +1462,10 @@ void CConfigManager::performMonitorReload() {
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
auto rule = getMonitorRuleFor(m->szName);
|
||||
|
||||
// ensure mirror
|
||||
m->setMirror(rule.mirrorOf);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
@@ -1498,3 +1531,15 @@ void CConfigManager::addParseError(const std::string& err) {
|
||||
if (parseError == "")
|
||||
parseError = err;
|
||||
}
|
||||
|
||||
CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
|
||||
for (auto&[ws, mon] : boundWorkspaces) {
|
||||
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return g_pCompositor->getMonitorFromString(mon);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ struct SMonitorRule {
|
||||
std::string defaultWorkspace = "";
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
@@ -93,6 +94,8 @@ public:
|
||||
|
||||
SMonitorRule getMonitorRuleFor(std::string);
|
||||
|
||||
CMonitor* getBoundMonitorForWS(std::string);
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
@@ -129,6 +132,8 @@ private:
|
||||
|
||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
@@ -164,6 +169,7 @@ private:
|
||||
void handleSource(const std::string&, const std::string&);
|
||||
void handleSubmap(const std::string&, const std::string&);
|
||||
void handleBlurLS(const std::string&, const std::string&);
|
||||
void handleBindWS(const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
@@ -83,6 +83,10 @@ gestures {
|
||||
#windowrule=pseudo,abc
|
||||
#windowrule=monitor 0,xyz
|
||||
|
||||
# some nice mouse binds
|
||||
bindm=SUPER,mouse:272,movewindow
|
||||
bindm=SUPER,mouse:273,resizewindow
|
||||
|
||||
# example binds
|
||||
bind=SUPER,Q,exec,kitty
|
||||
bind=SUPER,RETURN,exec,alacritty
|
||||
|
@@ -85,7 +85,8 @@ R"#({
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %s
|
||||
"xwayland": %s,
|
||||
"pinned": %s
|
||||
},)#",
|
||||
w.get(),
|
||||
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
|
||||
@@ -96,7 +97,8 @@ R"#({
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
|
||||
w->getPID(),
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false")
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false"),
|
||||
(w->m_bPinned ? "true" : "false")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -109,8 +111,8 @@ R"#({
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped) {
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
|
||||
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11);
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: %i\n\n",
|
||||
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -294,10 +296,12 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
"name": "%s",
|
||||
"defaultSpeed": %f
|
||||
},)#",
|
||||
&m,
|
||||
escapeJSONStrings(m.mouse->name).c_str()
|
||||
escapeJSONStrings(m.mouse->name).c_str(),
|
||||
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f
|
||||
);
|
||||
}
|
||||
|
||||
@@ -377,6 +381,23 @@ R"#( {
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
result += "\n],\n";
|
||||
|
||||
result += "\"touch\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTouchDevices) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
},)#",
|
||||
&d,
|
||||
d.pWlrDevice ? d.pWlrDevice->name : ""
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result[result.size() - 1] == ',')
|
||||
result.pop_back();
|
||||
@@ -388,7 +409,7 @@ R"#( {
|
||||
result += "mice:\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.mouse->name, (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
@@ -411,6 +432,12 @@ R"#( {
|
||||
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||
}
|
||||
|
||||
result += "\n\nTouch:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTouchDevices) {
|
||||
result += getFormat("\tTouch Device at %x:\n\t\t%s\n", &d, d.pWlrDevice ? d.pWlrDevice->name : "");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -526,6 +553,8 @@ std::string reloadRequest(std::string request) {
|
||||
g_pConfigManager->m_bNoMonitorReload = true;
|
||||
}
|
||||
|
||||
g_pConfigManager->tick();
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@@ -719,9 +748,21 @@ std::string getReply(std::string request) {
|
||||
return "unknown request";
|
||||
}
|
||||
|
||||
void HyprCtl::tickHyprCtl() {
|
||||
if (!requestMade)
|
||||
return;
|
||||
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
||||
char readBuffer[1024];
|
||||
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
|
||||
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
|
||||
|
||||
std::string request(readBuffer);
|
||||
|
||||
std::string reply = "";
|
||||
|
||||
@@ -732,88 +773,38 @@ void HyprCtl::tickHyprCtl() {
|
||||
reply = "Err: " + std::string(e.what());
|
||||
}
|
||||
|
||||
request = reply;
|
||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
||||
|
||||
requestMade = false;
|
||||
requestReady = true;
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload) {
|
||||
g_pConfigManager->ensureDPMS();
|
||||
}
|
||||
}
|
||||
|
||||
std::string getRequestFromThread(std::string rq) {
|
||||
|
||||
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
HyprCtl::request = rq;
|
||||
HyprCtl::requestMade = true;
|
||||
|
||||
while (!HyprCtl::requestReady) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
HyprCtl::requestReady = false;
|
||||
HyprCtl::requestMade = false;
|
||||
|
||||
std::string toReturn = HyprCtl::request;
|
||||
|
||||
HyprCtl::request = "";
|
||||
|
||||
return toReturn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HyprCtl::startHyprCtlSocket() {
|
||||
tThread = std::thread([&]() {
|
||||
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SOCKET < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
if (iSocketFD < 0) {
|
||||
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||
|
||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
|
||||
// 10 max queued.
|
||||
listen(SOCKET, 10);
|
||||
bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
// 10 max queued.
|
||||
listen(iSocketFD, 10);
|
||||
|
||||
char readBuffer[1024] = {0};
|
||||
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||
|
||||
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||
|
||||
while(1) {
|
||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
||||
if (ACCEPTEDCONNECTION < 0) {
|
||||
Debug::log(ERR, "Couldn't listen on the Hyprland Socket. (3) IPC will not work.");
|
||||
break;
|
||||
}
|
||||
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
|
||||
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
|
||||
|
||||
std::string request(readBuffer);
|
||||
|
||||
std::string reply = getRequestFromThread(request);
|
||||
|
||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
||||
|
||||
close(ACCEPTEDCONNECTION);
|
||||
}
|
||||
|
||||
close(SOCKET);
|
||||
});
|
||||
|
||||
tThread.detach();
|
||||
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
namespace HyprCtl {
|
||||
void startHyprCtlSocket();
|
||||
void tickHyprCtl();
|
||||
|
||||
// very simple thread-safe request method
|
||||
inline bool requestMade = false;
|
||||
@@ -15,7 +14,9 @@ namespace HyprCtl {
|
||||
|
||||
inline std::ifstream requestStream;
|
||||
|
||||
inline std::thread tThread;
|
||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
||||
|
||||
inline int iSocketFD = -1;
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
|
@@ -72,7 +72,7 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
|
||||
g_pInputManager->newTouchDevice(DEVICE);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
|
||||
|
@@ -190,7 +190,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
}
|
||||
|
||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
@@ -224,38 +224,45 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
// potentially can save on resources.
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
if (PMONITOR->isMirror()) {
|
||||
g_pHyprOpenGL->renderMirrored();
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
Debug::log(LOG, "Mirror frame");
|
||||
} else {
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (PMONITOR->ID == 0)
|
||||
g_pHyprError->draw();
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255, 0, 255, 100), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
damageBlinkCleanup++;
|
||||
if (damageBlinkCleanup > 3)
|
||||
damageBlinkCleanup = 0;
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
damageBlinkCleanup++;
|
||||
if (damageBlinkCleanup > 3)
|
||||
damageBlinkCleanup = 0;
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
|
||||
// calc frame damage
|
||||
@@ -272,10 +279,15 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
||||
|
||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||
|
||||
if (!PMONITOR->mirrors.empty())
|
||||
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
|
||||
|
||||
pixman_region32_fini(&frameDamage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
wlr_output_commit(PMONITOR->output);
|
||||
if (!wlr_output_commit(PMONITOR->output))
|
||||
return;
|
||||
|
||||
if (*PDAMAGEBLINK || *PNOVFR)
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
@@ -162,6 +162,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_sAdditionalConfigData.forceOpaque = true;
|
||||
} else if (r.szRule == "forceinput") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
|
||||
} else if (r.szRule == "pin") {
|
||||
PWINDOW->m_bPinned = true;
|
||||
} else if (r.szRule.find("rounding") == 0) {
|
||||
try {
|
||||
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
@@ -188,6 +190,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
// disallow tiled pinned
|
||||
if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating)
|
||||
PWINDOW->m_bPinned = false;
|
||||
|
||||
if (requestedWorkspace != "") {
|
||||
// process requested workspace
|
||||
if (requestedWorkspace.contains(' ')) {
|
||||
@@ -338,8 +344,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
|
||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
@@ -400,9 +405,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, false);
|
||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
|
||||
g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// Allow the renderer to catch the last frame.
|
||||
|
@@ -1,9 +1,7 @@
|
||||
#include "Color.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
CColor::CColor() {
|
||||
|
||||
}
|
||||
CColor::CColor() { }
|
||||
|
||||
CColor::CColor(float r, float g, float b, float a) {
|
||||
this->r = r;
|
||||
|
@@ -221,6 +221,9 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
|
@@ -65,6 +65,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
}
|
||||
|
||||
if (!m_bRenderingInitPassed) {
|
||||
output->allocator = nullptr;
|
||||
output->renderer = nullptr;
|
||||
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||
m_bRenderingInitPassed = true;
|
||||
}
|
||||
@@ -115,50 +117,14 @@ void CMonitor::onConnect(bool noRule) {
|
||||
}
|
||||
|
||||
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
|
||||
|
||||
setupDefaultWS(monitorRule);
|
||||
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
scale = monitorRule.scale;
|
||||
|
||||
m_pThisWrap = nullptr;
|
||||
|
||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
//
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
@@ -186,6 +152,20 @@ void CMonitor::onDisconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
// remove mirror
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
pMirrorOf = nullptr;
|
||||
}
|
||||
|
||||
if (!mirrors.empty()) {
|
||||
for (auto& m : mirrors) {
|
||||
m->setMirror("");
|
||||
}
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
@@ -246,3 +226,136 @@ void CMonitor::addDamage(pixman_region32_t* rg) {
|
||||
void CMonitor::addDamage(wlr_box* box) {
|
||||
wlr_output_damage_add_box(damage, box);
|
||||
}
|
||||
|
||||
bool CMonitor::isMirror() {
|
||||
return pMirrorOf != nullptr;
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||
PNEWWORKSPACE->startAnim(true, true, true);
|
||||
} else {
|
||||
if (newDefaultWorkspaceName == "")
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
}
|
||||
|
||||
activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
}
|
||||
|
||||
void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
const auto PMIRRORMON = g_pCompositor->getMonitorFromString(mirrorOf);
|
||||
|
||||
if (PMIRRORMON == pMirrorOf)
|
||||
return;
|
||||
|
||||
if (PMIRRORMON && PMIRRORMON->isMirror()) {
|
||||
Debug::log(ERR, "Cannot mirror a mirror!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PMIRRORMON == this) {
|
||||
Debug::log(ERR, "Cannot mirror self!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PMIRRORMON) {
|
||||
// disable mirroring
|
||||
|
||||
if (pMirrorOf) {
|
||||
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
|
||||
}
|
||||
|
||||
pMirrorOf = nullptr;
|
||||
|
||||
// set rule
|
||||
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName);
|
||||
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
// push to mvmonitors
|
||||
if (!m_pThisWrap) {
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
|
||||
setupDefaultWS(RULE);
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
|
||||
} else {
|
||||
CMonitor* BACKUPMON = nullptr;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m.get() != this) {
|
||||
BACKUPMON = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move all the WS
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : wspToMove) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||
w->startAnim(true, true, true);
|
||||
}
|
||||
|
||||
activeWorkspace = -1;
|
||||
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
|
||||
vecPosition = Vector2D(-1337420, -1337420);
|
||||
|
||||
pMirrorOf = PMIRRORMON;
|
||||
|
||||
pMirrorOf->mirrors.push_back(this);
|
||||
|
||||
// remove from mvmonitors
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
|
||||
}
|
||||
|
||||
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
struct SMonitorRule;
|
||||
|
||||
class CMonitor {
|
||||
public:
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
@@ -35,6 +37,10 @@ public:
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// mirroring
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
std::vector<CMonitor*> mirrors;
|
||||
|
||||
// for the special workspace
|
||||
bool specialWorkspaceOpen = false;
|
||||
|
||||
@@ -57,6 +63,8 @@ public:
|
||||
void onDisconnect();
|
||||
void addDamage(pixman_region32_t* rg);
|
||||
void addDamage(wlr_box* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
@@ -67,4 +75,7 @@ public:
|
||||
bool operator==(const CMonitor& rhs) {
|
||||
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
||||
}
|
||||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
};
|
@@ -101,6 +101,14 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
}
|
||||
|
||||
// remove references to this node
|
||||
for (auto& tn : surfaceTreeNodes) {
|
||||
for (auto& cs : tn.childSubsurfaces) {
|
||||
if (cs.pChild == pNode)
|
||||
cs.pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
surfaceTreeNodes.remove(*pNode);
|
||||
|
||||
Debug::log(LOG, "SurfaceTree Node removed");
|
||||
@@ -154,6 +162,9 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||
void Events::listener_mapSubsurface(void* owner, void* data) {
|
||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
||||
|
||||
if (subsurface->pChild)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
||||
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||
@@ -170,18 +181,16 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {0};
|
||||
wlr_box extents = {lx, ly, 0, 0};
|
||||
if (PNODE->pSurface) {
|
||||
wlr_surface_get_extends(PNODE->pSurface, &extents);
|
||||
|
||||
extents.x += lx;
|
||||
extents.y += ly;
|
||||
extents.width = PNODE->pSurface->current.width;
|
||||
extents.height = PNODE->pSurface->current.height;
|
||||
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
}
|
||||
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
subsurface->pChild = nullptr;
|
||||
//SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
//subsurface->pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +226,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
||||
|
||||
if (subsurface->pChild)
|
||||
listener_destroySubsurfaceNode(subsurface->pChild, nullptr);
|
||||
if (subsurface->pChild) {
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
|
||||
|
||||
|
@@ -322,3 +322,13 @@ struct SIMEPopup {
|
||||
return pSurface == other.pSurface;
|
||||
}
|
||||
};
|
||||
|
||||
struct STouchDevice {
|
||||
wlr_input_device* pWlrDevice = nullptr;
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const STouchDevice& other) {
|
||||
return pWlrDevice == other.pWlrDevice;
|
||||
}
|
||||
};
|
||||
|
@@ -91,6 +91,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_vRenderOffset.warp();
|
||||
m_fAlpha.warp();
|
||||
}
|
||||
|
||||
// check LS-es
|
||||
if (in) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (!ls->fadingOut)
|
||||
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWorkspace::setActive(bool on) {
|
||||
|
@@ -327,6 +327,13 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
@@ -448,6 +455,9 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
// check if it was grouped
|
||||
if (PNODE->isGroupMember()) {
|
||||
// get shit
|
||||
@@ -682,10 +692,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
@@ -785,12 +792,13 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
fullscreenRequestForWindow(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FULLSCREEN_FULL, false);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PNODE->isGroupMember()) {
|
||||
Debug::log(ERR, "Cannot enable group on fullscreen window");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE->isGroupMember()) {
|
||||
// dissolve group
|
||||
|
||||
const auto PHEAD = PNODE->getGroupHead();
|
||||
|
||||
SDwindleNodeData* current = PNODE->pNextGroupMember;
|
||||
@@ -928,7 +936,7 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWindow* forceTo) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return; // reject
|
||||
|
||||
@@ -946,10 +954,18 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
|
||||
else
|
||||
pNewNode = PNODE->pPreviousGroupMember;
|
||||
|
||||
if (forceTo) {
|
||||
const auto NODETO = getNodeFromWindow(forceTo);
|
||||
|
||||
if (NODETO)
|
||||
pNewNode = NODETO;
|
||||
}
|
||||
|
||||
PNODE->setGroupFocusedNode(pNewNode);
|
||||
|
||||
pNewNode->position = PNODE->position;
|
||||
pNewNode->size = PNODE->size;
|
||||
pNewNode->workspaceID = PNODE->workspaceID;
|
||||
|
||||
applyNodeDataToWindow(pNewNode);
|
||||
|
||||
@@ -1001,58 +1017,101 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
|
||||
void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
// windows should be valid, insallah
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
const auto PNODE2 = getNodeFromWindow(pWindow2);
|
||||
auto PNODE = getNodeFromWindow(pWindow);
|
||||
auto PNODE2 = getNodeFromWindow(pWindow2);
|
||||
|
||||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
if (!PNODE2 || !PNODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Dwindle: Rejecting a swap between workspaces");
|
||||
return;
|
||||
}
|
||||
SDwindleNodeData* ACTIVE1 = nullptr;
|
||||
SDwindleNodeData* ACTIVE2 = nullptr;
|
||||
|
||||
// we will not delete the nodes, just fix the tree
|
||||
if (PNODE2->pParent == PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
|
||||
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
PPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[0] = PNODE;
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
} else {
|
||||
if (PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Groups are confined to a monitor");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PNODE2->pParent) {
|
||||
const auto PPARENT = PNODE2->pParent;
|
||||
if (PNODE->isGroupMember()) {
|
||||
ACTIVE1 = PNODE;
|
||||
PNODE = PNODE->getGroupHead();
|
||||
}
|
||||
|
||||
if (PPARENT->children[0] == PNODE2) {
|
||||
PPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PNODE2->isGroupMember()) {
|
||||
ACTIVE2 = PNODE2;
|
||||
PNODE2 = PNODE2->getGroupHead();
|
||||
}
|
||||
|
||||
const auto PPARENTNODE2 = PNODE2->pParent;
|
||||
PNODE2->pParent = PNODE->pParent;
|
||||
PNODE->pParent = PPARENTNODE2;
|
||||
if (PNODE2->pParent == PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
// these are window nodes, so no children.
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
PPARENT->children[1] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[0] = PNODE;
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
} else {
|
||||
if (PNODE->pParent) {
|
||||
const auto PPARENT = PNODE->pParent;
|
||||
|
||||
// recalc the workspace
|
||||
if (PPARENT->children[0] == PNODE) {
|
||||
PPARENT->children[0] = PNODE2;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE2;
|
||||
}
|
||||
}
|
||||
|
||||
if (PNODE2->pParent) {
|
||||
const auto PPARENT = PNODE2->pParent;
|
||||
|
||||
if (PPARENT->children[0] == PNODE2) {
|
||||
PPARENT->children[0] = PNODE;
|
||||
} else {
|
||||
PPARENT->children[1] = PNODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto PPARENTNODE2 = PNODE2->pParent;
|
||||
PNODE2->pParent = PNODE->pParent;
|
||||
PNODE->pParent = PPARENTNODE2;
|
||||
|
||||
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
|
||||
} else {
|
||||
// swap the windows and recalc
|
||||
PNODE2->pWindow = pWindow;
|
||||
PNODE->pWindow = pWindow2;
|
||||
}
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
||||
}
|
||||
|
||||
// recalc the workspace
|
||||
getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive();
|
||||
|
||||
if (PNODE2->workspaceID != PNODE->workspaceID) {
|
||||
getMasterNodeOnWorkspace(PNODE2->workspaceID)->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
if (ACTIVE1) {
|
||||
ACTIVE1->position = PNODE->position;
|
||||
ACTIVE1->size = PNODE->size;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
|
||||
}
|
||||
|
||||
if (ACTIVE2) {
|
||||
ACTIVE2->position = PNODE2->position;
|
||||
ACTIVE2->size = PNODE2->size;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
@@ -1078,7 +1137,7 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
|
||||
else if (message == "togglesplit")
|
||||
toggleSplit(header.pWindow);
|
||||
else if (message == "groupinfo") {
|
||||
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
|
||||
auto res = getGroupMembers(header.pWindow ? header.pWindow : g_pCompositor->m_pLastWindow);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -75,7 +75,7 @@ private:
|
||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
|
||||
void toggleWindowGroup(CWindow*);
|
||||
void switchGroupWindow(CWindow*, bool forward);
|
||||
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
|
||||
void toggleSplit(CWindow*);
|
||||
std::deque<CWindow*> getGroupMembers(CWindow*);
|
||||
|
||||
|
@@ -64,8 +64,24 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
// check if it's on the correct monitor!
|
||||
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
|
||||
|
||||
// check if it's visible on any monitor (only for XDG)
|
||||
bool visible = pWindow->m_bIsX11;
|
||||
|
||||
if (!pWindow->m_bIsX11) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|
||||
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
|
||||
|
||||
visible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: detect a popup in a more consistent way.
|
||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
|
||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible) {
|
||||
// if it's not, fall back to the center placement
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
|
||||
} else {
|
||||
@@ -121,7 +137,7 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
@@ -176,11 +192,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE) {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
|
||||
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW);
|
||||
@@ -226,6 +242,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
pWindow->m_bPinned = false;
|
||||
|
||||
const auto TILED = isWindowTiled(pWindow);
|
||||
|
||||
if (!TILED) {
|
||||
|
@@ -84,6 +84,13 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// recalc
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
@@ -94,6 +101,9 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
if (!PNODE)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
if (PNODE->isMaster) {
|
||||
// find new one
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
@@ -326,10 +336,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
@@ -425,16 +432,17 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
return;
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Master: Rejecting a swap between workspaces");
|
||||
return;
|
||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
||||
}
|
||||
|
||||
// massive hack: just swap window pointers, lol
|
||||
const auto PWINDOW1 = PNODE->pWindow;
|
||||
PNODE->pWindow = PNODE2->pWindow;
|
||||
PNODE2->pWindow = PWINDOW1;
|
||||
PNODE->pWindow = pWindow2;
|
||||
PNODE2->pWindow = pWindow;
|
||||
|
||||
recalculateMonitor(PWINDOW1->m_iMonitorID);
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
if (PNODE2->workspaceID != PNODE->workspaceID)
|
||||
recalculateMonitor(pWindow2->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
|
@@ -14,6 +14,12 @@ int main(int argc, char** argv) {
|
||||
if (!getenv("XDG_RUNTIME_DIR"))
|
||||
throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
|
||||
|
||||
// export HYPRLAND_CMD
|
||||
std::string cmd = "";
|
||||
for (auto i = 0; i < argc; ++i)
|
||||
cmd += std::string(i == 0 ? "" : " ") + argv[i];
|
||||
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
|
||||
|
||||
// parse some args
|
||||
std::string configPath;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
|
@@ -42,6 +42,8 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["resizewindowpixel"] = resizeWindow;
|
||||
m_mDispatchers["swapnext"] = swapnext;
|
||||
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
|
||||
m_mDispatchers["pin"] = pinActive;
|
||||
m_mDispatchers["mouse"] = mouse;
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
}
|
||||
@@ -127,6 +129,24 @@ void CKeybindManager::updateXKBTranslationState() {
|
||||
m_pXKBTranslationState = xkb_state_new(PKEYMAP);
|
||||
}
|
||||
|
||||
bool CKeybindManager::ensureMouseBindState() {
|
||||
if (!m_bIsMouseBindActive)
|
||||
return false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
m_bIsMouseBindActive = false;
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_bIsMouseBindActive = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
if (!g_pCompositor->m_bSessionActive) {
|
||||
m_dPressedKeycodes.clear();
|
||||
@@ -159,6 +179,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_uLastCode = KEYCODE;
|
||||
m_uLastMouseCode = 0;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
bool found = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
// clean repeat
|
||||
@@ -185,8 +207,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE));
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym));
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end());
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym), m_dPressedKeysyms.end());
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
|
||||
|
||||
@@ -195,7 +217,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
return !found && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
@@ -234,6 +256,8 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
m_uLastCode = 0;
|
||||
m_uTimeLastMs = e->time_msec;
|
||||
|
||||
bool mouseBindWasActive = ensureMouseBindState();
|
||||
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
|
||||
|
||||
@@ -245,7 +269,7 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
return !found && !mouseBindWasActive;
|
||||
}
|
||||
|
||||
int repeatKeyHandler(void* data) {
|
||||
@@ -277,7 +301,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
}
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass") || k.shadowed)
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass" && k.handler != "mouse") || k.shadowed)
|
||||
continue;
|
||||
|
||||
if (!key.empty()) {
|
||||
@@ -306,7 +330,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.handler);
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
||||
|
||||
// Should never happen, as we check in the ConfigManager, but oh well
|
||||
if (DISPATCHER == m_mDispatchers.end()) {
|
||||
@@ -317,7 +341,10 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
|
||||
m_iPassPressed = (int)pressed;
|
||||
|
||||
DISPATCHER->second(k.arg);
|
||||
if (k.handler == "mouse")
|
||||
DISPATCHER->second((pressed ? "1" : "0") + k.arg);
|
||||
else
|
||||
DISPATCHER->second(k.arg);
|
||||
|
||||
m_iPassPressed = -1;
|
||||
|
||||
@@ -574,9 +601,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
// Workspace_back_and_forth being enabled means that an attempt to switch to
|
||||
// the current workspace will instead switch to the previous.
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(
|
||||
g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
static auto *const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
|
||||
|
||||
if (*PBACKANDFORTH && PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1 && !internal) {
|
||||
|
||||
workspaceToChangeTo = PCURRENTWORKSPACE->m_iPrevWorkspaceID;
|
||||
@@ -587,7 +614,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
static auto *const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
if (!*PALLOWWORKSPACECYCLES)
|
||||
PCURRENTWORKSPACE->m_iPrevWorkspaceID = -1;
|
||||
}
|
||||
|
||||
} else if (PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && !internal)
|
||||
return;
|
||||
|
||||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
@@ -613,6 +642,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
|
||||
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = workspaceToChangeTo;
|
||||
}
|
||||
}
|
||||
|
||||
// change it
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
@@ -671,7 +707,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
}
|
||||
|
||||
// Workspace doesn't exist, create and switch
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
|
||||
|
||||
const auto PMONITOR = BOUNDMON ? BOUNDMON : g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
const auto OLDWORKSPACE = PMONITOR->activeWorkspace;
|
||||
|
||||
@@ -700,6 +738,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
PMONITOR->specialWorkspaceOpen = false;
|
||||
|
||||
// fix pinned windows
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
|
||||
w->m_iWorkspaceID = workspaceToChangeTo;
|
||||
}
|
||||
}
|
||||
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
else
|
||||
@@ -712,6 +757,12 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
// mark the monitor dirty
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
// some stuf with the cursor and focus
|
||||
if (g_pCompositor->m_pLastMonitor != PMONITOR)
|
||||
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
|
||||
|
||||
g_pCompositor->m_pLastMonitor = PMONITOR;
|
||||
|
||||
// focus (clears the last)
|
||||
g_pInputManager->refocus();
|
||||
|
||||
@@ -781,17 +832,13 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
PWINDOW->moveToWorkspace(PWORKSPACE->m_iID);
|
||||
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
|
||||
PWINDOW->m_bIsFullscreen = false;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID)->m_bIsFullscreen = false;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
PWINDOW->m_bIsFullscreen = false;
|
||||
PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10);
|
||||
PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20);
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// Hack: So that the layout doesnt find our window at the cursor
|
||||
@@ -815,10 +862,10 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->specialWorkspaceOpen = false;
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
}
|
||||
|
||||
@@ -857,7 +904,12 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
// may be null until later!
|
||||
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
|
||||
|
||||
const auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
|
||||
auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
|
||||
if (!PWORKSPACE) {
|
||||
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
|
||||
if (BOUNDMON)
|
||||
PMONITORNEW = BOUNDMON;
|
||||
}
|
||||
|
||||
const auto OLDWORKSPACEIDONMONITOR = PMONITORNEW->activeWorkspace;
|
||||
const auto OLDWORKSPACEIDRETURN = PMONITOR->activeWorkspace;
|
||||
@@ -910,11 +962,14 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
if (PLASTWINDOW->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && PLASTWINDOW->m_bIsFullscreen) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PLASTWINDOW->m_iWorkspaceID);
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
@@ -1260,7 +1315,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
|
||||
@@ -1272,8 +1327,8 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
|
||||
|
||||
@@ -1292,6 +1347,9 @@ void CKeybindManager::moveWindow(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW);
|
||||
@@ -1309,7 +1367,10 @@ void CKeybindManager::resizeWindow(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
|
||||
|
||||
@@ -1328,11 +1389,14 @@ void CKeybindManager::circleNext(std::string arg) {
|
||||
if (g_pCompositor->m_pLastWindow->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsFullscreen) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
if (!PWINDOWTOCHANGETO->m_bPinned)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
||||
} else {
|
||||
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
||||
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
||||
@@ -1534,3 +1598,56 @@ void CKeybindManager::swapActiveWorkspaces(std::string args) {
|
||||
|
||||
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
|
||||
}
|
||||
|
||||
void CKeybindManager::pinActive(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) || !g_pCompositor->m_pLastWindow->m_bIsFloating)
|
||||
return;
|
||||
|
||||
g_pCompositor->m_pLastWindow->m_bPinned = !g_pCompositor->m_pLastWindow->m_bPinned;
|
||||
g_pCompositor->m_pLastWindow->m_iWorkspaceID = g_pCompositor->getMonitorFromID(g_pCompositor->m_pLastWindow->m_iMonitorID)->activeWorkspace;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
|
||||
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal());
|
||||
}
|
||||
|
||||
void CKeybindManager::mouse(std::string args) {
|
||||
const auto TRUEARG = args.substr(1);
|
||||
const auto PRESSED = args[0] == '1';
|
||||
|
||||
if (TRUEARG == "movewindow") {
|
||||
if (PRESSED) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
}
|
||||
}
|
||||
} else if (TRUEARG == "resizewindow") {
|
||||
if (PRESSED) {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = true;
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
g_pInputManager->dragMode = MBIND_RESIZE;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
||||
if (g_pInputManager->currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->dragMode = MBIND_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ struct SKeybind {
|
||||
std::string submap = "";
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
bool mouse = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
@@ -63,6 +64,8 @@ private:
|
||||
uint32_t m_uLastCode = 0;
|
||||
uint32_t m_uLastMouseCode = 0;
|
||||
|
||||
bool m_bIsMouseBindActive = false;
|
||||
|
||||
int m_iPassPressed = -1; // used for pass
|
||||
|
||||
CTimer m_tScrollTimer;
|
||||
@@ -75,6 +78,7 @@ private:
|
||||
xkb_state* m_pXKBTranslationState = nullptr;
|
||||
|
||||
void updateXKBTranslationState();
|
||||
bool ensureMouseBindState();
|
||||
|
||||
// -------------- Dispatchers -------------- //
|
||||
static void killActive(std::string);
|
||||
@@ -113,6 +117,8 @@ private:
|
||||
static void dpms(std::string);
|
||||
static void swapnext(std::string);
|
||||
static void swapActiveWorkspaces(std::string);
|
||||
static void pinActive(std::string);
|
||||
static void mouse(std::string);
|
||||
|
||||
friend class CCompositor;
|
||||
friend class CInputManager;
|
||||
|
@@ -7,7 +7,10 @@ int slowUpdate = 0;
|
||||
int handleTimer(void* data) {
|
||||
const auto PTM = (CThreadManager*)data;
|
||||
|
||||
g_pConfigManager->tick();
|
||||
static auto *const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
|
||||
|
||||
if (*PDISABLECFGRELOAD != 1)
|
||||
g_pConfigManager->tick();
|
||||
|
||||
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
|
||||
|
||||
@@ -19,8 +22,6 @@ CThreadManager::CThreadManager() {
|
||||
|
||||
HyprCtl::startHyprCtlSocket();
|
||||
|
||||
g_pCompositor->startHyprCtlTick();
|
||||
|
||||
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
|
||||
|
||||
wl_event_source_timer_update(m_esConfigTimer, 1000);
|
||||
|
@@ -63,7 +63,8 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
|
||||
g_pCompositor->m_pLastWindow = pWindow;
|
||||
|
||||
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
|
||||
if (!pWindow->m_bPinned)
|
||||
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) {
|
||||
|
@@ -29,7 +29,6 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto *const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
@@ -140,6 +139,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then, we check if the workspace doesnt have a fullscreen window
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
@@ -157,7 +159,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// only check floating because tiled cant be over fullscreen
|
||||
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
|
||||
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
|
||||
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && (*w)->m_bCreatedOverFullscreen) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
|
||||
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
|
||||
pFoundWindow = (*w).get();
|
||||
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
@@ -173,9 +175,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then windows
|
||||
if (!foundSurface) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
@@ -287,7 +286,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
if (*PFOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow)
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
|
||||
m_bLastFocusOnLS = false;
|
||||
return; // don't enter any new surfaces
|
||||
} else {
|
||||
@@ -384,7 +385,6 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
|
||||
// notify the keybind manager
|
||||
static auto *const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
|
||||
static auto *const PMAINMODINTERNAL = &g_pConfigManager->getConfigValuePtr("general:main_mod_internal")->intValue;
|
||||
const auto PASS = g_pKeybindManager->onMouseEvent(e);
|
||||
|
||||
if (!PASS && !*PPASSMOUSE)
|
||||
@@ -399,22 +399,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_bIsFloating)
|
||||
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
|
||||
|
||||
if ((e->button == BTN_LEFT || e->button == BTN_RIGHT) && wlr_keyboard_get_modifiers(PKEYBOARD) == (uint32_t)*PMAINMODINTERNAL) {
|
||||
currentlyDraggedWindow = g_pCompositor->windowFromCursor();
|
||||
dragButton = e->button;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
if (currentlyDraggedWindow) {
|
||||
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
|
||||
currentlyDraggedWindow = nullptr;
|
||||
dragButton = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1001,3 +987,22 @@ void CInputManager::disableAllKeyboards(bool virt) {
|
||||
k.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
|
||||
const auto PNEWDEV = &m_lTouchDevices.emplace_back();
|
||||
PNEWDEV->pWlrDevice = pDevice;
|
||||
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
|
||||
|
||||
Debug::log(LOG, "New touch device added at %x", PNEWDEV);
|
||||
|
||||
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
|
||||
destroyTouchDevice((STouchDevice*)data);
|
||||
}, PNEWDEV, "TouchDevice");
|
||||
}
|
||||
|
||||
void CInputManager::destroyTouchDevice(STouchDevice* pDevice) {
|
||||
Debug::log(LOG, "Touch device at %x removed", pDevice);
|
||||
|
||||
m_lTouchDevices.remove(*pDevice);
|
||||
}
|
||||
|
@@ -12,6 +12,12 @@ enum eClickBehaviorMode {
|
||||
CLICKMODE_KILL
|
||||
};
|
||||
|
||||
enum eMouseBindMode {
|
||||
MBIND_INVALID = -1,
|
||||
MBIND_MOVE = 0,
|
||||
MBIND_RESIZE
|
||||
};
|
||||
|
||||
struct STouchData {
|
||||
CWindow* touchFocusWindow = nullptr;
|
||||
Vector2D touchSurfaceOrigin;
|
||||
@@ -30,6 +36,8 @@ public:
|
||||
void newKeyboard(wlr_input_device*);
|
||||
void newVirtualKeyboard(wlr_input_device*);
|
||||
void newMouse(wlr_input_device*, bool virt = false);
|
||||
void newTouchDevice(wlr_input_device*);
|
||||
void destroyTouchDevice(STouchDevice*);
|
||||
void destroyKeyboard(SKeyboard*);
|
||||
void destroyMouse(wlr_input_device*);
|
||||
|
||||
@@ -59,7 +67,7 @@ public:
|
||||
|
||||
// for dragging floating windows
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
int dragButton = -1;
|
||||
eMouseBindMode dragMode = MBIND_INVALID;
|
||||
|
||||
SDrag m_sDrag;
|
||||
|
||||
@@ -75,6 +83,9 @@ public:
|
||||
// idle inhibitors
|
||||
std::list<SIdleInhibitor> m_lIdleInhibitors;
|
||||
|
||||
// Touch devices
|
||||
std::list<STouchDevice> m_lTouchDevices;
|
||||
|
||||
void newTabletTool(wlr_input_device*);
|
||||
void newTabletPad(wlr_input_device*);
|
||||
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||
|
@@ -2,9 +2,7 @@
|
||||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CInputMethodRelay::CInputMethodRelay() {
|
||||
|
||||
}
|
||||
CInputMethodRelay::CInputMethodRelay() { }
|
||||
|
||||
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
if (m_pWLRIME) {
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
|
||||
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
|
||||
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
|
||||
|
||||
@@ -11,7 +10,7 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
|
||||
int onMonitor = 0;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && w->m_iID != SPECIAL_WORKSPACE_ID) {
|
||||
onMonitor++;
|
||||
}
|
||||
}
|
||||
@@ -28,10 +27,15 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
|
||||
m_sActiveSwipe.avgSpeed = 0;
|
||||
m_sActiveSwipe.speedPoints = 0;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
ls->alpha = 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
return; // no valid swipe
|
||||
|
||||
@@ -49,6 +53,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
|
||||
|
||||
CWorkspace* pSwitchedTo = nullptr;
|
||||
|
||||
if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
|
||||
// revert
|
||||
if (abs(m_sActiveSwipe.delta) < 2) {
|
||||
@@ -66,6 +72,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
|
||||
}
|
||||
|
||||
pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin;
|
||||
} else if (m_sActiveSwipe.delta < 0) {
|
||||
// switch to left
|
||||
const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
|
||||
@@ -82,6 +90,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the left");
|
||||
|
||||
pSwitchedTo = PWORKSPACEL;
|
||||
} else {
|
||||
// switch to right
|
||||
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
|
||||
@@ -98,6 +108,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the right");
|
||||
|
||||
pSwitchedTo = PWORKSPACER;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
@@ -109,6 +121,11 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr;
|
||||
|
||||
g_pInputManager->refocus();
|
||||
|
||||
// apply alpha
|
||||
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow ? 0.f : 255.f;
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
@@ -127,8 +144,10 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
|
||||
|
||||
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
|
||||
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
|
||||
return;
|
||||
}
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true;
|
||||
|
||||
|
@@ -2,7 +2,6 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, g_pCompositor->m_pLastMonitor->vecPosition.x + e->x * g_pCompositor->m_pLastMonitor->vecSize.x, g_pCompositor->m_pLastMonitor->vecPosition.y + e->y * g_pCompositor->m_pLastMonitor->vecSize.y);
|
||||
|
||||
refocus();
|
||||
@@ -26,7 +25,6 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::onTouchUp(wlr_touch_up_event* e){
|
||||
|
||||
if (m_sTouchData.touchFocusWindow) {
|
||||
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id);
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h) {
|
||||
bool firstAlloc = false;
|
||||
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted %ix%i)", w, h);
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
|
@@ -102,6 +102,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
@@ -120,11 +121,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
void CHyprOpenGLImpl::end() {
|
||||
// end the render, copy the data to the WLR framebuffer
|
||||
if (!m_bFakeFrame) {
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
if (!m_RenderData.pMonitor->mirrors.empty())
|
||||
g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
|
||||
|
||||
clear(CColor(11, 11, 11, 255));
|
||||
|
||||
m_bEndFrame = true;
|
||||
@@ -1088,6 +1092,27 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
|
||||
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0, false, false);
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderMirrored() {
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
|
||||
|
||||
if (PFB->m_cTex.m_iTexID <= 0)
|
||||
return;
|
||||
|
||||
renderTexture(PFB->m_cTex, &monbox, 255.f, 0, false, false);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
|
||||
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
|
@@ -33,8 +33,10 @@ inline const float fanVertsFull[] = {
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer mirrorFB;
|
||||
CFramebuffer mirrorSwapFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs
|
||||
|
||||
CTexture stencilTex;
|
||||
|
||||
@@ -102,6 +104,9 @@ public:
|
||||
void preWindowPass();
|
||||
void preRender(CMonitor*);
|
||||
|
||||
void saveBufferForMirror();
|
||||
void renderMirrored();
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
|
@@ -65,11 +65,14 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
return false;
|
||||
|
||||
if (pWindow->m_bPinned)
|
||||
return true;
|
||||
|
||||
// now check if it has the same workspace
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
|
||||
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()) {
|
||||
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering) {
|
||||
return true;
|
||||
} else {
|
||||
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
|
||||
@@ -99,6 +102,9 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering)
|
||||
return true;
|
||||
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return true;
|
||||
|
||||
@@ -116,11 +122,39 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
|
||||
CWindow* pWorkspaceWindow = nullptr;
|
||||
|
||||
// loop over the tiled windows that are fading out
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsFullscreen || w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// and floating ones too
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.fl() == 0.f)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsFullscreen || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
||||
|
||||
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen){
|
||||
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering)))
|
||||
continue;
|
||||
|
||||
if (w->m_iMonitorID != pMonitor->ID)
|
||||
@@ -135,9 +169,9 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
|
||||
pWorkspaceWindow = w.get();
|
||||
}
|
||||
|
||||
// then render windows over fullscreen
|
||||
// then render windows over fullscreen.
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || !w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
@@ -159,13 +193,12 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
|
||||
}
|
||||
|
||||
// and the overlay layers
|
||||
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
// on non-full we draw the bar and shit
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
if (ls->alpha.fl() != 0.f)
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
@@ -188,7 +221,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec();
|
||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
|
||||
static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
|
||||
|
||||
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
|
||||
@@ -196,7 +229,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
|
||||
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : (PWORKSPACE->m_fAlpha.fl() / 255.f));
|
||||
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
|
||||
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||
@@ -772,7 +805,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
||||
return;
|
||||
|
||||
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
@@ -789,6 +822,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->isMirror())
|
||||
continue; // don't damage mirrors traditionally
|
||||
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
m->addDamage(&damageBox);
|
||||
@@ -812,6 +848,19 @@ void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
|
||||
for (auto& mirror : pMonitor->mirrors) {
|
||||
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
|
||||
|
||||
pixman_region32_t rg;
|
||||
pixman_region32_init(&rg);
|
||||
pixman_region32_copy(&rg, pRegion);
|
||||
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
|
||||
pMonitor->addDamage(&rg);
|
||||
pixman_region32_fini(&rg);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
||||
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
||||
return;
|
||||
@@ -1023,7 +1072,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecPosition = finalPos;
|
||||
}
|
||||
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
if (!pMonitor->isMirror())
|
||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
||||
|
||||
wlr_output_enable(pMonitor->output, true);
|
||||
|
||||
@@ -1036,6 +1086,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
// frame skip
|
||||
pMonitor->framesToSkip = 1;
|
||||
|
||||
// reload to fix mirrors
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(pixman_region32_t*);
|
||||
void damageMonitor(CMonitor*);
|
||||
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
|
||||
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, CMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
|
@@ -38,7 +38,7 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
|
||||
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
|
||||
|
@@ -22,7 +22,7 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
|
||||
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
|
||||
// we draw 3px above the window's border with 3px
|
||||
@@ -45,7 +45,7 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
// get the group info
|
||||
SLayoutMessageHeader header;
|
||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
||||
header.pWindow = m_pWindow;
|
||||
|
||||
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
|
||||
|
||||
@@ -82,6 +82,8 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
break;
|
||||
|
||||
scaleBox(&rect, pMonitor->scale);
|
||||
|
||||
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
|
||||
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
|
||||
|
||||
|
Submodule subprojects/wlroots updated: fd0b0276c9...2ad25b1460
Reference in New Issue
Block a user