Skip to content

Commit 4f7ac75

Browse files
MacDuenico
authored andcommitted
DisplaySettings: Support disabling the desktop wallpaper
This adds a "None" wallpaper option to allow removing the desktop wallpaper. This also fixes a longstanding bug that when opening DisplaySettings without a wallpaper set the first wallpaper would automatically be selected, marking the settings as modified without the user having made any changes. (This was due to the model index being invalid so the first index was automatically selected.)
1 parent fcf0f69 commit 4f7ac75

File tree

4 files changed

+104
-37
lines changed

4 files changed

+104
-37
lines changed

Base/res/icons/32x32/no-wallpaper.png

265 Bytes
Loading

Userland/Applications/DisplaySettings/BackgroundSettingsWidget.cpp

Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,93 @@ BackgroundSettingsWidget::BackgroundSettingsWidget(bool& background_settings_cha
5050
{
5151
}
5252

53+
/// A thin wrapper over FileSystemModel for wallpapers in /res/wallpapers. The
54+
/// only change from a plain FileSystemModel is row zero reserved for "None"
55+
/// (and this assumes no nested directories).
56+
class WallpapersModel final : public GUI::Model
57+
, GUI::ModelClient {
58+
public:
59+
static NonnullRefPtr<WallpapersModel> create()
60+
{
61+
return adopt_ref(*new WallpapersModel(GUI::FileSystemModel::create("/res/wallpapers")));
62+
}
63+
64+
virtual ~WallpapersModel() override
65+
{
66+
m_wallpaper_folder->unregister_client(*this);
67+
}
68+
69+
virtual int row_count(GUI::ModelIndex const&) const override
70+
{
71+
// Index zero is reserved for "None".
72+
return m_wallpaper_folder->row_count() + 1;
73+
}
74+
75+
virtual int column_count(GUI::ModelIndex const&) const override
76+
{
77+
return 1;
78+
}
79+
80+
virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
81+
{
82+
static GUI::Icon no_wallpaper_icon = GUI::Icon::default_icon("no-wallpaper"sv);
83+
if (index.row() == 0) {
84+
if (role == GUI::ModelRole::Icon)
85+
return no_wallpaper_icon;
86+
if (role == GUI::ModelRole::Display)
87+
return "None";
88+
return {};
89+
}
90+
return m_wallpaper_folder->data(fs_index(index, role), role);
91+
}
92+
93+
AK::ByteString full_path(GUI::ModelIndex const& index)
94+
{
95+
if (index.row() == 0)
96+
return "";
97+
return m_wallpaper_folder->full_path(fs_index(index));
98+
}
99+
100+
virtual void model_did_update(unsigned flags) override { did_update(flags); }
101+
102+
GUI::ModelIndex index_for_path(ByteString path)
103+
{
104+
auto wallpaper_index = m_wallpaper_folder->index(path, GUI::FileSystemModel::Column::Name);
105+
if (wallpaper_index.is_valid())
106+
return create_index(wallpaper_index.row() + 1, 0);
107+
return create_index(0, 0); // Default to "None".
108+
}
109+
110+
private:
111+
GUI::ModelIndex fs_index(GUI::ModelIndex const& index, GUI::ModelRole role = GUI::ModelRole::Display) const
112+
{
113+
VERIFY(index.row() > 0);
114+
return m_wallpaper_folder->index(index.row() - 1,
115+
role == GUI::ModelRole::Display ? GUI::FileSystemModel::Column::Name : GUI::FileSystemModel::Column::Icon);
116+
}
117+
118+
WallpapersModel(NonnullRefPtr<GUI::FileSystemModel> wallpaper_folder)
119+
: m_wallpaper_folder(move(wallpaper_folder))
120+
{
121+
m_wallpaper_folder->register_client(*this);
122+
}
123+
124+
NonnullRefPtr<GUI::FileSystemModel> m_wallpaper_folder;
125+
};
126+
53127
ErrorOr<void> BackgroundSettingsWidget::create_frame()
54128
{
55129
TRY(load_from_gml(background_settings_gml));
56130

57131
m_monitor_widget = *find_descendant_of_type_named<DisplaySettings::MonitorWidget>("monitor_widget");
58132

59133
m_wallpaper_view = *find_descendant_of_type_named<GUI::IconView>("wallpaper_view");
60-
m_wallpaper_view->set_model(GUI::FileSystemModel::create("/res/wallpapers"));
61-
m_wallpaper_view->set_model_column(GUI::FileSystemModel::Column::Name);
134+
m_wallpaper_view->set_model(WallpapersModel::create());
62135
m_wallpaper_view->on_selection_change = [this] {
63136
String path;
64137
if (!m_wallpaper_view->selection().is_empty()) {
65138
auto index = m_wallpaper_view->selection().first();
66-
auto path_or_error = String::from_byte_string(static_cast<GUI::FileSystemModel*>(m_wallpaper_view->model())->full_path(index));
139+
auto path_or_error = String::from_byte_string(static_cast<WallpapersModel*>(m_wallpaper_view->model())->full_path(index));
67140
if (path_or_error.is_error()) {
68141
GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv);
69142
return;
@@ -143,11 +216,9 @@ ErrorOr<void> BackgroundSettingsWidget::load_current_settings()
143216
auto ws_config = TRY(Core::ConfigFile::open("/etc/WindowServer.ini"));
144217

145218
auto selected_wallpaper = TRY(String::from_byte_string(Config::read_string("WindowManager"sv, "Background"sv, "Wallpaper"sv, ""sv)));
146-
if (!selected_wallpaper.is_empty()) {
147-
auto index = static_cast<GUI::FileSystemModel*>(m_wallpaper_view->model())->index(selected_wallpaper.to_byte_string(), m_wallpaper_view->model_column());
148-
m_wallpaper_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set);
149-
m_monitor_widget->set_wallpaper(selected_wallpaper);
150-
}
219+
auto index = static_cast<WallpapersModel*>(m_wallpaper_view->model())->index_for_path(selected_wallpaper.to_byte_string());
220+
m_wallpaper_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set);
221+
m_monitor_widget->set_wallpaper(selected_wallpaper);
151222

152223
auto mode = TRY(String::from_byte_string(ws_config->read_entry("Background", "Mode", "Center")));
153224
if (!m_modes.contains_slow(mode)) {
@@ -175,18 +246,13 @@ ErrorOr<void> BackgroundSettingsWidget::load_current_settings()
175246

176247
void BackgroundSettingsWidget::apply_settings()
177248
{
178-
auto wallpaper_path_or_empty = m_monitor_widget->wallpaper();
179-
180-
if (!GUI::Desktop::the().set_wallpaper(m_monitor_widget->wallpaper_bitmap(), wallpaper_path_or_empty)) {
181-
if (!wallpaper_path_or_empty.has_value()) {
182-
GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv);
183-
} else {
184-
auto detailed_error_message = String::formatted("Unable to load file {} as wallpaper", wallpaper_path_or_empty.value());
185-
if (!detailed_error_message.is_error())
186-
GUI::MessageBox::show_error(window(), detailed_error_message.release_value());
187-
else
188-
GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv);
189-
}
249+
// We need to provide an empty path (not OptionalNone) to set_wallpaper to save a solid color wallpaper.
250+
auto wallpaper_path = m_monitor_widget->wallpaper().value_or(""sv);
251+
if (!GUI::Desktop::the().set_wallpaper(m_monitor_widget->wallpaper_bitmap(), wallpaper_path)) {
252+
if (!wallpaper_path.is_empty())
253+
GUI::MessageBox::show_error(window(), MUST(String::formatted("Unable to load file {} as wallpaper", wallpaper_path)));
254+
else
255+
GUI::MessageBox::show_error(window(), "Unable to set wallpaper"sv);
190256
}
191257

192258
GUI::Desktop::the().set_background_color(m_color_input->text());

Userland/Applications/DisplaySettings/MonitorWidget.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,10 @@ ErrorOr<NonnullRefPtr<MonitorWidget>> MonitorWidget::try_create()
2727
return monitor_widget;
2828
}
2929

30-
bool MonitorWidget::set_wallpaper(String path)
30+
void MonitorWidget::load_wallpaper(String path)
3131
{
32-
if (!is_different_to_current_wallpaper_path(path))
33-
return false;
34-
3532
(void)Threading::BackgroundAction<NonnullRefPtr<Gfx::Bitmap>>::construct(
3633
[path](auto&) -> ErrorOr<NonnullRefPtr<Gfx::Bitmap>> {
37-
if (path.is_empty())
38-
return Error::from_errno(ENOENT);
3934
return Gfx::Bitmap::load_from_file(path);
4035
},
4136

@@ -52,12 +47,21 @@ bool MonitorWidget::set_wallpaper(String path)
5247
[this, path](Error) -> void {
5348
m_wallpaper_bitmap = nullptr;
5449
});
50+
}
5551

56-
if (path.is_empty())
52+
bool MonitorWidget::set_wallpaper(String path)
53+
{
54+
if (!is_different_to_current_wallpaper_path(path))
55+
return false;
56+
if (path.is_empty()) {
57+
m_wallpaper_bitmap = nullptr;
5758
m_desktop_wallpaper_path = OptionalNone();
58-
else
59+
m_desktop_dirty = true;
60+
update();
61+
} else {
62+
load_wallpaper(path);
5963
m_desktop_wallpaper_path = path;
60-
64+
}
6165
return true;
6266
}
6367

Userland/Applications/DisplaySettings/MonitorWidget.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class MonitorWidget final : public GUI::Widget {
4141

4242
virtual void paint_event(GUI::PaintEvent& event) override;
4343

44+
void load_wallpaper(String path);
45+
4446
Gfx::IntRect m_monitor_rect;
4547
RefPtr<Gfx::Bitmap> m_monitor_bitmap;
4648
RefPtr<Gfx::Bitmap> m_desktop_bitmap;
@@ -55,14 +57,9 @@ class MonitorWidget final : public GUI::Widget {
5557

5658
bool is_different_to_current_wallpaper_path(String const& path)
5759
{
58-
if (!m_desktop_wallpaper_path.has_value()) {
59-
if (path.is_empty())
60-
return false;
61-
return true;
62-
}
63-
if (m_desktop_wallpaper_path.value() == path)
64-
return false;
65-
return true;
60+
if (!path.is_empty())
61+
return path != m_desktop_wallpaper_path;
62+
return m_desktop_wallpaper_path.has_value();
6663
}
6764
};
6865

0 commit comments

Comments
 (0)