mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-06-08 11:13:15 +02:00
[PATCH] print: fix black screen on macOS arm64 after PDF export
On macOS arm64 (Apple Silicon, Sequoia), exporting a PDF via QPrintPreviewWidget leaves a black screen with only the mouse cursor visible. Cmd+Tab restores the display; the exported PDF itself is correct and clickable cross-reference links work fine. Root cause ---------- requestPaint() is a slot connected to QPrintPreviewWidget::paintRequested. Inside this slot the code was calling painter.end() manually, then pdfConvertUriToGoTo(). On macOS arm64 the Qt5 paint cycle backed by Metal/CALayer is asynchronous: closing the QPainter from *within* the paintRequested slot interrupts the compositor before it has flushed the backing store. The window goes black and never repaints because the close() that follows immediately destroys it. On x86_64 / older macOS (raster/CoreGraphics backend) the paint cycle is synchronous, so the same code happened to work. Fix --- 1. Remove the manual painter.end() and pdfConvertUriToGoTo() call from requestPaint(). The QPainter is stack-allocated; it destructs normally when the slot returns, which is the correct moment to flush the PDF. 2. In print(), capture the output file name before m_preview->print(), then defer both pdfConvertUriToGoTo() and this->close() to the next event-loop iteration via QTimer::singleShot(0, ...). This gives the Metal compositor one full event-loop turn to finish compositing the backing store before the window is torn down. The fix is a no-op on all other platforms: QTimer::singleShot(0) posts an event that fires in the very next iteration, so there is no perceptible delay. Tested ------ - macOS Sequoia 15.x, Apple M-series, Qt 5.15.x (arm64): black screen gone - macOS 10.15 x86_64 VM, Qt 5.15.x: no regression - Linux/Debian Qt 5.15.x: no regression - PDF cross-reference links and GoTo/FitR destinations: unaffected Fixes: black screen after PDF export on macOS arm64
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QMap>
|
||||
#include <QTimer>
|
||||
#include <QVector>
|
||||
|
||||
/**
|
||||
@@ -495,13 +496,12 @@ void ProjectPrintWindow::requestPaint()
|
||||
printDiagram(diagram, ui->m_fit_in_page_cb->isChecked(), &painter, m_printer, diagramPageMap);
|
||||
}
|
||||
|
||||
if (pdfExport) {
|
||||
painter.end(); // flush & close the PDF file on disk
|
||||
// Convert URI link annotations into native internal GoTo/FitR actions:
|
||||
// cross-references then jump inside the document (no new viewer
|
||||
// instance) and frame the target element.
|
||||
pdfConvertUriToGoTo(m_printer->outputFileName());
|
||||
}
|
||||
// Note: do NOT call painter.end() or pdfConvertUriToGoTo() here.
|
||||
// We are inside the paintRequested slot: the QPrintPreviewWidget still
|
||||
// owns the paint cycle. On macOS arm64 (Metal/CALayer compositor),
|
||||
// closing the QPainter manually inside this slot leaves the backing
|
||||
// store in an undefined state, producing a black screen after export.
|
||||
// pdfConvertUriToGoTo() is deferred to print() via QTimer::singleShot(0).
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1218,9 +1218,29 @@ void ProjectPrintWindow::on_m_uncheck_all_clicked()
|
||||
|
||||
void ProjectPrintWindow::print()
|
||||
{
|
||||
m_preview->print();
|
||||
const bool isPdf = (m_printer->outputFormat() == QPrinter::PdfFormat);
|
||||
const QString pdfFile = isPdf ? m_printer->outputFileName() : QString();
|
||||
|
||||
m_preview->print(); // triggers requestPaint() synchronously; painter
|
||||
// is created/destroyed inside that call
|
||||
|
||||
savePageSetupForCurrentPrinter();
|
||||
this->close();
|
||||
|
||||
if (isPdf && !pdfFile.isEmpty()) {
|
||||
// Defer post-processing and window close to the next event-loop
|
||||
// iteration. This lets the macOS arm64 Metal compositor finish
|
||||
// compositing the backing store before the window is destroyed,
|
||||
// which prevents the black screen observed on Apple Silicon under
|
||||
// macOS Sequoia (QPrintPreviewWidget + CALayer timing issue).
|
||||
QTimer::singleShot(0, this, [this, pdfFile]() {
|
||||
// Convert URI link annotations into native internal GoTo/FitR
|
||||
// actions so cross-references jump inside the document.
|
||||
pdfConvertUriToGoTo(pdfFile);
|
||||
this->close();
|
||||
});
|
||||
} else {
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectPrintWindow::on_m_date_cb_userDateChanged(const QDate &date)
|
||||
|
||||
Reference in New Issue
Block a user