summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-04-27 09:18:05 +0200
committerLiang Qi <liang.qi@qt.io>2016-04-27 09:18:05 +0200
commit23a36fd2bfcdb57849deaa1e10e6e3f7b1156ed8 (patch)
treeb527c7e3ba4a831b542b0bccfb6a5a748a8a4fd9 /src
parentc003a18ee332abf2387172eb0856a176a32a6c8f (diff)
parent072f5b513e486e884ea7fa4a1cac9aedf3846374 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qlogging.cpp9
-rw-r--r--src/corelib/io/qlockfile_unix.cpp12
-rw-r--r--src/corelib/io/qloggingregistry.cpp3
-rw-r--r--src/corelib/io/qprocess_win.cpp40
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp2
-rw-r--r--src/corelib/tools/qstring.cpp3
-rw-r--r--src/dbus/qdbusargument_p.h2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp2
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp2
-rw-r--r--src/network/socket/qabstractsocket.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp5
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp70
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp8
-rw-r--r--src/widgets/itemviews/qheaderview.cpp116
-rw-r--r--src/widgets/kernel/qwidget.cpp4
-rw-r--r--src/widgets/styles/qfusionstyle.cpp18
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp2
22 files changed, 235 insertions, 88 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index de37731b1a..4851d1ce6f 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -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;
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index 7255414bdc..03dc5fc660 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -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;
+
+ const bool val = QLockFilePrivate::checkFcntlWorksAfterFlock(fn);
+ worksPtr = new bool(val);
+ fcntlOK->insert(fn, worksPtr);
- return *worksPtr;
+ return val;
}
static bool setNativeLocks(const QString &fileName, int fd)
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index 818772a399..eaebbc1ffc 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -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)
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 5d8b567c8c..ed540f9e5b 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -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;
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index bff6a9ac15..d866d3bcf7 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -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());
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 9bfc46f32e..c3aae2fd22 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -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);
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index 296918961f..ca0a2cde13 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -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);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 935c17dfc1..c6173791a6 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -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();
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 59a0cd8ddc..d69d5983cb 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -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();
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index a874c1b43f..7bf9a6de7a 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -2181,7 +2181,7 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
}
do {
- if (state() != ConnectedState)
+ if (state() != ConnectedState && state() != BoundState)
return false;
bool readyToRead = false;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 4d2af84e8e..4d5f5d74f2 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -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
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 29cc4130ed..01e72303be 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -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;
}
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 9486dd84f0..b524adb2cb 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -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)
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index aec09a260b..f3667aaa0d 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -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
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 2e51576e3b..5ad349fdc2 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -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()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index e8af82ec8c..68d7b5622f 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -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;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 5e4aaa37d9..c507ac09b6 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -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)
+{
+ /* 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 ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR)
{
- return (mode == XCB_NOTIFY_MODE_GRAB && 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;
+ || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
}
-static bool ignoreEnterEvent(quint8 mode, quint8 detail)
+static bool ignoreEnterEvent(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_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);
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index c72761f2ae..f639be809c 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -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;
}
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 9306b20043..7b393463a6 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -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;
- 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->orientation == Qt::Horizontal) {
+ int logicalLeft = max;
+ int logicalRight = 0;
+
+ 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;
-
- 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;
- }
-
- int logicalTop = logicalIndex(top);
- int logicalBottom = logicalIndex(bottom);
-
- if (logicalTop == -1 || logicalBottom == -1)
- return QRect();
+ int logicalTop = max;
+ int logicalBottom = 0;
+
+ 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);
+ }
+
+ if (logicalTop < 0 || logicalTop >= count() ||
+ logicalBottom < 0 || logicalBottom >= count())
+ return QRegion();
int topPos = sectionViewportPosition(logicalTop);
int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 281567cede..5826116a96 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -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);
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 5b6e47e2c6..0dd3610164 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -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);
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index a0bc924dd9..dce0a93e10 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -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,