diff --git a/src/citron/util/vram_overlay.cpp b/src/citron/util/vram_overlay.cpp index fa1a43745..2e368609d 100644 --- a/src/citron/util/vram_overlay.cpp +++ b/src/citron/util/vram_overlay.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + #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(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(bytes) / (1024.0 * 1024.0 * 1024.0), 'f', 1) + QStringLiteral(" GB"); - } else if (bytes >= 1024 * 1024) { - return QString::number(static_cast(bytes) / (1024.0 * 1024.0), 'f', 1) + QStringLiteral(" MB"); - } else if (bytes >= 1024) { - return QString::number(static_cast(bytes) / 1024.0, 'f', 1) + QStringLiteral(" KB"); - } else { - return QString::number(bytes) + QStringLiteral(" B"); - } + if (bytes >= 1024 * 1024 * 1024) return QString::number(static_cast(bytes) / (1024.0 * 1024.0 * 1024.0), 'f', 1) + QStringLiteral(" GB"); + if (bytes >= 1024 * 1024) return QString::number(static_cast(bytes) / (1024.0 * 1024.0), 'f', 1) + QStringLiteral(" MB"); + if (bytes >= 1024) return QString::number(static_cast(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); -} \ No newline at end of file +}