mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +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:
parent
af14b8dc59
commit
ecbc0322c1
Notes:
sideshowbarker
2024-07-19 12:14:45 +09:00
Author: https://github.com/Quaker762 Commit: https://github.com/SerenityOS/serenity/commit/ecbc0322c11 Pull-request: https://github.com/SerenityOS/serenity/pull/525 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/bugaevc
15 changed files with 329 additions and 1 deletions
156
Applications/DisplayProperties/DisplayProperties.cpp
Normal file
156
Applications/DisplayProperties/DisplayProperties.cpp
Normal 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;
|
||||
}
|
||||
}
|
47
Applications/DisplayProperties/DisplayProperties.h
Normal file
47
Applications/DisplayProperties/DisplayProperties.h
Normal 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;
|
||||
};
|
54
Applications/DisplayProperties/ItemListModel.h
Normal file
54
Applications/DisplayProperties/ItemListModel.h
Normal 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;
|
||||
};
|
9
Applications/DisplayProperties/Makefile
Normal file
9
Applications/DisplayProperties/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
include ../../Makefile.common
|
||||
|
||||
OBJS = \
|
||||
DisplayProperties.o \
|
||||
main.o \
|
||||
|
||||
APP = DisplayProperties
|
||||
|
||||
include ../Makefile.common
|
22
Applications/DisplayProperties/main.cpp
Normal file
22
Applications/DisplayProperties/main.cpp
Normal 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();
|
||||
}
|
BIN
Base/res/icons/16x16/app-display-properties.png
Normal file
BIN
Base/res/icons/16x16/app-display-properties.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Base/res/icons/32x32/app-display-properties.png
Normal file
BIN
Base/res/icons/32x32/app-display-properties.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -86,6 +86,7 @@ cp ../Applications/SystemDialog/SystemDialog mnt/bin/SystemDialog
|
|||
cp ../Applications/ChanViewer/ChanViewer mnt/bin/ChanViewer
|
||||
cp ../Applications/Calculator/Calculator mnt/bin/Calculator
|
||||
cp ../Applications/SoundPlayer/SoundPlayer mnt/bin/SoundPlayer
|
||||
cp ../Applications/DisplayProperties/DisplayProperties mnt/bin/DisplayProperties
|
||||
cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld
|
||||
cp ../Demos/HelloWorld2/HelloWorld2 mnt/bin/HelloWorld2
|
||||
cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch
|
||||
|
|
|
@ -42,6 +42,7 @@ build_targets="$build_targets ../Libraries/LibVT"
|
|||
build_targets="$build_targets ../Applications/About"
|
||||
build_targets="$build_targets ../Applications/Calculator"
|
||||
build_targets="$build_targets ../Applications/ChanViewer"
|
||||
build_targets="$build_targets ../Applications/DisplayProperties"
|
||||
build_targets="$build_targets ../Applications/Downloader"
|
||||
build_targets="$build_targets ../Applications/FileManager"
|
||||
build_targets="$build_targets ../Applications/FontEditor"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <LibDraw/StylePainter.h>
|
||||
#include <LibGUI/GBoxLayout.h>
|
||||
#include <LibGUI/GPainter.h>
|
||||
#include <LibGUI/GTabWidget.h>
|
||||
#include <LibDraw/StylePainter.h>
|
||||
|
||||
GTabWidget::GTabWidget(GWidget* parent)
|
||||
: GWidget(parent)
|
||||
|
|
|
@ -109,6 +109,7 @@ struct WSAPI_ServerMessage {
|
|||
DidSetWindowBackingStore,
|
||||
DidSetWallpaper,
|
||||
DidGetWallpaper,
|
||||
DidSetResolution,
|
||||
DidSetWindowHasAlphaChannel,
|
||||
ScreenRectChanged,
|
||||
|
||||
|
@ -224,6 +225,7 @@ struct WSAPI_ClientMessage {
|
|||
Greeting,
|
||||
SetWallpaper,
|
||||
GetWallpaper,
|
||||
SetResolution,
|
||||
SetWindowOverrideCursor,
|
||||
WM_SetActiveWindow,
|
||||
WM_SetWindowMinimized,
|
||||
|
@ -260,6 +262,9 @@ struct WSAPI_ClientMessage {
|
|||
bool minimized;
|
||||
WSAPI_Point position;
|
||||
} wm;
|
||||
struct {
|
||||
WSAPI_Size resolution;
|
||||
} wm_conf;
|
||||
struct {
|
||||
int menubar_id;
|
||||
int menu_id;
|
||||
|
|
|
@ -289,6 +289,9 @@ bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, cons
|
|||
case WSAPI_ClientMessage::Type::GetWallpaper:
|
||||
CEventLoop::current().post_event(*this, make<WSAPIGetWallpaperRequest>(client_id()));
|
||||
break;
|
||||
case WSAPI_ClientMessage::Type::SetResolution:
|
||||
CEventLoop::current().post_event(*this, make<WSAPISetResolutionRequest>(client_id(), message.wm_conf.resolution.width, message.wm_conf.resolution.height));
|
||||
break;
|
||||
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
|
||||
CEventLoop::current().post_event(*this, make<WSAPISetWindowOverrideCursorRequest>(client_id(), message.window_id, (WSStandardCursor)message.cursor.cursor));
|
||||
break;
|
||||
|
@ -557,6 +560,15 @@ void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&)
|
|||
post_message(response);
|
||||
}
|
||||
|
||||
void WSClientConnection::handle_request(const WSAPISetResolutionRequest& request)
|
||||
{
|
||||
WSWindowManager::the().set_resolution(request.resolution().width(), request.resolution().height());
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidSetResolution;
|
||||
response.value = true;
|
||||
post_message(response);
|
||||
}
|
||||
|
||||
void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& request)
|
||||
{
|
||||
int window_id = request.window_id();
|
||||
|
@ -984,6 +996,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request)
|
|||
return handle_request(static_cast<const WSAPISetWallpaperRequest&>(request));
|
||||
case WSEvent::APIGetWallpaperRequest:
|
||||
return handle_request(static_cast<const WSAPIGetWallpaperRequest&>(request));
|
||||
case WSEvent::APISetResolutionRequest:
|
||||
return handle_request(static_cast<const WSAPISetResolutionRequest&>(request));
|
||||
case WSEvent::APISetWindowOverrideCursorRequest:
|
||||
return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
|
||||
case WSEvent::WMAPISetActiveWindowRequest:
|
||||
|
|
|
@ -73,6 +73,7 @@ private:
|
|||
void handle_request(const WSAPISetWindowOpacityRequest&);
|
||||
void handle_request(const WSAPISetWallpaperRequest&);
|
||||
void handle_request(const WSAPIGetWallpaperRequest&);
|
||||
void handle_request(const WSAPISetResolutionRequest&);
|
||||
void handle_request(const WSAPISetWindowOverrideCursorRequest&);
|
||||
void handle_request(const WSWMAPISetActiveWindowRequest&);
|
||||
void handle_request(const WSWMAPISetWindowMinimizedRequest&);
|
||||
|
|
|
@ -300,6 +300,8 @@ void WSCompositor::set_resolution(int desired_width, int desired_height)
|
|||
return;
|
||||
m_wallpaper_path = {};
|
||||
m_wallpaper = nullptr;
|
||||
// Make sure it's impossible to set an invalid resolution
|
||||
ASSERT(desired_width >= 640 && desired_height >= 480);
|
||||
WSScreen::the().set_resolution(desired_width, desired_height);
|
||||
init_bitmaps();
|
||||
compose();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibDraw/Point.h>
|
||||
#include <LibDraw/Rect.h>
|
||||
#include <WindowServer/WSCursor.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
#include <WindowServer/WSWindowType.h>
|
||||
|
||||
class WSEvent : public CEvent {
|
||||
|
@ -60,6 +61,7 @@ public:
|
|||
APIGetClipboardContentsRequest,
|
||||
APISetWallpaperRequest,
|
||||
APIGetWallpaperRequest,
|
||||
APISetResolutionRequest,
|
||||
APISetWindowOverrideCursorRequest,
|
||||
APISetWindowHasAlphaChannelRequest,
|
||||
APIMoveWindowToFrontRequest,
|
||||
|
@ -441,6 +443,20 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class WSAPISetResolutionRequest final : public WSAPIClientRequest {
|
||||
public:
|
||||
explicit WSAPISetResolutionRequest(int client_id, int width, int height)
|
||||
: WSAPIClientRequest(WSEvent::APISetResolutionRequest, client_id),
|
||||
m_resolution(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
Size resolution() const { return m_resolution; }
|
||||
|
||||
private:
|
||||
Size m_resolution;
|
||||
};
|
||||
|
||||
class WSAPISetWindowTitleRequest final : public WSAPIClientRequest {
|
||||
public:
|
||||
explicit WSAPISetWindowTitleRequest(int client_id, int window_id, const String& title)
|
||||
|
|
Loading…
Reference in a new issue