From 34394044b3dd0852aa58910aa7b1b7b897e6ebb8 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 13 Jun 2021 21:09:47 -0600 Subject: [PATCH] WindowServer: Validate that all screens can be reached If there are any screens that are detached from other screens it would not be possible to get to them using the mouse pointer. Also make sure that none of the screens are overlapping. --- Userland/Services/WindowServer/main.cpp | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Userland/Services/WindowServer/main.cpp b/Userland/Services/WindowServer/main.cpp index 69afde1b9c..284688614e 100644 --- a/Userland/Services/WindowServer/main.cpp +++ b/Userland/Services/WindowServer/main.cpp @@ -96,6 +96,20 @@ int main(int, char**) wm_config->read_num_entry(group_name, "Width", 1024 / scale), wm_config->read_num_entry("Screen", "Height", 768 / scale) }; + + // Check if the screen would be overlapping with another one + if (WindowServer::Screen::for_each([&](auto& screen) { + if (screen.rect().intersects(virtual_rect)) { + dbgln("Screen {} rect {} overlaps with screen {} rect {}: Ignoring configuration", screen.index(), screen.rect(), screen_index, virtual_rect); + return IterationDecision::Break; + } + return IterationDecision::Continue; + }) + == IterationDecision::Break) { + // Ignore the configuration + break; + } + auto* screen = WindowServer::Screen::create(device_path, virtual_rect, scale); if (!screen) { dbgln("Screen {} failed to be created", screen_index); @@ -109,6 +123,35 @@ int main(int, char**) fb_devices_configured.set(device_path); } + // Check that all screens are contiguous and can be "reached" from the main screen + { + Vector reachable_screens { &WindowServer::Screen::main() }; + bool did_reach_another_screen; + do { + did_reach_another_screen = false; + auto* latest_reachable_screen = reachable_screens[reachable_screens.size() - 1]; + WindowServer::Screen::for_each([&](auto& screen) { + if (&screen == latest_reachable_screen || reachable_screens.contains_slow(&screen)) + return IterationDecision::Continue; + if (screen.rect().is_adjacent(latest_reachable_screen->rect())) { + reachable_screens.append(&screen); + did_reach_another_screen = true; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + } while (did_reach_another_screen); + if (reachable_screens.size() != WindowServer::Screen::count()) { + WindowServer::Screen::for_each([&](auto& screen) { + if (!reachable_screens.contains_slow(&screen)) + dbgln("Screen {} cannot be reached from main screen {}: Bad configuration!", screen.index(), WindowServer::Screen::main().index()); + return IterationDecision::Continue; + }); + dbgln("At least one screen is not adjacent to another screen, exiting!"); + return 1; + } + } + // TODO: Enumerate the /dev/fbX devices and set up any ones we find that we haven't already used auto& screen_input = WindowServer::ScreenInput::the();