mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-03-31 09:17:04 +09:00
710 lines
37 KiB
C++
710 lines
37 KiB
C++
#include "../../include/gui/GlobalSettingsPage.hpp"
|
|
|
|
#include "../../include/Overlay.hpp"
|
|
#include "../../include/GlobalHotkeys.hpp"
|
|
#include "../../include/Theme.hpp"
|
|
#include "../../include/Process.hpp"
|
|
#include "../../include/gui/GsrPage.hpp"
|
|
#include "../../include/gui/PageStack.hpp"
|
|
#include "../../include/gui/ScrollablePage.hpp"
|
|
#include "../../include/gui/Subsection.hpp"
|
|
#include "../../include/gui/List.hpp"
|
|
#include "../../include/gui/Label.hpp"
|
|
#include "../../include/gui/Image.hpp"
|
|
#include "../../include/gui/RadioButton.hpp"
|
|
#include "../../include/gui/LineSeparator.hpp"
|
|
#include "../../include/gui/CustomRendererWidget.hpp"
|
|
|
|
#include <assert.h>
|
|
#include <X11/Xlib.h>
|
|
extern "C" {
|
|
#include <mgl/mgl.h>
|
|
}
|
|
#include <mglpp/window/Window.hpp>
|
|
#include <mglpp/graphics/Rectangle.hpp>
|
|
#include <mglpp/graphics/Text.hpp>
|
|
|
|
#ifndef GSR_UI_VERSION
|
|
#define GSR_UI_VERSION "Unknown"
|
|
#endif
|
|
|
|
#ifndef GSR_FLATPAK_VERSION
|
|
#define GSR_FLATPAK_VERSION "Unknown"
|
|
#endif
|
|
|
|
namespace gsr {
|
|
static const char* gpu_vendor_to_color_name(GpuVendor vendor) {
|
|
switch(vendor) {
|
|
case GpuVendor::UNKNOWN: return "amd";
|
|
case GpuVendor::AMD: return "amd";
|
|
case GpuVendor::INTEL: return "intel";
|
|
case GpuVendor::NVIDIA: return "nvidia";
|
|
case GpuVendor::BROADCOM: return "broadcom";
|
|
}
|
|
return "amd";
|
|
}
|
|
|
|
static const char* gpu_vendor_to_string(GpuVendor vendor) {
|
|
switch(vendor) {
|
|
case GpuVendor::UNKNOWN: return "Unknown";
|
|
case GpuVendor::AMD: return "AMD";
|
|
case GpuVendor::INTEL: return "Intel";
|
|
case GpuVendor::NVIDIA: return "NVIDIA";
|
|
case GpuVendor::BROADCOM: return "Broadcom";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
static uint32_t mgl_modifier_to_hotkey_modifier(mgl::Keyboard::Key modifier_key) {
|
|
switch(modifier_key) {
|
|
case mgl::Keyboard::LControl: return HOTKEY_MOD_LCTRL;
|
|
case mgl::Keyboard::LShift: return HOTKEY_MOD_LSHIFT;
|
|
case mgl::Keyboard::LAlt: return HOTKEY_MOD_LALT;
|
|
case mgl::Keyboard::LSystem: return HOTKEY_MOD_LSUPER;
|
|
case mgl::Keyboard::RControl: return HOTKEY_MOD_RCTRL;
|
|
case mgl::Keyboard::RShift: return HOTKEY_MOD_RSHIFT;
|
|
case mgl::Keyboard::RAlt: return HOTKEY_MOD_RALT;
|
|
case mgl::Keyboard::RSystem: return HOTKEY_MOD_RSUPER;
|
|
default: return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static bool key_is_alpha_numerical(mgl::Keyboard::Key key) {
|
|
return key >= mgl::Keyboard::A && key <= mgl::Keyboard::Num9;
|
|
}
|
|
|
|
GlobalSettingsPage::GlobalSettingsPage(Overlay *overlay, const GsrInfo *gsr_info, Config &config, PageStack *page_stack) :
|
|
StaticPage(mgl::vec2f(get_theme().window_width, get_theme().window_height).floor()),
|
|
overlay(overlay),
|
|
config(config),
|
|
gsr_info(gsr_info),
|
|
page_stack(page_stack)
|
|
{
|
|
auto content_page = std::make_unique<GsrPage>("Global", "Settings");
|
|
content_page->add_button("Back", "back", get_color_theme().page_bg_color);
|
|
content_page->on_click = [page_stack](const std::string &id) {
|
|
if(id == "back")
|
|
page_stack->pop();
|
|
};
|
|
content_page_ptr = content_page.get();
|
|
add_widget(std::move(content_page));
|
|
|
|
add_widgets();
|
|
load();
|
|
|
|
auto hotkey_overlay = std::make_unique<CustomRendererWidget>(get_size());
|
|
hotkey_overlay->draw_handler = [this](mgl::Window &window, mgl::vec2f, mgl::vec2f) {
|
|
Button *configure_hotkey_button = configure_hotkey_get_button_by_active_type();
|
|
if(!configure_hotkey_button)
|
|
return;
|
|
|
|
mgl::Text title_text("Press a key combination to use for the hotkey \"" + hotkey_configure_action_name + "\":", get_theme().title_font);
|
|
mgl::Text hotkey_text(configure_hotkey_button->get_text(), get_theme().top_bar_font);
|
|
mgl::Text description_text("Alpha-numerical keys can't be used alone in hotkeys, they have to be used one or more of these keys: Alt, Ctrl, Shift and Super.\nPress Esc to cancel or Backspace to remove the hotkey.", get_theme().body_font);
|
|
const float text_max_width = std::max(title_text.get_bounds().size.x, std::max(hotkey_text.get_bounds().size.x, description_text.get_bounds().size.x));
|
|
|
|
const float padding_horizontal = int(get_theme().window_height * 0.01f);
|
|
const float padding_vertical = int(get_theme().window_height * 0.01f);
|
|
|
|
const mgl::vec2f bg_size = mgl::vec2f(text_max_width + padding_horizontal*2.0f, get_theme().window_height * 0.13f).floor();
|
|
mgl::Rectangle bg_rect(mgl::vec2f(get_theme().window_width*0.5f - bg_size.x*0.5f, get_theme().window_height*0.5f - bg_size.y*0.5f).floor(), bg_size);
|
|
bg_rect.set_color(get_color_theme().page_bg_color);
|
|
window.draw(bg_rect);
|
|
|
|
const mgl::vec2f tint_size = mgl::vec2f(bg_size.x, 0.004f * get_theme().window_height).floor();
|
|
mgl::Rectangle tint_rect(bg_rect.get_position() - mgl::vec2f(0.0f, tint_size.y), tint_size);
|
|
tint_rect.set_color(get_color_theme().tint_color);
|
|
window.draw(tint_rect);
|
|
|
|
title_text.set_position(mgl::vec2f(bg_rect.get_position() + mgl::vec2f(bg_rect.get_size().x*0.5f - title_text.get_bounds().size.x*0.5f, padding_vertical)).floor());
|
|
description_text.set_position(mgl::vec2f(bg_rect.get_position() + mgl::vec2f(bg_rect.get_size().x*0.5f - description_text.get_bounds().size.x*0.5f, bg_rect.get_size().y - description_text.get_bounds().size.y - padding_vertical)).floor());
|
|
|
|
window.draw(title_text);
|
|
|
|
const float title_text_bottom = title_text.get_position().y + title_text.get_bounds().size.y;
|
|
hotkey_text.set_position(
|
|
mgl::vec2f(
|
|
bg_rect.get_position().x + bg_rect.get_size().x*0.5f - hotkey_text.get_bounds().size.x*0.5f,
|
|
title_text_bottom + (description_text.get_position().y - title_text_bottom) * 0.5f - hotkey_text.get_bounds().size.y*0.5f
|
|
).floor());
|
|
window.draw(hotkey_text);
|
|
|
|
const float caret_padding_x = int(0.001f * get_theme().window_height);
|
|
const mgl::vec2f caret_size = mgl::vec2f(std::max(2.0f, 0.002f * get_theme().window_height), hotkey_text.get_bounds().size.y).floor();
|
|
mgl::Rectangle caret_rect(hotkey_text.get_position() + mgl::vec2f(hotkey_text.get_bounds().size.x + caret_padding_x, hotkey_text.get_bounds().size.y*0.5f - caret_size.y*0.5f).floor(), caret_size);
|
|
window.draw(caret_rect);
|
|
|
|
window.draw(description_text);
|
|
};
|
|
hotkey_overlay->set_visible(false);
|
|
hotkey_overlay_ptr = hotkey_overlay.get();
|
|
add_widget(std::move(hotkey_overlay));
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_appearance_subsection(ScrollablePage *parent_page) {
|
|
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Accent color", get_color_theme().text_color));
|
|
auto tint_color_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
|
|
tint_color_radio_button_ptr = tint_color_radio_button.get();
|
|
tint_color_radio_button->add_item("Red", "amd");
|
|
tint_color_radio_button->add_item("Green", "nvidia");
|
|
tint_color_radio_button->add_item("blue", "intel");
|
|
tint_color_radio_button->on_selection_changed = [](const std::string&, const std::string &id) {
|
|
if(id == "amd")
|
|
get_color_theme().tint_color = mgl::Color(221, 0, 49);
|
|
else if(id == "nvidia")
|
|
get_color_theme().tint_color = mgl::Color(118, 185, 0);
|
|
else if(id == "intel")
|
|
get_color_theme().tint_color = mgl::Color(8, 109, 183);
|
|
return true;
|
|
};
|
|
list->add_widget(std::move(tint_color_radio_button));
|
|
return std::make_unique<Subsection>("Appearance", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_startup_subsection(ScrollablePage *parent_page) {
|
|
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Start program on system startup?", get_color_theme().text_color));
|
|
auto startup_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
|
|
startup_radio_button_ptr = startup_radio_button.get();
|
|
startup_radio_button->add_item("Yes", "start_on_system_startup");
|
|
startup_radio_button->add_item("No", "dont_start_on_system_startup");
|
|
startup_radio_button->on_selection_changed = [&](const std::string&, const std::string &id) {
|
|
bool enable = false;
|
|
if(id == "dont_start_on_system_startup")
|
|
enable = false;
|
|
else if(id == "start_on_system_startup")
|
|
enable = true;
|
|
else
|
|
return false;
|
|
|
|
const char *args[] = { "systemctl", enable ? "enable" : "disable", "--user", "gpu-screen-recorder-ui", nullptr };
|
|
std::string stdout_str;
|
|
const int exit_status = exec_program_on_host_get_stdout(args, stdout_str);
|
|
if(on_startup_changed)
|
|
on_startup_changed(enable, exit_status);
|
|
return exit_status == 0;
|
|
};
|
|
list->add_widget(std::move(startup_radio_button));
|
|
return std::make_unique<Subsection>("Startup", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
}
|
|
|
|
std::unique_ptr<RadioButton> GlobalSettingsPage::create_enable_keyboard_hotkeys_button() {
|
|
auto enable_hotkeys_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
|
|
enable_keyboard_hotkeys_radio_button_ptr = enable_hotkeys_radio_button.get();
|
|
enable_hotkeys_radio_button->add_item("Yes", "enable_hotkeys");
|
|
enable_hotkeys_radio_button->add_item("No", "disable_hotkeys");
|
|
enable_hotkeys_radio_button->add_item("Only grab virtual devices (supports input remapping software)", "enable_hotkeys_virtual_devices");
|
|
enable_hotkeys_radio_button->on_selection_changed = [&](const std::string&, const std::string &id) {
|
|
if(on_keyboard_hotkey_changed)
|
|
on_keyboard_hotkey_changed(id.c_str());
|
|
return true;
|
|
};
|
|
return enable_hotkeys_radio_button;
|
|
}
|
|
|
|
std::unique_ptr<RadioButton> GlobalSettingsPage::create_enable_joystick_hotkeys_button() {
|
|
auto enable_hotkeys_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
|
|
enable_joystick_hotkeys_radio_button_ptr = enable_hotkeys_radio_button.get();
|
|
enable_hotkeys_radio_button->add_item("Yes", "enable_hotkeys");
|
|
enable_hotkeys_radio_button->add_item("No", "disable_hotkeys");
|
|
enable_hotkeys_radio_button->on_selection_changed = [&](const std::string&, const std::string &id) {
|
|
if(on_joystick_hotkey_changed)
|
|
on_joystick_hotkey_changed(id.c_str());
|
|
return true;
|
|
};
|
|
return enable_hotkeys_radio_button;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_show_hide_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Show/hide UI:", get_color_theme().text_color));
|
|
auto show_hide_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
show_hide_button_ptr = show_hide_button.get();
|
|
list->add_widget(std::move(show_hide_button));
|
|
|
|
show_hide_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::SHOW_HIDE);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_replay_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Turn replay on/off:", get_color_theme().text_color));
|
|
auto turn_replay_on_off_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
turn_replay_on_off_button_ptr = turn_replay_on_off_button.get();
|
|
list->add_widget(std::move(turn_replay_on_off_button));
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Save replay:", get_color_theme().text_color));
|
|
auto save_replay_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
save_replay_button_ptr = save_replay_button.get();
|
|
list->add_widget(std::move(save_replay_button));
|
|
|
|
turn_replay_on_off_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::REPLAY_START_STOP);
|
|
};
|
|
|
|
save_replay_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::REPLAY_SAVE);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_record_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Start/stop recording:", get_color_theme().text_color));
|
|
auto start_stop_recording_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
start_stop_recording_button_ptr = start_stop_recording_button.get();
|
|
list->add_widget(std::move(start_stop_recording_button));
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Pause/unpause recording:", get_color_theme().text_color));
|
|
auto pause_unpause_recording_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
pause_unpause_recording_button_ptr = pause_unpause_recording_button.get();
|
|
list->add_widget(std::move(pause_unpause_recording_button));
|
|
|
|
start_stop_recording_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::RECORD_START_STOP);
|
|
};
|
|
|
|
pause_unpause_recording_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_stream_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Start/stop streaming:", get_color_theme().text_color));
|
|
auto start_stop_streaming_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
start_stop_streaming_button_ptr = start_stop_streaming_button.get();
|
|
list->add_widget(std::move(start_stop_streaming_button));
|
|
|
|
start_stop_streaming_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::STREAM_START_STOP);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_screenshot_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Take a screenshot:", get_color_theme().text_color));
|
|
auto take_screenshot_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
take_screenshot_button_ptr = take_screenshot_button.get();
|
|
list->add_widget(std::move(take_screenshot_button));
|
|
|
|
take_screenshot_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::TAKE_SCREENSHOT);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_screenshot_region_hotkey_options() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Take a screenshot of a region:", get_color_theme().text_color));
|
|
auto take_screenshot_region_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
take_screenshot_region_button_ptr = take_screenshot_region_button.get();
|
|
list->add_widget(std::move(take_screenshot_region_button));
|
|
|
|
take_screenshot_region_button_ptr->on_click = [this] {
|
|
configure_hotkey_start(ConfigureHotkeyType::TAKE_SCREENSHOT_REGION);
|
|
};
|
|
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<List> GlobalSettingsPage::create_hotkey_control_buttons() {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
|
|
auto clear_hotkeys_button = std::make_unique<Button>(&get_theme().body_font, "Clear hotkeys", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
clear_hotkeys_button->on_click = [this] {
|
|
config.streaming_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.record_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.record_config.pause_unpause_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.replay_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.replay_config.save_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
config.main_config.show_hide_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
load_hotkeys();
|
|
overlay->rebind_all_keyboard_hotkeys();
|
|
};
|
|
list->add_widget(std::move(clear_hotkeys_button));
|
|
|
|
auto reset_hotkeys_button = std::make_unique<Button>(&get_theme().body_font, "Reset hotkeys to default", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
reset_hotkeys_button->on_click = [this] {
|
|
config.set_hotkeys_to_default();
|
|
load_hotkeys();
|
|
overlay->rebind_all_keyboard_hotkeys();
|
|
};
|
|
list->add_widget(std::move(reset_hotkeys_button));
|
|
|
|
return list;
|
|
}
|
|
|
|
static std::unique_ptr<List> create_joystick_hotkey_text(mgl::Texture *image1, mgl::Texture *image2, float max_height, const char *suffix) {
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press", get_color_theme().text_color));
|
|
list->add_widget(std::make_unique<Image>(image1, mgl::vec2f{max_height, 1000.0f}, Image::ScaleBehavior::SCALE));
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "and", get_color_theme().text_color));
|
|
list->add_widget(std::make_unique<Image>(image2, mgl::vec2f{max_height, 1000.0f}, Image::ScaleBehavior::SCALE));
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, suffix, get_color_theme().text_color));
|
|
return list;
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_keyboard_hotkey_subsection(ScrollablePage *parent_page) {
|
|
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
List *list_ptr = list.get();
|
|
auto subsection = std::make_unique<Subsection>("Keyboard hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
|
|
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable keyboard hotkeys?", get_color_theme().text_color));
|
|
list_ptr->add_widget(create_enable_keyboard_hotkeys_button());
|
|
list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x));
|
|
list_ptr->add_widget(create_show_hide_hotkey_options());
|
|
list_ptr->add_widget(create_replay_hotkey_options());
|
|
list_ptr->add_widget(create_record_hotkey_options());
|
|
list_ptr->add_widget(create_stream_hotkey_options());
|
|
list_ptr->add_widget(create_screenshot_hotkey_options());
|
|
list_ptr->add_widget(create_screenshot_region_hotkey_options());
|
|
list_ptr->add_widget(create_hotkey_control_buttons());
|
|
return subsection;
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_controller_hotkey_subsection(ScrollablePage *parent_page) {
|
|
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
List *list_ptr = list.get();
|
|
auto subsection = std::make_unique<Subsection>("Controller hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
|
|
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable controller hotkeys?", get_color_theme().text_color));
|
|
list_ptr->add_widget(create_enable_joystick_hotkeys_button());
|
|
list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x));
|
|
list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_options_texture, get_theme().body_font.get_character_size(), "to show/hide the UI"));
|
|
list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_up_texture, get_theme().body_font.get_character_size(), "to take a screenshot"));
|
|
list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_down_texture, get_theme().body_font.get_character_size(), "to save a replay"));
|
|
list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_left_texture, get_theme().body_font.get_character_size(), "to start/stop recording"));
|
|
list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_right_texture, get_theme().body_font.get_character_size(), "to turn replay on/off"));
|
|
return subsection;
|
|
}
|
|
|
|
std::unique_ptr<Button> GlobalSettingsPage::create_exit_program_button() {
|
|
auto exit_program_button = std::make_unique<Button>(&get_theme().body_font, "Exit program", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
exit_program_button->on_click = [&]() {
|
|
if(on_click_exit_program_button)
|
|
on_click_exit_program_button("exit");
|
|
};
|
|
return exit_program_button;
|
|
}
|
|
|
|
std::unique_ptr<Button> GlobalSettingsPage::create_go_back_to_old_ui_button() {
|
|
auto exit_program_button = std::make_unique<Button>(&get_theme().body_font, "Go back to the old UI", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
|
|
exit_program_button->on_click = [&]() {
|
|
if(on_click_exit_program_button)
|
|
on_click_exit_program_button("back-to-old-ui");
|
|
};
|
|
return exit_program_button;
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_application_options_subsection(ScrollablePage *parent_page) {
|
|
const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
|
|
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL);
|
|
list->add_widget(create_exit_program_button());
|
|
if(inside_flatpak)
|
|
list->add_widget(create_go_back_to_old_ui_button());
|
|
return std::make_unique<Subsection>("Application options", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
}
|
|
|
|
std::unique_ptr<Subsection> GlobalSettingsPage::create_application_info_subsection(ScrollablePage *parent_page) {
|
|
const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
|
|
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
|
|
char str[128];
|
|
const std::string gsr_version = gsr_info->system_info.gsr_version.to_string();
|
|
snprintf(str, sizeof(str), "GSR version: %s", gsr_version.c_str());
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, str, get_color_theme().text_color));
|
|
|
|
snprintf(str, sizeof(str), "GSR-UI version: %s", GSR_UI_VERSION);
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, str, get_color_theme().text_color));
|
|
|
|
if(inside_flatpak) {
|
|
snprintf(str, sizeof(str), "Flatpak version: %s", GSR_FLATPAK_VERSION);
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, str, get_color_theme().text_color));
|
|
}
|
|
|
|
snprintf(str, sizeof(str), "GPU vendor: %s", gpu_vendor_to_string(gsr_info->gpu_info.vendor));
|
|
list->add_widget(std::make_unique<Label>(&get_theme().body_font, str, get_color_theme().text_color));
|
|
|
|
return std::make_unique<Subsection>("Application info", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
|
}
|
|
|
|
void GlobalSettingsPage::add_widgets() {
|
|
auto scrollable_page = std::make_unique<ScrollablePage>(content_page_ptr->get_inner_size());
|
|
|
|
auto settings_list = std::make_unique<List>(List::Orientation::VERTICAL);
|
|
settings_list->set_spacing(0.018f);
|
|
settings_list->add_widget(create_appearance_subsection(scrollable_page.get()));
|
|
settings_list->add_widget(create_startup_subsection(scrollable_page.get()));
|
|
settings_list->add_widget(create_keyboard_hotkey_subsection(scrollable_page.get()));
|
|
settings_list->add_widget(create_controller_hotkey_subsection(scrollable_page.get()));
|
|
settings_list->add_widget(create_application_options_subsection(scrollable_page.get()));
|
|
settings_list->add_widget(create_application_info_subsection(scrollable_page.get()));
|
|
scrollable_page->add_widget(std::move(settings_list));
|
|
|
|
content_page_ptr->add_widget(std::move(scrollable_page));
|
|
}
|
|
|
|
void GlobalSettingsPage::on_navigate_away_from_page() {
|
|
save();
|
|
if(on_page_closed)
|
|
on_page_closed();
|
|
}
|
|
|
|
void GlobalSettingsPage::load() {
|
|
if(config.main_config.tint_color.empty())
|
|
tint_color_radio_button_ptr->set_selected_item(gpu_vendor_to_color_name(gsr_info->gpu_info.vendor));
|
|
else
|
|
tint_color_radio_button_ptr->set_selected_item(config.main_config.tint_color);
|
|
|
|
const char *args[] = { "systemctl", "is-enabled", "--quiet", "--user", "gpu-screen-recorder-ui", nullptr };
|
|
std::string stdout_str;
|
|
const int exit_status = exec_program_on_host_get_stdout(args, stdout_str);
|
|
startup_radio_button_ptr->set_selected_item(exit_status == 0 ? "start_on_system_startup" : "dont_start_on_system_startup", false, false);
|
|
|
|
enable_keyboard_hotkeys_radio_button_ptr->set_selected_item(config.main_config.hotkeys_enable_option, false, false);
|
|
enable_joystick_hotkeys_radio_button_ptr->set_selected_item(config.main_config.joystick_hotkeys_enable_option, false, false);
|
|
|
|
load_hotkeys();
|
|
}
|
|
|
|
void GlobalSettingsPage::load_hotkeys() {
|
|
turn_replay_on_off_button_ptr->set_text(config.replay_config.start_stop_hotkey.to_string());
|
|
save_replay_button_ptr->set_text(config.replay_config.save_hotkey.to_string());
|
|
|
|
start_stop_recording_button_ptr->set_text(config.record_config.start_stop_hotkey.to_string());
|
|
pause_unpause_recording_button_ptr->set_text(config.record_config.pause_unpause_hotkey.to_string());
|
|
|
|
start_stop_streaming_button_ptr->set_text(config.streaming_config.start_stop_hotkey.to_string());
|
|
|
|
take_screenshot_button_ptr->set_text(config.screenshot_config.take_screenshot_hotkey.to_string());
|
|
take_screenshot_region_button_ptr->set_text(config.screenshot_config.take_screenshot_region_hotkey.to_string());
|
|
|
|
show_hide_button_ptr->set_text(config.main_config.show_hide_hotkey.to_string());
|
|
}
|
|
|
|
void GlobalSettingsPage::save() {
|
|
configure_hotkey_cancel();
|
|
config.main_config.tint_color = tint_color_radio_button_ptr->get_selected_id();
|
|
config.main_config.hotkeys_enable_option = enable_keyboard_hotkeys_radio_button_ptr->get_selected_id();
|
|
config.main_config.joystick_hotkeys_enable_option = enable_joystick_hotkeys_radio_button_ptr->get_selected_id();
|
|
save_config(config);
|
|
}
|
|
|
|
bool GlobalSettingsPage::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) {
|
|
if(!StaticPage::on_event(event, window, offset))
|
|
return false;
|
|
|
|
if(configure_hotkey_type == ConfigureHotkeyType::NONE)
|
|
return true;
|
|
|
|
Button *configure_hotkey_button = configure_hotkey_get_button_by_active_type();
|
|
if(!configure_hotkey_button)
|
|
return true;
|
|
|
|
if(event.type == mgl::Event::KeyPressed) {
|
|
if(event.key.code == mgl::Keyboard::Escape)
|
|
return false;
|
|
|
|
if(event.key.code == mgl::Keyboard::Backspace) {
|
|
configure_config_hotkey = {mgl::Keyboard::Unknown, 0};
|
|
configure_hotkey_button->set_text("");
|
|
configure_hotkey_stop_and_save();
|
|
return false;
|
|
}
|
|
|
|
if(mgl::Keyboard::key_is_modifier(event.key.code)) {
|
|
configure_config_hotkey.modifiers |= mgl_modifier_to_hotkey_modifier(event.key.code);
|
|
configure_hotkey_button->set_text(configure_config_hotkey.to_string());
|
|
} else if(event.key.code != mgl::Keyboard::Unknown && (configure_config_hotkey.modifiers != 0 || !key_is_alpha_numerical(event.key.code))) {
|
|
configure_config_hotkey.key = event.key.code;
|
|
configure_hotkey_button->set_text(configure_config_hotkey.to_string());
|
|
configure_hotkey_stop_and_save();
|
|
}
|
|
|
|
return false;
|
|
} else if(event.type == mgl::Event::KeyReleased) {
|
|
if(event.key.code == mgl::Keyboard::Escape) {
|
|
configure_hotkey_cancel();
|
|
return false;
|
|
}
|
|
|
|
if(mgl::Keyboard::key_is_modifier(event.key.code)) {
|
|
configure_config_hotkey.modifiers &= ~mgl_modifier_to_hotkey_modifier(event.key.code);
|
|
configure_hotkey_button->set_text(configure_config_hotkey.to_string());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Button* GlobalSettingsPage::configure_hotkey_get_button_by_active_type() {
|
|
switch(configure_hotkey_type) {
|
|
case ConfigureHotkeyType::NONE:
|
|
return nullptr;
|
|
case ConfigureHotkeyType::REPLAY_START_STOP:
|
|
return turn_replay_on_off_button_ptr;
|
|
case ConfigureHotkeyType::REPLAY_SAVE:
|
|
return save_replay_button_ptr;
|
|
case ConfigureHotkeyType::RECORD_START_STOP:
|
|
return start_stop_recording_button_ptr;
|
|
case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE:
|
|
return pause_unpause_recording_button_ptr;
|
|
case ConfigureHotkeyType::STREAM_START_STOP:
|
|
return start_stop_streaming_button_ptr;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT:
|
|
return take_screenshot_button_ptr;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT_REGION:
|
|
return take_screenshot_region_button_ptr;
|
|
case ConfigureHotkeyType::SHOW_HIDE:
|
|
return show_hide_button_ptr;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
ConfigHotkey* GlobalSettingsPage::configure_hotkey_get_config_by_active_type() {
|
|
switch(configure_hotkey_type) {
|
|
case ConfigureHotkeyType::NONE:
|
|
return nullptr;
|
|
case ConfigureHotkeyType::REPLAY_START_STOP:
|
|
return &config.replay_config.start_stop_hotkey;
|
|
case ConfigureHotkeyType::REPLAY_SAVE:
|
|
return &config.replay_config.save_hotkey;
|
|
case ConfigureHotkeyType::RECORD_START_STOP:
|
|
return &config.record_config.start_stop_hotkey;
|
|
case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE:
|
|
return &config.record_config.pause_unpause_hotkey;
|
|
case ConfigureHotkeyType::STREAM_START_STOP:
|
|
return &config.streaming_config.start_stop_hotkey;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT:
|
|
return &config.screenshot_config.take_screenshot_hotkey;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT_REGION:
|
|
return &config.screenshot_config.take_screenshot_region_hotkey;
|
|
case ConfigureHotkeyType::SHOW_HIDE:
|
|
return &config.main_config.show_hide_hotkey;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void GlobalSettingsPage::for_each_config_hotkey(std::function<void(ConfigHotkey *config_hotkey)> callback) {
|
|
ConfigHotkey *config_hotkeys[] = {
|
|
&config.replay_config.start_stop_hotkey,
|
|
&config.replay_config.save_hotkey,
|
|
&config.record_config.start_stop_hotkey,
|
|
&config.record_config.pause_unpause_hotkey,
|
|
&config.streaming_config.start_stop_hotkey,
|
|
&config.screenshot_config.take_screenshot_hotkey,
|
|
&config.screenshot_config.take_screenshot_region_hotkey,
|
|
&config.main_config.show_hide_hotkey
|
|
};
|
|
for(ConfigHotkey *config_hotkey : config_hotkeys) {
|
|
callback(config_hotkey);
|
|
}
|
|
}
|
|
|
|
void GlobalSettingsPage::configure_hotkey_start(ConfigureHotkeyType hotkey_type) {
|
|
assert(hotkey_type != ConfigureHotkeyType::NONE);
|
|
configure_config_hotkey = {0, 0};
|
|
configure_hotkey_type = hotkey_type;
|
|
|
|
content_page_ptr->set_visible(false);
|
|
hotkey_overlay_ptr->set_visible(true);
|
|
overlay->unbind_all_keyboard_hotkeys();
|
|
configure_hotkey_get_button_by_active_type()->set_text("");
|
|
|
|
switch(hotkey_type) {
|
|
case ConfigureHotkeyType::NONE:
|
|
hotkey_configure_action_name = "";
|
|
break;
|
|
case ConfigureHotkeyType::REPLAY_START_STOP:
|
|
hotkey_configure_action_name = "Turn replay on/off";
|
|
break;
|
|
case ConfigureHotkeyType::REPLAY_SAVE:
|
|
hotkey_configure_action_name = "Save replay";
|
|
break;
|
|
case ConfigureHotkeyType::RECORD_START_STOP:
|
|
hotkey_configure_action_name = "Start/stop recording";
|
|
break;
|
|
case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE:
|
|
hotkey_configure_action_name = "Pause/unpause recording";
|
|
break;
|
|
case ConfigureHotkeyType::STREAM_START_STOP:
|
|
hotkey_configure_action_name = "Start/stop streaming";
|
|
break;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT:
|
|
hotkey_configure_action_name = "Take a screenshot";
|
|
break;
|
|
case ConfigureHotkeyType::TAKE_SCREENSHOT_REGION:
|
|
hotkey_configure_action_name = "Take a screenshot of a region";
|
|
break;
|
|
case ConfigureHotkeyType::SHOW_HIDE:
|
|
hotkey_configure_action_name = "Show/hide UI";
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GlobalSettingsPage::configure_hotkey_cancel() {
|
|
Button *config_hotkey_button = configure_hotkey_get_button_by_active_type();
|
|
ConfigHotkey *config_hotkey = configure_hotkey_get_config_by_active_type();
|
|
if(config_hotkey_button && config_hotkey)
|
|
config_hotkey_button->set_text(config_hotkey->to_string());
|
|
|
|
configure_config_hotkey = {0, 0};
|
|
configure_hotkey_type = ConfigureHotkeyType::NONE;
|
|
content_page_ptr->set_visible(true);
|
|
hotkey_overlay_ptr->set_visible(false);
|
|
overlay->rebind_all_keyboard_hotkeys();
|
|
}
|
|
|
|
void GlobalSettingsPage::configure_hotkey_stop_and_save() {
|
|
Button *config_hotkey_button = configure_hotkey_get_button_by_active_type();
|
|
ConfigHotkey *config_hotkey = configure_hotkey_get_config_by_active_type();
|
|
if(config_hotkey_button && config_hotkey) {
|
|
bool hotkey_used_by_another_action = false;
|
|
if(configure_config_hotkey.key != mgl::Keyboard::Unknown) {
|
|
for_each_config_hotkey([&](ConfigHotkey *config_hotkey_item) {
|
|
if(config_hotkey_item != config_hotkey && *config_hotkey_item == configure_config_hotkey)
|
|
hotkey_used_by_another_action = true;
|
|
});
|
|
}
|
|
|
|
if(hotkey_used_by_another_action) {
|
|
const std::string error_msg = "The hotkey \"" + configure_config_hotkey.to_string() + " is already used for something else";
|
|
overlay->show_notification(error_msg.c_str(), 3.0, mgl::Color(255, 0, 0, 255), mgl::Color(255, 0, 0, 255), NotificationType::NONE);
|
|
config_hotkey_button->set_text(config_hotkey->to_string());
|
|
configure_config_hotkey = {0, 0};
|
|
return;
|
|
}
|
|
|
|
*config_hotkey = configure_config_hotkey;
|
|
}
|
|
|
|
configure_config_hotkey = {0, 0};
|
|
configure_hotkey_type = ConfigureHotkeyType::NONE;
|
|
content_page_ptr->set_visible(true);
|
|
hotkey_overlay_ptr->set_visible(false);
|
|
overlay->rebind_all_keyboard_hotkeys();
|
|
}
|
|
}
|