diff options
author | Tom <tomut@yahoo.com> | 2021-06-26 13:20:41 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-27 09:46:27 +0200 |
commit | a9906cfcd166e67305bc95f0a5a9b54a53e9afec (patch) | |
tree | b0d4e70a0e0ddbd8306664cae0823f054667e608 | |
parent | 38af4c29e69326c5aa7fab82f4870d03bc4f71f6 (diff) | |
download | serenity-a9906cfcd166e67305bc95f0a5a9b54a53e9afec.zip |
WindowServer: Try to auto-add unconfigured framebuffer devices
This will try to auto-add framebuffer devices that haven't been
explicitly configured to the right-hand side.
-rw-r--r-- | Userland/Services/WindowServer/ScreenLayout.h | 1 | ||||
-rw-r--r-- | Userland/Services/WindowServer/ScreenLayout.ipp | 76 | ||||
-rw-r--r-- | Userland/Services/WindowServer/main.cpp | 17 |
3 files changed, 93 insertions, 1 deletions
diff --git a/Userland/Services/WindowServer/ScreenLayout.h b/Userland/Services/WindowServer/ScreenLayout.h index e9d52bc43b..a2a44299c0 100644 --- a/Userland/Services/WindowServer/ScreenLayout.h +++ b/Userland/Services/WindowServer/ScreenLayout.h @@ -38,6 +38,7 @@ public: void normalize(); bool load_config(const Core::ConfigFile& config_file, String* error_msg = nullptr); bool save_config(Core::ConfigFile& config_file, bool sync = true) const; + bool try_auto_add_framebuffer(String const&); // TODO: spaceship operator bool operator!=(const ScreenLayout& other) const; diff --git a/Userland/Services/WindowServer/ScreenLayout.ipp b/Userland/Services/WindowServer/ScreenLayout.ipp index b2c55a3a59..6478724de4 100644 --- a/Userland/Services/WindowServer/ScreenLayout.ipp +++ b/Userland/Services/WindowServer/ScreenLayout.ipp @@ -4,7 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/API/FB.h> #include <Services/WindowServer/ScreenLayout.h> +#include <errno.h> +#include <fcntl.h> // Must be included after LibIPC/Forward.h #include <LibIPC/Decoder.h> @@ -183,6 +186,79 @@ bool ScreenLayout::operator!=(const ScreenLayout& other) const return false; } +bool ScreenLayout::try_auto_add_framebuffer(String const& device_path) +{ + int framebuffer_fd = open(device_path.characters(), O_RDWR | O_CLOEXEC); + if (framebuffer_fd < 0) { + int err = errno; + dbgln("Error ({}) opening framebuffer device {}", err, device_path); + return false; + } + ScopeGuard fd_guard([&] { + close(framebuffer_fd); + }); + FBResolution resolution {}; + if (fb_get_resolution(framebuffer_fd, &resolution) < 0) { + int err = errno; + dbgln("Error ({}) querying resolution from framebuffer device {}", err, device_path); + return false; + } + if (resolution.width == 0 || resolution.height == 0) { + // Looks like the display is not turned on. Since we don't know what the desired + // resolution should be, use the main display as reference. + if (screens.is_empty()) + return false; + auto& main_screen = screens[main_screen_index]; + resolution.width = main_screen.resolution.width(); + resolution.height = main_screen.resolution.height(); + } + + auto original_screens = move(screens); + screens = original_screens; + ArmedScopeGuard screens_guard([&] { + screens = move(original_screens); + }); + // Now that we know the current resolution, try to find a location that we can add onto + // TODO: make this a little more sophisticated in case a more complex layout is already configured + for (auto& screen : screens) { + auto screen_rect = screen.virtual_rect(); + Gfx::IntRect new_screen_rect { + screen_rect.right() + 1, + screen_rect.top(), + (int)resolution.width, + (int)resolution.height + }; + + bool collision = false; + for (auto& other_screen : screens) { + if (&screen == &other_screen) + continue; + if (other_screen.virtual_rect().intersects(new_screen_rect)) { + collision = true; + break; + } + } + + if (!collision) { + screens.append({ + device : device_path, + location : new_screen_rect.location(), + resolution : new_screen_rect.size(), + scale_factor : 1 + }); + + if (is_valid()) { + // We got lucky! + screens_guard.disarm(); + return true; + } + } + } + + dbgln("Failed to add framebuffer device {} with resolution {}x{} to screen layout", device_path, resolution.width, resolution.height); + return false; +} + } namespace IPC { diff --git a/Userland/Services/WindowServer/main.cpp b/Userland/Services/WindowServer/main.cpp index bad6afb571..5977f657ed 100644 --- a/Userland/Services/WindowServer/main.cpp +++ b/Userland/Services/WindowServer/main.cpp @@ -10,6 +10,8 @@ #include "Screen.h" #include "WindowManager.h" #include <LibCore/ConfigFile.h> +#include <LibCore/DirIterator.h> +#include <LibCore/File.h> #include <LibGfx/Palette.h> #include <LibGfx/SystemTheme.h> #include <signal.h> @@ -88,7 +90,20 @@ int main(int, char**) for (auto& screen_info : screen_layout.screens) fb_devices_configured.set(screen_info.device); - // TODO: Enumerate the /dev/fbX devices and set up any ones we find that we haven't already used + // Enumerate the /dev/fbX devices and try to set up any ones we find that we haven't already used + Core::DirIterator di("/dev", Core::DirIterator::SkipParentAndBaseDir); + while (di.has_next()) { + auto path = di.next_path(); + if (!path.starts_with("fb")) + continue; + auto full_path = String::formatted("/dev/{}", path); + if (!Core::File::is_device(full_path)) + continue; + if (fb_devices_configured.find(full_path) != fb_devices_configured.end()) + continue; + if (!screen_layout.try_auto_add_framebuffer(full_path)) + dbgln("Could not auto-add framebuffer device {} to screen layout", full_path); + } if (!WindowServer::Screen::apply_layout(move(screen_layout), error_msg)) { dbgln("Error applying screen layout: {}", error_msg); |