mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-20 22:43:47 -07:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c4a4c34156 | ||
|
d4fbedcd35 |
30
flake.lock
generated
30
flake.lock
generated
@@ -16,11 +16,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1752936381,
|
"lastModified": 1751740947,
|
||||||
"narHash": "sha256-b191B12GRfvOT3odGpx5IFyGRPZbBrvCLADZfFHoJFg=",
|
"narHash": "sha256-35040CHH7P3JGmhGVfEb2oJHL/A5mI2IXumhkxrBnao=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "aquamarine",
|
"repo": "aquamarine",
|
||||||
"rev": "141a991678b34e768f09b3a670c61a4c1d5d7110",
|
"rev": "dfc1db15a08c4cd234288f66e1199c653495301f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -105,11 +105,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1752149140,
|
"lastModified": 1751808145,
|
||||||
"narHash": "sha256-gbh1HL98Fdqu0jJIWN4OJQN7Kkth7+rbkFpSZLm/62A=",
|
"narHash": "sha256-OXgL0XaKMmfX2rRQkt9SkJw+QNfv0jExlySt1D6O72g=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprgraphics",
|
"repo": "hyprgraphics",
|
||||||
"rev": "340494a38b5ec453dfc542c6226481f736cc8a9a",
|
"rev": "b841473a0bd4a1a74a0b64f1ec2ab199035c349f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -238,11 +238,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1752252310,
|
"lastModified": 1751888065,
|
||||||
"narHash": "sha256-06i1pIh6wb+sDeDmWlzuPwIdaFMxLlj1J9I5B9XqSeo=",
|
"narHash": "sha256-F2SV9WGqgtRsXIdUrl3sRe0wXlQD+kRRZcSfbepjPJY=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprutils",
|
"repo": "hyprutils",
|
||||||
"rev": "bcabcbada90ed2aacb435dc09b91001819a6dc82",
|
"rev": "a8229739cf36d159001cfc203871917b83fdf917",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -261,11 +261,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1751897909,
|
"lastModified": 1751881472,
|
||||||
"narHash": "sha256-FnhBENxihITZldThvbO7883PdXC/2dzW4eiNvtoV5Ao=",
|
"narHash": "sha256-meB0SnXbwIe2trD041MLKEv6R7NZ759QwBcVIhlSBfE=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprwayland-scanner",
|
"repo": "hyprwayland-scanner",
|
||||||
"rev": "fcca0c61f988a9d092cbb33e906775014c61579d",
|
"rev": "8fb426b3e5452fd9169453fd6c10f8c14ca37120",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -276,11 +276,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1752687322,
|
"lastModified": 1751792365,
|
||||||
"narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=",
|
"narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251",
|
"rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@@ -45,68 +45,69 @@ static void expectSnapMove(const Vector2D FROM, const Vector2D* TO) {
|
|||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("at: {},{}", B.x, B.y));
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("at: {},{}", B.x, B.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testWindowSnap(const bool RESPECTGAPS) {
|
static void testSnap(const bool OVERLAP, const bool RESPECT) {
|
||||||
const double BORDERSIZE = 2;
|
const double BORDERSIZE = 2;
|
||||||
const double WINDOWSIZE = 100;
|
const double WINDOWSIZE = 100;
|
||||||
|
|
||||||
const double OTHER = 500;
|
// test window snapping
|
||||||
const double WINDOWGAP = 8;
|
{
|
||||||
const double GAPSIN = 5;
|
const double OTHER = 500;
|
||||||
const double GAP = (RESPECTGAPS ? 2 * GAPSIN : 0) + (2 * BORDERSIZE);
|
const double WINDOWGAP = 8;
|
||||||
const double END = GAP + WINDOWSIZE;
|
const double GAPSIN = 5;
|
||||||
|
const double GAP = (RESPECT ? GAPSIN : 0) + BORDERSIZE + (OVERLAP ? 0 : BORDERSIZE);
|
||||||
|
const double END = GAP + WINDOWSIZE;
|
||||||
|
|
||||||
double x;
|
double x;
|
||||||
Vector2D predict;
|
Vector2D predict;
|
||||||
|
|
||||||
x = WINDOWGAP + END;
|
x = WINDOWGAP + END;
|
||||||
expectSnapMove({OTHER + x, OTHER}, nullptr);
|
expectSnapMove({OTHER + x, OTHER}, nullptr);
|
||||||
expectSnapMove({OTHER - x, OTHER}, nullptr);
|
expectSnapMove({OTHER - x, OTHER}, nullptr);
|
||||||
expectSnapMove({OTHER, OTHER + x}, nullptr);
|
expectSnapMove({OTHER, OTHER + x}, nullptr);
|
||||||
expectSnapMove({OTHER, OTHER - x}, nullptr);
|
expectSnapMove({OTHER, OTHER - x}, nullptr);
|
||||||
x -= 1;
|
x -= 1;
|
||||||
expectSnapMove({OTHER + x, OTHER}, &(predict = {OTHER + END, OTHER}));
|
expectSnapMove({OTHER + x, OTHER}, &(predict = {OTHER + END, OTHER}));
|
||||||
expectSnapMove({OTHER - x, OTHER}, &(predict = {OTHER - END, OTHER}));
|
expectSnapMove({OTHER - x, OTHER}, &(predict = {OTHER - END, OTHER}));
|
||||||
expectSnapMove({OTHER, OTHER + x}, &(predict = {OTHER, OTHER + END}));
|
expectSnapMove({OTHER, OTHER + x}, &(predict = {OTHER, OTHER + END}));
|
||||||
expectSnapMove({OTHER, OTHER - x}, &(predict = {OTHER, OTHER - END}));
|
expectSnapMove({OTHER, OTHER - x}, &(predict = {OTHER, OTHER - END}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testMonitorSnap(const bool RESPECTGAPS, const bool OVERLAP) {
|
// test monitor snapping
|
||||||
const double BORDERSIZE = 2;
|
{
|
||||||
const double WINDOWSIZE = 100;
|
const double MONITORGAP = 10;
|
||||||
|
const double GAPSOUT = 20;
|
||||||
|
const double RESP = (RESPECT ? GAPSOUT : 0);
|
||||||
|
const double GAP = RESP + (OVERLAP ? 0 : BORDERSIZE);
|
||||||
|
const double END = GAP + WINDOWSIZE;
|
||||||
|
|
||||||
const double MONITORGAP = 10;
|
double x;
|
||||||
const double GAPSOUT = 20;
|
Vector2D predict;
|
||||||
const double RESP = (RESPECTGAPS ? GAPSOUT : 0);
|
|
||||||
const double GAP = RESP + (OVERLAP ? 0 : BORDERSIZE);
|
|
||||||
const double END = GAP + WINDOWSIZE;
|
|
||||||
|
|
||||||
double x;
|
x = MONITORGAP + GAP;
|
||||||
Vector2D predict;
|
expectSnapMove({x, x}, nullptr);
|
||||||
|
x -= 1;
|
||||||
|
expectSnapMove({x, x}, &(predict = {GAP, GAP}));
|
||||||
|
|
||||||
x = MONITORGAP + GAP;
|
x = MONITORGAP + END;
|
||||||
expectSnapMove({x, x}, nullptr);
|
expectSnapMove({1920 - x, 1080 - x}, nullptr);
|
||||||
x -= 1;
|
x -= 1;
|
||||||
expectSnapMove({x, x}, &(predict = {GAP, GAP}));
|
expectSnapMove({1920 - x, 1080 - x}, &(predict = {1920 - END, 1080 - END}));
|
||||||
|
|
||||||
x = MONITORGAP + END;
|
// test reserved area
|
||||||
expectSnapMove({1920 - x, 1080 - x}, nullptr);
|
const double RESERVED = 200;
|
||||||
x -= 1;
|
const double RGAP = RESERVED + RESP + BORDERSIZE;
|
||||||
expectSnapMove({1920 - x, 1080 - x}, &(predict = {1920 - END, 1080 - END}));
|
const double REND = RGAP + WINDOWSIZE;
|
||||||
|
|
||||||
// test reserved area
|
x = MONITORGAP + RGAP;
|
||||||
const double RESERVED = 200;
|
expectSnapMove({x, x}, nullptr);
|
||||||
const double RGAP = RESERVED + RESP + BORDERSIZE;
|
x -= 1;
|
||||||
const double REND = RGAP + WINDOWSIZE;
|
expectSnapMove({x, x}, &(predict = {RGAP, RGAP}));
|
||||||
|
|
||||||
x = MONITORGAP + RGAP;
|
x = MONITORGAP + REND;
|
||||||
expectSnapMove({x, x}, nullptr);
|
expectSnapMove({1920 - x, 1080 - x}, nullptr);
|
||||||
x -= 1;
|
x -= 1;
|
||||||
expectSnapMove({x, x}, &(predict = {RGAP, RGAP}));
|
expectSnapMove({1920 - x, 1080 - x}, &(predict = {1920 - REND, 1080 - REND}));
|
||||||
|
}
|
||||||
x = MONITORGAP + REND;
|
|
||||||
expectSnapMove({1920 - x, 1080 - x}, nullptr);
|
|
||||||
x -= 1;
|
|
||||||
expectSnapMove({1920 - x, 1080 - x}, &(predict = {1920 - REND, 1080 - REND}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test() {
|
static bool test() {
|
||||||
@@ -142,22 +143,20 @@ static bool test() {
|
|||||||
EXPECT(Tests::windowCount(), 2);
|
EXPECT(Tests::windowCount(), 2);
|
||||||
|
|
||||||
NLog::log("");
|
NLog::log("");
|
||||||
testWindowSnap(false);
|
testSnap(false, false);
|
||||||
testMonitorSnap(false, false);
|
|
||||||
|
|
||||||
NLog::log("\n{}Turning on respect_gaps", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/keyword general:snap:respect_gaps true"));
|
|
||||||
testWindowSnap(true);
|
|
||||||
testMonitorSnap(true, false);
|
|
||||||
|
|
||||||
NLog::log("\n{}Turning on border_overlap", Colors::YELLOW);
|
NLog::log("\n{}Turning on border_overlap", Colors::YELLOW);
|
||||||
OK(getFromSocket("/keyword general:snap:respect_gaps false"));
|
|
||||||
OK(getFromSocket("/keyword general:snap:border_overlap true"));
|
OK(getFromSocket("/keyword general:snap:border_overlap true"));
|
||||||
testMonitorSnap(false, true);
|
testSnap(true, false);
|
||||||
|
|
||||||
|
NLog::log("\n{}Turning on respect_gaps", Colors::YELLOW);
|
||||||
|
OK(getFromSocket("/keyword general:snap:border_overlap false"));
|
||||||
|
OK(getFromSocket("/keyword general:snap:respect_gaps true"));
|
||||||
|
testSnap(false, true);
|
||||||
|
|
||||||
NLog::log("\n{}Turning on both border_overlap and respect_gaps", Colors::YELLOW);
|
NLog::log("\n{}Turning on both border_overlap and respect_gaps", Colors::YELLOW);
|
||||||
OK(getFromSocket("/keyword general:snap:respect_gaps true"));
|
OK(getFromSocket("/keyword general:snap:border_overlap true"));
|
||||||
testMonitorSnap(true, true);
|
testSnap(true, true);
|
||||||
|
|
||||||
// kill all
|
// kill all
|
||||||
NLog::log("\n{}Killing all windows", Colors::YELLOW);
|
NLog::log("\n{}Killing all windows", Colors::YELLOW);
|
||||||
|
@@ -626,7 +626,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
|||||||
.description = "When enabled, lifting the finger off while dragging will not drop the dragged item. 0 -> disabled, 1 -> enabled with timeout, 2 -> enabled sticky."
|
.description = "When enabled, lifting the finger off while dragging will not drop the dragged item. 0 -> disabled, 1 -> enabled with timeout, 2 -> enabled sticky."
|
||||||
"dragging will not drop the dragged item.",
|
"dragging will not drop the dragged item.",
|
||||||
.type = CONFIG_OPTION_INT,
|
.type = CONFIG_OPTION_INT,
|
||||||
.data = SConfigOptionDescription::SRangeData{0, 0, 2},
|
.data = SConfigOptionDescription::SRangeData{2, 0, 2},
|
||||||
},
|
},
|
||||||
SConfigOptionDescription{
|
SConfigOptionDescription{
|
||||||
.value = "input:touchpad:tap-and-drag",
|
.value = "input:touchpad:tap-and-drag",
|
||||||
|
@@ -654,7 +654,7 @@ CConfigManager::CConfigManager() {
|
|||||||
registerConfigVar("input:touchpad:middle_button_emulation", Hyprlang::INT{0});
|
registerConfigVar("input:touchpad:middle_button_emulation", Hyprlang::INT{0});
|
||||||
registerConfigVar("input:touchpad:tap-to-click", Hyprlang::INT{1});
|
registerConfigVar("input:touchpad:tap-to-click", Hyprlang::INT{1});
|
||||||
registerConfigVar("input:touchpad:tap-and-drag", Hyprlang::INT{1});
|
registerConfigVar("input:touchpad:tap-and-drag", Hyprlang::INT{1});
|
||||||
registerConfigVar("input:touchpad:drag_lock", Hyprlang::INT{0});
|
registerConfigVar("input:touchpad:drag_lock", Hyprlang::INT{2});
|
||||||
registerConfigVar("input:touchpad:scroll_factor", {1.f});
|
registerConfigVar("input:touchpad:scroll_factor", {1.f});
|
||||||
registerConfigVar("input:touchpad:flip_x", Hyprlang::INT{0});
|
registerConfigVar("input:touchpad:flip_x", Hyprlang::INT{0});
|
||||||
registerConfigVar("input:touchpad:flip_y", Hyprlang::INT{0});
|
registerConfigVar("input:touchpad:flip_y", Hyprlang::INT{0});
|
||||||
@@ -777,7 +777,7 @@ CConfigManager::CConfigManager() {
|
|||||||
m_config->addSpecialConfigValue("device", "middle_button_emulation", Hyprlang::INT{0});
|
m_config->addSpecialConfigValue("device", "middle_button_emulation", Hyprlang::INT{0});
|
||||||
m_config->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1});
|
m_config->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1});
|
||||||
m_config->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1});
|
m_config->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1});
|
||||||
m_config->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{0});
|
m_config->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{2});
|
||||||
m_config->addSpecialConfigValue("device", "left_handed", Hyprlang::INT{0});
|
m_config->addSpecialConfigValue("device", "left_handed", Hyprlang::INT{0});
|
||||||
m_config->addSpecialConfigValue("device", "scroll_method", {STRVAL_EMPTY});
|
m_config->addSpecialConfigValue("device", "scroll_method", {STRVAL_EMPTY});
|
||||||
m_config->addSpecialConfigValue("device", "scroll_button", Hyprlang::INT{0});
|
m_config->addSpecialConfigValue("device", "scroll_button", Hyprlang::INT{0});
|
||||||
|
@@ -236,18 +236,6 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
SBoxExtents CWindow::getWindowExtentsUnified(uint64_t properties) {
|
|
||||||
SBoxExtents extents = {.topLeft = {0, 0}, .bottomRight = {0, 0}};
|
|
||||||
if (properties & RESERVED_EXTENTS)
|
|
||||||
extents.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_self.lock()));
|
|
||||||
if (properties & INPUT_EXTENTS)
|
|
||||||
extents.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self.lock(), true));
|
|
||||||
if (properties & FULL_EXTENTS)
|
|
||||||
extents.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self.lock(), false));
|
|
||||||
|
|
||||||
return extents;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||||
if (m_windowData.dimAround.valueOrDefault()) {
|
if (m_windowData.dimAround.valueOrDefault()) {
|
||||||
const auto PMONITOR = m_monitor.lock();
|
const auto PMONITOR = m_monitor.lock();
|
||||||
@@ -255,8 +243,16 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
|||||||
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SBoxExtents EXTENTS = {.topLeft = {0, 0}, .bottomRight = {0, 0}};
|
||||||
|
if (properties & RESERVED_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_self.lock()));
|
||||||
|
if (properties & INPUT_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self.lock(), true));
|
||||||
|
if (properties & FULL_EXTENTS)
|
||||||
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self.lock(), false));
|
||||||
|
|
||||||
CBox box = {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};
|
CBox box = {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};
|
||||||
box.addExtents(getWindowExtentsUnified(properties));
|
box.addExtents(EXTENTS);
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
@@ -324,7 +324,6 @@ class CWindow {
|
|||||||
CBox getFullWindowBoundingBox();
|
CBox getFullWindowBoundingBox();
|
||||||
SBoxExtents getFullWindowExtents();
|
SBoxExtents getFullWindowExtents();
|
||||||
CBox getWindowBoxUnified(uint64_t props);
|
CBox getWindowBoxUnified(uint64_t props);
|
||||||
SBoxExtents getWindowExtentsUnified(uint64_t props);
|
|
||||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
void addWindowDeco(UP<IHyprWindowDecoration> deco);
|
void addWindowDeco(UP<IHyprWindowDecoration> deco);
|
||||||
void updateWindowDecos();
|
void updateWindowDecos();
|
||||||
|
@@ -418,7 +418,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
|||||||
PWINDOW->m_swallowed->m_currentlySwallowed = true;
|
PWINDOW->m_swallowed->m_currentlySwallowed = true;
|
||||||
|
|
||||||
// emit the IPC event before the layout might focus the window to avoid a focus event first
|
// emit the IPC event before the layout might focus the window to avoid a focus event first
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, PWORKSPACE->m_name, PWINDOW->m_class, PWINDOW->m_title)});
|
g_pEventManager->postEvent(SHyprIPCEvent{
|
||||||
|
"openwindow", std::format("{:x},{},{},{}", PWINDOW, !requestedWorkspace.empty() ? requestedWorkspace : PWORKSPACE->m_name, PWINDOW->m_class, PWINDOW->m_title)});
|
||||||
|
|
||||||
if (PWINDOW->m_isFloating) {
|
if (PWINDOW->m_isFloating) {
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||||
|
@@ -8,15 +8,10 @@ CMonitorFrameScheduler::CMonitorFrameScheduler(PHLMONITOR m) : m_monitor(m) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitorFrameScheduler::newSchedulingEnabled() {
|
void CMonitorFrameScheduler::onSyncFired() {
|
||||||
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
||||||
|
|
||||||
return *PENABLENEW && g_pHyprOpenGL->explicitSyncSupported();
|
if (!*PENABLENEW)
|
||||||
}
|
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onSyncFired() {
|
|
||||||
|
|
||||||
if (!newSchedulingEnabled())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
|
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
|
||||||
@@ -41,7 +36,9 @@ void CMonitorFrameScheduler::onSyncFired() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onPresented() {
|
void CMonitorFrameScheduler::onPresented() {
|
||||||
if (!newSchedulingEnabled())
|
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
||||||
|
|
||||||
|
if (!*PENABLENEW)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_pendingThird)
|
if (!m_pendingThird)
|
||||||
@@ -56,8 +53,6 @@ void CMonitorFrameScheduler::onPresented() {
|
|||||||
m_pendingThird = false;
|
m_pendingThird = false;
|
||||||
|
|
||||||
g_pEventLoopManager->doLater([m = m_monitor.lock()] {
|
g_pEventLoopManager->doLater([m = m_monitor.lock()] {
|
||||||
if (!m)
|
|
||||||
return;
|
|
||||||
g_pHyprRenderer->commitPendingAndDoExplicitSync(m); // commit the pending frame. If it didn't fire yet (is not rendered) it doesn't matter. Syncs will wait.
|
g_pHyprRenderer->commitPendingAndDoExplicitSync(m); // commit the pending frame. If it didn't fire yet (is not rendered) it doesn't matter. Syncs will wait.
|
||||||
|
|
||||||
// schedule a frame: we might have some missed damage, which got cleared due to the above commit.
|
// schedule a frame: we might have some missed damage, which got cleared due to the above commit.
|
||||||
@@ -68,6 +63,8 @@ void CMonitorFrameScheduler::onPresented() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onFrame() {
|
void CMonitorFrameScheduler::onFrame() {
|
||||||
|
static auto PENABLENEW = CConfigValue<Hyprlang::INT>("render:new_render_scheduling");
|
||||||
|
|
||||||
if (!canRender())
|
if (!canRender())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -84,7 +81,7 @@ void CMonitorFrameScheduler::onFrame() {
|
|||||||
m_monitor->m_tearingState.frameScheduledWhileBusy = false;
|
m_monitor->m_tearingState.frameScheduledWhileBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSchedulingEnabled()) {
|
if (!*PENABLENEW) {
|
||||||
m_monitor->m_lastPresentationTimer.reset();
|
m_monitor->m_lastPresentationTimer.reset();
|
||||||
|
|
||||||
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
||||||
@@ -106,7 +103,7 @@ void CMonitorFrameScheduler::onFrame() {
|
|||||||
void CMonitorFrameScheduler::onFinishRender() {
|
void CMonitorFrameScheduler::onFinishRender() {
|
||||||
m_sync = CEGLSync::create(); // this destroys the old sync
|
m_sync = CEGLSync::create(); // this destroys the old sync
|
||||||
g_pEventLoopManager->doOnReadable(m_sync->fd().duplicate(), [this, mon = m_monitor] {
|
g_pEventLoopManager->doOnReadable(m_sync->fd().duplicate(), [this, mon = m_monitor] {
|
||||||
if (!mon) // might've gotten destroyed
|
if (!m_monitor) // might've gotten destroyed
|
||||||
return;
|
return;
|
||||||
onSyncFired();
|
onSyncFired();
|
||||||
});
|
});
|
||||||
|
@@ -24,7 +24,6 @@ class CMonitorFrameScheduler {
|
|||||||
private:
|
private:
|
||||||
bool canRender();
|
bool canRender();
|
||||||
void onFinishRender();
|
void onFinishRender();
|
||||||
bool newSchedulingEnabled();
|
|
||||||
|
|
||||||
bool m_renderAtFrame = true;
|
bool m_renderAtFrame = true;
|
||||||
bool m_pendingThird = false;
|
bool m_pendingThird = false;
|
||||||
|
@@ -420,38 +420,42 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND
|
|||||||
static auto SNAPBORDEROVERLAP = CConfigValue<Hyprlang::INT>("general:snap:border_overlap");
|
static auto SNAPBORDEROVERLAP = CConfigValue<Hyprlang::INT>("general:snap:border_overlap");
|
||||||
static auto SNAPRESPECTGAPS = CConfigValue<Hyprlang::INT>("general:snap:respect_gaps");
|
static auto SNAPRESPECTGAPS = CConfigValue<Hyprlang::INT>("general:snap:respect_gaps");
|
||||||
|
|
||||||
static auto PGAPSIN = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
|
||||||
static auto PGAPSOUT = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
|
|
||||||
const auto GAPSNONE = CCssGapData{0, 0, 0, 0};
|
|
||||||
|
|
||||||
const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize;
|
const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize;
|
||||||
int snaps = 0;
|
int snaps = 0;
|
||||||
|
|
||||||
|
const bool OVERLAP = *SNAPBORDEROVERLAP;
|
||||||
|
const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize();
|
||||||
|
|
||||||
struct SRange {
|
struct SRange {
|
||||||
double start = 0;
|
double start = 0;
|
||||||
double end = 0;
|
double end = 0;
|
||||||
};
|
};
|
||||||
const auto EXTENTS = DRAGGINGWINDOW->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS);
|
SRange sourceX = {sourcePos.x, sourcePos.x + sourceSize.x};
|
||||||
SRange sourceX = {sourcePos.x - EXTENTS.topLeft.x, sourcePos.x + sourceSize.x + EXTENTS.bottomRight.x};
|
SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y};
|
||||||
SRange sourceY = {sourcePos.y - EXTENTS.topLeft.y, sourcePos.y + sourceSize.y + EXTENTS.bottomRight.y};
|
|
||||||
|
|
||||||
if (*SNAPWINDOWGAP) {
|
if (*SNAPWINDOWGAP) {
|
||||||
const double GAPSIZE = *SNAPWINDOWGAP;
|
const double GAPSIZE = *SNAPWINDOWGAP;
|
||||||
const auto WSID = DRAGGINGWINDOW->workspaceID();
|
const auto WSID = DRAGGINGWINDOW->workspaceID();
|
||||||
const bool HASFULLSCREEN = DRAGGINGWINDOW->m_workspace && DRAGGINGWINDOW->m_workspace->m_hasFullscreenWindow;
|
const bool HASFULLSCREEN = DRAGGINGWINDOW->m_workspace && DRAGGINGWINDOW->m_workspace->m_hasFullscreenWindow;
|
||||||
|
|
||||||
const auto* GAPSIN = *SNAPRESPECTGAPS ? (CCssGapData*)PGAPSIN.ptr()->getData() : &GAPSNONE;
|
double gapOffset = 0;
|
||||||
const double GAPSX = GAPSIN->m_left + GAPSIN->m_right;
|
if (*SNAPRESPECTGAPS) {
|
||||||
const double GAPSY = GAPSIN->m_top + GAPSIN->m_bottom;
|
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
||||||
|
auto* PGAPSINPTR = (CCssGapData*)(PGAPSINDATA.ptr())->getData();
|
||||||
|
gapOffset = std::max({PGAPSINPTR->m_left, PGAPSINPTR->m_right, PGAPSINPTR->m_top, PGAPSINPTR->m_bottom});
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& other : g_pCompositor->m_windows) {
|
for (auto& other : g_pCompositor->m_windows) {
|
||||||
if ((HASFULLSCREEN && !other->m_createdOverFullscreen) || other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_isMapped || other->m_fadingOut ||
|
if ((HASFULLSCREEN && !other->m_createdOverFullscreen) || other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_isMapped || other->m_fadingOut ||
|
||||||
other->isX11OverrideRedirect())
|
other->isX11OverrideRedirect())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const CBox SURF = other->getWindowBoxUnified(RESERVED_EXTENTS);
|
const int OTHERBORDERSIZE = other->getRealBorderSize();
|
||||||
const SRange SURFBX = {SURF.x - GAPSX, SURF.x + SURF.w + GAPSX};
|
const double BORDERSIZE = OVERLAP ? std::max(DRAGGINGBORDERSIZE, OTHERBORDERSIZE) : (DRAGGINGBORDERSIZE + OTHERBORDERSIZE);
|
||||||
const SRange SURFBY = {SURF.y - GAPSY, SURF.y + SURF.h + GAPSY};
|
|
||||||
|
const CBox SURF = other->getWindowMainSurfaceBox();
|
||||||
|
const SRange SURFBX = {SURF.x - BORDERSIZE - gapOffset, SURF.x + SURF.w + BORDERSIZE + gapOffset};
|
||||||
|
const SRange SURFBY = {SURF.y - BORDERSIZE - gapOffset, SURF.y + SURF.h + BORDERSIZE + gapOffset};
|
||||||
|
|
||||||
// only snap windows if their ranges overlap in the opposite axis
|
// only snap windows if their ranges overlap in the opposite axis
|
||||||
if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) {
|
if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) {
|
||||||
@@ -474,8 +478,9 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND
|
|||||||
}
|
}
|
||||||
|
|
||||||
// corner snapping
|
// corner snapping
|
||||||
|
const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE;
|
||||||
if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) {
|
if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) {
|
||||||
const SRange SURFY = {SURFBY.start + GAPSY, SURFBY.end - GAPSY};
|
const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF};
|
||||||
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && !(snaps & SNAP_UP) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) {
|
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && !(snaps & SNAP_UP) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) {
|
||||||
SNAP(sourceY.start, sourceY.end, SURFY.start);
|
SNAP(sourceY.start, sourceY.end, SURFY.start);
|
||||||
snaps |= SNAP_UP;
|
snaps |= SNAP_UP;
|
||||||
@@ -485,7 +490,7 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) {
|
if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) {
|
||||||
const SRange SURFX = {SURFBX.start + GAPSX, SURFBX.end - GAPSX};
|
const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF};
|
||||||
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && !(snaps & SNAP_LEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) {
|
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && !(snaps & SNAP_LEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) {
|
||||||
SNAP(sourceX.start, sourceX.end, SURFX.start);
|
SNAP(sourceX.start, sourceX.end, SURFX.start);
|
||||||
snaps |= SNAP_LEFT;
|
snaps |= SNAP_LEFT;
|
||||||
@@ -499,44 +504,46 @@ void IHyprLayout::performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWIND
|
|||||||
|
|
||||||
if (*SNAPMONITORGAP) {
|
if (*SNAPMONITORGAP) {
|
||||||
const double GAPSIZE = *SNAPMONITORGAP;
|
const double GAPSIZE = *SNAPMONITORGAP;
|
||||||
const auto EXTENTNONE = SBoxExtents{{0, 0}, {0, 0}};
|
const double BORDERDIFF = OVERLAP ? DRAGGINGBORDERSIZE : 0;
|
||||||
const auto* EXTENTDIFF = *SNAPBORDEROVERLAP ? &EXTENTS : &EXTENTNONE;
|
|
||||||
const auto MON = DRAGGINGWINDOW->m_monitor.lock();
|
const auto MON = DRAGGINGWINDOW->m_monitor.lock();
|
||||||
const auto* GAPSOUT = *SNAPRESPECTGAPS ? (CCssGapData*)PGAPSOUT.ptr()->getData() : &GAPSNONE;
|
double gapOffset = 0;
|
||||||
|
if (*SNAPRESPECTGAPS) {
|
||||||
|
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
|
||||||
|
auto* PGAPSOUTPTR = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData();
|
||||||
|
gapOffset = std::max({PGAPSOUTPTR->m_left, PGAPSOUTPTR->m_right, PGAPSOUTPTR->m_top, PGAPSOUTPTR->m_bottom});
|
||||||
|
}
|
||||||
|
|
||||||
SRange monX = {MON->m_position.x + MON->m_reservedTopLeft.x + GAPSOUT->m_left, MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - GAPSOUT->m_right};
|
SRange monX = {MON->m_position.x + MON->m_reservedTopLeft.x + DRAGGINGBORDERSIZE + gapOffset,
|
||||||
SRange monY = {MON->m_position.y + MON->m_reservedTopLeft.y + GAPSOUT->m_top, MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - GAPSOUT->m_bottom};
|
MON->m_position.x + MON->m_size.x - MON->m_reservedBottomRight.x - DRAGGINGBORDERSIZE - gapOffset};
|
||||||
|
SRange monY = {MON->m_position.y + MON->m_reservedTopLeft.y + DRAGGINGBORDERSIZE + gapOffset,
|
||||||
|
MON->m_position.y + MON->m_size.y - MON->m_reservedBottomRight.y - DRAGGINGBORDERSIZE - gapOffset};
|
||||||
|
|
||||||
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) &&
|
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) &&
|
||||||
((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) ||
|
((MON->m_reservedTopLeft.x > 0 && canSnap(sourceX.start, monX.start, GAPSIZE)) ||
|
||||||
canSnap(sourceX.start, (monX.start -= MON->m_reservedTopLeft.x + EXTENTDIFF->topLeft.x), GAPSIZE))) {
|
canSnap(sourceX.start, (monX.start -= MON->m_reservedTopLeft.x + BORDERDIFF), GAPSIZE))) {
|
||||||
SNAP(sourceX.start, sourceX.end, monX.start);
|
SNAP(sourceX.start, sourceX.end, monX.start);
|
||||||
snaps |= SNAP_LEFT;
|
snaps |= SNAP_LEFT;
|
||||||
}
|
}
|
||||||
if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) &&
|
if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) &&
|
||||||
((MON->m_reservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) ||
|
((MON->m_reservedBottomRight.x > 0 && canSnap(sourceX.end, monX.end, GAPSIZE)) ||
|
||||||
canSnap(sourceX.end, (monX.end += MON->m_reservedBottomRight.x + EXTENTDIFF->bottomRight.x), GAPSIZE))) {
|
canSnap(sourceX.end, (monX.end += MON->m_reservedBottomRight.x + BORDERDIFF), GAPSIZE))) {
|
||||||
SNAP(sourceX.end, sourceX.start, monX.end);
|
SNAP(sourceX.end, sourceX.start, monX.end);
|
||||||
snaps |= SNAP_RIGHT;
|
snaps |= SNAP_RIGHT;
|
||||||
}
|
}
|
||||||
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) &&
|
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) &&
|
||||||
((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) ||
|
((MON->m_reservedTopLeft.y > 0 && canSnap(sourceY.start, monY.start, GAPSIZE)) ||
|
||||||
canSnap(sourceY.start, (monY.start -= MON->m_reservedTopLeft.y + EXTENTDIFF->topLeft.y), GAPSIZE))) {
|
canSnap(sourceY.start, (monY.start -= MON->m_reservedTopLeft.y + BORDERDIFF), GAPSIZE))) {
|
||||||
SNAP(sourceY.start, sourceY.end, monY.start);
|
SNAP(sourceY.start, sourceY.end, monY.start);
|
||||||
snaps |= SNAP_UP;
|
snaps |= SNAP_UP;
|
||||||
}
|
}
|
||||||
if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) &&
|
if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) &&
|
||||||
((MON->m_reservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) ||
|
((MON->m_reservedBottomRight.y > 0 && canSnap(sourceY.end, monY.end, GAPSIZE)) ||
|
||||||
canSnap(sourceY.end, (monY.end += MON->m_reservedBottomRight.y + EXTENTDIFF->bottomRight.y), GAPSIZE))) {
|
canSnap(sourceY.end, (monY.end += MON->m_reservedBottomRight.y + BORDERDIFF), GAPSIZE))) {
|
||||||
SNAP(sourceY.end, sourceY.start, monY.end);
|
SNAP(sourceY.end, sourceY.start, monY.end);
|
||||||
snaps |= SNAP_DOWN;
|
snaps |= SNAP_DOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove extents from main surface
|
|
||||||
sourceX = {sourceX.start + EXTENTS.topLeft.x, sourceX.end - EXTENTS.bottomRight.x};
|
|
||||||
sourceY = {sourceY.start + EXTENTS.topLeft.y, sourceY.end - EXTENTS.bottomRight.y};
|
|
||||||
|
|
||||||
if (MODE == MBIND_RESIZE_FORCE_RATIO) {
|
if (MODE == MBIND_RESIZE_FORCE_RATIO) {
|
||||||
if ((CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) {
|
if ((CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) {
|
||||||
const double SIZEY = (sourceX.end - sourceX.start) * (BEGINSIZE.y / BEGINSIZE.x);
|
const double SIZEY = (sourceX.end - sourceX.start) * (BEGINSIZE.y / BEGINSIZE.x);
|
||||||
|
@@ -210,7 +210,7 @@ CProtocolManager::CProtocolManager() {
|
|||||||
else
|
else
|
||||||
lease.reset();
|
lease.reset();
|
||||||
|
|
||||||
if (g_pHyprOpenGL->m_exts.EGL_ANDROID_native_fence_sync_ext && !PROTO::sync)
|
if (!PROTO::sync)
|
||||||
PROTO::sync = makeUnique<CDRMSyncobjProtocol>(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj");
|
PROTO::sync = makeUnique<CDRMSyncobjProtocol>(&wp_linux_drm_syncobj_manager_v1_interface, 1, "DRMSyncobj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,33 +91,35 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) {
|
|||||||
g_pCompositor->focusSurface(nullptr);
|
g_pCompositor->focusSurface(nullptr);
|
||||||
g_pSeatManager->setGrab(nullptr);
|
g_pSeatManager->setGrab(nullptr);
|
||||||
|
|
||||||
if (g_pCompositor->m_unsafeState) {
|
m_sessionLock->sendDeniedTimer = makeShared<CEventLoopTimer>(
|
||||||
m_sessionLock->sendDeniedTimer = makeShared<CEventLoopTimer>(
|
// Within this arbitrary amount of time, a session-lock client is expected to create and commit a lock surface for each output. If the client fails to do that, it will be denied.
|
||||||
// Within this arbitrary amount of time, a session-lock client is expected to create and commit a lock surface for each output. If the client fails to do that, it will be denied.
|
std::chrono::seconds(5),
|
||||||
std::chrono::seconds(5),
|
[](auto, auto) {
|
||||||
[](auto, auto) {
|
if (!g_pSessionLockManager || g_pSessionLockManager->clientLocked() || g_pSessionLockManager->clientDenied())
|
||||||
if (!g_pSessionLockManager || g_pSessionLockManager->clientLocked() || g_pSessionLockManager->clientDenied())
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (g_pCompositor->m_unsafeState || !g_pCompositor->m_aqBackend->hasSession() || !g_pCompositor->m_aqBackend->session->active) {
|
if (g_pCompositor->m_unsafeState || !g_pCompositor->m_aqBackend->hasSession() || !g_pCompositor->m_aqBackend->session->active) {
|
||||||
// Because the session is inactive, there is a good reason for why the client did't recieve locked or denied.
|
// Because the session is inactive, there is a good reason for why the client did't recieve locked or denied.
|
||||||
// We send locked, although this could lead to imperfect frames when we start to render again.
|
// We send locked, although this could lead to imperfect frames when we start to render again.
|
||||||
g_pSessionLockManager->m_sessionLock->lock->sendLocked();
|
g_pSessionLockManager->m_sessionLock->lock->sendLocked();
|
||||||
g_pSessionLockManager->m_sessionLock->hasSentLocked = true;
|
g_pSessionLockManager->m_sessionLock->hasSentLocked = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pSessionLockManager->m_sessionLock && g_pSessionLockManager->m_sessionLock->lock) {
|
if (g_pSessionLockManager->m_sessionLock && g_pSessionLockManager->m_sessionLock->lock) {
|
||||||
g_pSessionLockManager->m_sessionLock->lock->sendDenied();
|
g_pSessionLockManager->m_sessionLock->lock->sendDenied();
|
||||||
g_pSessionLockManager->m_sessionLock->hasSentDenied = true;
|
g_pSessionLockManager->m_sessionLock->hasSentDenied = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
|
if (m_sessionLock->sendDeniedTimer)
|
||||||
g_pEventLoopManager->addTimer(m_sessionLock->sendDeniedTimer);
|
g_pEventLoopManager->addTimer(m_sessionLock->sendDeniedTimer);
|
||||||
} else {
|
|
||||||
// Normally the locked event is sent after each output rendered a lock screen frame.
|
// Normally the locked event is sent after each output rendered a lock screen frame.
|
||||||
// When there are no outputs, send it right away.
|
// When there are no outputs, send it right away.
|
||||||
|
if (g_pCompositor->m_unsafeState) {
|
||||||
|
removeSendDeniedTimer();
|
||||||
m_sessionLock->lock->sendLocked();
|
m_sessionLock->lock->sendLocked();
|
||||||
m_sessionLock->hasSentLocked = true;
|
m_sessionLock->hasSentLocked = true;
|
||||||
}
|
}
|
||||||
|
@@ -100,27 +100,22 @@ void CEventLoopManager::enterLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::onTimerFire() {
|
void CEventLoopManager::onTimerFire() {
|
||||||
const auto CPY = m_timers.timers;
|
for (auto const& t : m_timers.timers) {
|
||||||
for (auto const& t : CPY) {
|
if (t.strongRef() > 1 /* if it's 1, it was lost. Don't call it. */ && t->passed() && !t->cancelled())
|
||||||
if (t.strongRef() > 2 /* if it's 2, it was lost. Don't call it. */ && t->passed() && !t->cancelled())
|
|
||||||
t->call(t);
|
t->call(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleRecalc();
|
nudgeTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::addTimer(SP<CEventLoopTimer> timer) {
|
void CEventLoopManager::addTimer(SP<CEventLoopTimer> timer) {
|
||||||
if (std::ranges::contains(m_timers.timers, timer))
|
m_timers.timers.push_back(timer);
|
||||||
return;
|
nudgeTimers();
|
||||||
m_timers.timers.emplace_back(timer);
|
|
||||||
scheduleRecalc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::removeTimer(SP<CEventLoopTimer> timer) {
|
void CEventLoopManager::removeTimer(SP<CEventLoopTimer> timer) {
|
||||||
if (!std::ranges::contains(m_timers.timers, timer))
|
|
||||||
return;
|
|
||||||
std::erase_if(m_timers.timers, [timer](const auto& t) { return timer == t; });
|
std::erase_if(m_timers.timers, [timer](const auto& t) { return timer == t; });
|
||||||
scheduleRecalc();
|
nudgeTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timespecAddNs(timespec* pTimespec, int64_t delta) {
|
static void timespecAddNs(timespec* pTimespec, int64_t delta) {
|
||||||
@@ -136,21 +131,7 @@ static void timespecAddNs(timespec* pTimespec, int64_t delta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEventLoopManager::scheduleRecalc() {
|
|
||||||
// do not do it instantly, do it later. Avoid recursive access to the timer
|
|
||||||
// vector, it could be catastrophic if we modify it while iterating
|
|
||||||
|
|
||||||
if (m_timers.recalcScheduled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_timers.recalcScheduled = true;
|
|
||||||
|
|
||||||
doLater([this] { nudgeTimers(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEventLoopManager::nudgeTimers() {
|
void CEventLoopManager::nudgeTimers() {
|
||||||
m_timers.recalcScheduled = false;
|
|
||||||
|
|
||||||
// remove timers that have gone missing
|
// remove timers that have gone missing
|
||||||
std::erase_if(m_timers.timers, [](const auto& t) { return t.strongRef() <= 1; });
|
std::erase_if(m_timers.timers, [](const auto& t) { return t.strongRef() <= 1; });
|
||||||
|
|
||||||
|
@@ -27,8 +27,8 @@ class CEventLoopManager {
|
|||||||
|
|
||||||
void onTimerFire();
|
void onTimerFire();
|
||||||
|
|
||||||
// schedules a recalc of the timers
|
// recalculates timers
|
||||||
void scheduleRecalc();
|
void nudgeTimers();
|
||||||
|
|
||||||
// schedules a function to run later, aka in a wayland idle event.
|
// schedules a function to run later, aka in a wayland idle event.
|
||||||
void doLater(const std::function<void()>& fn);
|
void doLater(const std::function<void()>& fn);
|
||||||
@@ -69,7 +69,6 @@ class CEventLoopManager {
|
|||||||
private:
|
private:
|
||||||
// Manages the event sources after AQ pollFDs change.
|
// Manages the event sources after AQ pollFDs change.
|
||||||
void syncPollFDs();
|
void syncPollFDs();
|
||||||
void nudgeTimers();
|
|
||||||
|
|
||||||
struct SEventSourceData {
|
struct SEventSourceData {
|
||||||
SP<Aquamarine::SPollFD> pollFD;
|
SP<Aquamarine::SPollFD> pollFD;
|
||||||
@@ -85,7 +84,6 @@ class CEventLoopManager {
|
|||||||
struct {
|
struct {
|
||||||
std::vector<SP<CEventLoopTimer>> timers;
|
std::vector<SP<CEventLoopTimer>> timers;
|
||||||
Hyprutils::OS::CFileDescriptor timerfd;
|
Hyprutils::OS::CFileDescriptor timerfd;
|
||||||
bool recalcScheduled = false;
|
|
||||||
} m_timers;
|
} m_timers;
|
||||||
|
|
||||||
SIdleData m_idle;
|
SIdleData m_idle;
|
||||||
|
@@ -14,13 +14,13 @@ CEventLoopTimer::CEventLoopTimer(std::optional<Time::steady_dur> timeout, std::f
|
|||||||
void CEventLoopTimer::updateTimeout(std::optional<Time::steady_dur> timeout) {
|
void CEventLoopTimer::updateTimeout(std::optional<Time::steady_dur> timeout) {
|
||||||
if (!timeout.has_value()) {
|
if (!timeout.has_value()) {
|
||||||
m_expires.reset();
|
m_expires.reset();
|
||||||
g_pEventLoopManager->scheduleRecalc();
|
g_pEventLoopManager->nudgeTimers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_expires = Time::steadyNow() + *timeout;
|
m_expires = Time::steadyNow() + *timeout;
|
||||||
|
|
||||||
g_pEventLoopManager->scheduleRecalc();
|
g_pEventLoopManager->nudgeTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEventLoopTimer::passed() {
|
bool CEventLoopTimer::passed() {
|
||||||
|
@@ -219,7 +219,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
|
|||||||
m_pending.updated.bits.input = true;
|
m_pending.updated.bits.input = true;
|
||||||
|
|
||||||
if (!region) {
|
if (!region) {
|
||||||
m_pending.input = CBox{{}, Vector2D{INT32_MAX - 1, INT32_MAX - 1}};
|
m_pending.input = CBox{{}, m_pending.bufferSize};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,12 +26,12 @@ struct SSurfaceState {
|
|||||||
bool rejected = false;
|
bool rejected = false;
|
||||||
|
|
||||||
// initial values, copied from protocol text
|
// initial values, copied from protocol text
|
||||||
CHLBufferReference buffer = {}; // The initial surface contents are void
|
CHLBufferReference buffer = {}; // The initial surface contents are void
|
||||||
CRegion damage, bufferDamage; // The initial value for pending damage is empty
|
CRegion damage, bufferDamage; // The initial value for pending damage is empty
|
||||||
CRegion opaque; // The initial value for an opaque region is empty
|
CRegion opaque; // The initial value for an opaque region is empty
|
||||||
CRegion input = CBox{{}, {INT32_MAX - 1, INT32_MAX - 1}}; // The initial value for an input region is infinite
|
CRegion input = CBox{{}, {INT32_MAX, INT32_MAX}}; // The initial value for an input region is infinite
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; // A newly created surface has its buffer transformation set to normal
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; // A newly created surface has its buffer transformation set to normal
|
||||||
int scale = 1; // A newly created surface has its buffer scale set to 1
|
int scale = 1; // A newly created surface has its buffer scale set to 1
|
||||||
|
|
||||||
// these don't have well defined initial values in the protocol, but these work
|
// these don't have well defined initial values in the protocol, but these work
|
||||||
Vector2D size, bufferSize;
|
Vector2D size, bufferSize;
|
||||||
|
@@ -257,7 +257,7 @@ EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) {
|
|||||||
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
||||||
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
|
|
||||||
Debug::log(LOG, "Supported EGL global extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS);
|
Debug::log(LOG, "Supported EGL extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS, ' '), EGLEXTENSIONS);
|
||||||
|
|
||||||
m_exts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference");
|
m_exts.KHR_display_reference = EGLEXTENSIONS.contains("KHR_display_reference");
|
||||||
|
|
||||||
@@ -344,15 +344,6 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
|
|||||||
if (!m_exts.EXT_image_dma_buf_import || !m_exts.EXT_image_dma_buf_import_modifiers)
|
if (!m_exts.EXT_image_dma_buf_import || !m_exts.EXT_image_dma_buf_import_modifiers)
|
||||||
Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
|
Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
|
||||||
|
|
||||||
const std::string EGLEXTENSIONS_DISPLAY = (const char*)eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Supported EGL display extensions: ({}) {}", std::ranges::count(EGLEXTENSIONS_DISPLAY, ' '), EGLEXTENSIONS_DISPLAY);
|
|
||||||
|
|
||||||
m_exts.EGL_ANDROID_native_fence_sync_ext = EGLEXTENSIONS_DISPLAY.contains("EGL_ANDROID_native_fence_sync");
|
|
||||||
|
|
||||||
if (!m_exts.EGL_ANDROID_native_fence_sync_ext)
|
|
||||||
Debug::log(WARN, "Your GPU does not support explicit sync via the EGL_ANDROID_native_fence_sync extension.");
|
|
||||||
|
|
||||||
#ifdef USE_TRACY_GPU
|
#ifdef USE_TRACY_GPU
|
||||||
|
|
||||||
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
|
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
|
||||||
@@ -3063,10 +3054,6 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) {
|
|||||||
return pMonitor->m_output->state->state().drmFormat;
|
return pMonitor->m_output->state->state().drmFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprOpenGLImpl::explicitSyncSupported() {
|
|
||||||
return m_exts.EGL_ANDROID_native_fence_sync_ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
||||||
return m_drmFormats;
|
return m_drmFormats;
|
||||||
}
|
}
|
||||||
@@ -3133,8 +3120,6 @@ float SRenderModifData::combinedScale() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UP<CEGLSync> CEGLSync::create() {
|
UP<CEGLSync> CEGLSync::create() {
|
||||||
RASSERT(g_pHyprOpenGL->m_exts.EGL_ANDROID_native_fence_sync_ext, "Tried to create an EGL sync when syncs are not supported on the gpu");
|
|
||||||
|
|
||||||
EGLSyncKHR sync = g_pHyprOpenGL->m_proc.eglCreateSyncKHR(g_pHyprOpenGL->m_eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
EGLSyncKHR sync = g_pHyprOpenGL->m_proc.eglCreateSyncKHR(g_pHyprOpenGL->m_eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
|
||||||
|
|
||||||
if (sync == EGL_NO_SYNC_KHR) {
|
if (sync == EGL_NO_SYNC_KHR) {
|
||||||
|
@@ -253,8 +253,6 @@ class CHyprOpenGLImpl {
|
|||||||
|
|
||||||
void ensureLockTexturesRendered(bool load);
|
void ensureLockTexturesRendered(bool load);
|
||||||
|
|
||||||
bool explicitSyncSupported();
|
|
||||||
|
|
||||||
bool m_shadersInitialized = false;
|
bool m_shadersInitialized = false;
|
||||||
SP<SPreparedShaders> m_shaders;
|
SP<SPreparedShaders> m_shaders;
|
||||||
|
|
||||||
@@ -299,7 +297,6 @@ class CHyprOpenGLImpl {
|
|||||||
bool KHR_display_reference = false;
|
bool KHR_display_reference = false;
|
||||||
bool IMG_context_priority = false;
|
bool IMG_context_priority = false;
|
||||||
bool EXT_create_context_robustness = false;
|
bool EXT_create_context_robustness = false;
|
||||||
bool EGL_ANDROID_native_fence_sync_ext = false;
|
|
||||||
} m_exts;
|
} m_exts;
|
||||||
|
|
||||||
SP<CTexture> m_screencopyDeniedTexture;
|
SP<CTexture> m_screencopyDeniedTexture;
|
||||||
|
@@ -2326,22 +2326,6 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||||||
if (m_renderMode == RENDER_MODE_NORMAL)
|
if (m_renderMode == RENDER_MODE_NORMAL)
|
||||||
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
|
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
|
||||||
|
|
||||||
if (!g_pHyprOpenGL->explicitSyncSupported()) {
|
|
||||||
Debug::log(TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");
|
|
||||||
|
|
||||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here
|
|
||||||
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
|
||||||
glFinish();
|
|
||||||
else
|
|
||||||
glFlush(); // mark an implicit sync point
|
|
||||||
|
|
||||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
|
||||||
if (renderingDoneCallback)
|
|
||||||
renderingDoneCallback();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UP<CEGLSync> eglSync = CEGLSync::create();
|
UP<CEGLSync> eglSync = CEGLSync::create();
|
||||||
if (eglSync && eglSync->isValid()) {
|
if (eglSync && eglSync->isValid()) {
|
||||||
for (auto const& buf : m_usedAsyncBuffers) {
|
for (auto const& buf : m_usedAsyncBuffers) {
|
||||||
@@ -2366,7 +2350,11 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||||||
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(ERR, "renderer: Explicit sync failed, releasing resources");
|
Debug::log(ERR, "renderer: couldn't use EGLSync for explicit gpu synchronization");
|
||||||
|
|
||||||
|
// nvidia doesn't have implicit sync, so we have to explicitly wait here
|
||||||
|
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
||||||
|
glFinish();
|
||||||
|
|
||||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||||
if (renderingDoneCallback)
|
if (renderingDoneCallback)
|
||||||
|
Reference in New Issue
Block a user