/* * Copyright (c) 2019-2020, Jesse Buhagiar * Copyright (c) 2020-2021, Andreas Kling * Copyright (c) 2022, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include "BackgroundSettingsWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DisplaySettings { ErrorOr> BackgroundSettingsWidget::try_create(bool& background_settings_changed) { auto background_settings_widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) BackgroundSettingsWidget(background_settings_changed))); TRY(background_settings_widget->m_modes.try_append(TRY(String::from_utf8("Tile"sv)))); TRY(background_settings_widget->m_modes.try_append(TRY(String::from_utf8("Center"sv)))); TRY(background_settings_widget->m_modes.try_append(TRY(String::from_utf8("Stretch"sv)))); TRY(background_settings_widget->create_frame()); TRY(background_settings_widget->load_current_settings()); return background_settings_widget; } BackgroundSettingsWidget::BackgroundSettingsWidget(bool& background_settings_changed) : m_background_settings_changed { background_settings_changed } { } ErrorOr BackgroundSettingsWidget::create_frame() { TRY(load_from_gml(background_settings_gml)); m_monitor_widget = *find_descendant_of_type_named("monitor_widget"); m_wallpaper_view = *find_descendant_of_type_named("wallpaper_view"); m_wallpaper_view->set_model(GUI::FileSystemModel::create("/res/wallpapers")); m_wallpaper_view->set_model_column(GUI::FileSystemModel::Column::Name); m_wallpaper_view->on_selection_change = [this] { String path = String::from_utf8_short_string(""sv); if (!m_wallpaper_view->selection().is_empty()) { auto index = m_wallpaper_view->selection().first(); auto path_or_error = String::from_deprecated_string(static_cast(m_wallpaper_view->model())->full_path(index)); if (path_or_error.is_error()) { GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv); return; } path = path_or_error.release_value(); } m_monitor_widget->set_wallpaper(path); set_modified(true); }; m_context_menu = GUI::Menu::construct(); auto const file_manager_icon = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-file-manager.png"sv)); m_show_in_file_manager_action = GUI::Action::create("Show in File Manager", file_manager_icon, [this](GUI::Action const&) { LexicalPath path { m_monitor_widget->wallpaper().value().to_deprecated_string() }; Desktop::Launcher::open(URL::create_with_file_scheme(path.dirname(), path.basename())); }); m_context_menu->add_action(*m_show_in_file_manager_action); TRY(m_context_menu->try_add_separator()); m_copy_action = GUI::CommonActions::make_copy_action( [this](auto&) { auto wallpaper = m_monitor_widget->wallpaper(); if (wallpaper.has_value()) GUI::Clipboard::the().set_data(URL::create_with_file_scheme(wallpaper.value().to_deprecated_string()).to_deprecated_string().bytes(), "text/uri-list"); }, this); m_context_menu->add_action(*m_copy_action); m_wallpaper_view->on_context_menu_request = [&](const GUI::ModelIndex& index, const GUI::ContextMenuEvent& event) { if (index.is_valid()) { m_context_menu->popup(event.screen_position(), m_show_in_file_manager_action); } }; auto& button = *find_descendant_of_type_named("wallpaper_open_button"); button.on_click = [this](auto) { auto response = FileSystemAccessClient::Client::the().open_file(window(), "Select Wallpaper"sv, "/res/wallpapers"sv, Core::File::OpenMode::Read, { { GUI::FileTypeFilter::image_files(), GUI::FileTypeFilter::all_files() } }); if (response.is_error()) return; m_wallpaper_view->selection().clear(); m_monitor_widget->set_wallpaper(response.release_value().filename()); m_background_settings_changed = true; set_modified(true); }; m_mode_combo = *find_descendant_of_type_named("mode_combo"); m_mode_combo->set_only_allow_values_from_model(true); m_mode_combo->set_model(*GUI::ItemListModel::create(m_modes)); bool first_mode_change = true; m_mode_combo->on_change = [this, first_mode_change](auto&, const GUI::ModelIndex& index) mutable { m_monitor_widget->set_wallpaper_mode(m_modes.at(index.row())); m_background_settings_changed = !first_mode_change; first_mode_change = false; set_modified(true); }; m_color_input = *find_descendant_of_type_named("color_input"); m_color_input->set_color_has_alpha_channel(false); m_color_input->set_color_picker_title("Select Desktop Color"); bool first_color_change = true; m_color_input->on_change = [this, first_color_change]() mutable { m_monitor_widget->set_background_color(m_color_input->color()); m_background_settings_changed = !first_color_change; first_color_change = false; set_modified(true); }; return {}; } ErrorOr BackgroundSettingsWidget::load_current_settings() { auto ws_config = TRY(Core::ConfigFile::open("/etc/WindowServer.ini")); auto selected_wallpaper = TRY(String::from_deprecated_string(Config::read_string("WindowManager"sv, "Background"sv, "Wallpaper"sv, ""sv))); if (!selected_wallpaper.is_empty()) { auto index = static_cast(m_wallpaper_view->model())->index(selected_wallpaper.to_deprecated_string(), m_wallpaper_view->model_column()); m_wallpaper_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set); m_monitor_widget->set_wallpaper(selected_wallpaper); } auto mode = TRY(String::from_deprecated_string(ws_config->read_entry("Background", "Mode", "Center"))); if (!m_modes.contains_slow(mode)) { warnln("Invalid background mode '{}' in WindowServer config, falling back to 'Center'", mode); mode = TRY(String::from_utf8("Center"sv)); } m_monitor_widget->set_wallpaper_mode(mode); m_mode_combo->set_selected_index(m_modes.find_first_index(mode).value_or(0), GUI::AllowCallback::No); auto palette_desktop_color = palette().desktop_background(); auto background_color = ws_config->read_entry("Background", "Color", ""); if (!background_color.is_empty()) { auto opt_color = Color::from_string(background_color); if (opt_color.has_value()) palette_desktop_color = opt_color.value(); } m_color_input->set_color(palette_desktop_color, GUI::AllowCallback::No); m_monitor_widget->set_background_color(palette_desktop_color); m_background_settings_changed = false; return {}; } void BackgroundSettingsWidget::apply_settings() { auto wallpaper_path_or_empty = m_monitor_widget->wallpaper(); if (!GUI::Desktop::the().set_wallpaper(m_monitor_widget->wallpaper_bitmap(), wallpaper_path_or_empty)) { if (!wallpaper_path_or_empty.has_value()) { GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv); } else { auto detailed_error_message = String::formatted("Unable to load file {} as wallpaper", wallpaper_path_or_empty.value()); if (!detailed_error_message.is_error()) GUI::MessageBox::show_error(window(), detailed_error_message.release_value()); else GUI::MessageBox::show_error(window(), "Unable to load wallpaper"sv); } } GUI::Desktop::the().set_background_color(m_color_input->text()); GUI::Desktop::the().set_wallpaper_mode(m_monitor_widget->wallpaper_mode()); } }