Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: src/corelib/io/qprocess_win.cpp src/widgets/itemviews/qheaderview.cpp Change-Id: I0a59ade9cd6e91f770fdf298a7d72a41e79fd761
This commit is contained in:
commit
23a36fd2bf
@ -53,6 +53,15 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!qstrcmp(argv[i], "-g"))
|
||||
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||
else if (!qstrcmp(argv[i], "-s"))
|
||||
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
|
||||
else if (!qstrcmp(argv[i], "-d"))
|
||||
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
|
||||
}
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
Widget w;
|
||||
|
@ -60,10 +60,12 @@
|
||||
#include <QPushButton>
|
||||
#include <QTextEdit>
|
||||
#include <QSplitter>
|
||||
#include <QGuiApplication>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
|
||||
struct Version {
|
||||
const char *str;
|
||||
@ -235,6 +237,24 @@ Widget::Widget(QWidget *parent)
|
||||
m_renderWindowContainer = new QWidget;
|
||||
addRenderWindow();
|
||||
|
||||
QString description;
|
||||
QTextStream str(&description);
|
||||
str << "Qt " << QT_VERSION_STR << ' ' << QGuiApplication::platformName();
|
||||
const char *openGlVariables[] =
|
||||
{"QT_ANGLE_PLATFORM", "QT_OPENGL", "QT_OPENGL_BUGLIST", "QT_OPENGL_DLL"};
|
||||
const size_t variableCount = sizeof(openGlVariables) / sizeof(openGlVariables[0]);
|
||||
for (size_t v = 0; v < variableCount; ++v) {
|
||||
if (qEnvironmentVariableIsSet(openGlVariables[v]))
|
||||
str << ' ' << openGlVariables[v] << '=' << qgetenv(openGlVariables[v]);
|
||||
}
|
||||
if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES))
|
||||
str << " Qt::AA_UseOpenGLES";
|
||||
if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL))
|
||||
str << " Qt::AA_UseSoftwareOpenGL";
|
||||
if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL))
|
||||
str << " Qt::AA_UseSoftwareOpenGL";
|
||||
layout->addWidget(new QLabel(description));
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
|
@ -988,15 +988,18 @@ struct QMessagePattern {
|
||||
#endif
|
||||
#ifdef QLOGGING_HAVE_BACKTRACE
|
||||
struct BacktraceParams {
|
||||
QString backtraceSeparator;
|
||||
int backtraceDepth;
|
||||
QString backtraceSeparator;
|
||||
int backtraceDepth;
|
||||
};
|
||||
QList<BacktraceParams> backtraceArgs; // backtrace argumens in sequence of %{backtrace
|
||||
QVector<BacktraceParams> backtraceArgs; // backtrace argumens in sequence of %{backtrace
|
||||
#endif
|
||||
|
||||
bool fromEnvironment;
|
||||
static QBasicMutex mutex;
|
||||
};
|
||||
#ifdef QLOGGING_HAVE_BACKTRACE
|
||||
Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_MOVABLE_TYPE);
|
||||
#endif
|
||||
|
||||
QBasicMutex QMessagePattern::mutex;
|
||||
|
||||
|
@ -151,12 +151,14 @@ static bool fcntlWorksAfterFlock(const QString &fn)
|
||||
if (fcntlOK.isDestroyed())
|
||||
return QLockFilePrivate::checkFcntlWorksAfterFlock(fn);
|
||||
bool *worksPtr = fcntlOK->object(fn);
|
||||
if (!worksPtr) {
|
||||
worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn));
|
||||
fcntlOK->insert(fn, worksPtr);
|
||||
}
|
||||
if (worksPtr)
|
||||
return *worksPtr;
|
||||
|
||||
return *worksPtr;
|
||||
const bool val = QLockFilePrivate::checkFcntlWorksAfterFlock(fn);
|
||||
worksPtr = new bool(val);
|
||||
fcntlOK->insert(fn, worksPtr);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool setNativeLocks(const QString &fileName, int fd)
|
||||
|
@ -365,9 +365,6 @@ void QLoggingRegistry::setApiRules(const QString &content)
|
||||
*/
|
||||
void QLoggingRegistry::updateRules()
|
||||
{
|
||||
if (categoryFilter != defaultCategoryFilter)
|
||||
return;
|
||||
|
||||
rules = qtConfigRules + configRules + apiRules + envRules;
|
||||
|
||||
for (auto it = categories.keyBegin(), end = categories.keyEnd(); it != end; ++it)
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <qfileinfo.h>
|
||||
#include <qregexp.h>
|
||||
#include <qwineventnotifier.h>
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
#include <private/qthread_p.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
@ -817,8 +818,45 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
|
||||
return stdinChannel.writer->write(data, maxlen);
|
||||
}
|
||||
|
||||
// Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails
|
||||
// with ERROR_ELEVATION_REQUIRED.
|
||||
static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments,
|
||||
const QString &workingDir, qint64 *pid)
|
||||
{
|
||||
typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *);
|
||||
|
||||
static const ShellExecuteExType shellExecuteEx = // XP ServicePack 1 onwards.
|
||||
reinterpret_cast<ShellExecuteExType>(QSystemLibrary::resolve(QLatin1String("shell32"),
|
||||
"ShellExecuteExW"));
|
||||
if (!shellExecuteEx)
|
||||
return false;
|
||||
|
||||
const QString args = qt_create_commandline(QString(), arguments); // needs arguments only
|
||||
SHELLEXECUTEINFOW shellExecuteExInfo;
|
||||
memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW));
|
||||
shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||
shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI;
|
||||
shellExecuteExInfo.lpVerb = L"runas";
|
||||
const QString program = QDir::toNativeSeparators(programIn);
|
||||
shellExecuteExInfo.lpFile = reinterpret_cast<LPCWSTR>(program.utf16());
|
||||
if (!args.isEmpty())
|
||||
shellExecuteExInfo.lpParameters = reinterpret_cast<LPCWSTR>(args.utf16());
|
||||
if (!workingDir.isEmpty())
|
||||
shellExecuteExInfo.lpDirectory = reinterpret_cast<LPCWSTR>(workingDir.utf16());
|
||||
shellExecuteExInfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
if (!shellExecuteEx(&shellExecuteExInfo))
|
||||
return false;
|
||||
if (pid)
|
||||
*pid = qint64(GetProcessId(shellExecuteExInfo.hProcess));
|
||||
CloseHandle(shellExecuteExInfo.hProcess);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
|
||||
{
|
||||
static const DWORD errorElevationRequired = 740;
|
||||
|
||||
QString args = qt_create_commandline(program, arguments);
|
||||
bool success = false;
|
||||
PROCESS_INFORMATION pinfo;
|
||||
@ -838,6 +876,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
|
||||
CloseHandle(pinfo.hProcess);
|
||||
if (pid)
|
||||
*pid = pinfo.dwProcessId;
|
||||
} else if (GetLastError() == errorElevationRequired) {
|
||||
success = startDetachedUacPrompt(program, arguments, workingDir, pid);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -520,7 +520,7 @@ QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
|
||||
return mimeTypeForFile(url.toLocalFile());
|
||||
|
||||
const QString scheme = url.scheme();
|
||||
if (scheme.startsWith(QLatin1String("http")))
|
||||
if (scheme.startsWith(QLatin1String("http")) || scheme == QLatin1String("mailto"))
|
||||
return mimeTypeForName(d->defaultMimeType());
|
||||
|
||||
return mimeTypeForFile(url.path());
|
||||
|
@ -10092,6 +10092,9 @@ static inline int qt_find_latin1_string(const QChar *haystack, int size,
|
||||
QLatin1String needle,
|
||||
int from, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (size < needle.size())
|
||||
return -1;
|
||||
|
||||
const char *latin1 = needle.latin1();
|
||||
int len = needle.size();
|
||||
QVarLengthArray<ushort> s(len);
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
inline QDBusArgumentPrivate(int flags = 0)
|
||||
: message(0), ref(1), capabilities(flags)
|
||||
{ }
|
||||
~QDBusArgumentPrivate();
|
||||
virtual ~QDBusArgumentPrivate();
|
||||
|
||||
static bool checkRead(QDBusArgumentPrivate *d);
|
||||
static bool checkReadAndDetach(QDBusArgumentPrivate *&d);
|
||||
|
@ -1956,7 +1956,7 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
|
||||
void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
|
||||
{
|
||||
if (sessionState == QNetworkSession::Disconnected
|
||||
&& (state != Idle || state != Reconnecting)) {
|
||||
&& state != Idle && state != Reconnecting) {
|
||||
error(QNetworkReplyImpl::NetworkSessionFailedError,
|
||||
QCoreApplication::translate("QNetworkReply", "Network session error."));
|
||||
finished();
|
||||
|
@ -325,7 +325,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
|
||||
void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
|
||||
{
|
||||
if (sessionState == QNetworkSession::Disconnected
|
||||
&& (state != Idle || state != Reconnecting)) {
|
||||
&& state != Idle && state != Reconnecting) {
|
||||
error(QNetworkReplyImpl::NetworkSessionFailedError,
|
||||
QCoreApplication::translate("QNetworkReply", "Network session error."));
|
||||
finished();
|
||||
|
@ -2181,7 +2181,7 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
|
||||
}
|
||||
|
||||
do {
|
||||
if (state() != ConnectedState)
|
||||
if (state() != ConnectedState && state() != BoundState)
|
||||
return false;
|
||||
|
||||
bool readyToRead = false;
|
||||
|
@ -72,6 +72,7 @@ typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow;
|
||||
QCocoaWindow *_platformWindow;
|
||||
BOOL _grabbingMouse;
|
||||
BOOL _releaseOnMouseUp;
|
||||
QPointer<QObject> _watcher;
|
||||
}
|
||||
|
||||
@property (nonatomic, readonly) QCocoaNSWindow *window;
|
||||
@ -321,6 +322,11 @@ public: // for QNSView
|
||||
};
|
||||
QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
|
||||
QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false)
|
||||
|
||||
// This object is tracked by a 'watcher'
|
||||
// object in a window helper, preventing use of dangling
|
||||
// pointers.
|
||||
QObject sentinel;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -99,6 +99,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
// make sure that m_nsWindow stays valid until the
|
||||
// QCocoaWindow is deleted by Qt.
|
||||
[_window setReleasedWhenClosed:NO];
|
||||
_watcher = &_platformWindow->sentinel;
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -107,7 +108,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
- (void)handleWindowEvent:(NSEvent *)theEvent
|
||||
{
|
||||
QCocoaWindow *pw = self.platformWindow;
|
||||
if (pw && pw->m_forwardWindow) {
|
||||
if (_watcher && pw && pw->m_forwardWindow) {
|
||||
if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) {
|
||||
QNSView *forwardView = pw->m_qtView;
|
||||
if (theEvent.type == NSLeftMouseUp) {
|
||||
@ -146,7 +147,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
if (!self.window.delegate)
|
||||
return; // Already detached, pending NSAppKitDefined event
|
||||
|
||||
if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
|
||||
if (_watcher && pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
|
||||
NSPoint loc = [theEvent locationInWindow];
|
||||
NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
|
||||
NSRect contentFrame = [[self.window contentView] frame];
|
||||
@ -162,6 +163,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
- (void)detachFromPlatformWindow
|
||||
{
|
||||
_platformWindow = 0;
|
||||
_watcher.clear();
|
||||
[self.window.delegate release];
|
||||
self.window.delegate = nil;
|
||||
}
|
||||
|
@ -374,13 +374,11 @@ QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window,
|
||||
QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
|
||||
{
|
||||
#if defined(QT_OPENGL_DYNAMIC)
|
||||
const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers();
|
||||
|
||||
QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer();
|
||||
switch (requestedRenderer) {
|
||||
case QWindowsOpenGLTester::DesktopGl:
|
||||
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
|
||||
if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag)
|
||||
if ((QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DisableRotationFlag)
|
||||
&& !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) {
|
||||
qCWarning(lcQpaGl, "Unable to disable rotation.");
|
||||
}
|
||||
@ -406,6 +404,7 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
|
||||
break;
|
||||
}
|
||||
|
||||
const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers();
|
||||
if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) {
|
||||
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
|
||||
if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag)
|
||||
|
@ -1135,6 +1135,8 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
|
||||
|
||||
// Activate topWindow
|
||||
if (!d->visibleWindows.isEmpty()) {
|
||||
Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated
|
||||
|
@ -567,6 +567,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
, m_buttons(0)
|
||||
, m_focusWindow(0)
|
||||
, m_mouseGrabber(0)
|
||||
, m_mousePressWindow(0)
|
||||
, m_clientLeader(0)
|
||||
, m_systemTrayTracker(0)
|
||||
, m_glIntegration(Q_NULLPTR)
|
||||
@ -1379,6 +1380,11 @@ void QXcbConnection::setFocusWindow(QXcbWindow *w)
|
||||
void QXcbConnection::setMouseGrabber(QXcbWindow *w)
|
||||
{
|
||||
m_mouseGrabber = w;
|
||||
m_mousePressWindow = Q_NULLPTR;
|
||||
}
|
||||
void QXcbConnection::setMousePressWindow(QXcbWindow *w)
|
||||
{
|
||||
m_mousePressWindow = w;
|
||||
}
|
||||
|
||||
void QXcbConnection::grabServer()
|
||||
|
@ -481,6 +481,8 @@ public:
|
||||
void setFocusWindow(QXcbWindow *);
|
||||
QXcbWindow *mouseGrabber() const { return m_mouseGrabber; }
|
||||
void setMouseGrabber(QXcbWindow *);
|
||||
QXcbWindow *mousePressWindow() const { return m_mousePressWindow; }
|
||||
void setMousePressWindow(QXcbWindow *);
|
||||
|
||||
QByteArray startupId() const { return m_startupId; }
|
||||
void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
|
||||
@ -668,6 +670,7 @@ private:
|
||||
|
||||
QXcbWindow *m_focusWindow;
|
||||
QXcbWindow *m_mouseGrabber;
|
||||
QXcbWindow *m_mousePressWindow;
|
||||
|
||||
xcb_window_t m_clientLeader;
|
||||
QByteArray m_startupId;
|
||||
|
@ -592,8 +592,12 @@ QXcbWindow::~QXcbWindow()
|
||||
{
|
||||
if (window()->type() != Qt::ForeignWindow)
|
||||
destroy();
|
||||
else if (connection()->mouseGrabber() == this)
|
||||
connection()->setMouseGrabber(Q_NULLPTR);
|
||||
else {
|
||||
if (connection()->mouseGrabber() == this)
|
||||
connection()->setMouseGrabber(Q_NULLPTR);
|
||||
if (connection()->mousePressWindow() == this)
|
||||
connection()->setMousePressWindow(Q_NULLPTR);
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbWindow::destroy()
|
||||
@ -851,6 +855,16 @@ void QXcbWindow::hide()
|
||||
|
||||
if (connection()->mouseGrabber() == this)
|
||||
connection()->setMouseGrabber(Q_NULLPTR);
|
||||
if (QPlatformWindow *w = connection()->mousePressWindow()) {
|
||||
// Unset mousePressWindow when it (or one of its parents) is unmapped
|
||||
while (w) {
|
||||
if (w == this) {
|
||||
connection()->setMousePressWindow(Q_NULLPTR);
|
||||
break;
|
||||
}
|
||||
w = w->parent();
|
||||
}
|
||||
}
|
||||
|
||||
m_mapped = false;
|
||||
|
||||
@ -2199,6 +2213,8 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
|
||||
return;
|
||||
}
|
||||
|
||||
connection()->setMousePressWindow(this);
|
||||
|
||||
handleMouseEvent(timestamp, local, global, modifiers, source);
|
||||
}
|
||||
|
||||
@ -2213,19 +2229,44 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection()->buttons() == Qt::NoButton)
|
||||
connection()->setMousePressWindow(Q_NULLPTR);
|
||||
|
||||
handleMouseEvent(timestamp, local, global, modifiers, source);
|
||||
}
|
||||
|
||||
static bool ignoreLeaveEvent(quint8 mode, quint8 detail)
|
||||
static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
|
||||
{
|
||||
return (mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
|
||||
|| detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
||||
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL;
|
||||
/* Checking for XCB_NOTIFY_MODE_GRAB and XCB_NOTIFY_DETAIL_ANCESTOR prevents unwanted
|
||||
* enter/leave events on AwesomeWM on mouse button press. It also ignores duplicated
|
||||
* enter/leave events on Alt+Tab switching on some WMs with XInput2 events.
|
||||
* Without XInput2 events the (Un)grabAncestor cannot be checked when mouse button is
|
||||
* not pressed, otherwise (e.g. on Alt+Tab) it can igonre important enter/leave events.
|
||||
*/
|
||||
if (conn) {
|
||||
const bool mouseButtonsPressed = (conn->buttons() != Qt::NoButton);
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
return mouseButtonsPressed || (conn->isAtLeastXI22() && conn->xi2MouseEvents());
|
||||
#else
|
||||
return mouseButtonsPressed;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ignoreEnterEvent(quint8 mode, quint8 detail)
|
||||
static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR)
|
||||
{
|
||||
return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
|
||||
return ((doCheckUnGrabAncestor(conn)
|
||||
&& mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
|
||||
|| (mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_INFERIOR)
|
||||
|| detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
||||
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
|
||||
}
|
||||
|
||||
static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR)
|
||||
{
|
||||
return ((doCheckUnGrabAncestor(conn)
|
||||
&& mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
|
||||
|| (mode != XCB_NOTIFY_MODE_NORMAL && mode != XCB_NOTIFY_MODE_UNGRAB)
|
||||
|| detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
||||
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
|
||||
@ -2259,9 +2300,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
|
||||
|
||||
const QPoint global = QPoint(root_x, root_y);
|
||||
|
||||
if (ignoreEnterEvent(mode, detail)
|
||||
|| (connection()->buttons() != Qt::NoButton
|
||||
&& QGuiApplicationPrivate::lastCursorPosition != global))
|
||||
if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow())
|
||||
return;
|
||||
|
||||
const QPoint local(event_x, event_y);
|
||||
@ -2273,11 +2312,7 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
|
||||
{
|
||||
connection()->setTime(timestamp);
|
||||
|
||||
const QPoint global(root_x, root_y);
|
||||
|
||||
if (ignoreLeaveEvent(mode, detail)
|
||||
|| (connection()->buttons() != Qt::NoButton
|
||||
&& QGuiApplicationPrivate::lastCursorPosition != global))
|
||||
if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow())
|
||||
return;
|
||||
|
||||
EnterEventChecker checker;
|
||||
@ -2300,6 +2335,11 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i
|
||||
{
|
||||
QPoint local(event_x, event_y);
|
||||
QPoint global(root_x, root_y);
|
||||
|
||||
// "mousePressWindow" can be NULL i.e. if a window will be grabbed or umnapped, so set it again here
|
||||
if (connection()->buttons() != Qt::NoButton && connection()->mousePressWindow() == Q_NULLPTR)
|
||||
connection()->setMousePressWindow(this);
|
||||
|
||||
handleMouseEvent(timestamp, local, global, modifiers, source);
|
||||
}
|
||||
|
||||
|
@ -867,9 +867,11 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
|
||||
if (newName == idx.data().toString())
|
||||
return true;
|
||||
|
||||
const QString parentPath = filePath(parent(idx));
|
||||
|
||||
if (newName.isEmpty()
|
||||
|| QDir::toNativeSeparators(newName).contains(QDir::separator())
|
||||
|| !QDir(filePath(parent(idx))).rename(oldName, newName)) {
|
||||
|| !QDir(parentPath).rename(oldName, newName)) {
|
||||
#ifndef QT_NO_MESSAGEBOX
|
||||
QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"),
|
||||
QFileSystemModel::tr("<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.")
|
||||
@ -896,7 +898,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
|
||||
parentNode->visibleChildren.removeAt(visibleLocation);
|
||||
QFileSystemModelPrivate::QFileSystemNode * oldValue = parentNode->children.value(oldName);
|
||||
parentNode->children[newName] = oldValue;
|
||||
QFileInfo info(d->rootDir, newName);
|
||||
QFileInfo info(parentPath, newName);
|
||||
oldValue->fileName = newName;
|
||||
oldValue->parent = parentNode;
|
||||
#ifndef QT_NO_FILESYSTEMWATCHER
|
||||
@ -908,7 +910,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
|
||||
parentNode->visibleChildren.insert(visibleLocation, newName);
|
||||
|
||||
d->delayedSort();
|
||||
emit fileRenamed(filePath(idx.parent()), oldName, newName);
|
||||
emit fileRenamed(parentPath, oldName, newName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3013,30 +3013,41 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c
|
||||
{
|
||||
Q_D(const QHeaderView);
|
||||
const int max = d->modelSectionCount();
|
||||
|
||||
if (d->orientation == Qt::Horizontal) {
|
||||
int left = max;
|
||||
int right = 0;
|
||||
int rangeLeft, rangeRight;
|
||||
int logicalLeft = max;
|
||||
int logicalRight = 0;
|
||||
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items and we don't want invalid ranges
|
||||
// FIXME an item inside the range may be the leftmost or rightmost
|
||||
rangeLeft = visualIndex(r.left());
|
||||
if (rangeLeft == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
rangeRight = visualIndex(r.right());
|
||||
if (rangeRight == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
if (rangeLeft < left)
|
||||
left = rangeLeft;
|
||||
if (rangeRight > right)
|
||||
right = rangeRight;
|
||||
if (d->visualIndices.empty()) {
|
||||
// If no reordered sections, skip redundant visual-to-logical transformations
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items and we don't want invalid ranges
|
||||
if (r.left() < logicalLeft)
|
||||
logicalLeft = r.left();
|
||||
if (r.right() > logicalRight)
|
||||
logicalRight = r.right();
|
||||
}
|
||||
} else {
|
||||
int left = max;
|
||||
int right = 0;
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items and we don't want invalid ranges
|
||||
for (int k = r.left(); k <= r.right(); ++k) {
|
||||
int visual = visualIndex(k);
|
||||
if (visual == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
if (visual < left)
|
||||
left = visual;
|
||||
if (visual > right)
|
||||
right = visual;
|
||||
}
|
||||
}
|
||||
logicalLeft = logicalIndex(left);
|
||||
logicalRight = logicalIndex(right);
|
||||
}
|
||||
|
||||
int logicalLeft = logicalIndex(left);
|
||||
int logicalRight = logicalIndex(right);
|
||||
|
||||
if (logicalLeft < 0 || logicalLeft >= count() ||
|
||||
logicalRight < 0 || logicalRight >= count())
|
||||
return QRegion();
|
||||
@ -3047,31 +3058,44 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c
|
||||
return QRect(leftPos, 0, rightPos - leftPos, height());
|
||||
}
|
||||
// orientation() == Qt::Vertical
|
||||
int top = max;
|
||||
int bottom = 0;
|
||||
int rangeTop, rangeBottom;
|
||||
int logicalTop = max;
|
||||
int logicalBottom = 0;
|
||||
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items
|
||||
// FIXME an item inside the range may be the leftmost or rightmost
|
||||
rangeTop = visualIndex(r.top());
|
||||
if (rangeTop == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
rangeBottom = visualIndex(r.bottom());
|
||||
if (rangeBottom == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
if (rangeTop < top)
|
||||
top = rangeTop;
|
||||
if (rangeBottom > bottom)
|
||||
bottom = rangeBottom;
|
||||
if (d->visualIndices.empty()) {
|
||||
// If no reordered sections, skip redundant visual-to-logical transformations
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items and we don't want invalid ranges
|
||||
if (r.top() < logicalTop)
|
||||
logicalTop = r.top();
|
||||
if (r.bottom() > logicalBottom)
|
||||
logicalBottom = r.bottom();
|
||||
}
|
||||
} else {
|
||||
int top = max;
|
||||
int bottom = 0;
|
||||
|
||||
for (const auto &r : selection) {
|
||||
if (r.parent().isValid() || !r.isValid())
|
||||
continue; // we only know about toplevel items and we don't want invalid ranges
|
||||
for (int k = r.top(); k <= r.bottom(); ++k) {
|
||||
int visual = visualIndex(k);
|
||||
if (visual == -1) // in some cases users may change the selections
|
||||
continue; // before we have a chance to do the layout
|
||||
if (visual < top)
|
||||
top = visual;
|
||||
if (visual > bottom)
|
||||
bottom = visual;
|
||||
}
|
||||
}
|
||||
|
||||
logicalTop = logicalIndex(top);
|
||||
logicalBottom = logicalIndex(bottom);
|
||||
}
|
||||
|
||||
int logicalTop = logicalIndex(top);
|
||||
int logicalBottom = logicalIndex(bottom);
|
||||
|
||||
if (logicalTop == -1 || logicalBottom == -1)
|
||||
return QRect();
|
||||
if (logicalTop < 0 || logicalTop >= count() ||
|
||||
logicalBottom < 0 || logicalBottom >= count())
|
||||
return QRegion();
|
||||
|
||||
int topPos = sectionViewportPosition(logicalTop);
|
||||
int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
|
||||
|
@ -5263,7 +5263,9 @@ QPixmap QWidget::grab(const QRect &rectangle)
|
||||
if (!r.intersects(rect()))
|
||||
return QPixmap();
|
||||
|
||||
QPixmap res(r.size());
|
||||
const qreal dpr = devicePixelRatioF();
|
||||
QPixmap res((QSizeF(r.size()) * dpr).toSize());
|
||||
res.setDevicePixelRatio(dpr);
|
||||
if (!d->isOpaque)
|
||||
res.fill(Qt::transparent);
|
||||
d->render(&res, QPoint(), QRegion(r), renderFlags);
|
||||
|
@ -3422,12 +3422,28 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
|
||||
QSize textSize = option->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
|
||||
int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
|
||||
int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
|
||||
|
||||
const int width = textSize.width()
|
||||
+ (option->subControls & QStyle::SC_GroupBoxCheckBox ? indicatorWidth + 5 : 0);
|
||||
|
||||
rect = QRect();
|
||||
|
||||
if (option->rect.width() > width) {
|
||||
switch (groupBox->textAlignment & Qt::AlignHorizontal_Mask) {
|
||||
case Qt::AlignHCenter:
|
||||
rect.moveLeft((option->rect.width() - width) / 2);
|
||||
break;
|
||||
case Qt::AlignRight:
|
||||
rect.moveLeft(option->rect.width() - width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (subControl == SC_GroupBoxCheckBox) {
|
||||
rect.setWidth(indicatorWidth);
|
||||
rect.setHeight(indicatorHeight);
|
||||
rect.moveTop(textSize.height() > indicatorHeight ? (textSize.height() - indicatorHeight) / 2 : 0);
|
||||
rect.moveLeft(1);
|
||||
rect.translate(1, 0);
|
||||
} else if (subControl == SC_GroupBoxLabel) {
|
||||
rect.setSize(textSize);
|
||||
rect.moveTop(1);
|
||||
|
@ -1149,7 +1149,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
|
||||
if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
|
||||
alignment |= Qt::TextHideMnemonic;
|
||||
|
||||
if (widget) { // Not needed for QtQuick Controls
|
||||
if (widget && mbi->palette.color(QPalette::Window) != Qt::transparent) { // Not needed for QtQuick Controls
|
||||
//The rect adjustment is a workaround for the menu not really filling its background.
|
||||
XPThemeData theme(widget, painter,
|
||||
QWindowsXPStylePrivate::MenuTheme,
|
||||
|
@ -513,6 +513,8 @@ void tst_QMimeDatabase::mimeTypeForUrl()
|
||||
QVERIFY(db.mimeTypeForUrl(QUrl::fromEncoded("http://foo/bar.png")).isDefault()); // HTTP can't know before downloading
|
||||
QCOMPARE(db.mimeTypeForUrl(QUrl::fromEncoded("ftp://foo/bar.png")).name(), QString::fromLatin1("image/png"));
|
||||
QCOMPARE(db.mimeTypeForUrl(QUrl::fromEncoded("ftp://foo/bar")).name(), QString::fromLatin1("application/octet-stream")); // unknown extension
|
||||
QCOMPARE(db.mimeTypeForUrl(QUrl("mailto:something@example.com")).name(), QString::fromLatin1("application/octet-stream")); // unknown
|
||||
QCOMPARE(db.mimeTypeForUrl(QUrl("mailto:something@polish.pl")).name(), QString::fromLatin1("application/octet-stream")); // unknown, NOT perl ;)
|
||||
}
|
||||
|
||||
void tst_QMimeDatabase::mimeTypeForData_data()
|
||||
|
@ -29,9 +29,16 @@
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
|
||||
# include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Windows: Suppress crash notification dialog.
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
||||
#endif
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QTcpServer server;
|
||||
|
@ -693,6 +693,7 @@ void tst_QFileSystemModel::nameFilters()
|
||||
}
|
||||
void tst_QFileSystemModel::setData_data()
|
||||
{
|
||||
QTest::addColumn<QString>("subdirName");
|
||||
QTest::addColumn<QStringList>("files");
|
||||
QTest::addColumn<QString>("oldFileName");
|
||||
QTest::addColumn<QString>("newFileName");
|
||||
@ -702,7 +703,15 @@ void tst_QFileSystemModel::setData_data()
|
||||
<< QDir::temp().absolutePath() + '/' + "a"
|
||||
<< false;
|
||||
*/
|
||||
QTest::newRow("in current dir") << (QStringList() << "a" << "b" << "c")
|
||||
QTest::newRow("in current dir")
|
||||
<< QString()
|
||||
<< (QStringList() << "a" << "b" << "c")
|
||||
<< "a"
|
||||
<< "d"
|
||||
<< true;
|
||||
QTest::newRow("in subdir")
|
||||
<< "s"
|
||||
<< (QStringList() << "a" << "b" << "c")
|
||||
<< "a"
|
||||
<< "d"
|
||||
<< true;
|
||||
@ -711,15 +720,25 @@ void tst_QFileSystemModel::setData_data()
|
||||
void tst_QFileSystemModel::setData()
|
||||
{
|
||||
QSignalSpy spy(model, SIGNAL(fileRenamed(QString,QString,QString)));
|
||||
QString tmp = flatDirTestPath;
|
||||
QFETCH(QString, subdirName);
|
||||
QFETCH(QStringList, files);
|
||||
QFETCH(QString, oldFileName);
|
||||
QFETCH(QString, newFileName);
|
||||
QFETCH(bool, success);
|
||||
|
||||
QString tmp = flatDirTestPath;
|
||||
if (!subdirName.isEmpty()) {
|
||||
QDir dir(tmp);
|
||||
QVERIFY(dir.mkdir(subdirName));
|
||||
tmp.append('/' + subdirName);
|
||||
}
|
||||
QVERIFY(createFiles(tmp, files));
|
||||
QModelIndex root = model->setRootPath(tmp);
|
||||
QTRY_COMPARE(model->rowCount(root), files.count());
|
||||
QModelIndex tmpIdx = model->setRootPath(flatDirTestPath);
|
||||
if (!subdirName.isEmpty()) {
|
||||
tmpIdx = model->index(tmp);
|
||||
model->fetchMore(tmpIdx);
|
||||
}
|
||||
QTRY_COMPARE(model->rowCount(tmpIdx), files.count());
|
||||
|
||||
QModelIndex idx = model->index(tmp + '/' + oldFileName);
|
||||
QCOMPARE(idx.isValid(), true);
|
||||
@ -727,16 +746,21 @@ void tst_QFileSystemModel::setData()
|
||||
|
||||
model->setReadOnly(false);
|
||||
QCOMPARE(model->setData(idx, newFileName), success);
|
||||
model->setReadOnly(true);
|
||||
if (success) {
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QList<QVariant> arguments = spy.takeFirst();
|
||||
QCOMPARE(model->data(idx, QFileSystemModel::FileNameRole).toString(), newFileName);
|
||||
QCOMPARE(model->fileInfo(idx).filePath(), tmp + '/' + newFileName);
|
||||
QCOMPARE(model->index(arguments.at(0).toString()), model->index(tmp));
|
||||
QCOMPARE(arguments.at(1).toString(), oldFileName);
|
||||
QCOMPARE(arguments.at(2).toString(), newFileName);
|
||||
QCOMPARE(QFile::rename(tmp + '/' + newFileName, tmp + '/' + oldFileName), true);
|
||||
}
|
||||
QTRY_COMPARE(model->rowCount(root), files.count());
|
||||
QTRY_COMPARE(model->rowCount(tmpIdx), files.count());
|
||||
// cleanup
|
||||
if (!subdirName.isEmpty())
|
||||
QVERIFY(QDir(tmp).removeRecursively());
|
||||
}
|
||||
|
||||
void tst_QFileSystemModel::sortPersistentIndex()
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
void testEvent();
|
||||
void testhorizontalOffset();
|
||||
void testverticalOffset();
|
||||
void testVisualRegionForSelection();
|
||||
friend class tst_QHeaderView;
|
||||
};
|
||||
|
||||
@ -204,6 +205,7 @@ private slots:
|
||||
void QTBUG8650_crashOnInsertSections();
|
||||
void QTBUG12268_hiddenMovedSectionSorting();
|
||||
void QTBUG14242_hideSectionAutoSize();
|
||||
void QTBUG50171_visualRegionForSwappedItems();
|
||||
void ensureNoIndexAtLength();
|
||||
void offsetConsistent();
|
||||
|
||||
@ -2281,6 +2283,24 @@ void tst_QHeaderView::QTBUG14242_hideSectionAutoSize()
|
||||
QCOMPARE(calced_length, afterlength);
|
||||
}
|
||||
|
||||
void tst_QHeaderView::QTBUG50171_visualRegionForSwappedItems()
|
||||
{
|
||||
protected_QHeaderView headerView(Qt::Horizontal);
|
||||
QtTestModel model;
|
||||
model.rows = 2;
|
||||
model.cols = 3;
|
||||
headerView.setModel(&model);
|
||||
headerView.swapSections(1, 2);
|
||||
headerView.hideSection(0);
|
||||
headerView.testVisualRegionForSelection();
|
||||
}
|
||||
|
||||
void protected_QHeaderView::testVisualRegionForSelection()
|
||||
{
|
||||
QRegion r = visualRegionForSelection(QItemSelection(model()->index(1, 0), model()->index(1, 2)));
|
||||
QCOMPARE(r.boundingRect().contains(QRect(1, 1, length() - 2, 1)), true);
|
||||
}
|
||||
|
||||
void tst_QHeaderView::ensureNoIndexAtLength()
|
||||
{
|
||||
QTableView qtv;
|
||||
|
@ -3030,8 +3030,23 @@ protected:
|
||||
QSize sizeHint() const { return QSize(500, 500); }
|
||||
};
|
||||
|
||||
// Scale to remove devicePixelRatio should scaling be active.
|
||||
static QPixmap grabFromWidget(QWidget *w, const QRect &rect)
|
||||
{
|
||||
QPixmap pixmap = w->grab(rect);
|
||||
const qreal devicePixelRatio = pixmap.devicePixelRatioF();
|
||||
if (!qFuzzyCompare(devicePixelRatio, qreal(1))) {
|
||||
pixmap = pixmap.scaled((QSizeF(pixmap.size()) / devicePixelRatio).toSize(),
|
||||
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap.setDevicePixelRatio(1);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void tst_QWidget::testContentsPropagation()
|
||||
{
|
||||
if (!qFuzzyCompare(qApp->devicePixelRatio(), qreal(1)))
|
||||
QSKIP("This test does not work with scaling.");
|
||||
ContentsPropagationWidget widget;
|
||||
widget.setFixedSize(500, 500);
|
||||
widget.setContentsPropagation(false);
|
||||
@ -9203,7 +9218,7 @@ void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
|
||||
|
||||
QPixmap correct(main.size());
|
||||
correct.fill(Qt::green);
|
||||
const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
|
||||
const QPixmap mainPixmap = grabFromWidget(&main, QRect(QPoint(0, 0), QSize(-1, -1)));
|
||||
|
||||
QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
|
||||
correct.toImage().convertToFormat(QImage::Format_RGB32));
|
||||
@ -9667,10 +9682,10 @@ void tst_QWidget::grab()
|
||||
p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
|
||||
p.end();
|
||||
|
||||
QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
|
||||
QPixmap actual = grabFromWidget(&widget, QRect(64, 64, 64, 64));
|
||||
QVERIFY(lenientCompare(actual, expected));
|
||||
|
||||
actual = widget.grab(QRect(64, 64, -1, -1));
|
||||
actual = grabFromWidget(&widget, QRect(64, 64, -1, -1));
|
||||
QVERIFY(lenientCompare(actual, expected));
|
||||
|
||||
// Make sure a widget that is not yet shown is grabbed correctly.
|
||||
|
Loading…
Reference in New Issue
Block a user