mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:57:45 +00:00
WindowServer: Add a "scale" parameter to the SetResolution message and plumb it through
Now, `chres 640 480 2` can set the UI to HighDPI 640x480 at runtime. A real GUI for changing the display factor will come later. (`chres 640 480 2` followed by `chres 1280 960` is very fast since we don't have to re-allocate the framebuffer since both modes use the exact same number of physical pixels.)
This commit is contained in:
parent
248d75e13b
commit
63ac9462ad
9 changed files with 53 additions and 32 deletions
|
@ -246,7 +246,8 @@ void DisplaySettingsWidget::load_current_settings()
|
||||||
|
|
||||||
void DisplaySettingsWidget::send_settings_to_window_server()
|
void DisplaySettingsWidget::send_settings_to_window_server()
|
||||||
{
|
{
|
||||||
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetResolution>(m_monitor_widget->desktop_resolution());
|
// FIXME: Add UI for changing the scale factor.
|
||||||
|
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetResolution>(m_monitor_widget->desktop_resolution(), 1);
|
||||||
if (!result->success()) {
|
if (!result->success()) {
|
||||||
GUI::MessageBox::show(nullptr, String::formatted("Reverting to resolution {}x{}", result->resolution().width(), result->resolution().height()),
|
GUI::MessageBox::show(nullptr, String::formatted("Reverting to resolution {}x{}", result->resolution().width(), result->resolution().height()),
|
||||||
"Unable to set resolution", GUI::MessageBox::Type::Error);
|
"Unable to set resolution", GUI::MessageBox::Type::Error);
|
||||||
|
|
|
@ -340,7 +340,7 @@ OwnPtr<Messages::WindowServer::GetWallpaperResponse> ClientConnection::handle(co
|
||||||
|
|
||||||
OwnPtr<Messages::WindowServer::SetResolutionResponse> ClientConnection::handle(const Messages::WindowServer::SetResolution& message)
|
OwnPtr<Messages::WindowServer::SetResolutionResponse> ClientConnection::handle(const Messages::WindowServer::SetResolution& message)
|
||||||
{
|
{
|
||||||
return make<Messages::WindowServer::SetResolutionResponse>(WindowManager::the().set_resolution(message.resolution().width(), message.resolution().height()), WindowManager::the().resolution());
|
return make<Messages::WindowServer::SetResolutionResponse>(WindowManager::the().set_resolution(message.resolution().width(), message.resolution().height(), message.scale_factor()), WindowManager::the().resolution(), WindowManager::the().scale_factor());
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnPtr<Messages::WindowServer::SetWindowTitleResponse> ClientConnection::handle(const Messages::WindowServer::SetWindowTitle& message)
|
OwnPtr<Messages::WindowServer::SetWindowTitleResponse> ClientConnection::handle(const Messages::WindowServer::SetWindowTitle& message)
|
||||||
|
|
|
@ -710,19 +710,19 @@ void Compositor::run_animations(Gfx::DisjointRectSet& flush_rects)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compositor::set_resolution(int desired_width, int desired_height)
|
bool Compositor::set_resolution(int desired_width, int desired_height, int scale_factor)
|
||||||
{
|
{
|
||||||
auto screen_rect = Screen::the().rect();
|
auto screen_rect = Screen::the().rect();
|
||||||
if (screen_rect.width() == desired_width && screen_rect.height() == desired_height)
|
if (screen_rect.width() == desired_width && screen_rect.height() == desired_height && Screen::the().scale_factor() == scale_factor)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Make sure it's impossible to set an invalid resolution
|
// Make sure it's impossible to set an invalid resolution
|
||||||
if (!(desired_width >= 640 && desired_height >= 480)) {
|
if (!(desired_width >= 640 && desired_height >= 480 && scale_factor >= 1)) {
|
||||||
dbg() << "Compositor: Tried to set invalid resolution: " << desired_width << "x" << desired_height;
|
dbg() << "Compositor: Tried to set invalid resolution: " << desired_width << "x" << desired_height << " @ " << scale_factor << "x";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = Screen::the().set_resolution(desired_width, desired_height, 1);
|
bool success = Screen::the().set_resolution(desired_width, desired_height, scale_factor);
|
||||||
init_bitmaps();
|
init_bitmaps();
|
||||||
invalidate_occlusions();
|
invalidate_occlusions();
|
||||||
compose();
|
compose();
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
void invalidate_screen();
|
void invalidate_screen();
|
||||||
void invalidate_screen(const Gfx::IntRect&);
|
void invalidate_screen(const Gfx::IntRect&);
|
||||||
|
|
||||||
bool set_resolution(int desired_width, int desired_height);
|
bool set_resolution(int desired_width, int desired_height, int scale_factor);
|
||||||
|
|
||||||
bool set_background_color(const String& background_color);
|
bool set_background_color(const String& background_color);
|
||||||
|
|
||||||
|
|
|
@ -69,43 +69,53 @@ Screen::~Screen()
|
||||||
close(m_framebuffer_fd);
|
close(m_framebuffer_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Screen::set_resolution(int width, int height, int scale_factor)
|
bool Screen::set_resolution(int width, int height, int new_scale_factor)
|
||||||
{
|
{
|
||||||
FBResolution physical_resolution { 0, (unsigned)(width * scale_factor), (unsigned)(height * scale_factor) };
|
int new_physical_width = width * new_scale_factor;
|
||||||
|
int new_physical_height = height * new_scale_factor;
|
||||||
|
if (physical_width() == new_physical_width && physical_height() == new_physical_height) {
|
||||||
|
assert(scale_factor() != new_scale_factor);
|
||||||
|
on_change_resolution(m_pitch, physical_width(), physical_height(), new_scale_factor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBResolution physical_resolution { 0, (unsigned)new_physical_width, (unsigned)new_physical_height };
|
||||||
int rc = fb_set_resolution(m_framebuffer_fd, &physical_resolution);
|
int rc = fb_set_resolution(m_framebuffer_fd, &physical_resolution);
|
||||||
#ifdef WSSCREEN_DEBUG
|
#ifdef WSSCREEN_DEBUG
|
||||||
dbg() << "fb_set_resolution() - return code " << rc;
|
dbg() << "fb_set_resolution() - return code " << rc;
|
||||||
#endif
|
#endif
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
on_change_resolution(physical_resolution.pitch, physical_resolution.width, physical_resolution.height, scale_factor);
|
on_change_resolution(physical_resolution.pitch, physical_resolution.width, physical_resolution.height, new_scale_factor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
dbg() << "Invalid resolution " << width << "x" << height;
|
dbg() << "Invalid resolution " << width << "x" << height;
|
||||||
on_change_resolution(physical_resolution.pitch, physical_resolution.width, physical_resolution.height, scale_factor);
|
on_change_resolution(physical_resolution.pitch, physical_resolution.width, physical_resolution.height, new_scale_factor);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::on_change_resolution(int pitch, int physical_width, int physical_height, int scale_factor)
|
void Screen::on_change_resolution(int pitch, int new_physical_width, int new_physical_height, int new_scale_factor)
|
||||||
{
|
{
|
||||||
if (m_framebuffer) {
|
if (physical_width() != new_physical_width || physical_height() != new_physical_height) {
|
||||||
size_t previous_size_in_bytes = m_size_in_bytes;
|
if (m_framebuffer) {
|
||||||
int rc = munmap(m_framebuffer, previous_size_in_bytes);
|
size_t previous_size_in_bytes = m_size_in_bytes;
|
||||||
|
int rc = munmap(m_framebuffer, previous_size_in_bytes);
|
||||||
|
ASSERT(rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = fb_get_size_in_bytes(m_framebuffer_fd, &m_size_in_bytes);
|
||||||
ASSERT(rc == 0);
|
ASSERT(rc == 0);
|
||||||
|
|
||||||
|
m_framebuffer = (Gfx::RGBA32*)mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0);
|
||||||
|
ASSERT(m_framebuffer && m_framebuffer != (void*)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = fb_get_size_in_bytes(m_framebuffer_fd, &m_size_in_bytes);
|
|
||||||
ASSERT(rc == 0);
|
|
||||||
|
|
||||||
m_framebuffer = (Gfx::RGBA32*)mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0);
|
|
||||||
ASSERT(m_framebuffer && m_framebuffer != (void*)-1);
|
|
||||||
|
|
||||||
m_pitch = pitch;
|
m_pitch = pitch;
|
||||||
m_width = physical_width / scale_factor;
|
m_width = new_physical_width / new_scale_factor;
|
||||||
m_height = physical_height / scale_factor;
|
m_height = new_physical_height / new_scale_factor;
|
||||||
m_scale_factor = scale_factor;
|
m_scale_factor = new_scale_factor;
|
||||||
|
|
||||||
m_physical_cursor_location.constrain(physical_rect());
|
m_physical_cursor_location.constrain(physical_rect());
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,9 +124,9 @@ const Gfx::Font& WindowManager::window_title_font() const
|
||||||
return Gfx::FontDatabase::default_bold_font();
|
return Gfx::FontDatabase::default_bold_font();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowManager::set_resolution(int width, int height)
|
bool WindowManager::set_resolution(int width, int height, int scale)
|
||||||
{
|
{
|
||||||
bool success = Compositor::the().set_resolution(width, height);
|
bool success = Compositor::the().set_resolution(width, height, scale);
|
||||||
MenuManager::the().set_needs_window_resize();
|
MenuManager::the().set_needs_window_resize();
|
||||||
ClientConnection::for_each_client([&](ClientConnection& client) {
|
ClientConnection::for_each_client([&](ClientConnection& client) {
|
||||||
client.notify_about_new_screen_rect(Screen::the().rect());
|
client.notify_about_new_screen_rect(Screen::the().rect());
|
||||||
|
@ -139,14 +139,16 @@ bool WindowManager::set_resolution(int width, int height)
|
||||||
}
|
}
|
||||||
if (m_config) {
|
if (m_config) {
|
||||||
if (success) {
|
if (success) {
|
||||||
dbg() << "Saving resolution: " << Gfx::IntSize(width, height) << " to config file at " << m_config->file_name();
|
dbg() << "Saving resolution: " << Gfx::IntSize(width, height) << " @ " << scale << "x to config file at " << m_config->file_name();
|
||||||
m_config->write_num_entry("Screen", "Width", width);
|
m_config->write_num_entry("Screen", "Width", width);
|
||||||
m_config->write_num_entry("Screen", "Height", height);
|
m_config->write_num_entry("Screen", "Height", height);
|
||||||
|
m_config->write_num_entry("Screen", "ScaleFactor", scale);
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
} else {
|
} else {
|
||||||
dbg() << "Saving fallback resolution: " << resolution() << " to config file at " << m_config->file_name();
|
dbg() << "Saving fallback resolution: " << resolution() << " @ 1x to config file at " << m_config->file_name();
|
||||||
m_config->write_num_entry("Screen", "Width", resolution().width());
|
m_config->write_num_entry("Screen", "Width", resolution().width());
|
||||||
m_config->write_num_entry("Screen", "Height", resolution().height());
|
m_config->write_num_entry("Screen", "Height", resolution().height());
|
||||||
|
m_config->write_num_entry("Screen", "ScaleFactor", 1);
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,6 +176,11 @@ void WindowManager::set_scroll_step_size(unsigned step_size)
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WindowManager::scale_factor() const
|
||||||
|
{
|
||||||
|
return Screen::the().scale_factor();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::add_window(Window& window)
|
void WindowManager::add_window(Window& window)
|
||||||
{
|
{
|
||||||
bool is_first_window = m_windows_in_order.is_empty();
|
bool is_first_window = m_windows_in_order.is_empty();
|
||||||
|
|
|
@ -142,8 +142,9 @@ public:
|
||||||
const Gfx::Font& font() const;
|
const Gfx::Font& font() const;
|
||||||
const Gfx::Font& window_title_font() const;
|
const Gfx::Font& window_title_font() const;
|
||||||
|
|
||||||
bool set_resolution(int width, int height);
|
bool set_resolution(int width, int height, int scale);
|
||||||
Gfx::IntSize resolution() const;
|
Gfx::IntSize resolution() const;
|
||||||
|
int scale_factor() const;
|
||||||
|
|
||||||
void set_acceleration_factor(double);
|
void set_acceleration_factor(double);
|
||||||
void set_scroll_step_size(unsigned);
|
void set_scroll_step_size(unsigned);
|
||||||
|
|
|
@ -87,7 +87,7 @@ endpoint WindowServer = 2
|
||||||
SetBackgroundColor(String background_color) => ()
|
SetBackgroundColor(String background_color) => ()
|
||||||
SetWallpaperMode(String mode) => ()
|
SetWallpaperMode(String mode) => ()
|
||||||
|
|
||||||
SetResolution(Gfx::IntSize resolution) => (bool success, Gfx::IntSize resolution)
|
SetResolution(Gfx::IntSize resolution, int scale_factor) => (bool success, Gfx::IntSize resolution, int scale_factor)
|
||||||
SetWindowIconBitmap(i32 window_id, Gfx::ShareableBitmap icon) => ()
|
SetWindowIconBitmap(i32 window_id, Gfx::ShareableBitmap icon) => ()
|
||||||
|
|
||||||
GetWallpaper() => (String path)
|
GetWallpaper() => (String path)
|
||||||
|
|
|
@ -32,17 +32,19 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int width = -1;
|
int width = -1;
|
||||||
int height = -1;
|
int height = -1;
|
||||||
|
int scale = 1;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help("Change the screen resolution.");
|
args_parser.set_general_help("Change the screen resolution.");
|
||||||
args_parser.add_positional_argument(width, "Width", "width");
|
args_parser.add_positional_argument(width, "Width", "width");
|
||||||
args_parser.add_positional_argument(height, "Height", "height");
|
args_parser.add_positional_argument(height, "Height", "height");
|
||||||
|
args_parser.add_positional_argument(scale, "Scale Factor", "scale", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
// A Core::EventLoop is all we need, but WindowServerConnection needs a full Application object.
|
// A Core::EventLoop is all we need, but WindowServerConnection needs a full Application object.
|
||||||
char* dummy_argv[] = { argv[0] };
|
char* dummy_argv[] = { argv[0] };
|
||||||
auto app = GUI::Application::construct(1, dummy_argv);
|
auto app = GUI::Application::construct(1, dummy_argv);
|
||||||
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetResolution>(Gfx::IntSize { width, height });
|
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetResolution>(Gfx::IntSize { width, height }, scale);
|
||||||
if (!result->success()) {
|
if (!result->success()) {
|
||||||
warnln("failed to set resolution");
|
warnln("failed to set resolution");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue