MonitorSettingsWidget.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (c) 2019-2020, Jesse Buhagiar <jooster669@gmail.com>
  3. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "MonitorSettingsWidget.h"
  8. #include <Applications/DisplaySettings/MonitorSettingsGML.h>
  9. #include <LibCore/ConfigFile.h>
  10. #include <LibGUI/BoxLayout.h>
  11. #include <LibGUI/Button.h>
  12. #include <LibGUI/ComboBox.h>
  13. #include <LibGUI/Desktop.h>
  14. #include <LibGUI/ItemListModel.h>
  15. #include <LibGUI/MessageBox.h>
  16. #include <LibGUI/RadioButton.h>
  17. #include <LibGUI/WindowServerConnection.h>
  18. #include <LibGfx/SystemTheme.h>
  19. namespace DisplaySettings {
  20. MonitorSettingsWidget::MonitorSettingsWidget()
  21. {
  22. create_resolution_list();
  23. create_frame();
  24. load_current_settings();
  25. }
  26. void MonitorSettingsWidget::create_resolution_list()
  27. {
  28. // TODO: Find a better way to get the default resolution
  29. m_resolutions.append({ 640, 480 });
  30. m_resolutions.append({ 800, 600 });
  31. m_resolutions.append({ 1024, 768 });
  32. m_resolutions.append({ 1280, 720 });
  33. m_resolutions.append({ 1280, 768 });
  34. m_resolutions.append({ 1280, 960 });
  35. m_resolutions.append({ 1280, 1024 });
  36. m_resolutions.append({ 1360, 768 });
  37. m_resolutions.append({ 1368, 768 });
  38. m_resolutions.append({ 1440, 900 });
  39. m_resolutions.append({ 1600, 900 });
  40. m_resolutions.append({ 1600, 1200 });
  41. m_resolutions.append({ 1920, 1080 });
  42. m_resolutions.append({ 2048, 1152 });
  43. m_resolutions.append({ 2560, 1080 });
  44. m_resolutions.append({ 2560, 1440 });
  45. }
  46. void MonitorSettingsWidget::create_frame()
  47. {
  48. load_from_gml(monitor_settings_window_gml);
  49. m_monitor_widget = *find_descendant_of_type_named<DisplaySettings::MonitorWidget>("monitor_widget");
  50. m_resolution_combo = *find_descendant_of_type_named<GUI::ComboBox>("resolution_combo");
  51. m_resolution_combo->set_only_allow_values_from_model(true);
  52. m_resolution_combo->set_model(*GUI::ItemListModel<Gfx::IntSize>::create(m_resolutions));
  53. m_resolution_combo->on_change = [this](auto&, const GUI::ModelIndex& index) {
  54. m_monitor_widget->set_desktop_resolution(m_resolutions.at(index.row()));
  55. m_monitor_widget->update();
  56. };
  57. m_display_scale_radio_1x = *find_descendant_of_type_named<GUI::RadioButton>("scale_1x");
  58. m_display_scale_radio_1x->on_checked = [this](bool checked) {
  59. if (checked) {
  60. m_monitor_widget->set_desktop_scale_factor(1);
  61. m_monitor_widget->update();
  62. }
  63. };
  64. m_display_scale_radio_2x = *find_descendant_of_type_named<GUI::RadioButton>("scale_2x");
  65. m_display_scale_radio_2x->on_checked = [this](bool checked) {
  66. if (checked) {
  67. m_monitor_widget->set_desktop_scale_factor(2);
  68. m_monitor_widget->update();
  69. }
  70. };
  71. }
  72. void MonitorSettingsWidget::load_current_settings()
  73. {
  74. auto ws_config = Core::ConfigFile::open("/etc/WindowServer.ini");
  75. int scale_factor = ws_config->read_num_entry("Screen", "ScaleFactor", 1);
  76. if (scale_factor != 1 && scale_factor != 2) {
  77. dbgln("unexpected ScaleFactor {}, setting to 1", scale_factor);
  78. scale_factor = 1;
  79. }
  80. (scale_factor == 1 ? m_display_scale_radio_1x : m_display_scale_radio_2x)->set_checked(true);
  81. m_monitor_widget->set_desktop_scale_factor(scale_factor);
  82. // Let's attempt to find the current resolution and select it!
  83. Gfx::IntSize find_size;
  84. find_size.set_width(ws_config->read_num_entry("Screen", "Width", 1024));
  85. find_size.set_height(ws_config->read_num_entry("Screen", "Height", 768));
  86. auto index = m_resolutions.find_first_index(find_size).value_or(0);
  87. Gfx::IntSize m_current_resolution = m_resolutions.at(index);
  88. m_monitor_widget->set_desktop_resolution(m_current_resolution);
  89. m_resolution_combo->set_selected_index(index);
  90. m_monitor_widget->update();
  91. }
  92. void MonitorSettingsWidget::apply_settings()
  93. {
  94. // Store the current screen resolution and scale factor in case the user wants to revert to it.
  95. auto ws_config(Core::ConfigFile::open("/etc/WindowServer.ini"));
  96. Gfx::IntSize current_resolution;
  97. current_resolution.set_width(ws_config->read_num_entry("Screen", "Width", 1024));
  98. current_resolution.set_height(ws_config->read_num_entry("Screen", "Height", 768));
  99. int current_scale_factor = ws_config->read_num_entry("Screen", "ScaleFactor", 1);
  100. if (current_scale_factor != 1 && current_scale_factor != 2) {
  101. dbgln("unexpected ScaleFactor {}, setting to 1", current_scale_factor);
  102. current_scale_factor = 1;
  103. }
  104. if (current_resolution != m_monitor_widget->desktop_resolution() || current_scale_factor != m_monitor_widget->desktop_scale_factor()) {
  105. auto result = GUI::WindowServerConnection::the().set_resolution(m_monitor_widget->desktop_resolution(), m_monitor_widget->desktop_scale_factor());
  106. if (!result.success()) {
  107. GUI::MessageBox::show(nullptr, String::formatted("Reverting to resolution {}x{} @ {}x", result.resolution().width(), result.resolution().height(), result.scale_factor()),
  108. "Unable to set resolution", GUI::MessageBox::Type::Error);
  109. } else {
  110. auto box = GUI::MessageBox::construct(window(), String::formatted("Do you want to keep the new settings? They will be reverted after 10 seconds."),
  111. String::formatted("New screen resolution: {}x{} @ {}x", m_monitor_widget->desktop_resolution().width(), m_monitor_widget->desktop_resolution().height(),
  112. m_monitor_widget->desktop_scale_factor()),
  113. GUI::MessageBox::Type::Question, GUI::MessageBox::InputType::YesNo);
  114. box->set_icon(window()->icon());
  115. // If after 10 seconds the user doesn't close the message box, just close it.
  116. auto timer = Core::Timer::construct(10000, [&] {
  117. box->close();
  118. });
  119. // If the user selects "No", closes the window or the window gets closed by the 10 seconds timer, revert the changes.
  120. if (box->exec() != GUI::MessageBox::ExecYes) {
  121. result = GUI::WindowServerConnection::the().set_resolution(current_resolution, current_scale_factor);
  122. if (!result.success()) {
  123. GUI::MessageBox::show(nullptr, String::formatted("Reverting to resolution {}x{} @ {}x", result.resolution().width(), result.resolution().height(), result.scale_factor()),
  124. "Unable to set resolution", GUI::MessageBox::Type::Error);
  125. }
  126. }
  127. }
  128. }
  129. }
  130. }