Merge "Merge remote-tracking branch 'origin/5.12' into 5.13" into refs/staging/5.13
This commit is contained in:
commit
55b4641962
@ -17,7 +17,7 @@ QMAKE_EXTENSION_SHLIB = dylib
|
||||
QMAKE_EXTENSIONS_AUX_SHLIB = tbd
|
||||
QMAKE_LIBDIR =
|
||||
|
||||
# sdk.prf will prefix the proper SDK sysroot
|
||||
# qtConfLibrary_openglMakeSpec will prefix the proper SDK sysroot
|
||||
QMAKE_INCDIR_OPENGL = \
|
||||
/System/Library/Frameworks/OpenGL.framework/Headers \
|
||||
/System/Library/Frameworks/AGL.framework/Headers/
|
||||
|
@ -33,10 +33,6 @@ QMAKE_MAC_SDK_PATH = $$xcodeSDKInfo(Path)
|
||||
QMAKE_MAC_SDK_PLATFORM_PATH = $$xcodeSDKInfo(PlatformPath)
|
||||
QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion)
|
||||
|
||||
sysrootified =
|
||||
for(val, QMAKE_INCDIR_OPENGL): sysrootified += $${QMAKE_MAC_SDK_PATH}$$val
|
||||
QMAKE_INCDIR_OPENGL = $$sysrootified
|
||||
|
||||
QMAKESPEC_NAME = $$basename(QMAKESPEC)
|
||||
|
||||
# Resolve SDK version of various tools
|
||||
|
@ -1454,6 +1454,7 @@ void VcprojGenerator::initTranslationFiles()
|
||||
vcProject.TranslationFiles.Guid = _GUIDTranslationFiles;
|
||||
|
||||
vcProject.TranslationFiles.addFiles(project->values("TRANSLATIONS"));
|
||||
vcProject.TranslationFiles.addFiles(project->values("EXTRA_TRANSLATIONS"));
|
||||
|
||||
vcProject.TranslationFiles.Project = this;
|
||||
vcProject.TranslationFiles.Config = &(vcProject.Configuration);
|
||||
@ -1576,7 +1577,7 @@ void VcprojGenerator::initExtraCompilerOutputs()
|
||||
const ProStringList &tmp_in = project->values(project->first(ProKey(*it + ".input")).toKey());
|
||||
for (int i = 0; i < tmp_in.count(); ++i) {
|
||||
const QString &filename = tmp_in.at(i).toQString();
|
||||
if (extraCompilerSources.contains(filename))
|
||||
if (extraCompilerSources.contains(filename) && !otherFiltersContain(filename))
|
||||
extraCompile.addFile(Option::fixPathToTargetOS(
|
||||
replaceExtraCompilerVariables(filename, tmp_out, QString(), NoShell), false));
|
||||
}
|
||||
@ -1592,7 +1593,7 @@ void VcprojGenerator::initExtraCompilerOutputs()
|
||||
const ProStringList &tmp_in = project->values(inputVar.toKey());
|
||||
for (int i = 0; i < tmp_in.count(); ++i) {
|
||||
const QString &filename = tmp_in.at(i).toQString();
|
||||
if (extraCompilerSources.contains(filename))
|
||||
if (extraCompilerSources.contains(filename) && !otherFiltersContain(filename))
|
||||
extraCompile.addFile(Option::fixPathToTargetOS(
|
||||
replaceExtraCompilerVariables(filename, QString(), QString(), NoShell), false));
|
||||
}
|
||||
@ -1606,6 +1607,28 @@ void VcprojGenerator::initExtraCompilerOutputs()
|
||||
}
|
||||
}
|
||||
|
||||
bool VcprojGenerator::otherFiltersContain(const QString &fileName) const
|
||||
{
|
||||
auto filterFileMatches = [&fileName] (const VCFilterFile &ff)
|
||||
{
|
||||
return ff.file == fileName;
|
||||
};
|
||||
for (const VCFilter *filter : { &vcProject.RootFiles,
|
||||
&vcProject.SourceFiles,
|
||||
&vcProject.HeaderFiles,
|
||||
&vcProject.GeneratedFiles,
|
||||
&vcProject.LexYaccFiles,
|
||||
&vcProject.TranslationFiles,
|
||||
&vcProject.FormFiles,
|
||||
&vcProject.ResourceFiles,
|
||||
&vcProject.DeploymentFiles,
|
||||
&vcProject.DistributionFiles}) {
|
||||
if (std::any_of(filter->Files.cbegin(), filter->Files.cend(), filterFileMatches))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -132,6 +132,7 @@ private:
|
||||
ProString firstInputFileName(const ProString &extraCompilerName) const;
|
||||
QString firstExpandedOutputFileName(const ProString &extraCompilerName);
|
||||
void createCustomBuildToolFakeFile(const QString &cbtFilePath, const QString &realOutFilePath);
|
||||
bool otherFiltersContain(const QString &fileName) const;
|
||||
friend class VCFilter;
|
||||
};
|
||||
|
||||
|
@ -2676,9 +2676,9 @@ QStringList QCoreApplication::libraryPaths()
|
||||
QStringList *app_libpaths = new QStringList;
|
||||
coreappdata()->app_libpaths.reset(app_libpaths);
|
||||
|
||||
const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
|
||||
QString libPathEnv = qEnvironmentVariable("QT_PLUGIN_PATH");
|
||||
if (!libPathEnv.isEmpty()) {
|
||||
QStringList paths = QFile::decodeName(libPathEnv).split(QDir::listSeparator(), QString::SkipEmptyParts);
|
||||
QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts);
|
||||
for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
|
||||
QString canonicalPath = QDir(*it).canonicalPath();
|
||||
if (!canonicalPath.isEmpty()
|
||||
|
@ -95,7 +95,7 @@ class QEventDispatcherWin32Private;
|
||||
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
|
||||
|
||||
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
|
||||
: threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0),
|
||||
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
|
||||
getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0),
|
||||
wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
|
||||
{
|
||||
@ -552,7 +552,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
wakeUp(); // trigger a call to sendPostedEvents()
|
||||
}
|
||||
|
||||
d->interrupt = false;
|
||||
d->interrupt.store(false);
|
||||
emit awake();
|
||||
|
||||
bool canWait;
|
||||
@ -568,7 +568,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
pHandles = &d->winEventNotifierActivatedEvent;
|
||||
}
|
||||
QVarLengthArray<MSG> processedTimers;
|
||||
while (!d->interrupt) {
|
||||
while (!d->interrupt.load()) {
|
||||
MSG msg;
|
||||
bool haveMessage;
|
||||
|
||||
@ -649,7 +649,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
|
||||
// still nothing - wait for message or signalled objects
|
||||
canWait = (!retVal
|
||||
&& !d->interrupt
|
||||
&& !d->interrupt.load()
|
||||
&& (flags & QEventLoop::WaitForMoreEvents));
|
||||
if (canWait) {
|
||||
emit aboutToBlock();
|
||||
@ -1022,7 +1022,7 @@ void QEventDispatcherWin32::wakeUp()
|
||||
void QEventDispatcherWin32::interrupt()
|
||||
{
|
||||
Q_D(QEventDispatcherWin32);
|
||||
d->interrupt = true;
|
||||
d->interrupt.store(true);
|
||||
wakeUp();
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,7 @@ public:
|
||||
|
||||
DWORD threadId;
|
||||
|
||||
bool interrupt;
|
||||
bool closingDown;
|
||||
QAtomicInt interrupt;
|
||||
|
||||
// internal window handle used for socketnotifiers/timers/etc
|
||||
HWND internalHwnd;
|
||||
@ -193,9 +192,11 @@ public:
|
||||
void postActivateSocketNotifiers();
|
||||
void doWsaAsyncSelect(int socket, long event);
|
||||
|
||||
bool closingDown = false;
|
||||
|
||||
bool winEventNotifierListModified = false;
|
||||
HANDLE winEventNotifierActivatedEvent;
|
||||
QList<QWinEventNotifier *> winEventNotifierList;
|
||||
bool winEventNotifierListModified = false;
|
||||
void activateEventNotifier(QWinEventNotifier * wen);
|
||||
|
||||
QList<MSG> queuedUserInputEvents;
|
||||
|
@ -2175,8 +2175,10 @@ void QObject::removeEventFilter(QObject *obj)
|
||||
|
||||
Note that entering and leaving a new event loop (e.g., by opening a modal
|
||||
dialog) will \e not perform the deferred deletion; for the object to be
|
||||
deleted, the control must return to the event loop from which
|
||||
deleteLater() was called.
|
||||
deleted, the control must return to the event loop from which deleteLater()
|
||||
was called. This does not apply to objects deleted while a previous, nested
|
||||
event loop was still running: the Qt event loop will delete those objects
|
||||
as soon as the new nested event loop starts.
|
||||
|
||||
\b{Note:} It is safe to call this function more than once; when the
|
||||
first deferred deletion event is delivered, any pending events for the
|
||||
|
@ -448,7 +448,7 @@
|
||||
],
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "gl", "condition": "!config.darwin" },
|
||||
{ "type": "makeSpec", "spec": "OPENGL" }
|
||||
{ "type": "openglMakeSpec" }
|
||||
]
|
||||
},
|
||||
"opengl_es2": {
|
||||
|
@ -15,6 +15,17 @@ defineTest(qtConfLibrary_freetype) {
|
||||
return(true)
|
||||
}
|
||||
|
||||
defineTest(qtConfLibrary_openglMakeSpec) {
|
||||
darwin:sdk {
|
||||
sysrootified =
|
||||
for(val, QMAKE_INCDIR_OPENGL): sysrootified += $${QMAKE_MAC_SDK_PATH}$$val
|
||||
QMAKE_INCDIR_OPENGL = $$sysrootified
|
||||
}
|
||||
$${1}.spec = OPENGL
|
||||
!qtConfLibrary_makeSpec($$1, $$2): return(false)
|
||||
return(true)
|
||||
}
|
||||
|
||||
# Check for Direct X shader compiler 'fxc'.
|
||||
# Up to Direct X SDK June 2010 and for MinGW, this is pointed to by the
|
||||
# DXSDK_DIR variable. Starting with Windows Kit 8, it is included in
|
||||
|
@ -695,13 +695,29 @@ QList<QTouchEvent::TouchPoint>
|
||||
}
|
||||
|
||||
if (states == Qt::TouchPointReleased) {
|
||||
g_nextPointId = 1;
|
||||
g_pointIdMap->clear();
|
||||
// All points on deviceId have been released.
|
||||
// Remove all points associated with that device from g_pointIdMap.
|
||||
// (On other devices, some touchpoints might still be pressed.
|
||||
// But this function is only called with points from one device at a time.)
|
||||
for (auto it = g_pointIdMap->begin(); it != g_pointIdMap->end();) {
|
||||
if (it.key() >> 32 == quint64(deviceId))
|
||||
it = g_pointIdMap->erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (g_pointIdMap->isEmpty())
|
||||
g_nextPointId = 1;
|
||||
}
|
||||
|
||||
return touchPoints;
|
||||
}
|
||||
|
||||
void QWindowSystemInterfacePrivate::clearPointIdMap()
|
||||
{
|
||||
g_pointIdMap->clear();
|
||||
g_nextPointId = 1;
|
||||
}
|
||||
|
||||
QList<QWindowSystemInterface::TouchPoint>
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
|
||||
const QWindow *window)
|
||||
|
@ -537,6 +537,7 @@ public:
|
||||
static QList<QWindowSystemInterface::TouchPoint>
|
||||
toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
|
||||
const QWindow *window);
|
||||
static void clearPointIdMap();
|
||||
|
||||
static void installWindowSystemEventHandler(QWindowSystemEventHandler *handler);
|
||||
static void removeWindowSystemEventhandler(QWindowSystemEventHandler *handler);
|
||||
|
@ -297,7 +297,7 @@ void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
|
||||
QSyntaxHighlighter::QSyntaxHighlighter(QObject *parent)
|
||||
: QObject(*new QSyntaxHighlighterPrivate, parent)
|
||||
{
|
||||
if (parent->inherits("QTextEdit")) {
|
||||
if (parent && parent->inherits("QTextEdit")) {
|
||||
QTextDocument *doc = parent->property("document").value<QTextDocument *>();
|
||||
if (doc)
|
||||
setDocument(doc);
|
||||
|
@ -62,9 +62,6 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
|
||||
QEglFSScreen::~QEglFSScreen()
|
||||
{
|
||||
delete m_cursor;
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositor::destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
QRect QEglFSScreen::geometry() const
|
||||
|
@ -62,6 +62,7 @@ QEglFSWindow::QEglFSWindow(QWindow *w)
|
||||
: QPlatformWindow(w),
|
||||
#ifndef QT_NO_OPENGL
|
||||
m_backingStore(0),
|
||||
m_rasterCompositingContext(0),
|
||||
#endif
|
||||
m_raster(false),
|
||||
m_winId(0),
|
||||
@ -144,18 +145,18 @@ void QEglFSWindow::create()
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
if (isRaster()) {
|
||||
QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
|
||||
context->setShareContext(qt_gl_global_share_context());
|
||||
context->setFormat(m_format);
|
||||
context->setScreen(window()->screen());
|
||||
if (Q_UNLIKELY(!context->create()))
|
||||
m_rasterCompositingContext = new QOpenGLContext;
|
||||
m_rasterCompositingContext->setShareContext(qt_gl_global_share_context());
|
||||
m_rasterCompositingContext->setFormat(m_format);
|
||||
m_rasterCompositingContext->setScreen(window()->screen());
|
||||
if (Q_UNLIKELY(!m_rasterCompositingContext->create()))
|
||||
qFatal("EGLFS: Failed to create compositing context");
|
||||
compositor->setTarget(context, window(), screen->rawGeometry());
|
||||
compositor->setTarget(m_rasterCompositingContext, window(), screen->rawGeometry());
|
||||
compositor->setRotation(qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"));
|
||||
// If there is a "root" window into which raster and QOpenGLWidget content is
|
||||
// composited, all other contexts must share with its context.
|
||||
if (!qt_gl_global_share_context()) {
|
||||
qt_gl_set_global_share_context(context);
|
||||
qt_gl_set_global_share_context(m_rasterCompositingContext);
|
||||
// What we set up here is in effect equivalent to the application setting
|
||||
// AA_ShareOpenGLContexts. Set the attribute to be fully consistent.
|
||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||
@ -166,6 +167,10 @@ void QEglFSWindow::create()
|
||||
|
||||
void QEglFSWindow::destroy()
|
||||
{
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositor::instance()->removeWindow(this);
|
||||
#endif
|
||||
|
||||
QEglFSScreen *screen = this->screen();
|
||||
if (m_flags.testFlag(HasNativeWindow)) {
|
||||
#ifndef QT_NO_OPENGL
|
||||
@ -177,12 +182,14 @@ void QEglFSWindow::destroy()
|
||||
screen->setPrimarySurface(EGL_NO_SURFACE);
|
||||
|
||||
invalidateSurface();
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositor::destroy();
|
||||
delete m_rasterCompositingContext;
|
||||
#endif
|
||||
}
|
||||
|
||||
m_flags = 0;
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositor::instance()->removeWindow(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QEglFSWindow::invalidateSurface()
|
||||
|
@ -116,6 +116,7 @@ public:
|
||||
protected:
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositorBackingStore *m_backingStore;
|
||||
QOpenGLContext *m_rasterCompositingContext;
|
||||
#endif
|
||||
bool m_raster;
|
||||
WId m_winId;
|
||||
|
@ -1,6 +1,6 @@
|
||||
TARGET = qhaiku
|
||||
|
||||
QT += core-private gui-private eventdistpatcher_support-private
|
||||
QT += core-private gui-private eventdispatcher_support-private
|
||||
|
||||
SOURCES = \
|
||||
main.cpp \
|
||||
|
@ -1099,6 +1099,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
||||
return false;
|
||||
case QtWindows::ClipboardEvent:
|
||||
return false;
|
||||
case QtWindows::CursorEvent: // Sent to windows that do not have capture (see QTBUG-58590).
|
||||
if (QWindowsCursor::hasOverrideCursor()) {
|
||||
QWindowsCursor::enforceOverrideCursor();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case QtWindows::UnknownEvent:
|
||||
return false;
|
||||
case QtWindows::AccessibleObjectFromWindowRequest:
|
||||
|
@ -1912,7 +1912,7 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
|
||||
bool click = (index == d->pressedIndex && index.isValid());
|
||||
bool selectedClicked = click && (event->button() == Qt::LeftButton) && d->pressedAlreadySelected;
|
||||
EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
|
||||
bool edited = edit(index, trigger, event);
|
||||
const bool edited = click ? edit(index, trigger, event) : false;
|
||||
|
||||
d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;
|
||||
|
||||
|
@ -1315,8 +1315,8 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
|
||||
if (tl.isValid() && br.isValid()
|
||||
&& d->isIndexEnabled(tl)
|
||||
&& d->isIndexEnabled(br)) {
|
||||
QRect first = rectForIndex(tl);
|
||||
QRect last = rectForIndex(br);
|
||||
QRect first = d->cellRectForIndex(tl);
|
||||
QRect last = d->cellRectForIndex(br);
|
||||
QRect middle;
|
||||
if (d->flow == LeftToRight) {
|
||||
QRect &top = first;
|
||||
|
@ -333,14 +333,31 @@ public:
|
||||
inline QModelIndex listViewItemToIndex(const QListViewItem &item) const
|
||||
{ return model->index(commonListView->itemIndex(item), column, root); }
|
||||
|
||||
inline bool hasRectForIndex(const QModelIndex &index) const
|
||||
{
|
||||
return isIndexValid(index) && index.parent() == root && index.column() == column && !isHidden(index.row());
|
||||
}
|
||||
|
||||
QRect rectForIndex(const QModelIndex &index) const
|
||||
{
|
||||
if (!isIndexValid(index) || index.parent() != root || index.column() != column || isHidden(index.row()))
|
||||
if (!hasRectForIndex(index))
|
||||
return QRect();
|
||||
executePostedLayout();
|
||||
return viewItemRect(indexToListViewItem(index));
|
||||
}
|
||||
|
||||
QRect cellRectForIndex(const QModelIndex &index)
|
||||
{
|
||||
if (!hasRectForIndex(index))
|
||||
return QRect();
|
||||
executePostedLayout();
|
||||
auto oldItemAlignment = itemAlignment;
|
||||
itemAlignment = Qt::Alignment();
|
||||
const QRect rect = rectForIndex(index);
|
||||
itemAlignment = oldItemAlignment;
|
||||
return rect;
|
||||
}
|
||||
|
||||
void viewUpdateGeometries() { q_func()->updateGeometries(); }
|
||||
|
||||
|
||||
|
@ -204,6 +204,7 @@ private slots:
|
||||
void basicRawEventTranslationOfIds();
|
||||
void multiPointRawEventTranslationOnTouchScreen();
|
||||
void multiPointRawEventTranslationOnTouchPad();
|
||||
void touchOnMultipleTouchscreens();
|
||||
void deleteInEventHandler();
|
||||
void deleteInRawEventTranslation();
|
||||
void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
|
||||
@ -213,11 +214,13 @@ private slots:
|
||||
|
||||
private:
|
||||
QTouchDevice *touchScreenDevice;
|
||||
QTouchDevice *secondaryTouchScreenDevice;
|
||||
QTouchDevice *touchPadDevice;
|
||||
};
|
||||
|
||||
tst_QTouchEvent::tst_QTouchEvent()
|
||||
: touchScreenDevice(QTest::createTouchDevice())
|
||||
, secondaryTouchScreenDevice(QTest::createTouchDevice())
|
||||
, touchPadDevice(QTest::createTouchDevice(QTouchDevice::TouchPad))
|
||||
{
|
||||
}
|
||||
@ -225,6 +228,7 @@ tst_QTouchEvent::tst_QTouchEvent()
|
||||
void tst_QTouchEvent::cleanup()
|
||||
{
|
||||
QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
|
||||
QWindowSystemInterfacePrivate::clearPointIdMap();
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::qPointerUniqueId()
|
||||
@ -951,6 +955,157 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::touchOnMultipleTouchscreens()
|
||||
{
|
||||
tst_QTouchEventWidget touchWidget;
|
||||
touchWidget.setWindowTitle(QTest::currentTestFunction());
|
||||
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
touchWidget.setGeometry(100, 100, 400, 300);
|
||||
touchWidget.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
|
||||
QWindow *window = touchWidget.windowHandle();
|
||||
|
||||
QPointF pos = touchWidget.rect().center();
|
||||
QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
|
||||
QPointF delta(10, 10);
|
||||
QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
|
||||
|
||||
QVector<QTouchEvent::TouchPoint> rawTouchPoints(3);
|
||||
rawTouchPoints[0].setId(0);
|
||||
rawTouchPoints[1].setId(10);
|
||||
rawTouchPoints[2].setId(11);
|
||||
|
||||
// this should be translated to a TouchBegin
|
||||
rawTouchPoints[0].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[0].setScreenPos(screenPos);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
rawTouchPoints[0].setRawScreenPositions({{12, 34}, {56, 78}});
|
||||
ulong timestamp = 1234;
|
||||
QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(!touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
QTouchEvent::TouchPoint touchBeginPoint = touchWidget.touchBeginPoints.first();
|
||||
const int touchPointId = (QTouchDevicePrivate::get(touchScreenDevice)->id << 24) + 1;
|
||||
const int secTouchPointId = (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 2;
|
||||
QCOMPARE(touchBeginPoint.id(), touchPointId);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// press a point on secondaryTouchScreenDevice
|
||||
touchWidget.seenTouchBegin = false;
|
||||
rawTouchPoints[1].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[1].setScreenPos(screenPos);
|
||||
rawTouchPoints[1].setNormalizedPos(normalized(rawTouchPoints[1].pos(), screenGeometry));
|
||||
rawTouchPoints[1].setRawScreenPositions({{90, 100}, {110, 120}});
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
touchBeginPoint = touchWidget.touchBeginPoints[0];
|
||||
QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 2);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[1].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// press another point on secondaryTouchScreenDevice
|
||||
touchWidget.seenTouchBegin = false;
|
||||
rawTouchPoints[2].setState(Qt::TouchPointPressed);
|
||||
rawTouchPoints[2].setScreenPos(screenPos);
|
||||
rawTouchPoints[2].setNormalizedPos(normalized(rawTouchPoints[2].pos(), screenGeometry));
|
||||
rawTouchPoints[2].setRawScreenPositions({{130, 140}, {150, 160}});
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchBeginPoints.count(), 1);
|
||||
QCOMPARE(touchWidget.timestamp, timestamp);
|
||||
touchBeginPoint = touchWidget.touchBeginPoints[0];
|
||||
QCOMPARE(touchBeginPoint.id(), (QTouchDevicePrivate::get(secondaryTouchScreenDevice)->id << 24) + 3);
|
||||
QCOMPARE(touchBeginPoint.state(), rawTouchPoints[2].state());
|
||||
QCOMPARE(touchBeginPoint.pos(), pos);
|
||||
|
||||
// moving the first point should translate to TouchUpdate
|
||||
rawTouchPoints[0].setState(Qt::TouchPointMoved);
|
||||
rawTouchPoints[0].setScreenPos(screenPos + delta);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints.count(), 1);
|
||||
QTouchEvent::TouchPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first();
|
||||
QCOMPARE(touchUpdatePoint.id(), touchPointId);
|
||||
QCOMPARE(touchUpdatePoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchUpdatePoint.pos(), pos + delta);
|
||||
|
||||
// releasing the first point translates to TouchEnd
|
||||
rawTouchPoints[0].setState(Qt::TouchPointReleased);
|
||||
rawTouchPoints[0].setScreenPos(screenPos + delta + delta);
|
||||
rawTouchPoints[0].setNormalizedPos(normalized(rawTouchPoints[0].pos(), screenGeometry));
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[0], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchEndPoints.count(), 1);
|
||||
QTouchEvent::TouchPoint touchEndPoint = touchWidget.touchEndPoints.first();
|
||||
QCOMPARE(touchEndPoint.id(), touchPointId);
|
||||
QCOMPARE(touchEndPoint.state(), rawTouchPoints[0].state());
|
||||
QCOMPARE(touchEndPoint.pos(), pos + delta + delta);
|
||||
|
||||
// Widgets don't normally handle this case: if a TouchEnd was seen before, then
|
||||
// WA_WState_AcceptedTouchBeginEvent will be false, and
|
||||
// QApplicationPrivate::translateRawTouchEvent will ignore touch events that aren't TouchBegin.
|
||||
// So we have to set it true. It _did_ in fact accept the touch begin from the secondary device,
|
||||
// but it also got a TouchEnd from the primary device in the meantime.
|
||||
touchWidget.setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, true);
|
||||
|
||||
// Releasing one point on the secondary touchscreen does not yet generate TouchEnd.
|
||||
touchWidget.seenTouchEnd = false;
|
||||
touchWidget.touchEndPoints.clear();
|
||||
rawTouchPoints[1].setState(Qt::TouchPointReleased);
|
||||
rawTouchPoints[2].setState(Qt::TouchPointStationary);
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[1] << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(!touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints.count(), 2);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints[0].id(), secTouchPointId);
|
||||
QCOMPARE(touchWidget.touchUpdatePoints[1].id(), secTouchPointId + 1);
|
||||
|
||||
// releasing the last point on the secondary touchscreen translates to TouchEnd
|
||||
touchWidget.seenTouchEnd = false;
|
||||
rawTouchPoints[2].setState(Qt::TouchPointReleased);
|
||||
nativeTouchPoints =
|
||||
QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QTouchEvent::TouchPoint>() << rawTouchPoints[2], window);
|
||||
QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints);
|
||||
QCoreApplication::processEvents();
|
||||
QVERIFY(touchWidget.seenTouchBegin);
|
||||
QVERIFY(touchWidget.seenTouchUpdate);
|
||||
QVERIFY(touchWidget.seenTouchEnd);
|
||||
QCOMPARE(touchWidget.touchEndPoints.count(), 1);
|
||||
touchEndPoint = touchWidget.touchEndPoints.first();
|
||||
QCOMPARE(touchEndPoint.id(), secTouchPointId + 1);
|
||||
QCOMPARE(touchEndPoint.state(), rawTouchPoints[2].state());
|
||||
}
|
||||
|
||||
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
|
||||
{
|
||||
tst_QTouchEventWidget touchWidget;
|
||||
|
@ -121,6 +121,7 @@ private slots:
|
||||
void task254449_draggingItemToNegativeCoordinates();
|
||||
void keyboardSearch();
|
||||
void shiftSelectionWithNonUniformItemSizes();
|
||||
void shiftSelectionWithItemAlignment();
|
||||
void clickOnViewportClearsSelection();
|
||||
void task262152_setModelColumnNavigate();
|
||||
void taskQTBUG_2233_scrollHiddenItems_data();
|
||||
@ -1802,6 +1803,51 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QListView::shiftSelectionWithItemAlignment()
|
||||
{
|
||||
QStringList items;
|
||||
for (int c = 0; c < 2; c++) {
|
||||
for (int i = 10; i > 0; i--)
|
||||
items << QString(i, QLatin1Char('*'));
|
||||
|
||||
for (int i = 1; i < 11; i++)
|
||||
items << QString(i, QLatin1Char('*'));
|
||||
}
|
||||
|
||||
QListView view;
|
||||
view.setFlow(QListView::TopToBottom);
|
||||
view.setWrapping(true);
|
||||
view.setItemAlignment(Qt::AlignLeft);
|
||||
view.setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
QStringListModel model(items);
|
||||
view.setModel(&model);
|
||||
|
||||
QFont font = view.font();
|
||||
font.setPixelSize(10);
|
||||
view.setFont(font);
|
||||
view.resize(300, view.sizeHintForRow(0) * items.size() / 2 + view.horizontalScrollBar()->height());
|
||||
|
||||
view.show();
|
||||
QApplication::setActiveWindow(&view);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&view));
|
||||
QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow());
|
||||
|
||||
QModelIndex index1 = view.model()->index(items.size() / 4, 0);
|
||||
QPoint p = view.visualRect(index1).center();
|
||||
QVERIFY(view.viewport()->rect().contains(p));
|
||||
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
|
||||
QCOMPARE(view.currentIndex(), index1);
|
||||
QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1);
|
||||
|
||||
QModelIndex index2 = view.model()->index(items.size() / 4 * 3, 0);
|
||||
p = view.visualRect(index2).center();
|
||||
QVERIFY(view.viewport()->rect().contains(p));
|
||||
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p);
|
||||
QCOMPARE(view.currentIndex(), index2);
|
||||
QCOMPARE(view.selectionModel()->selectedIndexes().size(), index2.row() - index1.row() + 1);
|
||||
}
|
||||
|
||||
void tst_QListView::clickOnViewportClearsSelection()
|
||||
{
|
||||
QStringList items;
|
||||
|
@ -200,6 +200,7 @@ private slots:
|
||||
void taskQTBUG_45697_crash();
|
||||
void taskQTBUG_7232_AllowUserToControlSingleStep();
|
||||
void taskQTBUG_8376();
|
||||
void taskQTBUG_61476();
|
||||
void testInitialFocus();
|
||||
};
|
||||
|
||||
@ -4806,5 +4807,58 @@ void tst_QTreeView::taskQTBUG_8376()
|
||||
QCOMPARE(rowHeightLvl1Visible, rowHeightLvl1Visible2);
|
||||
}
|
||||
|
||||
void tst_QTreeView::taskQTBUG_61476()
|
||||
{
|
||||
// This checks that if a user clicks on an item to collapse it that it
|
||||
// does not edit (in this case change the check state) the item that is
|
||||
// now over the mouse just because it got a release event
|
||||
QTreeView tv;
|
||||
QStandardItemModel model;
|
||||
QStandardItem *lastTopLevel = nullptr;
|
||||
{
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
QStandardItem *item = new QStandardItem(QLatin1String("Row Item"));
|
||||
item->setCheckable(true);
|
||||
item->setCheckState(Qt::Checked);
|
||||
model.appendRow(item);
|
||||
lastTopLevel = item;
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
QStandardItem *childItem = new QStandardItem(QLatin1String("Child row Item"));
|
||||
childItem->setCheckable(true);
|
||||
childItem->setCheckState(Qt::Checked);
|
||||
item->appendRow(childItem);
|
||||
QStandardItem *grandChild = new QStandardItem(QLatin1String("Grand child row Item"));
|
||||
grandChild->setCheckable(true);
|
||||
grandChild->setCheckState(Qt::Checked);
|
||||
childItem->appendRow(grandChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
tv.setModel(&model);
|
||||
tv.expandAll();
|
||||
// We need it to be this size so that the effect of the collapsing will
|
||||
// cause the parent item to move to be under the cursor
|
||||
tv.resize(200, 200);
|
||||
tv.show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&tv));
|
||||
tv.verticalScrollBar()->setValue(tv.verticalScrollBar()->maximum());
|
||||
|
||||
// We want to press specifically right around where a checkbox for the
|
||||
// parent item could be when collapsing
|
||||
QTreeViewPrivate *priv = static_cast<QTreeViewPrivate*>(qt_widget_private(&tv));
|
||||
const QModelIndex mi = lastTopLevel->child(0)->index();
|
||||
const QRect rect = priv->itemDecorationRect(mi);
|
||||
const QPoint pos = rect.center();
|
||||
|
||||
QTest::mousePress(tv.viewport(), Qt::LeftButton, 0, pos);
|
||||
if (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, 0, &tv) ==
|
||||
QEvent::MouseButtonPress)
|
||||
QTRY_VERIFY(!tv.isExpanded(mi));
|
||||
|
||||
QTest::mouseRelease(tv.viewport(), Qt::LeftButton, 0, pos);
|
||||
QTRY_VERIFY(!tv.isExpanded(mi));
|
||||
QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTreeView)
|
||||
#include "tst_qtreeview.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user