mirror of
https://git.citron-emu.org/citron/emulator
synced 2026-01-08 10:47:56 +00:00
Merge branch 'VRAM_Wayland_Fix' into 'main'
fix: Drag-to-move Issue (Wayland) See merge request citron/emulator!58
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
#include <numeric>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QWindow>
|
||||
|
||||
#include "citron/main.h"
|
||||
#include "citron/util/vram_overlay.h"
|
||||
#include "core/core.h"
|
||||
@@ -22,7 +25,7 @@
|
||||
#include "common/settings.h"
|
||||
|
||||
VramOverlay::VramOverlay(GMainWindow* parent)
|
||||
: QWidget(parent), main_window(parent) {
|
||||
: QWidget(parent), main_window(parent) {
|
||||
|
||||
// Set up the widget properties
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
@@ -35,16 +38,16 @@ VramOverlay::VramOverlay(GMainWindow* parent)
|
||||
warning_font = QFont(QString::fromUtf8("Segoe UI"), 10, QFont::Bold);
|
||||
|
||||
// Modern dark theme colors
|
||||
background_color = QColor(15, 15, 15, 220); // Dark background with good opacity
|
||||
border_color = QColor(45, 45, 45, 255); // Subtle border
|
||||
text_color = QColor(240, 240, 240, 255); // Clean white text
|
||||
secondary_text_color = QColor(180, 180, 180, 255); // Secondary text
|
||||
background_color = QColor(15, 15, 15, 220);
|
||||
border_color = QColor(45, 45, 45, 255);
|
||||
text_color = QColor(240, 240, 240, 255);
|
||||
secondary_text_color = QColor(180, 180, 180, 255);
|
||||
|
||||
// VRAM usage colors - modern palette
|
||||
vram_safe_color = QColor(76, 175, 80, 255); // Green
|
||||
vram_warning_color = QColor(255, 193, 7, 255); // Amber
|
||||
vram_danger_color = QColor(244, 67, 54, 255); // Red
|
||||
leak_warning_color = QColor(255, 152, 0, 255); // Orange
|
||||
vram_safe_color = QColor(76, 175, 80, 255);
|
||||
vram_warning_color = QColor(255, 193, 7, 255);
|
||||
vram_danger_color = QColor(244, 67, 54, 255);
|
||||
leak_warning_color = QColor(255, 152, 0, 255);
|
||||
|
||||
// Graph colors - clean and modern
|
||||
graph_background_color = QColor(25, 25, 25, 255);
|
||||
@@ -56,7 +59,7 @@ VramOverlay::VramOverlay(GMainWindow* parent)
|
||||
update_timer.setSingleShot(false);
|
||||
connect(&update_timer, &QTimer::timeout, this, &VramOverlay::UpdateVramStats);
|
||||
|
||||
// Set clean, compact size to match performance overlay
|
||||
// Set clean, compact size
|
||||
resize(250, 180);
|
||||
|
||||
// Position in top-right corner
|
||||
@@ -69,9 +72,7 @@ void VramOverlay::SetVisible(bool visible) {
|
||||
if (is_visible == visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_visible = visible;
|
||||
|
||||
if (visible) {
|
||||
show();
|
||||
update_timer.start(1000); // Update every 1 second
|
||||
@@ -82,35 +83,28 @@ void VramOverlay::SetVisible(bool visible) {
|
||||
}
|
||||
|
||||
void VramOverlay::UpdatePosition() {
|
||||
if (main_window) {
|
||||
QPoint main_window_pos = main_window->pos();
|
||||
if (main_window && !has_been_moved) {
|
||||
QPoint main_window_pos = main_window->mapToGlobal(QPoint(0,0));
|
||||
QSize main_window_size = main_window->size();
|
||||
|
||||
// Position in top-right corner with proper margin
|
||||
move(main_window_pos.x() + main_window_size.width() - width() - 15, main_window_pos.y() + 15);
|
||||
}
|
||||
}
|
||||
|
||||
void VramOverlay::paintEvent(QPaintEvent* event) {
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||
|
||||
// Draw rounded background
|
||||
QPainterPath background_path;
|
||||
background_path.addRoundedRect(rect(), corner_radius, corner_radius);
|
||||
painter.fillPath(background_path, background_color);
|
||||
|
||||
// Draw subtle border
|
||||
painter.setPen(QPen(border_color, border_width));
|
||||
painter.drawPath(background_path);
|
||||
|
||||
// Draw content sections
|
||||
DrawVramInfo(painter);
|
||||
DrawVramGraph(painter);
|
||||
|
||||
if (current_vram_data.leak_detected) {
|
||||
DrawLeakWarning(painter);
|
||||
}
|
||||
@@ -120,135 +114,94 @@ void VramOverlay::DrawVramInfo(QPainter& painter) {
|
||||
const int section_padding = 12;
|
||||
const int line_height = 14;
|
||||
const int section_spacing = 6;
|
||||
|
||||
int y_offset = section_padding + 4;
|
||||
|
||||
// Title
|
||||
painter.setFont(title_font);
|
||||
painter.setPen(text_color);
|
||||
painter.drawText(section_padding, y_offset, QString::fromUtf8("VRAM Monitor"));
|
||||
y_offset += line_height + section_spacing;
|
||||
|
||||
// Main VRAM usage with percentage
|
||||
painter.setFont(value_font);
|
||||
QColor vram_color = GetVramColor(current_vram_data.vram_percentage);
|
||||
painter.setPen(vram_color);
|
||||
|
||||
QString vram_text = QString::fromUtf8("%1 / %2 (%3%)")
|
||||
.arg(FormatMemorySize(current_vram_data.used_vram))
|
||||
.arg(FormatMemorySize(current_vram_data.total_vram))
|
||||
.arg(FormatPercentage(current_vram_data.vram_percentage));
|
||||
|
||||
.arg(FormatMemorySize(current_vram_data.used_vram))
|
||||
.arg(FormatMemorySize(current_vram_data.total_vram))
|
||||
.arg(FormatPercentage(current_vram_data.vram_percentage));
|
||||
painter.drawText(section_padding, y_offset, vram_text);
|
||||
y_offset += line_height + section_spacing;
|
||||
|
||||
// Memory breakdown - more compact
|
||||
painter.setFont(small_font);
|
||||
painter.setPen(secondary_text_color);
|
||||
|
||||
QString buffer_text = QString::fromUtf8("Buffers: %1").arg(FormatMemorySize(current_vram_data.buffer_memory));
|
||||
painter.drawText(section_padding, y_offset, buffer_text);
|
||||
y_offset += line_height - 1;
|
||||
|
||||
QString texture_text = QString::fromUtf8("Textures: %1").arg(FormatMemorySize(current_vram_data.texture_memory));
|
||||
painter.drawText(section_padding, y_offset, texture_text);
|
||||
y_offset += line_height - 1;
|
||||
|
||||
QString staging_text = QString::fromUtf8("Staging: %1").arg(FormatMemorySize(current_vram_data.staging_memory));
|
||||
painter.drawText(section_padding, y_offset, staging_text);
|
||||
y_offset += line_height + section_spacing;
|
||||
|
||||
// VRAM mode indicator
|
||||
painter.setPen(secondary_text_color);
|
||||
QString mode_text;
|
||||
switch (Settings::values.vram_usage_mode.GetValue()) {
|
||||
case Settings::VramUsageMode::Conservative:
|
||||
mode_text = QString::fromUtf8("Mode: Conservative");
|
||||
break;
|
||||
case Settings::VramUsageMode::Aggressive:
|
||||
mode_text = QString::fromUtf8("Mode: Aggressive");
|
||||
break;
|
||||
case Settings::VramUsageMode::HighEnd:
|
||||
mode_text = QString::fromUtf8("Mode: High-End GPU");
|
||||
break;
|
||||
case Settings::VramUsageMode::Insane:
|
||||
mode_text = QString::fromUtf8("Mode: Insane");
|
||||
painter.setPen(leak_warning_color);
|
||||
break;
|
||||
default:
|
||||
mode_text = QString::fromUtf8("Mode: Unknown");
|
||||
break;
|
||||
case Settings::VramUsageMode::Conservative: mode_text = QString::fromUtf8("Mode: Conservative"); break;
|
||||
case Settings::VramUsageMode::Aggressive: mode_text = QString::fromUtf8("Mode: Aggressive"); break;
|
||||
case Settings::VramUsageMode::HighEnd: mode_text = QString::fromUtf8("Mode: High-End GPU"); break;
|
||||
case Settings::VramUsageMode::Insane: mode_text = QString::fromUtf8("Mode: Insane"); painter.setPen(leak_warning_color); break;
|
||||
default: mode_text = QString::fromUtf8("Mode: Unknown"); break;
|
||||
}
|
||||
painter.drawText(section_padding, y_offset, mode_text);
|
||||
}
|
||||
|
||||
void VramOverlay::DrawVramGraph(QPainter& painter) {
|
||||
if (vram_usage_history.empty()) {
|
||||
return;
|
||||
}
|
||||
if (vram_usage_history.empty()) return;
|
||||
|
||||
const int graph_padding = 12;
|
||||
const int graph_y = height() - 60;
|
||||
const int graph_width = width() - (graph_padding * 2);
|
||||
const int local_graph_height = 40;
|
||||
|
||||
// Draw graph background with proper isolation
|
||||
QRect graph_rect(graph_padding, graph_y, graph_width, local_graph_height);
|
||||
QPainterPath graph_path;
|
||||
graph_path.addRoundedRect(graph_rect, 3, 3);
|
||||
painter.fillPath(graph_path, graph_background_color);
|
||||
|
||||
// Draw subtle border around graph area
|
||||
painter.setPen(QPen(graph_grid_color, 1));
|
||||
painter.drawPath(graph_path);
|
||||
|
||||
// Draw horizontal grid lines inside the graph
|
||||
painter.setPen(QPen(graph_grid_color, 1));
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
int y = graph_y + (i * local_graph_height / 4);
|
||||
painter.drawLine(graph_padding + 1, y, graph_padding + graph_width - 1, y);
|
||||
}
|
||||
|
||||
// Draw VRAM usage line
|
||||
if (vram_usage_history.size() > 1) {
|
||||
painter.setPen(QPen(graph_line_color, 2));
|
||||
|
||||
QPainterPath line_path;
|
||||
for (size_t i = 0; i < vram_usage_history.size(); ++i) {
|
||||
double x = graph_padding + 2 + (static_cast<double>(i) / (vram_usage_history.size() - 1)) * (graph_width - 4);
|
||||
double y = graph_y + local_graph_height - 2 - (vram_usage_history[i] / 100.0) * (local_graph_height - 4);
|
||||
|
||||
if (i == 0) {
|
||||
line_path.moveTo(x, y);
|
||||
} else {
|
||||
line_path.lineTo(x, y);
|
||||
}
|
||||
if (i == 0) line_path.moveTo(x, y); else line_path.lineTo(x, y);
|
||||
}
|
||||
painter.drawPath(line_path);
|
||||
|
||||
// Draw fill under the line
|
||||
line_path.lineTo(graph_padding + graph_width - 2, graph_y + local_graph_height - 2);
|
||||
line_path.lineTo(graph_padding + 2, graph_y + local_graph_height - 2);
|
||||
line_path.closeSubpath();
|
||||
|
||||
painter.fillPath(line_path, graph_fill_color);
|
||||
}
|
||||
}
|
||||
|
||||
void VramOverlay::DrawLeakWarning(QPainter& painter) {
|
||||
const int warning_y = height() - 20;
|
||||
|
||||
// Draw warning background
|
||||
QRect warning_rect(padding, warning_y, width() - (padding * 2), 16);
|
||||
QPainterPath warning_path;
|
||||
warning_path.addRoundedRect(warning_rect, 2, 2);
|
||||
painter.fillPath(warning_path, QColor(255, 152, 0, 80));
|
||||
|
||||
// Draw warning text
|
||||
painter.setFont(small_font);
|
||||
painter.setPen(leak_warning_color);
|
||||
QString warning_text = QString::fromUtf8("⚠ Leak: +%1 MB")
|
||||
.arg(current_vram_data.leak_increase_mb);
|
||||
QString warning_text = QString::fromUtf8("⚠ Leak: +%1 MB").arg(current_vram_data.leak_increase_mb);
|
||||
painter.drawText(warning_rect, Qt::AlignCenter, warning_text);
|
||||
}
|
||||
|
||||
@@ -257,32 +210,54 @@ void VramOverlay::resizeEvent(QResizeEvent* event) {
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
// LINUX-SPECIFIC IMPLEMENTATION (Wayland Fix)
|
||||
void VramOverlay::mousePressEvent(QMouseEvent* event) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (windowHandle()) {
|
||||
windowHandle()->startSystemMove();
|
||||
}
|
||||
}
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void VramOverlay::mouseMoveEvent(QMouseEvent* event) {
|
||||
// Intentionally blank, the system compositor handles the move.
|
||||
QWidget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
#else
|
||||
// ORIGINAL IMPLEMENTATION (For Windows, Android, etc.)
|
||||
void VramOverlay::mousePressEvent(QMouseEvent* event) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
is_dragging = true;
|
||||
drag_start_pos = event->globalPosition().toPoint();
|
||||
widget_start_pos = pos();
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void VramOverlay::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (is_dragging) {
|
||||
QPoint delta = event->globalPosition().toPoint() - drag_start_pos;
|
||||
move(widget_start_pos + delta);
|
||||
has_been_moved = true;
|
||||
}
|
||||
QWidget::mouseMoveEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VramOverlay::mouseReleaseEvent(QMouseEvent* event) {
|
||||
Q_UNUSED(event)
|
||||
is_dragging = false;
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
is_dragging = false;
|
||||
has_been_moved = true;
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void VramOverlay::UpdateVramStats() {
|
||||
if (!main_window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!main_window) return;
|
||||
try {
|
||||
current_vram_data.total_vram = main_window->GetTotalVram();
|
||||
current_vram_data.used_vram = main_window->GetUsedVram();
|
||||
@@ -298,10 +273,9 @@ void VramOverlay::UpdateVramStats() {
|
||||
current_vram_data.available_vram = 0;
|
||||
}
|
||||
|
||||
// Leak detection
|
||||
frame_counter++;
|
||||
if (frame_counter % 10 == 0) { // Check every 10 seconds
|
||||
if (current_vram_data.used_vram > last_vram_usage + (50 * 1024 * 1024)) { // 50MB increase
|
||||
if (frame_counter % 10 == 0) {
|
||||
if (last_vram_usage > 0 && current_vram_data.used_vram > last_vram_usage + (50 * 1024 * 1024)) {
|
||||
current_vram_data.leak_detected = true;
|
||||
current_vram_data.leak_increase_mb = (current_vram_data.used_vram - last_vram_usage) / (1024 * 1024);
|
||||
} else {
|
||||
@@ -310,39 +284,24 @@ void VramOverlay::UpdateVramStats() {
|
||||
}
|
||||
last_vram_usage = current_vram_data.used_vram;
|
||||
}
|
||||
|
||||
AddVramUsage(current_vram_data.vram_percentage);
|
||||
|
||||
if (!has_been_moved) {
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
update();
|
||||
} catch (...) {
|
||||
// Ignore exceptions during VRAM access
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
QColor VramOverlay::GetVramColor(double percentage) const {
|
||||
if (percentage < 70.0) {
|
||||
return vram_safe_color;
|
||||
} else if (percentage < 90.0) {
|
||||
return vram_warning_color;
|
||||
} else {
|
||||
return vram_danger_color;
|
||||
}
|
||||
if (percentage < 70.0) return vram_safe_color;
|
||||
if (percentage < 90.0) return vram_warning_color;
|
||||
return vram_danger_color;
|
||||
}
|
||||
|
||||
QString VramOverlay::FormatMemorySize(u64 bytes) const {
|
||||
if (bytes >= 1024 * 1024 * 1024) {
|
||||
return QString::number(static_cast<double>(bytes) / (1024.0 * 1024.0 * 1024.0), 'f', 1) + QStringLiteral(" GB");
|
||||
} else if (bytes >= 1024 * 1024) {
|
||||
return QString::number(static_cast<double>(bytes) / (1024.0 * 1024.0), 'f', 1) + QStringLiteral(" MB");
|
||||
} else if (bytes >= 1024) {
|
||||
return QString::number(static_cast<double>(bytes) / 1024.0, 'f', 1) + QStringLiteral(" KB");
|
||||
} else {
|
||||
return QString::number(bytes) + QStringLiteral(" B");
|
||||
}
|
||||
if (bytes >= 1024 * 1024 * 1024) return QString::number(static_cast<double>(bytes) / (1024.0 * 1024.0 * 1024.0), 'f', 1) + QStringLiteral(" GB");
|
||||
if (bytes >= 1024 * 1024) return QString::number(static_cast<double>(bytes) / (1024.0 * 1024.0), 'f', 1) + QStringLiteral(" MB");
|
||||
if (bytes >= 1024) return QString::number(static_cast<double>(bytes) / 1024.0, 'f', 1) + QStringLiteral(" KB");
|
||||
return QString::number(bytes) + QStringLiteral(" B");
|
||||
}
|
||||
|
||||
QString VramOverlay::FormatPercentage(double percentage) const {
|
||||
@@ -351,20 +310,15 @@ QString VramOverlay::FormatPercentage(double percentage) const {
|
||||
|
||||
void VramOverlay::AddVramUsage(double percentage) {
|
||||
vram_usage_history.push_back(percentage);
|
||||
|
||||
if (vram_usage_history.size() > MAX_VRAM_HISTORY) {
|
||||
vram_usage_history.pop_front();
|
||||
}
|
||||
|
||||
// Update min/max for scaling
|
||||
min_vram_usage = *std::min_element(vram_usage_history.begin(), vram_usage_history.end());
|
||||
max_vram_usage = *std::max_element(vram_usage_history.begin(), vram_usage_history.end());
|
||||
|
||||
// Add some padding to the range
|
||||
double range = max_vram_usage - min_vram_usage;
|
||||
if (range < 10.0) {
|
||||
range = 10.0;
|
||||
if (!vram_usage_history.empty()) {
|
||||
min_vram_usage = *std::min_element(vram_usage_history.begin(), vram_usage_history.end());
|
||||
max_vram_usage = *std::max_element(vram_usage_history.begin(), vram_usage_history.end());
|
||||
double range = max_vram_usage - min_vram_usage;
|
||||
if (range < 10.0) range = 10.0;
|
||||
min_vram_usage = std::max(0.0, min_vram_usage - range * 0.1);
|
||||
max_vram_usage = std::min(100.0, max_vram_usage + range * 0.1);
|
||||
}
|
||||
min_vram_usage = std::max(0.0, min_vram_usage - range * 0.1);
|
||||
max_vram_usage = std::min(100.0, max_vram_usage + range * 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user