Merge remote-tracking branch 'origin/5.3' into dev

Conflicts:
	mkspecs/qnx-x86-qcc/qplatformdefs.h
	src/corelib/global/qglobal.h
	src/network/socket/qnativesocketengine_winrt.cpp
	src/plugins/platforms/android/androidjniaccessibility.cpp
	src/plugins/platforms/windows/qwindowswindow.cpp

Manually adjusted:
	mkspecs/qnx-armle-v7-qcc/qplatformdefs.h
	to include 9ce697f2d5

Thanks goes to Sergio for the qnx mkspecs adjustments.

Change-Id: I53b1fd6bc5bc884e5ee2c2b84975f58171a1cb8e
This commit is contained in:
Frederik Gladhorn 2014-07-01 10:03:53 +02:00
commit a09a8d509a
204 changed files with 2504 additions and 1308 deletions

101
dist/changes-5.3.1 vendored Normal file
View File

@ -0,0 +1,101 @@
Qt 5.3.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.3.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://qt-project.org/doc/qt-5.3
The Qt version 5.3 series is binary compatible with the 5.2.x series.
Applications compiled for 5.2 will continue to run with 5.3.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt-project.org/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtCore
------
- QAbstractProxyModel:
* Fixed QAbstractProxyModel::sibling to work in the same manner as the
Qt4 code used to behave. Previously, Qt5's implementation would treat
the row and column as positions in the source model instead of a
position in the proxy itself.
QtGui
-----
- Text:
* [QTBUG-36083] Respect QFont::fixedPitch() for fallbacks when font
family cannot be matched.
* [QTBUG-37190] Fixed crash when trying to load a font from invalid
data.
QtSql
-----
- QDB2 and QODBC
* [QTBUG-39137] Fix error handling problem caused by unintialized variable
passed to SQLNumResultCols.
- QPSQL
* [QTBUG-12477] Fix PSQL column metadata.
- QSqlQuery
* Fix misbehavior of seek in special query positions BeforeFirstRow and
AfterLastRow. (commit 3e6e70bddd84536deaae69421d05785ae6ce28cd)
* [QTBUG-33169] Fix for bindvalue(int) memory allocation problem.
QtWidgets
---------
- QMenu:
* [QTBUG-38498] Accessibility: Menus are now read by screen readers
with more reliability.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
Android
-------
- [QTBUG-38960] Fixed regression where there would be flickering on
startup and shutdown of the application.
- [QTBUG-35975] Fixed repaint issues in drag and drop.
- Text:
* [QTBUG-37844] Fall back to Droid Sans Mono for QFont::Courier style
hint.
****************************************************************************
* Tools *
****************************************************************************
configure & build system
------------------------
- [QTBUG-38445] Fixed build against static ICU on Unix
- [QTBUG-38544] Fixed LLVM build with SIMD features
- [QTBUG-39253] PDB files are now installed also for static libraries
- Added support for -separate-debug-info on Windows
- Added [-no]-pulseaudio and [-no]-alsa options on Unix
- Several fixes to installed .pc and .prl files
- Fixed MinGW build under MSYS
- Fixed installation of unneeded static libraries in dynamic builds
qmake
-----
- [QTBUG-37054] Fixed use of relative paths in QMAKE_BUNDLE_DATA with Xcode
- [QTBUG-38260] Custom Info.plist supplied via QMAKE_INFO_PLIST is now used
as-is, without placeholder replacement
- QMAKE_TARGET_BUNDLE_PREFIX does not need a trailing dot any more

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@ -28,31 +28,35 @@
/*!
\example layouts/basiclayouts
\title Basic Layouts Example
\brief Shows how to use the standard layout managers.
\brief The Basic Layouts example shows how to use the standard layout
managers that are available in Qt: QBoxLayout, QGridLayout and
QFormLayout.
\e{Basic Layouts} shows how to use the standard layout managers that are
available in Qt: QBoxLayout, QGridLayout, and QFormLayout.
\image basiclayouts-example.png Screenshot of the Basic Layouts example
The QBoxLayout class lines up widgets horizontally or vertically.
QHBoxLayout and QVBoxLayout are convenience subclasses of QBoxLayout.
QGridLayout lays out widgets in cells by dividing the available space
into rows and columns. QFormLayout, on the other hand, lays out its
into rows and columns. QFormLayout, on the other hand, sets its
children in a two-column form with labels in the left column and
input fields in the right column.
For more information, visit the \l{Layout Management} page.
\include examples-run.qdocinc
\section1 Dialog Class Definition
\snippet layouts/basiclayouts/dialog.h 0
The \c Dialog class inherits QDialog. It is a custom widget that
displays its child widgets using the geometry managers:
QHBoxLayout, QVBoxLayout, QGridLayout and QFormLayout.
QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout.
We declare four private functions to simplify the class
constructor: The \c createMenu(), \c createHorizontalGroupBox(),
\c createGridGroupBox() and \c createFormGroupBox() functions create
There are four private functions to simplify the class
constructor: the \c createMenu(), \c createHorizontalGroupBox(),
\c createGridGroupBox(), and \c createFormGroupBox() functions create
several widgets that the example uses to demonstrate how the layout
affects their appearances.

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@ -28,9 +28,14 @@
/*!
\example layouts/borderlayout
\title Border Layout Example
\brief Shows how to arrange child widgets along a border.
\brief The Border Layout example shows how to create a custom layout that arranges
child widgets according to a simple set of rules.
\e{Border Layout} implements a layout that arranges child widgets to
surround the main area.
\image borderlayout-example.png
For more information, visit the \l{Layout Management} page.
\include examples-run.qdocinc
*/

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@ -28,7 +28,13 @@
/*!
\example layouts/dynamiclayouts
\title Dynamic Layouts Example
\brief Shows how to re-orient widgets in running applications.
\brief The Dynamic Layouts example shows how to move widgets around in
existing layouts.
\e{Dynamic Layouts} implements dynamically placed widgets within running
applications. The widget placement depends on whether \c Horizontal or \c
Vertical is chosen.
For more information, visit the \l{Layout Management} page.
\include examples-run.qdocinc
*/

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@ -28,18 +28,19 @@
/*!
\example layouts/flowlayout
\title Flow Layout Example
\brief Shows how to arrange widgets for different window sizes.
\brief The Flow Layout example demonstrates a custom layout that arranges child
widgets from left to right and top to bottom in a top-level widget.
\e{Flow Layout} implements a layout that handles different window sizes. The
widget placement changes depending on the width of the application window.
\image flowlayout-example.png Screenshot of the Flow Layout example
The items are first laid out horizontally and then vertically when each line
in the layout runs out of space.
The Flowlayout class mainly uses QLayout and QWidgetItem, while the
Window uses QWidget and QLabel. We will only document the definition
and implementation of \c FlowLayout below.
Window uses QWidget and QLabel.
For more information, visit the \l{Layout Management} page.
\include examples-run.qdocinc
\section1 FlowLayout Class Definition

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@ -112,15 +112,19 @@
{ImageViewer}'s appearance.
\snippet widgets/imageviewer/imageviewer.cpp 1
In the \c open() slot, we show a file dialog to the user. We compile
a list of mime types for use as a filter by querying QImageReader
for the available mime type names.
We show the file dialog until a valid file name is entered or
the user cancels.
The function \c loadFile() is used to load the image.
\snippet widgets/imageviewer/imageviewer.cpp 2
In the \c open() slot, we show a file dialog to the user. The
easiest way to create a QFileDialog is to use the static
convenience functions. QFileDialog::getOpenFileName() returns an
existing file selected by the user. If the user presses \uicontrol
Cancel, QFileDialog returns an empty string.
Unless the file name is a empty string, we check if the file's
In the \c loadFile() function, we check if the file's
format is an image format by constructing a QImage which tries to
load the image from the file. If the constructor returns a null
image, we use a QMessageBox to alert the user.
@ -135,7 +139,6 @@
information message with an \uicontrol OK button (the default) is
sufficient, since the message is part of a normal operation.
\snippet widgets/imageviewer/imageviewer.cpp 3
\snippet widgets/imageviewer/imageviewer.cpp 4
If the format is supported, we display the image in \c imageLabel

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -61,38 +61,60 @@ ImageViewer::ImageViewer()
createActions();
createMenus();
setWindowTitle(tr("Image Viewer"));
resize(500, 400);
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
}
//! [0]
//! [2]
bool ImageViewer::loadFile(const QString &fileName)
{
QImage image(fileName);
if (image.isNull()) {
QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName)));
setWindowFilePath(QString());
imageLabel->setPixmap(QPixmap());
imageLabel->adjustSize();
return false;
}
//! [2] //! [3]
imageLabel->setPixmap(QPixmap::fromImage(image));
//! [3] //! [4]
scaleFactor = 1.0;
printAct->setEnabled(true);
fitToWindowAct->setEnabled(true);
updateActions();
if (!fitToWindowAct->isChecked())
imageLabel->adjustSize();
setWindowFilePath(fileName);
return true;
}
//! [4]
//! [2]
//! [1]
void ImageViewer::open()
//! [1] //! [2]
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::information(this, tr("Image Viewer"),
tr("Cannot load %1.").arg(fileName));
return;
}
//! [2] //! [3]
imageLabel->setPixmap(QPixmap::fromImage(image));
//! [3] //! [4]
scaleFactor = 1.0;
QStringList mimeTypeFilters;
foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes())
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
QFileDialog dialog(this, tr("Open File"),
picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.first());
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
printAct->setEnabled(true);
fitToWindowAct->setEnabled(true);
updateActions();
if (!fitToWindowAct->isChecked())
imageLabel->adjustSize();
}
while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {}
}
//! [4]
//! [1]
//! [5]
void ImageViewer::print()

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -61,6 +61,7 @@ class ImageViewer : public QMainWindow
public:
ImageViewer();
bool loadFile(const QString &);
private slots:
void open();

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -39,13 +39,23 @@
****************************************************************************/
#include <QApplication>
#include <QCommandLineParser>
#include "imageviewer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGuiApplication::setApplicationDisplayName(ImageViewer::tr("Image Viewer"));
QCommandLineParser commandLineParser;
commandLineParser.addHelpOption();
commandLineParser.addPositionalArgument(ImageViewer::tr("[file]"), ImageViewer::tr("Image file to open."));
commandLineParser.process(QCoreApplication::arguments());
ImageViewer imageViewer;
if (!commandLineParser.positionalArguments().isEmpty()
&& !imageViewer.loadFile(commandLineParser.positionalArguments().front())) {
return -1;
}
imageViewer.show();
return app.exec();
}

View File

@ -166,8 +166,6 @@ contains(CONFIG, plugin) {
return()
}
contains($$list(network sql widgets gui), $$MODULE): CMAKE_LOAD_PLUGINS = true
unix:contains(QT_CONFIG, reduce_relocations):CMAKE_ADD_FPIE_FLAGS = "true"
CMAKE_MKSPEC = $$[QMAKE_XSPEC]
@ -293,3 +291,14 @@ exists($$cmake_macros_file.input) {
}
cmake_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5$${CMAKE_MODULE_NAME}
# We are generating cmake files. Most developers of Qt are not aware of cmake,
# so we require automatic tests to be available. The only module which should
# set CMAKE_MODULE_TESTS to '-' is enginio because that is known to be broken.
# Other modules should either create proper tests in tests/auto/cmake or, as
# a temporary measure, disable the generation of cmake files
# with 'CONFIG -= create_cmake'
!equals(CMAKE_MODULE_TESTS, -) {
isEmpty(CMAKE_MODULE_TESTS): CMAKE_MODULE_TESTS = $$MODULE_BASE_INDIR/tests/auto/cmake
!exists($$CMAKE_MODULE_TESTS): error("Missing CMake tests.")
}

View File

@ -283,7 +283,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!ENDIF // CMAKE_DEBUG_TYPE
!!IF !isEmpty(CMAKE_LOAD_PLUGINS)
file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")
macro(_populate_$${CMAKE_MODULE_NAME}_plugin_properties Plugin Configuration PLUGIN_LOCATION)
set_property(TARGET Qt5::${Plugin} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
@ -299,11 +299,12 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
)
endmacro()
file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")
foreach(pluginTarget ${pluginTargets})
include(${pluginTarget})
endforeach()
!!ENDIF
if (pluginTargets)
foreach(pluginTarget ${pluginTargets})
include(${pluginTarget})
endforeach()
endif()
!!IF !isEmpty(CMAKE_MODULE_EXTRAS)
include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}ConfigExtras.cmake\")

View File

@ -128,7 +128,7 @@ contains(qt_module_deps, qml): \
QML_IMPORT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_qml_plugin_import.cpp
write_file($$QML_IMPORT_CPP, IMPORT_FILE_CONT)|error("Aborting.")
SOURCES += $$QML_IMPORT_CPP
QMAKE_CLEAN += $$QML_IMPORT_CPP
QMAKE_DISTCLEAN += $$QML_IMPORT_CPP
# copy qml files. this part is platform spesific.
mac {

View File

@ -22,7 +22,7 @@
target.path = $$[QT_HOST_LIBS]
else: \
target.path = $$[QT_INSTALL_LIBS]
target.CONFIG = no_dll
!static: target.CONFIG = no_dll
INSTALLS += target
}

View File

@ -32,6 +32,7 @@ qt_install_headers {
!isEmpty(header_files_client) {
wayland_generated_client_headers.files = $$header_files_client
wayland_generated_client_headers.path = $$private_headers.path
wayland_generated_client_headers.CONFIG = no_check_exist
INSTALLS += wayland_generated_client_headers
WAYLAND_CLIENT_HEADER_DEST = $$header_dest/
WAYLAND_CLIENT_INCLUDE_DIR = $$MODULE_INCNAME/private
@ -41,6 +42,7 @@ qt_install_headers {
!isEmpty(header_files_server) {
wayland_generated_server_headers.files = $$header_files_server
wayland_generated_server_headers.path = $$private_headers.path
wayland_generated_server_headers.CONFIG = no_check_exist
INSTALLS += wayland_generated_server_headers
WAYLAND_SERVER_HEADER_DEST = $$header_dest/
WAYLAND_SERVER_INCLUDE_DIR = $$MODULE_INCNAME/private

View File

@ -3,7 +3,7 @@
** Copyright (C) 2012 - 2014 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@ -42,68 +42,6 @@
#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H
// Get Qt defines/settings
#include "qglobal.h"
// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
#include <unistd.h>
#define __STDC_CONSTANT_MACROS
// We are hot - unistd.h should have turned on the specific APIs we requested
#include <pthread.h>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/time.h>
// QNX doesn't have the System V <sys/shm.h> header. This is not a standard
// POSIX header, it's only documented in the Single UNIX Specification.
// The preferred POSIX compliant way to share memory is to use the functions
// in <sys/mman.h> that comply with the POSIX Real Time Interface (1003.1b).
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <netinet/in.h>
#ifndef QT_NO_IPV6IFNAME
#include <net/if.h>
#endif
// for htonl
#include <arpa/inet.h>
#define QT_USE_XOPEN_LFS_EXTENSIONS
#if defined(__EXT_QNX__READDIR_R) && !defined(__EXT_QNX__READDIR64_R)
#define QT_NO_READDIR64
#endif
#include "../common/posix/qplatformdefs.h"
#if defined(__EXT_QNX__READDIR64_R)
#define QT_EXT_QNX_READDIR_R ::_readdir64_r
#elif defined(__EXT_QNX__READDIR_R)
#define QT_EXT_QNX_READDIR_R ::_readdir_r
#endif
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
// QNX6 doesn't have getpagesize()
inline int getpagesize()
{
return ::sysconf(_SC_PAGESIZE);
}
#include <stdlib.h>
#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP"))
#include "../common/qnx/qplatformdefs.h"
#endif // QPLATFORMDEFS_H

View File

@ -208,17 +208,17 @@ QMakeEvaluator::~QMakeEvaluator()
{
}
void QMakeEvaluator::initFrom(const QMakeEvaluator &other)
void QMakeEvaluator::initFrom(const QMakeEvaluator *other)
{
Q_ASSERT_X(&other, "QMakeEvaluator::visitProFile", "Project not prepared");
m_functionDefs = other.m_functionDefs;
m_valuemapStack = other.m_valuemapStack;
Q_ASSERT_X(other, "QMakeEvaluator::visitProFile", "Project not prepared");
m_functionDefs = other->m_functionDefs;
m_valuemapStack = other->m_valuemapStack;
m_valuemapInited = true;
m_qmakespec = other.m_qmakespec;
m_qmakespecName = other.m_qmakespecName;
m_mkspecPaths = other.m_mkspecPaths;
m_featureRoots = other.m_featureRoots;
m_dirSep = other.m_dirSep;
m_qmakespec = other->m_qmakespec;
m_qmakespecName = other->m_qmakespecName;
m_mkspecPaths = other->m_mkspecPaths;
m_featureRoots = other->m_featureRoots;
m_dirSep = other->m_dirSep;
}
//////// Evaluator tools /////////
@ -1355,7 +1355,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
return ReturnFalse;
#endif
initFrom(*baseEnv->evaluator);
initFrom(baseEnv->evaluator);
} else {
if (!m_valuemapInited)
loadDefaults();

View File

@ -167,7 +167,7 @@ public:
bool prepareProject(const QString &inDir);
bool loadSpecInternal();
bool loadSpec();
void initFrom(const QMakeEvaluator &other);
void initFrom(const QMakeEvaluator *other);
void setupProject();
void evaluateCommand(const QString &cmds, const QString &where);
void applyExtraConfigs();

View File

@ -252,8 +252,10 @@ int runQMake(int argc, char **argv)
#endif
if(!dir.isNull() && dir != ".")
Option::output_dir = dir;
if(QDir::isRelativePath(Option::output_dir))
if (QDir::isRelativePath(Option::output_dir)) {
Option::output.setFileName(fi.fileName());
Option::output_dir.prepend(oldpwd + QLatin1Char('/'));
}
Option::output_dir = QDir::cleanPath(Option::output_dir);
}

View File

@ -60,7 +60,7 @@ QMakeProject::QMakeProject()
QMakeProject::QMakeProject(QMakeProject *p)
: QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler)
{
initFrom(*p);
initFrom(p);
}
bool QMakeProject::boolRet(VisitReturn vr)

View File

@ -738,7 +738,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
if (num_glyphs == 0)
continue;
buffer->ensure (buffer->len + num_glyphs + (endWithPDF ? 1 : 0));
const long ensureCount = DIV_CEIL(sizeof(CGGlyph) + sizeof(CGPoint) + sizeof(CFIndex), sizeof(*scratch));
buffer->ensure (buffer->len + ensureCount * (num_glyphs + (endWithPDF ? 1 : 0)));
scratch = buffer->get_scratch_buffer (&scratch_size);

View File

@ -53,6 +53,7 @@ import android.text.TextUtils;
import android.view.accessibility.*;
import android.view.MotionEvent;
import android.view.View.OnHoverListener;
import android.content.Context;
@ -85,9 +86,19 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
// the offset of the view on screen into account (eg status bar on top)
private final int[] m_globalOffset = new int[2];
private class HoverEventListener implements View.OnHoverListener
{
@Override
public boolean onHover(View v, MotionEvent event)
{
return dispatchHoverEvent(event);
}
}
public QtAccessibilityDelegate(View host)
{
m_view = host;
m_view.setOnHoverListener(new HoverEventListener());
m_manager = (AccessibilityManager) host.getContext()
.getSystemService(Context.ACCESSIBILITY_SERVICE);
@ -103,7 +114,7 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
// For "explore by touch" we need all movement events here first
// (user moves finger over screen to discover items on screen).
public boolean dispatchHoverEvent(MotionEvent event)
private boolean dispatchHoverEvent(MotionEvent event)
{
if (!m_manager.isTouchExplorationEnabled()) {
return false;

View File

@ -110,24 +110,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
}
}
public boolean dispatchHoverEvent(MotionEvent event) {
// Always attempt to dispatch hover events to accessibility first.
if (m_accessibilityDelegate != null) {
try {
Method dispHoverA11y = m_accessibilityDelegate.getClass().getMethod("dispatchHoverEvent", MotionEvent.class);
boolean ret = (Boolean) dispHoverA11y.invoke(m_accessibilityDelegate, event);
if (ret)
return true;
SurfaceView view = (SurfaceView) this;
Method dispHoverView = view.getClass().getMethod("dispatchHoverEvent", MotionEvent.class);
return (Boolean) dispHoverView.invoke(view, event);
} catch (Exception e) {
Log.w("Qt A11y", "EXCEPTION in dispatchHoverEvent for Accessibility: " + e);
}
}
return false;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{

View File

@ -67,8 +67,10 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return --_q_value != 0;
}
static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW
{
if (currentValue)
*currentValue = _q_value;
if (_q_value == expectedValue) {
_q_value = newValue;
return true;
@ -83,8 +85,8 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return tmp;
}
static
T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
template <typename AdditiveType> static
T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW
{
T returnValue = _q_value;
_q_value += valueToAdd;

View File

@ -42,7 +42,7 @@
class MyStylePlugin : public QStylePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE mystyleplugin.json)
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json")
public:
QStyle *create(const QString &key);
};

View File

@ -59,7 +59,11 @@
#include <QtCore/qconfig.h>
#include <QtCore/qfeatures.h>
#endif
#define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
#if defined(Q_CC_MSVC) && _MSC_VER <= 1500 /* VS2008 */
# define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE)
#else
# define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE))
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
# define QT_NO_UNSHARABLE_CONTAINERS
#endif

View File

@ -566,7 +566,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group)
QStringList QLibraryInfo::platformPluginArguments(const QString &platformName)
{
#ifndef QT_BOOTSTRAPPED
#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_SETTINGS)
if (const QSettings *settings = QLibraryInfoPrivate::findConfiguration()) {
QString key = QLatin1String(platformsSection);
key += QLatin1Char('/');
@ -574,7 +574,7 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName)
key += QLatin1String("Arguments");
return settings->value(key).toStringList();
}
#endif // !QT_BOOTSTRAPPED
#endif // !QT_BOOTSTRAPPED && !QT_NO_SETTINGS
return QStringList();
}

View File

@ -1395,8 +1395,7 @@ void qErrnoWarning(int code, const char *msg, ...)
\since 5.0
Installs a Qt message \a handler which has been defined
previously. Returns a pointer to the previous message handler
(which may be 0).
previously. Returns a pointer to the previous message handler.
The message handler is a function that prints out debug messages,
warnings, critical and fatal error messages. The Qt library (debug

View File

@ -530,7 +530,8 @@ void QFileInfo::setFile(const QDir &dir, const QString &file)
is true. In contrast to canonicalFilePath(), symbolic links or
redundant "." or ".." elements are not necessarily removed.
If the QFileInfo is empty it returns QDir::currentPath().
\warning If filePath() is empty the behavior of this function
is undefined.
\sa filePath(), canonicalFilePath(), isRelative()
*/
@ -572,8 +573,8 @@ QString QFileInfo::canonicalFilePath() const
In contrast to canonicalPath() symbolic links or redundant "." or
".." elements are not necessarily removed.
\warning If the QFileInfo object was created with an empty QString,
the behavior of this function is undefined.
\warning If filePath() is empty the behavior of this function
is undefined.
\sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative()
*/

View File

@ -64,6 +64,25 @@
QT_BEGIN_NAMESPACE
namespace {
class RaiiAutoreleasePool
{
Q_DISABLE_COPY(RaiiAutoreleasePool)
public:
RaiiAutoreleasePool()
: pool([[NSAutoreleasePool alloc] init])
{}
~RaiiAutoreleasePool()
{ [pool release]; }
private:
NSAutoreleasePool *pool;
};
#define Q_AUTORELEASE_POOL(pool) RaiiAutoreleasePool pool; Q_UNUSED(pool);
}
static void callBackFunction(ConstFSEventStreamRef streamRef,
void *clientCallBackInfo,
size_t numEvents,
@ -71,6 +90,8 @@ static void callBackFunction(ConstFSEventStreamRef streamRef,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
Q_AUTORELEASE_POOL(pool)
char **paths = static_cast<char **>(eventPaths);
QFseventsFileSystemWatcherEngine *engine = static_cast<QFseventsFileSystemWatcherEngine *>(clientCallBackInfo);
engine->processEvent(streamRef, numEvents, paths, eventFlags, eventIds);
@ -283,6 +304,7 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString path
void QFseventsFileSystemWatcherEngine::restartStream()
{
Q_AUTORELEASE_POOL(pool)
QMutexLocker locker(&lock);
stopStream();
startStream();
@ -313,6 +335,8 @@ QFseventsFileSystemWatcherEngine::QFseventsFileSystemWatcherEngine(QObject *pare
QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
Q_AUTORELEASE_POOL(pool)
if (stream)
FSEventStreamStop(stream);
@ -327,6 +351,8 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
Q_AUTORELEASE_POOL(pool)
if (stream) {
DEBUG("Flushing, last id is %llu", FSEventStreamGetLatestEventId(stream));
FSEventStreamFlushSync(stream);
@ -413,6 +439,8 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
QStringList *files,
QStringList *directories)
{
Q_AUTORELEASE_POOL(pool)
QMutexLocker locker(&lock);
bool needsRestart = false;

View File

@ -50,6 +50,18 @@ const char qtDefaultCategoryName[] = "default";
Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
(qtDefaultCategoryName))
#ifndef Q_ATOMIC_INT8_IS_SUPPORTED
static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
{
const int bit = 1 << shift;
if (enable)
atomic->fetchAndOrRelaxed(bit);
else
atomic->fetchAndAndRelaxed(~bit);
}
#endif
/*!
\class QLoggingCategory
\inmodule QtCore
@ -129,13 +141,13 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
Order of evaluation:
\list
\li Rules from QtProject/qlogging.ini
\li Rules from QtProject/qtlogging.ini
\li Rules set by \l setFilterRules()
\li Rules from file in \c QT_LOGGING_CONF
\li Rules from environment variable QT_LOGGING_RULES
\endlist
The \c QtProject/qlogging.ini file is looked up in all directories returned
The \c QtProject/qtlogging.ini file is looked up in all directories returned
by QStandardPaths::GenericConfigLocation, e.g.
\list
@ -171,13 +183,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
*/
QLoggingCategory::QLoggingCategory(const char *category)
: d(0),
name(0),
enabledDebug(true),
enabledWarning(true),
enabledCritical(true)
name(0)
{
Q_UNUSED(d);
Q_UNUSED(placeholder);
enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
const bool isDefaultCategory
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
@ -249,9 +259,9 @@ QLoggingCategory::~QLoggingCategory()
bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
{
switch (msgtype) {
case QtDebugMsg: return enabledDebug;
case QtWarningMsg: return enabledWarning;
case QtCriticalMsg: return enabledCritical;
case QtDebugMsg: return isDebugEnabled();
case QtWarningMsg: return isWarningEnabled();
case QtCriticalMsg: return isCriticalEnabled();
case QtFatalMsg: return true;
}
return false;
@ -270,9 +280,15 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
switch (type) {
case QtDebugMsg: enabledDebug = enable; break;
case QtWarningMsg: enabledWarning = enable; break;
case QtCriticalMsg: enabledCritical = enable; break;
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
case QtDebugMsg: bools.enabledDebug.store(enable); break;
case QtWarningMsg: bools.enabledWarning.store(enable); break;
case QtCriticalMsg: bools.enabledCritical.store(enable); break;
#else
case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break;
case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break;
case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break;
#endif
case QtFatalMsg: break;
}
}

View File

@ -57,10 +57,15 @@ public:
bool isEnabled(QtMsgType type) const;
void setEnabled(QtMsgType type, bool enable);
bool isDebugEnabled() const { return enabledDebug; }
bool isWarningEnabled() const { return enabledWarning; }
bool isCriticalEnabled() const { return enabledCritical; }
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
bool isDebugEnabled() const { return bools.enabledDebug.load(); }
bool isWarningEnabled() const { return bools.enabledWarning.load(); }
bool isCriticalEnabled() const { return bools.enabledCritical.load(); }
#else
bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; }
bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; }
bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; }
#endif
const char *categoryName() const { return name; }
// allows usage of both factory method and variable in qCX macros
@ -78,10 +83,24 @@ private:
void *d; // reserved for future use
const char *name;
bool enabledDebug;
bool enabledWarning;
bool enabledCritical;
bool placeholder[5]; // reserve for future use
#ifdef Q_BIG_ENDIAN
enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16 };
#else
enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8 };
#endif
struct AtomicBools {
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
QBasicAtomicInteger<bool> enabledDebug;
QBasicAtomicInteger<bool> enabledWarning;
QBasicAtomicInteger<bool> enabledCritical;
#endif
};
union {
AtomicBools bools;
QBasicAtomicInt enabled;
};
bool placeholder[4]; // reserve for future use
};
#define Q_DECLARE_LOGGING_CATEGORY(name) \

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Intel Corporation
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -819,9 +820,6 @@ QProcessPrivate::QProcessPrivate()
emittedBytesWritten = false;
#ifdef Q_OS_WIN
notifier = 0;
stdoutReader = 0;
stderrReader = 0;
pipeWriter = 0;
processFinishedNotifier = 0;
#endif // Q_OS_WIN
#ifdef Q_OS_UNIX
@ -889,9 +887,9 @@ void QProcessPrivate::cleanup()
notifier = 0;
}
#endif
destroyChannel(&stdoutChannel);
destroyChannel(&stderrChannel);
destroyChannel(&stdinChannel);
closeChannel(&stdoutChannel);
closeChannel(&stderrChannel);
closeChannel(&stdinChannel);
destroyPipe(childStartedPipe);
destroyPipe(deathPipe);
#ifdef Q_OS_UNIX
@ -901,49 +899,63 @@ void QProcessPrivate::cleanup()
/*!
\internal
Returns true if we emitted readyRead().
*/
bool QProcessPrivate::_q_canReadStandardOutput()
bool QProcessPrivate::tryReadFromChannel(Channel *channel)
{
Q_Q(QProcess);
qint64 available = bytesAvailableFromStdout();
if (available == 0) {
if (stdoutChannel.notifier)
stdoutChannel.notifier->setEnabled(false);
destroyChannel(&stdoutChannel);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available");
#endif
if (channel->pipe[0] == INVALID_Q_PIPE)
return false;
qint64 available = bytesAvailableInChannel(channel);
if (available == 0)
available = 1; // always try to read at least one byte
char *ptr = channel->buffer.reserve(available);
qint64 readBytes = readFromChannel(channel, ptr, available);
if (readBytes <= 0)
channel->buffer.chop(available);
if (readBytes == -2) {
// EWOULDBLOCK
return false;
}
char *ptr = outputReadBuffer.reserve(available);
qint64 readBytes = readFromStdout(ptr, available);
if (readBytes == -1) {
processError = QProcess::ReadError;
q->setErrorString(QProcess::tr("Error reading from process"));
emit q->error(processError);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process");
qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process", channel - &stdinChannel);
#endif
return false;
}
if (readBytes == 0) {
// EOF
if (channel->notifier)
channel->notifier->setEnabled(false);
closeChannel(channel);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available", channel - &stdinChannel);
#endif
return false;
}
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
qDebug("QProcessPrivate::tryReadFromChannel(%d), read %d bytes from the process' output", channel - &stdinChannel
int(readBytes));
#endif
if (stdoutChannel.closed) {
outputReadBuffer.chop(readBytes);
if (channel->closed) {
channel->buffer.chop(readBytes);
return false;
}
outputReadBuffer.chop(available - readBytes);
channel->buffer.chop(available - readBytes);
bool didRead = false;
bool isStdout = channel == &stdoutChannel;
if (readBytes == 0) {
if (stdoutChannel.notifier)
stdoutChannel.notifier->setEnabled(false);
} else if (processChannel == QProcess::StandardOutput) {
if (channel->notifier)
channel->notifier->setEnabled(false);
} else if ((processChannel == QProcess::StandardOutput) == isStdout) {
didRead = true;
if (!emittedReadyRead) {
emittedReadyRead = true;
@ -951,53 +963,27 @@ bool QProcessPrivate::_q_canReadStandardOutput()
emittedReadyRead = false;
}
}
emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
if (isStdout)
emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
else
emit q->readyReadStandardError(QProcess::QPrivateSignal());
return didRead;
}
/*!
\internal
*/
bool QProcessPrivate::_q_canReadStandardOutput()
{
return tryReadFromChannel(&stdoutChannel);
}
/*!
\internal
*/
bool QProcessPrivate::_q_canReadStandardError()
{
Q_Q(QProcess);
qint64 available = bytesAvailableFromStderr();
if (available == 0) {
if (stderrChannel.notifier)
stderrChannel.notifier->setEnabled(false);
destroyChannel(&stderrChannel);
return false;
}
char *ptr = errorReadBuffer.reserve(available);
qint64 readBytes = readFromStderr(ptr, available);
if (readBytes == -1) {
processError = QProcess::ReadError;
q->setErrorString(QProcess::tr("Error reading from process"));
emit q->error(processError);
return false;
}
if (stderrChannel.closed) {
errorReadBuffer.chop(readBytes);
return false;
}
errorReadBuffer.chop(available - readBytes);
bool didRead = false;
if (readBytes == 0) {
if (stderrChannel.notifier)
stderrChannel.notifier->setEnabled(false);
} else if (processChannel == QProcess::StandardError) {
didRead = true;
if (!emittedReadyRead) {
emittedReadyRead = true;
emit q->readyRead();
emittedReadyRead = false;
}
}
emit q->readyReadStandardError(QProcess::QPrivateSignal());
return didRead;
return tryReadFromChannel(&stderrChannel);
}
/*!
@ -1009,17 +995,17 @@ bool QProcessPrivate::_q_canWrite()
if (stdinChannel.notifier)
stdinChannel.notifier->setEnabled(false);
if (writeBuffer.isEmpty()) {
if (stdinChannel.buffer.isEmpty()) {
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
#endif
return false;
}
qint64 written = writeToStdin(writeBuffer.readPointer(),
writeBuffer.nextDataBlockSize());
qint64 written = writeToStdin(stdinChannel.buffer.readPointer(),
stdinChannel.buffer.nextDataBlockSize());
if (written < 0) {
destroyChannel(&stdinChannel);
closeChannel(&stdinChannel);
processError = QProcess::WriteError;
q->setErrorString(QProcess::tr("Error writing to process"));
emit q->error(processError);
@ -1031,16 +1017,16 @@ bool QProcessPrivate::_q_canWrite()
#endif
if (written != 0) {
writeBuffer.free(written);
stdinChannel.buffer.free(written);
if (!emittedBytesWritten) {
emittedBytesWritten = true;
emit q->bytesWritten(written);
emittedBytesWritten = false;
}
}
if (stdinChannel.notifier && !writeBuffer.isEmpty())
if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty())
stdinChannel.notifier->setEnabled(true);
if (writeBuffer.isEmpty() && stdinChannel.closed)
if (stdinChannel.buffer.isEmpty() && stdinChannel.closed)
closeWriteChannel();
return true;
}
@ -1163,7 +1149,7 @@ void QProcessPrivate::closeWriteChannel()
// instead.
flushPipeWriter();
#endif
destroyChannel(&stdinChannel);
closeChannel(&stdinChannel);
}
/*!
@ -1308,10 +1294,10 @@ void QProcess::setReadChannel(ProcessChannel channel)
QByteArray buf = d->buffer.readAll();
if (d->processChannel == QProcess::StandardOutput) {
for (int i = buf.size() - 1; i >= 0; --i)
d->outputReadBuffer.ungetChar(buf.at(i));
d->stdoutChannel.buffer.ungetChar(buf.at(i));
} else {
for (int i = buf.size() - 1; i >= 0; --i)
d->errorReadBuffer.ungetChar(buf.at(i));
d->stderrChannel.buffer.ungetChar(buf.at(i));
}
}
d->processChannel = channel;
@ -1359,7 +1345,7 @@ void QProcess::closeWriteChannel()
{
Q_D(QProcess);
d->stdinChannel.closed = true; // closing
if (d->writeBuffer.isEmpty())
if (d->stdinChannel.buffer.isEmpty())
d->closeWriteChannel();
}
@ -1589,8 +1575,8 @@ bool QProcess::canReadLine() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
? &d->errorReadBuffer
: &d->outputReadBuffer;
? &d->stderrChannel.buffer
: &d->stdoutChannel.buffer;
return readBuffer->canReadLine() || QIODevice::canReadLine();
}
@ -1618,8 +1604,8 @@ bool QProcess::atEnd() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
? &d->errorReadBuffer
: &d->outputReadBuffer;
? &d->stderrChannel.buffer
: &d->stdoutChannel.buffer;
return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
}
@ -1636,8 +1622,8 @@ qint64 QProcess::bytesAvailable() const
{
Q_D(const QProcess);
const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
? &d->errorReadBuffer
: &d->outputReadBuffer;
? &d->stderrChannel.buffer
: &d->stdoutChannel.buffer;
#if defined QPROCESS_DEBUG
qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
(d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
@ -1650,7 +1636,7 @@ qint64 QProcess::bytesAvailable() const
qint64 QProcess::bytesToWrite() const
{
Q_D(const QProcess);
qint64 size = d->writeBuffer.size();
qint64 size = d->stdinChannel.buffer.size();
#ifdef Q_OS_WIN
size += d->pipeWriterBytesToWrite();
#endif
@ -1897,8 +1883,8 @@ qint64 QProcess::readData(char *data, qint64 maxlen)
if (!maxlen)
return 0;
QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
? &d->errorReadBuffer
: &d->outputReadBuffer;
? &d->stderrChannel.buffer
: &d->stdoutChannel.buffer;
if (maxlen == 1 && !readBuffer->isEmpty()) {
int c = readBuffer->getChar();
@ -1961,7 +1947,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
}
if (len == 1) {
d->writeBuffer.putChar(*data);
d->stdinChannel.buffer.putChar(*data);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
#if defined QPROCESS_DEBUG
@ -1971,7 +1957,7 @@ qint64 QProcess::writeData(const char *data, qint64 len)
return 1;
}
char *dest = d->writeBuffer.reserve(len);
char *dest = d->stdinChannel.buffer.reserve(len);
memcpy(dest, data, len);
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
@ -2112,8 +2098,8 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
outputReadBuffer.clear();
errorReadBuffer.clear();
stdoutChannel.buffer.clear();
stderrChannel.buffer.clear();
if (stdinChannel.type != QProcessPrivate::Channel::Normal)
mode &= ~QIODevice::WriteOnly; // not open for writing

View File

@ -253,6 +253,9 @@ public:
{
pipe[0] = INVALID_Q_PIPE;
pipe[1] = INVALID_Q_PIPE;
#ifdef Q_OS_WIN
reader = 0;
#endif
}
void clear();
@ -282,6 +285,13 @@ public:
QString file;
QProcessPrivate *process;
QSocketNotifier *notifier;
#ifdef Q_OS_WIN
union {
QWindowsPipeReader *reader;
QWindowsPipeWriter *writer;
};
#endif
QRingBuffer buffer;
Q_PIPE pipe[2];
unsigned type : 2;
@ -316,8 +326,10 @@ public:
Channel stdinChannel;
Channel stdoutChannel;
Channel stderrChannel;
bool createChannel(Channel &channel);
bool openChannel(Channel &channel);
void closeChannel(Channel *channel);
void closeWriteChannel();
bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr
QString program;
QStringList arguments;
@ -326,14 +338,9 @@ public:
#endif
QProcessEnvironment environment;
QRingBuffer outputReadBuffer;
QRingBuffer errorReadBuffer;
QRingBuffer writeBuffer;
Q_PIPE childStartedPipe[2];
Q_PIPE deathPipe[2];
void destroyPipe(Q_PIPE pipe[2]);
void destroyChannel(Channel *channel);
QSocketNotifier *startupSocketNotifier;
QSocketNotifier *deathNotifier;
@ -341,9 +348,6 @@ public:
#ifdef Q_OS_WIN
// the wonderful windows notifier
QTimer *notifier;
QWindowsPipeReader *stdoutReader;
QWindowsPipeReader *stderrReader;
QWindowsPipeWriter *pipeWriter;
QWinEventNotifier *processFinishedNotifier;
#endif
@ -383,10 +387,8 @@ public:
bool waitForFinished(int msecs = 30000);
bool waitForWrite(int msecs = 30000);
qint64 bytesAvailableFromStdout() const;
qint64 bytesAvailableFromStderr() const;
qint64 readFromStdout(char *data, qint64 maxlen);
qint64 readFromStderr(char *data, qint64 maxlen);
qint64 bytesAvailableInChannel(const Channel *channel) const;
qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen);
qint64 writeToStdin(const char *data, qint64 maxlen);
void cleanup();

View File

@ -377,7 +377,7 @@ void QProcessPrivate::destroyPipe(int *pipe)
}
}
void QProcessPrivate::destroyChannel(Channel *channel)
void QProcessPrivate::closeChannel(Channel *channel)
{
destroyPipe(channel->pipe);
}
@ -387,7 +387,7 @@ void QProcessPrivate::destroyChannel(Channel *channel)
This function must be called in order: stdin, stdout, stderr
*/
bool QProcessPrivate::createChannel(Channel &channel)
bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@ -573,9 +573,9 @@ void QProcessPrivate::startProcess()
processManager()->start();
// Initialize pipes
if (!createChannel(stdinChannel) ||
!createChannel(stdoutChannel) ||
!createChannel(stderrChannel) ||
if (!openChannel(stdinChannel) ||
!openChannel(stdoutChannel) ||
!openChannel(stderrChannel) ||
qt_create_pipe(childStartedPipe) != 0 ||
qt_create_pipe(deathPipe) != 0) {
processError = QProcess::FailedToStart;
@ -963,47 +963,32 @@ bool QProcessPrivate::processStarted()
return i <= 0;
}
qint64 QProcessPrivate::bytesAvailableFromStdout() const
qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
int nbytes = 0;
qint64 available = 0;
if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
if (::ioctl(channel->pipe[0], FIONREAD, (char *) &nbytes) >= 0)
available = (qint64) nbytes;
#if defined (QPROCESS_DEBUG)
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);
qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %lld", channel - &stdinChannel, available);
#endif
return available;
}
qint64 QProcessPrivate::bytesAvailableFromStderr() const
qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
int nbytes = 0;
qint64 available = 0;
if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)
available = (qint64) nbytes;
#if defined (QPROCESS_DEBUG)
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);
#endif
return available;
}
qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
{
qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
qint64 bytesRead = qt_safe_read(channel->pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
#endif
return bytesRead;
}
qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
{
qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
int save_errno = errno;
qDebug("QProcessPrivate::readFromChannel(%d, %p \"%s\", %lld) == %lld",
channel - &stdinChannel,
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
errno = save_errno;
#endif
if (bytesRead == -1 && errno == EWOULDBLOCK)
return -2;
return bytesRead;
}
@ -1126,7 +1111,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (stderrChannel.pipe[0] != -1)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@ -1188,7 +1173,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QList<QSocketNotifier *> notifiers = defaultNotifiers();
#endif
while (!writeBuffer.isEmpty()) {
while (!stdinChannel.buffer.isEmpty()) {
fd_set fdread;
fd_set fdwrite;
@ -1207,7 +1192,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
add_fd(nfds, stderrChannel.pipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
@ -1282,7 +1267,7 @@ bool QProcessPrivate::waitForFinished(int msecs)
if (processState == QProcess::Running)
add_fd(nfds, deathPipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());

View File

@ -158,7 +158,7 @@ static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
This function must be called in order: stdin, stdout, stderr
*/
bool QProcessPrivate::createChannel(Channel &channel)
bool QProcessPrivate::openChannel(Channel &channel)
{
Q_Q(QProcess);
@ -180,34 +180,31 @@ bool QProcessPrivate::createChannel(Channel &channel)
&channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS);
}
} else {
QWindowsPipeReader *pipeReader = 0;
if (&channel == &stdoutChannel) {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedOutputChannel) {
if (!stdoutReader) {
stdoutReader = new QWindowsPipeReader(q);
q->connect(stdoutReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
if (!stdoutChannel.reader) {
stdoutChannel.reader = new QWindowsPipeReader(q);
q->connect(stdoutChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardOutput()));
}
pipeReader = stdoutReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_OUTPUT_HANDLE);
}
} else /* if (&channel == &stderrChannel) */ {
if (processChannelMode != QProcess::ForwardedChannels
&& processChannelMode != QProcess::ForwardedErrorChannel) {
if (!stderrReader) {
stderrReader = new QWindowsPipeReader(q);
q->connect(stderrReader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
if (!stderrChannel.reader) {
stderrChannel.reader = new QWindowsPipeReader(q);
q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
}
pipeReader = stderrReader;
} else {
duplicateStdWriteChannel(channel.pipe, STD_ERROR_HANDLE);
}
}
if (pipeReader) {
if (channel.reader) {
qt_create_pipe(channel.pipe, false);
pipeReader->setHandle(channel.pipe[0]);
pipeReader->startAsyncRead();
channel.reader->setHandle(channel.pipe[0]);
channel.reader->startAsyncRead();
}
}
@ -332,25 +329,15 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
}
}
void QProcessPrivate::destroyChannel(Channel *channel)
void QProcessPrivate::closeChannel(Channel *channel)
{
if (channel == &stdinChannel) {
if (pipeWriter) {
delete pipeWriter;
pipeWriter = 0;
}
} else if (channel == &stdoutChannel) {
if (stdoutReader) {
stdoutReader->stop();
stdoutReader->deleteLater();
stdoutReader = 0;
}
} else if (channel == &stderrChannel) {
if (stderrReader) {
stderrReader->stop();
stderrReader->deleteLater();
stderrReader = 0;
}
delete stdinChannel.writer;
stdinChannel.writer = 0;
} else if (channel->reader) {
channel->reader->stop();
channel->reader->deleteLater();
channel->reader = 0;
}
destroyPipe(channel->pipe);
}
@ -486,9 +473,9 @@ void QProcessPrivate::startProcess()
q->setProcessState(QProcess::Starting);
if (!createChannel(stdinChannel) ||
!createChannel(stdoutChannel) ||
!createChannel(stderrChannel))
if (!openChannel(stdinChannel) ||
!openChannel(stdoutChannel) ||
!openChannel(stderrChannel))
return;
QString args = qt_create_commandline(program, arguments);
@ -577,47 +564,25 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
qint64 QProcessPrivate::bytesAvailableFromStdout() const
qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *channel) const
{
if (stdoutChannel.pipe[0] == INVALID_Q_PIPE)
return 0;
Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
Q_ASSERT(channel->reader);
if (!stdoutReader)
return 0;
DWORD bytesAvail = stdoutReader->bytesAvailable();
DWORD bytesAvail = channel->reader->bytesAvailable();
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
qDebug("QProcessPrivate::bytesAvailableInChannel(%d) == %d", channel - &stdinChannel, bytesAvail);
#endif
return bytesAvail;
}
qint64 QProcessPrivate::bytesAvailableFromStderr() const
qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint64 maxlen)
{
if (stderrChannel.pipe[0] == INVALID_Q_PIPE)
return 0;
if (!stderrReader)
return 0;
DWORD bytesAvail = stderrReader->bytesAvailable();
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
#endif
return bytesAvail;
Q_ASSERT(channel->pipe[0] != INVALID_Q_PIPE);
Q_ASSERT(channel->reader);
return channel->reader->read(data, maxlen);
}
qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
{
return stdoutReader ? stdoutReader->read(data, maxlen) : 0;
}
qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
{
return stderrReader ? stderrReader->read(data, maxlen) : 0;
}
static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
{
DWORD currentProcId = 0;
@ -659,20 +624,20 @@ bool QProcessPrivate::waitForStarted(int)
bool QProcessPrivate::drainOutputPipes()
{
if (!stdoutReader && !stderrReader)
if (!stdoutChannel.reader && !stderrChannel.reader)
return false;
bool someReadyReadEmitted = false;
forever {
bool readyReadEmitted = false;
bool readOperationActive = false;
if (stdoutReader) {
readyReadEmitted |= stdoutReader->waitForReadyRead(0);
readOperationActive = stdoutReader && stdoutReader->isReadOperationActive();
if (stdoutChannel.reader) {
readyReadEmitted |= stdoutChannel.reader->waitForReadyRead(0);
readOperationActive = stdoutChannel.reader && stdoutChannel.reader->isReadOperationActive();
}
if (stderrReader) {
readyReadEmitted |= stderrReader->waitForReadyRead(0);
readOperationActive |= stderrReader && stderrReader->isReadOperationActive();
if (stderrChannel.reader) {
readyReadEmitted |= stderrChannel.reader->waitForReadyRead(0);
readOperationActive |= stderrChannel.reader && stderrChannel.reader->isReadOperationActive();
}
someReadyReadEmitted |= readyReadEmitted;
if (!readOperationActive || !readyReadEmitted)
@ -690,13 +655,13 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
if (!writeBuffer.isEmpty() && !_q_canWrite())
if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
if (pipeWriter && pipeWriter->waitForWrite(0))
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
if ((stdoutReader && stdoutReader->waitForReadyRead(0))
|| (stderrReader && stderrReader->waitForReadyRead(0)))
if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
|| (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)))
return true;
if (!pid)
@ -726,12 +691,12 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
forever {
// Check if we have any data pending: the pipe writer has
// bytes waiting to written, or it has written data since the
// last time we called pipeWriter->waitForWrite().
bool pendingDataInPipe = pipeWriter && (pipeWriter->bytesToWrite() || pipeWriter->hadWritten());
// last time we called stdinChannel.writer->waitForWrite().
bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
// If we don't have pending data, and our write buffer is
// empty, we fail.
if (!pendingDataInPipe && writeBuffer.isEmpty())
if (!pendingDataInPipe && stdinChannel.buffer.isEmpty())
return false;
// If we don't have pending data and we do have data in our
@ -746,21 +711,21 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
// written. This will succeed if either the pipe writer has
// already written the data, or if it manages to write data
// within the given timeout. If the write buffer was non-empty
// and the pipeWriter is now dead, that means _q_canWrite()
// and the stdinChannel.writer is now dead, that means _q_canWrite()
// destroyed the writer after it successfully wrote the last
// batch.
if (!pipeWriter || pipeWriter->waitForWrite(0))
if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))
return true;
// If we wouldn't write anything, check if we can read stdout.
if (bytesAvailableFromStdout() != 0) {
_q_canReadStandardOutput();
if (bytesAvailableInChannel(&stdoutChannel) != 0) {
tryReadFromChannel(&stdoutChannel);
timer.resetIncrements();
}
// Check if we can read stderr.
if (bytesAvailableFromStderr() != 0) {
_q_canReadStandardError();
if (bytesAvailableInChannel(&stderrChannel) != 0) {
tryReadFromChannel(&stderrChannel);
timer.resetIncrements();
}
@ -795,13 +760,13 @@ bool QProcessPrivate::waitForFinished(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
if (!writeBuffer.isEmpty() && !_q_canWrite())
if (!stdinChannel.buffer.isEmpty() && !_q_canWrite())
return false;
if (pipeWriter && pipeWriter->waitForWrite(0))
if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
timer.resetIncrements();
if (stdoutReader && stdoutReader->waitForReadyRead(0))
if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
if (stderrReader && stderrReader->waitForReadyRead(0))
if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
timer.resetIncrements();
if (!pid) {
@ -837,33 +802,32 @@ void QProcessPrivate::findExitCode()
void QProcessPrivate::flushPipeWriter()
{
if (pipeWriter && pipeWriter->bytesToWrite() > 0) {
pipeWriter->waitForWrite(ULONG_MAX);
}
if (stdinChannel.writer && stdinChannel.writer->bytesToWrite() > 0)
stdinChannel.writer->waitForWrite(ULONG_MAX);
}
qint64 QProcessPrivate::pipeWriterBytesToWrite() const
{
return pipeWriter ? pipeWriter->bytesToWrite() : qint64(0);
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
}
qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
Q_Q(QProcess);
if (!pipeWriter) {
pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
pipeWriter->start();
if (!stdinChannel.writer) {
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
stdinChannel.writer->start();
}
return pipeWriter->write(data, maxlen);
return stdinChannel.writer->write(data, maxlen);
}
bool QProcessPrivate::waitForWrite(int msecs)
{
Q_Q(QProcess);
if (!pipeWriter || pipeWriter->waitForWrite(msecs))
if (!stdinChannel.writer || stdinChannel.writer->waitForWrite(msecs))
return true;
processError = QProcess::Timedout;
@ -875,7 +839,7 @@ void QProcessPrivate::_q_notified()
{
notifier->stop();
if (!writeBuffer.isEmpty() && (!pipeWriter || pipeWriter->waitForWrite(0)))
if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0)))
_q_canWrite();
if (processState != QProcess::NotRunning)

View File

@ -62,7 +62,7 @@ void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
Q_UNUSED(pipe);
}
void QProcessPrivate::destroyChannel(Channel *channel)
void QProcessPrivate::closeChannel(Channel *channel)
{
Q_UNUSED(channel);
}
@ -174,22 +174,12 @@ bool QProcessPrivate::processStarted()
return processState == QProcess::Running;
}
qint64 QProcessPrivate::bytesAvailableFromStdout() const
qint64 QProcessPrivate::bytesAvailableInChannel(const Channel *) const
{
return 0;
}
qint64 QProcessPrivate::bytesAvailableFromStderr() const
{
return 0;
}
qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
{
return -1;
}
qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
qint64 QProcessPrivate::readFromChannel(const Channel *, char *data, qint64 maxlen)
{
return -1;
}

View File

@ -104,14 +104,23 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case GenericCacheLocation:
return writableLocation(GenericDataLocation) + QLatin1String("/cache");
case RuntimeLocation:
case HomeLocation:
result = QDir::homePath();
break;
case TempLocation:
result = QDir::tempPath();
break;
case ApplicationsLocation:
case DesktopLocation:
case FontsLocation:
case HomeLocation:
case RuntimeLocation:
// these are read-only
break;
case DocumentsLocation:
case MusicLocation:
case MoviesLocation:
case PicturesLocation:
case DownloadLocation:
default:
Q_UNIMPLEMENTED();
}

View File

@ -132,7 +132,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
{
if (pipeBroken && actualReadBufferSize == 0)
return -1; // signal EOF
return 0; // signal EOF
qint64 readSoFar;
// If startAsyncRead() has read data, copy it to its destination.
@ -159,6 +159,8 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
emitReadyReadTimer->stop();
if (!readSequenceStarted)
startAsyncRead();
if (readSoFar == 0)
return -2; // signal EWOULDBLOCK
}
return readSoFar;

View File

@ -325,8 +325,6 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
{
if (internalHwnd)
DestroyWindow(internalHwnd);
QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
}
void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
@ -486,10 +484,26 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
#endif
}
static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
// Provide class name and atom for the message window used by
// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads.
struct QWindowsMessageWindowClassContext
{
QWindowsMessageWindowClassContext();
~QWindowsMessageWindowClassContext();
ATOM atom;
wchar_t *className;
};
QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext()
: atom(0), className(0)
{
// make sure that multiple Qt's can coexist in the same process
QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget")
+ QString::number(quintptr(qt_internal_proc));
className = new wchar_t[qClassName.size() + 1];
qClassName.toWCharArray(className);
className[qClassName.size()] = 0;
WNDCLASS wc;
wc.style = 0;
@ -501,16 +515,37 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16());
wc.lpszClassName = className;
atom = RegisterClass(&wc);
if (!atom) {
qErrnoWarning("%s: RegisterClass() failed", Q_FUNC_INFO, qPrintable(qClassName));
delete [] className;
className = 0;
}
}
RegisterClass(&wc);
QWindowsMessageWindowClassContext::~QWindowsMessageWindowClassContext()
{
if (className) {
UnregisterClass(className, qWinAppInst());
delete [] className;
}
}
Q_GLOBAL_STATIC(QWindowsMessageWindowClassContext, qWindowsMessageWindowClassContext)
static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
{
QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
if (!ctx->atom)
return 0;
#ifdef Q_OS_WINCE
HWND parent = 0;
#else
HWND parent = HWND_MESSAGE;
#endif
HWND wnd = CreateWindow(wc.lpszClassName, // classname
wc.lpszClassName, // window name
HWND wnd = CreateWindow(ctx->className, // classname
ctx->className, // window name
0, // style
0, 0, 0, 0, // geometry
parent, // parent
@ -519,7 +554,8 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
0); // windows creation data.
if (!wnd) {
qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
qErrnoWarning("%s: CreateWindow() for QEventDispatcherWin32 internal window failed", Q_FUNC_INFO);
return 0;
}
#ifdef GWLP_USERDATA
@ -620,7 +656,9 @@ void QEventDispatcherWin32::createInternalHwnd()
// setup GetMessage hook needed to drive our posted events
d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
if (!d->getMessageHook) {
qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
int errorCode = GetLastError();
qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s",
errorCode, qPrintable(qt_error_string(errorCode)));
}
#endif

View File

@ -113,10 +113,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
{
jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative");
if (env->ExceptionCheck()) {
env->ExceptionClear();
if (exceptionCheck(env))
return JNI_ERR;
}
jmethodID activityMethodID = env->GetStaticMethodID(jQtNative,
"activity",

View File

@ -3238,7 +3238,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
int method_index_absolute = method_index + method_offset;
while (c2) {
if (c2->receiver == receiver && c2->method() == method_index_absolute)
if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute)
return 0;
c2 = c2->nextConnectionList;
}

View File

@ -622,7 +622,7 @@ namespace QtPrivate {
static char test(...);
enum {
Ok = sizeof(test(dummy<Functor>())) == sizeof(int),
Value = Ok ? sizeof...(ArgList) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
};
};

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
static const char boilerplate_supported_but_time_limited[] =
"\nQt %1 Evaluation License\n"
"Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n"
"Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).\n"
"This trial version may only be used for evaluation purposes\n"
"and will shut down after 120 minutes.\n"
"Registered to:\n"
@ -65,7 +65,7 @@ static const char boilerplate_supported_but_time_limited[] =
static const char boilerplate_supported[] =
"\nQt %1 Evaluation License\n"
"Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).\n"
"Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).\n"
"This trial version may only be used for evaluation purposes\n"
"Registered to:\n"
" Licensee: %2\n\n"

View File

@ -359,7 +359,7 @@ class QLibraryStore
{
public:
inline ~QLibraryStore();
static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version);
static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints);
static inline void releaseLibrary(QLibraryPrivate *lib);
static inline void cleanup();
@ -438,17 +438,21 @@ QLibraryStore *QLibraryStore::instance()
return qt_library_data;
}
inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version)
inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance();
// check if this library is already loaded
QLibraryPrivate *lib = 0;
if (Q_LIKELY(data))
if (Q_LIKELY(data)) {
lib = data->libraryMap.value(fileName);
if (lib)
lib->mergeLoadHints(loadHints);
}
if (!lib)
lib = new QLibraryPrivate(fileName, version);
lib = new QLibraryPrivate(fileName, version, loadHints);
// track this library
if (Q_LIKELY(data))
@ -479,21 +483,34 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
delete lib;
}
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
loadHints(0),
loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{ }
QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
{
return QLibraryStore::findOrCreate(fileName, version);
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
return QLibraryStore::findOrCreate(fileName, version, loadHints);
}
QLibraryPrivate::~QLibraryPrivate()
{
}
void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
{
// if the library is already loaded, we can't change the load hints
if (pHnd)
return;
loadHints = lh;
}
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
{
if (!pHnd)

View File

@ -94,7 +94,8 @@ public:
void release();
QFunctionPointer resolve(const char *);
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = 0);
static QStringList suffixes_sys(const QString &fullVersion);
static QStringList prefixes_sys();
@ -117,8 +118,9 @@ public:
}
private:
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version);
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints);
~QLibraryPrivate();
void mergeLoadHints(QLibrary::LoadHints loadHints);
bool load_sys();
bool unload_sys();

View File

@ -352,11 +352,8 @@ void QPluginLoader::setFileName(const QString &fileName)
else
fn = locatePlugin(fileName);
d = QLibraryPrivate::findOrCreate(fn);
d->loadHints = lh;
if (fn.isEmpty())
d->errorString = QLibrary::tr("The shared library was not found.");
else
d = QLibraryPrivate::findOrCreate(fn, QString(), lh);
if (!fn.isEmpty())
d->updatePluginState();
#else

View File

@ -58,6 +58,7 @@
\inmodule QtCore
\brief The QAtomicInteger class provides platform-independent atomic operations on integers.
\ingroup thread
\since 5.3
For atomic operations on pointers, see the QAtomicPointer class.

View File

@ -380,7 +380,7 @@ bool QBasicMutex::isRecursive()
*/
/*!
\fn QMutex *QMutexLocker::mutex()
\fn QMutex *QMutexLocker::mutex() const
Returns the mutex on which the QMutexLocker is operating.

View File

@ -77,7 +77,7 @@ public:
return fastTryLock();
}
bool isRecursive();
bool isRecursive(); //### Qt6: mark const
private:
inline bool fastTryLock() Q_DECL_NOTHROW {
@ -186,10 +186,10 @@ public:
inline explicit QMutex(RecursionMode mode = NonRecursive) { Q_UNUSED(mode); }
static inline void lock() {}
static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
static inline void unlock() {}
static inline bool isRecursive() { return true; }
inline void lock() {}
inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
inline void unlock() {}
inline bool isRecursive() { return true; }
private:
Q_DISABLE_COPY(QMutex)
@ -201,9 +201,9 @@ public:
inline explicit QMutexLocker(QMutex *) {}
inline ~QMutexLocker() {}
static inline void unlock() {}
static void relock() {}
static inline QMutex *mutex() { return 0; }
inline void unlock() {}
void relock() {}
inline QMutex *mutex() const { return 0; }
private:
Q_DISABLE_COPY(QMutexLocker)

View File

@ -75,10 +75,17 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
{
detach();
UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_UPPER_FIRST : UCOL_OFF;
// The strength attribute in ICU is rather badly documented. Basically UCOL_PRIMARY
// ignores differences between base characters and accented characters as well as case.
// So A and A-umlaut would compare equal.
// UCOL_SECONDARY ignores case differences. UCOL_TERTIARY is the default in most languages
// and does case sensitive comparison.
// UCOL_QUATERNARY is used as default in a few languages such as Japanese to take care of some
// additional differences in those languages.
UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY;
UErrorCode status = U_ZERO_ERROR;
ucol_setAttribute(d->collator, UCOL_CASE_FIRST, val, &status);
ucol_setAttribute(d->collator, UCOL_STRENGTH, val, &status);
if (U_FAILURE(status))
qWarning("ucol_setAttribute: Case First failed: %d", status);
}

View File

@ -128,12 +128,15 @@ bool QCollator::ignorePunctuation() const
int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
{
SInt32 result;
return UCCompareText(d->collator.collator,
Boolean equivalent;
UCCompareText(d->collator.collator,
reinterpret_cast<const UniChar *>(s1), len1,
reinterpret_cast<const UniChar *>(s2), len2,
NULL,
&equivalent,
&result);
return result;
if (equivalent)
return 0;
return result < 0 ? -1 : 1;
}
int QCollator::compare(const QString &str1, const QString &str2) const
{

View File

@ -90,7 +90,7 @@ public:
// special case: it is in the first buffer
int nextDataBlockSizeValue = nextDataBlockSize();
if (pos - head < nextDataBlockSizeValue) {
if (pos < nextDataBlockSizeValue) {
length = nextDataBlockSizeValue - pos;
return buffers.at(0).constData() + head + pos;
}

View File

@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
\since 4.8
\ingroup misc
The QScopedAssignment class can be used to revert state when an
The QScopedValueRollback class can be used to revert state when an
exception is thrown without needing to write try-catch blocks.
It can also be used to manage variables that are temporarily set,

View File

@ -220,8 +220,10 @@
|| (defined(Q_CC_CLANG) && (__clang_major__ * 100 + __clang_minor__ >= 208)) \
|| defined(Q_CC_INTEL))
# define QT_COMPILER_SUPPORTS_X86INTRIN
# ifndef Q_CC_INTEL
# ifdef Q_CC_INTEL
// The Intel compiler has no <x86intrin.h> -- all intrinsics are in <immintrin.h>;
# include <immintrin.h>
# else
// GCC 4.4 and Clang 2.8 added a few more intrinsics there
# include <x86intrin.h>
# endif

View File

@ -9894,9 +9894,7 @@ QString QString::toHtmlEscaped() const
the read-only segment of the compiled object file.
For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to
QLatin1String.
The result of the QStringLiteral expression can be cast into a QString.
QString::fromUtf8().
If you have code looking like:
\code

View File

@ -256,7 +256,7 @@ private:
void deliverCall(QObject *object, int flags, const QDBusMessage &msg,
const QVector<int> &metaTypes, int slotIdx);
bool isServiceRegisteredByThread(const QString &serviceName) const;
bool isServiceRegisteredByThread(const QString &serviceName);
QString getNameOwnerNoCache(const QString &service);

View File

@ -73,8 +73,8 @@
QT_BEGIN_NAMESPACE
static bool isDebugging;
#define qDBusDebug if (!::isDebugging); else qDebug
static QBasicAtomicInt isDebugging = Q_BASIC_ATOMIC_INITIALIZER(-1);
#define qDBusDebug if (::isDebugging == 0); else qDebug
Q_GLOBAL_STATIC_WITH_ARGS(const QString, orgFreedesktopDBusString, (QLatin1String(DBUS_SERVICE_DBUS)))
@ -1022,13 +1022,12 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
anonymousAuthenticationAllowed(false)
{
static const bool threads = q_dbus_threads_init_default();
static const int debugging = qgetenv("QDBUS_DEBUG").toInt();
::isDebugging = debugging;
if (::isDebugging == -1)
::isDebugging = qgetenv("QDBUS_DEBUG").toInt();
Q_UNUSED(threads)
Q_UNUSED(debugging)
#ifdef QDBUS_THREAD_DEBUG
if (debugging > 1)
if (::isDebugging > 1)
qdbusThreadDebug = qdbusDefaultThreadDebug;
#endif
@ -2488,12 +2487,15 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName)
serviceNames.removeAll(serviceName);
}
bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const
bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName)
{
if (!serviceName.isEmpty() && serviceName == baseService)
return true;
QStringList copy = serviceNames;
return copy.contains(serviceName);
if (serviceName == dbusServiceString())
return false;
QDBusReadLocker locker(UnregisterServiceAction, this);
return serviceNames.contains(serviceName);
}
void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEvent *ev)

View File

@ -1713,10 +1713,6 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
/*! \internal */
QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
{
if (!&ev) {
d << "QAccessibleEvent(null)";
return d;
}
d.nospace() << "QAccessibleEvent(";
if (ev.object()) {
d.nospace() << "object=" << hex << ev.object() << dec;

View File

@ -64,7 +64,7 @@ template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,con
return QQuaternion::slerp(f, t, progress);
}
static void qRegisterGuiGetInterpolator()
void qRegisterGuiGetInterpolator()
{
qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
qRegisterAnimationInterpolator<QVector2D>(_q_interpolateVariant<QVector2D>);

View File

@ -674,7 +674,7 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCo
return;
qint64 oldPos = device->pos();
if (!device->seek(0))
if (device->isSequential() || !device->seek(0))
return;
int colorCount = 0;

View File

@ -363,44 +363,93 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon
}
}
void QPixmapIconEngine::addFile(const QString &fileName, const QSize &_size, QIcon::Mode mode, QIcon::State state)
// Read out original image depth as set by ICOReader
static inline int origIcoDepth(const QImage &image)
{
if (!fileName.isEmpty()) {
QString abs = fileName;
if (fileName.at(0) != QLatin1Char(':'))
abs = QFileInfo(fileName).absoluteFilePath();
QImageReader reader(abs);
const QString s = image.text(QStringLiteral("_q_icoOrigDepth"));
return s.isEmpty() ? 32 : s.toInt();
}
do {
QSize size = _size;
QPixmap pixmap;
for (int i = 0; i < pixmaps.count(); ++i) {
if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
QPixmapIconEngineEntry *pe = &pixmaps[i];
if (size == QSize()) {
pixmap.convertFromImage(reader.read());
size = pixmap.size();
}
if (pe->size == QSize() && pe->pixmap.isNull()) {
pe->pixmap = QPixmap(pe->fileName);
// Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
// but be used as a 1x pixmap by QIcon.
pe->pixmap.setDevicePixelRatio(1.0);
pe->size = pe->pixmap.size();
}
if (pe->size == size) {
pe->pixmap = pixmap;
pe->fileName = abs;
return;
}
}
}
QPixmapIconEngineEntry e(abs, size, mode, state);
e.pixmap = pixmap;
pixmaps += e;
} while (reader.jumpToNextImage());
static inline int findBySize(const QList<QImage> &images, const QSize &size)
{
for (int i = 0; i < images.size(); ++i) {
if (images.at(i).size() == size)
return i;
}
return -1;
}
// Convenience class providing a bool read() function.
namespace {
class ImageReader
{
public:
ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
QByteArray format() const { return m_reader.format(); }
bool read(QImage *image)
{
if (m_atEnd)
return false;
*image = m_reader.read();
if (!image->size().isValid()) {
m_atEnd = true;
return false;
}
m_atEnd = !m_reader.jumpToNextImage();
return true;
}
private:
QImageReader m_reader;
bool m_atEnd;
};
} // namespace
void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
{
if (fileName.isEmpty())
return;
const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath();
const bool ignoreSize = !size.isValid();
ImageReader imageReader(abs);
const QByteArray format = imageReader.format();
if (format.isEmpty()) // Device failed to open or unsupported format.
return;
QImage image;
if (format != "ico") {
if (ignoreSize) { // No size specified: Add all images.
while (imageReader.read(&image))
pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
} else {
// Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
while (imageReader.read(&image) && image.size() != size) {}
pixmaps += image.size() == size ?
QPixmapIconEngineEntry(abs, image, mode, state) : QPixmapIconEngineEntry(abs, size, mode, state);
}
return;
}
// Special case for reading Windows ".ico" files. Historically (QTBUG-39287),
// these files may contain low-resolution images. As this information is lost,
// ICOReader sets the original format as an image text key value. Read all matching
// images into a list trying to find the highest quality per size.
QList<QImage> icoImages;
while (imageReader.read(&image)) {
if (ignoreSize || image.size() == size) {
const int position = findBySize(icoImages, image.size());
if (position >= 0) { // Higher quality available? -> replace.
if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
icoImages[position] = image;
} else {
icoImages.append(image);
}
}
}
foreach (const QImage &i, icoImages)
pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
}
QString QPixmapIconEngine::key() const

View File

@ -89,6 +89,7 @@ struct QPixmapIconEngineEntry
:pixmap(pm), size(pm.size()), mode(m), state(s){}
QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
:fileName(file), size(sz), mode(m), state(s){}
QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off);
QPixmap pixmap;
QString fileName;
QSize size;
@ -97,7 +98,14 @@ struct QPixmapIconEngineEntry
bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
};
inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
: fileName(file), size(image.size()), mode(m), state(s)
{
pixmap.convertFromImage(image);
// Reset the devicePixelRatio. The pixmap may be loaded from a @2x file,
// but be used as a 1x pixmap by QIcon.
pixmap.setDevicePixelRatio(1.0);
}
class QPixmapIconEngine : public QIconEngine {
public:

View File

@ -1662,11 +1662,14 @@ void QImage::fill(uint pixel)
return;
}
if (d->format == Format_RGB32 || d->format == Format_RGBX8888)
if (d->format == Format_RGB32)
pixel |= 0xff000000;
if (d->format == Format_RGBX8888 || d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied)
pixel = ARGB2RGBA(pixel);
if (d->format == Format_RGBX8888)
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
pixel |= 0xff000000;
#else
pixel |= 0x000000ff;
#endif
qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
@ -1716,22 +1719,27 @@ void QImage::fill(const QColor &color)
if (!d)
return;
if (d->depth == 32) {
uint pixel = color.rgba();
if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied)
pixel = qPremultiply(pixel);
fill((uint) pixel);
} else if (d->format == QImage::Format_RGB16) {
switch (d->format) {
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
fill(color.rgba());
break;
case QImage::Format_ARGB32_Premultiplied:
fill(qPremultiply(color.rgba()));
break;
case QImage::Format_RGBX8888:
fill(ARGB2RGBA(color.rgba() | 0xff000000));
break;
case QImage::Format_RGBA8888:
fill(ARGB2RGBA(color.rgba()));
break;
case QImage::Format_RGBA8888_Premultiplied:
fill(ARGB2RGBA(qPremultiply(color.rgba())));
break;
case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
} else if (d->depth == 1) {
if (color == Qt::color1)
fill((uint) 1);
else
fill((uint) 0);
} else if (d->depth == 8) {
break;
case QImage::Format_Indexed8: {
uint pixel = 0;
for (int i=0; i<d->colortable.size(); ++i) {
if (color.rgba() == d->colortable.at(i)) {
@ -1740,20 +1748,24 @@ void QImage::fill(const QColor &color)
}
}
fill(pixel);
} else {
break;
}
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
if (color == Qt::color1)
fill((uint) 1);
else
fill((uint) 0);
break;
default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), color);
}
}}
}
/*!
Inverts all pixel values in the image.
@ -2685,13 +2697,6 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
return maskImage;
}
/*
This code is contributed by Philipp Lang,
GeneriCom Software Germany (www.generi.com)
under the terms of the QPL, Version 1.0
*/
/*!
\fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const
Returns a mirror of the image, mirrored in the horizontal and/or
@ -2703,61 +2708,108 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
\sa {QImage#Image Transformations}{Image Transformations}
*/
template<typename T>
inline void mirrored_helper_loop(int w, int h, int dxi, int dxs, int dyi, int dy, const uchar* sdata, uchar* ddata, int sbpl, int dbpl)
template<class T> inline void do_mirror_data(QImageData *dst, QImageData *src,
int dstX0, int dstY0,
int dstXIncr, int dstYIncr,
int w, int h)
{
for (int sy = 0; sy < h; sy++, dy += dyi) {
const T* ssl = (T*)(sdata + sy*sbpl);
T* dsl = (T*)(ddata + dy*dbpl);
int dx = dxs;
for (int sx = 0; sx < w; sx++, dx += dxi)
dsl[dx] = ssl[sx];
}
}
template<typename T>
inline void mirrored_helper_loop_inplace(int w, int h, int dxi, int dxs, int dyi, int dy, uchar* sdata, int sbpl)
{
for (int sy = 0; sy < h; sy++, dy += dyi) {
T* ssl = (T*)(sdata + sy*sbpl);
T* dsl = (T*)(sdata + dy*sbpl);
int dx = dxs;
for (int sx = 0; sx < w; sx++, dx += dxi)
std::swap(dsl[dx], ssl[sx]);
}
}
inline void mirror_horizonal_bitmap(int w, int h, int dxs, uchar* data, int bpl, bool monolsb)
{
int shift = w % 8;
const uchar* bitflip = qt_get_bitflip_array();
for (int y = h-1; y >= 0; y--) {
quint8* a0 = (quint8*)(data + y*bpl);
// Swap bytes
quint8* a = a0+dxs;
while (a >= a0) {
*a = bitflip[*a];
a--;
if (dst == src) {
// When mirroring in-place, stop in the middle for one of the directions, since we
// are swapping the bytes instead of merely copying.
const int srcXEnd = dstX0 ? w / 2 : w;
const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h;
for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
std::swap(srcPtr[srcX], dstPtr[dstX]);
}
// Shift bits if unaligned
if (shift != 0) {
a = a0+dxs;
quint8 c = 0;
if (monolsb) {
while (a >= a0) {
quint8 nc = *a << shift;
*a = (*a >> (8-shift)) | c;
--a;
c = nc;
}
} else {
while (a >= a0) {
quint8 nc = *a >> shift;
*a = (*a << (8-shift)) | c;
--a;
c = nc;
} else {
for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
for (int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
dstPtr[dstX] = srcPtr[srcX];
}
}
}
inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical)
{
Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
int w = src->width;
int h = src->height;
int depth = src->depth;
if (src->depth == 1) {
w = (w + 7) / 8; // byte aligned width
depth = 8;
}
int dstX0 = 0, dstXIncr = 1;
int dstY0 = 0, dstYIncr = 1;
if (horizontal) {
// 0 -> w-1, 1 -> w-2, 2 -> w-3, ...
dstX0 = w - 1;
dstXIncr = -1;
}
if (vertical) {
// 0 -> h-1, 1 -> h-2, 2 -> h-3, ...
dstY0 = h - 1;
dstYIncr = -1;
}
switch (depth) {
case 32:
do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
case 24:
do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
case 16:
do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
case 8:
do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
default:
Q_ASSERT(false);
break;
}
// The bytes are now all in the correct place. In addition, the bits in the individual
// bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image.
if (horizontal && dst->depth == 1) {
Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
const int shift = 8 - (dst->width % 8);
const uchar *bitflip = qt_get_bitflip_array();
for (int y = 0; y < h; ++y) {
uchar *begin = dst->data + y * dst->bytes_per_line;
uchar *end = begin + dst->bytes_per_line;
for (uchar *p = begin; p < end; ++p) {
*p = bitflip[*p];
// When the data is non-byte aligned, an extra bit shift (of the number of
// unused bits at the end) is needed for the entire scanline.
if (shift != 8 && p != begin) {
if (dst->format == QImage::Format_Mono) {
for (int i = 0; i < shift; ++i) {
p[-1] <<= 1;
p[-1] |= (*p & (128 >> i)) >> (7 - i);
}
} else {
for (int i = 0; i < shift; ++i) {
p[-1] >>= 1;
p[-1] |= (*p & (1 << i)) << (7 - i);
}
}
}
}
if (shift != 8) {
if (dst->format == QImage::Format_Mono)
end[-1] <<= shift;
else
end[-1] >>= shift;
}
}
}
}
@ -2773,8 +2825,6 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return *this;
int w = d->width;
int h = d->height;
// Create result image, copy colormap
QImage result(d->width, d->height, d->format);
QIMAGE_SANITYCHECK_MEMORY(result);
@ -2787,29 +2837,8 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
result.d->has_alpha_clut = d->has_alpha_clut;
result.d->devicePixelRatio = d->devicePixelRatio;
if (d->depth == 1)
w = (w+7)/8;
int dxi = horizontal ? -1 : 1;
int dxs = horizontal ? w-1 : 0;
int dyi = vertical ? -1 : 1;
int dys = vertical ? h-1 : 0;
do_mirror(result.d, d, horizontal, vertical);
// 1 bit, 8 bit
if (d->depth == 1 || d->depth == 8)
mirrored_helper_loop<quint8>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
// 16 bit
else if (d->depth == 16)
mirrored_helper_loop<quint16>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
// 24 bit
else if (d->depth == 24)
mirrored_helper_loop<quint24>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
// 32 bit
else if (d->depth == 32)
mirrored_helper_loop<quint32>(w, h, dxi, dxs, dyi, dys, d->data, result.d->data, d->bytes_per_line, result.d->bytes_per_line);
// special handling of 1 bit images for horizontal mirroring
if (horizontal && d->depth == 1)
mirror_horizonal_bitmap(d->width, d->height, dxs, result.d->data, result.d->bytes_per_line, d->format == Format_MonoLSB);
return result;
}
@ -2818,45 +2847,12 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
*/
void QImage::mirrored_inplace(bool horizontal, bool vertical)
{
if (!d)
return;
if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
return;
detach();
int w = d->width;
int h = d->height;
if (d->depth == 1)
w = (w+7)/8;
int dxi = horizontal ? -1 : 1;
int dxs = horizontal ? w-1 : 0;
int dyi = vertical ? -1 : 1;
int dys = vertical ? h-1 : 0;
if (vertical)
h = h/2;
else if (horizontal)
w = w/2;
// 1 bit, 8 bit
if (d->depth == 1 || d->depth == 8)
mirrored_helper_loop_inplace<quint8>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
// 16 bit
else if (d->depth == 16)
mirrored_helper_loop_inplace<quint16>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
// 24 bit
else if (d->depth == 24)
mirrored_helper_loop_inplace<quint24>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
// 32 bit
else if (d->depth == 32)
mirrored_helper_loop_inplace<quint32>(w, h, dxi, dxs, dyi, dys, d->data, d->bytes_per_line);
// special handling of 1 bit images for horizontal mirroring
if (horizontal && d->depth == 1)
mirror_horizonal_bitmap(d->width, d->height, dxs, d->data, d->bytes_per_line, d->format == Format_MonoLSB);
do_mirror(d, d, horizontal, vertical);
}
/*!

View File

@ -1098,6 +1098,7 @@ bool QPixmap::isDetached() const
*/
bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
{
detach();
if (image.isNull() || !data)
*this = QPixmap::fromImage(image, flags);
else

View File

@ -363,10 +363,12 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
}
is_null = (w <= 0 || h <= 0);
image.d->devicePixelRatio = sourceImage.devicePixelRatio();
if (image.d)
image.d->devicePixelRatio = sourceImage.devicePixelRatio();
//ensure the pixmap and the image resulting from toImage() have the same cacheKey();
setSerialNumber(image.cacheKey() >> 32);
setDetachNumber(image.d->detach_no);
if (image.d)
setDetachNumber(image.d->detach_no);
}
QImage* QRasterPlatformPixmap::buffer()

View File

@ -171,6 +171,7 @@ bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
extern void qRegisterGuiVariant();
extern void qRegisterGuiGetInterpolator();
extern void qInitDrawhelperAsm();
extern void qInitImageConversions();
@ -489,6 +490,12 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\li \c{-platformtheme} \e platformTheme, specifies the platform theme.
Overridden by the \c QT_QPA_PLATFORMTHEME environment variable.
\li \c{-plugin} \e plugin, specifies additional plugins to load. The argument
may appear multiple times.
Overridden by the \c QT_QPA_GENERIC_PLUGINS environment variable.
\li \c{-qmljsdebugger=}, activates the QML/JS debugger with a specified port.
The value must be of format \c{port:1234}\e{[,block]}, where
\e block is optional
@ -1281,6 +1288,9 @@ void QGuiApplicationPrivate::init()
// trigger registering of QVariant's GUI types
qRegisterGuiVariant();
// trigger registering of animation interpolators
qRegisterGuiGetInterpolator();
QWindowSystemInterfacePrivate::eventTime.start();
is_app_running = true;

View File

@ -123,7 +123,8 @@ bool QPlatformClipboard::ownsMode(QClipboard::Mode mode) const
void QPlatformClipboard::emitChanged(QClipboard::Mode mode)
{
QGuiApplication::clipboard()->emitChanged(mode);
if (!QGuiApplicationPrivate::is_app_closing) // QTBUG-39317, prevent emission when closing down.
QGuiApplication::clipboard()->emitChanged(mode);
}
QT_END_NAMESPACE

View File

@ -443,9 +443,10 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
samples = qBound(0, int(samples), int(maxSamples));
}
samples = qMax(0, samples);
requestedSamples = samples;
size = sz;
target = texture_target;
// texture dimensions
QT_RESET_GLERROR(); // reset error state
GLuint fbo = 0;
@ -477,6 +478,9 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
valid = checkFramebufferStatus(ctx);
if (valid) {
// Query the actual number of samples. This can be greater than the requested
// value since the typically supported values are 0, 4, 8, ..., and the
// requests are mapped to the next supported value.
funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
}
@ -546,7 +550,10 @@ void QOpenGLFramebufferObjectPrivate::initTexture(GLenum target, GLenum internal
void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment)
{
int samples = format.samples();
// Use the same sample count for all attachments. format.samples() already contains
// the actual number of samples for the color attachment and is not suitable. Use
// requestedSamples instead.
const int samples = requestedSamples;
// free existing attachments
if (depth_buffer_guard) {

View File

@ -131,6 +131,7 @@ public:
GLenum target;
QSize size;
QOpenGLFramebufferObjectFormat format;
int requestedSamples;
uint valid : 1;
QOpenGLFramebufferObject::Attachment fbo_attachment;
QOpenGLExtensions funcs;

View File

@ -283,46 +283,48 @@ static int qt_gl_resolve_features()
QSurfaceFormat format = QOpenGLContext::currentContext()->format();
QOpenGLExtensionMatcher extensions;
// Recognize features by extension name.
if (extensions.match("GL_ARB_multitexture"))
features |= QOpenGLFunctions::Multitexture;
if (extensions.match("GL_ARB_shader_objects"))
features |= QOpenGLFunctions::Shaders;
if (extensions.match("GL_EXT_framebuffer_object") ||
extensions.match("GL_ARB_framebuffer_object"))
features |= QOpenGLFunctions::Framebuffers;
if (extensions.match("GL_EXT_blend_color"))
features |= QOpenGLFunctions::BlendColor;
if (extensions.match("GL_EXT_blend_equation_separate"))
features |= QOpenGLFunctions::BlendEquationSeparate;
if (extensions.match("GL_EXT_blend_func_separate"))
features |= QOpenGLFunctions::BlendFuncSeparate;
if (extensions.match("GL_EXT_blend_subtract"))
features |= QOpenGLFunctions::BlendSubtract;
if (extensions.match("GL_ARB_texture_compression"))
features |= QOpenGLFunctions::CompressedTextures;
if (extensions.match("GL_ARB_multisample"))
features |= QOpenGLFunctions::Multisample;
if (extensions.match("GL_ARB_texture_non_power_of_two"))
features |= QOpenGLFunctions::NPOTTextures |
QOpenGLFunctions::NPOTTextureRepeat;
// assume version 2.0 or higher
features |= QOpenGLFunctions::BlendColor |
QOpenGLFunctions::BlendEquation |
QOpenGLFunctions::Multitexture |
QOpenGLFunctions::CompressedTextures |
QOpenGLFunctions::Multisample |
QOpenGLFunctions::BlendFuncSeparate |
QOpenGLFunctions::Buffers |
QOpenGLFunctions::Shaders |
QOpenGLFunctions::StencilSeparate |
QOpenGLFunctions::BlendEquationSeparate |
QOpenGLFunctions::NPOTTextures |
QOpenGLFunctions::NPOTTextureRepeat;
if (format.majorVersion() >= 3)
features |= QOpenGLFunctions::Framebuffers;
else if (extensions.match("GL_EXT_framebuffer_object") ||
extensions.match("GL_ARB_framebuffer_object"))
features |= QOpenGLFunctions::Framebuffers;
if (format.majorVersion() >= 2) {
features |= QOpenGLFunctions::BlendColor |
QOpenGLFunctions::BlendEquation |
QOpenGLFunctions::BlendSubtract |
QOpenGLFunctions::Multitexture |
QOpenGLFunctions::CompressedTextures |
QOpenGLFunctions::Multisample |
QOpenGLFunctions::BlendFuncSeparate |
QOpenGLFunctions::Buffers |
QOpenGLFunctions::Shaders |
QOpenGLFunctions::StencilSeparate |
QOpenGLFunctions::BlendEquationSeparate |
QOpenGLFunctions::NPOTTextures |
QOpenGLFunctions::NPOTTextureRepeat;
} else {
// Recognize features by extension name.
if (extensions.match("GL_ARB_multitexture"))
features |= QOpenGLFunctions::Multitexture;
if (extensions.match("GL_ARB_shader_objects"))
features |= QOpenGLFunctions::Shaders;
if (extensions.match("GL_EXT_blend_color"))
features |= QOpenGLFunctions::BlendColor;
if (extensions.match("GL_EXT_blend_equation_separate"))
features |= QOpenGLFunctions::BlendEquationSeparate;
if (extensions.match("GL_EXT_blend_subtract"))
features |= QOpenGLFunctions::BlendSubtract;
if (extensions.match("GL_EXT_blend_func_separate"))
features |= QOpenGLFunctions::BlendFuncSeparate;
if (extensions.match("GL_ARB_texture_compression"))
features |= QOpenGLFunctions::CompressedTextures;
if (extensions.match("GL_ARB_multisample"))
features |= QOpenGLFunctions::Multisample;
if (extensions.match("GL_ARB_texture_non_power_of_two"))
features |= QOpenGLFunctions::NPOTTextures |
QOpenGLFunctions::NPOTTextureRepeat;
}
const QPair<int, int> version = format.version();
if (version < qMakePair(3, 0)

View File

@ -1798,71 +1798,6 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
}
fx = v_fx.i[0];
fy = v_fy.i[0];
#elif defined(__ARM_NEON__)
BILINEAR_ROTATE_BOUNDS_PROLOG
const int16x8_t colorMask = vdupq_n_s16(0x00ff);
const int16x8_t invColorMask = vmvnq_s16(colorMask);
const int16x8_t v_256 = vdupq_n_s16(256);
int32x4_t v_fdx = vdupq_n_s32(fdx*4);
int32x4_t v_fdy = vdupq_n_s32(fdy*4);
const uchar *textureData = data->texture.imageData;
const int bytesPerLine = data->texture.bytesPerLine;
union Vect_buffer { int32x4_t vect; quint32 i[4]; };
Vect_buffer v_fx, v_fy;
for (int i = 0; i < 4; i++) {
v_fx.i[i] = fx;
v_fy.i[i] = fy;
fx += fdx;
fy += fdy;
}
const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
while (b < boundedEnd) {
if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
break;
if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
break;
if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
break;
if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
break;
Vect_buffer tl, tr, bl, br;
Vect_buffer v_fx_shifted, v_fy_shifted;
v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16);
for (int i = 0; i < 4; i++) {
const int x1 = v_fx_shifted.i[i];
const int y1 = v_fy_shifted.i[i];
const uchar *sl = textureData + bytesPerLine * y1;
const uint *s1 = (const uint *)sl;
const uint *s2 = (const uint *)(sl + bytesPerLine);
tl.i[i] = s1[x1];
tr.i[i] = s1[x1+1];
bl.i[i] = s2[x1];
br.i[i] = s2[x1+1];
}
int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12);
v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16));
int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
b+=4;
v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
v_fy.vect = vaddq_s32(v_fy.vect, v_fdy);
}
fx = v_fx.i[0];
fy = v_fy.i[0];
#endif
}
@ -6318,6 +6253,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
}
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
const uchar *map,
@ -6326,6 +6262,7 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
{
qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip);
}
#endif
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,

View File

@ -761,7 +761,7 @@ void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
bool((painter()->renderHints() & QPainter::TextAntialiasing)
&& !(painter()->font().styleStrategy() & QFont::NoAntialias)));
painter()->translate(p.x(), p.y());
painter()->fillPath(path, state->pen().brush());
painter()->fillPath(path, painter()->pen().brush());
painter()->restore();
}
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@ -830,6 +830,8 @@ void QPaintEngineEx::drawEllipse(const QRectF &r)
int point_count = 0;
x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
if (point_count == 0)
return;
QVectorPath vp((qreal *) pts, point_count + 1, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
draw(vp);
}

View File

@ -181,9 +181,13 @@ static const HB_FontClass hb_fontClass = {
static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
{
QFontEngine *fe = (QFontEngine *)font;
Q_ASSERT(fe->faceData.get_font_table);
if (!fe->faceData.get_font_table(fe->faceData.user_data, tableTag, buffer, length))
QFontEngine::FaceData *data = (QFontEngine::FaceData *)font;
Q_ASSERT(data);
qt_get_font_table_func_t get_font_table = data->get_font_table;
Q_ASSERT(get_font_table);
if (!get_font_table(data->user_data, tableTag, buffer, length))
return HB_Err_Invalid_Argument;
return HB_Err_Ok;
}
@ -291,8 +295,11 @@ void *QFontEngine::harfbuzzFont() const
#endif
if (!font_) {
HB_Face hbFace = (HB_Face)harfbuzzFace();
if (hbFace->font_for_init != 0)
if (hbFace->font_for_init) {
void *data = hbFace->font_for_init;
q_check_ptr(qHBLoadFace(hbFace));
free(data);
}
HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec));
Q_CHECK_PTR(hbFont);
@ -323,7 +330,12 @@ void *QFontEngine::harfbuzzFace() const
return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
#endif
if (!face_) {
HB_Face hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData));
Q_CHECK_PTR(data);
data->user_data = faceData.user_data;
data->get_font_table = faceData.get_font_table;
HB_Face hbFace = qHBNewFace(data, hb_getSFntTable);
Q_CHECK_PTR(hbFace);
hbFace->isSymbolFont = symbol;
@ -376,8 +388,11 @@ bool QFontEngine::supportsScript(QChar::Script script) const
}
#endif
HB_Face hbFace = (HB_Face)harfbuzzFace();
if (hbFace->font_for_init != 0)
if (hbFace->font_for_init) {
void *data = hbFace->font_for_init;
q_check_ptr(qHBLoadFace(hbFace));
free(data);
}
return hbFace->supported_scripts[script_to_hbscript(script)];
}

View File

@ -295,8 +295,7 @@ int QFontMetrics::descent() const
/*!
Returns the height of the font.
This is always equal to ascent()+descent()+1 (the 1 is for the
base line).
This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/
@ -1159,8 +1158,7 @@ qreal QFontMetricsF::descent() const
/*!
Returns the height of the font.
This is always equal to ascent()+descent()+1 (the 1 is for the
base line).
This is always equal to ascent()+descent().
\sa leading(), lineSpacing()
*/

View File

@ -1219,8 +1219,8 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS
d->init();
}
#else
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent,
QHttpNetworkConnection::ConnectionType connectionType)
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt,
QHttpNetworkConnection::ConnectionType connectionType, QObject *parent)
: QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt , connectionType)), parent)
{
Q_D(QHttpNetworkConnection);

View File

@ -110,8 +110,8 @@ public:
ConnectionType connectionType = ConnectionTypeHTTP);
#else
explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false,
QObject *parent = 0,
ConnectionType connectionType = ConnectionTypeHTTP);
ConnectionType connectionType = ConnectionTypeHTTP,
QObject *parent = 0);
QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80,
bool encrypt = false, QObject *parent = 0,
ConnectionType connectionType = ConnectionTypeHTTP);

View File

@ -338,7 +338,7 @@ void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QStrin
void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
QAuthenticator *authenticator)
{
manager->proxyAuthenticationRequired(proxy, synchronous, authenticator, &reply->lastProxyAuthentication);
manager->proxyAuthenticationRequired(QUrl(), proxy, synchronous, authenticator, &reply->lastProxyAuthentication);
}
#endif

View File

@ -99,13 +99,13 @@ bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString&
bool retValue = false;
SecProtocolType protocolType = kSecProtocolTypeAny;
if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeFTP;
protocolType = kSecProtocolTypeFTPProxy;
} else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
|| scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTP;
protocolType = kSecProtocolTypeHTTPProxy;
} else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
|| scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTPS;
protocolType = kSecProtocolTypeHTTPSProxy;
}
QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
err = SecKeychainFindInternetPassword(NULL,
@ -1392,21 +1392,6 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
}
}
#ifndef QT_NO_NETWORKPROXY
#if defined(Q_OS_MACX)
//now we try to get the username and password from keychain
//if not successful signal will be emitted
QString username;
QString password;
if (getProxyAuth(proxy.hostName(),reply->request().url().scheme(),username,password)) {
authenticator->setUser(username);
authenticator->setPassword(password);
authenticationManager->cacheProxyCredentials(proxy, authenticator);
return;
}
#endif
#endif //QT_NO_NETWORKPROXY
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
if (synchronous)
@ -1419,7 +1404,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
}
#ifndef QT_NO_NETWORKPROXY
void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url,
const QNetworkProxy &proxy,
bool synchronous,
QAuthenticator *authenticator,
QNetworkProxy *lastProxyAuthentication)
@ -1435,6 +1421,26 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkPro
}
}
#if defined(Q_OS_OSX)
//now we try to get the username and password from keychain
//if not successful signal will be emitted
QString username;
QString password;
if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
// only cache the system credentials if they are correct (or if they have changed)
// to not run into an endless loop in case they are wrong
QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
if (!priv->hasFailed || cred.user != username || cred.password != password) {
authenticator->setUser(username);
authenticator->setPassword(password);
authenticationManager->cacheProxyCredentials(proxy, authenticator);
return;
}
}
#else
Q_UNUSED(url);
#endif
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
if (synchronous)

View File

@ -113,7 +113,8 @@ public:
const QAuthenticator *auth = 0);
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy,
void proxyAuthenticationRequired(const QUrl &url,
const QNetworkProxy &proxy,
bool synchronous,
QAuthenticator *authenticator,
QNetworkProxy *lastProxyAuthentication);

View File

@ -975,6 +975,9 @@ void QNetworkReplyHttpImplPrivate::initCacheSaveDevice()
cacheSaveDevice = managerPrivate->networkCache->prepare(metaData);
if (cacheSaveDevice)
q->connect(cacheSaveDevice, SIGNAL(aboutToClose()), SLOT(_q_cacheSaveDeviceAboutToClose()));
if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) {
if (cacheSaveDevice && !cacheSaveDevice->isOpen())
qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- "
@ -1220,7 +1223,7 @@ void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetwork
void QNetworkReplyHttpImplPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
QAuthenticator *authenticator)
{
managerPrivate->proxyAuthenticationRequired(proxy, synchronous, authenticator, &lastProxyAuthentication);
managerPrivate->proxyAuthenticationRequired(request.url(), proxy, synchronous, authenticator, &lastProxyAuthentication);
}
#endif
@ -1708,6 +1711,13 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingDataFinished()
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
void QNetworkReplyHttpImplPrivate::_q_cacheSaveDeviceAboutToClose()
{
// do not keep a dangling pointer to the device around (device
// is closing because e.g. QAbstractNetworkCache::remove() was called).
cacheSaveDevice = 0;
}
void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
{
Q_Q(QNetworkReplyHttpImpl);

View File

@ -130,6 +130,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
#ifndef QT_NO_SSL
@ -179,6 +180,8 @@ public:
void _q_bufferOutgoingData();
void _q_bufferOutgoingDataFinished();
void _q_cacheSaveDeviceAboutToClose();
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();

View File

@ -90,6 +90,7 @@ public:
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value);
void setRawHeader(const QByteArray &headerName, const QByteArray &value);
void setError(QNetworkReply::NetworkError errorCode, const QString &errorString);
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
};
@interface QtNSURLConnectionDelegate : NSObject
@ -140,6 +141,7 @@ QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivat
void QNetworkReplyNSURLConnectionImplPrivate::setFinished()
{
q_func()->setFinished(true);
QMetaObject::invokeMethod(q_func(), "finished", Qt::QueuedConnection);
}
void QNetworkReplyNSURLConnectionImplPrivate::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
@ -157,6 +159,11 @@ void QNetworkReplyNSURLConnectionImplPrivate::setError(QNetworkReply::NetworkErr
q_func()->setError(errorCode, errorString);
}
void QNetworkReplyNSURLConnectionImplPrivate::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
{
q_func()->setAttribute(code, value);
}
void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
{
Q_D(QNetworkReplyNSURLConnectionImpl);
@ -269,6 +276,9 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
NSString *value = [headers objectForKey:key];
replyprivate->setRawHeader(QString::fromNSString(key).toUtf8(), QString::fromNSString(value).toUtf8());
}
int code = [httpResponse statusCode];
replyprivate->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, code);
} else {
if ([aResponse expectedContentLength] != NSURLResponseUnknownLength)
replyprivate->setHeader(QNetworkRequest::ContentLengthHeader, [aResponse expectedContentLength]);
@ -317,8 +327,7 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
Q_UNUSED(connection)
replyprivate->setFinished();
QMetaObject::invokeMethod(replyprivate->q_func(), "finished", Qt::QueuedConnection);
replyprivate->setFinished();
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection

View File

@ -160,9 +160,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
Q_CHECK_PTR(ns);
state._u._ext.nsaddrs[0] = ns;
}
#ifndef __UCLIBC__
// Set nsmap[] to indicate that nsaddrs[0] is an IPv6 address
// See: https://sourceware.org/ml/libc-hacker/2002-05/msg00035.html
state._u._ext.nsmap[0] = MAXNS + 1;
#endif
state._u._ext.nscount6 = 1;
ns->sin6_family = AF_INET6;
ns->sin6_port = htons(53);
@ -370,11 +372,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
}
#else
void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply)
void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply)
{
Q_UNUSED(requestType)
Q_UNUSED(requestName)
Q_UNUSED(nameserver)
reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("Resolver library can't be loaded: No runtime library loading support");
return;

View File

@ -85,7 +85,7 @@ public:
explicit QHostAddress(quint32 ip4Addr);
explicit QHostAddress(quint8 *ip6Addr);
explicit QHostAddress(const Q_IPV6ADDR &ip6Addr);
explicit QHostAddress(const sockaddr *sockaddr);
explicit QHostAddress(const sockaddr *address);
explicit QHostAddress(const QString &address);
QHostAddress(const QHostAddress &copy);
QHostAddress(SpecialAddress address);
@ -97,7 +97,7 @@ public:
void setAddress(quint32 ip4Addr);
void setAddress(quint8 *ip6Addr);
void setAddress(const Q_IPV6ADDR &ip6Addr);
void setAddress(const sockaddr *sockaddr);
void setAddress(const sockaddr *address);
bool setAddress(const QString &address);
QAbstractSocket::NetworkLayerProtocol protocol() const;

View File

@ -53,6 +53,7 @@
// We mean it.
//
#include <QtCore/qglobal.h>
#include <winsock2.h>
#include <qt_windows.h>
#include <time.h>

View File

@ -202,7 +202,17 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize)
if (!maxSize)
return 0;
return d->pipeReader->read(data, maxSize);
qint64 ret = d->pipeReader->read(data, maxSize);
// QWindowsPipeReader::read() returns error codes that don't match what we need
switch (ret) {
case 0: // EOF -> transform to error
return -1;
case -2: // EWOULDBLOCK -> no error, just no bytes
return 0;
default:
return ret;
}
}
qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)

View File

@ -246,8 +246,11 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
d->tcp = handler->pendingTcpSockets.take(socketDescriptor);
d->socketType = QAbstractSocket::TcpSocket;
if (!d->tcp || !d->fetchConnectionParameters())
if (!d->tcp || !d->fetchConnectionParameters()) {
d->setError(QAbstractSocket::UnsupportedSocketOperationError,
d->InvalidSocketErrorString);
return false;
}
d->socketState = socketState;
return true;
@ -475,9 +478,9 @@ void QNativeSocketEngine::close()
Q_D(QNativeSocketEngine);
if (d->socketDescriptor != -1) {
ComPtr<IClosable> socket;
if (d->socketType == QAbstractSocket::TcpSocket)
if (d->socketType == QAbstractSocket::TcpSocket && d->tcp)
d->tcp.As(&socket);
else if (d->socketType == QAbstractSocket::UdpSocket)
else if (d->socketType == QAbstractSocket::UdpSocket && d->udp)
d->udp.As(&socket);
if (socket) {

View File

@ -153,6 +153,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/)
return JNI_VERSION_1_4;
}
QT_BEGIN_NAMESPACE
QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData()
{
QList<QByteArray> certificateData;
@ -177,3 +179,5 @@ QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData()
return certificateData;
}
QT_END_NAMESPACE

View File

@ -84,32 +84,22 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay
int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size
int visualAlphaSize = chosenVisualInfo->depth == 32 ? 8 : 0;
bool visualMatchesConfig = false;
if ( visualRedSize == configRedSize &&
visualGreenSize == configGreenSize &&
visualBlueSize == configBlueSize )
{
// We need XRender to check the alpha channel size of the visual. If we don't have
// the alpha size, we don't check it against the EGL config's alpha size.
if (visualAlphaSize >= 0)
visualMatchesConfig = visualAlphaSize == configAlphaSize;
else
visualMatchesConfig = true;
}
const bool visualMatchesConfig = visualRedSize == configRedSize
&& visualGreenSize == configGreenSize
&& visualBlueSize == configBlueSize
&& visualAlphaSize == configAlphaSize;
// In some cases EGL tends to suggest a 24-bit visual for 8888
// configs. In such a case we have to fall back to XGetVisualInfo.
if (!visualMatchesConfig) {
if (visualAlphaSize >= 0) {
qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable",
(int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize,
configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize);
} else {
qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable",
(int)visualId, visualRedSize, visualGreenSize, visualBlueSize,
configId, configRedSize, configGreenSize, configBlueSize);
}
visualId = 0;
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
qWarning("Warning: EGL suggested using X Visual ID %d (%d %d %d depth %d) for EGL config %d (%d %d %d %d), but this is incompatible",
(int)visualId, visualRedSize, visualGreenSize, visualBlueSize, chosenVisualInfo->depth,
configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
#endif
}
} else {
qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
@ -133,8 +123,7 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay
return visualId;
}
// Finally, try to
// use XGetVisualInfo and only use the bit depths to match on:
// Finally, try to use XGetVisualInfo and only use the bit depths to match on:
if (!visualId) {
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));

View File

@ -517,6 +517,8 @@ void ICOReader::read16_24_32BMP(QImage & image)
}
}
static const char icoOrigDepthKey[] = "_q_icoOrigDepth";
QImage ICOReader::iconAt(int index)
{
QImage img;
@ -535,7 +537,9 @@ QImage ICOReader::iconAt(int index)
if (isPngImage) {
iod->seek(iconEntry.dwImageOffset);
return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png");
QImage image = QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png");
image.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount));
return image;
}
BMP_INFOHDR header;
@ -598,6 +602,7 @@ QImage ICOReader::iconAt(int index)
}
}
}
img.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount));
}
}
}

View File

@ -111,21 +111,17 @@ void TableGenerator::findComposeFile()
}
// check for the system provided compose files
if (!found && cleanState()) {
QByteArray loc = locale().toUpper().toUtf8();
QString table = readLocaleMappings(loc);
if (table.isEmpty())
table = readLocaleMappings(readLocaleAliases(loc));
QString table = composeTableForLocale();
if (cleanState()) {
if (table.isEmpty())
// no table mappings for the system's locale in the compose.dir
m_state = UnsupportedLocale;
else
found = processFile(systemComposeDir() + QLatin1String("/") + table);
found = processFile(systemComposeDir() + QLatin1Char('/') + table);
#ifdef DEBUG_GENERATOR
if (found)
qDebug() << "Using Compose file from: " <<
systemComposeDir() + QLatin1String("/") + table;
systemComposeDir() + QLatin1Char('/') + table;
#endif
}
}
@ -137,6 +133,15 @@ void TableGenerator::findComposeFile()
m_state = MissingComposeFile;
}
QString TableGenerator::composeTableForLocale()
{
QByteArray loc = locale().toUpper().toUtf8();
QString table = readLocaleMappings(loc);
if (table.isEmpty())
table = readLocaleMappings(readLocaleAliases(loc));
return table;
}
bool TableGenerator::findSystemComposeDir()
{
bool found = false;
@ -311,7 +316,7 @@ void TableGenerator::parseIncludeInstruction(QString line)
// expand substitutions if present
line.replace(QLatin1String("%H"), QString(qgetenv("HOME")));
line.replace(QLatin1String("%L"), locale());
line.replace(QLatin1String("%L"), systemComposeDir() + QLatin1Char('/') + composeTableForLocale());
line.replace(QLatin1String("%S"), systemComposeDir());
processFile(line);

View File

@ -118,13 +118,14 @@ protected:
void findComposeFile();
bool findSystemComposeDir();
QString systemComposeDir();
QString composeTableForLocale();
ushort keysymToUtf8(quint32 sym);
QString readLocaleMappings(const QByteArray &locale);
QByteArray readLocaleAliases(const QByteArray &locale);
void initPossibleLocations();
bool cleanState() const { return ((m_state & NoErrors) == NoErrors); }
bool cleanState() const { return m_state == NoErrors; }
QString locale() const;
private:

View File

@ -49,6 +49,7 @@
#include "qrect.h"
#include "QtGui/qaccessible.h"
#include <QtCore/qmath.h>
#include <QtCore/private/qjnihelpers_p.h>
#include "qdebug.h"
@ -56,6 +57,8 @@ static const char m_qtTag[] = "Qt A11Y";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
QT_BEGIN_NAMESPACE
namespace QtAndroidAccessibility
{
static jmethodID m_addActionMethodID = 0;
@ -227,7 +230,7 @@ if (!clazz) { \
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
if (QAccessibleTextInterface *textIface = iface->textInterface()) {
if (textIface->selectionCount() > 0) {
if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) {
int startSelection;
int endSelection;
textIface->selection(0, &startSelection, &endSelection);
@ -286,12 +289,15 @@ if (!clazz) { \
bool registerNatives(JNIEnv *env)
{
if (QtAndroidPrivate::androidSdkVersion() < 16)
return true; // We need API level 16 or higher
jclass clazz;
FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/accessibility/QtNativeAccessibility");
jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz));
if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
__android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
__android_log_print(ANDROID_LOG_FATAL,"Qt A11y", "RegisterNatives failed");
return false;
}
@ -305,9 +311,14 @@ if (!clazz) { \
GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setScrollableMethodID, nodeInfoClass, "setScrollable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V");
if (QtAndroidPrivate::androidSdkVersion() >= 18) {
GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
}
return true;
}
}
QT_END_NAMESPACE

View File

@ -42,10 +42,15 @@
#ifndef ANDROIDJNIACCESSIBILITY_H
#define ANDROIDJNIACCESSIBILITY_H
#include <jni.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
namespace QtAndroidAccessibility
{
bool registerNatives(JNIEnv *env);
}
QT_END_NAMESPACE
#endif // ANDROIDJNIINPUT_H

View File

@ -42,6 +42,8 @@
#include "androidjniclipboard.h"
#include "androidjnimain.h"
QT_BEGIN_NAMESPACE
using namespace QtAndroid;
namespace QtAndroidClipboard
{
@ -118,3 +120,5 @@ namespace QtAndroidClipboard
return true;
}
}
QT_END_NAMESPACE

View File

@ -45,6 +45,8 @@
#include <jni.h>
#include <QString>
QT_BEGIN_NAMESPACE
class QAndroidPlatformClipboard;
namespace QtAndroidClipboard
{
@ -58,4 +60,6 @@ namespace QtAndroidClipboard
bool registerNatives(JNIEnv *env);
}
QT_END_NAMESPACE
#endif // ANDROIDJNICLIPBOARD_H

View File

@ -49,6 +49,8 @@
#include <QDebug>
QT_BEGIN_NAMESPACE
using namespace QtAndroid;
namespace QtAndroidInput
@ -758,3 +760,5 @@ namespace QtAndroidInput
return true;
}
}
QT_END_NAMESPACE

View File

@ -42,6 +42,9 @@
#ifndef ANDROIDJNIINPUT_H
#define ANDROIDJNIINPUT_H
#include <jni.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
namespace QtAndroidInput
{
@ -56,4 +59,6 @@ namespace QtAndroidInput
bool registerNatives(JNIEnv *env);
}
QT_END_NAMESPACE
#endif // ANDROIDJNIINPUT_H

View File

@ -76,6 +76,8 @@
Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
QT_BEGIN_NAMESPACE
static JavaVM *m_javaVM = NULL;
static jclass m_applicationClass = NULL;
static jobject m_classLoaderObject = NULL;
@ -423,6 +425,7 @@ namespace QtAndroid
m_destroySurfaceMethodID,
surfaceId);
}
} // namespace QtAndroid
@ -548,7 +551,7 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
}
static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
jint /*widthPixels*/, jint /*heightPixels*/,
jint widthPixels, jint heightPixels,
jint desktopWidthPixels, jint desktopHeightPixels,
jdouble xdpi, jdouble ydpi, jdouble scaledDensity)
{
@ -557,13 +560,17 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
m_scaledDensity = scaledDensity;
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,desktopHeightPixels,
qRound(double(desktopWidthPixels) / xdpi * 25.4),
qRound(double(desktopHeightPixels) / ydpi * 25.4));
QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,
desktopHeightPixels,
qRound(double(desktopWidthPixels) / xdpi * 25.4),
qRound(double(desktopHeightPixels) / ydpi * 25.4),
widthPixels,
heightPixels);
} else {
m_androidPlatformIntegration->setDisplayMetrics(qRound(double(desktopWidthPixels) / xdpi * 25.4),
qRound(double(desktopHeightPixels) / ydpi * 25.4));
m_androidPlatformIntegration->setDesktopSize(desktopWidthPixels, desktopHeightPixels);
m_androidPlatformIntegration->setScreenSize(widthPixels, heightPixels);
}
}
@ -743,17 +750,11 @@ static int registerNatives(JNIEnv *env)
return JNI_TRUE;
}
jint androidApiLevel(JNIEnv *env)
{
jclass clazz;
FIND_AND_CHECK_CLASS("android/os/Build$VERSION");
jfieldID fieldId;
GET_AND_CHECK_STATIC_FIELD(fieldId, clazz, "SDK_INT", "I");
return env->GetStaticIntField(clazz, fieldId);
}
QT_END_NAMESPACE
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
{
QT_USE_NAMESPACE
typedef union {
JNIEnv *nativeEnvironment;
void *venv;
@ -774,17 +775,12 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives(env)
|| !QtAndroidClipboard::registerNatives(env)
|| !QtAndroidMenu::registerNatives(env)
|| !QtAndroidAccessibility::registerNatives(env)
|| !QtAndroidDialogHelpers::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
jint apiLevel = androidApiLevel(env);
if (apiLevel >= 16 && !QtAndroidAccessibility::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt A11y", "registerNatives failed");
return -1;
}
m_javaVM = vm;
return JNI_VERSION_1_4;
}

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