Merge remote-tracking branch 'origin/5.5' into 5.6

Conflicts:
	qmake/doc/src/qmake-manual.qdoc
	src/corelib/tools/qstring.h
	src/gui/image/qimagereader.cpp
	src/network/access/qnetworkaccessmanager.cpp
	src/tools/qdoc/doc/examples/examples.qdoc
	src/widgets/accessible/qaccessiblewidgetfactory_p.h
	src/widgets/doc/qtwidgets.qdocconf

Change-Id: I8fae62283aebefe24e5ca4b4abd97386560c0fcb
This commit is contained in:
Liang Qi 2015-10-02 14:23:08 +02:00
commit d0eaa737e1
144 changed files with 1816 additions and 526 deletions

View File

@ -27,24 +27,16 @@
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment-qnx.html \externalpage http://doc.qt.io/qtcreator/creator-deployment-qnx.html
\title Qt Creator: Deploying Applications to QNX Devices \title Qt Creator: Deploying Applications to QNX Neutrino Devices
*/ */
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-baremetal.html \externalpage http://doc.qt.io/qtcreator/creator-developing-baremetal.html
\title Qt Creator: Connecting Bare Metal Devices \title Qt Creator: Connecting Bare Metal Devices
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-bb10.html
\title Qt Creator: Connecting BlackBerry 10 Devices
*/
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-qnx.html \externalpage http://doc.qt.io/qtcreator/creator-developing-qnx.html
\title Qt Creator: Connecting QNX Devices \title Qt Creator: Connecting QNX Devices
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment-bb10.html
\title Qt Creator: Deploying Applications to BlackBerry 10 Devices
*/
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-generic-linux.html \externalpage http://doc.qt.io/qtcreator/creator-developing-generic-linux.html
\title Qt Creator: Connecting Embedded Linux Devices \title Qt Creator: Connecting Embedded Linux Devices
@ -98,7 +90,19 @@
\title Qt Creator: Creating Screens \title Qt Creator: Creating Screens
*/ */
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-qml-application.html \externalpage http://doc.qt.io/qtcreator/creator-qtquick-designer-extensions.html
\title Qt Creator: Using Qt Quick Designer Extensions
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qmldesigner-pathview-editor.html
\title Qt Creator: Editing PathView Properties
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qmldesigner-connections.html
\title Qt Creator: Adding Connections
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html
\title Qt Creator: Creating a Qt Quick Application \title Qt Creator: Creating a Qt Quick Application
*/ */
/*! /*!
@ -279,7 +283,7 @@
*/ */
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-testing.html \externalpage http://doc.qt.io/qtcreator/creator-testing.html
\title Qt Creator: Debugging and Analyzing \title Qt Creator: Testing
*/ */
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment.html \externalpage http://doc.qt.io/qtcreator/creator-deployment.html
@ -297,10 +301,6 @@
\externalpage http://doc.qt.io/qtcreator/creator-design-mode.html \externalpage http://doc.qt.io/qtcreator/creator-design-mode.html
\title Qt Creator: Designing User Interfaces \title Qt Creator: Designing User Interfaces
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/creator-publish-ovi.html
\title Qt Creator: Publishing
*/
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-glossary.html \externalpage http://doc.qt.io/qtcreator/creator-glossary.html
\title Qt Creator: Glossary \title Qt Creator: Glossary
@ -499,7 +499,19 @@
\externalpage http://doc.qt.io/qtcreator/creator-quick-ui-forms.html \externalpage http://doc.qt.io/qtcreator/creator-quick-ui-forms.html
\title Qt Creator: Qt Quick UI Forms \title Qt Creator: Qt Quick UI Forms
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/qtcreator-uiforms-example.html
\title Qt Creator: Using Qt Quick UI Forms
*/
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-clang-static-analyzer.html \externalpage http://doc.qt.io/qtcreator/creator-clang-static-analyzer.html
\title Qt Creator: Using Clang Static Analyzer \title Qt Creator: Using Clang Static Analyzer
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/creator-cpu-usage-analyzer.html
\title Qt Creator: Analyzing CPU Usage
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-autotest.html
\title Qt Creator: Running Autotests
*/

View File

@ -2,7 +2,7 @@ naturallanguage = en
outputencoding = UTF-8 outputencoding = UTF-8
sourceencoding = UTF-8 sourceencoding = UTF-8
examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css" examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css *.glsl"
examples.imageextensions = "*.png *.jpg *.gif" examples.imageextensions = "*.png *.jpg *.gif"
headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"

View File

@ -35,37 +35,4 @@
supported by the Qt Network APIs. supported by the Qt Network APIs.
\image torrent-example.png \image torrent-example.png
\section1 License Information
The implementation of the US Secure Hash Algorithm 1 (SHA1) in this example is
derived from the original description in \l{http://www.rfc-editor.org/rfc/rfc3174.txt}{RFC 3174}.
\legalese
Copyright (C) The Internet Society (2001). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
\endlegalese
*/ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,183 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\example desktop/systray
\title System Tray Icon Example
The System Tray Icon example shows how to add an icon with a menu
and popup messages to a desktop environment's system tray.
\image systemtray-example.png Screenshot of the System Tray Icon.
Modern operating systems usually provide a special area on the
desktop, called the system tray or notification area, where
long-running applications can display icons and short messages.
This example consists of one single class, \c Window, providing
the main application window (i.e., an editor for the system tray
icon) and the associated icon.
\image systemtray-editor.png
The editor allows the user to choose the preferred icon as well as
set the balloon message's type and duration. The user can also
edit the message's title and body. Finally, the editor provide a
checkbox controlling whether the icon is actually shown in the
system tray, or not.
\section1 Window Class Definition
The \c Window class inherits QWidget:
\snippet desktop/systray/window.h 0
We implement several private slots to respond to user
interaction. The other private functions are only convenience
functions provided to simplify the constructor.
The tray icon is an instance of the QSystemTrayIcon class. To
check whether a system tray is present on the user's desktop, call
the static QSystemTrayIcon::isSystemTrayAvailable()
function. Associated with the icon, we provide a menu containing
the typical \gui minimize, \gui maximize, \gui restore and \gui
quit actions. We reimplement the QWidget::setVisible() function to
update the tray icon's menu whenever the editor's appearance
changes, e.g., when maximizing or minimizing the main application
window.
Finally, we reimplement QWidget's \l {QWidget::}{closeEvent()}
function to be able to inform the user (when closing the editor
window) that the program will keep running in the system tray
until the user chooses the \gui Quit entry in the icon's context
menu.
\section1 Window Class Implementation
When constructing the editor widget, we first create the various
editor elements before we create the actual system tray icon:
\snippet desktop/systray/window.cpp 0
We ensure that the application responds to user input by
connecting most of the editor's input widgets (including the
system tray icon) to the application's private slots. But note the
visibility checkbox; its \l {QCheckBox::}{toggled()} signal is
connected to the \e {icon}'s \l {QSystemTrayIcon::}{setVisible()}
function instead.
\snippet desktop/systray/window.cpp 3
The \c setIcon() slot is triggered whenever the current index in
the icon combobox changes, i.e., whenever the user chooses another
icon in the editor. Note that it is also called when the user
activates the tray icon with the left mouse button, triggering the
icon's \l {QSystemTrayIcon::}{activated()} signal. We will come
back to this signal shortly.
The QSystemTrayIcon::setIcon() function sets the \l
{QSystemTrayIcon::}{icon} property that holds the actual system
tray icon. On Windows, the system tray icon size is 16x16; on X11,
the preferred size is 22x22. The icon will be scaled to the
appropriate size as necessary.
Note that on X11, due to a limitation in the system tray
specification, mouse clicks on transparent areas in the icon are
propagated to the system tray. If this behavior is unacceptable,
we suggest using an icon with no transparency.
\snippet desktop/systray/window.cpp 4
Whenever the user activates the system tray icon, it emits its \l
{QSystemTrayIcon::}{activated()} signal passing the triggering
reason as parameter. QSystemTrayIcon provides the \l
{QSystemTrayIcon::}{ActivationReason} enum to describe how the
icon was activated.
In the constructor, we connected our icon's \l
{QSystemTrayIcon::}{activated()} signal to our custom \c
iconActivated() slot: If the user has clicked the icon using the
left mouse button, this function changes the icon image by
incrementing the icon combobox's current index, triggering the \c
setIcon() slot as mentioned above. If the user activates the icon
using the middle mouse button, it calls the custom \c
showMessage() slot:
\snippet desktop/systray/window.cpp 5
When the \e showMessage() slot is triggered, we first retrieve the
message icon depending on the currently chosen message type. The
QSystemTrayIcon::MessageIcon enum describes the icon that is shown
when a balloon message is displayed. Then we call
QSystemTrayIcon's \l {QSystemTrayIcon::}{showMessage()} function
to show the message with the title, body, and icon for the time
specified in milliseconds.
OS X users note: The Growl notification system must be
installed for QSystemTrayIcon::showMessage() to display messages.
QSystemTrayIcon also has the corresponding, \l {QSystemTrayIcon::}
{messageClicked()} signal, which is emitted when the user clicks a
message displayed by \l {QSystemTrayIcon::}{showMessage()}.
\snippet desktop/systray/window.cpp 6
In the constructor, we connected the \l
{QSystemTrayIcon::}{messageClicked()} signal to our custom \c
messageClicked() slot that simply displays a message using the
QMessageBox class.
QMessageBox provides a modal dialog with a short message, an icon,
and buttons laid out depending on the current style. It supports
four severity levels: "Question", "Information", "Warning" and
"Critical". The easiest way to pop up a message box in Qt is to
call one of the associated static functions, e.g.,
QMessageBox::information().
As we mentioned earlier, we reimplement a couple of QWidget's
virtual functions:
\snippet desktop/systray/window.cpp 1
Our reimplementation of the QWidget::setVisible() function updates
the tray icon's menu whenever the editor's appearance changes,
e.g., when maximizing or minimizing the main application window,
before calling the base class implementation.
\snippet desktop/systray/window.cpp 2
We have reimplemented the QWidget::closeEvent() event handler to
receive widget close events, showing the above message to the
users when they are closing the editor window.
In addition to the functions and slots discussed above, we have
also implemented several convenience functions to simplify the
constructor: \c createIconGroupBox(), \c createMessageGroupBox(),
\c createActions() and \c createTrayIcon(). See the \l
{desktop/systray/window.cpp}{window.cpp} file for details.
*/

View File

@ -16,7 +16,7 @@ MOC_INCLUDEPATH = $$QMAKESPEC $$_PRO_FILE_PWD_ $$MOC_INCLUDEPATH $$QMAKE_DEFAULT
# has too many includes. We do this to overcome a command-line limit on Win < XP # has too many includes. We do this to overcome a command-line limit on Win < XP
WIN_INCLUDETEMP= WIN_INCLUDETEMP=
win32:count(MOC_INCLUDEPATH, 40, >) { win32:count(MOC_INCLUDEPATH, 40, >) {
WIN_INCLUDETEMP = $$MOC_DIR/mocinclude.tmp WIN_INCLUDETEMP = $$MOC_DIR/mocinclude.opt
WIN_INCLUDETEMP_CONT = WIN_INCLUDETEMP_CONT =
for (inc, MOC_INCLUDEPATH): \ for (inc, MOC_INCLUDEPATH): \

View File

@ -3253,7 +3253,8 @@ MakefileGenerator::writePkgConfigFile()
int suffix = bundle.lastIndexOf(".framework"); int suffix = bundle.lastIndexOf(".framework");
if (suffix != -1) if (suffix != -1)
bundle = bundle.left(suffix); bundle = bundle.left(suffix);
pkgConfiglibName = "-framework " + bundle + " "; t << "-framework ";
pkgConfiglibName = bundle.toQString();
} else { } else {
if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir)) if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir))
t << "-L${libdir} "; t << "-L${libdir} ";

View File

@ -655,6 +655,7 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) { switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
case NET2015: case NET2015:
t << _slnHeader140; t << _slnHeader140;
break;
case NET2013: case NET2013:
t << _slnHeader120; t << _slnHeader120;
break; break;
@ -1036,6 +1037,17 @@ void VcprojGenerator::initConfiguration()
conf.suppressUnknownOptionWarnings = project->isActiveConfig("suppress_vcproj_warnings"); conf.suppressUnknownOptionWarnings = project->isActiveConfig("suppress_vcproj_warnings");
conf.CompilerVersion = which_dotnet_version(project->first("MSVC_VER").toLatin1()); conf.CompilerVersion = which_dotnet_version(project->first("MSVC_VER").toLatin1());
if (conf.CompilerVersion >= NET2012) {
conf.WinRT = project->isActiveConfig("winrt");
if (conf.WinRT) {
conf.WinPhone = project->isActiveConfig("winphone");
// Saner defaults
conf.compiler.UsePrecompiledHeader = pchNone;
conf.compiler.CompileAsWinRT = _False;
conf.linker.GenerateWindowsMetadata = _False;
}
}
initCompilerTool(); initCompilerTool();
// Only on configuration per build // Only on configuration per build
@ -1082,17 +1094,6 @@ void VcprojGenerator::initConfiguration()
conf.PrimaryOutputExtension = '.' + targetSuffix; conf.PrimaryOutputExtension = '.' + targetSuffix;
} }
if (conf.CompilerVersion >= NET2012) {
conf.WinRT = project->isActiveConfig("winrt");
if (conf.WinRT) {
conf.WinPhone = project->isActiveConfig("winphone");
// Saner defaults
conf.compiler.UsePrecompiledHeader = pchNone;
conf.compiler.CompileAsWinRT = _False;
conf.linker.GenerateWindowsMetadata = _False;
}
}
conf.Name = project->values("BUILD_NAME").join(' '); conf.Name = project->values("BUILD_NAME").join(' ');
if (conf.Name.isEmpty()) if (conf.Name.isEmpty())
conf.Name = isDebug ? "Debug" : "Release"; conf.Name = isDebug ? "Debug" : "Release";

View File

@ -45,12 +45,12 @@
#ifdef __linux__ #ifdef __linux__
# define HAVE_WAIT4 1 # define HAVE_WAIT4 1
# if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x207 && \ # if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x207 && \
(!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921))) (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201)))
# include <sys/eventfd.h> # include <sys/eventfd.h>
# define HAVE_EVENTFD 1 # define HAVE_EVENTFD 1
# endif # endif
# if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x209 && \ # if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x209 && \
(!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921))) (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201)))
# define HAVE_PIPE2 1 # define HAVE_PIPE2 1
# endif # endif
#endif #endif
@ -721,7 +721,7 @@ err_free:
} }
#endif // FORKFD_NO_FORKFD #endif // FORKFD_NO_FORKFD
#if defined(_POSIX_SPAWN) && !defined(FORKFD_NO_SPAWNFD) #if _POSIX_SPAWN > 0 && !defined(FORKFD_NO_SPAWNFD)
int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_actions_t *file_actions, int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_actions_t *file_actions,
posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) posix_spawnattr_t *attrp, char *const argv[], char *const envp[])
{ {

View File

@ -29,7 +29,7 @@
#include <stdint.h> #include <stdint.h>
#include <unistd.h> // to get the POSIX flags #include <unistd.h> // to get the POSIX flags
#ifdef _POSIX_SPAWN #if _POSIX_SPAWN > 0
# include <spawn.h> # include <spawn.h>
#endif #endif
@ -51,7 +51,7 @@ int forkfd(int flags, pid_t *ppid);
int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage); int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage);
int forkfd_close(int ffd); int forkfd_close(int ffd);
#ifdef _POSIX_SPAWN #if _POSIX_SPAWN > 0
/* only for spawnfd: */ /* only for spawnfd: */
# define FFD_SPAWN_SEARCH_PATH O_RDWR # define FFD_SPAWN_SEARCH_PATH O_RDWR

View File

@ -1035,16 +1035,16 @@ bool QBasicAtomicOps<size>::deref(T &_q_value) Q_DECL_NOTHROW
} }
template<int size> template <typename T> inline template<int size> template <typename T> inline
bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
{ {
return testAndSetAcquire(_q_value, expectedValue, newValue); return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue);
} }
template<int size> template <typename T> inline template<int size> template <typename T> inline
bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
{ {
orderedMemoryFence(_q_value); orderedMemoryFence(_q_value);
return testAndSetAcquire(_q_value, expectedValue, newValue); return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue);
} }
template<int size> template <typename T> inline template<int size> template <typename T> inline

View File

@ -25,8 +25,7 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags tagfile = ../../../doc/qtcore/qtcore.tags
depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml
# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630
headerdirs += .. headerdirs += ..

View File

@ -71,6 +71,8 @@
which are currently active. All the states in a valid configuration of the state machine will which are currently active. All the states in a valid configuration of the state machine will
have a common ancestor. have a common ancestor.
\sa {The Declarative State Machine Framework}
\section1 Classes in the State Machine Framework \section1 Classes in the State Machine Framework
These classes are provided by qt for creating event-driven state machines. These classes are provided by qt for creating event-driven state machines.

View File

@ -1714,6 +1714,17 @@
\value Key_Zoom \value Key_Zoom
\value Key_Exit \value Key_Exit
\value Key_Cancel \value Key_Cancel
\value Key_MicVolumeUp
\value Key_Find
\value Key_Open
\value Key_MicVolumeDown
\value Key_New
\value Key_Settings
\value Key_Redo
\value Key_Exit
\value Key_Info
\value Key_Undo
\value Key_Guide
\sa QKeyEvent::key() \sa QKeyEvent::key()
*/ */

View File

@ -83,6 +83,7 @@ void debugBinaryString(const char *data, qint64 maxlen)
static void checkWarnMessage(const QIODevice *device, const char *function, const char *what) static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
{ {
#ifndef QT_NO_WARNING_OUTPUT
QDebug d = qWarning(); QDebug d = qWarning();
d.noquote(); d.noquote();
d.nospace(); d.nospace();
@ -98,6 +99,11 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
Q_UNUSED(device) Q_UNUSED(device)
#endif // !QT_NO_QOBJECT #endif // !QT_NO_QOBJECT
d << ": " << what; d << ": " << what;
#else
Q_UNUSED(device);
Q_UNUSED(function);
Q_UNUSED(what);
#endif // QT_NO_WARNING_OUTPUT
} }
#define CHECK_MAXLEN(function, returnType) \ #define CHECK_MAXLEN(function, returnType) \

View File

@ -56,7 +56,13 @@
# include <cstdio> # include <cstdio>
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
# include <sys/user.h> # include <sys/user.h>
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
# include <sys/cdefs.h>
# include <sys/param.h>
# include <sys/sysctl.h>
# else
# include <libutil.h> # include <libutil.h>
# endif
#endif #endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -241,9 +247,27 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
buf[len] = 0; buf[len] = 0;
return QFileInfo(QFile::decodeName(buf)).fileName(); return QFileInfo(QFile::decodeName(buf)).fileName();
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
size_t len = 0;
if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0)
return QString();
kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len));
# else
kinfo_proc *proc = kinfo_getproc(pid); kinfo_proc *proc = kinfo_getproc(pid);
# endif
if (!proc) if (!proc)
return QString(); return QString();
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) {
free(proc);
return QString();
}
if (proc->ki_pid != pid) {
free(proc);
return QString();
}
# endif
QString name = QFile::decodeName(proc->ki_comm); QString name = QFile::decodeName(proc->ki_comm);
free(proc); free(proc);
return name; return name;

View File

@ -200,7 +200,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
case AppDataLocation: case AppDataLocation:
case AppLocalDataLocation: case AppLocalDataLocation:
case GenericDataLocation: case GenericDataLocation:
if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) { if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) {
QString result = convertCharArray(path); QString result = convertCharArray(path);
if (type != GenericDataLocation && type != GenericConfigLocation) { if (type != GenericDataLocation && type != GenericConfigLocation) {
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED

View File

@ -2858,7 +2858,7 @@ QTextStream &endl(QTextStream &stream)
/*! /*!
\relates QTextStream \relates QTextStream
Calls \l{QTextStream::flush()}{flush()} on \a stream and returns \a stream. Calls QTextStream::flush() on \a stream and returns \a stream.
\sa endl(), reset(), {QTextStream manipulators} \sa endl(), reset(), {QTextStream manipulators}
*/ */

View File

@ -187,7 +187,7 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
pipeBroken = true; pipeBroken = true;
break; break;
default: default:
emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead")); emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified"));
pipeBroken = true; pipeBroken = true;
break; break;
} }

View File

@ -90,11 +90,38 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
return maxlen; return maxlen;
} }
class QPipeWriterOverlapped
{
public:
QPipeWriterOverlapped()
{
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}
~QPipeWriterOverlapped()
{
CloseHandle(overlapped.hEvent);
}
void prepare()
{
const HANDLE hEvent = overlapped.hEvent;
ZeroMemory(&overlapped, sizeof overlapped);
overlapped.hEvent = hEvent;
}
OVERLAPPED *operator&()
{
return &overlapped;
}
private:
OVERLAPPED overlapped;
};
void QWindowsPipeWriter::run() void QWindowsPipeWriter::run()
{ {
OVERLAPPED overl; QPipeWriterOverlapped overl;
memset(&overl, 0, sizeof overl);
overl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
forever { forever {
lock.lock(); lock.lock();
while(data.isEmpty() && (!quitNow)) { while(data.isEmpty() && (!quitNow)) {
@ -115,26 +142,24 @@ void QWindowsPipeWriter::run()
const char *ptrData = copy.data(); const char *ptrData = copy.data();
qint64 maxlen = copy.size(); qint64 maxlen = copy.size();
qint64 totalWritten = 0; qint64 totalWritten = 0;
overl.Offset = 0; overl.prepare();
overl.OffsetHigh = 0;
while ((!quitNow) && totalWritten < maxlen) { while ((!quitNow) && totalWritten < maxlen) {
DWORD written = 0; DWORD written = 0;
if (!WriteFile(writePipe, ptrData + totalWritten, if (!WriteFile(writePipe, ptrData + totalWritten,
maxlen - totalWritten, &written, &overl)) { maxlen - totalWritten, &written, &overl)) {
const DWORD writeError = GetLastError();
if (GetLastError() == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) { if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
// give the os a rest // give the os a rest
msleep(100); msleep(100);
continue; continue;
} }
#ifndef Q_OS_WINCE #ifndef Q_OS_WINCE
if (GetLastError() == ERROR_IO_PENDING) { if (writeError != ERROR_IO_PENDING) {
if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) { qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed.");
CloseHandle(overl.hEvent); return;
return; }
} if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
} else { qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed.");
CloseHandle(overl.hEvent);
return; return;
} }
#else #else
@ -154,7 +179,6 @@ void QWindowsPipeWriter::run()
emit bytesWritten(totalWritten); emit bytesWritten(totalWritten);
emit canWrite(); emit canWrite();
} }
CloseHandle(overl.hEvent);
} }
#endif //QT_NO_THREAD #endif //QT_NO_THREAD

View File

@ -455,8 +455,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
qt_application_thread_id = QThread::currentThreadId(); qt_application_thread_id = QThread::currentThreadId();
# endif # endif
// note: this call to QThread::currentThread() may end up setting theMainThread! QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
if (QThread::currentThread() != theMainThread) if (cur != theMainThread)
qWarning("WARNING: QApplication was not created in the main() thread."); qWarning("WARNING: QApplication was not created in the main() thread.");
#endif #endif
} }
@ -526,11 +526,11 @@ void QCoreApplicationPrivate::eventDispatcherReady()
{ {
} }
QThread *QCoreApplicationPrivate::theMainThread = 0; QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0);
QThread *QCoreApplicationPrivate::mainThread() QThread *QCoreApplicationPrivate::mainThread()
{ {
Q_ASSERT(theMainThread != 0); Q_ASSERT(theMainThread.load() != 0);
return theMainThread; return theMainThread.load();
} }
bool QCoreApplicationPrivate::threadRequiresCoreApplication() bool QCoreApplicationPrivate::threadRequiresCoreApplication()
@ -2759,7 +2759,7 @@ bool QCoreApplication::hasPendingEvents()
QAbstractEventDispatcher *QCoreApplication::eventDispatcher() QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{ {
if (QCoreApplicationPrivate::theMainThread) if (QCoreApplicationPrivate::theMainThread)
return QCoreApplicationPrivate::theMainThread->eventDispatcher(); return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher();
return 0; return 0;
} }

View File

@ -105,7 +105,7 @@ public:
} }
void maybeQuit(); void maybeQuit();
static QThread *theMainThread; static QBasicAtomicPointer<QThread> theMainThread;
static QThread *mainThread(); static QThread *mainThread();
static bool threadRequiresCoreApplication(); static bool threadRequiresCoreApplication();

View File

@ -390,6 +390,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QSockNot *sn = dict ? dict->value(wp) : 0; QSockNot *sn = dict ? dict->value(wp) : 0;
if (sn) { if (sn) {
d->doWsaAsyncSelect(sn->fd, 0);
d->active_fd[sn->fd].selected = false;
if (type < 3) { if (type < 3) {
QEvent event(QEvent::SockAct); QEvent event(QEvent::SockAct);
QCoreApplication::sendEvent(sn->obj, &event); QCoreApplication::sendEvent(sn->obj, &event);
@ -632,19 +634,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
} }
} }
void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket) void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event)
{ {
Q_ASSERT(internalHwnd); Q_ASSERT(internalHwnd);
int sn_event = 0; // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
if (sn_read.contains(socket))
sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
if (sn_write.contains(socket))
sn_event |= FD_WRITE | FD_CONNECT;
if (sn_except.contains(socket))
sn_event |= FD_OOB;
// BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
// This is a BoundsChecker bug and not a Qt bug // This is a BoundsChecker bug and not a Qt bug
WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event); WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event);
} }
void QEventDispatcherWin32::createInternalHwnd() void QEventDispatcherWin32::createInternalHwnd()
@ -657,13 +652,6 @@ void QEventDispatcherWin32::createInternalHwnd()
installMessageHook(); installMessageHook();
// register all socket notifiers
QList<int> sockets = (d->sn_read.keys().toSet()
+ d->sn_write.keys().toSet()
+ d->sn_except.keys().toSet()).toList();
for (int i = 0; i < sockets.count(); ++i)
d->doWsaAsyncSelect(sockets.at(i));
// start all normal timers // start all normal timers
for (int i = 0; i < d->timerVec.count(); ++i) for (int i = 0; i < d->timerVec.count(); ++i)
d->registerTimer(d->timerVec.at(i)); d->registerTimer(d->timerVec.at(i));
@ -748,28 +736,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
msg = d->queuedSocketEvents.takeFirst(); msg = d->queuedSocketEvents.takeFirst();
} else { } else {
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) if (haveMessage) {
&& ((msg.message >= WM_KEYFIRST if ((flags & QEventLoop::ExcludeUserInputEvents)
&& msg.message <= WM_KEYLAST) && ((msg.message >= WM_KEYFIRST
|| (msg.message >= WM_MOUSEFIRST && msg.message <= WM_KEYLAST)
&& msg.message <= WM_MOUSELAST) || (msg.message >= WM_MOUSEFIRST
|| msg.message == WM_MOUSEWHEEL && msg.message <= WM_MOUSELAST)
|| msg.message == WM_MOUSEHWHEEL || msg.message == WM_MOUSEWHEEL
|| msg.message == WM_TOUCH || msg.message == WM_MOUSEHWHEEL
|| msg.message == WM_TOUCH
#ifndef QT_NO_GESTURES #ifndef QT_NO_GESTURES
|| msg.message == WM_GESTURE || msg.message == WM_GESTURE
|| msg.message == WM_GESTURENOTIFY || msg.message == WM_GESTURENOTIFY
#endif #endif
|| msg.message == WM_CLOSE)) { || msg.message == WM_CLOSE)) {
// queue user input events for later processing // queue user input events for later processing
haveMessage = false; d->queuedUserInputEvents.append(msg);
d->queuedUserInputEvents.append(msg); continue;
} }
if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) if ((flags & QEventLoop::ExcludeSocketNotifiers)
&& (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
// queue socket events for later processing // queue socket events for later processing
haveMessage = false; d->queuedSocketEvents.append(msg);
d->queuedSocketEvents.append(msg); continue;
}
} else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) {
// register all socket notifiers
for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
it != end; ++it) {
QSockFd &sd = it.value();
if (!sd.selected) {
d->doWsaAsyncSelect(it.key(), sd.event);
sd.selected = true;
}
}
} }
} }
if (!haveMessage) { if (!haveMessage) {
@ -895,8 +895,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
sn->fd = sockfd; sn->fd = sockfd;
dict->insert(sn->fd, sn); dict->insert(sn->fd, sn);
if (d->internalHwnd) long event = 0;
d->doWsaAsyncSelect(sockfd); if (d->sn_read.contains(sockfd))
event |= FD_READ | FD_CLOSE | FD_ACCEPT;
if (d->sn_write.contains(sockfd))
event |= FD_WRITE | FD_CONNECT;
if (d->sn_except.contains(sockfd))
event |= FD_OOB;
QSFDict::iterator it = d->active_fd.find(sockfd);
if (it != d->active_fd.end()) {
QSockFd &sd = it.value();
if (sd.selected) {
d->doWsaAsyncSelect(sockfd, 0);
sd.selected = false;
}
sd.event |= event;
} else {
d->active_fd.insert(sockfd, QSockFd(event));
}
} }
void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
@ -915,6 +932,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
#endif #endif
Q_D(QEventDispatcherWin32); Q_D(QEventDispatcherWin32);
QSFDict::iterator it = d->active_fd.find(sockfd);
if (it != d->active_fd.end()) {
QSockFd &sd = it.value();
if (sd.selected)
d->doWsaAsyncSelect(sockfd, 0);
const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB };
sd.event ^= event[type];
if (sd.event == 0)
d->active_fd.erase(it);
else
sd.selected = false;
}
QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
QSNDict *dict = sn_vec[type]; QSNDict *dict = sn_vec[type];
QSockNot *sn = dict->value(sockfd); QSockNot *sn = dict->value(sockfd);
@ -923,9 +953,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
dict->remove(sockfd); dict->remove(sockfd);
delete sn; delete sn;
if (d->internalHwnd)
d->doWsaAsyncSelect(sockfd);
} }
void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
@ -1163,6 +1190,7 @@ void QEventDispatcherWin32::closingDown()
unregisterSocketNotifier((*(d->sn_write.begin()))->obj); unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
while (!d->sn_except.isEmpty()) while (!d->sn_except.isEmpty())
unregisterSocketNotifier((*(d->sn_except.begin()))->obj); unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
// clean up any timers // clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i) for (int i = 0; i < d->timerVec.count(); ++i)

View File

@ -115,6 +115,14 @@ struct QSockNot {
}; };
typedef QHash<int, QSockNot *> QSNDict; typedef QHash<int, QSockNot *> QSNDict;
struct QSockFd {
long event;
bool selected;
explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { }
};
typedef QHash<int, QSockFd> QSFDict;
struct WinTimerInfo { // internal timer info struct WinTimerInfo { // internal timer info
QObject *dispatcher; QObject *dispatcher;
int timerId; int timerId;
@ -169,7 +177,8 @@ public:
QSNDict sn_read; QSNDict sn_read;
QSNDict sn_write; QSNDict sn_write;
QSNDict sn_except; QSNDict sn_except;
void doWsaAsyncSelect(int socket); QSFDict active_fd;
void doWsaAsyncSelect(int socket, long event);
QList<QWinEventNotifier *> winEventNotifierList; QList<QWinEventNotifier *> winEventNotifierList;
void activateEventNotifier(QWinEventNotifier * wen); void activateEventNotifier(QWinEventNotifier * wen);

View File

@ -1547,12 +1547,13 @@ bool QMetaObject::invokeMethod(QObject *obj,
/*! /*!
\fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other) \fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other)
Move-assigns \a other to this object. Move-assigns \a other to this object, and returns a reference.
*/ */
/*! /*!
\fn QMetaObject::Connection::Connection(Connection &&o) \fn QMetaObject::Connection::Connection(Connection &&o)
Move-constructs a Connection instance, making it point to the same object that \a o was pointing to. Move-constructs a Connection instance, making it point to the same object
that \a o was pointing to.
*/ */
/*! /*!

View File

@ -1485,7 +1485,7 @@ void QObject::moveToThread(QThread *targetThread)
} else if (d->threadData != currentData) { } else if (d->threadData != currentData) {
qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
"Cannot move to target thread (%p)\n", "Cannot move to target thread (%p)\n",
currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR); currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
qWarning("You might be loading two sets of Qt binaries into the same process. " qWarning("You might be loading two sets of Qt binaries into the same process. "

View File

@ -98,42 +98,6 @@ public:
QTcpSocket and QUdpSocket provide notification through signals, so QTcpSocket and QUdpSocket provide notification through signals, so
there is normally no need to use a QSocketNotifier on them. there is normally no need to use a QSocketNotifier on them.
\section1 Notes for Windows Users
The socket passed to QSocketNotifier will become non-blocking, even if
it was created as a blocking socket.
The activated() signal is sometimes triggered by high general activity
on the host, even if there is nothing to read. A subsequent read from
the socket can then fail, the error indicating that there is no data
available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
limitation, and not a bug in QSocketNotifier.
To ensure that the socket notifier handles read notifications correctly,
follow these steps when you receive a notification:
\list 1
\li Disable the notifier.
\li Read data from the socket.
\li Re-enable the notifier if you are interested in more data (such as after
having written a new command to a remote server).
\endlist
To ensure that the socket notifier handles write notifications correctly,
follow these steps when you receive a notification:
\list 1
\li Disable the notifier.
\li Write as much data as you can (before \c EWOULDBLOCK is returned).
\li Re-enable notifier if you have more data to write.
\endlist
\b{Further information:}
On Windows, Qt always disables the notifier after getting a notification,
and only re-enables it if more data is expected. For example, if data is
read from the socket and it can be used to read more, or if reading or
writing is not possible because the socket would block, in which case
it is necessary to wait before attempting to read or write again.
\sa QFile, QProcess, QTcpSocket, QUdpSocket \sa QFile, QProcess, QTcpSocket, QUdpSocket
*/ */

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -38,6 +38,7 @@
#ifndef QT_NO_MIMETYPE #ifndef QT_NO_MIMETYPE
#include "qmimetypeparser_p.h"
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <qendian.h> #include <qendian.h>
@ -231,26 +232,53 @@ static inline QByteArray makePattern(const QByteArray &value)
return pattern; return pattern;
} }
QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, // Evaluate a magic match rule like
// <match value="must be converted with BinHex" type="string" offset="11"/>
// <match value="0x9501" type="big16" offset="0:64"/>
QMimeMagicRule::QMimeMagicRule(const QString &typeStr,
const QByteArray &theValue, const QByteArray &theValue,
int theStartPos, const QString &offsets,
int theEndPos, const QByteArray &theMask,
const QByteArray &theMask) : QString *errorString) :
d(new QMimeMagicRulePrivate) d(new QMimeMagicRulePrivate)
{ {
Q_ASSERT(!theValue.isEmpty());
d->type = theType;
d->value = theValue; d->value = theValue;
d->startPos = theStartPos;
d->endPos = theEndPos;
d->mask = theMask; d->mask = theMask;
d->matchFunction = 0; d->matchFunction = 0;
d->type = QMimeMagicRule::type(typeStr.toLatin1());
if (d->type == Invalid) {
*errorString = QStringLiteral("Type %s is not supported").arg(typeStr);
}
// Parse for offset as "1" or "1:10"
const int colonIndex = offsets.indexOf(QLatin1Char(':'));
const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex);
const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1);
if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) ||
!QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) {
d->type = Invalid;
return;
}
if (d->value.isEmpty()) {
d->type = Invalid;
if (errorString)
*errorString = QLatin1String("Invalid empty magic rule value");
return;
}
if (d->type >= Host16 && d->type <= Byte) { if (d->type >= Host16 && d->type <= Byte) {
bool ok; bool ok;
d->number = d->value.toUInt(&ok, 0); // autodetect d->number = d->value.toUInt(&ok, 0); // autodetect
Q_ASSERT(ok); if (!ok) {
d->type = Invalid;
if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg(
QString::fromLatin1(d->value));
return;
}
d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect
} }
@ -259,9 +287,23 @@ QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
d->pattern = makePattern(d->value); d->pattern = makePattern(d->value);
d->pattern.squeeze(); d->pattern.squeeze();
if (!d->mask.isEmpty()) { if (!d->mask.isEmpty()) {
Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x")); if (d->mask.size() < 4 || !d->mask.startsWith("0x")) {
d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2)); d->type = Invalid;
Q_ASSERT(d->mask.size() == d->pattern.size()); if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg(
QString::fromLatin1(d->mask));
return;
}
const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
d->mask.constData() + 2, d->mask.size() - 2));
if (tempMask.size() != d->pattern.size()) {
d->type = Invalid;
if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg(
QString::fromLatin1(d->mask));
return;
}
d->mask = tempMask;
} else { } else {
d->mask.fill(char(-1), d->pattern.size()); d->mask.fill(char(-1), d->pattern.size());
} }

View File

@ -61,7 +61,8 @@ class QMimeMagicRule
public: public:
enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte }; enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte };
QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray()); QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets,
const QByteArray &mask, QString *errorString);
QMimeMagicRule(const QMimeMagicRule &other); QMimeMagicRule(const QMimeMagicRule &other);
~QMimeMagicRule(); ~QMimeMagicRule();

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/ ** Contact: http://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -153,8 +153,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren
return ParseError; return ParseError;
} }
// Parse int number from an (attribute) string) // Parse int number from an (attribute) string
static bool parseNumber(const QString &n, int *target, QString *errorMessage) bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage)
{ {
bool ok; bool ok;
*target = n.toInt(&ok); *target = n.toInt(&ok);
@ -165,37 +165,14 @@ static bool parseNumber(const QString &n, int *target, QString *errorMessage)
return true; return true;
} }
// Evaluate a magic match rule like
// <match value="must be converted with BinHex" type="string" offset="11"/>
// <match value="0x9501" type="big16" offset="0:64"/>
#ifndef QT_NO_XMLSTREAMREADER #ifndef QT_NO_XMLSTREAMREADER
static bool createMagicMatchRule(const QXmlStreamAttributes &atts, static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage)
QString *errorMessage, QMimeMagicRule *&rule)
{ {
const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString(); const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString();
QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1());
if (magicType == QMimeMagicRule::Invalid) {
qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData());
return true;
}
const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString(); const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString();
if (value.isEmpty()) { const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
*errorMessage = QString::fromLatin1("Empty match value detected.");
return false;
}
// Parse for offset as "1" or "1:10"
int startPos, endPos;
const QString offsetS = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
const int colonIndex = offsetS.indexOf(QLatin1Char(':'));
const QString startPosS = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex);
const QString endPosS = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1);
if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage))
return false;
const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString(); const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString();
return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage);
rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1());
return true;
} }
#endif #endif
@ -283,9 +260,10 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
} }
break; break;
case ParseMagicMatchRule: { case ParseMagicMatchRule: {
QMimeMagicRule *rule = 0; QString magicErrorMessage;
if (!createMagicMatchRule(atts, errorMessage, rule)) QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage);
return false; if (!rule->isValid())
qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage));
QList<QMimeMagicRule> *ruleList; QList<QMimeMagicRule> *ruleList;
if (currentRules.isEmpty()) if (currentRules.isEmpty())
ruleList = &rules; ruleList = &rules;

View File

@ -66,6 +66,8 @@ public:
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage); bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
static bool parseNumber(const QString &n, int *target, QString *errorMessage);
protected: protected:
virtual bool process(const QMimeType &t, QString *errorMessage) = 0; virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0; virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;

View File

@ -148,7 +148,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library
#endif #endif
ElfSectionHeader strtab; ElfSectionHeader strtab;
qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); qulonglong soff = e_shoff + qelfword_t(e_shentsize) * qelfword_t(e_shtrndx);
if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
if (lib) if (lib)

View File

@ -571,19 +571,26 @@ FreeList *freelist()
return &list; return &list;
} }
#else #else
static QBasicAtomicPointer<FreeList> freeListPtr;
FreeList *freelist() FreeList *freelist()
{ {
static QAtomicPointer<FreeList> list; FreeList *local = freeListPtr.loadAcquire();
FreeList *local = list.loadAcquire();
if (!local) { if (!local) {
local = new FreeList; local = new FreeList;
if (!list.testAndSetRelease(0, local)) { if (!freeListPtr.testAndSetRelease(0, local)) {
delete local; delete local;
local = list.loadAcquire(); local = freeListPtr.loadAcquire();
} }
} }
return local; return local;
} }
static void qFreeListDeleter()
{
delete freeListPtr.load();
}
Q_DESTRUCTOR_FUNCTION(qFreeListDeleter)
#endif #endif
} }

View File

@ -276,7 +276,7 @@ public:
QStack<QEventLoop *> eventLoops; QStack<QEventLoop *> eventLoops;
QPostEventList postEventList; QPostEventList postEventList;
QThread *thread; QAtomicPointer<QThread> thread;
Qt::HANDLE threadId; Qt::HANDLE threadId;
QAtomicPointer<QAbstractEventDispatcher> eventDispatcher; QAtomicPointer<QAbstractEventDispatcher> eventDispatcher;
QVector<void *> tls; QVector<void *> tls;

View File

@ -222,7 +222,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->isAdopted = true; data->isAdopted = true;
data->threadId = (Qt::HANDLE)pthread_self(); data->threadId = (Qt::HANDLE)pthread_self();
if (!QCoreApplicationPrivate::theMainThread) if (!QCoreApplicationPrivate::theMainThread)
QCoreApplicationPrivate::theMainThread = data->thread; QCoreApplicationPrivate::theMainThread = data->thread.load();
} }
return data; return data;
} }

View File

@ -121,7 +121,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
threadData->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())); threadData->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
if (!QCoreApplicationPrivate::theMainThread) { if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread; QCoreApplicationPrivate::theMainThread = threadData->thread.load();
// TODO: is there a way to reflect the branch's behavior using // TODO: is there a way to reflect the branch's behavior using
// WinRT API? // WinRT API?
} else { } else {

View File

@ -121,7 +121,7 @@ void **QThreadStorageData::get() const
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p", DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id, id,
*v, *v,
data->thread); data->thread.load());
return *v ? v : 0; return *v ? v : 0;
} }
@ -143,7 +143,7 @@ void **QThreadStorageData::set(void *p)
DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
id, id,
value, value,
data->thread); data->thread.load());
QMutexLocker locker(&destructorsMutex); QMutexLocker locker(&destructorsMutex);
DestructorMap *destr = destructors(); DestructorMap *destr = destructors();
@ -159,7 +159,7 @@ void **QThreadStorageData::set(void *p)
// store new data // store new data
value = p; value = p;
DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p); DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p);
return &value; return &value;
} }

View File

@ -3123,6 +3123,7 @@ QTimeZone QDateTime::timeZone() const
case Qt::UTC: case Qt::UTC:
return QTimeZone::utc(); return QTimeZone::utc();
case Qt::OffsetFromUTC: case Qt::OffsetFromUTC:
return QTimeZone(d->m_offsetFromUtc);
case Qt::TimeZone: case Qt::TimeZone:
Q_ASSERT(d->m_timeZone.isValid()); Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone; return d->m_timeZone;

View File

@ -1244,13 +1244,13 @@ inline bool QByteArray::operator==(const QString &s) const
inline bool QByteArray::operator!=(const QString &s) const inline bool QByteArray::operator!=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; } { return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
inline bool QByteArray::operator<(const QString &s) const inline bool QByteArray::operator<(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
inline bool QByteArray::operator>(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; } { return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; }
inline bool QByteArray::operator>(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
inline bool QByteArray::operator<=(const QString &s) const inline bool QByteArray::operator<=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
inline bool QByteArray::operator>=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; } { return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; }
inline bool QByteArray::operator>=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
#ifndef QT_NO_CAST_TO_ASCII #ifndef QT_NO_CAST_TO_ASCII

View File

@ -101,8 +101,6 @@ template <typename StringType> struct QStringAlgorithms
if (begin == str.cbegin() && end == str.cend()) if (begin == str.cbegin() && end == str.cend())
return str; return str;
if (begin == end)
return StringType();
if (!isConst && str.isDetached()) if (!isConst && str.isDetached())
return trimmed_helper_inplace(str, begin, end); return trimmed_helper_inplace(str, begin, end);
return StringType(begin, end - begin); return StringType(begin, end - begin);

View File

@ -1171,7 +1171,7 @@ QImageIOHandler::Transformations QImageReader::transformation() const
Determines that images returned by read() should have transformation metadata automatically Determines that images returned by read() should have transformation metadata automatically
applied if \a enabled is \c true. applied if \a enabled is \c true.
\sa autoTransform(), read() \sa autoTransform(), transformation(), read()
*/ */
void QImageReader::setAutoTransform(bool enabled) void QImageReader::setAutoTransform(bool enabled)
{ {

View File

@ -182,7 +182,8 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
} else { // read ascii data } else { // read ascii data
uchar *p; uchar *p;
int n; int n;
for (y=0; y<h; y++) { char buf;
for (y = 0; (y < h) && (device->peek(&buf, 1) == 1); y++) {
p = outImage->scanLine(y); p = outImage->scanLine(y);
n = pbm_bpl; n = pbm_bpl;
if (nbits == 1) { if (nbits == 1) {

View File

@ -393,7 +393,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
bmm.fill(Qt::color1); bmm.fill(Qt::color1);
} }
d = QCursorData::setBitmap(bm, bmm, hotX, hotY); d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
d->pixmap = pixmap; d->pixmap = pixmap;
} }
@ -436,7 +436,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
: d(0) : d(0)
{ {
d = QCursorData::setBitmap(bitmap, mask, hotX, hotY); d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
} }
/*! /*!
@ -656,7 +656,7 @@ void QCursorData::initialize()
QCursorData::initialized = true; QCursorData::initialized = true;
} }
QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
{ {
if (!QCursorData::initialized) if (!QCursorData::initialized)
QCursorData::initialize(); QCursorData::initialize();
@ -670,8 +670,8 @@ QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask,
d->bm = new QBitmap(bitmap); d->bm = new QBitmap(bitmap);
d->bmm = new QBitmap(mask); d->bmm = new QBitmap(mask);
d->cshape = Qt::BitmapCursor; d->cshape = Qt::BitmapCursor;
d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio;
d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio;
return d; return d;
} }

View File

@ -70,7 +70,8 @@ public:
short hx, hy; short hx, hy;
static bool initialized; static bool initialized;
void update(); void update();
static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY); static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY,
qreal devicePixelRatio);
}; };
extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp

View File

@ -1131,7 +1131,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
QHighDpiScaling::initHighDpiScaling(); QHighDpiScaling::initHighDpiScaling();
// Load the platform integration // Load the platform integration
QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH")); QString platformPluginPath = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
QByteArray platformName; QByteArray platformName;
@ -1161,7 +1161,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
arg.remove(0, 1); arg.remove(0, 1);
if (arg == "-platformpluginpath") { if (arg == "-platformpluginpath") {
if (++i < argc) if (++i < argc)
platformPluginPath = QLatin1String(argv[i]); platformPluginPath = QString::fromLocal8Bit(argv[i]);
} else if (arg == "-platform") { } else if (arg == "-platform") {
if (++i < argc) if (++i < argc)
platformName = argv[i]; platformName = argv[i];

View File

@ -1271,8 +1271,11 @@ void QWindow::setMinimumSize(const QSize &size)
*/ */
void QWindow::setX(int arg) void QWindow::setX(int arg)
{ {
Q_D(QWindow);
if (x() != arg) if (x() != arg)
setGeometry(QRect(arg, y(), width(), height())); setGeometry(QRect(arg, y(), width(), height()));
else
d->positionAutomatic = false;
} }
/*! /*!
@ -1281,8 +1284,11 @@ void QWindow::setX(int arg)
*/ */
void QWindow::setY(int arg) void QWindow::setY(int arg)
{ {
Q_D(QWindow);
if (y() != arg) if (y() != arg)
setGeometry(QRect(x(), arg, width(), height())); setGeometry(QRect(x(), arg, width(), height()));
else
d->positionAutomatic = false;
} }
/*! /*!

View File

@ -232,6 +232,7 @@ bool QWindowSystemInterface::tryHandleShortcutOverrideEvent(QWindow *w, QKeyEven
{ {
#ifndef QT_NO_SHORTCUT #ifndef QT_NO_SHORTCUT
Q_ASSERT(ev->type() == QKeyEvent::ShortcutOverride); Q_ASSERT(ev->type() == QKeyEvent::ShortcutOverride);
QGuiApplicationPrivate::modifier_buttons = ev->modifiers();
QObject *focus = w->focusObject(); QObject *focus = w->focusObject();
if (!focus) if (!focus)

View File

@ -148,8 +148,6 @@ QMatrix4x4::QMatrix4x4(const float *values)
top-most 4 rows of \a matrix. If \a matrix has less than 4 columns top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
or rows, the remaining elements are filled with elements from the or rows, the remaining elements are filled with elements from the
identity matrix. identity matrix.
\sa QMatrix4x4(const QGenericMatrix &)
*/ */
/*! /*!

View File

@ -43,6 +43,7 @@
#include <qwindow.h> #include <qwindow.h>
#include <qlibrary.h> #include <qlibrary.h>
#include <qimage.h> #include <qimage.h>
#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -1275,9 +1276,19 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
// Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian. // Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian.
const bool supports_bgra = context->isOpenGLES() const bool has_bgra_ext = context->isOpenGLES()
? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra")) ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
: context->hasExtension(QByteArrayLiteral("GL_EXT_bgra")); : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
const char *renderer = reinterpret_cast<const char *>(funcs->glGetString(GL_RENDERER));
const char *ver = reinterpret_cast<const char *>(funcs->glGetString(GL_VERSION));
// Blacklist PowerVR Rogue G6200 as it has problems with its BGRA support.
const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0
&& ::strstr(ver, "1.3") != 0);
const bool supports_bgra = has_bgra_ext && !blackListed;
if (supports_bgra) { if (supports_bgra) {
QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits()); funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());

View File

@ -720,10 +720,11 @@ static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)
template<DrawPixel drawPixel, class Dasher> template<DrawPixel drawPixel, class Dasher>
static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps) static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)
{ {
bool didDraw = qAbs(rx2 - rx1) + qAbs(ry2 - ry1) >= 1.0;
if (stroker->clipLine(rx1, ry1, rx2, ry2)) if (stroker->clipLine(rx1, ry1, rx2, ry2))
return true; return true;
bool didDraw = false;
const int half = stroker->legacyRounding ? 31 : 0; const int half = stroker->legacyRounding ? 31 : 0;
int x1 = toF26Dot6(rx1) + half; int x1 = toF26Dot6(rx1) + half;
int y1 = toF26Dot6(ry1) + half; int y1 = toF26Dot6(ry1) + half;

View File

@ -151,7 +151,8 @@ QPdfWriter::QPdfWriter(const QString &filename)
Constructs a PDF writer that will write the pdf to \a device. Constructs a PDF writer that will write the pdf to \a device.
*/ */
QPdfWriter::QPdfWriter(QIODevice *device) QPdfWriter::QPdfWriter(QIODevice *device)
: QObject(*new QPdfWriterPrivate) : QObject(*new QPdfWriterPrivate),
QPagedPaintDevice(new QPdfPagedPaintDevicePrivate(d_func()))
{ {
Q_D(QPdfWriter); Q_D(QPdfWriter);

View File

@ -888,8 +888,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
// if HTTP mandates we should close // if HTTP mandates we should close
// or the reply is not finished yet, e.g. it was aborted // or the reply is not finished yet, e.g. it was aborted
// we have to close that connection // we have to close that connection
if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) {
channels[i].close(); if (reply->isAborted()) {
channels[i].abort();
} else {
channels[i].close();
}
}
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
return; return;

View File

@ -205,6 +205,26 @@ void QHttpNetworkConnectionChannel::close()
} }
void QHttpNetworkConnectionChannel::abort()
{
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
else if (socket->state() == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
// pendingEncrypt must only be true in between connected and encrypted states
pendingEncrypt = false;
if (socket) {
// socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
// there is no socket yet.
socket->abort();
}
}
bool QHttpNetworkConnectionChannel::sendRequest() bool QHttpNetworkConnectionChannel::sendRequest()
{ {
Q_ASSERT(!protocolHandler.isNull()); Q_ASSERT(!protocolHandler.isNull());
@ -1080,6 +1100,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
connection->d_func()->pauseConnection(); connection->d_func()->pauseConnection();
if (pendingEncrypt && !reply) if (pendingEncrypt && !reply)
connection->d_func()->dequeueRequest(socket); connection->d_func()->dequeueRequest(socket);
if (reply) // a reply was actually dequeued.
reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest();
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) { if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) {
if (reply) if (reply)
emit reply->sslErrors(errors); emit reply->sslErrors(errors);

View File

@ -157,6 +157,7 @@ public:
void init(); void init();
void close(); void close();
void abort();
bool sendRequest(); bool sendRequest();

View File

@ -264,6 +264,17 @@ char* QHttpNetworkReply::userProvidedDownloadBuffer()
return d->userProvidedDownloadBuffer; return d->userProvidedDownloadBuffer;
} }
void QHttpNetworkReply::abort()
{
Q_D(QHttpNetworkReply);
d->state = QHttpNetworkReplyPrivate::Aborted;
}
bool QHttpNetworkReply::isAborted() const
{
return d_func()->state == QHttpNetworkReplyPrivate::Aborted;
}
bool QHttpNetworkReply::isFinished() const bool QHttpNetworkReply::isFinished() const
{ {
return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState;

View File

@ -121,6 +121,9 @@ public:
void setUserProvidedDownloadBuffer(char*); void setUserProvidedDownloadBuffer(char*);
char* userProvidedDownloadBuffer(); char* userProvidedDownloadBuffer();
void abort();
bool isAborted() const;
bool isFinished() const; bool isFinished() const;
bool isPipeliningUsed() const; bool isPipeliningUsed() const;
@ -214,7 +217,8 @@ public:
SPDYSYNSent, SPDYSYNSent,
SPDYUploading, SPDYUploading,
SPDYHalfClosed, SPDYHalfClosed,
SPDYClosed SPDYClosed,
Aborted
} state; } state;
QHttpNetworkRequest request; QHttpNetworkRequest request;

View File

@ -396,6 +396,7 @@ void QHttpThreadDelegate::abortRequest()
qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous; qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous;
#endif #endif
if (httpReply) { if (httpReply) {
httpReply->abort();
delete httpReply; delete httpReply;
httpReply = 0; httpReply = 0;
} }

View File

@ -278,7 +278,8 @@ static void ensureInitialized()
\snippet code/src_network_access_qnetworkaccessmanager.cpp 4 \snippet code/src_network_access_qnetworkaccessmanager.cpp 4
Network requests can be reenabled again by calling Network requests can be re-enabled again, and this property will resume to
reflect the actual device state by calling
\snippet code/src_network_access_qnetworkaccessmanager.cpp 5 \snippet code/src_network_access_qnetworkaccessmanager.cpp 5
@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
Q_D(QNetworkAccessManager); Q_D(QNetworkAccessManager);
if (!d->networkSessionRequired) { // if a session is required, we track online state through
// if a session is required, we track online state through // the QNetworkSession's signals if a request is already made.
// the QNetworkSession's signals // we need to track current accessibility state by default
connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), //
SLOT(_q_onlineStateChanged(bool))); connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
} SLOT(_q_onlineStateChanged(bool)));
// we would need all active configurations to check for
// d->networkConfigurationManager.isOnline(), which is asynchronous
// and potentially expensive. We can just check the configuration here
d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
#endif #endif
} }
@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible) void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
{ {
Q_D(QNetworkAccessManager); Q_D(QNetworkAccessManager);
d->defaultAccessControl = false;
d->defaultAccessControl = accessible == NotAccessible ? false : true;
if (d->networkAccessible != accessible) { if (d->networkAccessible != accessible) {
NetworkAccessibility previous = networkAccessible(); NetworkAccessibility previous = networkAccessible();
@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA
QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
{ {
Q_D(const QNetworkAccessManager); Q_D(const QNetworkAccessManager);
if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined))
return UnknownAccessibility;
if (d->networkSessionRequired) { if (d->networkSessionRequired) {
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
if (networkSession) { if (networkSession) {
@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
if (online) { if (online) {
if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
online = false; online = false;
networkAccessible = QNetworkAccessManager::NotAccessible; if (networkAccessible != QNetworkAccessManager::NotAccessible) {
emit q->networkAccessibleChanged(networkAccessible); networkAccessible = QNetworkAccessManager::NotAccessible;
emit q->networkAccessibleChanged(networkAccessible);
}
} }
} else { } else {
if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
online = true; online = true;
if (defaultAccessControl) if (defaultAccessControl)
networkAccessible = QNetworkAccessManager::Accessible; if (networkAccessible != QNetworkAccessManager::Accessible) {
emit q->networkAccessibleChanged(networkAccessible); networkAccessible = QNetworkAccessManager::Accessible;
emit q->networkAccessibleChanged(networkAccessible);
}
} }
} }
} }
void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
{ {
// if the user set a config, we only care whether this one is active. Q_Q(QNetworkAccessManager);
// if the user set a config, we only care whether this one is active.
// Otherwise, this QNAM is online if there is an online config. // Otherwise, this QNAM is online if there is an online config.
if (customNetworkConfiguration) { if (customNetworkConfiguration) {
online = (networkConfiguration.state() & QNetworkConfiguration::Active); online = (networkConfiguration.state() & QNetworkConfiguration::Active);
} else { } else {
if (isOnline && online != isOnline) { if (online != isOnline) {
networkSessionStrongRef.clear(); if (isOnline) {
networkSessionWeakRef.clear(); networkSessionStrongRef.clear();
networkSessionWeakRef.clear();
}
online = isOnline;
}
}
if (online) {
if (defaultAccessControl) {
if (networkAccessible != QNetworkAccessManager::Accessible) {
networkAccessible = QNetworkAccessManager::Accessible;
emit q->networkAccessibleChanged(networkAccessible);
}
}
} else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) {
if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) {
networkAccessible = QNetworkAccessManager::UnknownAccessibility;
emit q->networkAccessibleChanged(networkAccessible);
}
} else {
if (networkAccessible != QNetworkAccessManager::NotAccessible) {
networkAccessible = QNetworkAccessManager::NotAccessible;
emit q->networkAccessibleChanged(networkAccessible);
} }
online = isOnline;
} }
} }

View File

@ -78,7 +78,6 @@ public:
customNetworkConfiguration(false), customNetworkConfiguration(false),
networkSessionRequired(networkConfigurationManager.capabilities() networkSessionRequired(networkConfigurationManager.capabilities()
& QNetworkConfigurationManager::NetworkSessionRequired), & QNetworkConfigurationManager::NetworkSessionRequired),
networkAccessible(QNetworkAccessManager::Accessible),
activeReplyCount(0), activeReplyCount(0),
online(false), online(false),
initializeSession(true), initializeSession(true),
@ -86,7 +85,18 @@ public:
cookieJarCreated(false), cookieJarCreated(false),
defaultAccessControl(true), defaultAccessControl(true),
authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create()) authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
{ } {
#ifndef QT_NO_BEARERMANAGEMENT
// we would need all active configurations to check for
// d->networkConfigurationManager.isOnline(), which is asynchronous
// and potentially expensive. We can just check the configuration here
online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active));
if (online)
networkAccessible = QNetworkAccessManager::Accessible;
else
networkAccessible = QNetworkAccessManager::NotAccessible;
#endif
}
~QNetworkAccessManagerPrivate(); ~QNetworkAccessManagerPrivate();
void _q_replyFinished(); void _q_replyFinished();

View File

@ -1238,7 +1238,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData
if (statusCode == 304) { if (statusCode == 304) {
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
qDebug() << "Received a 304 from" << url(); qDebug() << "Received a 304 from" << request.url();
#endif #endif
QAbstractNetworkCache *nc = managerPrivate->networkCache; QAbstractNetworkCache *nc = managerPrivate->networkCache;
if (nc) { if (nc) {
@ -1562,7 +1562,7 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe
} }
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
QByteArray n = rawHeader(header); QByteArray n = q->rawHeader(header);
QByteArray o; QByteArray o;
if (it != cacheHeaders.rawHeaders.constEnd()) if (it != cacheHeaders.rawHeaders.constEnd())
o = (*it).second; o = (*it).second;
@ -1781,6 +1781,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error."))); Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error.")));
QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
return; return;
#endif
} else {
#ifndef QT_NO_BEARERMANAGEMENT
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
#endif #endif
} }
@ -1950,6 +1955,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
} }
} }
void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
{
if (sessionState == QNetworkSession::Disconnected
&& (state != Idle || state != Reconnecting)) {
error(QNetworkReplyImpl::NetworkSessionFailedError,
QCoreApplication::translate("QNetworkReply", "Network session error."));
finished();
}
}
void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed()
{ {
// Abort waiting and working replies. // Abort waiting and working replies.

View File

@ -96,6 +96,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif #endif
Q_PRIVATE_SLOT(d_func(), void _q_finished()) Q_PRIVATE_SLOT(d_func(), void _q_finished())
@ -171,6 +172,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected(); void _q_networkSessionConnected();
void _q_networkSessionFailed(); void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif #endif
void _q_finished(); void _q_finished();

View File

@ -125,6 +125,11 @@ void QNetworkReplyImplPrivate::_q_startOperation()
finished(); finished();
#endif #endif
return; return;
} else {
#ifndef QT_NO_BEARERMANAGEMENT
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
#endif
} }
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
@ -309,6 +314,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
} }
} }
void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
{
if (sessionState == QNetworkSession::Disconnected
&& (state != Idle || state != Reconnecting)) {
error(QNetworkReplyImpl::NetworkSessionFailedError,
QCoreApplication::translate("QNetworkReply", "Network session error."));
finished();
}
}
void QNetworkReplyImplPrivate::_q_networkSessionFailed() void QNetworkReplyImplPrivate::_q_networkSessionFailed()
{ {
// Abort waiting and working replies. // Abort waiting and working replies.

View File

@ -89,6 +89,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif #endif
@ -122,6 +123,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected(); void _q_networkSessionConnected();
void _q_networkSessionFailed(); void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif #endif

View File

@ -85,6 +85,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\li Digest-MD5 \li Digest-MD5
\endlist \endlist
\target qauthenticator-options
\section1 Options \section1 Options
In addition to the username and password required for authentication, a In addition to the username and password required for authentication, a
@ -104,8 +105,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\section2 Basic \section2 Basic
\table \table
\header \li Option \li Direction \li Description \header \li Option \li Direction \li Type \li Description
\row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm()
\endtable \endtable
The Basic authentication mechanism supports no outgoing options. The Basic authentication mechanism supports no outgoing options.
@ -119,8 +120,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\section2 Digest-MD5 \section2 Digest-MD5
\table \table
\header \li Option \li Direction \li Description \header \li Option \li Direction \li Type \li Description
\row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm()
\endtable \endtable
The Digest-MD5 authentication mechanism supports no outgoing options. The Digest-MD5 authentication mechanism supports no outgoing options.
@ -130,7 +131,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
/*! /*!
Constructs an empty authentication object Constructs an empty authentication object.
*/ */
QAuthenticator::QAuthenticator() QAuthenticator::QAuthenticator()
: d(0) : d(0)
@ -138,7 +139,7 @@ QAuthenticator::QAuthenticator()
} }
/*! /*!
Destructs the object Destructs the object.
*/ */
QAuthenticator::~QAuthenticator() QAuthenticator::~QAuthenticator()
{ {
@ -207,7 +208,7 @@ bool QAuthenticator::operator==(const QAuthenticator &other) const
*/ */
/*! /*!
returns the user used for authentication. Returns the user used for authentication.
*/ */
QString QAuthenticator::user() const QString QAuthenticator::user() const
{ {
@ -227,7 +228,7 @@ void QAuthenticator::setUser(const QString &user)
} }
/*! /*!
returns the password used for authentication. Returns the password used for authentication.
*/ */
QString QAuthenticator::password() const QString QAuthenticator::password() const
{ {
@ -260,7 +261,7 @@ void QAuthenticator::detach()
} }
/*! /*!
returns the realm requiring authentication. Returns the realm requiring authentication.
*/ */
QString QAuthenticator::realm() const QString QAuthenticator::realm() const
{ {
@ -279,10 +280,11 @@ void QAuthenticator::setRealm(const QString &realm)
/*! /*!
\since 4.7 \since 4.7
Returns the value related to option \a opt if it was set by the server. Returns the value related to option \a opt if it was set by the server.
See \l{QAuthenticator#Options} for more information on incoming options. See the \l{QAuthenticator#qauthenticator-options}{Options section} for
more information on incoming options.
If option \a opt isn't found, an invalid QVariant will be returned. If option \a opt isn't found, an invalid QVariant will be returned.
\sa options(), QAuthenticator#Options \sa options(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/ */
QVariant QAuthenticator::option(const QString &opt) const QVariant QAuthenticator::option(const QString &opt) const
{ {
@ -292,10 +294,10 @@ QVariant QAuthenticator::option(const QString &opt) const
/*! /*!
\since 4.7 \since 4.7
Returns all incoming options set in this QAuthenticator object by parsing Returns all incoming options set in this QAuthenticator object by parsing
the server reply. See \l{QAuthenticator#Options} for more information the server reply. See the \l{QAuthenticator#qauthenticator-options}{Options section}
on incoming options. for more information on incoming options.
\sa option(), QAuthenticator#Options \sa option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/ */
QVariantHash QAuthenticator::options() const QVariantHash QAuthenticator::options() const
{ {
@ -306,9 +308,9 @@ QVariantHash QAuthenticator::options() const
\since 4.7 \since 4.7
Sets the outgoing option \a opt to value \a value. Sets the outgoing option \a opt to value \a value.
See \l{QAuthenticator#Options} for more information on outgoing options. See the \l{QAuthenticator#qauthenticator-options}{Options section} for more information on outgoing options.
\sa options(), option(), QAuthenticator#Options \sa options(), option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/ */
void QAuthenticator::setOption(const QString &opt, const QVariant &value) void QAuthenticator::setOption(const QString &opt, const QVariant &value)
{ {
@ -318,7 +320,10 @@ void QAuthenticator::setOption(const QString &opt, const QVariant &value)
/*! /*!
Returns \c true if the authenticator is null. Returns \c true if the object has not been initialized. Returns
\c false if non-const member functions have been called, or
the content was constructed or copied from another initialized
QAuthenticator object.
*/ */
bool QAuthenticator::isNull() const bool QAuthenticator::isNull() const
{ {

View File

@ -745,15 +745,9 @@ bool QAbstractSocketPrivate::canReadNotification()
return true; return true;
} }
if (socketEngine) { // turn the socket engine off if we've reached the buffer size limit
// turn the socket engine off if we've either: if (socketEngine && isBuffered)
// - got pending datagrams socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
// - reached the buffer size limit
if (isBuffered)
socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
else if (socketType != QAbstractSocket::TcpSocket)
socketEngine->setReadNotificationEnabled(!socketEngine->hasPendingDatagrams());
}
// reset the read socket notifier state if we reentered inside the // reset the read socket notifier state if we reentered inside the
// readyRead() connected slot. // readyRead() connected slot.

View File

@ -85,7 +85,8 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
} }
serverName = requestedServerName; serverName = requestedServerName;
QString tempPath; QByteArray encodedTempPath;
const QByteArray encodedFullServerName = QFile::encodeName(fullServerName);
QScopedPointer<QTemporaryDir> tempDir; QScopedPointer<QTemporaryDir> tempDir;
// Check any of the flags // Check any of the flags
@ -96,8 +97,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
return false; return false;
} }
tempPath = tempDir->path(); encodedTempPath = QFile::encodeName(tempDir->path() + QLatin1String("/s"));
tempPath += QLatin1String("/s");
} }
// create the unix socket // create the unix socket
@ -111,23 +111,23 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
// Construct the unix address // Construct the unix address
struct ::sockaddr_un addr; struct ::sockaddr_un addr;
addr.sun_family = PF_UNIX; addr.sun_family = PF_UNIX;
if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) { if (sizeof(addr.sun_path) < (uint)encodedFullServerName.size() + 1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
if (socketOptions & QLocalServer::WorldAccessOption) { if (socketOptions & QLocalServer::WorldAccessOption) {
if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) { if (sizeof(addr.sun_path) < (uint)encodedTempPath.size() + 1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
::memcpy(addr.sun_path, tempPath.toLatin1().data(), ::memcpy(addr.sun_path, encodedTempPath.constData(),
tempPath.toLatin1().size() + 1); encodedTempPath.size() + 1);
} else { } else {
::memcpy(addr.sun_path, fullServerName.toLatin1().data(), ::memcpy(addr.sun_path, encodedFullServerName.constData(),
fullServerName.toLatin1().size() + 1); encodedFullServerName.size() + 1);
} }
// bind // bind
@ -165,13 +165,13 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
if (socketOptions & QLocalServer::OtherAccessOption) if (socketOptions & QLocalServer::OtherAccessOption)
mode |= S_IRWXO; mode |= S_IRWXO;
if (::chmod(tempPath.toLatin1(), mode) == -1) { if (::chmod(encodedTempPath.constData(), mode) == -1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) { if (::rename(encodedTempPath.constData(), encodedFullServerName.constData()) == -1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;

View File

@ -268,15 +268,16 @@ void QLocalSocketPrivate::_q_connectToSocket()
connectingPathName += QLatin1Char('/') + connectingName; connectingPathName += QLatin1Char('/') + connectingName;
} }
const QByteArray encodedConnectingPathName = QFile::encodeName(connectingPathName);
struct sockaddr_un name; struct sockaddr_un name;
name.sun_family = PF_UNIX; name.sun_family = PF_UNIX;
if (sizeof(name.sun_path) < (uint)connectingPathName.toLatin1().size() + 1) { if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) {
QString function = QLatin1String("QLocalSocket::connectToServer"); QString function = QLatin1String("QLocalSocket::connectToServer");
errorOccurred(QLocalSocket::ServerNotFoundError, function); errorOccurred(QLocalSocket::ServerNotFoundError, function);
return; return;
} }
::memcpy(name.sun_path, connectingPathName.toLatin1().data(), ::memcpy(name.sun_path, encodedConnectingPathName.constData(),
connectingPathName.toLatin1().size() + 1); encodedConnectingPathName.size() + 1);
if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
QString function = QLatin1String("QLocalSocket::connectToServer"); QString function = QLatin1String("QLocalSocket::connectToServer");
switch (errno) switch (errno)

View File

@ -370,7 +370,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
int n, level; int n, level;
convertToLevelAndOption(opt, socketProtocol, level, n); convertToLevelAndOption(opt, socketProtocol, level, n);
#if defined(SO_REUSEPORT) #if defined(SO_REUSEPORT) && !defined(Q_OS_LINUX)
if (opt == QNativeSocketEngine::AddressReusable) { if (opt == QNativeSocketEngine::AddressReusable) {
// on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
// same port (which is useful for multicast UDP). SO_REUSEPORT is, but // same port (which is useful for multicast UDP). SO_REUSEPORT is, but

View File

@ -1070,8 +1070,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
buf.buf = &c; buf.buf = &c;
buf.len = sizeof(c); buf.len = sizeof(c);
DWORD flags = MSG_PEEK; DWORD flags = MSG_PEEK;
if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) {
return 0; int err = WSAGetLastError();
if (err != WSAECONNRESET && err != WSAENETRESET)
return 0;
}
} }
return nbytes; return nbytes;
} }
@ -1099,14 +1102,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
int err = WSAGetLastError(); int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) { if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err); WS_ERROR_DEBUG(err);
if (err == WSAECONNRESET || err == WSAENETRESET) { result = (err == WSAECONNRESET || err == WSAENETRESET);
// Discard error message to prevent QAbstractSocket from
// getting this message repeatedly after reenabling the
// notifiers.
flags = 0;
::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
&storage.a, &storageSize, 0, 0);
}
} else { } else {
// If there's no error, or if our buffer was too small, there must be // If there's no error, or if our buffer was too small, there must be
// a pending datagram. // a pending datagram.
@ -1159,12 +1155,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
if (recvResult != SOCKET_ERROR) { if (recvResult != SOCKET_ERROR) {
ret = qint64(bytesRead); ret = qint64(bytesRead);
break; break;
} else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) { } else {
bufferCount += 5; switch (err) {
delete[] buf; case WSAEMSGSIZE:
} else if (recvResult == SOCKET_ERROR) { bufferCount += 5;
WS_ERROR_DEBUG(err); delete[] buf;
ret = -1; continue;
case WSAECONNRESET:
case WSAENETRESET:
ret = 0;
break;
default:
WS_ERROR_DEBUG(err);
ret = -1;
break;
}
break; break;
} }
} }

View File

@ -285,23 +285,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
return false; return false;
} }
d->socketState = QAbstractSocket::ConnectingState; d->socketState = QAbstractSocket::ConnectingState;
hr = QWinRTFunctions::await(d->connectOp); hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
RETURN_FALSE_IF_FAILED("Connection could not be established"); d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
bool connectionErrors = false; Q_ASSERT_SUCCEEDED(hr);
d->handleConnectionErrors(d->connectOp.Get(), &connectionErrors);
if (connectionErrors)
return false;
d->connectOp.Reset();
d->socketState = QAbstractSocket::ConnectedState; return d->socketState == QAbstractSocket::ConnectedState;
emit connectionReady();
// Delay the reader so that the SSL socket can upgrade
if (d->sslSocket)
connect(d->sslSocket, SIGNAL(encrypted()), SLOT(establishRead()));
else
establishRead();
return true;
} }
bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
@ -330,8 +318,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
return false; return false;
} }
EventRegistrationToken token; d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken);
d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token);
hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
if (FAILED(hr)) { if (FAILED(hr)) {
qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message
@ -688,6 +675,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
{ {
Q_UNUSED(msecs); Q_UNUSED(msecs);
Q_UNUSED(timedOut); Q_UNUSED(timedOut);
Q_D(QNativeSocketEngine);
if (d->socketState == QAbstractSocket::ConnectingState) {
HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
if (SUCCEEDED(hr)) {
d->handleConnectionEstablished(d->connectOp.Get());
return true;
}
}
return false; return false;
} }
@ -728,7 +723,6 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
if (bytesToWrite()) if (bytesToWrite())
return; // will be emitted as a result of bytes written return; // will be emitted as a result of bytes written
writeNotification(); writeNotification();
d->notifyOnWrite = false;
} }
} }
@ -785,9 +779,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
qWarning("Failed to create stream socket"); qWarning("Failed to create stream socket");
return false; return false;
} }
EventRegistrationToken token;
socketDescriptor = qintptr(socket.Detach()); socketDescriptor = qintptr(socket.Detach());
udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token); udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken);
break; break;
} }
default: default:
@ -815,11 +808,19 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, closingDown(false) , closingDown(false)
, socketDescriptor(-1) , socketDescriptor(-1)
, sslSocket(Q_NULLPTR) , sslSocket(Q_NULLPTR)
, connectionToken( { -1 } )
{ {
} }
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
{ {
if (socketDescriptor == -1 || connectionToken.value == -1)
return;
if (socketType == QAbstractSocket::UdpSocket)
udpSocket()->remove_MessageReceived(connectionToken);
else if (socketType == QAbstractSocket::TcpSocket)
tcpListener->remove_ConnectionReceived(connectionToken);
} }
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
@ -1119,10 +1120,19 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK; return S_OK;
} }
void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAction, bool *errorsOccured) HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus)
{ {
bool error = true; handleConnectionEstablished(action);
HRESULT hr = connectAction->GetResults(); return S_OK;
}
void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action)
{
Q_Q(QNativeSocketEngine);
if (wasDeleted || !connectOp) // Protect against a late callback
return;
HRESULT hr = action->GetResults();
switch (hr) { switch (hr) {
case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
@ -1140,13 +1150,32 @@ void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAct
if (FAILED(hr)) { if (FAILED(hr)) {
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
socketState = QAbstractSocket::UnconnectedState; socketState = QAbstractSocket::UnconnectedState;
} else {
error = false;
} }
break; break;
} }
if (errorsOccured)
*errorsOccured = error; // The callback might be triggered several times if we do not cancel/reset it here
if (connectOp) {
ComPtr<IAsyncInfo> info;
connectOp.As(&info);
if (info) {
info->Cancel();
info->Close();
}
connectOp.Reset();
}
socketState = QAbstractSocket::ConnectedState;
emit q->connectionReady();
if (socketType != QAbstractSocket::TcpSocket)
return;
// Delay the reader so that the SSL socket can upgrade
if (sslSocket)
QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead);
else
q->establishRead();
} }
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
@ -1166,7 +1195,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
hr = buffer->get_Length(&bufferLength); hr = buffer->get_Length(&bufferLength);
Q_ASSERT_SUCCEEDED(hr); Q_ASSERT_SUCCEEDED(hr);
if (!bufferLength) { if (!bufferLength) {
if (q->isReadNotificationEnabled()) if (notifyOnRead)
emit q->readReady(); emit q->readReady();
return S_OK; return S_OK;
} }
@ -1190,7 +1219,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
readBytes.seek(readPos); readBytes.seek(readPos);
readMutex.unlock(); readMutex.unlock();
if (q->isReadNotificationEnabled()) if (notifyOnRead)
emit q->readReady(); emit q->readReady();
ComPtr<IInputStream> stream; ComPtr<IInputStream> stream;

View File

@ -207,13 +207,15 @@ private:
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections; QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
QEventLoop eventLoop; QEventLoop eventLoop;
QAbstractSocket *sslSocket; QAbstractSocket *sslSocket;
EventRegistrationToken connectionToken;
HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
void handleConnectionErrors(ABI::Windows::Foundation::IAsyncAction *connectAction, bool *errorsOccured); HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus); HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
}; };

View File

@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
elliptic-curve cipher algorithms. elliptic-curve cipher algorithms.
Elliptic curves can be constructed from a "short name" (SN) (fromShortName()), Elliptic curves can be constructed from a "short name" (SN) (fromShortName()),
and by a call to QSslSocket::supportedEllipticCurves(). and by a call to QSslConfiguration::supportedEllipticCurves().
QSslEllipticCurve instances can be compared for equality and can be used as keys QSslEllipticCurve instances can be compared for equality and can be used as keys
in QHash and QSet. They cannot be used as key in a QMap. in QHash and QSet. They cannot be used as key in a QMap.
@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
Constructs an invalid elliptic curve. Constructs an invalid elliptic curve.
\sa isValid(), QSslSocket::supportedEllipticCurves() \sa isValid(), QSslConfiguration::supportedEllipticCurves()
*/ */
/*! /*!
@ -136,7 +136,6 @@ QT_BEGIN_NAMESPACE
\relates QSslEllipticCurve \relates QSslEllipticCurve
Returns true if the curve \a lhs represents the same curve of \a rhs; Returns true if the curve \a lhs represents the same curve of \a rhs;
false otherwise.
*/ */
/*! /*!

View File

@ -257,7 +257,6 @@ int QSslPreSharedKeyAuthenticator::maximumPreSharedKeyLength() const
identity hint, identity, pre shared key, maximum length for the identity identity hint, identity, pre shared key, maximum length for the identity
and maximum length for the pre shared key. and maximum length for the pre shared key.
\sa operator!=(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/ */
bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
{ {
@ -277,7 +276,6 @@ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKey
Returns true if the authenticator object \a lhs is different than \a rhs; Returns true if the authenticator object \a lhs is different than \a rhs;
false otherwise. false otherwise.
\sa operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -59,6 +59,11 @@ QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag)
menuItemsByID.insert(m_dbusID, this); menuItemsByID.insert(m_dbusID, this);
} }
QDBusPlatformMenuItem::~QDBusPlatformMenuItem()
{
menuItemsByID.remove(m_dbusID);
}
void QDBusPlatformMenuItem::setTag(quintptr tag) void QDBusPlatformMenuItem::setTag(quintptr tag)
{ {
m_tag = tag; m_tag = tag;
@ -155,6 +160,7 @@ QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag)
QDBusPlatformMenu::~QDBusPlatformMenu() QDBusPlatformMenu::~QDBusPlatformMenu()
{ {
menusByID.remove(m_dbusID); menusByID.remove(m_dbusID);
m_topLevelMenus.removeOne(this);
} }
void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)

View File

@ -57,6 +57,7 @@ class QDBusPlatformMenuItem : public QPlatformMenuItem
public: public:
QDBusPlatformMenuItem(quintptr tag = 0LL); QDBusPlatformMenuItem(quintptr tag = 0LL);
~QDBusPlatformMenuItem();
quintptr tag()const Q_DECL_OVERRIDE { return m_tag; } quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
void setTag(quintptr tag) Q_DECL_OVERRIDE; void setTag(quintptr tag) Q_DECL_OVERRIDE;

View File

@ -39,6 +39,10 @@
#include <QtPlatformHeaders/QEGLNativeContext> #include <QtPlatformHeaders/QEGLNativeContext>
#include <QDebug> #include <QDebug>
#ifdef Q_OS_ANDROID
#include <QtCore/private/qjnihelpers_p.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! /*!
@ -305,6 +309,14 @@ void QEGLPlatformContext::updateFormatFromGL()
QByteArray version = QByteArray(reinterpret_cast<const char *>(s)); QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
int major, minor; int major, minor;
if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) { if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
#ifdef Q_OS_ANDROID
// Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
static int apiLevel = QtAndroidPrivate::androidSdkVersion();
if (apiLevel <= 17 && major >= 3) {
major = 2;
minor = 0;
}
#endif
m_format.setMajorVersion(major); m_format.setMajorVersion(major);
m_format.setMinorVersion(minor); m_format.setMinorVersion(minor);
} }

View File

@ -243,8 +243,13 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextBesideIcon; toolButtonStyle = Qt::ToolButtonTextBesideIcon;
toolBarIconSize = 0; toolBarIconSize = 0;
styleNames.clear(); styleNames.clear();
if (kdeVersion >= 5)
styleNames << QStringLiteral("breeze");
styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows"); styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows");
iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen"); if (kdeVersion >= 5)
iconFallbackThemeName = iconThemeName = QStringLiteral("breeze");
else
iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
QHash<QString, QSettings*> kdeSettings; QHash<QString, QSettings*> kdeSettings;

View File

@ -303,7 +303,7 @@ NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoin
NSImage *nsimage; NSImage *nsimage;
if (pixmap.devicePixelRatio() > 1.0) { if (pixmap.devicePixelRatio() > 1.0) {
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();
QPixmap scaledPixmap = pixmap.scaled(layoutSize); QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap)); nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap));
CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage()); CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage());
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];

View File

@ -87,9 +87,17 @@ void QCocoaScreen::updateGeometry()
NSRect frameRect = [nsScreen frame]; NSRect frameRect = [nsScreen frame];
if (m_screenIndex == 0) { // Since Mavericks, there is a setting, System Preferences->Mission Control->
// Displays have separate Spaces.
BOOL spansDisplays = NO;
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
spansDisplays = [NSScreen screensHaveSeparateSpaces];
#endif
if (spansDisplays || m_screenIndex == 0) {
m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height);
// This is the primary screen, the one that contains the menubar. Its origin should be // Displays have separate Spaces setting is on or this is the primary screen,
// the one that contains the menubar. Its origin should be
// (0, 0), and it's the only one whose available geometry differs from its full geometry. // (0, 0), and it's the only one whose available geometry differs from its full geometry.
NSRect visibleRect = [nsScreen visibleFrame]; NSRect visibleRect = [nsScreen visibleFrame];
m_availableGeometry = QRect(visibleRect.origin.x, m_availableGeometry = QRect(visibleRect.origin.x,

View File

@ -463,6 +463,13 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil; NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil;
NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil; NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
QScreen *screen = 0;
if (parentWindow)
screen = parentWindow->screen();
if (!screen && !QGuiApplication::screens().isEmpty())
screen = QGuiApplication::screens().at(0);
Q_ASSERT(screen);
// Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:. // Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:.
// However, this showed not to work with modal windows where the menu items // However, this showed not to work with modal windows where the menu items
// would appear disabled. So, we resort to a more artisanal solution. Note // would appear disabled. So, we resort to a more artisanal solution. Note
@ -479,6 +486,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
[popupCell setTransparent:YES]; [popupCell setTransparent:YES];
[popupCell setMenu:m_nativeMenu]; [popupCell setMenu:m_nativeMenu];
[popupCell selectItem:nsItem]; [popupCell selectItem:nsItem];
int availableHeight = screen->availableSize().height();
const QPoint &globalPos = parentWindow->mapToGlobal(pos);
int menuHeight = m_nativeMenu.size.height;
if (globalPos.y() + menuHeight > availableHeight) {
// Maybe we need to fix the vertical popup position but we don't know the
// exact popup height at the moment (and Cocoa is just guessing) nor its
// position. So, instead of translating by the popup's full height, we need
// to estimate where the menu will show up and translate by the remaining height.
float idx = ([m_nativeMenu indexOfItem:nsItem] + 1.0f) / m_nativeMenu.numberOfItems;
float heightBelowPos = (1.0 - idx) * menuHeight;
if (globalPos.y() + heightBelowPos > availableHeight)
pos.setY(pos.y() - globalPos.y() + availableHeight - heightBelowPos);
}
NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10); NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10);
[popupCell performClickWithFrame:cellFrame inView:view]; [popupCell performClickWithFrame:cellFrame inView:view];
} else { } else {
@ -487,22 +509,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
if (view) { if (view) {
// convert coordinates from view to the view's window // convert coordinates from view to the view's window
nsPos = [view convertPoint:nsPos toView:nil]; nsPos = [view convertPoint:nsPos toView:nil];
} else if (!QGuiApplication::screens().isEmpty()) { } else {
QScreen *screen = QGuiApplication::screens().at(0);
nsPos.y = screen->availableVirtualSize().height() - nsPos.y; nsPos.y = screen->availableVirtualSize().height() - nsPos.y;
} }
if (view) { if (view) {
// Finally, we need to synthesize an event. // Finally, we need to synthesize an event.
NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown
location:nsPos location:nsPos
modifierFlags:0 modifierFlags:0
timestamp:0 timestamp:0
windowNumber:view ? view.window.windowNumber : 0 windowNumber:view ? view.window.windowNumber : 0
context:nil context:nil
eventNumber:0 eventNumber:0
clickCount:1 clickCount:1
pressure:1.0]; pressure:1.0];
[NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view]; [NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view];
} else { } else {
[m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0]; [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0];

View File

@ -799,13 +799,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
return styleMask; return styleMask;
if ((type & Qt::Popup) == Qt::Popup) { if ((type & Qt::Popup) == Qt::Popup) {
if (!windowIsPopupType(type)) { if (!windowIsPopupType(type)) {
styleMask = NSUtilityWindowMask; styleMask = NSUtilityWindowMask | NSResizableWindowMask;
if (!(flags & Qt::CustomizeWindowHint)) { if (!(flags & Qt::CustomizeWindowHint)) {
styleMask |= NSResizableWindowMask | NSClosableWindowMask | styleMask |= NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask;
NSMiniaturizableWindowMask | NSTitledWindowMask;
} else { } else {
if (flags & Qt::WindowMaximizeButtonHint)
styleMask |= NSResizableWindowMask;
if (flags & Qt::WindowTitleHint) if (flags & Qt::WindowTitleHint)
styleMask |= NSTitledWindowMask; styleMask |= NSTitledWindowMask;
if (flags & Qt::WindowCloseButtonHint) if (flags & Qt::WindowCloseButtonHint)
@ -1352,6 +1349,9 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
[m_contentView setHidden: YES]; [m_contentView setHidden: YES];
} }
m_nsWindow.ignoresMouseEvents =
(window()->flags() & Qt::WindowTransparentForInput) == Qt::WindowTransparentForInput;
const qreal opacity = qt_window_private(window())->opacity; const qreal opacity = qt_window_private(window())->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0))) if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity); setOpacity(opacity);

View File

@ -710,8 +710,12 @@ QT_WARNING_POP
// Popups implicitly grap mouse events; forward to the active popup if there is one // Popups implicitly grap mouse events; forward to the active popup if there is one
if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) { if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
if (QNSView *popupView = popup->qtView()) // Tooltips must be transparent for mouse events
targetView = popupView; // The bug reference is QTBUG-46379
if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) {
if (QNSView *popupView = popup->qtView())
targetView = popupView;
}
} }
[targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];

View File

@ -62,7 +62,7 @@ public:
void setRole(MenuRole role) Q_DECL_OVERRIDE; void setRole(MenuRole role) Q_DECL_OVERRIDE;
void setCheckable(bool) Q_DECL_OVERRIDE {} void setCheckable(bool) Q_DECL_OVERRIDE {}
void setChecked(bool) Q_DECL_OVERRIDE {} void setChecked(bool) Q_DECL_OVERRIDE {}
void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE {} void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE;
void setEnabled(bool enabled) Q_DECL_OVERRIDE; void setEnabled(bool enabled) Q_DECL_OVERRIDE;
void setIconSize(int) Q_DECL_OVERRIDE {} void setIconSize(int) Q_DECL_OVERRIDE {}
@ -73,6 +73,7 @@ public:
bool m_enabled; bool m_enabled;
bool m_separator; bool m_separator;
QIOSMenu *m_menu; QIOSMenu *m_menu;
QKeySequence m_shortcut;
private: private:
QString removeMnemonics(const QString &original); QString removeMnemonics(const QString &original);
@ -134,6 +135,7 @@ private:
void toggleShowUsingUIMenuController(bool show); void toggleShowUsingUIMenuController(bool show);
void toggleShowUsingUIPickerView(bool show); void toggleShowUsingUIPickerView(bool show);
QIOSMenuItemList visibleMenuItems() const; QIOSMenuItemList visibleMenuItems() const;
QIOSMenuItemList filterFirstResponderActions(const QIOSMenuItemList &menuItems);
void repositionMenu(); void repositionMenu();
}; };

View File

@ -277,6 +277,11 @@ void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role)
m_role = role; m_role = role;
} }
void QIOSMenuItem::setShortcut(const QKeySequence &sequence)
{
m_shortcut = sequence;
}
void QIOSMenuItem::setEnabled(bool enabled) void QIOSMenuItem::setEnabled(bool enabled)
{ {
m_enabled = enabled; m_enabled = enabled;
@ -364,7 +369,7 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *)
switch (m_effectiveMenuType) { switch (m_effectiveMenuType) {
case EditMenu: case EditMenu:
[m_menuController setVisibleMenuItems:visibleMenuItems()]; [m_menuController setVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
break; break;
default: default:
[m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem]; [m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];
@ -469,7 +474,7 @@ void QIOSMenu::toggleShowUsingUIMenuController(bool show)
{ {
if (show) { if (show) {
Q_ASSERT(!m_menuController); Q_ASSERT(!m_menuController);
m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()]; m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
repositionMenu(); repositionMenu();
connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu); connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
} else { } else {
@ -542,6 +547,36 @@ QIOSMenuItemList QIOSMenu::visibleMenuItems() const
return visibleMenuItems; return visibleMenuItems;
} }
QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &menuItems)
{
// UIResponderStandardEditActions found in first responder will be prepended to the edit
// menu automatically (or e.g made available as buttons on the virtual keyboard). So we
// filter them out to avoid duplicates, and let first responder handle the actions instead.
// In case of QIOSTextResponder, edit actions will be converted to key events that ends up
// triggering the shortcuts of the filtered menu items.
QIOSMenuItemList filteredMenuItems;
UIResponder *responder = [UIResponder currentFirstResponder];
for (int i = 0; i < menuItems.count(); ++i) {
QIOSMenuItem *menuItem = menuItems.at(i);
QKeySequence shortcut = menuItem->m_shortcut;
if ((shortcut == QKeySequence::Cut && [responder canPerformAction:@selector(cut:) withSender:nil])
|| (shortcut == QKeySequence::Copy && [responder canPerformAction:@selector(copy:) withSender:nil])
|| (shortcut == QKeySequence::Paste && [responder canPerformAction:@selector(paste:) withSender:nil])
|| (shortcut == QKeySequence::Delete && [responder canPerformAction:@selector(delete:) withSender:nil])
|| (shortcut == QKeySequence::SelectAll && [responder canPerformAction:@selector(selectAll:) withSender:nil])
|| (shortcut == QKeySequence::Undo && [responder canPerformAction:@selector(undo:) withSender:nil])
|| (shortcut == QKeySequence::Redo && [responder canPerformAction:@selector(redo:) withSender:nil])
|| (shortcut == QKeySequence::Bold && [responder canPerformAction:@selector(toggleBoldface:) withSender:nil])
|| (shortcut == QKeySequence::Italic && [responder canPerformAction:@selector(toggleItalics:) withSender:nil])
|| (shortcut == QKeySequence::Underline && [responder canPerformAction:@selector(toggleUnderline:) withSender:nil])) {
continue;
}
filteredMenuItems.append(menuItem);
}
return filteredMenuItems;
}
void QIOSMenu::repositionMenu() void QIOSMenu::repositionMenu()
{ {
switch (m_effectiveMenuType) { switch (m_effectiveMenuType) {

View File

@ -231,6 +231,9 @@
if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>())) if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>()))
self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease]; self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease];
self.undoManager.groupsByEvent = NO;
[self rebuildUndoStack];
return self; return self;
} }
@ -346,42 +349,181 @@
- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers - (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers
{ {
QKeyEvent press(QEvent::KeyPress, key, modifiers); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers);
QKeyEvent release(QEvent::KeyRelease, key, modifiers); QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers);
[self sendEventToFocusObject:press]; }
[self sendEventToFocusObject:release];
#ifndef QT_NO_SHORTCUT
- (void)sendShortcut:(QKeySequence::StandardKey)standardKey
{
const int keys = QKeySequence(standardKey)[0];
Qt::Key key = Qt::Key(keys & 0x0000FFFF);
Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keys & 0xFFFF0000);
[self sendKeyPressRelease:key modifiers:modifiers];
} }
- (void)cut:(id)sender - (void)cut:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier]; [self sendShortcut:QKeySequence::Cut];
} }
- (void)copy:(id)sender - (void)copy:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier]; [self sendShortcut:QKeySequence::Copy];
} }
- (void)paste:(id)sender - (void)paste:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier]; [self sendShortcut:QKeySequence::Paste];
} }
- (void)selectAll:(id)sender - (void)selectAll:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier]; [self sendShortcut:QKeySequence::SelectAll];
} }
- (void)delete:(id)sender - (void)delete:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier]; [self sendShortcut:QKeySequence::Delete];
} }
- (void)toggleBoldface:(id)sender
{
Q_UNUSED(sender);
[self sendShortcut:QKeySequence::Bold];
}
- (void)toggleItalics:(id)sender
{
Q_UNUSED(sender);
[self sendShortcut:QKeySequence::Italic];
}
- (void)toggleUnderline:(id)sender
{
Q_UNUSED(sender);
[self sendShortcut:QKeySequence::Underline];
}
// -------------------------------------------------------------------------
- (void)undo
{
[self sendShortcut:QKeySequence::Undo];
[self rebuildUndoStack];
}
- (void)redo
{
[self sendShortcut:QKeySequence::Redo];
[self rebuildUndoStack];
}
- (void)registerRedo
{
NSUndoManager *undoMgr = self.undoManager;
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(redo) object:nil];
[undoMgr endUndoGrouping];
}
- (void)rebuildUndoStack
{
dispatch_async(dispatch_get_main_queue (), ^{
// Register dummy undo/redo operations to enable Cmd-Z and Cmd-Shift-Z
// Ensure we do this outside any undo/redo callback since NSUndoManager
// will treat registerUndoWithTarget as registering a redo when called
// from within a undo callback.
NSUndoManager *undoMgr = self.undoManager;
[undoMgr removeAllActions];
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(undo) object:nil];
[undoMgr endUndoGrouping];
// Schedule an operation that we immediately pop off to be able to schedule a redo
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(registerRedo) object:nil];
[undoMgr endUndoGrouping];
[undoMgr undo];
// Note that, perhaps because of a bug in UIKit, the buttons on the shortcuts bar ends up
// disabled if a undo/redo callback doesn't lead to a [UITextInputDelegate textDidChange].
// And we only call that method if Qt made changes to the text. The effect is that the buttons
// become disabled when there is nothing more to undo (Qt didn't change anything upon receiving
// an undo request). This seems to be OK behavior, so we let it stay like that unless it shows
// to cause problems.
});
}
// -------------------------------------------------------------------------
- (void)keyCommandTriggered:(UIKeyCommand *)keyCommand
{
Qt::Key key = Qt::Key_unknown;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
if (keyCommand.input == UIKeyInputLeftArrow)
key = Qt::Key_Left;
else if (keyCommand.input == UIKeyInputRightArrow)
key = Qt::Key_Right;
else if (keyCommand.input == UIKeyInputUpArrow)
key = Qt::Key_Up;
else if (keyCommand.input == UIKeyInputDownArrow)
key = Qt::Key_Down;
else
Q_UNREACHABLE();
if (keyCommand.modifierFlags & UIKeyModifierAlternate)
modifiers |= Qt::AltModifier;
if (keyCommand.modifierFlags & UIKeyModifierShift)
modifiers |= Qt::ShiftModifier;
if (keyCommand.modifierFlags & UIKeyModifierCommand)
modifiers |= Qt::ControlModifier;
[self sendKeyPressRelease:key modifiers:modifiers];
}
- (void)addKeyCommandsToArray:(NSMutableArray *)array key:(NSString *)key
{
SEL s = @selector(keyCommandTriggered:);
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:0 action:s]];
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierShift action:s]];
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate action:s]];
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:s]];
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand action:s]];
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:s]];
}
- (NSArray *)keyCommands
{
// Since keyCommands is called for every key
// press/release, we cache the result
static dispatch_once_t once;
static NSMutableArray *array;
dispatch_once(&once, ^{
// We let Qt move the cursor around when the arrow keys are being used. This
// is normally implemented through UITextInput, but since IM in Qt have poor
// support for moving the cursor vertically, and even less support for selecting
// text across multiple paragraphs, we do this through key events.
array = [NSMutableArray new];
[self addKeyCommandsToArray:array key:UIKeyInputUpArrow];
[self addKeyCommandsToArray:array key:UIKeyInputDownArrow];
[self addKeyCommandsToArray:array key:UIKeyInputLeftArrow];
[self addKeyCommandsToArray:array key:UIKeyInputRightArrow];
});
return array;
}
#endif // QT_NO_SHORTCUT
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
- (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties
@ -540,7 +682,17 @@
- (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset - (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset
{ {
int p = static_cast<QUITextPosition *>(position).index; int p = static_cast<QUITextPosition *>(position).index;
return [QUITextPosition positionWithIndex:(direction == UITextLayoutDirectionRight ? p + offset : p - offset)];
switch (direction) {
case UITextLayoutDirectionLeft:
return [QUITextPosition positionWithIndex:p - offset];
case UITextLayoutDirectionRight:
return [QUITextPosition positionWithIndex:p + offset];
default:
// Qt doesn't support getting the position above or below the current position, so
// for those cases we just return the current position, making it a no-op.
return position;
}
} }
- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction - (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction
@ -608,6 +760,15 @@
return toCGRect(startRect.united(endRect)); return toCGRect(startRect.united(endRect));
} }
- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
Q_UNUSED(range);
// This method is supposed to return a rectangle for each line with selection. Since we don't
// expose an API in Qt/IM for getting this information, and since we never seems to be getting
// a call from UIKit for this, we return an empty array until a need arise.
return [[NSArray new] autorelease];
}
- (CGRect)caretRectForPosition:(UITextPosition *)position - (CGRect)caretRectForPosition:(UITextPosition *)position
{ {
Q_UNUSED(position); Q_UNUSED(position);
@ -734,10 +895,10 @@
- (void)deleteBackward - (void)deleteBackward
{ {
// Since we're posting im events directly to the focus object, we should do the // UITextInput selects the text to be deleted before calling this method. To avoid
// same for key events. Otherwise they might end up in a different place or out // drawing the selection, we flush after posting the key press/release.
// of sync with im events.
[self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier]; [self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier];
QWindowSystemInterface::flushWindowSystemEvents();
} }
@end @end

View File

@ -107,6 +107,8 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const
switch (hint) { switch (hint) {
case QPlatformTheme::StyleNames: case QPlatformTheme::StyleNames:
return QStringList(QStringLiteral("fusion")); return QStringList(QStringLiteral("fusion"));
case KeyboardScheme:
return QVariant(int(MacKeyboardScheme));
default: default:
return QPlatformTheme::themeHint(hint); return QPlatformTheme::themeHint(hint);
} }

View File

@ -185,7 +185,14 @@
- (void)setFrame:(CGRect)newFrame - (void)setFrame:(CGRect)newFrame
{ {
[super setFrame:CGRectMake(0, 0, CGRectGetWidth(newFrame), CGRectGetHeight(self.window.bounds))]; Q_UNUSED(newFrame);
Q_ASSERT(!self.window || self.window.rootViewController.view == self);
// When presenting view controllers our view may be temporarily reparented into a UITransitionView
// instead of the UIWindow, and the UITransitionView may have a transform set, so we need to do a
// mapping even if we still expect to always be the root view-controller.
CGRect transformedWindowBounds = [self.superview convertRect:self.window.bounds fromView:self.window];
[super setFrame:transformedWindowBounds];
} }
- (void)setBounds:(CGRect)newBounds - (void)setBounds:(CGRect)newBounds

View File

@ -152,7 +152,7 @@ bool QWindowsLibEGL::init()
eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface); eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay); eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers); eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress); eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress) if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
return false; return false;

View File

@ -71,7 +71,7 @@ struct QWindowsLibEGL
EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw); EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw);
EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void); EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void);
EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname); QFunctionPointer (EGLAPIENTRY *eglGetProcAddress)(const char *procname);
EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list); EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);

View File

@ -67,18 +67,20 @@ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) :
bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{ {
const QEventLoop::ProcessEventsFlags oldFlags = m_flags;
m_flags = flags; m_flags = flags;
if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags; qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags;
const bool rc = QEventDispatcherWin32::processEvents(flags); const bool rc = QEventDispatcherWin32::processEvents(flags);
if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled()) if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc; qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc;
m_flags = oldFlags;
return rc; return rc;
} }
void QWindowsGuiEventDispatcher::sendPostedEvents() void QWindowsGuiEventDispatcher::sendPostedEvents()
{ {
QCoreApplication::sendPostedEvents(); QEventDispatcherWin32::sendPostedEvents();
QWindowSystemInterface::sendWindowSystemEvents(m_flags); QWindowSystemInterface::sendWindowSystemEvents(m_flags);
} }

View File

@ -276,7 +276,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers()
{ {
const GpuDescription gpu = GpuDescription::detect(); const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true); const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true);
qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result; return result;
} }
@ -284,7 +284,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers()
{ {
const GpuDescription gpu = GpuDescription::detect(); const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false); const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false);
qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result; return result;
} }

View File

@ -806,7 +806,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties()
home += QLatin1Char('/'); home += QLatin1Char('/');
if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/')) if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/'))
cur += QLatin1Char('/'); cur += QLatin1Char('/');
if (cur.left(home.length()) != home) if (!cur.startsWith(home))
cur = home; cur = home;
if (QGuiApplication::platformName() == QLatin1String("xcb")) { if (QGuiApplication::platformName() == QLatin1String("xcb")) {
if (printer->docName().isEmpty()) { if (printer->docName().isEmpty()) {

Some files were not shown because too many files have changed in this diff Show More