mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 02:24:14 -05:00
core/fullscreen: set pos/size of all group members to the same value when FSing groups (#15577)
* Fix group members not having uniform size when FSed * fix the same bug - but for scrolling * format * fix include * ditto * groups are evil * format * TEST - Default handled FS -- tested in dwindle Co-authored-by: Aqa-Ib <16420574+Aqa-Ib@users.noreply.github.com> * TEST - Default handled FS -- tested in scrolling Co-authored-by: Aqa-Ib <16420574+Aqa-Ib@users.noreply.github.com> * TEST - layout handled FS -- Scrolling Co-authored-by: Aqa-Ib <16420574+Aqa-Ib@users.noreply.github.com> * format and comment fix * spelling is hard * slight fix for posterity * spelling is very hard * thankyouclangdverycool * revert change that made all windows in a group show up as FS in hyprctl clients * change test to reflect the reversion * mirror mirror can you tell me who forgot to revert that change after it was redundant? * tribute to the magic mirror * clean up includes * format * Hope is the first step on the road to disappointment Fix tests failing --------- Co-authored-by: Aqa-Ib <16420574+Aqa-Ib@users.noreply.github.com>
This commit is contained in:
@@ -344,6 +344,184 @@ TEST_CASE(dwindleFullscreenMaximiseDispatchers) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(dwindleTestFsingGroupedWindows) {
|
||||
|
||||
// Shared test among all default handled FS
|
||||
|
||||
/*
|
||||
When a group of windows are FSed, all the windows in the group are expected to have the same size
|
||||
*/
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ general = { layout = 'dwindle' } })"));
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ group = { auto_group = true } })"));
|
||||
|
||||
// Config opt for adding gaps_out and border_size and a workspace rule that removes them from maximised windows to make sure maximise works properly
|
||||
|
||||
OK(getFromSocket("r/eval hl.config({ general = { gaps_out = 10, border_size = 10 } })"));
|
||||
OK(getFromSocket("/eval hl.workspace_rule({ workspace = 'f[1]', gaps_out = 0, border_size = 0 })"));
|
||||
|
||||
ASSERT(Tests::windowCount(), 0);
|
||||
auto kitten1 = Tests::spawnKitty("kitten1");
|
||||
if (!kitten1) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.toggle()"));
|
||||
|
||||
auto kitten2 = Tests::spawnKitty("kitten2");
|
||||
if (!kitten2) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
ASSERT(Tests::windowCount(), 2);
|
||||
|
||||
// Fullscreen
|
||||
{
|
||||
auto checkHiddenGroupMember = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1080");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,0");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = false })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = false })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = false })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
|
||||
// prep for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'unset' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = false })"));
|
||||
}
|
||||
|
||||
// Maximized
|
||||
{
|
||||
auto checkHiddenGroupMember = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1059");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,21");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = false })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'unset', layout_aware = false })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = false })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(dwindleTestFsFocusUnderFSWindow) {
|
||||
|
||||
// Shared test among all default handled FS
|
||||
|
||||
@@ -346,6 +346,323 @@ TEST_CASE(scroll_LAYOUT_HANDLED_maximized) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(scroll_LAYOUT_HANDLED_TestFsingGroupedWindows) {
|
||||
|
||||
/*
|
||||
When a group of windows are FSed, all the windows in the group are expected to have the same size
|
||||
|
||||
In scrolling's layout FS handling, this is expected to hold true even when we scroll away from the window
|
||||
|
||||
*/
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ group = { auto_group = true } })"));
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { follow_focus = false } })"));
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { wrap_swapcol = false } })"));
|
||||
|
||||
// Config opt for adding gaps_out and border_size and a workspace rule that removes them from maximised windows to make sure maximise works properly
|
||||
|
||||
OK(getFromSocket("r/eval hl.config({ general = { gaps_out = 10, border_size = 10 } })"));
|
||||
OK(getFromSocket("/eval hl.workspace_rule({ workspace = 'f[1]', gaps_out = 0, border_size = 0 })"));
|
||||
|
||||
// 2 grouped windows, 1 ungrouped window
|
||||
ASSERT(Tests::windowCount(), 0);
|
||||
auto kitten1 = Tests::spawnKitty("kitten1");
|
||||
if (!kitten1) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.toggle()"));
|
||||
|
||||
auto kitten2 = Tests::spawnKitty("kitten2");
|
||||
if (!kitten2) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ group = { auto_group = false } })"));
|
||||
|
||||
auto kitten3 = Tests::spawnKitty("kitten3");
|
||||
if (!kitten3) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
|
||||
ASSERT(Tests::windowCount(), 3);
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
|
||||
// Fullscreen
|
||||
{
|
||||
auto checkHiddenGroupMember = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1080");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,0");
|
||||
}
|
||||
};
|
||||
|
||||
auto checkHiddenGroupMember_notCovering = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "at: -960,0");
|
||||
// fullscreen windows are MONBOX sized so they disregard borders and gaps_out even when not covering
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1080");
|
||||
EXPECT_CONTAINS(windowEntry, "fullscreen: 0");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = true })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
|
||||
// Try scrolling away
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('focus r')"));
|
||||
|
||||
// not scrolling onto it because follow_focus = false
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: -960,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember_notCovering("kitten1");
|
||||
|
||||
// atm the viewport moves if you switch to next window in group, this it to compensate
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('inhibit_scroll 1')"));
|
||||
// try switching to next window in group when you have scrolled away
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('inhibit_scroll 0')"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: -960,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember_notCovering("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// re-establish covering status of FS group for the next test
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { follow_focus = true } })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { follow_focus = false } })"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = true })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = true })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
|
||||
// prep for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'unset' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = true })"));
|
||||
// The window may have been dropped from floating to tiling in the wrong place. make sure it is the leftmost
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('swapcol l')"));
|
||||
}
|
||||
|
||||
// Maximized
|
||||
{
|
||||
auto checkHiddenGroupMember_tiled = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1915,1059");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,21");
|
||||
}
|
||||
};
|
||||
|
||||
auto checkHiddenGroupMember_floating = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1059");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,21");
|
||||
}
|
||||
};
|
||||
|
||||
auto checkHiddenGroupMember_notCovering = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "at: -940,41");
|
||||
// cuz the gaps and borders workspace rule now applies as it is no longer covering
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1875,1019");
|
||||
EXPECT_CONTAINS(windowEntry, "fullscreen: 0");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = true })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1915,1059");
|
||||
}
|
||||
checkHiddenGroupMember_tiled("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1915,1059");
|
||||
}
|
||||
checkHiddenGroupMember_tiled("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
|
||||
// Try scrolling away
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('focus r')"));
|
||||
|
||||
// not scrolling onto it because follow_focus = false
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: -940,41");
|
||||
EXPECT_CONTAINS(str, "size: 1875,1019");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 1");
|
||||
}
|
||||
checkHiddenGroupMember_notCovering("kitten1");
|
||||
|
||||
// atm the viewport moves if you switch to next window in group, this it to compensate
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('inhibit_scroll 1')"));
|
||||
// try switching to next window in group when you have scrolled away
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.layout('inhibit_scroll 0')"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: -940,41");
|
||||
EXPECT_CONTAINS(str, "size: 1875,1019");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 1");
|
||||
}
|
||||
checkHiddenGroupMember_notCovering("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// re-establish covering status of FS group for the next test
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { follow_focus = true } })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.focus({window = 'class:kitten2'})"));
|
||||
OK(getFromSocket("/eval hl.config({ scrolling = { follow_focus = false } })"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'unset', layout_aware = true })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = true })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember_floating("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember_floating("kitten2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(scroll_LAYOUT_HANDLED_fullscreenRetainsGeometryWhileScrolling) {
|
||||
OK(getFromSocket("/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
|
||||
@@ -1075,7 +1392,7 @@ TEST_CASE(scroll_LAYOUT_HANDLED_focusInDirectionFocusFollowFocusTrue) {
|
||||
// if on_focus_under_fullscreen = 0 focus({direction}) is disallowed from moving focus from FS window
|
||||
// if on_focus_under_fullscreen = 1/2, standard behaviour of the config option won't be followed but focus will move in the firection specified as if window was not FS
|
||||
|
||||
OK(getFromSocket("r/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
OK(getFromSocket("/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
|
||||
/*
|
||||
This test serves as a test for all layouts that use deafult FS behaviour
|
||||
@@ -1396,6 +1713,184 @@ TEST_CASE(scroll_DEFAULT_HANDLED_fullscreenMaximiseDispatchers) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(scroll_DEFAULT_HANDLED_TestFsingGroupedWindows) {
|
||||
|
||||
// Shared test among all default handled FS
|
||||
|
||||
/*
|
||||
When a group of windows are FSed, all the windows in the group are expected to have the same size
|
||||
*/
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ general = { layout = 'scrolling' } })"));
|
||||
|
||||
OK(getFromSocket("/eval hl.config({ group = { auto_group = true } })"));
|
||||
|
||||
// Config opt for adding gaps_out and border_size and a workspace rule that removes them from maximised windows to make sure maximise works properly
|
||||
|
||||
OK(getFromSocket("r/eval hl.config({ general = { gaps_out = 10, border_size = 10 } })"));
|
||||
OK(getFromSocket("/eval hl.workspace_rule({ workspace = 'f[1]', gaps_out = 0, border_size = 0 })"));
|
||||
|
||||
ASSERT(Tests::windowCount(), 0);
|
||||
auto kitten1 = Tests::spawnKitty("kitten1");
|
||||
if (!kitten1) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.toggle()"));
|
||||
|
||||
auto kitten2 = Tests::spawnKitty("kitten2");
|
||||
if (!kitten2) {
|
||||
FAIL_TEST("Could not spawn kitty");
|
||||
}
|
||||
ASSERT(Tests::windowCount(), 2);
|
||||
|
||||
// Fullscreen
|
||||
{
|
||||
auto checkHiddenGroupMember = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1080");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,0");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = false })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = false })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'set', layout_aware = false })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member.
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member.
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,0");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1080");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
|
||||
// prep for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'unset' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'fullscreen', action = 'unset', layout_aware = false })"));
|
||||
}
|
||||
|
||||
// Maximized
|
||||
{
|
||||
auto checkHiddenGroupMember = [&](const std::string& targetKitten) {
|
||||
auto clients = getFromSocket("/clients");
|
||||
auto classPos = clients.find("class: " + targetKitten);
|
||||
if (classPos == std::string::npos) {
|
||||
FAIL_TEST("Could not find specific kitten in clients output");
|
||||
} else {
|
||||
auto entryStart = clients.rfind("Window ", classPos);
|
||||
auto entryEnd = clients.find("\n\n", classPos);
|
||||
auto windowEntry = clients.substr(entryStart, entryEnd - entryStart);
|
||||
EXPECT_CONTAINS(windowEntry, "size: 1920,1059");
|
||||
EXPECT_CONTAINS(windowEntry, "at: 0,21");
|
||||
}
|
||||
};
|
||||
|
||||
// Tiled
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = false })"));
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member.
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
|
||||
// go back for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.prev()"));
|
||||
// unset FS for next test
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'unset', layout_aware = false })"));
|
||||
|
||||
// floating
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.float({ action = 'set' })"));
|
||||
OK(getFromSocket("/dispatch hl.dsp.window.fullscreen({ mode = 'maximized', action = 'set', layout_aware = false })"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten2).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten2");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten1");
|
||||
|
||||
// try switching to next window in group
|
||||
OK(getFromSocket("/dispatch hl.dsp.group.next()"));
|
||||
|
||||
{
|
||||
// check position and size for the focused group member (kitten1).
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitten1");
|
||||
EXPECT_CONTAINS(str, "at: 0,21");
|
||||
EXPECT_CONTAINS(str, "size: 1920,1059");
|
||||
}
|
||||
checkHiddenGroupMember("kitten2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(scroll_DEFAULT_HANDLED_testFsFocusUnderFSWindow) {
|
||||
|
||||
// Shared test among all default handled FS
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "../../../desktop/state/FocusState.hpp"
|
||||
#include "../../../protocols/types/ContentType.hpp"
|
||||
#include "../../../config/shared/parserUtils/ParserUtils.hpp"
|
||||
#include "desktop/rule/windowRule/WindowRuleEffectContainer.hpp"
|
||||
#include "../../../desktop/view/Group.hpp"
|
||||
|
||||
#include <hyprutils/string/Numeric.hpp>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
@@ -415,7 +415,8 @@ bool CWindowRule::matches(PHLWINDOW w, bool allowEnvLookup) {
|
||||
return false;
|
||||
break;
|
||||
case RULE_PROP_FULLSCREEN:
|
||||
if (!engine->match(Fullscreen::controller()->isFullscreen(w)))
|
||||
// FS states of a group are owned by the current window of the group
|
||||
if (!engine->match(Fullscreen::controller()->isFullscreen(w->m_group ? w->m_group->current() : w)))
|
||||
return false;
|
||||
break;
|
||||
case RULE_PROP_PINNED:
|
||||
@@ -435,11 +436,13 @@ bool CWindowRule::matches(PHLWINDOW w, bool allowEnvLookup) {
|
||||
return false;
|
||||
break;
|
||||
case RULE_PROP_FULLSCREENSTATE_INTERNAL:
|
||||
if (!engine->match(Fullscreen::controller()->getFullscreenModes(w).internal))
|
||||
// FS states of a group are owned by the current window of the group
|
||||
if (!engine->match(Fullscreen::controller()->getFullscreenModes(w->m_group ? w->m_group->current() : w).internal))
|
||||
return false;
|
||||
break;
|
||||
case RULE_PROP_FULLSCREENSTATE_CLIENT:
|
||||
if (!engine->match(Fullscreen::controller()->getFullscreenModes(w).client))
|
||||
// FS states of a group are owned by the current window of the group
|
||||
if (!engine->match(Fullscreen::controller()->getFullscreenModes(w->m_group ? w->m_group->current() : w).client))
|
||||
return false;
|
||||
break;
|
||||
case RULE_PROP_ON_WORKSPACE:
|
||||
|
||||
@@ -258,7 +258,6 @@ void CGroup::setCurrent(size_t idx) {
|
||||
if (IS_FULLSCREEN) {
|
||||
Fullscreen::controller()->setFullscreenMode(newWindow, FS_MODE_INTERNAL, std::nullopt, IS_LAYOUT_HANDLED);
|
||||
newWindow->m_target->warpPositionSize();
|
||||
oldWindow->m_target->setPositionGlobal(newWindow->m_target->position()); // TODO: this is a hack and sucks
|
||||
}
|
||||
|
||||
if (WASFOCUS)
|
||||
|
||||
@@ -552,6 +552,7 @@ void SScrollingData::recalculate(bool forceInstant) {
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = true;
|
||||
// must set pos of the highest level target (i.e. if target a part of a group, must set that group's pos which will set the pos of all member targets)
|
||||
TDATA->target->setPositionGlobal(targetBoxWithGaps(TDATA->layoutBox, i, j, COL_HAS_FS_TARGET && TARGET_FS_MODE == Fullscreen::FSMODE_FULLSCREEN));
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = false;
|
||||
}
|
||||
|
||||
if (forceInstant && TDATA->target)
|
||||
|
||||
@@ -45,7 +45,7 @@ bool CScrollingFullscreenHandler::isFullscreen(SP<Layout::ITarget> target, const
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
// A window group's FS modes are considered to be owned by its current window
|
||||
// A window group's FS state is considered to be owned by its current window
|
||||
if (const auto WINDOW_GROUP_TARGET = dc<Layout::CWindowGroupTarget*>(target.get()); WINDOW_GROUP_TARGET && target->type() == Layout::TARGET_TYPE_GROUP) {
|
||||
if (WINDOW_GROUP_TARGET->getGroup() && WINDOW_GROUP_TARGET->getGroup()->current() && WINDOW_GROUP_TARGET->getGroup()->current()->m_target)
|
||||
target = WINDOW_GROUP_TARGET->getGroup()->current()->m_target;
|
||||
@@ -96,6 +96,7 @@ SFullscreenMode CScrollingFullscreenHandler::getFullscreenModes(SP<Layout::ITarg
|
||||
if (!target)
|
||||
return {};
|
||||
|
||||
// A window group's FS modes are considered to be owned by its current window
|
||||
if (const auto WINDOW_GROUP_TARGET = dc<Layout::CWindowGroupTarget*>(target.get()); WINDOW_GROUP_TARGET && target->type() == Layout::TARGET_TYPE_GROUP) {
|
||||
if (WINDOW_GROUP_TARGET->getGroup() && WINDOW_GROUP_TARGET->getGroup()->current() && WINDOW_GROUP_TARGET->getGroup()->current()->m_target)
|
||||
target = WINDOW_GROUP_TARGET->getGroup()->current()->m_target;
|
||||
@@ -288,9 +289,18 @@ void CScrollingFullscreenHandler::updateTargetRulesAndDecos(const SP<Layout::ITa
|
||||
const auto MONITOR = target->workspace()->m_monitor.lock();
|
||||
const auto WINDOW = target->window();
|
||||
|
||||
WINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
WINDOW->updateDecorationValues();
|
||||
// If window is in a group, we need to update these values for ALL members of the group.
|
||||
if (WINDOW->m_group) {
|
||||
for (const auto& gm : WINDOW->m_group->windows()) {
|
||||
gm->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
gm->updateDecorationValues();
|
||||
}
|
||||
} else {
|
||||
WINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
WINDOW->updateDecorationValues();
|
||||
}
|
||||
|
||||
// Normally, FS controller's FS state setter's method of handling window rules should be used; but calling g_layoutManager->recalculateMonitor(MONITOR) and getSpace()->recalculate()
|
||||
// here would lead to an inf recursion
|
||||
@@ -565,7 +575,6 @@ eFullscreenHandler CScrollingFullscreenHandler::getFullscreenHandlerName() const
|
||||
|
||||
void CScrollingFullscreenHandler::sScrollingDataRecalculateHelper(const SP<Layout::Tiled::SScrollingTargetData> CURRENT_FS_TDATA, const PHLMONITOR MONITOR,
|
||||
const bool TARGET_WORKSPACE_HAS_FS) {
|
||||
|
||||
// TODO Decouple FS logic from SScrollingData::recalculate() to avoid having to schedule a prop refresh: it has to be here and it's a mess because recalculate() handled scrolling
|
||||
// onto/away from FS windows and this process doesn't call the controller's FS setters which are normally responsible for handling window rule checks.
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../../state/MonitorState.hpp"
|
||||
#include "../../desktop/Workspace.hpp"
|
||||
#include "../../managers/fullscreen/FullscreenController.hpp"
|
||||
#include "../../desktop/view/Group.hpp"
|
||||
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
|
||||
@@ -44,6 +45,11 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
if (!m_window)
|
||||
return;
|
||||
|
||||
const auto effectiveWindow = [&]() {
|
||||
// FS state of a window in a group is owned by the current window of that group.
|
||||
return window()->m_group ? window()->m_group->current() : window();
|
||||
};
|
||||
|
||||
g_pHyprRenderer->damageWindow(m_window.lock());
|
||||
CScopeGuard x([this] { g_pHyprRenderer->damageWindow(m_window.lock()); });
|
||||
|
||||
@@ -67,7 +73,7 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
}
|
||||
|
||||
// Non-FS Floating Windows
|
||||
if (floating() && m_window && !Fullscreen::controller()->isFullscreen(m_window.lock())) {
|
||||
if (floating() && m_window && !Fullscreen::controller()->isFullscreen(effectiveWindow())) {
|
||||
m_window->setBox(m_box.logicalBox);
|
||||
|
||||
if (CONFIGURECLIENT)
|
||||
@@ -79,17 +85,15 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
|
||||
/* FS Handling */
|
||||
|
||||
// prevent re-setting an FS window's pos after it is set by the FS calls
|
||||
if (m_window && Fullscreen::controller()->isFullscreen(m_window.lock(), std::nullopt, true)) {
|
||||
// prevent re-setting a covering FS window's pos after it is set by the FS calls
|
||||
if (m_window && Fullscreen::controller()->isFullscreen(effectiveWindow(), std::nullopt, true)) {
|
||||
if (!Fullscreen::controller()->m_windowPosSettingQueued)
|
||||
return;
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = false;
|
||||
}
|
||||
|
||||
// Default Handled FS (floating or tiling)
|
||||
if (const auto FSMODES = Fullscreen::controller()->getFullscreenModes(m_window.lock());
|
||||
FSMODES.internal != Fullscreen::FSMODE_NONE && !Fullscreen::controller()->layoutManagedFS(m_self->window())) {
|
||||
|
||||
if (const auto FSMODES = Fullscreen::controller()->getFullscreenModes(effectiveWindow());
|
||||
FSMODES.internal != Fullscreen::FSMODE_NONE && !Fullscreen::controller()->layoutManagedFS(effectiveWindow())) {
|
||||
if (FSMODES.internal == Fullscreen::FSMODE_FULLSCREEN) {
|
||||
m_window->setBox(m_box.logicalBox);
|
||||
|
||||
@@ -100,7 +104,8 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
visualBox.round();
|
||||
|
||||
// Reserved area must be updated before this is called
|
||||
const auto RESERVED = m_window->getFullWindowReservedArea();
|
||||
// Reserved area for all windows in a group are owned by the leading window. Other windows are hidden anyway so this simply ensures their sizes are uniform when FSed
|
||||
const auto RESERVED = effectiveWindow()->getFullWindowReservedArea();
|
||||
|
||||
m_window->setBox({visualBox.pos() + RESERVED.topLeft, visualBox.size() - (RESERVED.topLeft + RESERVED.bottomRight)});
|
||||
}
|
||||
@@ -111,9 +116,9 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Layout handled FS
|
||||
if (const auto FSMODES = Fullscreen::controller()->getFullscreenModes(m_window.lock());
|
||||
FSMODES.internal != Fullscreen::FSMODE_NONE && Fullscreen::controller()->layoutManagedFS(m_self->window())) {
|
||||
// Layout handled FS (Tiled Only)
|
||||
if (const auto FSMODES = Fullscreen::controller()->getFullscreenModes(effectiveWindow());
|
||||
FSMODES.internal != Fullscreen::FSMODE_NONE && Fullscreen::controller()->layoutManagedFS(effectiveWindow())) {
|
||||
|
||||
CBox nodeBox = m_box.logicalBox;
|
||||
CBox visualBox = m_box.visualBox.empty() ? nodeBox : m_box.visualBox;
|
||||
@@ -124,7 +129,8 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
} else if (FSMODES.internal == Fullscreen::FSMODE_MAXIMIZED) {
|
||||
|
||||
// Reserved area must be updated before this is called
|
||||
const auto RESERVED = m_window->getFullWindowReservedArea();
|
||||
// Reserved area for all windows in a group are owned by the leading window. Other windows are hidden anyway so this simply ensures their sizes are uniform when FSed
|
||||
const auto RESERVED = effectiveWindow()->getFullWindowReservedArea();
|
||||
m_window->setBox({visualBox.pos() + RESERVED.topLeft, visualBox.size() - (RESERVED.topLeft + RESERVED.bottomRight)});
|
||||
}
|
||||
|
||||
@@ -166,7 +172,7 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
|
||||
Vector2D ratioPadding;
|
||||
|
||||
if ((*REQUESTEDRATIO).y != 0 && m_space->algorithm()->tiledTargets() <= 1 && m_window && !Fullscreen::controller()->isFullscreen(m_window.lock())) {
|
||||
if ((*REQUESTEDRATIO).y != 0 && m_space->algorithm()->tiledTargets() <= 1 && m_window) {
|
||||
const Vector2D originalSize = MONITOR_WORKAREA.size();
|
||||
|
||||
const double requestedRatio = (*REQUESTEDRATIO).x / (*REQUESTEDRATIO).y;
|
||||
@@ -194,7 +200,7 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
|
||||
}
|
||||
|
||||
if (isPseudo() && m_window && !Fullscreen::controller()->isFullscreen(m_window.lock())) {
|
||||
if (isPseudo() && m_window) {
|
||||
// Calculate pseudo
|
||||
float scale = 1;
|
||||
|
||||
@@ -226,9 +232,8 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
|
||||
if (*PCLAMP_TILED) {
|
||||
Vector2D minSize = m_window->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE});
|
||||
Vector2D maxSize =
|
||||
Fullscreen::controller()->isFullscreen(m_window.lock()) ? Vector2D{INFINITY, INFINITY} : m_window->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY});
|
||||
calcSize = calcSize.clamp(minSize, maxSize);
|
||||
Vector2D maxSize = m_window->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY});
|
||||
calcSize = calcSize.clamp(minSize, maxSize);
|
||||
|
||||
calcPos += (availableSpace - calcSize) / 2.0;
|
||||
|
||||
@@ -236,7 +241,7 @@ void CWindowTarget::updatePos(uint8_t flags) {
|
||||
calcPos.y = std::clamp(calcPos.y, MONITOR_WORKAREA.y, std::max(MONITOR_WORKAREA.y, MONITOR_WORKAREA.y + MONITOR_WORKAREA.h - calcSize.y));
|
||||
}
|
||||
|
||||
if (m_window->onSpecialWorkspace() && m_window && !Fullscreen::controller()->isFullscreen(m_window.lock())) {
|
||||
if (m_window->onSpecialWorkspace() && m_window) {
|
||||
// if special, we adjust the coords a bit
|
||||
static auto PSCALEFACTOR = CConfigValue<Config::FLOAT>("dwindle:special_scale_factor");
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ bool IFullscreenHandler::isFullscreen(SP<Layout::ITarget> target, const std::opt
|
||||
!isFullscreen(target, std::nullopt, covering);
|
||||
}
|
||||
|
||||
// A window group's FS modes are considered to be owned by its current window
|
||||
// A window group's FS state is considered to be owned by its current window
|
||||
if (const auto WINDOW_GROUP_TARGET = dc<Layout::CWindowGroupTarget*>(target.get()); WINDOW_GROUP_TARGET && target->type() == Layout::TARGET_TYPE_GROUP) {
|
||||
if (WINDOW_GROUP_TARGET->getGroup() && WINDOW_GROUP_TARGET->getGroup()->current() && WINDOW_GROUP_TARGET->getGroup()->current()->m_target)
|
||||
target = WINDOW_GROUP_TARGET->getGroup()->current()->m_target;
|
||||
@@ -70,6 +70,7 @@ SFullscreenMode IFullscreenHandler::getFullscreenModes(SP<Layout::ITarget> targe
|
||||
if (!target)
|
||||
return {};
|
||||
|
||||
// A window group's FS modes are considered to be owned by its current window
|
||||
if (const auto WINDOW_GROUP_TARGET = dc<Layout::CWindowGroupTarget*>(target.get()); WINDOW_GROUP_TARGET && target->type() == Layout::TARGET_TYPE_GROUP) {
|
||||
if (WINDOW_GROUP_TARGET->getGroup() && WINDOW_GROUP_TARGET->getGroup()->current() && WINDOW_GROUP_TARGET->getGroup()->current()->m_target)
|
||||
target = WINDOW_GROUP_TARGET->getGroup()->current()->m_target;
|
||||
@@ -165,9 +166,19 @@ void IFullscreenHandler::updateTargetRulesAndDecos(const SP<Layout::ITarget> tar
|
||||
|
||||
// Target must be a fullscreen window as considered by window/workspace rule matchers by now.
|
||||
// update all the values necessary for FS windows to get correct window dimensions and pos
|
||||
WINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
WINDOW->updateDecorationValues();
|
||||
|
||||
// If window is in a group, we need to update these values for ALL members of the group.
|
||||
if (WINDOW->m_group) {
|
||||
for (const auto& gm : WINDOW->m_group->windows()) {
|
||||
gm->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
gm->updateDecorationValues();
|
||||
}
|
||||
} else {
|
||||
WINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
WINDOW->updateDecorationValues();
|
||||
}
|
||||
g_layoutManager->recalculateMonitor(MONITOR, Layout::CLayoutManager::RECALCULATE_MONITOR_REASON_TOGGLE_FULLSCREEN);
|
||||
getSpace()->recalculate(Layout::RECALCULATE_REASON_TOGGLE_DEFAULT_HANDLED_FULLSCREEN);
|
||||
}
|
||||
@@ -197,6 +208,7 @@ void IFullscreenHandler::setTargetSizeAndPosition(const SP<Layout::ITarget> targ
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = true;
|
||||
LAYOUT_TARGET->setPositionGlobal(WORKAREA);
|
||||
}
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = false;
|
||||
}
|
||||
|
||||
void IFullscreenHandler::syncTargetSizeAndPosition() {
|
||||
@@ -253,6 +265,7 @@ void IFullscreenHandler::syncTargetSizeAndPosition() {
|
||||
LAYOUT_TARGET->setPositionGlobal(WORKSPACE->m_space->workArea(FS_TARGET->floating()));
|
||||
}
|
||||
}
|
||||
Fullscreen::controller()->m_windowPosSettingQueued = false;
|
||||
}
|
||||
|
||||
void IFullscreenHandler::setNoMembersAboveFullscreen() {
|
||||
|
||||
Reference in New Issue
Block a user