Merge 5.14 into 5.14.2

Change-Id: Ib4b26bad47a850cde6253fb3422aae34b2cf622b
This commit is contained in:
Kari Oikarinen 2020-03-10 09:43:16 +02:00
commit d6d902a990
36 changed files with 300 additions and 158 deletions

View File

@ -50,8 +50,12 @@
#include "printview.h"
#ifndef QT_NO_PRINTER
#include <QPrinter>
#if defined(QT_PRINTSUPPORT_LIB)
# include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printer)
# include <QPrinter>
# endif
#endif
PrintView::PrintView()
@ -62,9 +66,11 @@ PrintView::PrintView()
void PrintView::print(QPrinter *printer)
{
#ifndef QT_NO_PRINTER
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
resize(printer->width(), printer->height());
render(printer);
#else
Q_UNUSED(printer)
#endif
}

View File

@ -638,7 +638,7 @@ QString encode_pos(int row, int col)
void SpreadSheet::print()
{
#if QT_CONFIG(printpreviewdialog)
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
QPrinter printer(QPrinter::ScreenResolution);
QPrintPreviewDialog dlg(&printer);
PrintView view;

View File

@ -197,7 +197,7 @@ void TextEdit::setupFileActions()
a->setPriority(QAction::LowPriority);
menu->addSeparator();
#ifndef QT_NO_PRINTER
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
a->setPriority(QAction::LowPriority);
@ -559,7 +559,7 @@ void TextEdit::filePrint()
void TextEdit::filePrintPreview()
{
#if QT_CONFIG(printpreviewdialog)
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer, this);
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview);
@ -569,17 +569,17 @@ void TextEdit::filePrintPreview()
void TextEdit::printPreview(QPrinter *printer)
{
#ifdef QT_NO_PRINTER
Q_UNUSED(printer);
#else
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
textEdit->print(printer);
#else
Q_UNUSED(printer)
#endif
}
void TextEdit::filePrintPdf()
{
#ifndef QT_NO_PRINTER
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
//! [0]
QFileDialog fileDialog(this, tr("Export PDF"));
fileDialog.setAcceptMode(QFileDialog::AcceptSave);

View File

@ -1,6 +1,8 @@
TEMPLATE = app
TARGET = notepad
QT += widgets
qtHaveModule(printsupport): QT += printsupport
requires(qtConfig(fontdialog))

View File

@ -69,10 +69,11 @@
#include <QStatusBar>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
#include <QPrintDialog>
#endif
# include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printdialog)
# include <QPrintDialog>
# endif
#endif
//! [0]

View File

@ -53,8 +53,12 @@
#include <QMainWindow>
#include <QImage>
#ifndef QT_NO_PRINTER
#include <QPrinter>
#if defined(QT_PRINTSUPPORT_LIB)
# include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printer)
# include <QPrinter>
# endif
#endif
QT_BEGIN_NAMESPACE
@ -100,7 +104,7 @@ private:
QScrollArea *scrollArea;
double scaleFactor = 1;
#ifndef QT_NO_PRINTER
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printer;
#endif

View File

@ -1949,8 +1949,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
example.)
If you are working with large amounts of filtering and have to invoke
invalidateFilter() repeatedly, using reset() may be more efficient,
depending on the implementation of your model. However, reset() returns the
invalidateFilter() repeatedly, using beginResetModel() / endResetModel() may
be more efficient, depending on the implementation of your model. However,
beginResetModel() / endResetModel() returns the
proxy model to its original state, losing selection information, and will
cause the proxy model to be repopulated.

View File

@ -589,7 +589,8 @@ QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry;
Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value);
Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value);
Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value);
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)

View File

@ -389,17 +389,12 @@ QObject *QFactoryLoader::instance(int index) const
QMutexLocker lock(&d->mutex);
if (index < d->libraryList.size()) {
QLibraryPrivate *library = d->libraryList.at(index);
if (library->instance || library->loadPlugin()) {
if (!library->inst)
library->inst = library->instance();
QObject *obj = library->inst.data();
if (obj) {
if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj;
}
if (QObject *obj = library->pluginInstance()) {
if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj;
}
return 0;
return nullptr;
}
index -= d->libraryList.size();
lock.unlock();

View File

@ -407,7 +407,7 @@ inline void QLibraryStore::cleanup()
QLibraryPrivate *lib = it.value();
if (lib->libraryRefCount.loadRelaxed() == 1) {
if (lib->libraryUnloadCount.loadRelaxed() > 0) {
Q_ASSERT(lib->pHnd);
Q_ASSERT(lib->pHnd.loadRelaxed());
lib->libraryUnloadCount.storeRelaxed(1);
#ifdef __GLIBC__
// glibc has a bug in unloading from global destructors
@ -498,8 +498,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
}
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
: fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
{
loadHintsInt.storeRelaxed(loadHints);
if (canonicalFileName.isEmpty())
@ -519,7 +518,7 @@ QLibraryPrivate::~QLibraryPrivate()
void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
{
// if the library is already loaded, we can't change the load hints
if (pHnd)
if (pHnd.loadRelaxed())
return;
loadHintsInt.storeRelaxed(lh);
@ -527,7 +526,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
{
if (!pHnd)
if (!pHnd.loadRelaxed())
return 0;
return resolve_sys(symbol);
}
@ -539,9 +538,36 @@ void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
mergeLoadHints(lh);
}
QObject *QLibraryPrivate::pluginInstance()
{
// first, check if the instance is cached and hasn't been deleted
QObject *obj = (QMutexLocker(&mutex), inst.data());
if (obj)
return obj;
// We need to call the plugin's factory function. Is that cached?
// skip increasing the reference count (why? -Thiago)
QtPluginInstanceFunction factory = instanceFactory.loadAcquire();
if (!factory)
factory = loadPlugin();
if (!factory)
return nullptr;
obj = factory();
// cache again
QMutexLocker locker(&mutex);
if (inst)
obj = inst;
else
inst = obj;
return obj;
}
bool QLibraryPrivate::load()
{
if (pHnd) {
if (pHnd.loadRelaxed()) {
libraryUnloadCount.ref();
return true;
}
@ -550,7 +576,9 @@ bool QLibraryPrivate::load()
Q_TRACE(QLibraryPrivate_load_entry, fileName);
mutex.lock();
bool ret = load_sys();
mutex.unlock();
if (qt_debug_component()) {
if (ret) {
qDebug() << "loaded library" << fileName;
@ -573,9 +601,10 @@ bool QLibraryPrivate::load()
bool QLibraryPrivate::unload(UnloadFlag flag)
{
if (!pHnd)
if (!pHnd.loadRelaxed())
return false;
if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
QMutexLocker locker(&mutex);
delete inst.data();
if (flag == NoUnloadSys || unload_sys()) {
if (qt_debug_component())
@ -584,12 +613,13 @@ bool QLibraryPrivate::unload(UnloadFlag flag)
//when the library is unloaded, we release the reference on it so that 'this'
//can get deleted
libraryRefCount.deref();
pHnd = 0;
instance = 0;
pHnd.storeRelaxed(nullptr);
instanceFactory.storeRelaxed(nullptr);
return true;
}
}
return (pHnd == 0);
return false;
}
void QLibraryPrivate::release()
@ -597,22 +627,23 @@ void QLibraryPrivate::release()
QLibraryStore::releaseLibrary(this);
}
bool QLibraryPrivate::loadPlugin()
QtPluginInstanceFunction QLibraryPrivate::loadPlugin()
{
if (instance) {
if (auto ptr = instanceFactory.loadAcquire()) {
libraryUnloadCount.ref();
return true;
return ptr;
}
if (pluginState == IsNotAPlugin)
return false;
return nullptr;
if (load()) {
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
return instance;
auto ptr = reinterpret_cast<QtPluginInstanceFunction>(resolve("qt_plugin_instance"));
instanceFactory.storeRelease(ptr); // two threads may store the same value
return ptr;
}
if (qt_debug_component())
qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
pluginState = IsNotAPlugin;
return false;
return nullptr;
}
/*!
@ -719,6 +750,7 @@ bool QLibraryPrivate::isPlugin()
void QLibraryPrivate::updatePluginState()
{
QMutexLocker locker(&mutex);
errorString.clear();
if (pluginState != MightBeAPlugin)
return;
@ -739,7 +771,7 @@ void QLibraryPrivate::updatePluginState()
}
#endif
if (!pHnd) {
if (!pHnd.loadRelaxed()) {
// scan for the plugin metadata without loading
success = findPatternUnloaded(fileName, this);
} else {
@ -803,7 +835,7 @@ bool QLibrary::load()
if (!d)
return false;
if (did_load)
return d->pHnd;
return d->pHnd.loadRelaxed();
did_load = true;
return d->load();
}
@ -839,7 +871,7 @@ bool QLibrary::unload()
*/
bool QLibrary::isLoaded() const
{
return d && d->pHnd;
return d && d->pHnd.loadRelaxed();
}
@ -950,8 +982,10 @@ void QLibrary::setFileName(const QString &fileName)
QString QLibrary::fileName() const
{
if (d)
if (d) {
QMutexLocker locker(&d->mutex);
return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
}
return QString();
}
@ -1092,7 +1126,12 @@ QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &versi
*/
QString QLibrary::errorString() const
{
return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
QString str;
if (d) {
QMutexLocker locker(&d->mutex);
str = d->errorString;
}
return str.isEmpty() ? tr("Unknown error") : str;
}
/*!

View File

@ -54,10 +54,10 @@
#include <QtCore/private/qglobal_p.h>
#include "QtCore/qlibrary.h"
#include "QtCore/qmutex.h"
#include "QtCore/qpointer.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qplugin.h"
#include "QtCore/qsharedpointer.h"
#ifdef Q_OS_WIN
# include "QtCore/qt_windows.h"
#endif
@ -72,21 +72,18 @@ class QLibraryStore;
class QLibraryPrivate
{
public:
#ifdef Q_OS_WIN
HINSTANCE
using Handle = HINSTANCE;
#else
void *
using Handle = void *;
#endif
pHnd;
enum UnloadFlag { UnloadSys, NoUnloadSys };
QString fileName, qualifiedFileName;
QString fullVersion;
const QString fileName;
const QString fullVersion;
bool load();
bool loadPlugin(); // loads and resolves instance
QtPluginInstanceFunction loadPlugin(); // loads and resolves instance
bool unload(UnloadFlag flag = UnloadSys);
void release();
QFunctionPointer resolve(const char *);
@ -94,17 +91,22 @@ public:
QLibrary::LoadHints loadHints() const
{ return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); }
void setLoadHints(QLibrary::LoadHints lh);
QObject *pluginInstance();
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = nullptr);
static QStringList suffixes_sys(const QString &fullVersion);
static QStringList prefixes_sys();
QPointer<QObject> inst;
QtPluginInstanceFunction instance;
QJsonObject metaData;
QAtomicPointer<std::remove_pointer<QtPluginInstanceFunction>::type> instanceFactory;
QAtomicPointer<std::remove_pointer<Handle>::type> pHnd;
// the mutex protects the fields below
QMutex mutex;
QPointer<QObject> inst; // used by QFactoryLoader
QJsonObject metaData;
QString errorString;
QString qualifiedFileName;
void updatePluginState();
bool isPlugin();

View File

@ -214,8 +214,9 @@ bool QLibraryPrivate::load_sys()
#endif
bool retry = true;
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
Handle hnd = nullptr;
for (int prefix = 0; retry && !hnd && prefix < prefixes.size(); prefix++) {
for (int suffix = 0; retry && !hnd && suffix < suffixes.size(); suffix++) {
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
continue;
if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
@ -232,7 +233,7 @@ bool QLibraryPrivate::load_sys()
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
}
pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
hnd = dlopen(QFile::encodeName(attempt), dlFlags);
#ifdef Q_OS_ANDROID
if (!pHnd) {
auto attemptFromBundle = attempt;
@ -248,7 +249,7 @@ bool QLibraryPrivate::load_sys()
}
#endif
if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
if (!hnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
// We only want to continue if dlopen failed due to that the shared library did not exist.
// However, we are only able to apply this check for absolute filenames (since they are
// not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
@ -259,7 +260,7 @@ bool QLibraryPrivate::load_sys()
}
#ifdef Q_OS_MAC
if (!pHnd) {
if (!hnd) {
QByteArray utf8Bundle = fileName.toUtf8();
QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true);
QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl);
@ -268,23 +269,24 @@ bool QLibraryPrivate::load_sys()
char executableFile[FILENAME_MAX];
CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
attempt = QString::fromUtf8(executableFile);
pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
hnd = dlopen(QFile::encodeName(attempt), dlFlags);
}
}
#endif
if (!pHnd) {
if (!hnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror());
}
if (pHnd) {
if (hnd) {
qualifiedFileName = attempt;
errorString.clear();
}
return (pHnd != 0);
pHnd.storeRelaxed(hnd);
return (hnd != nullptr);
}
bool QLibraryPrivate::unload_sys()
{
if (dlclose(pHnd)) {
if (dlclose(pHnd.loadAcquire())) {
#if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in
char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance
if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative"
@ -316,13 +318,7 @@ Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symb
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol));
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
QString::fromLatin1(symbol), fileName, qdlerror());
} else {
errorString.clear();
}
QFunctionPointer address = QFunctionPointer(dlsym(pHnd.loadAcquire(), symbol));
return address;
}

View File

@ -95,26 +95,27 @@ bool QLibraryPrivate::load_sys()
attempts.prepend(QDir::rootPath() + fileName);
#endif
Handle hnd = nullptr;
for (const QString &attempt : qAsConst(attempts)) {
#ifndef Q_OS_WINRT
pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
hnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
#else // Q_OS_WINRT
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (pHnd)
hnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (hnd)
qualifiedFileName = attempt;
#endif // !Q_OS_WINRT
// If we have a handle or the last error is something other than "unable
// to find the module", then bail out
if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
if (hnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
break;
}
#ifndef Q_OS_WINRT
SetErrorMode(oldmode);
#endif
if (!pHnd) {
if (!hnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(
QDir::toNativeSeparators(fileName), qt_error_string());
} else {
@ -123,7 +124,7 @@ bool QLibraryPrivate::load_sys()
#ifndef Q_OS_WINRT
wchar_t buffer[MAX_PATH];
::GetModuleFileName(pHnd, buffer, MAX_PATH);
::GetModuleFileName(hnd, buffer, MAX_PATH);
QString moduleFileName = QString::fromWCharArray(buffer);
moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
@ -138,19 +139,20 @@ bool QLibraryPrivate::load_sys()
HMODULE hmod;
bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN |
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast<const wchar_t *>(pHnd),
reinterpret_cast<const wchar_t *>(hnd),
&hmod);
Q_ASSERT(!ok || hmod == pHnd);
Q_ASSERT(!ok || hmod == hnd);
Q_UNUSED(ok);
}
#endif // !Q_OS_WINRT
}
return (pHnd != 0);
pHnd.storeRelaxed(hnd);
return (pHnd != nullptr);
}
bool QLibraryPrivate::unload_sys()
{
if (!FreeLibrary(pHnd)) {
if (!FreeLibrary(pHnd.loadAcquire())) {
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
QDir::toNativeSeparators(fileName), qt_error_string());
return false;
@ -161,13 +163,7 @@ bool QLibraryPrivate::unload_sys()
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{
FARPROC address = GetProcAddress(pHnd, symbol);
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
QString::fromLatin1(symbol), QDir::toNativeSeparators(fileName), qt_error_string());
} else {
errorString.clear();
}
FARPROC address = GetProcAddress(pHnd.loadAcquire(), symbol);
return QFunctionPointer(address);
}
QT_END_NAMESPACE

View File

@ -196,9 +196,7 @@ QObject *QPluginLoader::instance()
{
if (!isLoaded() && !load())
return 0;
if (!d->inst && d->instance)
d->inst = d->instance();
return d->inst.data();
return d->pluginInstance();
}
/*!
@ -233,7 +231,7 @@ bool QPluginLoader::load()
if (!d || d->fileName.isEmpty())
return false;
if (did_load)
return d->pHnd && d->instance;
return d->pHnd && d->instanceFactory.loadAcquire();
if (!d->isPlugin())
return false;
did_load = true;
@ -275,7 +273,7 @@ bool QPluginLoader::unload()
*/
bool QPluginLoader::isLoaded() const
{
return d && d->pHnd && d->instance;
return d && d->pHnd && d->instanceFactory.loadRelaxed();
}
#if defined(QT_SHARED)

View File

@ -115,7 +115,8 @@ struct ByteData
QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
};
Q_STATIC_ASSERT(std::is_pod<ByteData>::value);
Q_STATIC_ASSERT(std::is_trivial<ByteData>::value);
Q_STATIC_ASSERT(std::is_standard_layout<ByteData>::value);
} // namespace QtCbor
Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE);

View File

@ -1666,7 +1666,7 @@ void QWindow::setGeometry(const QRect &rect)
if (newScreen && isTopLevel())
nativeRect = QHighDpi::toNativePixels(rect, newScreen);
else
nativeRect = QHighDpi::toNativePixels(rect, this);
nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
d->platformWindow->setGeometry(nativeRect);
} else {
d->geometry = rect;
@ -1717,8 +1717,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
QRect QWindow::geometry() const
{
Q_D(const QWindow);
if (d->platformWindow)
return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this);
if (d->platformWindow) {
const auto nativeGeometry = d->platformWindow->geometry();
return isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, this)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, this);
}
return d->geometry;
}

View File

@ -296,14 +296,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window)
, newGeometry(newGeometry)
{
if (const QPlatformWindow *pw = window->handle())
requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window);
if (const QPlatformWindow *pw = window->handle()) {
const auto nativeGeometry = pw->QPlatformWindow::geometry();
requestedGeometry = window->isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, window)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
}
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{
Q_ASSERT(window);
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window));
const auto newRectDi = window->isTopLevel()
? QHighDpi::fromNativePixels(newRect, window)
: QHighDpi::fromNativeLocalPosition(newRect, window);
auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect);

View File

@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top();
blockFormat = list->item(list->count() - 1).blockFormat();
if (list)
blockFormat = list->item(list->count() - 1).blockFormat();
else
qWarning() << "attempted to insert into a list that no longer exists";
}
if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
}
if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat));
} else if (!m_listStack.isEmpty() && m_listItem) {
} else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
m_listStack.top()->add(m_cursor->block());
}
m_needsInsertList = false;

View File

@ -56,6 +56,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h>
#include <QtCore/qpointer.h>
#include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE
@ -113,7 +114,7 @@ private:
#endif
QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row
QStack<QTextList *> m_listStack;
QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont;
QPalette m_palette;

View File

@ -46,7 +46,11 @@
#include <QSocketNotifier>
#include <QLoggingCategory>
#ifdef Q_OS_FREEBSD
#include <dev/evdev/input.h>
#else
#include <linux/input.h>
#endif
QT_BEGIN_NAMESPACE

View File

@ -334,7 +334,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested;
requested.flags = window->flags();
requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
requested.geometry = window->isTopLevel()
? QHighDpi::toNativePixels(window->geometry(), window)
: QHighDpi::toNativeLocalPosition(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())

View File

@ -122,6 +122,7 @@ static const char *xcb_atomnames = {
"_NET_WM_STATE_MODAL\0"
"_NET_WM_STATE_STAYS_ON_TOP\0"
"_NET_WM_STATE_DEMANDS_ATTENTION\0"
"_NET_WM_STATE_HIDDEN\0"
"_NET_WM_USER_TIME\0"
"_NET_WM_USER_TIME_WINDOW\0"

View File

@ -123,6 +123,7 @@ public:
_NET_WM_STATE_MODAL,
_NET_WM_STATE_STAYS_ON_TOP,
_NET_WM_STATE_DEMANDS_ATTENTION,
_NET_WM_STATE_HIDDEN,
_NET_WM_USER_TIME,
_NET_WM_USER_TIME_WINDOW,

View File

@ -276,7 +276,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen);
QRect rect = parent()
? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
: QHighDpi::toNativePixels(window()->geometry(), platformScreen);
if (type == Qt::Desktop) {
m_window = platformScreen->root();
@ -905,6 +907,8 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
result |= NetWmStateStaysOnTop;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
result |= NetWmStateHidden;
} else {
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
}
@ -1076,6 +1080,9 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
states |= NetWmStateBelow;
}
if (window()->windowStates() & Qt::WindowMinimized)
states |= NetWmStateHidden;
if (window()->windowStates() & Qt::WindowFullScreen)
states |= NetWmStateFullScreen;
@ -1109,6 +1116,8 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_HIDDEN));
if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
@ -2217,10 +2226,16 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|| (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
}
}
if (m_minimized)
newState = Qt::WindowMinimized;
const NetWmStates states = netWmStates();
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
// not be visible on the screen if its desktop/viewport were active and its coordinates were
// within the screen bounds. The canonical example is that minimized windows should be in
// the _NET_WM_STATE_HIDDEN state.
if (m_minimized && (!connection()->wmSupport()->isSupportedByWM(NetWmStateHidden)
|| states.testFlag(NetWmStateHidden)))
newState = Qt::WindowMinimized;
if (states & NetWmStateFullScreen)
newState |= Qt::WindowFullScreen;
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))

View File

@ -68,7 +68,8 @@ public:
NetWmStateMaximizedVert = 0x10,
NetWmStateModal = 0x20,
NetWmStateStaysOnTop = 0x40,
NetWmStateDemandsAttention = 0x80
NetWmStateDemandsAttention = 0x80,
NetWmStateHidden = 0x100
};
Q_DECLARE_FLAGS(NetWmStates, NetWmState)

View File

@ -546,12 +546,19 @@ void WriteInitialization::acceptUI(DomUI *node)
m_output << m_option.indent << language::endFunctionDefinition("setupUi");
if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) {
// Mark varName as unused to avoid compiler warnings.
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("(void)");
m_refreshInitialization += varName ;
m_refreshInitialization += language::eol;
if (!m_mainFormUsedInRetranslateUi) {
if (language::language() == Language::Cpp) {
// Mark varName as unused to avoid compiler warnings.
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("(void)");
m_refreshInitialization += varName ;
m_refreshInitialization += language::eol;
} else if (language::language() == Language::Python) {
// output a 'pass' to have an empty function
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("pass");
m_refreshInitialization += language::eol;
}
}
m_output << m_option.indent

View File

@ -62,6 +62,7 @@
#include <qshareddata.h>
#include <qdebug.h>
#include <stdio.h>
#include <limits>
QT_BEGIN_NAMESPACE
@ -4866,7 +4867,7 @@ void QDomElement::setAttribute(const QString& name, float value)
if (!impl)
return;
QString x;
x.setNum(value);
x.setNum(value, 'g', 8);
IMPL->setAttribute(name, x);
}
@ -4880,7 +4881,7 @@ void QDomElement::setAttribute(const QString& name, double value)
if (!impl)
return;
QString x;
x.setNum(value);
x.setNum(value, 'g', 17);
IMPL->setAttribute(name, x);
}
@ -5049,7 +5050,7 @@ void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, doub
if (!impl)
return;
QString x;
x.setNum(value);
x.setNum(value, 'g', 17);
IMPL->setAttributeNS(nsURI, qName, x);
}

View File

@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono()
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
/*
Call QTest::qSleep, and return true if the time actually slept is
within \a deviationPercent percent of the requested sleep time.
Otherwise, return false, in which case the test should to abort.
*/
auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool {
auto before = steady_clock::now();
QTest::qSleep(ms);
auto after = steady_clock::now();
auto diff = duration_cast<milliseconds>(after - before).count();
bool inRange = qAbs(diff - ms) < ms * deviationPercent/100.0;
if (!inRange)
qWarning() << "sleeping" << diff << "instead of" << ms << inRange;
return inRange;
};
auto steady_before = steady_clock::now();
auto system_before = system_clock::now();
QTest::qSleep(minResolution);
if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto now = QDeadlineTimer::current(timerType);
QTest::qSleep(minResolution);
auto steady_reference = steady_clock::now();
auto system_reference = system_clock::now();
if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto sampling_start = steady_clock::now();
auto steady_deadline = now.deadline<steady_clock>();
@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono()
}
{
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
auto reference = duration_cast<milliseconds>(steady_after - steady_reference).count();
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_after(steady_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(steady_deadline - steady_before);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
reference = duration_cast<milliseconds>(steady_reference - steady_before).count();
diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_before(steady_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
}
{
auto diff = duration_cast<milliseconds>(system_after - system_deadline);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
QDeadlineTimer dt_after(system_after, timerType);
auto reference = duration_cast<milliseconds>(system_after - system_reference).count();
auto diff = duration_cast<milliseconds>(system_after - system_deadline).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(system_deadline - system_before);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
QDeadlineTimer dt_before(system_before, timerType);
reference = duration_cast<milliseconds>(system_reference - system_before).count();
diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());

View File

@ -1,3 +0,0 @@
[elapsed]
macos
windows-10

View File

@ -368,7 +368,7 @@ void tst_QLibrary::errorString_data()
QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*");
QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error");
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Cannot resolve symbol \"nosuchsymbol\" in \\S+: .*");
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Unknown error");
QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error");
#ifdef Q_OS_WIN

View File

@ -0,0 +1,5 @@
<t><EFBFBD>
* <20>
<09>
* <20>

View File

@ -0,0 +1 @@
| --:| <?`?><?|`

View File

@ -5,5 +5,7 @@ SOURCES += tst_qtextmarkdownimporter.cpp
TESTDATA += \
data/thematicBreaks.md \
data/headingBulletsContinuations.md \
data/fuzz20450.md \
data/fuzz20580.md \
DEFINES += SRCDIR=\\\"$$PWD\\\"

View File

@ -57,6 +57,8 @@ private slots:
void lists();
void avoidBlankLineAtBeginning_data();
void avoidBlankLineAtBeginning();
void pathological_data();
void pathological();
};
void tst_QTextMarkdownImporter::headingBulletsContinuations()
@ -256,5 +258,27 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning() // QTBUG-81060
QCOMPARE(i, expectedNumberOfParagraphs);
}
void tst_QTextMarkdownImporter::pathological_data()
{
QTest::addColumn<QString>("warning");
QTest::newRow("fuzz20450") << "attempted to insert into a list that no longer exists";
QTest::newRow("fuzz20580") << "";
}
void tst_QTextMarkdownImporter::pathological() // avoid crashing on crazy input
{
QFETCH(QString, warning);
QString filename = QLatin1String("data/") + QTest::currentDataTag() + QLatin1String(".md");
QFile f(QFINDTESTDATA(filename));
QVERIFY(f.open(QFile::ReadOnly));
#ifdef QT_NO_DEBUG
Q_UNUSED(warning)
#else
if (!warning.isEmpty())
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
#endif
QTextDocument().setMarkdown(f.readAll());
}
QTEST_MAIN(tst_QTextMarkdownImporter)
#include "tst_qtextmarkdownimporter.moc"

View File

@ -2,7 +2,3 @@
# QTBUG-66345
opensuse-42.3
ubuntu-16.04
[setWindowState]
ubuntu-18.04
rhel-7.6

View File

@ -38,6 +38,7 @@
#include <QtTest/QtTest>
#include <QtXml>
#include <QVariant>
#include <cmath>
QT_FORWARD_DECLARE_CLASS(QDomDocument)
QT_FORWARD_DECLARE_CLASS(QDomNode)
@ -408,7 +409,9 @@ void tst_QDom::setGetAttributes()
const int intVal = std::numeric_limits<int>::min();
const uint uintVal = std::numeric_limits<uint>::max();
const float floatVal = 0.1234f;
const double doubleVal = 0.1234;
const double doubleVal1 = 1./6.;
const double doubleVal2 = std::nextafter(doubleVal1, 1.);
const double doubleVal3 = std::nextafter(doubleVal2, 1.);
rootNode.setAttribute("qstringVal", qstringVal);
rootNode.setAttribute("qlonglongVal", qlonglongVal);
@ -416,7 +419,9 @@ void tst_QDom::setGetAttributes()
rootNode.setAttribute("intVal", intVal);
rootNode.setAttribute("uintVal", uintVal);
rootNode.setAttribute("floatVal", floatVal);
rootNode.setAttribute("doubleVal", doubleVal);
rootNode.setAttribute("doubleVal1", doubleVal1);
rootNode.setAttribute("doubleVal2", doubleVal2);
rootNode.setAttribute("doubleVal3", doubleVal3);
QDomElement nsNode = doc.createElement("NS");
rootNode.appendChild(nsNode);
@ -426,7 +431,9 @@ void tst_QDom::setGetAttributes()
nsNode.setAttributeNS("namespace", "intVal", intVal);
nsNode.setAttributeNS("namespace", "uintVal", uintVal);
nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm
nsNode.setAttributeNS("namespace", "doubleVal", doubleVal);
nsNode.setAttributeNS("namespace", "doubleVal1", doubleVal1);
nsNode.setAttributeNS("namespace", "doubleVal2", doubleVal2);
nsNode.setAttributeNS("namespace", "doubleVal3", doubleVal3);
bool bOk;
QCOMPARE(rootNode.attribute("qstringVal"), qstringVal);
@ -440,8 +447,10 @@ void tst_QDom::setGetAttributes()
QVERIFY(bOk);
QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal);
QVERIFY(bOk);
QCOMPARE(rootNode.attribute("doubleVal").toDouble(&bOk), doubleVal);
QVERIFY(bOk);
QVERIFY(rootNode.attribute("doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
QVERIFY(rootNode.attribute("doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
QVERIFY(rootNode.attribute("doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal);
QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal);
@ -454,8 +463,9 @@ void tst_QDom::setGetAttributes()
QVERIFY(bOk);
QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal);
QVERIFY(bOk);
QCOMPARE(nsNode.attributeNS("namespace", "doubleVal").toDouble(&bOk), doubleVal);
QVERIFY(bOk);
QVERIFY(nsNode.attributeNS("namespace", "doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
QVERIFY(nsNode.attributeNS("namespace", "doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
QVERIFY(nsNode.attributeNS("namespace", "doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
QLocale::setDefault(oldLocale);
}