mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 01:37:34 +00:00
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.
This commit is contained in:
parent
38af4c29e6
commit
a9906cfcd1
3 changed files with 93 additions and 1 deletions
|
@ -38,6 +38,7 @@ public:
|
||||||
void normalize();
|
void normalize();
|
||||||
bool load_config(const Core::ConfigFile& config_file, String* error_msg = nullptr);
|
bool load_config(const Core::ConfigFile& config_file, String* error_msg = nullptr);
|
||||||
bool save_config(Core::ConfigFile& config_file, bool sync = true) const;
|
bool save_config(Core::ConfigFile& config_file, bool sync = true) const;
|
||||||
|
bool try_auto_add_framebuffer(String const&);
|
||||||
|
|
||||||
// TODO: spaceship operator
|
// TODO: spaceship operator
|
||||||
bool operator!=(const ScreenLayout& other) const;
|
bool operator!=(const ScreenLayout& other) const;
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <Kernel/API/FB.h>
|
||||||
#include <Services/WindowServer/ScreenLayout.h>
|
#include <Services/WindowServer/ScreenLayout.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
// Must be included after LibIPC/Forward.h
|
// Must be included after LibIPC/Forward.h
|
||||||
#include <LibIPC/Decoder.h>
|
#include <LibIPC/Decoder.h>
|
||||||
|
@ -183,6 +186,79 @@ bool ScreenLayout::operator!=(const ScreenLayout& other) const
|
||||||
return false;
|
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 {
|
namespace IPC {
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "Screen.h"
|
#include "Screen.h"
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
#include <LibCore/ConfigFile.h>
|
#include <LibCore/ConfigFile.h>
|
||||||
|
#include <LibCore/DirIterator.h>
|
||||||
|
#include <LibCore/File.h>
|
||||||
#include <LibGfx/Palette.h>
|
#include <LibGfx/Palette.h>
|
||||||
#include <LibGfx/SystemTheme.h>
|
#include <LibGfx/SystemTheme.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -88,7 +90,20 @@ int main(int, char**)
|
||||||
for (auto& screen_info : screen_layout.screens)
|
for (auto& screen_info : screen_layout.screens)
|
||||||
fb_devices_configured.set(screen_info.device);
|
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)) {
|
if (!WindowServer::Screen::apply_layout(move(screen_layout), error_msg)) {
|
||||||
dbgln("Error applying screen layout: {}", error_msg);
|
dbgln("Error applying screen layout: {}", error_msg);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue