mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 19:27:45 +00:00
WindowServer: Add the screen mode property in the screen configuration
This will allow us to change between a couple of properties, for now it's only Device and Virtual. (How about Remote :^) ) These get handled by a different screen backend in the Screen.
This commit is contained in:
parent
e95ae4a143
commit
be98ce0f9f
6 changed files with 72 additions and 22 deletions
|
@ -2,6 +2,7 @@
|
||||||
MainScreen=0
|
MainScreen=0
|
||||||
|
|
||||||
[Screen0]
|
[Screen0]
|
||||||
|
Mode=Device
|
||||||
Device=/dev/fb0
|
Device=/dev/fb0
|
||||||
Left=0
|
Left=0
|
||||||
Top=0
|
Top=0
|
||||||
|
|
|
@ -144,14 +144,22 @@ void MonitorSettingsWidget::load_current_settings()
|
||||||
|
|
||||||
m_screens.clear();
|
m_screens.clear();
|
||||||
m_screen_edids.clear();
|
m_screen_edids.clear();
|
||||||
|
|
||||||
|
size_t virtual_screen_count = 0;
|
||||||
for (size_t i = 0; i < m_screen_layout.screens.size(); i++) {
|
for (size_t i = 0; i < m_screen_layout.screens.size(); i++) {
|
||||||
String screen_display_name;
|
String screen_display_name;
|
||||||
if (auto edid = EDID::Parser::from_framebuffer_device(m_screen_layout.screens[i].device, 0); !edid.is_error()) { // TODO: multihead
|
if (m_screen_layout.screens[i].mode == WindowServer::ScreenLayout::Screen::Mode::Device) {
|
||||||
|
if (auto edid = EDID::Parser::from_framebuffer_device(m_screen_layout.screens[i].device.value(), 0); !edid.is_error()) { // TODO: multihead
|
||||||
screen_display_name = display_name_from_edid(edid.value());
|
screen_display_name = display_name_from_edid(edid.value());
|
||||||
m_screen_edids.append(edid.release_value());
|
m_screen_edids.append(edid.release_value());
|
||||||
} else {
|
} else {
|
||||||
dbgln("Error getting EDID from device {}: {}", m_screen_layout.screens[i].device, edid.error());
|
dbgln("Error getting EDID from device {}: {}", m_screen_layout.screens[i].device.value(), edid.error());
|
||||||
screen_display_name = m_screen_layout.screens[i].device;
|
screen_display_name = m_screen_layout.screens[i].device.value();
|
||||||
|
m_screen_edids.append({});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbgln("Frame buffer {} is virtual.", i);
|
||||||
|
screen_display_name = String::formatted("Virtual screen {}", virtual_screen_count++);
|
||||||
m_screen_edids.append({});
|
m_screen_edids.append({});
|
||||||
}
|
}
|
||||||
if (i == m_screen_layout.main_screen_index)
|
if (i == m_screen_layout.main_screen_index)
|
||||||
|
|
|
@ -98,7 +98,7 @@ bool Screen::apply_layout(ScreenLayout&& screen_layout, String& error_msg)
|
||||||
|
|
||||||
for (auto& it : screens_with_resolution_change) {
|
for (auto& it : screens_with_resolution_change) {
|
||||||
auto& existing_screen = *it.key;
|
auto& existing_screen = *it.key;
|
||||||
dbgln("Closing device {} in preparation for resolution change", layout_backup.screens[existing_screen.index()].device);
|
dbgln("Closing device {} in preparation for resolution change", layout_backup.screens[existing_screen.index()].device.value_or("<virtual screen>"));
|
||||||
existing_screen.close_device();
|
existing_screen.close_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +229,8 @@ bool Screen::open_device()
|
||||||
auto& info = screen_layout_info();
|
auto& info = screen_layout_info();
|
||||||
|
|
||||||
// TODO: Support other backends
|
// TODO: Support other backends
|
||||||
m_backend = make<HardwareScreenBackend>(info.device);
|
if (info.mode == ScreenLayout::Screen::Mode::Device) {
|
||||||
|
m_backend = make<HardwareScreenBackend>(info.device.value());
|
||||||
auto return_value = m_backend->open();
|
auto return_value = m_backend->open();
|
||||||
if (return_value.is_error()) {
|
if (return_value.is_error()) {
|
||||||
dbgln("Screen #{}: Failed to open backend: {}", index(), return_value.error());
|
dbgln("Screen #{}: Failed to open backend: {}", index(), return_value.error());
|
||||||
|
@ -238,6 +239,10 @@ bool Screen::open_device()
|
||||||
|
|
||||||
set_resolution(true);
|
set_resolution(true);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln("Unsupported screen type {}", ScreenLayout::Screen::mode_to_string(info.mode));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::close_device()
|
void Screen::close_device()
|
||||||
|
|
|
@ -18,7 +18,12 @@ namespace WindowServer {
|
||||||
class ScreenLayout {
|
class ScreenLayout {
|
||||||
public:
|
public:
|
||||||
struct Screen {
|
struct Screen {
|
||||||
String device;
|
enum class Mode {
|
||||||
|
Invalid,
|
||||||
|
Device,
|
||||||
|
Virtual,
|
||||||
|
} mode;
|
||||||
|
Optional<String> device;
|
||||||
Gfx::IntPoint location;
|
Gfx::IntPoint location;
|
||||||
Gfx::IntSize resolution;
|
Gfx::IntSize resolution;
|
||||||
int scale_factor;
|
int scale_factor;
|
||||||
|
@ -28,6 +33,22 @@ public:
|
||||||
return { location, { resolution.width() / scale_factor, resolution.height() / scale_factor } };
|
return { location, { resolution.width() / scale_factor, resolution.height() / scale_factor } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static StringView mode_to_string(Mode mode)
|
||||||
|
{
|
||||||
|
#define __ENUMERATE_MODE_ENUM(val) \
|
||||||
|
case Mode::val: \
|
||||||
|
return #val;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
__ENUMERATE_MODE_ENUM(Invalid)
|
||||||
|
__ENUMERATE_MODE_ENUM(Device)
|
||||||
|
__ENUMERATE_MODE_ENUM(Virtual)
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
|
||||||
|
#undef __ENUMERATE_MODE_ENUM
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(Screen const&) const = default;
|
bool operator==(Screen const&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ bool ScreenLayout::is_valid(String* error_msg) const
|
||||||
int smallest_y = 0;
|
int smallest_y = 0;
|
||||||
for (size_t i = 0; i < screens.size(); i++) {
|
for (size_t i = 0; i < screens.size(); i++) {
|
||||||
auto& screen = screens[i];
|
auto& screen = screens[i];
|
||||||
if (screen.device.is_null() || screen.device.is_empty()) {
|
if (screen.mode == Screen::Mode::Device && (screen.device->is_empty() || screen.device->is_null())) {
|
||||||
if (error_msg)
|
if (error_msg)
|
||||||
*error_msg = String::formatted("Screen #{} has no path", i);
|
*error_msg = String::formatted("Screen #{} has no path", i);
|
||||||
return false;
|
return false;
|
||||||
|
@ -235,7 +235,16 @@ bool ScreenLayout::load_config(const Core::ConfigFile& config_file, String* erro
|
||||||
auto group_name = String::formatted("Screen{}", index);
|
auto group_name = String::formatted("Screen{}", index);
|
||||||
if (!config_file.has_group(group_name))
|
if (!config_file.has_group(group_name))
|
||||||
break;
|
break;
|
||||||
screens.append({ config_file.read_entry(group_name, "Device"),
|
auto str_mode = config_file.read_entry(group_name, "Mode");
|
||||||
|
auto mode = str_mode == "Device" ? Screen::Mode::Device : str_mode == "Virtual" ? Screen::Mode::Virtual
|
||||||
|
: Screen::Mode::Invalid;
|
||||||
|
if (mode == Screen::Mode::Invalid) {
|
||||||
|
*error_msg = String::formatted("Invalid screen mode '{}'", str_mode);
|
||||||
|
*this = {};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto device = (mode == Screen::Mode::Device) ? config_file.read_entry(group_name, "Device") : Optional<String> {};
|
||||||
|
screens.append({ mode, device,
|
||||||
{ config_file.read_num_entry(group_name, "Left"), config_file.read_num_entry(group_name, "Top") },
|
{ config_file.read_num_entry(group_name, "Left"), config_file.read_num_entry(group_name, "Top") },
|
||||||
{ config_file.read_num_entry(group_name, "Width"), config_file.read_num_entry(group_name, "Height") },
|
{ config_file.read_num_entry(group_name, "Width"), config_file.read_num_entry(group_name, "Height") },
|
||||||
config_file.read_num_entry(group_name, "ScaleFactor", 1) });
|
config_file.read_num_entry(group_name, "ScaleFactor", 1) });
|
||||||
|
@ -255,7 +264,9 @@ bool ScreenLayout::save_config(Core::ConfigFile& config_file, bool sync) const
|
||||||
while (index < screens.size()) {
|
while (index < screens.size()) {
|
||||||
auto& screen = screens[index];
|
auto& screen = screens[index];
|
||||||
auto group_name = String::formatted("Screen{}", index);
|
auto group_name = String::formatted("Screen{}", index);
|
||||||
config_file.write_entry(group_name, "Device", screen.device);
|
config_file.write_entry(group_name, "Mode", Screen::mode_to_string(screen.mode));
|
||||||
|
if (screen.mode == Screen::Mode::Device)
|
||||||
|
config_file.write_entry(group_name, "Device", screen.device.value());
|
||||||
config_file.write_num_entry(group_name, "Left", screen.location.x());
|
config_file.write_num_entry(group_name, "Left", screen.location.x());
|
||||||
config_file.write_num_entry(group_name, "Top", screen.location.y());
|
config_file.write_num_entry(group_name, "Top", screen.location.y());
|
||||||
config_file.write_num_entry(group_name, "Width", screen.resolution.width());
|
config_file.write_num_entry(group_name, "Width", screen.resolution.width());
|
||||||
|
@ -321,7 +332,8 @@ bool ScreenLayout::try_auto_add_framebuffer(String const& device_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto append_screen = [&](Gfx::IntRect const& new_screen_rect) {
|
auto append_screen = [&](Gfx::IntRect const& new_screen_rect) {
|
||||||
screens.append({ .device = device_path,
|
screens.append({ .mode = Screen::Mode::Device,
|
||||||
|
.device = device_path,
|
||||||
.location = new_screen_rect.location(),
|
.location = new_screen_rect.location(),
|
||||||
.resolution = new_screen_rect.size(),
|
.resolution = new_screen_rect.size(),
|
||||||
.scale_factor = 1 });
|
.scale_factor = 1 });
|
||||||
|
@ -379,13 +391,15 @@ namespace IPC {
|
||||||
|
|
||||||
bool encode(Encoder& encoder, const WindowServer::ScreenLayout::Screen& screen)
|
bool encode(Encoder& encoder, const WindowServer::ScreenLayout::Screen& screen)
|
||||||
{
|
{
|
||||||
encoder << screen.device << screen.location << screen.resolution << screen.scale_factor;
|
encoder << screen.mode << screen.device << screen.location << screen.resolution << screen.scale_factor;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> decode(Decoder& decoder, WindowServer::ScreenLayout::Screen& screen)
|
ErrorOr<void> decode(Decoder& decoder, WindowServer::ScreenLayout::Screen& screen)
|
||||||
{
|
{
|
||||||
String device;
|
WindowServer::ScreenLayout::Screen::Mode mode;
|
||||||
|
TRY(decoder.decode(mode));
|
||||||
|
Optional<String> device;
|
||||||
TRY(decoder.decode(device));
|
TRY(decoder.decode(device));
|
||||||
Gfx::IntPoint location;
|
Gfx::IntPoint location;
|
||||||
TRY(decoder.decode(location));
|
TRY(decoder.decode(location));
|
||||||
|
@ -393,7 +407,7 @@ ErrorOr<void> decode(Decoder& decoder, WindowServer::ScreenLayout::Screen& scree
|
||||||
TRY(decoder.decode(resolution));
|
TRY(decoder.decode(resolution));
|
||||||
int scale_factor = 0;
|
int scale_factor = 0;
|
||||||
TRY(decoder.decode(scale_factor));
|
TRY(decoder.decode(scale_factor));
|
||||||
screen = { device, location, resolution, scale_factor };
|
screen = { mode, device, location, resolution, scale_factor };
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,8 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
||||||
|
|
||||||
if (screen_layout.load_config(*wm_config, &error_msg)) {
|
if (screen_layout.load_config(*wm_config, &error_msg)) {
|
||||||
for (auto& screen_info : screen_layout.screens)
|
for (auto& screen_info : screen_layout.screens)
|
||||||
fb_devices_configured.set(screen_info.device);
|
if (screen_info.mode == WindowServer::ScreenLayout::Screen::Mode::Device)
|
||||||
|
fb_devices_configured.set(screen_info.device.value());
|
||||||
|
|
||||||
add_unconfigured_devices();
|
add_unconfigured_devices();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue