mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-04-03 01:48:29 -04:00
fix(gamescope): Fix Perf Overlay for Gamescope
Signed-off-by: Collecting <collecting@noreply.localhost>
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
#include <QSizeGrip>
|
||||||
|
#include <QGridLayout>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
@@ -22,7 +24,7 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
#include <WbemIdl.h>
|
#include <WbemIdl.h>
|
||||||
#pragma comment(lib, "wbemuuid.lib") // For MSVC, helps the linker find the library
|
#pragma comment(lib, "wbemuuid.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
@@ -37,85 +39,91 @@
|
|||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
|
||||||
PerformanceOverlay::PerformanceOverlay(GMainWindow* parent)
|
PerformanceOverlay::PerformanceOverlay(QWidget* parent) : QWidget(UISettings::IsGamescope() ? nullptr : parent) {
|
||||||
: QWidget(parent), main_window(parent) {
|
if (parent) {
|
||||||
|
main_window = qobject_cast<GMainWindow*>(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UISettings::IsGamescope()) {
|
||||||
|
setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);
|
||||||
|
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||||
|
} else {
|
||||||
|
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the widget properties
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
|
setAttribute(Qt::WA_NoSystemBackground);
|
||||||
|
setAttribute(Qt::WA_WState_ExplicitShowHide);
|
||||||
|
|
||||||
// Initialize fonts with better typography
|
if (UISettings::IsGamescope()) {
|
||||||
title_font = QFont(QString::fromUtf8("Segoe UI"), 9, QFont::Medium);
|
title_font = QFont(QString::fromUtf8("Segoe UI"), 9, QFont::Bold);
|
||||||
value_font = QFont(QString::fromUtf8("Segoe UI"), 11, QFont::Bold);
|
value_font = QFont(QString::fromUtf8("Segoe UI"), 10, QFont::Bold);
|
||||||
small_font = QFont(QString::fromUtf8("Segoe UI"), 8, QFont::Normal);
|
small_font = QFont(QString::fromUtf8("Segoe UI"), 8, QFont::Normal);
|
||||||
|
setMinimumSize(160, 130);
|
||||||
|
resize(195, 160);
|
||||||
|
} else {
|
||||||
|
title_font = QFont(QString::fromUtf8("Segoe UI"), 9, QFont::Medium);
|
||||||
|
value_font = QFont(QString::fromUtf8("Segoe UI"), 11, QFont::Bold);
|
||||||
|
small_font = QFont(QString::fromUtf8("Segoe UI"), 8, QFont::Normal);
|
||||||
|
setMinimumSize(220, 180);
|
||||||
|
resize(220, 180);
|
||||||
|
}
|
||||||
|
|
||||||
temperature_color = QColor(76, 175, 80, 255); // Default to green
|
auto* layout = new QGridLayout(this);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
size_grip = new QSizeGrip(this);
|
||||||
|
layout->addWidget(size_grip, 0, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||||
|
|
||||||
// Graph colors
|
temperature_color = QColor(76, 175, 80, 255);
|
||||||
graph_background_color = QColor(40, 40, 40, 100);
|
graph_background_color = QColor(40, 40, 40, 100);
|
||||||
graph_line_color = QColor(76, 175, 80, 200);
|
graph_line_color = QColor(76, 175, 80, 200);
|
||||||
graph_fill_color = QColor(76, 175, 80, 60);
|
graph_fill_color = QColor(76, 175, 80, 60);
|
||||||
|
|
||||||
// Set up timer for updates
|
|
||||||
update_timer.setSingleShot(false);
|
update_timer.setSingleShot(false);
|
||||||
connect(&update_timer, &QTimer::timeout, this, &PerformanceOverlay::UpdatePerformanceStats);
|
connect(&update_timer, &QTimer::timeout, this, &PerformanceOverlay::UpdatePerformanceStats);
|
||||||
|
|
||||||
// Connect to the main window's theme change signal
|
if (main_window) {
|
||||||
connect(parent, &GMainWindow::themeChanged, this, &PerformanceOverlay::UpdateTheme);
|
connect(main_window, &GMainWindow::themeChanged, this, &PerformanceOverlay::UpdateTheme);
|
||||||
// Set the initial theme colors
|
}
|
||||||
|
|
||||||
UpdateTheme();
|
UpdateTheme();
|
||||||
|
|
||||||
// Set initial size - larger to accommodate the graph
|
|
||||||
resize(220, 180);
|
|
||||||
|
|
||||||
// Position in top-left corner
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceOverlay::~PerformanceOverlay() = default;
|
PerformanceOverlay::~PerformanceOverlay() = default;
|
||||||
|
|
||||||
void PerformanceOverlay::SetVisible(bool visible) {
|
void PerformanceOverlay::SetVisible(bool visible) {
|
||||||
if (is_visible == visible) {
|
is_enabled = visible;
|
||||||
return;
|
is_visible = visible; // Update the state so the check works next time
|
||||||
}
|
|
||||||
|
|
||||||
is_visible = visible;
|
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
show();
|
show();
|
||||||
update_timer.start(500); // Update every 500ms for more accurate data
|
update_timer.start(500);
|
||||||
} else {
|
} else {
|
||||||
|
update_timer.stop(); // Stop the timer first
|
||||||
hide();
|
hide();
|
||||||
update_timer.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::paintEvent(QPaintEvent* event) {
|
void PerformanceOverlay::paintEvent(QPaintEvent* event) {
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
|
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
|
||||||
// Draw background with rounded corners and subtle shadow effect
|
|
||||||
QPainterPath background_path;
|
QPainterPath background_path;
|
||||||
background_path.addRoundedRect(rect(), corner_radius, corner_radius);
|
background_path.addRoundedRect(rect(), corner_radius, corner_radius);
|
||||||
|
|
||||||
// Draw subtle shadow
|
if (!UISettings::IsGamescope()) {
|
||||||
QPainterPath shadow_path = background_path.translated(1, 1);
|
QPainterPath shadow_path = background_path.translated(1, 1);
|
||||||
painter.fillPath(shadow_path, QColor(0, 0, 0, 40));
|
painter.fillPath(shadow_path, QColor(0, 0, 0, 40));
|
||||||
|
}
|
||||||
|
|
||||||
// Draw main background
|
|
||||||
painter.fillPath(background_path, background_color);
|
painter.fillPath(background_path, background_color);
|
||||||
|
|
||||||
// Draw subtle border
|
|
||||||
painter.setPen(QPen(border_color, border_width));
|
painter.setPen(QPen(border_color, border_width));
|
||||||
painter.drawPath(background_path);
|
painter.drawPath(background_path);
|
||||||
|
|
||||||
// Draw performance information
|
|
||||||
DrawPerformanceInfo(painter);
|
DrawPerformanceInfo(painter);
|
||||||
|
|
||||||
// Draw frame graph
|
|
||||||
DrawFrameGraph(painter);
|
DrawFrameGraph(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,128 +132,110 @@ void PerformanceOverlay::resizeEvent(QResizeEvent* event) {
|
|||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PerformanceOverlay::mousePressEvent(QMouseEvent* event) {
|
||||||
|
if (event->button() == Qt::LeftButton && !size_grip->geometry().contains(event->pos())) {
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
// LINUX-SPECIFIC IMPLEMENTATION (Wayland Fix)
|
if (!UISettings::IsGamescope() && windowHandle()) {
|
||||||
void PerformanceOverlay::mousePressEvent(QMouseEvent* event) {
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
// Hand off window moving responsibility to the OS compositor.
|
|
||||||
if (windowHandle()) {
|
|
||||||
windowHandle()->startSystemMove();
|
windowHandle()->startSystemMove();
|
||||||
|
} else {
|
||||||
|
is_dragging = true;
|
||||||
|
drag_start_pos = event->globalPosition().toPoint() - this->pos();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
QWidget::mousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PerformanceOverlay::mouseMoveEvent(QMouseEvent* event) {
|
|
||||||
// This function is intentionally left blank for dragging, as the
|
|
||||||
// system compositor now handles the entire move operation.
|
|
||||||
QWidget::mouseMoveEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// ORIGINAL IMPLEMENTATION
|
|
||||||
void PerformanceOverlay::mousePressEvent(QMouseEvent* event) {
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
is_dragging = true;
|
is_dragging = true;
|
||||||
drag_start_pos = event->globalPosition().toPoint();
|
drag_start_pos = event->globalPosition().toPoint() - this->pos();
|
||||||
widget_start_pos = this->pos();
|
#endif
|
||||||
setCursor(Qt::ClosedHandCursor);
|
event->accept();
|
||||||
}
|
}
|
||||||
QWidget::mousePressEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::mouseMoveEvent(QMouseEvent* event) {
|
void PerformanceOverlay::mouseMoveEvent(QMouseEvent* event) {
|
||||||
if (is_dragging) {
|
if (is_dragging) {
|
||||||
QPoint delta = event->globalPosition().toPoint() - drag_start_pos;
|
move(event->globalPosition().toPoint() - drag_start_pos);
|
||||||
move(widget_start_pos + delta);
|
event->accept();
|
||||||
}
|
}
|
||||||
QWidget::mouseMoveEvent(event);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void PerformanceOverlay::mouseReleaseEvent(QMouseEvent* event) {
|
void PerformanceOverlay::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
is_dragging = false;
|
is_dragging = false;
|
||||||
has_been_moved = true;
|
has_been_moved = true;
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
|
event->accept();
|
||||||
}
|
}
|
||||||
QWidget::mouseReleaseEvent(event);
|
QWidget::mouseReleaseEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PerformanceOverlay::UpdatePerformanceStats() {
|
void PerformanceOverlay::UpdatePerformanceStats() {
|
||||||
if (!main_window) {
|
if (!main_window || !is_enabled) return;
|
||||||
return;
|
|
||||||
|
if (UISettings::IsGamescope()) {
|
||||||
|
bool ui_active = (QApplication::activePopupWidget() != nullptr);
|
||||||
|
|
||||||
|
if (!ui_active) {
|
||||||
|
for (QWidget* w : QApplication::topLevelWidgets()) {
|
||||||
|
if (w->isVisible() && w != main_window && w != this &&
|
||||||
|
!w->inherits("GRenderWindow") &&
|
||||||
|
!w->inherits("VramOverlay") &&
|
||||||
|
!w->inherits("ControllerOverlay") &&
|
||||||
|
!w->inherits("PerformanceOverlay")) {
|
||||||
|
ui_active = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui_active) {
|
||||||
|
if (!this->isHidden()) this->hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isHidden()) {
|
||||||
|
this->show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Desktop: Only force a show if the user actually has it enabled in the menu
|
||||||
|
if (is_enabled && this->isHidden()) {
|
||||||
|
this->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get shader building info (this is safe to call)
|
|
||||||
shaders_building = main_window->GetShadersBuilding();
|
shaders_building = main_window->GetShadersBuilding();
|
||||||
|
|
||||||
// Use a static counter to only call the performance methods occasionally
|
|
||||||
// This reduces the chance of conflicts with the status bar updates
|
|
||||||
static int update_counter = 0;
|
static int update_counter = 0;
|
||||||
update_counter++;
|
update_counter++;
|
||||||
|
|
||||||
// Try to get performance data every 2nd update (every 1 second)
|
|
||||||
if (update_counter % 2 == 0) {
|
if (update_counter % 2 == 0) {
|
||||||
try {
|
try {
|
||||||
current_fps = main_window->GetCurrentFPS();
|
current_fps = main_window->GetCurrentFPS();
|
||||||
current_frame_time = main_window->GetCurrentFrameTime();
|
current_frame_time = main_window->GetCurrentFrameTime();
|
||||||
emulation_speed = main_window->GetEmulationSpeed();
|
emulation_speed = main_window->GetEmulationSpeed();
|
||||||
|
|
||||||
// Validate the values
|
if (std::isnan(current_fps) || current_fps < 0.0 || current_fps > 1000.0) current_fps = 60.0;
|
||||||
if (std::isnan(current_fps) || current_fps < 0.0 || current_fps > 1000.0) {
|
if (std::isnan(current_frame_time) || current_frame_time < 0.0 || current_frame_time > 100.0) current_frame_time = 16.67;
|
||||||
current_fps = 60.0;
|
if (std::isnan(emulation_speed) || emulation_speed < 0.0 || emulation_speed > 1000.0) emulation_speed = 100.0;
|
||||||
}
|
|
||||||
if (std::isnan(current_frame_time) || current_frame_time < 0.0 || current_frame_time > 100.0) {
|
|
||||||
current_frame_time = 16.67;
|
|
||||||
}
|
|
||||||
if (std::isnan(emulation_speed) || emulation_speed < 0.0 || emulation_speed > 1000.0) {
|
|
||||||
emulation_speed = 100.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure FPS and frame time are consistent
|
if (current_fps > 0.0) current_frame_time = 1000.0 / current_fps;
|
||||||
if (current_fps > 0.0 && current_frame_time > 0.0) {
|
} catch (...) {}
|
||||||
// Recalculate frame time from FPS to ensure consistency
|
|
||||||
current_frame_time = 1000.0 / current_fps;
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
// If we get an exception, use the last known good values
|
|
||||||
// Don't reset to defaults immediately
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update hardware temperatures every 4th update (every 2 seconds)
|
|
||||||
if (update_counter % 4 == 0) {
|
if (update_counter % 4 == 0) {
|
||||||
UpdateHardwareTemperatures();
|
UpdateHardwareTemperatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have valid data yet, use defaults
|
if (std::isnan(current_fps) || current_fps <= 0.0) current_fps = 60.0;
|
||||||
if (std::isnan(current_fps) || current_fps <= 0.0) {
|
if (std::isnan(current_frame_time) || current_frame_time <= 0.0) current_frame_time = 16.67;
|
||||||
current_fps = 60.0;
|
if (std::isnan(emulation_speed) || emulation_speed <= 0.0) emulation_speed = 100.0;
|
||||||
}
|
|
||||||
if (std::isnan(current_frame_time) || current_frame_time <= 0.0) {
|
|
||||||
current_frame_time = 16.67; // 60 FPS
|
|
||||||
}
|
|
||||||
if (std::isnan(emulation_speed) || emulation_speed <= 0.0) {
|
|
||||||
emulation_speed = 100.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add frame time to graph history (only if it's valid)
|
if (current_frame_time > 0.0) AddFrameTime(current_frame_time);
|
||||||
if (current_frame_time > 0.0) {
|
|
||||||
AddFrameTime(current_frame_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update FPS and Temperature colors based on performance
|
|
||||||
fps_color = GetFpsColor(current_fps);
|
fps_color = GetFpsColor(current_fps);
|
||||||
temperature_color = GetTemperatureColor(std::max({cpu_temperature, gpu_temperature, battery_temperature}));
|
temperature_color = GetTemperatureColor(std::max({cpu_temperature, gpu_temperature, battery_temperature}));
|
||||||
|
|
||||||
// Trigger a repaint
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::UpdateHardwareTemperatures() {
|
void PerformanceOverlay::UpdateHardwareTemperatures() {
|
||||||
// Reset data
|
|
||||||
cpu_temperature = 0.0f;
|
cpu_temperature = 0.0f;
|
||||||
gpu_temperature = 0.0f;
|
gpu_temperature = 0.0f;
|
||||||
cpu_sensor_type.clear();
|
cpu_sensor_type.clear();
|
||||||
@@ -254,41 +244,80 @@ void PerformanceOverlay::UpdateHardwareTemperatures() {
|
|||||||
battery_temperature = 0.0f;
|
battery_temperature = 0.0f;
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
// --- Standard Linux Thermal Zone Reading ---
|
// 1. Read Battery Data (Steam Deck / Laptops)
|
||||||
QDir thermal_dir(QString::fromUtf8("/sys/class/thermal/"));
|
QDir bat_dir(QStringLiteral("/sys/class/power_supply/"));
|
||||||
QStringList filters{QString::fromUtf8("thermal_zone*")};
|
QStringList bats = bat_dir.entryList({QStringLiteral("BAT*")}, QDir::Dirs);
|
||||||
QStringList thermal_zones = thermal_dir.entryList(filters, QDir::Dirs);
|
for (const QString& node : bats) {
|
||||||
|
QFile cap_file(bat_dir.filePath(node + QStringLiteral("/capacity")));
|
||||||
|
if (cap_file.open(QIODevice::ReadOnly)) {
|
||||||
|
battery_percentage = cap_file.readAll().trimmed().toInt();
|
||||||
|
cap_file.close();
|
||||||
|
|
||||||
for (const QString& zone_name : thermal_zones) {
|
QFile btemp_file(bat_dir.filePath(node + QStringLiteral("/temp")));
|
||||||
QFile type_file(thermal_dir.filePath(zone_name + QString::fromUtf8("/type")));
|
if (btemp_file.open(QIODevice::ReadOnly)) {
|
||||||
if (!type_file.open(QIODevice::ReadOnly | QIODevice::Text)) continue;
|
float raw_temp = btemp_file.readAll().trimmed().toFloat();
|
||||||
QString type = QString::fromUtf8(type_file.readAll()).trimmed();
|
// Detect millidegrees (35000) or tenths (350)
|
||||||
type_file.close();
|
battery_temperature = (raw_temp > 1000) ? raw_temp / 1000.0f : raw_temp / 10.0f;
|
||||||
|
btemp_file.close();
|
||||||
QFile temp_file(thermal_dir.filePath(zone_name + QString::fromUtf8("/temp")));
|
|
||||||
if (!temp_file.open(QIODevice::ReadOnly | QIODevice::Text)) continue;
|
|
||||||
float temp = temp_file.readAll().trimmed().toFloat() / 1000.0f;
|
|
||||||
temp_file.close();
|
|
||||||
|
|
||||||
if (type.contains(QString::fromUtf8("x86_pkg_temp")) || type.contains(QString::fromUtf8("cpu"))) {
|
|
||||||
if (temp > cpu_temperature) {
|
|
||||||
cpu_temperature = temp;
|
|
||||||
cpu_sensor_type = QString::fromUtf8("CPU");
|
|
||||||
}
|
}
|
||||||
} else if (type.contains(QString::fromUtf8("radeon")) || type.contains(QString::fromUtf8("amdgpu")) || type.contains(QString::fromUtf8("nvidia")) || type.contains(QString::fromUtf8("nouveau"))) {
|
break;
|
||||||
if (temp > gpu_temperature) {
|
}
|
||||||
gpu_temperature = temp;
|
}
|
||||||
gpu_sensor_type = QString::fromUtf8("GPU");
|
|
||||||
|
// 2. Read APU/CPU Temperatures
|
||||||
|
QDir hwmon_dir(QStringLiteral("/sys/class/hwmon/"));
|
||||||
|
QStringList hwmons = hwmon_dir.entryList({QStringLiteral("hwmon*")}, QDir::Dirs);
|
||||||
|
for (const QString& h_node : hwmons) {
|
||||||
|
QFile name_file(hwmon_dir.filePath(h_node + QStringLiteral("/name")));
|
||||||
|
if (!name_file.open(QIODevice::ReadOnly)) continue;
|
||||||
|
QString hw_name = QString::fromUtf8(name_file.readAll().trimmed());
|
||||||
|
name_file.close();
|
||||||
|
|
||||||
|
// GPU Portion (Standard Steam Deck & Desktop AMD)
|
||||||
|
if (hw_name == QStringLiteral("amdgpu")) {
|
||||||
|
QFile t_file(hwmon_dir.filePath(h_node + QStringLiteral("/temp1_input")));
|
||||||
|
if (t_file.open(QIODevice::ReadOnly)) {
|
||||||
|
gpu_temperature = t_file.readAll().trimmed().toFloat() / 1000.0f;
|
||||||
|
gpu_sensor_type = QStringLiteral("GPU");
|
||||||
|
t_file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CPU Portion (k10temp = AMD Deck/Desktop, coretemp = Intel Desktop)
|
||||||
|
else if (hw_name == QStringLiteral("k10temp") || hw_name == QStringLiteral("coretemp") || hw_name == QStringLiteral("zenpower")) {
|
||||||
|
// Check for temp1_input (AMD) or temp2_input (Intel coretemp usually starts at 2 for package)
|
||||||
|
QStringList input_candidates = {QStringLiteral("temp1_input"), QStringLiteral("temp2_input")};
|
||||||
|
for (const auto& input : input_candidates) {
|
||||||
|
QFile t_file(hwmon_dir.filePath(h_node + QStringLiteral("/") + input));
|
||||||
|
if (t_file.open(QIODevice::ReadOnly)) {
|
||||||
|
cpu_temperature = t_file.readAll().trimmed().toFloat() / 1000.0f;
|
||||||
|
cpu_sensor_type = QStringLiteral("CPU");
|
||||||
|
t_file.close();
|
||||||
|
if (cpu_temperature > 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fallback to generic thermal_zones
|
||||||
|
if (cpu_temperature <= 0.0f) {
|
||||||
|
QDir thermal_dir(QStringLiteral("/sys/class/thermal/"));
|
||||||
|
QStringList thermal_zones = thermal_dir.entryList({QStringLiteral("thermal_zone*")}, QDir::Dirs);
|
||||||
|
for (const QString& zone_name : thermal_zones) {
|
||||||
|
QFile temp_file(thermal_dir.filePath(zone_name + QStringLiteral("/temp")));
|
||||||
|
if (temp_file.open(QIODevice::ReadOnly)) {
|
||||||
|
cpu_temperature = temp_file.readAll().trimmed().toFloat() / 1000.0f;
|
||||||
|
cpu_sensor_type = QStringLiteral("CPU");
|
||||||
|
temp_file.close();
|
||||||
|
if (cpu_temperature > 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
// This uses QtAndroid Extras to get battery info from the Android system.
|
|
||||||
// NOTE: This requires the QtAndroidExtras module to be linked in the build.
|
|
||||||
QJniObject battery_status = QJniObject::callStaticObjectMethod(
|
QJniObject battery_status = QJniObject::callStaticObjectMethod(
|
||||||
"android/content/CONTEXT", "registerReceiver",
|
"android/content/Context", "registerReceiver",
|
||||||
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;",
|
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;",
|
||||||
nullptr, new QJniObject("android.content.IntentFilter", "(Ljava/lang/String;)V", "android.intent.action.BATTERY_CHANGED"));
|
nullptr, new QJniObject("android.content.IntentFilter", "(Ljava/lang/String;)V", "android.intent.action.BATTERY_CHANGED"));
|
||||||
|
|
||||||
@@ -300,12 +329,8 @@ void PerformanceOverlay::UpdateHardwareTemperatures() {
|
|||||||
int temp_tenths = battery_status.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I",
|
int temp_tenths = battery_status.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I",
|
||||||
QJniObject::fromString("temperature").object<jstring>(), -1);
|
QJniObject::fromString("temperature").object<jstring>(), -1);
|
||||||
|
|
||||||
if (scale > 0) {
|
if (scale > 0) battery_percentage = (level * 100) / scale;
|
||||||
battery_percentage = (level * 100) / scale;
|
if (temp_tenths > 0) battery_temperature = static_cast<float>(temp_tenths) / 10.0f;
|
||||||
}
|
|
||||||
if (temp_tenths > 0) {
|
|
||||||
battery_temperature = static_cast<float>(temp_tenths) / 10.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -313,9 +338,7 @@ void PerformanceOverlay::UpdateHardwareTemperatures() {
|
|||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
IWbemLocator* pLoc = nullptr;
|
IWbemLocator* pLoc = nullptr;
|
||||||
IWbemServices* pSvc = nullptr;
|
IWbemServices* pSvc = nullptr;
|
||||||
|
|
||||||
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
|
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
|
||||||
|
|
||||||
if (SUCCEEDED(hres)) {
|
if (SUCCEEDED(hres)) {
|
||||||
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
|
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
|
||||||
if (SUCCEEDED(hres)) {
|
if (SUCCEEDED(hres)) {
|
||||||
@@ -331,12 +354,11 @@ void PerformanceOverlay::UpdateHardwareTemperatures() {
|
|||||||
while (pEnumerator) {
|
while (pEnumerator) {
|
||||||
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||||
if (uReturn == 0) break;
|
if (uReturn == 0) break;
|
||||||
|
|
||||||
VARIANT vtProp;
|
VARIANT vtProp;
|
||||||
pclsObj->Get(L"CurrentTemperature", 0, &vtProp, 0, 0);
|
pclsObj->Get(L"CurrentTemperature", 0, &vtProp, 0, 0);
|
||||||
float temp_kelvin = vtProp.uintVal / 10.0f;
|
float temp_kelvin = vtProp.uintVal / 10.0f;
|
||||||
cpu_temperature = temp_kelvin - 273.15f;
|
cpu_temperature = temp_kelvin - 273.15f;
|
||||||
cpu_sensor_type = QString::fromUtf8("CPU");
|
cpu_sensor_type = QStringLiteral("CPU");
|
||||||
VariantClear(&vtProp);
|
VariantClear(&vtProp);
|
||||||
pclsObj->Release();
|
pclsObj->Release();
|
||||||
}
|
}
|
||||||
@@ -348,15 +370,9 @@ void PerformanceOverlay::UpdateHardwareTemperatures() {
|
|||||||
if(pSvc) pSvc->Release();
|
if(pSvc) pSvc->Release();
|
||||||
if(pLoc) pLoc->Release();
|
if(pLoc) pLoc->Release();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
void PerformanceOverlay::UpdatePosition() {
|
void PerformanceOverlay::UpdatePosition() {
|
||||||
if (!main_window) {
|
if (main_window && !has_been_moved) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only position in top-left corner if we haven't been moved by the user
|
|
||||||
if (!has_been_moved) {
|
|
||||||
QPoint main_window_pos = main_window->mapToGlobal(QPoint(0, 0));
|
QPoint main_window_pos = main_window->mapToGlobal(QPoint(0, 0));
|
||||||
move(main_window_pos.x() + 10, main_window_pos.y() + 10);
|
move(main_window_pos.x() + 10, main_window_pos.y() + 10);
|
||||||
}
|
}
|
||||||
@@ -365,92 +381,85 @@ void PerformanceOverlay::UpdatePosition() {
|
|||||||
void PerformanceOverlay::DrawPerformanceInfo(QPainter& painter) {
|
void PerformanceOverlay::DrawPerformanceInfo(QPainter& painter) {
|
||||||
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
|
||||||
int y_offset = padding;
|
// Dynamic spacing based on font size to prevent squishing
|
||||||
const int line_height = 20;
|
const int title_step = painter.fontMetrics().height() + 2;
|
||||||
|
const int stat_step = painter.fontMetrics().height() + 2;
|
||||||
|
|
||||||
// Draw title
|
int y_left = (padding / 2) + painter.fontMetrics().ascent();
|
||||||
|
int y_right = y_left + 10;
|
||||||
|
|
||||||
|
// 1. Draw Title (Left)
|
||||||
painter.setFont(title_font);
|
painter.setFont(title_font);
|
||||||
painter.setPen(text_color);
|
painter.setPen(text_color);
|
||||||
painter.drawText(padding, y_offset + 12, QString::fromUtf8("CITRON"));
|
painter.drawText(padding, y_left, QStringLiteral("CITRON PERFORMANCE"));
|
||||||
|
|
||||||
int y_offset_right = padding;
|
// 2. Draw Hardware Stats (Right Column)
|
||||||
const int line_height_right = 18;
|
|
||||||
|
|
||||||
// Draw Temperatures
|
|
||||||
painter.setFont(small_font);
|
painter.setFont(small_font);
|
||||||
|
const int hw_step = UISettings::IsGamescope() ? 16 : 20;
|
||||||
|
|
||||||
float core_temp_to_display = std::max(cpu_temperature, gpu_temperature);
|
if (cpu_temperature > 0.0f) {
|
||||||
if (core_temp_to_display > 0.0f) {
|
QString cpu_text = QStringLiteral("CPU:%1°C").arg(cpu_temperature, 0, 'f', 0);
|
||||||
QString core_label = gpu_temperature > cpu_temperature ? gpu_sensor_type : cpu_sensor_type;
|
painter.setPen(GetTemperatureColor(cpu_temperature));
|
||||||
QString core_temp_text = QString::fromUtf8("%1: %2°C").arg(core_label).arg(core_temp_to_display, 0, 'f', 0);
|
int tw = painter.fontMetrics().horizontalAdvance(cpu_text);
|
||||||
painter.setPen(GetTemperatureColor(core_temp_to_display));
|
painter.drawText(width() - padding - tw, y_right, cpu_text);
|
||||||
int text_width = painter.fontMetrics().horizontalAdvance(core_temp_text);
|
y_right += hw_step;
|
||||||
painter.drawText(width() - padding - text_width, y_offset_right + 12, core_temp_text);
|
}
|
||||||
|
|
||||||
|
if (gpu_temperature > 0.0f) {
|
||||||
|
QString gpu_text = QStringLiteral("GPU:%1°C").arg(gpu_temperature, 0, 'f', 0);
|
||||||
|
painter.setPen(GetTemperatureColor(gpu_temperature));
|
||||||
|
int tw = painter.fontMetrics().horizontalAdvance(gpu_text);
|
||||||
|
painter.drawText(width() - padding - tw, y_right, gpu_text);
|
||||||
|
y_right += hw_step;
|
||||||
}
|
}
|
||||||
y_offset_right += line_height_right;
|
|
||||||
|
|
||||||
// Draw Battery info
|
|
||||||
if (battery_percentage > 0) {
|
if (battery_percentage > 0) {
|
||||||
QString batt_text = QString::fromUtf8("Batt: %1%").arg(battery_percentage);
|
QString batt_text = QStringLiteral("Battery %:%1%").arg(battery_percentage);
|
||||||
if (battery_temperature > 0.0f) {
|
if (battery_temperature > 0.0f) {
|
||||||
batt_text += QString::fromUtf8(" (%1°C)").arg(battery_temperature, 0, 'f', 0);
|
batt_text += QStringLiteral(" (%1°C)").arg(battery_temperature, 0, 'f', 0);
|
||||||
}
|
}
|
||||||
painter.setPen(text_color);
|
painter.setPen(text_color);
|
||||||
int text_width = painter.fontMetrics().horizontalAdvance(batt_text);
|
int tw = painter.fontMetrics().horizontalAdvance(batt_text);
|
||||||
painter.drawText(width() - padding - text_width, y_offset_right + 12, batt_text);
|
painter.drawText(width() - padding - tw, y_right, batt_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
y_offset += line_height + 4;
|
// 3. Draw FPS (Left Column)
|
||||||
|
y_left += title_step;
|
||||||
// Draw FPS
|
|
||||||
painter.setFont(value_font);
|
painter.setFont(value_font);
|
||||||
painter.setPen(fps_color);
|
painter.setPen(fps_color);
|
||||||
QString fps_text = QString::fromUtf8("%1 FPS").arg(FormatFps(current_fps));
|
painter.drawText(padding, y_left, QStringLiteral("%1 FPS").arg(FormatFps(current_fps)));
|
||||||
painter.drawText(padding, y_offset, fps_text);
|
|
||||||
y_offset += line_height;
|
|
||||||
|
|
||||||
// Draw frame time
|
// 4. Draw Small Stats (Left Column)
|
||||||
|
y_left += title_step;
|
||||||
painter.setFont(small_font);
|
painter.setFont(small_font);
|
||||||
painter.setPen(text_color);
|
painter.setPen(text_color);
|
||||||
QString frame_time_text = QString::fromUtf8("Frame: %1 ms").arg(FormatFrameTime(current_frame_time));
|
painter.drawText(padding, y_left, QStringLiteral("Frame:%1 ms").arg(FormatFrameTime(current_frame_time)));
|
||||||
painter.drawText(padding, y_offset, frame_time_text);
|
|
||||||
y_offset += line_height - 2;
|
|
||||||
|
|
||||||
// Draw emulation speed
|
y_left += stat_step;
|
||||||
QString speed_text = QString::fromUtf8("Speed: %1%").arg(emulation_speed, 0, 'f', 0);
|
painter.drawText(padding, y_left, QStringLiteral("Speed:%1%").arg(emulation_speed, 0, 'f', 0));
|
||||||
painter.drawText(padding, y_offset, speed_text);
|
|
||||||
y_offset += line_height - 2;
|
|
||||||
|
|
||||||
// Draw shader building info with accent color
|
|
||||||
if (shaders_building > 0) {
|
if (shaders_building > 0) {
|
||||||
painter.setPen(QColor(255, 152, 0, 255)); // Material Design orange
|
y_left += stat_step;
|
||||||
QString shader_text = QString::fromUtf8("Building: %1 shader(s)").arg(shaders_building);
|
painter.setPen(QColor(255, 152, 0));
|
||||||
painter.drawText(padding, y_offset, shader_text);
|
painter.drawText(padding, y_left, QStringLiteral("Building:%1").arg(shaders_building));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::DrawFrameGraph(QPainter& painter) {
|
void PerformanceOverlay::DrawFrameGraph(QPainter& painter) {
|
||||||
if (frame_times.empty()) {
|
if (frame_times.empty()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int graph_y = height() - graph_height - padding;
|
const int graph_y = height() - graph_height - padding;
|
||||||
const int graph_width = width() - (padding * 2);
|
const int graph_width = width() - (padding * 2);
|
||||||
const QRect graph_rect(padding, graph_y, graph_width, graph_height);
|
const QRect graph_rect(padding, graph_y, graph_width, graph_height);
|
||||||
|
|
||||||
// Draw graph background
|
|
||||||
painter.fillRect(graph_rect, graph_background_color);
|
painter.fillRect(graph_rect, graph_background_color);
|
||||||
|
|
||||||
// Calculate graph bounds
|
|
||||||
const double min_val = std::max(0.0, min_frame_time - 1.0);
|
const double min_val = std::max(0.0, min_frame_time - 1.0);
|
||||||
const double max_val = std::max(16.67, max_frame_time + 1.0); // 16.67ms = 60 FPS
|
const double max_val = std::max(16.67, max_frame_time + 1.0);
|
||||||
const double range = max_val - min_val;
|
const double range = max_val - min_val;
|
||||||
|
if (range <= 0.0) return;
|
||||||
|
|
||||||
if (range <= 0.0) {
|
// Grid lines
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw grid lines
|
|
||||||
painter.setPen(QPen(QColor(80, 80, 80, 100), 1));
|
painter.setPen(QPen(QColor(80, 80, 80, 100), 1));
|
||||||
const int grid_lines = 4;
|
const int grid_lines = 4;
|
||||||
for (int i = 1; i < grid_lines; ++i) {
|
for (int i = 1; i < grid_lines; ++i) {
|
||||||
@@ -458,12 +467,11 @@ void PerformanceOverlay::DrawFrameGraph(QPainter& painter) {
|
|||||||
painter.drawLine(graph_rect.left(), y, graph_rect.right(), y);
|
painter.drawLine(graph_rect.left(), y, graph_rect.right(), y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw 60 FPS line (16.67ms)
|
// 60 FPS Target line
|
||||||
const int fps60_y = graph_y + graph_height - static_cast<int>((16.67 - min_val) / range * graph_height);
|
const int fps60_y = graph_y + graph_height - static_cast<int>((16.67 - min_val) / range * graph_height);
|
||||||
painter.setPen(QPen(QColor(255, 255, 255, 80), 1, Qt::DashLine));
|
painter.setPen(QPen(QColor(255, 255, 255, 80), 1, Qt::DashLine));
|
||||||
painter.drawLine(graph_rect.left(), fps60_y, graph_rect.right(), fps60_y);
|
painter.drawLine(graph_rect.left(), fps60_y, graph_rect.right(), fps60_y);
|
||||||
|
|
||||||
// Draw frame time line
|
|
||||||
painter.setPen(QPen(graph_line_color, 2));
|
painter.setPen(QPen(graph_line_color, 2));
|
||||||
painter.setBrush(graph_fill_color);
|
painter.setBrush(graph_fill_color);
|
||||||
|
|
||||||
@@ -476,45 +484,39 @@ void PerformanceOverlay::DrawFrameGraph(QPainter& painter) {
|
|||||||
const double normalized_y = (frame_time - min_val) / range;
|
const double normalized_y = (frame_time - min_val) / range;
|
||||||
const int x = graph_rect.left() + static_cast<int>(i * x_step);
|
const int x = graph_rect.left() + static_cast<int>(i * x_step);
|
||||||
const int y = graph_y + graph_height - static_cast<int>(normalized_y * graph_height);
|
const int y = graph_y + graph_height - static_cast<int>(normalized_y * graph_height);
|
||||||
|
if (i == 0) graph_path.moveTo(x, y); else graph_path.lineTo(x, y);
|
||||||
if (i == 0) {
|
|
||||||
graph_path.moveTo(x, y);
|
|
||||||
} else {
|
|
||||||
graph_path.lineTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the path for filling
|
|
||||||
graph_path.lineTo(graph_rect.right(), graph_rect.bottom());
|
graph_path.lineTo(graph_rect.right(), graph_rect.bottom());
|
||||||
graph_path.lineTo(graph_rect.left(), graph_rect.bottom());
|
graph_path.lineTo(graph_rect.left(), graph_rect.bottom());
|
||||||
graph_path.closeSubpath();
|
graph_path.closeSubpath();
|
||||||
|
|
||||||
painter.drawPath(graph_path);
|
painter.drawPath(graph_path);
|
||||||
|
|
||||||
// Draw statistics text
|
|
||||||
painter.setFont(small_font);
|
painter.setFont(small_font);
|
||||||
painter.setPen(text_color);
|
painter.setPen(text_color);
|
||||||
|
|
||||||
const QString min_text = QString::fromUtf8("Min: %1ms").arg(FormatFrameTime(min_frame_time));
|
const QString min_str = QStringLiteral("Min:%1ms").arg(FormatFrameTime(min_frame_time));
|
||||||
const QString avg_text = QString::fromUtf8("Avg: %1ms").arg(FormatFrameTime(avg_frame_time));
|
const QString avg_str = QStringLiteral("Avg:%2ms").arg(FormatFrameTime(avg_frame_time));
|
||||||
const QString max_text = QString::fromUtf8("Max: %1ms").arg(FormatFrameTime(max_frame_time));
|
const QString max_str = QStringLiteral("Max:%1ms").arg(FormatFrameTime(max_frame_time));
|
||||||
|
|
||||||
painter.drawText(graph_rect.left(), graph_y - 5, min_text);
|
// Combine into one line for measurement
|
||||||
painter.drawText(graph_rect.center().x() - painter.fontMetrics().horizontalAdvance(avg_text) / 2,
|
const QString full_line = QStringLiteral("%1 %2 %3").arg(min_str, avg_str, max_str);
|
||||||
graph_y - 5, avg_text);
|
int total_width = painter.fontMetrics().horizontalAdvance(full_line);
|
||||||
painter.drawText(graph_rect.right() - painter.fontMetrics().horizontalAdvance(max_text),
|
|
||||||
graph_y - 5, max_text);
|
// If there is enough room, flatten it across the top. Otherwise, stack it.
|
||||||
|
if (total_width < graph_width - 10) {
|
||||||
|
// Flat layout
|
||||||
|
painter.drawText(graph_rect.left(), graph_y - 6, full_line);
|
||||||
|
} else {
|
||||||
|
// Stacked layout (Fallback for small windows/High-DPI scaling)
|
||||||
|
painter.drawText(graph_rect.left(), graph_y - 18, QStringLiteral("%1 %2").arg(min_str, avg_str));
|
||||||
|
painter.drawText(graph_rect.left(), graph_y - 4, max_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::AddFrameTime(double frame_time_ms) {
|
void PerformanceOverlay::AddFrameTime(double frame_time_ms) {
|
||||||
frame_times.push_back(frame_time_ms);
|
frame_times.push_back(frame_time_ms);
|
||||||
|
if (frame_times.size() > MAX_FRAME_HISTORY) frame_times.pop_front();
|
||||||
// Keep only the last MAX_FRAME_HISTORY frames
|
|
||||||
if (frame_times.size() > MAX_FRAME_HISTORY) {
|
|
||||||
frame_times.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update statistics
|
|
||||||
if (!frame_times.empty()) {
|
if (!frame_times.empty()) {
|
||||||
min_frame_time = *std::min_element(frame_times.begin(), frame_times.end());
|
min_frame_time = *std::min_element(frame_times.begin(), frame_times.end());
|
||||||
max_frame_time = *std::max_element(frame_times.begin(), frame_times.end());
|
max_frame_time = *std::max_element(frame_times.begin(), frame_times.end());
|
||||||
@@ -523,54 +525,39 @@ void PerformanceOverlay::AddFrameTime(double frame_time_ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QColor PerformanceOverlay::GetFpsColor(double fps) const {
|
QColor PerformanceOverlay::GetFpsColor(double fps) const {
|
||||||
if (fps >= 55.0) {
|
if (fps >= 55.0) return QColor(76, 175, 80, 255);
|
||||||
return QColor(76, 175, 80, 255); // Material Design green - Good performance
|
if (fps >= 45.0) return QColor(255, 152, 0, 255);
|
||||||
} else if (fps >= 45.0) {
|
if (fps >= 30.0) return QColor(255, 87, 34, 255);
|
||||||
return QColor(255, 152, 0, 255); // Material Design orange - Moderate performance
|
return QColor(244, 67, 54, 255);
|
||||||
} else if (fps >= 30.0) {
|
|
||||||
return QColor(255, 87, 34, 255); // Material Design deep orange - Poor performance
|
|
||||||
} else {
|
|
||||||
return QColor(244, 67, 54, 255); // Material Design red - Very poor performance
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor PerformanceOverlay::GetTemperatureColor(float temperature) const {
|
QColor PerformanceOverlay::GetTemperatureColor(float temperature) const {
|
||||||
if (temperature > 70.0f) {
|
if (temperature > 85.0f) return QColor(244, 67, 54, 255);
|
||||||
return QColor(244, 67, 54, 255); // Material Design red
|
if (temperature > 75.0f) return QColor(255, 152, 0, 255);
|
||||||
} else if (temperature > 60.0f) {
|
return QColor(76, 175, 80, 255);
|
||||||
return QColor(255, 152, 0, 255); // Material Design orange
|
|
||||||
} else {
|
|
||||||
return QColor(76, 175, 80, 255); // Material Design green
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PerformanceOverlay::FormatFps(double fps) const {
|
QString PerformanceOverlay::FormatFps(double fps) const {
|
||||||
if (std::isnan(fps) || fps < 0.0) {
|
if (std::isnan(fps) || fps < 0.0) return QString::fromUtf8("0.0");
|
||||||
return QString::fromUtf8("0.0");
|
|
||||||
}
|
|
||||||
return QString::number(fps, 'f', 1);
|
return QString::number(fps, 'f', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PerformanceOverlay::FormatFrameTime(double frame_time_ms) const {
|
QString PerformanceOverlay::FormatFrameTime(double frame_time_ms) const {
|
||||||
if (std::isnan(frame_time_ms) || frame_time_ms < 0.0) {
|
if (std::isnan(frame_time_ms) || frame_time_ms < 0.0) return QString::fromUtf8("0.00");
|
||||||
return QString::fromUtf8("0.00");
|
|
||||||
}
|
|
||||||
return QString::number(frame_time_ms, 'f', 2);
|
return QString::number(frame_time_ms, 'f', 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceOverlay::UpdateTheme() {
|
void PerformanceOverlay::UpdateTheme() {
|
||||||
if (UISettings::IsDarkTheme()) {
|
if (UISettings::IsDarkTheme()) {
|
||||||
// Dark Theme Colors (your original values)
|
background_color = QColor(20, 20, 20, 200);
|
||||||
background_color = QColor(20, 20, 20, 200); // Slightly more opaque
|
|
||||||
border_color = QColor(60, 60, 60, 120);
|
border_color = QColor(60, 60, 60, 120);
|
||||||
text_color = QColor(220, 220, 220, 255);
|
text_color = QColor(220, 220, 220, 255);
|
||||||
graph_background_color = QColor(40, 40, 40, 100);
|
graph_background_color = QColor(40, 40, 40, 100);
|
||||||
} else {
|
} else {
|
||||||
// Light Theme Colors
|
|
||||||
background_color = QColor(245, 245, 245, 220);
|
background_color = QColor(245, 245, 245, 220);
|
||||||
border_color = QColor(200, 200, 200, 120);
|
border_color = QColor(200, 200, 200, 120);
|
||||||
text_color = QColor(20, 20, 20, 255);
|
text_color = QColor(20, 20, 20, 255);
|
||||||
graph_background_color = QColor(220, 220, 220, 100);
|
graph_background_color = QColor(220, 220, 220, 100);
|
||||||
}
|
}
|
||||||
update(); // Force a repaint with the new colors
|
update();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user