mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:57:35 +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()
|
||||
{
|
||||
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()) {
|
||||
GUI::MessageBox::show(nullptr, String::formatted("Reverting to resolution {}x{}", result->resolution().width(), result->resolution().height()),
|
||||
"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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -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();
|
||||
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;
|
||||
|
||||
// Make sure it's impossible to set an invalid resolution
|
||||
if (!(desired_width >= 640 && desired_height >= 480)) {
|
||||
dbg() << "Compositor: Tried to set invalid resolution: " << desired_width << "x" << desired_height;
|
||||
if (!(desired_width >= 640 && desired_height >= 480 && scale_factor >= 1)) {
|
||||
dbg() << "Compositor: Tried to set invalid resolution: " << desired_width << "x" << desired_height << " @ " << scale_factor << "x";
|
||||
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();
|
||||
invalidate_occlusions();
|
||||
compose();
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
void invalidate_screen();
|
||||
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);
|
||||
|
||||
|
|
|
@ -69,43 +69,53 @@ Screen::~Screen()
|
|||
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);
|
||||
#ifdef WSSCREEN_DEBUG
|
||||
dbg() << "fb_set_resolution() - return code " << rc;
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
if (rc == -1) {
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
size_t previous_size_in_bytes = m_size_in_bytes;
|
||||
int rc = munmap(m_framebuffer, previous_size_in_bytes);
|
||||
if (physical_width() != new_physical_width || physical_height() != new_physical_height) {
|
||||
if (m_framebuffer) {
|
||||
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);
|
||||
|
||||
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_width = physical_width / scale_factor;
|
||||
m_height = physical_height / scale_factor;
|
||||
m_scale_factor = scale_factor;
|
||||
m_width = new_physical_width / new_scale_factor;
|
||||
m_height = new_physical_height / new_scale_factor;
|
||||
m_scale_factor = new_scale_factor;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
ClientConnection::for_each_client([&](ClientConnection& client) {
|
||||
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 (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", "Height", height);
|
||||
m_config->write_num_entry("Screen", "ScaleFactor", scale);
|
||||
m_config->sync();
|
||||
} 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", "Height", resolution().height());
|
||||
m_config->write_num_entry("Screen", "ScaleFactor", 1);
|
||||
m_config->sync();
|
||||
}
|
||||
}
|
||||
|
@ -174,6 +176,11 @@ void WindowManager::set_scroll_step_size(unsigned step_size)
|
|||
m_config->sync();
|
||||
}
|
||||
|
||||
int WindowManager::scale_factor() const
|
||||
{
|
||||
return Screen::the().scale_factor();
|
||||
}
|
||||
|
||||
void WindowManager::add_window(Window& window)
|
||||
{
|
||||
bool is_first_window = m_windows_in_order.is_empty();
|
||||
|
|
|
@ -142,8 +142,9 @@ public:
|
|||
const Gfx::Font& 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;
|
||||
int scale_factor() const;
|
||||
|
||||
void set_acceleration_factor(double);
|
||||
void set_scroll_step_size(unsigned);
|
||||
|
|
|
@ -87,7 +87,7 @@ endpoint WindowServer = 2
|
|||
SetBackgroundColor(String background_color) => ()
|
||||
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) => ()
|
||||
|
||||
GetWallpaper() => (String path)
|
||||
|
|
|
@ -32,17 +32,19 @@ int main(int argc, char** argv)
|
|||
{
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
int scale = 1;
|
||||
|
||||
Core::ArgsParser args_parser;
|
||||
args_parser.set_general_help("Change the screen resolution.");
|
||||
args_parser.add_positional_argument(width, "Width", "width");
|
||||
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);
|
||||
|
||||
// A Core::EventLoop is all we need, but WindowServerConnection needs a full Application object.
|
||||
char* dummy_argv[] = { argv[0] };
|
||||
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()) {
|
||||
warnln("failed to set resolution");
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue