1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 16:37:47 +00:00

Applications: Create a display properties manager

An interactive application to modify the current display settings, such as
the current wallpaper as well as the screen resolution. Currently we're
adding the resolutions ourselves, because there's currently no way to
detect was resolutions the current display adapter supports (or at least
I can't see one... Maybe VBE does and I'm stupid). It even comes with
a very nice template'd `ItemList` that can support a vector of any type,
which makes life much simpler.
This commit is contained in:
Jesse Buhagiar 2019-09-03 21:45:02 +10:00 committed by Andreas Kling
parent af14b8dc59
commit ecbc0322c1
15 changed files with 329 additions and 1 deletions

View file

@ -0,0 +1,156 @@
#include <AK/StringBuilder.h>
#include <LibCore/CDirIterator.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GDesktop.h>
#include <LibGUI/GEventLoop.h>
#include <LibGUI/GFileSystemModel.h>
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GListView.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GSplitter.h>
#include <LibGUI/GTabWidget.h>
#include <LibGUI/GToolBar.h>
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
#include <Servers/WindowServer/WSWindowManager.h>
#include "DisplayProperties.h"
#include "ItemListModel.h"
DisplayPropertiesWidget::DisplayPropertiesWidget()
: m_wm_config(CConfigFile::get_for_app("WindowManager"))
{
create_root_widget();
create_frame();
create_resolution_list();
create_wallpaper_list();
}
void DisplayPropertiesWidget::create_resolution_list()
{
// TODO: Find a better way to get the default resolution
m_resolutions.append({ 640, 480 });
m_resolutions.append({ 800, 600 });
m_resolutions.append({ 1024, 768 });
m_resolutions.append({ 1280, 1024 });
m_resolutions.append({ 1366, 768 });
m_resolutions.append({ 1440, 900 });
m_resolutions.append({ 1600, 900 });
m_resolutions.append({ 1920, 1080 });
m_resolutions.append({ 2560, 1080 });
m_selected_resolution = m_resolutions.at(0);
}
void DisplayPropertiesWidget::create_root_widget()
{
m_root_widget = new GWidget;
m_root_widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
m_root_widget->set_fill_with_background_color(true);
m_root_widget->layout()->set_margins({ 4, 4, 4, 16 });
}
void DisplayPropertiesWidget::create_wallpaper_list()
{
CDirIterator iterator("/res/wallpapers/", CDirIterator::Flags::SkipDots);
while (iterator.has_next())
m_wallpapers.append(iterator.next_path());
}
void DisplayPropertiesWidget::create_frame()
{
auto* tab_widget = new GTabWidget(m_root_widget);
// First, let's create the "Background" tab
auto* background_splitter = new GSplitter(Orientation::Vertical, nullptr);
tab_widget->add_widget("Wallpaper", background_splitter);
auto* background_content = new GWidget(background_splitter);
background_content->set_layout(make<GBoxLayout>(Orientation::Vertical));
background_content->layout()->add_spacer();
background_content->layout()->set_margins({ 4, 4, 4, 4 });
auto* wallpaper_list = new GListView(background_content);
wallpaper_list->set_background_color(Color::White);
wallpaper_list->set_model(*ItemListModel<AK::String>::create(m_wallpapers));
wallpaper_list->horizontal_scrollbar().set_visible(false);
wallpaper_list->on_selection = [this](auto& index) {
m_selected_wallpaper = m_wallpapers.at(index.row());
};
// Let's add the settings tab
auto* settings_splitter = new GSplitter(Orientation::Vertical, nullptr);
tab_widget->add_widget("Settings", settings_splitter);
auto* settings_content = new GWidget(settings_splitter);
settings_content->set_layout(make<GBoxLayout>(Orientation::Vertical));
settings_content->layout()->add_spacer();
settings_content->layout()->set_margins({ 4, 4, 4, 4 });
auto* resolution_list = new GListView(settings_content);
resolution_list->set_background_color(Color::White);
resolution_list->set_model(*ItemListModel<Size>::create(m_resolutions));
resolution_list->horizontal_scrollbar().set_visible(false);
resolution_list->on_selection = [this](auto& index) {
m_selected_resolution = m_resolutions.at(index.row());
};
// Add the apply and cancel buttons
auto* bottom_widget = new GWidget(m_root_widget);
bottom_widget->set_layout(make<GBoxLayout>(Orientation::Horizontal));
bottom_widget->layout()->add_spacer();
bottom_widget->set_size_policy(Orientation::Vertical, SizePolicy::Fixed);
bottom_widget->set_preferred_size(1, 22);
auto* apply_button = new GButton(bottom_widget);
apply_button->set_text("Apply");
apply_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed);
apply_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed);
apply_button->set_preferred_size(60, 22);
apply_button->on_click = [this, tab_widget](GButton&) {
send_settings_to_window_server(tab_widget->get_active_tab());
};
auto* ok_button = new GButton(bottom_widget);
ok_button->set_text("OK");
ok_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed);
ok_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed);
ok_button->set_preferred_size(60, 22);
ok_button->on_click = [this, tab_widget](GButton&) {
send_settings_to_window_server(tab_widget->get_active_tab());
GApplication::the().quit();
};
auto* cancel_button = new GButton(bottom_widget);
cancel_button->set_text("Cancel");
cancel_button->set_size_policy(Orientation::Vertical, SizePolicy::Fixed);
cancel_button->set_size_policy(Orientation::Horizontal, SizePolicy::Fixed);
cancel_button->set_preferred_size(60, 22);
cancel_button->on_click = [this](GButton&) {
GApplication::the().quit();
};
}
void DisplayPropertiesWidget::send_settings_to_window_server(int tab_index)
{
if (tab_index == TabIndices::Wallpaper) {
StringBuilder builder;
builder.append("/res/wallpapers/");
builder.append(m_selected_wallpaper);
GDesktop::the().set_wallpaper(builder.to_string());
} else if (tab_index == TabIndices::Settings) {
WSAPI_ClientMessage request;
request.type = WSAPI_ClientMessage::Type::SetResolution;
dbg() << "Attempting to set resolution " << m_selected_resolution;
request.wm_conf.resolution = { m_selected_resolution.width(), m_selected_resolution.height() };
auto response = GWindowServerConnection::the().sync_request(request, WSAPI_ServerMessage::Type::DidSetResolution);
ASSERT(response.value == 1);
} else {
dbg() << "Invalid tab index " << tab_index;
}
}

View file

@ -0,0 +1,47 @@
#pragma once
#include <AK/AKString.h>
#include <AK/RefPtr.h>
#include <AK/Vector.h>
#include <LibCore/CConfigFile.h>
#include <LibDraw/Color.h>
#include <LibDraw/Size.h>
#include <LibGUI/GWidget.h>
class DisplayPropertiesWidget final {
public:
enum class ButtonOperations {
Ok,
Apply,
Cancel,
};
enum TabIndices {
Wallpaper,
Settings
};
public:
DisplayPropertiesWidget();
// Apply the settings to the Window Server
void send_settings_to_window_server(int tabIndex);
void create_frame();
inline GWidget* get_root_widget() const { return m_root_widget; }
private:
void create_wallpaper_list();
void create_resolution_list();
void create_root_widget();
private:
String m_wallpaper_path;
RefPtr<CConfigFile> m_wm_config;
GWidget* m_root_widget { nullptr };
Vector<Size> m_resolutions;
Vector<String> m_wallpapers;
Size m_selected_resolution;
String m_selected_wallpaper;
};

View file

@ -0,0 +1,54 @@
#pragma once
#include <AK/NonnullRefPtr.h>
#include <AK/Vector.h>
#include <LibGUI/GModel.h>
template<typename T>
class ItemListModel final : public GModel {
public:
static NonnullRefPtr<ItemListModel> create(Vector<T>& data) { return adopt(*new ItemListModel<T>(data)); }
virtual ~ItemListModel() override {}
virtual int row_count(const GModelIndex&) const override
{
return m_data.size();
}
virtual int column_count(const GModelIndex&) const override
{
return 1;
}
virtual String column_name(int) const override
{
return "Data";
}
virtual ColumnMetadata column_metadata(int) const override
{
return { 70, TextAlignment::CenterLeft };
}
virtual GVariant data(const GModelIndex& index, Role role = Role::Display) const override
{
if (role == Role::Display)
return m_data.at(index.row());
return {};
}
virtual void update() override
{
did_update();
}
private:
explicit ItemListModel(Vector<T>& data)
: m_data(data)
{
}
Vector<T>& m_data;
};

View file

@ -0,0 +1,9 @@
include ../../Makefile.common
OBJS = \
DisplayProperties.o \
main.o \
APP = DisplayProperties
include ../Makefile.common

View file

@ -0,0 +1,22 @@
#include "DisplayProperties.h"
#include <LibDraw/PNGLoader.h>
#include <LibGUI/GApplication.h>
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
int main(int argc, char** argv)
{
GApplication app(argc, argv);
DisplayPropertiesWidget instance;
auto* window = new GWindow();
window->set_title("Display Properties");
window->resize(400, 448);
window->set_resizable(false);
window->set_main_widget(instance.get_root_widget());
window->set_icon(load_png("/res/icons/16x16/app-display-properties.png"));
window->show();
return app.exec();
}