Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements display resolution settings #948

Merged
merged 1 commit into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@
struct Param;
struct Pkg;

/**
* Display resolution to report to the kernel.
*/
enum DisplayResolution {
/**
* 1280 × 720.
*/
DisplayResolution_Hd,
/**
* 1920 × 1080.
*/
DisplayResolution_FullHd,
/**
* 3840 × 2160.
*/
DisplayResolution_UltraHd,
};

/**
* Log category.
*/
Expand Down Expand Up @@ -124,6 +142,10 @@ char *profile_id(const struct Profile *p);

const char *profile_name(const struct Profile *p);

enum DisplayResolution profile_display_resolution(const struct Profile *p);

void profile_set_display_resolution(struct Profile *p, enum DisplayResolution v);

struct RustError *profile_save(const struct Profile *p, const char *path);

struct RustError *update_firmware(const char *root,
Expand Down
2 changes: 1 addition & 1 deletion src/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ obfw = { git = "https://github.com/obhq/firmware-dumper.git", features = ["read"
obvirt = { path = "../obvirt" }
param = { path = "../param" }
pkg = { path = "../pkg" }
postcard = { version = "1.0.10", features = ["use-std"], default-features = false }
ciborium = "0.2.2"
serde = { version = "1.0.209", features = ["derive"] }
thiserror = "1.0"
uuid = { version = "1.10.0", features = ["serde", "v4"] }
Expand Down
48 changes: 41 additions & 7 deletions src/core/src/profile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ use uuid::Uuid;
#[no_mangle]
pub unsafe extern "C" fn profile_new(name: *const c_char) -> *mut Profile {
Box::into_raw(Box::new(Profile {
id: Uuid::new_v4(),
name: CStr::from_ptr(name).to_owned(),
created: SystemTime::now(),
..Default::default()
}))
}

Expand All @@ -31,18 +30,18 @@ pub unsafe extern "C" fn profile_load(
}
};

// TODO: Use from_io() once https://github.com/jamesmunns/postcard/issues/162 is implemented.
// Open profile.bin.
let path = root.join("profile.bin");
let data = match std::fs::read(&path) {
let file = match File::open(&path) {
Ok(v) => v,
Err(e) => {
*err = RustError::with_source(format_args!("couldn't read {}", path.display()), e);
*err = RustError::with_source(format_args!("couldn't open {}", path.display()), e);
return null_mut();
}
};

// Load profile.bin.
let p = match postcard::from_bytes(&data) {
let p = match ciborium::from_reader(file) {
Ok(v) => v,
Err(e) => {
*err = RustError::with_source(format_args!("couldn't load {}", path.display()), e);
Expand All @@ -68,6 +67,16 @@ pub unsafe extern "C" fn profile_name(p: *const Profile) -> *const c_char {
(*p).name.as_ptr()
}

#[no_mangle]
pub unsafe extern "C" fn profile_display_resolution(p: *const Profile) -> DisplayResolution {
(*p).display_resolution
}

#[no_mangle]
pub unsafe extern "C" fn profile_set_display_resolution(p: *mut Profile, v: DisplayResolution) {
(*p).display_resolution = v;
}

#[no_mangle]
pub unsafe extern "C" fn profile_save(p: *const Profile, path: *const c_char) -> *mut RustError {
// Check if path UTF-8.
Expand All @@ -91,7 +100,7 @@ pub unsafe extern "C" fn profile_save(p: *const Profile, path: *const c_char) ->
};

// Write profile.bin.
if let Err(e) = postcard::to_io(&*p, file) {
if let Err(e) = ciborium::into_writer(&*p, file) {
return RustError::with_source(format_args!("couldn't write {}", path.display()), e);
}

Expand All @@ -100,8 +109,33 @@ pub unsafe extern "C" fn profile_save(p: *const Profile, path: *const c_char) ->

/// Contains settings to launch the kernel.
#[derive(Deserialize, Serialize)]
#[serde(default)]
pub struct Profile {
id: Uuid,
name: CString,
display_resolution: DisplayResolution,
created: SystemTime,
}

impl Default for Profile {
fn default() -> Self {
Self {
id: Uuid::new_v4(),
name: CString::new("Default").unwrap(),
display_resolution: DisplayResolution::Hd,
created: SystemTime::now(),
}
}
}

/// Display resolution to report to the kernel.
#[repr(C)]
#[derive(Clone, Copy, Deserialize, Serialize)]
pub enum DisplayResolution {
/// 1280 × 720.
Hd,
/// 1920 × 1080.
FullHd,
/// 3840 × 2160.
UltraHd,
}
61 changes: 60 additions & 1 deletion src/display_settings.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,69 @@
#include "display_settings.hpp"

#include <QComboBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QMessageBox>
#include <QVBoxLayout>

DisplaySettings::DisplaySettings(QWidget *parent) :
QWidget(parent)
QWidget(parent),
m_resolutions(nullptr),
m_profile(nullptr)
{
auto layout = new QGridLayout();

layout->addWidget(buildResolution(), 0, 0);
layout->setColumnStretch(1, 1);
layout->setRowStretch(1, 1);

setLayout(layout);
}

DisplaySettings::~DisplaySettings()
{
}

void DisplaySettings::setProfile(Profile *p)
{
// Set current profile before update the widgets since the update may trigger some signals.
m_profile = p;

// Set resolution.
auto resolution = profile_display_resolution(p);
auto i = m_resolutions->findData(resolution);

if (i < 0) {
QMessageBox::critical(
this,
"Error",
QString("Unknown display resolution %1.").arg(resolution));
} else {
m_resolutions->setCurrentIndex(i);
}
}

QWidget *DisplaySettings::buildResolution()
{
// Setup group box.
auto group = new QGroupBox("Resolution");
auto layout = new QVBoxLayout();

// Setup resolution list.
m_resolutions = new QComboBox();
m_resolutions->addItem("1280 × 720", DisplayResolution_Hd);
m_resolutions->addItem("1920 × 1080", DisplayResolution_FullHd);
m_resolutions->addItem("3840 × 2160", DisplayResolution_UltraHd);

connect(m_resolutions, &QComboBox::currentIndexChanged, [this](int index) {
auto value = static_cast<DisplayResolution>(m_resolutions->itemData(index).toInt());

profile_set_display_resolution(m_profile, value);
});

layout->addWidget(m_resolutions);

group->setLayout(layout);

return group;
}
11 changes: 11 additions & 0 deletions src/display_settings.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
#pragma once

#include "core.h"

#include <QWidget>

class QComboBox;

class DisplaySettings final : public QWidget {
public:
DisplaySettings(QWidget *parent = nullptr);
~DisplaySettings() override;

void setProfile(Profile *p);
private:
QWidget *buildResolution();

QComboBox *m_resolutions;
Profile *m_profile;
};
12 changes: 12 additions & 0 deletions src/launch_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ QLayout *LaunchSettings::buildActions(ProfileList *profiles)
m_profiles = new QComboBox();
m_profiles->setModel(profiles);

connect(m_profiles, &QComboBox::currentIndexChanged, this, &LaunchSettings::profileChanged);

layout->addWidget(m_profiles, 1);

// Actions bar.
Expand Down Expand Up @@ -141,3 +143,13 @@ void LaunchSettings::requestGamesContextMenu(const QPoint &pos)
dialog.exec();
}
}

void LaunchSettings::profileChanged(int index)
{
assert(index >= 0);

auto profiles = reinterpret_cast<ProfileList *>(m_profiles->model());
auto p = profiles->get(index);

m_display->setProfile(p);
}
1 change: 1 addition & 0 deletions src/launch_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class LaunchSettings final : public QWidget {
QLayout *buildActions(ProfileList *profiles);

void requestGamesContextMenu(const QPoint &pos);
void profileChanged(int index);

DisplaySettings *m_display;
QTableView *m_games;
Expand Down