Merge dev into 5.6

Change-Id: I061f2513ef58f696e75b11928d89aaaf059659a3
This commit is contained in:
Oswald Buddenhagen 2015-08-17 19:55:41 +02:00
commit 5a039bf53e
95 changed files with 2410 additions and 1389 deletions

3
configure vendored
View File

@ -3636,9 +3636,6 @@ if [ -z "$QT_INSTALL_PREFIX" ]; then
else
QT_INSTALL_PREFIX="/usr/local/Qt-${QT_VERSION}" # the default install prefix is /usr/local/Qt-$QT_VERSION
fi
HAVE_INSTALL_PATH=false
else
HAVE_INSTALL_PATH=true
fi
QT_INSTALL_PREFIX=`makeabs "$QT_INSTALL_PREFIX"`

View File

@ -196,6 +196,7 @@ void MainWindow::createActions()
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
//!
#ifndef QT_NO_CLIPBOARD
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this);
//! [21]
@ -226,6 +227,8 @@ void MainWindow::createActions()
menuBar()->addSeparator();
#endif // !QT_NO_CLIPBOARD
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
@ -237,11 +240,13 @@ void MainWindow::createActions()
//! [22]
//! [23]
#ifndef QT_NO_CLIPBOARD
cutAct->setEnabled(false);
//! [23] //! [24]
copyAct->setEnabled(false);
connect(textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
connect(textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
#endif // !QT_NO_CLIPBOARD
}
//! [24]

View File

@ -224,6 +224,7 @@ void MainWindow::createActions()
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
#ifndef QT_NO_CLIPBOARD
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this);
cutAct->setShortcuts(QKeySequence::Cut);
@ -252,6 +253,7 @@ void MainWindow::createActions()
editToolBar->addAction(pasteAct);
menuBar()->addSeparator();
#endif // !QT_NO_CLIPBOARD
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
@ -260,10 +262,12 @@ void MainWindow::createActions()
QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
#ifndef QT_NO_CLIPBOARD
cutAct->setEnabled(false);
copyAct->setEnabled(false);
connect(textEdit, &QTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
connect(textEdit, &QTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
#endif // !QT_NO_CLIPBOARD
}
void MainWindow::createStatusBar()

1
src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp vendored Normal file → Executable file
View File

@ -203,6 +203,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
if (width == 0 || height == 0)
{
checkForOutOfDateSwapChain();
return egl::Error(EGL_SUCCESS);
}

View File

@ -154,14 +154,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
const int textureLength = std::max(backbufferWidth, backbufferHeight);
offscreenTextureDesc.Width = textureLength;
offscreenTextureDesc.Height = textureLength;
#else
offscreenTextureDesc.Width = backbufferWidth;
offscreenTextureDesc.Height = backbufferHeight;
#endif
offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
offscreenTextureDesc.MipLevels = 1;
offscreenTextureDesc.ArraySize = 1;
@ -241,14 +235,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
if (mDepthBufferFormat != GL_NONE)
{
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
const int textureLength = std::max(backbufferWidth, backbufferHeight);
depthStencilTextureDesc.Width = textureLength;
depthStencilTextureDesc.Height = textureLength;
#else
depthStencilTextureDesc.Width = backbufferWidth;
depthStencilTextureDesc.Height = backbufferHeight;
#endif
depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
depthStencilTextureDesc.MipLevels = 1;
depthStencilTextureDesc.ArraySize = 1;
@ -349,7 +337,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
return EGL_SUCCESS;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
// Can only call resize if we have already created our swap buffer and resources
ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
@ -392,12 +379,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
}
return resetOffscreenTexture(backbufferWidth, backbufferHeight);
#else
// Do nothing on Windows Phone apart from updating the internal buffer/width height
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return EGL_SUCCESS;
#endif
}
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
@ -552,27 +533,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
// Create a quad in homogeneous coordinates
float x1 = -1.0f;
float y1 = -1.0f;
float x2 = 1.0f;
float y2 = 1.0f;
const float dim = std::max(mWidth, mHeight);
float u1 = 0;
float v1 = 0;
float u2 = float(width) / dim;
float v2 = float(height) / dim;
const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
const bool rotateL = flags == NativeWindow::RotateLeft;
const bool rotateR = flags == NativeWindow::RotateRight;
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
#else
// Create a quad in homogeneous coordinates
float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
@ -588,7 +548,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
#endif
deviceContext->Unmap(mQuadVB, 0);
@ -618,13 +577,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
viewport.Width = (rotateL || rotateR) ? height : width;
viewport.Height = (rotateL || rotateR) ? width : height;
#else
viewport.Width = mWidth;
viewport.Height = mHeight;
#endif
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport);

View File

@ -191,25 +191,4 @@ HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWind
return result;
}
static float GetLogicalDpi()
{
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
float dpi = 96.0f;
if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
{
if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
{
return dpi;
}
}
return dpi;
}
long ConvertDipsToPixels(float dips)
{
static const float dipsPerInch = 96.0f;
return lround((dips * GetLogicalDpi() / dipsPerInch));
}
}

View File

@ -19,7 +19,6 @@ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CD
namespace rx
{
long ConvertDipsToPixels(float dips);
class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
{
@ -64,8 +63,7 @@ class CoreWindowSizeChangedHandler :
ABI::Windows::Foundation::Size windowSize;
if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
{
SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
host->setNewClientSize(windowSizeInPixels);
host->setNewClientSize(windowSize);
}
}

View File

@ -288,4 +288,25 @@ HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Coll
return result;
}
static float GetLogicalDpi()
{
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
float dpi = 96.0f;
if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
{
if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
{
return dpi;
}
}
return dpi;
}
long ConvertDipsToPixels(float dips)
{
static const float dipsPerInch = 96.0f;
return lround((dips * GetLogicalDpi() / dipsPerInch));
}
}

View File

@ -26,6 +26,8 @@ using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
long ConvertDipsToPixels(float dips);
class InspectableNativeWindow
{
public:
@ -45,7 +47,7 @@ class InspectableNativeWindow
virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
virtual bool registerForSizeChangeEvents() = 0;
virtual void unregisterForSizeChangeEvents() = 0;
virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; }
virtual HRESULT scaleSwapChain(const Size& newSize) { return S_OK; }
bool getClientRect(RECT *rect)
{
@ -59,11 +61,11 @@ class InspectableNativeWindow
return true;
}
void setNewClientSize(const SIZE &newSize)
void setNewClientSize(const Size &newSize)
{
if (mSupportsSwapChainResize && !mRequiresSwapChainScaling)
if (mSupportsSwapChainResize)
{
mNewClientRect = { 0, 0, newSize.cx, newSize.cy };
mNewClientRect = { 0, 0, ConvertDipsToPixels(newSize.Width), ConvertDipsToPixels(newSize.Height) };
mClientRectChanged = true;
}

View File

@ -66,7 +66,7 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
}
else
{
result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect);
result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect, &mRequiresSwapChainScaling);
}
}
@ -139,7 +139,6 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
ComPtr<IDXGISwapChain1> newSwapChain;
ComPtr<ISwapChainPanelNative> swapChainPanelNative;
RECT currentPanelSize = {};
HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
@ -167,13 +166,13 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
// first reading the current size of the swapchain panel, then scaling
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize);
}
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
result = mSwapChainPanel.As(&uiElement);
ASSERT(SUCCEEDED(result));
// Scale the swapchain to fit inside the contents of the panel.
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom };
Size currentSize;
result = uiElement->get_RenderSize(&currentSize);
ASSERT(SUCCEEDED(result));
result = scaleSwapChain(currentSize);
}
@ -190,9 +189,9 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
return result;
}
HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &newSize)
{
ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom };
ABI::Windows::Foundation::Size renderScale = { newSize.Width / mNewClientRect.right, newSize.Height / mNewClientRect.bottom };
// Setup a scale matrix for the swap chain
DXGI_MATRIX_3X2_F scaleMatrix = {};
scaleMatrix._11 = renderScale.Width;
@ -208,7 +207,7 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
return result;
}
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize)
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize, bool *scalingActive)
{
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
ABI::Windows::Foundation::Size renderSize = { 0, 0 };
@ -220,7 +219,14 @@ HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISw
if (SUCCEEDED(result))
{
*windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) };
long width = ConvertDipsToPixels(renderSize.Width);
long height = ConvertDipsToPixels(renderSize.Height);
*windowSize = { 0, 0, width, height };
if (scalingActive)
{
*scalingActive = width != renderSize.Width || height != renderSize.Height;
}
}
return result;

View File

@ -22,7 +22,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
HRESULT scaleSwapChain(const SIZE &newSize);
HRESULT scaleSwapChain(const Size &newSize) override;
private:
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
@ -62,8 +62,7 @@ class SwapChainPanelSizeChangedHandler :
HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
if (SUCCEEDED(result))
{
SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
host->setNewClientSize(windowSize);
host->setNewClientSize(newSize);
}
}
@ -74,6 +73,6 @@ class SwapChainPanelSizeChangedHandler :
std::weak_ptr<InspectableNativeWindow> mHost;
};
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize, bool *scalingActive = nullptr);
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_

View File

@ -54,6 +54,9 @@
# define HAVE_PIPE2 1
# endif
#endif
#if defined(__FreeBSD__) && __FreeBSD__ >= 9
# include <sys/procdesc.h>
#endif
#if _POSIX_VERSION-0 >= 200809L || _XOPEN_VERSION-0 >= 500
# define HAVE_WAITID 1
@ -506,6 +509,46 @@ static int create_pipe(int filedes[], int flags)
return ret;
}
#if defined(FORKFD_NO_SPAWNFD) && defined(__FreeBSD__) && __FreeBSD__ >= 9
# if __FreeBSD__ == 9
/* PROCDESC is an optional feature in the kernel and wasn't enabled
* by default on FreeBSD 9. So we need to check for it at runtime. */
static ffd_atomic_int system_has_forkfd = FFD_ATOMIC_INIT(1);
# else
/* On FreeBSD 10, PROCDESC was enabled by default. On v11, it's not an option
* anymore and can't be disabled. */
static const int system_has_forkfd = 1;
# endif
static int system_forkfd(int flags, pid_t *ppid)
{
int ret;
pid_t pid;
pid = pdfork(&ret, PD_DAEMON);
if (__builtin_expect(pid == -1, 0)) {
# if __FreeBSD__ == 9
if (errno == ENOSYS) {
/* PROCDESC wasn't compiled into the kernel: don't try it again. */
ffd_atomic_store(&system_has_forkfd, 0, FFD_ATOMIC_RELAXED);
}
# endif
return -1;
}
if (pid == 0) {
/* child process */
return FFD_CHILD_PROCESS;
}
/* parent process */
if (flags & FFD_CLOEXEC)
fcntl(ret, F_SETFD, FD_CLOEXEC);
if (flags & FFD_NONBLOCK)
fcntl(ret, F_SETFL, fcntl(ret, F_GETFL) | O_NONBLOCK);
if (ppid)
*ppid = pid;
return ret;
}
#else
static const int system_has_forkfd = 0;
static int system_forkfd(int flags, pid_t *ppid)
{
@ -513,6 +556,7 @@ static int system_forkfd(int flags, pid_t *ppid)
(void)ppid;
return -1;
}
#endif
#ifndef FORKFD_NO_FORKFD
/**
@ -748,6 +792,26 @@ int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage)
struct pipe_payload payload;
int ret;
if (system_has_forkfd) {
#if defined(__FreeBSD__) && __FreeBSD__ >= 9
pid_t pid;
int status;
int options = WEXITED;
ret = pdgetpid(ffd, &pid);
if (ret == -1)
return ret;
ret = fcntl(ffd, F_GETFL);
if (ret == -1)
return ret;
options |= (ret & O_NONBLOCK) ? WNOHANG : 0;
ret = wait4(pid, &status, options, rusage);
if (ret != -1 && info)
convertStatusToForkfdInfo(status, info);
return ret == -1 ? -1 : 0;
#endif
}
ret = read(ffd, &payload, sizeof(payload));
if (ret == -1)
return ret; /* pass errno, probably EINTR, EBADF or EWOULDBLOCK */

View File

@ -203,6 +203,16 @@ public class QtActivityDelegate
private final int ImhUrlCharactersOnly = 0x400000;
private final int ImhLatinOnly = 0x800000;
// enter key type - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
private final int EnterKeyDefault = 0;
private final int EnterKeyReturn = 1;
private final int EnterKeyDone = 2;
private final int EnterKeyGo = 3;
private final int EnterKeySend = 4;
private final int EnterKeySearch = 5;
private final int EnterKeyNext = 6;
private final int EnterKeyPrevious = 7;
// application state
private final int ApplicationSuspended = 0x0;
private final int ApplicationHidden = 0x1;
@ -239,7 +249,7 @@ public class QtActivityDelegate
}, 5);
}
public void showSoftwareKeyboard(int x, int y, int width, int height, int inputHints)
public void showSoftwareKeyboard(int x, int y, int width, int height, int inputHints, int enterKeyType)
{
if (m_imm == null)
return;
@ -252,7 +262,31 @@ public class QtActivityDelegate
m_activity.getWindow().setSoftInputMode(m_softInputMode);
int initialCapsMode = 0;
int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
switch (enterKeyType) {
case EnterKeyReturn:
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
break;
case EnterKeyGo:
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
break;
case EnterKeySend:
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
break;
case EnterKeySearch:
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
break;
case EnterKeyNext:
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
break;
case EnterKeyPrevious:
if (Build.VERSION.SDK_INT > 10)
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
break;
}
int inputType = android.text.InputType.TYPE_CLASS_TEXT;
if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
@ -278,6 +312,8 @@ public class QtActivityDelegate
if ((inputHints & (ImhEmailCharactersOnly | ImhUrlCharactersOnly)) != 0) {
if ((inputHints & ImhUrlCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI;
if (enterKeyType == 0) // not explicitly overridden
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
} else if ((inputHints & ImhEmailCharactersOnly) != 0) {
inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
@ -305,7 +341,7 @@ public class QtActivityDelegate
}
}
if ((inputHints & ImhMultiLine) != 0)
if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
m_editText.setInitialCapsMode(initialCapsMode);

View File

@ -389,12 +389,13 @@ public class QtNative
final int y,
final int width,
final int height,
final int inputHints )
final int inputHints,
final int enterKeyType)
{
runAction(new Runnable() {
@Override
public void run() {
m_activityDelegate.showSoftwareKeyboard(x, y, width, height, inputHints);
m_activityDelegate.showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
}
});
}

View File

@ -0,0 +1,361 @@
From 333bb863e5c3e04fcc513e4750208fa3742be7a1 Mon Sep 17 00:00:00 2001
From: Andrew Knight <andrew.knight@intopalo.com>
Date: Sat, 8 Aug 2015 21:42:03 +0300
Subject: [PATCH 2/4] ANGLE: Use pixel sizes in the XAML swap chain
This is necessary for Qt applications, as they render to GL in physical
pixels. This is consistent with the CoreWindow swap chain behavior.
This includes a partial revert of "ANGLE: Improve Windows Phone Support"
as the modifications to SwapChain11 are incompatible with the XAML swap
chain.
This change only affects Windows Runtime targets.
Change-Id: I401ae81028a9dfdb9da37f51c60844467c476f76
---
.../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 46 ----------------------
.../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 21 ----------
.../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 4 +-
.../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 21 ++++++++++
.../d3d/d3d11/winrt/InspectableNativeWindow.h | 10 +++--
.../d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 30 ++++++++------
.../d3d/d3d11/winrt/SwapChainPanelNativeWindow.h | 7 ++--
7 files changed, 49 insertions(+), 90 deletions(-)
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index dc539cf..0af2cf1 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -154,14 +154,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- const int textureLength = std::max(backbufferWidth, backbufferHeight);
- offscreenTextureDesc.Width = textureLength;
- offscreenTextureDesc.Height = textureLength;
-#else
offscreenTextureDesc.Width = backbufferWidth;
offscreenTextureDesc.Height = backbufferHeight;
-#endif
offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
offscreenTextureDesc.MipLevels = 1;
offscreenTextureDesc.ArraySize = 1;
@@ -241,14 +235,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
if (mDepthBufferFormat != GL_NONE)
{
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- const int textureLength = std::max(backbufferWidth, backbufferHeight);
- depthStencilTextureDesc.Width = textureLength;
- depthStencilTextureDesc.Height = textureLength;
-#else
depthStencilTextureDesc.Width = backbufferWidth;
depthStencilTextureDesc.Height = backbufferHeight;
-#endif
depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
depthStencilTextureDesc.MipLevels = 1;
depthStencilTextureDesc.ArraySize = 1;
@@ -349,7 +337,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
return EGL_SUCCESS;
}
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
// Can only call resize if we have already created our swap buffer and resources
ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
@@ -392,12 +379,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
}
return resetOffscreenTexture(backbufferWidth, backbufferHeight);
-#else
- // Do nothing on Windows Phone apart from updating the internal buffer/width height
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
- return EGL_SUCCESS;
-#endif
}
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
@@ -552,27 +533,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- // Create a quad in homogeneous coordinates
- float x1 = -1.0f;
- float y1 = -1.0f;
- float x2 = 1.0f;
- float y2 = 1.0f;
-
- const float dim = std::max(mWidth, mHeight);
- float u1 = 0;
- float v1 = 0;
- float u2 = float(width) / dim;
- float v2 = float(height) / dim;
-
- const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
- const bool rotateL = flags == NativeWindow::RotateLeft;
- const bool rotateR = flags == NativeWindow::RotateRight;
- d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
- d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
-#else
// Create a quad in homogeneous coordinates
float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
@@ -588,7 +548,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
-#endif
deviceContext->Unmap(mQuadVB, 0);
@@ -618,13 +577,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- viewport.Width = (rotateL || rotateR) ? height : width;
- viewport.Height = (rotateL || rotateR) ? width : height;
-#else
viewport.Width = mWidth;
viewport.Height = mHeight;
-#endif
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport);
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
index fa9a69c..f45a077 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -191,25 +191,4 @@ HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWind
return result;
}
-
-static float GetLogicalDpi()
-{
- ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
- float dpi = 96.0f;
-
- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
- {
- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
- {
- return dpi;
- }
- }
- return dpi;
-}
-
-long ConvertDipsToPixels(float dips)
-{
- static const float dipsPerInch = 96.0f;
- return lround((dips * GetLogicalDpi() / dipsPerInch));
-}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
index 59df9d5..87cdfe6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
@@ -19,7 +19,6 @@ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CD
namespace rx
{
-long ConvertDipsToPixels(float dips);
class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
{
@@ -64,8 +63,7 @@ class CoreWindowSizeChangedHandler :
ABI::Windows::Foundation::Size windowSize;
if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
{
- SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
- host->setNewClientSize(windowSizeInPixels);
+ host->setNewClientSize(windowSize);
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
index 2bf48c5..e83f479 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -288,4 +288,25 @@ HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Coll
return result;
}
+
+static float GetLogicalDpi()
+{
+ ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+ float dpi = 96.0f;
+
+ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+ {
+ if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+ {
+ return dpi;
+ }
+ }
+ return dpi;
+}
+
+long ConvertDipsToPixels(float dips)
+{
+ static const float dipsPerInch = 96.0f;
+ return lround((dips * GetLogicalDpi() / dipsPerInch));
+}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
index 575bdf8..f053407 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
@@ -26,6 +26,8 @@ using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
+long ConvertDipsToPixels(float dips);
+
class InspectableNativeWindow
{
public:
@@ -45,7 +47,7 @@ class InspectableNativeWindow
virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
virtual bool registerForSizeChangeEvents() = 0;
virtual void unregisterForSizeChangeEvents() = 0;
- virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; }
+ virtual HRESULT scaleSwapChain(const Size& newSize) { return S_OK; }
bool getClientRect(RECT *rect)
{
@@ -59,11 +61,11 @@ class InspectableNativeWindow
return true;
}
- void setNewClientSize(const SIZE &newSize)
+ void setNewClientSize(const Size &newSize)
{
- if (mSupportsSwapChainResize && !mRequiresSwapChainScaling)
+ if (mSupportsSwapChainResize)
{
- mNewClientRect = { 0, 0, newSize.cx, newSize.cy };
+ mNewClientRect = { 0, 0, ConvertDipsToPixels(newSize.Width), ConvertDipsToPixels(newSize.Height) };
mClientRectChanged = true;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
index 53899db..0b48b54 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
@@ -66,7 +66,7 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
}
else
{
- result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect);
+ result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect, &mRequiresSwapChainScaling);
}
}
@@ -139,7 +139,6 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
ComPtr<IDXGISwapChain1> newSwapChain;
ComPtr<ISwapChainPanelNative> swapChainPanelNative;
- RECT currentPanelSize = {};
HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
@@ -167,13 +166,13 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
// first reading the current size of the swapchain panel, then scaling
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
- result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize);
- }
+ ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
+ result = mSwapChainPanel.As(&uiElement);
+ ASSERT(SUCCEEDED(result));
- // Scale the swapchain to fit inside the contents of the panel.
- if (SUCCEEDED(result) && mRequiresSwapChainScaling)
- {
- SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom };
+ Size currentSize;
+ result = uiElement->get_RenderSize(&currentSize);
+ ASSERT(SUCCEEDED(result));
result = scaleSwapChain(currentSize);
}
@@ -190,9 +189,9 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa
return result;
}
-HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
+HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &newSize)
{
- ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom };
+ ABI::Windows::Foundation::Size renderScale = { newSize.Width / mNewClientRect.right, newSize.Height / mNewClientRect.bottom };
// Setup a scale matrix for the swap chain
DXGI_MATRIX_3X2_F scaleMatrix = {};
scaleMatrix._11 = renderScale.Width;
@@ -208,7 +207,7 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
return result;
}
-HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize)
+HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize, bool *scalingActive)
{
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
ABI::Windows::Foundation::Size renderSize = { 0, 0 };
@@ -220,7 +219,14 @@ HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISw
if (SUCCEEDED(result))
{
- *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) };
+ long width = ConvertDipsToPixels(renderSize.Width);
+ long height = ConvertDipsToPixels(renderSize.Height);
+ *windowSize = { 0, 0, width, height };
+
+ if (scalingActive)
+ {
+ *scalingActive = width != renderSize.Width || height != renderSize.Height;
+ }
}
return result;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
index caf327d..5debd2f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
@@ -22,7 +22,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
- HRESULT scaleSwapChain(const SIZE &newSize);
+ HRESULT scaleSwapChain(const Size &newSize) override;
private:
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
@@ -62,8 +62,7 @@ class SwapChainPanelSizeChangedHandler :
HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
if (SUCCEEDED(result))
{
- SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
- host->setNewClientSize(windowSize);
+ host->setNewClientSize(newSize);
}
}
@@ -74,6 +73,6 @@ class SwapChainPanelSizeChangedHandler :
std::weak_ptr<InspectableNativeWindow> mHost;
};
-HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
+HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize, bool *scalingActive = nullptr);
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
--
1.9.5.msysgit.1

View File

@ -496,10 +496,13 @@ typedef qptrdiff qintptr;
#ifdef Q_CC_MSVC
# define Q_NEVER_INLINE __declspec(noinline)
# define Q_ALWAYS_INLINE __forceinline
#elif defined(Q_CC_GNU)
# define Q_NEVER_INLINE __attribute__((noinline))
# define Q_ALWAYS_INLINE inline __attribute__((always_inline))
#else
# define Q_NEVER_INLINE
# define Q_ALWAYS_INLINE inline
#endif
//defines the type for the WNDPROC on windows

View File

@ -2206,6 +2206,16 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
mode &= ~QIODevice::ReadOnly; // not open for reading
if (mode == 0)
mode = QIODevice::Unbuffered;
#ifndef Q_OS_WINCE
if ((mode & QIODevice::ReadOnly) == 0) {
if (stdoutChannel.type == QProcessPrivate::Channel::Normal)
q->setStandardOutputFile(q->nullDevice());
if (stderrChannel.type == QProcessPrivate::Channel::Normal
&& processChannelMode != QProcess::MergedChannels)
q->setStandardErrorFile(q->nullDevice());
}
#endif
q->QIODevice::open(mode);
stdinChannel.closed = false;

View File

@ -182,7 +182,7 @@ QT_BEGIN_NAMESPACE
\li "C:/Users/<USER>/AppData/Local/<APPNAME>/cache"
\row \li GenericDataLocation
\li "~/Library/Application Support", "/Library/Application Support"
\li "C:/Users/<USER>/AppData/Local", "C:/ProgramData"
\li "C:/Users/<USER>/AppData/Local", "C:/ProgramData", "<APPDIR>", "<APPDIR>/data"
\row \li RuntimeLocation
\li "~/Library/Application Support"
\li "C:/Users/<USER>"

View File

@ -212,10 +212,8 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
}
dirs.append(result);
#ifndef QT_BOOTSTRAPPED
if (type != GenericDataLocation) {
dirs.append(QCoreApplication::applicationDirPath());
dirs.append(QCoreApplication::applicationDirPath() + QLatin1String("/data"));
}
#endif
}
break;

View File

@ -323,17 +323,9 @@ uint QCoreApplicationPrivate::attribs = (1 << Qt::AA_SynthesizeMouseForUnhandled
struct QCoreApplicationData {
QCoreApplicationData() Q_DECL_NOTHROW {
#ifndef QT_NO_LIBRARY
app_libpaths = 0;
manual_libpaths = 0;
#endif
applicationNameSet = false;
}
~QCoreApplicationData() {
#ifndef QT_NO_LIBRARY
delete app_libpaths;
delete manual_libpaths;
#endif
#ifndef QT_NO_QOBJECT
// cleanup the QAdoptedThread created for the main() thread
if (QCoreApplicationPrivate::theMainThread) {
@ -377,8 +369,8 @@ struct QCoreApplicationData {
bool applicationNameSet; // true if setApplicationName was called
#ifndef QT_NO_LIBRARY
QStringList *app_libpaths;
QStringList *manual_libpaths;
QScopedPointer<QStringList> app_libpaths;
QScopedPointer<QStringList> manual_libpaths;
#endif
};
@ -571,9 +563,9 @@ void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
{
#ifndef QT_NO_LIBRARY
QStringList *app_libpaths = coreappdata()->app_libpaths;
QStringList *app_libpaths = coreappdata()->app_libpaths.data();
if (!app_libpaths)
coreappdata()->app_libpaths = app_libpaths = new QStringList;
coreappdata()->app_libpaths.reset(app_libpaths = new QStringList);
QString app_location = QCoreApplication::applicationFilePath();
app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
#ifdef Q_OS_WINRT
@ -774,16 +766,14 @@ void QCoreApplication::init()
// Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
// into account. If necessary, recompute right away and replay the manual changes on top of the
// new lib paths.
QStringList *appPaths = coreappdata()->app_libpaths;
QStringList *manualPaths = coreappdata()->manual_libpaths;
QStringList *appPaths = coreappdata()->app_libpaths.take();
QStringList *manualPaths = coreappdata()->manual_libpaths.take();
if (appPaths) {
coreappdata()->app_libpaths = 0;
if (manualPaths) {
// Replay the delta. As paths can only be prepended to the front or removed from
// anywhere in the list, we can just linearly scan the lists and find the items that
// have been removed. Once the original list is exhausted we know all the remaining
// items have been added.
coreappdata()->manual_libpaths = 0;
QStringList newPaths(libraryPaths());
for (int i = manualPaths->length(), j = appPaths->length(); i > 0 || j > 0; qt_noop()) {
if (--j < 0) {
@ -796,7 +786,7 @@ void QCoreApplication::init()
}
}
delete manualPaths;
coreappdata()->manual_libpaths = new QStringList(newPaths);
coreappdata()->manual_libpaths.reset(new QStringList(newPaths));
}
delete appPaths;
}
@ -872,10 +862,8 @@ QCoreApplication::~QCoreApplication()
#endif
#ifndef QT_NO_LIBRARY
delete coreappdata()->app_libpaths;
coreappdata()->app_libpaths = 0;
delete coreappdata()->manual_libpaths;
coreappdata()->manual_libpaths = 0;
coreappdata()->app_libpaths.reset();
coreappdata()->manual_libpaths.reset();
#endif
}
@ -2540,7 +2528,8 @@ QStringList QCoreApplication::libraryPaths()
return *(coreappdata()->manual_libpaths);
if (!coreappdata()->app_libpaths) {
QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList;
QStringList *app_libpaths = new QStringList;
coreappdata()->app_libpaths.reset(app_libpaths);
const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
if (!libPathEnv.isEmpty()) {
@ -2592,9 +2581,10 @@ void QCoreApplication::setLibraryPaths(const QStringList &paths)
if (!coreappdata()->app_libpaths)
libraryPaths();
if (!coreappdata()->manual_libpaths)
coreappdata()->manual_libpaths = new QStringList;
if (coreappdata()->manual_libpaths)
*(coreappdata()->manual_libpaths) = paths;
else
coreappdata()->manual_libpaths.reset(new QStringList(paths));
locker.unlock();
QFactoryLoader::refreshAll();
@ -2626,18 +2616,18 @@ void QCoreApplication::addLibraryPath(const QString &path)
QMutexLocker locker(libraryPathMutex());
QStringList *libpaths = coreappdata()->manual_libpaths;
QStringList *libpaths = coreappdata()->manual_libpaths.data();
if (libpaths) {
if (libpaths->contains(canonicalPath))
return;
} else {
// make sure that library paths are initialized
libraryPaths();
QStringList *app_libpaths = coreappdata()->app_libpaths;
QStringList *app_libpaths = coreappdata()->app_libpaths.data();
if (app_libpaths->contains(canonicalPath))
return;
libpaths = coreappdata()->manual_libpaths = new QStringList(*app_libpaths);
coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
}
libpaths->prepend(canonicalPath);
@ -2665,18 +2655,18 @@ void QCoreApplication::removeLibraryPath(const QString &path)
QMutexLocker locker(libraryPathMutex());
QStringList *libpaths = coreappdata()->manual_libpaths;
QStringList *libpaths = coreappdata()->manual_libpaths.data();
if (libpaths) {
if (libpaths->removeAll(canonicalPath) == 0)
return;
} else {
// make sure that library paths is initialized
libraryPaths();
QStringList *app_libpaths = coreappdata()->app_libpaths;
QStringList *app_libpaths = coreappdata()->app_libpaths.data();
if (!app_libpaths->contains(canonicalPath))
return;
libpaths = coreappdata()->manual_libpaths = new QStringList(*app_libpaths);
coreappdata()->manual_libpaths.reset(libpaths = new QStringList(*app_libpaths));
libpaths->removeAll(canonicalPath);
}

View File

@ -40,6 +40,7 @@
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
#include <functional>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.system.threading.h>
@ -70,6 +71,23 @@ struct WinRTTimerInfo : public QAbstractEventDispatcher::TimerInfo {
quint64 targetTime;
};
class AgileDispatchedHandler : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDispatchedHandler, IAgileObject>
{
public:
AgileDispatchedHandler(const std::function<HRESULT()> &delegate)
: delegate(delegate)
{
}
HRESULT __stdcall Invoke()
{
return delegate();
}
private:
std::function<HRESULT()> delegate;
};
class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
{
Q_DECLARE_PUBLIC(QEventDispatcherWinRT)
@ -80,8 +98,6 @@ public:
private:
ComPtr<IThreadPoolTimerStatics> timerFactory;
ComPtr<ICoreDispatcher> coreDispatcher;
QPointer<QThread> thread;
QHash<int, QObject *> timerIdToObject;
QVector<WinRTTimerInfo> timerInfos;
@ -136,40 +152,11 @@ private:
}
return true;
}
void fetchCoreDispatcher()
{
ComPtr<ICoreImmersiveApplication> application;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
RETURN_VOID_IF_FAILED("Failed to get the application factory");
static ComPtr<ICoreApplicationView> view;
if (view)
return;
hr = application->get_MainView(&view);
RETURN_VOID_IF_FAILED("Failed to get the main view");
ComPtr<ICoreApplicationView2> view2;
hr = view.As(&view2);
RETURN_VOID_IF_FAILED("Failed to cast the main view");
hr = view2->get_Dispatcher(&coreDispatcher);
if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) // expected in thread pool cases
return;
RETURN_VOID_IF_FAILED("Failed to get core dispatcher");
thread = QThread::currentThread();
}
};
QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
: QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent)
{
Q_D(QEventDispatcherWinRT);
d->fetchCoreDispatcher();
}
QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
@ -180,25 +167,43 @@ QEventDispatcherWinRT::~QEventDispatcherWinRT()
{
}
HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT ()> &delegate)
{
static __declspec(thread) ICoreDispatcher *dispatcher = nullptr;
if (!dispatcher) {
HRESULT hr;
ComPtr<ICoreImmersiveApplication> application;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
ComPtr<ICoreApplicationView> view;
hr = application->get_MainView(&view);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<ICoreWindow> window;
hr = view->get_CoreWindow(&window);
Q_ASSERT_SUCCEEDED(hr);
hr = window->get_Dispatcher(&dispatcher);
Q_ASSERT_SUCCEEDED(hr);
}
HRESULT hr;
boolean onXamlThread;
hr = dispatcher->get_HasThreadAccess(&onXamlThread);
Q_ASSERT_SUCCEEDED(hr);
if (onXamlThread) // Already there
return delegate();
ComPtr<IAsyncAction> op;
hr = dispatcher->RunAsync(CoreDispatcherPriority_Normal, Make<AgileDispatchedHandler>(delegate).Get(), &op);
if (FAILED(hr))
return hr;
return QWinRTFunctions::await(op);
}
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
if (d->thread && d->thread != QThread::currentThread())
d->fetchCoreDispatcher();
do {
// Process native events
if (d->coreDispatcher) {
boolean hasThreadAccess;
HRESULT hr = d->coreDispatcher->get_HasThreadAccess(&hasThreadAccess);
if (SUCCEEDED(hr) && hasThreadAccess) {
hr = d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
if (FAILED(hr))
qErrnoWarning(hr, "Failed to process events");
}
}
// Additional user events have to be handled before timer events, but the function may not
// return yet.
const bool userEventsSent = sendPostedEvents(flags);
@ -284,9 +289,10 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
TimeSpan period;
period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
IThreadPoolTimer *timer;
const HANDLE handle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE);
const HANDLE cancelHandle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE|EVENT_MODIFY_STATE);
HRESULT hr = runOnXamlThread([&]() {
IThreadPoolTimer *timer;
HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
Callback<ITimerElapsedHandler>([handle, cancelHandle](IThreadPoolTimer *timer) {
DWORD cancelResult = WaitForSingleObjectEx(cancelHandle, 0, TRUE);
@ -306,13 +312,15 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
CloseHandle(cancelHandle);
return S_OK;
}).Get(), &timer);
RETURN_HR_IF_FAILED("Failed to create periodic timer");
d->addTimer(timerId, interval, timerType, object, handle, cancelHandle);
return hr;
});
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to create periodic timer");
CloseHandle(handle);
CloseHandle(cancelHandle);
return;
}
d->addTimer(timerId, interval, timerType, object, handle, cancelHandle);
}
bool QEventDispatcherWinRT::unregisterTimer(int timerId)

View File

@ -50,6 +50,8 @@
#include <qt_windows.h>
namespace std { template <typename T> class function; }
QT_BEGIN_NAMESPACE
quint64 qt_msectime();
@ -65,6 +67,8 @@ public:
explicit QEventDispatcherWinRT(QObject *parent = 0);
~QEventDispatcherWinRT();
static HRESULT runOnXamlThread(const std::function<HRESULT()> &delegate);
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();

View File

@ -46,13 +46,6 @@ QT_END_NAMESPACE
#pragma qt_sync_stop_processing
#endif
#ifdef Q_CC_GNU
// lowercase is fine, we'll undef it below
#define always_inline __attribute__((always_inline, gnu_inline))
#else
#define always_inline
#endif
template<int> struct QAtomicOpsSupport { enum { IsSupported = 0 }; };
template<> struct QAtomicOpsSupport<4> { enum { IsSupported = 1 }; };
@ -84,19 +77,19 @@ template <typename BaseClass> struct QGenericAtomicOps
{
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T load(const T &_q_value) Q_DECL_NOTHROW
{
return _q_value;
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
void store(T &_q_value, X newValue) Q_DECL_NOTHROW
{
_q_value = newValue;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T loadAcquire(const T &_q_value) Q_DECL_NOTHROW
{
T tmp = *static_cast<const volatile T *>(&_q_value);
@ -104,7 +97,7 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
void storeRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
@ -115,13 +108,13 @@ template <typename BaseClass> struct QGenericAtomicOps
{ return BaseClass::isFetchAndAddNative(); }
static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW
{ return BaseClass::isFetchAndAddWaitFree(); }
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
bool ref(T &_q_value) Q_DECL_NOTHROW
{
return BaseClass::fetchAndAddRelaxed(_q_value, 1) != T(-1);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
bool deref(T &_q_value) Q_DECL_NOTHROW
{
return BaseClass::fetchAndAddRelaxed(_q_value, -1) != 1;
@ -138,7 +131,7 @@ template <typename BaseClass> struct QGenericAtomicOps
bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW;
#endif
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
@ -146,21 +139,21 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
@ -168,14 +161,14 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
@ -185,7 +178,7 @@ template <typename BaseClass> struct QGenericAtomicOps
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; }
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
T fetchAndStoreRelaxed(T &_q_value, X newValue) Q_DECL_NOTHROW
{
// implement fetchAndStore on top of testAndSet
@ -196,7 +189,7 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
T fetchAndStoreAcquire(T &_q_value, X newValue) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
@ -204,14 +197,14 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
T fetchAndStoreRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
template <typename T, typename X> static inline always_inline
template <typename T, typename X> static Q_ALWAYS_INLINE
T fetchAndStoreOrdered(T &_q_value, X newValue) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
@ -220,7 +213,7 @@ template <typename BaseClass> struct QGenericAtomicOps
static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return false; }
static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
{
// implement fetchAndAdd on top of testAndSet
@ -231,7 +224,7 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
@ -239,28 +232,28 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
{
// implement fetchAndSub on top of fetchAndAdd
return fetchAndAddRelaxed(_q_value, -operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
@ -268,21 +261,21 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAndRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndAnd on top of testAndSet
@ -293,7 +286,7 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAndAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
@ -301,21 +294,21 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAndRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndAndOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndOrRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndOr on top of testAndSet
@ -326,7 +319,7 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndOrAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
@ -334,21 +327,21 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndOrRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndOrOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndXorRelaxed(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
// implement fetchAndXor on top of testAndSet
@ -359,7 +352,7 @@ template <typename BaseClass> struct QGenericAtomicOps
}
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndXorAcquire(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
@ -367,14 +360,14 @@ template <typename BaseClass> struct QGenericAtomicOps
return tmp;
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndXorRelease(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndXorRelaxed(_q_value, operand);
}
template <typename T> static inline always_inline
template <typename T> static Q_ALWAYS_INLINE
T fetchAndXorOrdered(T &_q_value, typename QtPrivate::QEnableIf<QTypeInfo<T>::isIntegral, T>::Type operand) Q_DECL_NOTHROW
{
BaseClass::orderedMemoryFence(_q_value);
@ -382,7 +375,5 @@ template <typename BaseClass> struct QGenericAtomicOps
}
};
#undef always_inline
QT_END_NAMESPACE
#endif // QGENERICATOMIC_H

View File

@ -2240,7 +2240,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
Returns a pointer to the current item's key.
*/
/*! \fn bool QHash::key_iterator::operator==(key_iterator other)
/*! \fn bool QHash::key_iterator::operator==(key_iterator other) const
Returns \c true if \a other points to the same item as this
iterator; otherwise returns \c false.
@ -2248,7 +2248,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
\sa operator!=()
*/
/*! \fn bool QHash::key_iterator::operator!=(key_iterator other)
/*! \fn bool QHash::key_iterator::operator!=(key_iterator other) const
Returns \c true if \a other points to a different item than this
iterator; otherwise returns \c false.

View File

@ -378,7 +378,7 @@ void **QListData::erase(void **xi)
references into a QVector and non-heap-allocating QLists.
Internally, QList\<T\> is represented as an array of T if
If \c{sizeof(T) <= sizeof(void*)} and T has been declared to be
\c{sizeof(T) <= sizeof(void*)} and T has been declared to be
either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using
\l {Q_DECLARE_TYPEINFO}. Otherwise, QList\<T\> is represented
as an array of T* and the items are allocated on the heap.

View File

@ -1719,7 +1719,7 @@ void QMapDataBase::freeData(QMapDataBase *d)
Returns a pointer to the current item's key.
*/
/*! \fn bool QMap::key_iterator::operator==(key_iterator other)
/*! \fn bool QMap::key_iterator::operator==(key_iterator other) const
Returns \c true if \a other points to the same item as this
iterator; otherwise returns \c false.
@ -1727,7 +1727,7 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa operator!=()
*/
/*! \fn bool QMap::key_iterator::operator!=(key_iterator other)
/*! \fn bool QMap::key_iterator::operator!=(key_iterator other) const
Returns \c true if \a other points to a different item than this
iterator; otherwise returns \c false.

View File

@ -1935,6 +1935,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE
}
}
#endif
e->eventAccepted = ev.isAccepted();
}
void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e)

View File

@ -689,6 +689,14 @@ QRect QPlatformWindow::windowGeometry() const
return QHighDpi::toNativePixels(window()->geometry(), window());
}
/*!
Returns the QWindow frame geometry.
*/
QRect QPlatformWindow::windowFrameGeometry() const
{
return QHighDpi::toNativePixels(window()->frameGeometry(), window());
}
/*!
Returns the closest acceptable geometry for a given geometry before
a resize/move event for platforms that support it, for example to

View File

@ -138,6 +138,7 @@ public:
QSize windowBaseSize() const;
QSize windowSizeIncrement() const;
QRect windowGeometry() const;
QRect windowFrameGeometry() const;
QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const;
protected:

View File

@ -303,24 +303,24 @@ bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, ulong ti
}
void QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
bool QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
handleKeyEvent(w, time, t, k, mods, text, autorep, count);
return handleKeyEvent(w, time, t, k, mods, text, autorep, count);
}
void QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
{
// This is special handling needed for OS X which eventually will call sendEvent(), on other platforms
// this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for
// shortcut overriding on other platforms.
#if defined(Q_OS_OSX)
if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(tlw, timestamp, k, mods, text))
return;
return true;
#endif // Q_OS_OSX
QWindowSystemInterfacePrivate::KeyEvent * e =
new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
@ -441,10 +441,12 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e
windowSystemEventQueue.remove(event);
}
void QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
{
bool accepted = true;
if (synchronousWindowSystemEvents) {
QGuiApplicationPrivate::processWindowSystemEvent(ev);
accepted = ev->eventAccepted;
delete ev;
} else {
windowSystemEventQueue.append(ev);
@ -452,6 +454,7 @@ void QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfa
if (dispatcher)
dispatcher->wakeUp();
}
return accepted;
}
void QWindowSystemInterface::registerTouchDevice(QTouchDevice *device)
@ -611,7 +614,7 @@ void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::Process
Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
flushWindowSystemEvents(flags);
sendWindowSystemEvents(flags);
QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
}

View File

@ -95,8 +95,8 @@ public:
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
const QString & text = QString(), bool autorep = false, ushort count = 1);
static void handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
static void handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
static void handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,

View File

@ -101,7 +101,7 @@ public:
};
explicit WindowSystemEvent(EventType t)
: type(t), flags(0) { }
: type(t), flags(0), eventAccepted(true) { }
virtual ~WindowSystemEvent() { }
bool synthetic() const { return flags & Synthetic; }
@ -109,6 +109,7 @@ public:
EventType type;
int flags;
bool eventAccepted;
};
class CloseEvent : public WindowSystemEvent {
@ -480,7 +481,7 @@ public:
static WindowSystemEvent *getNonUserInputWindowSystemEvent();
static WindowSystemEvent *peekWindowSystemEvent(EventType t);
static void removeWindowSystemEvent(WindowSystemEvent *event);
static void handleWindowSystemEvent(WindowSystemEvent *ev);
static bool handleWindowSystemEvent(WindowSystemEvent *ev);
static QElapsedTimer eventTime;
static bool synchronousWindowSystemEvents;

View File

@ -182,7 +182,8 @@ void QBackingStore::beginPaint(const QRegion &region)
qCDebug(lcScaling) << "QBackingStore::beginPaint new backingstore for" << d_ptr->window;
qCDebug(lcScaling) << " source size" << source->size() << "dpr" << source->devicePixelRatio();
d_ptr->highDpiBackingstore.reset(
new QImage(source->bits(), source->width(), source->height(), source->format()));
new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format()));
qreal targetDevicePixelRatio = d_ptr->window->devicePixelRatio();
d_ptr->highDpiBackingstore->setDevicePixelRatio(targetDevicePixelRatio);
qCDebug(lcScaling) <<" destination size" << d_ptr->highDpiBackingstore->size()

View File

@ -395,169 +395,6 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
}
}
template<QtPixelOrder PixelOrder>
static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_argb32pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
fflush(stdout);
#endif
const uint *src = (const uint *) srcPixels;
uint *dst = (uint *) destPixels;
if (const_alpha == 256) {
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = src[x];
dst[x] = qConvertArgb32ToA2rgb30<PixelOrder>(s) + BYTE_MUL_RGB30(dst[x], 255 - qAlpha(s));
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
} else if (const_alpha != 0) {
const_alpha = (const_alpha * 255) >> 8;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = src[x];
dst[x] = BYTE_MUL_RGB30(qConvertArgb32ToA2rgb30<PixelOrder>(s), const_alpha) + BYTE_MUL_RGB30(dst[x], 255 - qt_div_255(qAlpha(s) * const_alpha));
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
}
}
template<QtPixelOrder PixelOrder>
static void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb32_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
fflush(stdout);
#endif
if (const_alpha != 256) {
qt_blend_argb32pm_on_a2rgb30pm<PixelOrder>(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
return;
}
const uint *src = (const uint *) srcPixels;
uint *dst = (uint *) destPixels;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
dst[x] = qConvertRgb32ToRgb30<PixelOrder>(src[x]);
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
}
static void qt_blend_a2rgb30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_a2rgb30pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
fflush(stdout);
#endif
const uint *src = (const uint *) srcPixels;
uint *dst = (uint *) destPixels;
if (const_alpha == 256) {
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = src[x];
dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s));
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
} else if (const_alpha != 0) {
const uint const_alpha255 = (const_alpha * 255) >> 8;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8;
uint s = BYTE_MUL_RGB30(src[x], const_alpha255);
dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - a);
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
}
}
static void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb30_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
fflush(stdout);
#endif
if (const_alpha != 256) {
qt_blend_a2rgb30pm_on_a2rgb30pm(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
return;
}
const uint *src = (const uint *) srcPixels;
uint *dst = (uint *) destPixels;
int len = w * 4;
for (int y=0; y<h; ++y) {
memcpy(dst, src, len);
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
}
static void qt_blend_a2bgr30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_a2bgr30pm_on_a2rgb32pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
fflush(stdout);
#endif
const uint *src = (const uint *) srcPixels;
uint *dst = (uint *) destPixels;
if (const_alpha == 256) {
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = qRgbSwapRgb30(src[x]);
dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s));
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
} else if (const_alpha != 0) {
const uint const_alpha255 = (const_alpha * 255) >> 8;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8;
uint s = BYTE_MUL_RGB30(src[x], const_alpha255);
dst[x] = qRgbSwapRgb30(s) + BYTE_MUL_RGB30(dst[x], 255 - a);
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
}
}
}
struct Blend_RGB32_on_RGB32_NoAlpha {
inline void write(quint32 *dst, quint32 src) { *dst = src; }
@ -772,30 +609,6 @@ void qInitBlendFunctions()
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32;
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32;
#endif
qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
qBlendFunctions[QImage::Format_BGR30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
qBlendFunctions[QImage::Format_BGR30][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
qTransformFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32;
qTransformFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32;

View File

@ -1252,8 +1252,27 @@ static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *b
const __m128i cmask = _mm_set1_epi32(0x000003ff);
int i = 0;
__m128i vr, vg, vb, va;
for (; i < count-1; i += 2) {
__m128i vs = _mm_loadu_si128((const __m128i*)buffer);
if (i < count && (const uintptr_t)buffer & 0x8) {
*dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
++i;
}
for (; i < count-15; i += 16) {
// Repremultiplying is really expensive and hard to do in SIMD without AVX2,
// so we try to avoid it by checking if it is needed 16 samples at a time.
__m128i vOr = _mm_set1_epi32(0);
__m128i vAnd = _mm_set1_epi32(0xffffffff);
for (int j = 0; j < 16; j += 2) {
__m128i vs = _mm_load_si128((const __m128i*)(buffer + j));
vOr = _mm_or_si128(vOr, vs);
vAnd = _mm_and_si128(vAnd, vs);
}
const quint16 orAlpha = ((uint)_mm_extract_epi16(vOr, 3)) | ((uint)_mm_extract_epi16(vOr, 7));
const quint16 andAlpha = ((uint)_mm_extract_epi16(vAnd, 3)) & ((uint)_mm_extract_epi16(vAnd, 7));
if (andAlpha == 0xffff) {
for (int j = 0; j < 16; j += 2) {
__m128i vs = _mm_load_si128((const __m128i*)buffer);
buffer += 2;
vr = _mm_srli_epi64(vs, 6);
vg = _mm_srli_epi64(vs, 16 + 6 - 10);
@ -1272,6 +1291,16 @@ static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *b
_mm_storel_epi64((__m128i*)dest, vd);
dest += 2;
}
} else if (orAlpha == 0) {
for (int j = 0; j < 16; ++j) {
*dest++ = 0;
buffer++;
}
} else {
for (int j = 0; j < 16; ++j)
*dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
}
}
for (; i < count; ++i)
*dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);

View File

@ -62,15 +62,12 @@ QT_BEGIN_NAMESPACE
#if defined(Q_CC_GNU)
# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_ALWAYS_INLINE inline __attribute__((always_inline))
# define Q_DECL_RESTRICT __restrict__
#elif defined(Q_CC_MSVC)
# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_ALWAYS_INLINE __forceinline
# define Q_DECL_RESTRICT __restrict
#else
# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_ALWAYS_INLINE inline
# define Q_DECL_RESTRICT
#endif
@ -712,18 +709,6 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
static Q_ALWAYS_INLINE uint BYTE_MUL_RGB30(uint x, uint a) {
uint xa = x >> 30;
uint xr = (x >> 20) & 0x3ff;
uint xg = (x >> 10) & 0x3ff;
uint xb = x & 0x3ff;
xa = qt_div_255(xa * a);
xr = qt_div_255(xr * a);
xg = qt_div_255(xg * a);
xb = qt_div_255(xb * a);
return (xa << 30) | (xr << 20) | (xg << 10) | xb;
}
static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
{
uint a = c >> 30;
@ -897,6 +882,18 @@ inline QRgb qRepremultiply(QRgb p)
return qPremultiply(p);
}
template<unsigned int Shift>
inline QRgba64 qRepremultiply(QRgba64 p)
{
const uint alpha = p.alpha();
if (alpha == 65535 || alpha == 0)
return p;
p = p.unpremultiplied();
Q_CONSTEXPR uint mult = 65535 / (65535 >> Shift);
p.setAlpha(mult * (alpha >> Shift));
return p.premultiplied();
}
template<>
inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
{
@ -1000,6 +997,7 @@ template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64);
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;
@ -1010,6 +1008,7 @@ inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;

View File

@ -40,35 +40,43 @@
QT_BEGIN_NAMESPACE
class QRgba64 {
struct qrgba_t {
quint16 red;
quint16 green;
quint16 blue;
quint16 alpha;
quint64 rgba;
// Make sure that the representation always has the order: red green blue alpha, independent
// of byte order. This way, vector operations that assume 4 16-bit values see the correct ones.
enum {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
RedShift = 48,
GreenShift = 32,
BlueShift = 16,
AlphaShift = 0
#else // little endian:
RedShift = 0,
GreenShift = 16,
BlueShift = 32,
AlphaShift = 48
#endif
};
union {
struct qrgba_t c;
quint64 rgba;
};
public:
// No constructors are allowed, since this needs to be usable in a union in no-c++11 mode.
// When c++11 is mandatory, we can add all but a copy constructor.
Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
Q_DECL_RELAXED_CONSTEXPR static
QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
{
QRgba64 rgba64
#ifdef Q_COMPILER_UNIFORM_INIT
= {}
#endif
;
rgba64.c.red = red;
rgba64.c.green = green;
rgba64.c.blue = blue;
rgba64.c.alpha = alpha;
rgba64.rgba = quint64(red) << RedShift
| quint64(green) << GreenShift
| quint64(blue) << BlueShift
| quint64(alpha) << AlphaShift;
return rgba64;
}
Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint64 c)
Q_DECL_RELAXED_CONSTEXPR static
QRgba64 fromRgba64(quint64 c)
{
QRgba64 rgba64
#ifdef Q_COMPILER_UNIFORM_INIT
@ -85,42 +93,49 @@ public:
rgb64.rgba |= rgb64.rgba << 8;
return rgb64;
}
Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromArgb32(uint rgb)
Q_DECL_RELAXED_CONSTEXPR static
QRgba64 fromArgb32(uint rgb)
{
return fromRgba(rgb >> 16, rgb >> 8, rgb, rgb >> 24);
}
Q_DECL_CONSTEXPR bool isOpaque() const { return c.alpha == 0xffff; }
Q_DECL_CONSTEXPR bool isTransparent() const { return c.alpha == 0; }
Q_DECL_CONSTEXPR bool isOpaque() const
{
return (rgba & alphaMask()) == alphaMask();
}
Q_DECL_CONSTEXPR bool isTransparent() const
{
return (rgba & alphaMask()) == 0;
}
Q_DECL_CONSTEXPR quint16 red() const { return c.red; }
Q_DECL_CONSTEXPR quint16 green() const { return c.green; }
Q_DECL_CONSTEXPR quint16 blue() const { return c.blue; }
Q_DECL_CONSTEXPR quint16 alpha() const { return c.alpha; }
void setRed(quint16 _red) { c.red = _red; }
void setGreen(quint16 _green) { c.green = _green; }
void setBlue(quint16 _blue) { c.blue = _blue; }
void setAlpha(quint16 _alpha) { c.alpha = _alpha; }
Q_DECL_CONSTEXPR quint16 red() const { return rgba >> RedShift; }
Q_DECL_CONSTEXPR quint16 green() const { return rgba >> GreenShift; }
Q_DECL_CONSTEXPR quint16 blue() const { return rgba >> BlueShift; }
Q_DECL_CONSTEXPR quint16 alpha() const { return rgba >> AlphaShift; }
void setRed(quint16 _red) { *this = fromRgba64(_red, green(), blue(), alpha()); }
void setGreen(quint16 _green) { *this = fromRgba64(red(), _green, blue(), alpha()); }
void setBlue(quint16 _blue) { *this = fromRgba64(red(), green(), _blue, alpha()); }
void setAlpha(quint16 _alpha) { *this = fromRgba64(red(), green(), blue(), _alpha); }
Q_DECL_CONSTEXPR quint8 red8() const { return div_257(c.red); }
Q_DECL_CONSTEXPR quint8 green8() const { return div_257(c.green); }
Q_DECL_CONSTEXPR quint8 blue8() const { return div_257(c.blue); }
Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(c.alpha); }
Q_DECL_CONSTEXPR quint8 red8() const { return div_257(red()); }
Q_DECL_CONSTEXPR quint8 green8() const { return div_257(green()); }
Q_DECL_CONSTEXPR quint8 blue8() const { return div_257(blue()); }
Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(alpha()); }
Q_DECL_CONSTEXPR uint toArgb32() const
{
return (alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8();
}
Q_DECL_CONSTEXPR ushort toRgb16() const
{
return (c.red & 0xf800) | ((c.green >> 10) << 5) | (c.blue >> 11);
return (red() & 0xf800) | ((green() >> 10) << 5) | (blue() >> 11);
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 premultiplied() const
{
const quint32 a = c.alpha;
const quint16 r = div_65535(c.red * a);
const quint16 g = div_65535(c.green * a);
const quint16 b = div_65535(c.blue * a);
const quint32 a = alpha();
const quint16 r = div_65535(red() * a);
const quint16 g = div_65535(green() * a);
const quint16 b = div_65535(blue() * a);
return fromRgba64(r, g, b, a);
}
@ -145,27 +160,31 @@ public:
}
private:
static Q_DECL_CONSTEXPR quint64 alphaMask() { return quint64(0xffff) << AlphaShift; }
static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; }
static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); }
static Q_DECL_CONSTEXPR uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_32bit() const
{
if (c.alpha == 0xffff || c.alpha == 0)
const quint16 a = alpha();
if (a == 0xffff || a == 0)
return *this;
const quint16 r = (quint32(c.red) * 0xffff + c.alpha/2) / c.alpha;
const quint16 g = (quint32(c.green) * 0xffff + c.alpha/2) / c.alpha;
const quint16 b = (quint32(c.blue) * 0xffff + c.alpha/2) / c.alpha;
return fromRgba64(r, g, b, c.alpha);
const quint16 r = (quint32(red()) * 0xffff + a/2) / a;
const quint16 g = (quint32(green()) * 0xffff + a/2) / a;
const quint16 b = (quint32(blue()) * 0xffff + a/2) / a;
return fromRgba64(r, g, b, a);
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_64bit() const
{
if (c.alpha == 0xffff || c.alpha == 0)
const quint16 a = alpha();
if (a == 0xffff || a == 0)
return *this;
const quint64 fa = (Q_UINT64_C(0xffff00008000) + c.alpha/2) / c.alpha;
const quint16 r = (c.red * fa + 0x80000000) >> 32;
const quint16 g = (c.green * fa + 0x80000000) >> 32;
const quint16 b = (c.blue * fa + 0x80000000) >> 32;
return fromRgba64(r, g, b, c.alpha);
const quint64 fa = (Q_UINT64_C(0xffff00008000) + a/2) / a;
const quint16 r = (red() * fa + 0x80000000) >> 32;
const quint16 g = (green() * fa + 0x80000000) >> 32;
const quint16 b = (blue() * fa + 0x80000000) >> 32;
return fromRgba64(r, g, b, a);
}
};

View File

@ -99,6 +99,13 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng
static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0};
static const QFontEngine::HintStyle ftInitialDefaultHintStyle =
#ifdef Q_OS_WIN
QFontEngineFT::HintFull;
#else
QFontEngineFT::HintNone;
#endif
// -------------------------- Freetype support ------------------------------
class QtFreetypeData
@ -629,11 +636,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
antialias = true;
freetype = 0;
default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
#ifndef Q_OS_WIN
default_hint_style = HintNone;
#else
default_hint_style = HintFull;
#endif
default_hint_style = ftInitialDefaultHintStyle;
subpixelType = Subpixel_None;
lcdFilterType = 0;
#if defined(FT_LCD_FILTER_H)
@ -760,6 +763,24 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
return true;
}
void QFontEngineFT::setQtDefaultHintStyle(QFont::HintingPreference hintingPreference)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
setDefaultHintStyle(HintNone);
break;
case QFont::PreferFullHinting:
setDefaultHintStyle(HintFull);
break;
case QFont::PreferVerticalHinting:
setDefaultHintStyle(HintLight);
break;
case QFont::PreferDefaultHinting:
setDefaultHintStyle(ftInitialDefaultHintStyle);
break;
}
}
void QFontEngineFT::setDefaultHintStyle(HintStyle style)
{
default_hint_style = style;

View File

@ -281,7 +281,7 @@ private:
virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE;
void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference);
virtual void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE;
virtual QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
@ -307,6 +307,7 @@ private:
friend class QFontEngineFTRawFont;
friend class QFontconfigDatabase;
friend class QBasicFontDatabase;
friend class QCoreTextFontDatabase;
friend class QFontEngineMultiFontConfig;
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;

View File

@ -1120,6 +1120,15 @@ QT_BEGIN_INCLUDE_NAMESPACE
QT_END_INCLUDE_NAMESPACE
#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE)
static const char *s_shapersForOsxFreeType[] =
{
"ot",
"fallback",
Q_NULLPTR
};
#endif
int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const
{
uint glyphs_shaped = 0;
@ -1172,7 +1181,15 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
};
const int num_features = 1;
bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0);
const char *const *shaper_list = Q_NULLPTR;
#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE)
// What's behind QFontEngine::FaceData::user_data isn't compatible between CoreText and
// FreeType font engines - specifically functions in hb-coretext.cc would run into undefined
// behavior with data from the FreeType engine. The OpenType shaper works with that engine.
if (actualFontEngine->type() == QFontEngine::Freetype)
shaper_list = s_shapersForOsxFreeType;
#endif
bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list);
if (Q_UNLIKELY(!shapedOk)) {
hb_buffer_destroy(buffer);
return 0;

View File

@ -115,8 +115,6 @@ public:
QNetworkReplyImplPrivate();
void _q_startOperation();
void _q_sourceReadyRead();
void _q_sourceReadChannelFinished();
void _q_copyReadyRead();
void _q_copyReadChannelFinished();
void _q_bufferOutgoingData();

View File

@ -1810,12 +1810,12 @@ QString QAbstractSocket::peerName() const
*/
bool QAbstractSocket::canReadLine() const
{
bool hasLine = d_func()->buffer.canReadLine();
bool hasLine = QIODevice::canReadLine();
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::canReadLine() == %s, buffer size = %lld, size = %lld",
hasLine ? "true" : "false", d_func()->buffer.size(), d_func()->buffer.size());
#endif
return hasLine || QIODevice::canReadLine();
return hasLine;
}
/*!

View File

@ -149,7 +149,7 @@ public:
qint64 bytesAvailable() const Q_DECL_OVERRIDE;
qint64 bytesToWrite() const Q_DECL_OVERRIDE;
bool canReadLine() const Q_DECL_OVERRIDE;
bool canReadLine() const Q_DECL_OVERRIDE; // ### Qt6: remove me
quint16 localPort() const;
QHostAddress localAddress() const;

View File

@ -76,24 +76,6 @@ void QBasicFontDatabase::populateFontDatabase()
}
}
inline static void setHintingPreference(QFontEngine *engine, QFont::HintingPreference hintingPreference)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintNone);
break;
case QFont::PreferFullHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintFull);
break;
case QFont::PreferVerticalHinting:
engine->setDefaultHintStyle(QFontEngineFT::HintLight);
break;
case QFont::PreferDefaultHinting:
// Leave it as it is
break;
}
}
QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
@ -119,7 +101,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPt
delete engine;
engine = 0;
} else {
setHintingPreference(engine, static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
}
return engine;
@ -172,7 +154,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pi
}
fe->updateFamilyNameAndStyle();
setHintingPreference(fe, hintingPreference);
fe->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
return fe;
}

View File

@ -1,6 +1,13 @@
HEADERS += $$PWD/qcoretextfontdatabase_p.h $$PWD/qfontengine_coretext_p.h
OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.mm
contains(QT_CONFIG, freetype) {
include($$QT_SOURCE_TREE/src/3rdparty/freetype_dependency.pri)
HEADERS += $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft_p.h
SOURCES += $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft.cpp
CONFIG += opentype
}
ios: \
# On iOS CoreText and CoreGraphics are stand-alone frameworks
LIBS_PRIVATE += -framework CoreText -framework CoreGraphics

View File

@ -33,6 +33,8 @@
#include "qglobal.h"
#include <sys/param.h>
#if defined(Q_OS_MACX)
#import <Cocoa/Cocoa.h>
#import <IOKit/graphics/IOGraphicsLib.h>
@ -45,6 +47,9 @@
#include <QtCore/QSettings>
#include <QtGui/QGuiApplication>
#include <QtCore/QtEndian>
#ifndef QT_NO_FREETYPE
#include <QtGui/private/qfontengine_ft_p.h>
#endif
QT_BEGIN_NAMESPACE
@ -102,8 +107,12 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context)
}
#endif
QCoreTextFontDatabase::QCoreTextFontDatabase()
QCoreTextFontDatabase::QCoreTextFontDatabase(bool useFreeType)
#ifndef QT_NO_FREETYPE
: m_useFreeType(useFreeType)
#endif
{
Q_UNUSED(useFreeType)
#ifdef Q_OS_MACX
QSettings appleSettings(QLatin1String("apple.com"));
QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
@ -348,10 +357,48 @@ void QCoreTextFontDatabase::releaseHandle(void *handle)
CFRelease(CTFontDescriptorRef(handle));
}
#ifndef QT_NO_FREETYPE
static QByteArray filenameForCFUrl(CFURLRef url)
{
// The on-stack buffer prevents that a QByteArray allocated for the worst case (MAXPATHLEN)
// stays around for the lifetime of the font. Additionally, it helps to move the char
// signedness cast to an acceptable place.
uchar buffer[MAXPATHLEN];
QByteArray filename;
if (!CFURLGetFileSystemRepresentation(url, true, buffer, sizeof(buffer))) {
qWarning("QCoreTextFontDatabase::filenameForCFUrl: could not resolve file for URL %s",
qPrintable(QString::fromCFString(CFURLGetString(url))));
} else {
QCFType<CFStringRef> scheme = CFURLCopyScheme(url);
if (QString::fromCFString(scheme) == QLatin1String("qrc"))
filename = ":";
filename += reinterpret_cast<char *>(buffer);
}
return filename;
}
#endif
extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
#ifndef QT_NO_FREETYPE
if (m_useFreeType) {
QCFType<CFURLRef> url(static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute)));
QByteArray filename;
if (url)
filename = filenameForCFUrl(url);
return freeTypeFontEngine(f, filename);
}
#endif
qreal scaledPointSize = f.pixelSize;
// When 96 DPI is forced, the Mac plugin will use DPI 72 for some
@ -363,7 +410,6 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
if (QGuiApplication::testAttribute(Qt::AA_Use96Dpi))
scaledPointSize = f.pointSize;
CTFontDescriptorRef descriptor = (CTFontDescriptorRef) usrPtr;
CGAffineTransform matrix = qt_transform_from_fontdef(f);
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix);
if (font) {
@ -385,6 +431,29 @@ static void releaseFontData(void* info, const void* data, size_t size)
QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
#ifndef QT_NO_FREETYPE
if (m_useFreeType) {
QByteArray *fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
QCFType<CGFontRef> cgFont(CGFontCreateWithDataProvider(dataProvider));
if (!cgFont) {
qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed");
return Q_NULLPTR;
}
QFontDef fontDef;
fontDef.pixelSize = pixelSize;
fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi();
fontDef.hintingPreference = hintingPreference;
CGAffineTransform transform = qt_transform_from_fontdef(fontDef);
QCFType<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR));
QCFType<CFURLRef> url(static_cast<CFURLRef>(CTFontCopyAttribute(ctFont, kCTFontURLAttribute)));
return freeTypeFontEngine(fontDef, filenameForCFUrl(url), fontData);
}
#endif
Q_UNUSED(hintingPreference);
QByteArray* fontDataCopy = new QByteArray(fontData);
@ -556,10 +625,36 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
}
#if HAVE_CORETEXT
static CFArrayRef createDescriptorArrayForFont(CTFontRef font)
static CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName = QString())
{
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(array, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
Q_UNUSED(fileName)
#ifndef QT_NO_FREETYPE
// The physical font source URL (usually a local file or Qt resource) is only required for
// FreeType, when using non-system fonts, and needs some hackery to attach in a format
// agreeable to OSX.
if (!fileName.isEmpty()) {
QCFType<CFURLRef> fontURL;
if (fileName.startsWith(QLatin1String(":/"))) {
// QUrl::fromLocalFile() doesn't accept qrc pseudo-paths like ":/fonts/myfont.ttf".
// Therefore construct from QString with the qrc:// scheme -> "qrc:///fonts/myfont.ttf".
fontURL = QUrl(QStringLiteral("qrc://") + fileName.mid(1)).toCFURL();
} else if (!fileName.isEmpty()) {
// At this point we hope that filename is in a format that QUrl can handle.
fontURL = QUrl::fromLocalFile(fileName).toCFURL();
}
QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL);
descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes);
}
#endif
CFArrayAppendValue(array, descriptor);
return array;
}
#endif
@ -580,7 +675,11 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
if (cgFont) {
if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) {
QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
fonts = createDescriptorArrayForFont(font);
fonts = createDescriptorArrayForFont(font
#ifndef QT_NO_FREETYPE
, m_useFreeType ? fileName : QString()
#endif
);
m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont)));
}
}
@ -880,5 +979,36 @@ void QCoreTextFontDatabase::removeApplicationFonts()
#endif
}
#ifndef QT_NO_FREETYPE
QFontEngine *QCoreTextFontDatabase::freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename,
const QByteArray &fontData)
{
QFontEngine::FaceId faceId;
faceId.filename = filename;
const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
QScopedPointer<QFontEngineFT> engine(new QFontEngineFT(fontDef));
QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono;
if (antialias) {
QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint();
if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
format = QFontEngineFT::Format_A8;
engine->subpixelType = QFontEngine::Subpixel_None;
} else {
format = QFontEngineFT::Format_A32;
engine->subpixelType = subpixelType;
}
}
if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) {
qWarning() << "QCoreTextFontDatabase::freeTypefontEngine Failed to create engine";
return Q_NULLPTR;
}
engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
return engine.take();
}
#endif
QT_END_NAMESPACE

View File

@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
class QCoreTextFontDatabase : public QPlatformFontDatabase
{
public:
QCoreTextFontDatabase();
QCoreTextFontDatabase(bool useFreeType = false);
~QCoreTextFontDatabase();
void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
@ -95,6 +95,11 @@ public:
private:
void populateFromDescriptor(CTFontDescriptorRef font);
#ifndef QT_NO_FREETYPE
bool m_useFreeType;
QFontEngine *freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename,
const QByteArray &fontData = QByteArray());
#endif
mutable QString defaultFontName;
void removeApplicationFonts();

View File

@ -70,18 +70,20 @@ namespace QtAndroidInput
candidatesEnd);
}
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints)
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
{
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
"showSoftwareKeyboard",
"(IIIII)V",
"(IIIIII)V",
left,
top,
width,
height,
inputHints);
inputHints,
enterKeyType
);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints;
qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
#endif
}

View File

@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
namespace QtAndroidInput
{
// Software keyboard support
void showSoftwareKeyboard(int top, int left, int width, int height, int inputHints);
void showSoftwareKeyboard(int top, int left, int width, int height, int inputHints, int enterKeyType);
void resetSoftwareKeyboard();
void hideSoftwareKeyboard();
bool isSoftwareKeyboardVisible();

View File

@ -545,7 +545,9 @@ void QAndroidInputContext::showInputPanel()
rect.top(),
rect.width(),
rect.height(),
query->value(Qt::ImHints).toUInt());
query->value(Qt::ImHints).toUInt(),
query->value(Qt::ImEnterKeyType).toUInt()
);
}
void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)

View File

@ -50,11 +50,9 @@ public:
QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
Q_UNUSED(paramList);
QMacAutoReleasePool pool;
if (system.compare(QLatin1String("cocoa"), Qt::CaseInsensitive) == 0)
return new QCocoaIntegration;
return new QCocoaIntegration(paramList);
return 0;
}

View File

@ -73,6 +73,7 @@ public:
QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor; }
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
// ----------------------------------------------------
// Additional methods
@ -97,10 +98,16 @@ public:
class QCocoaIntegration : public QPlatformIntegration
{
public:
QCocoaIntegration();
enum Option {
UseFreeTypeFontEngine = 0x1
};
Q_DECLARE_FLAGS(Options, Option)
QCocoaIntegration(const QStringList &paramList);
~QCocoaIntegration();
static QCocoaIntegration *instance();
Options options() const;
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
@ -141,6 +148,7 @@ public:
void setApplicationIcon(const QIcon &icon) const Q_DECL_OVERRIDE;
private:
static QCocoaIntegration *mInstance;
Options mOptions;
QScopedPointer<QCoreTextFontDatabase> mFontDb;
@ -160,6 +168,8 @@ private:
QList<QCocoaWindow *> m_popupWindowStack;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QCocoaIntegration::Options)
QT_END_NAMESPACE
#endif

View File

@ -142,6 +142,16 @@ qreal QCocoaScreen::devicePixelRatio() const
return qreal(screen ? [screen backingScaleFactor] : 1.0);
}
QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const
{
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
if (type == QPlatformScreen::Subpixel_None) {
// Every OSX machine has RGB pixels unless a peculiar or rotated non-Apple screen is attached
type = QPlatformScreen::Subpixel_RGB;
}
return type;
}
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
NSPoint screenPoint = qt_mac_flipPoint(point);
@ -244,10 +254,25 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height
return windowPixmap;
}
static QCocoaIntegration::Options parseOptions(const QStringList &paramList)
{
QCocoaIntegration::Options options;
foreach (const QString &param, paramList) {
#ifndef QT_NO_FREETYPE
if (param == QLatin1String("fontengine=freetype"))
options |= QCocoaIntegration::UseFreeTypeFontEngine;
else
#endif
qWarning() << "Unknown option" << param;
}
return options;
}
QCocoaIntegration *QCocoaIntegration::mInstance = 0;
QCocoaIntegration::QCocoaIntegration()
: mFontDb(new QCoreTextFontDatabase())
QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
: mOptions(parseOptions(paramList))
, mFontDb(new QCoreTextFontDatabase(mOptions.testFlag(UseFreeTypeFontEngine)))
#ifndef QT_NO_ACCESSIBILITY
, mAccessibility(new QCocoaAccessibility)
#endif
@ -345,6 +370,11 @@ QCocoaIntegration *QCocoaIntegration::instance()
return mInstance;
}
QCocoaIntegration::Options QCocoaIntegration::options() const
{
return mOptions;
}
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted ones
*/

View File

@ -36,11 +36,13 @@
#include "qwinrtcursor.h"
#include "qwinrtscreen.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <QtCore/qfunctions_winrt.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <functional>
#include <wrl.h>
#include <windows.ui.core.h>
#include <windows.foundation.h>
@ -77,12 +79,17 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
Q_D(QWinRTCursor);
HRESULT hr;
ICoreWindow *coreWindow = static_cast<QWinRTScreen *>(window->screen()->handle())->coreWindow();
CoreCursorType type;
switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
case Qt::BlankCursor:
hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow]() {
coreWindow->put_PointerCursor(Q_NULLPTR);
return S_OK;
});
RETURN_VOID_IF_FAILED("Failed to set blank native cursor");
return;
default:
case Qt::OpenHandCursor:
@ -142,11 +149,13 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
}
ComPtr<ICoreCursor> cursor;
HRESULT hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
RETURN_VOID_IF_FAILED("Failed to create native cursor.");
hr = coreWindow->put_PointerCursor(cursor.Get());
RETURN_VOID_IF_FAILED("Failed to set native cursor.");
hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &cursor]() {
return coreWindow->put_PointerCursor(cursor.Get());
});
RETURN_VOID_IF_FAILED("Failed to set native cursor");
}
#endif // QT_NO_CURSOR
@ -154,8 +163,12 @@ QPoint QWinRTCursor::pos() const
{
ICoreWindow *coreWindow =
static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle())->coreWindow();
HRESULT hr;
Point point;
coreWindow->get_PointerPosition(&point);
hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &point]() {
return coreWindow->get_PointerPosition(&point);
});
RETURN_IF_FAILED("Failed to get native cursor position", QPoint());
return QPoint(point.X, point.Y);
}

View File

@ -35,40 +35,133 @@
****************************************************************************/
#include "qwinrteglcontext.h"
#include "qwinrtwindow.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <functional>
#include <EGL/egl.h>
#define EGL_EGLEXT_PROTOTYPES
#include "EGL/eglext.h"
#include <EGL/eglext.h>
#include <QOpenGLContext>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
QT_BEGIN_NAMESPACE
QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config)
: QEGLPlatformContext(format, share, display, &config), m_eglSurface(surface)
class QWinRTEGLContextPrivate
{
public:
QSurfaceFormat format;
EGLDisplay eglDisplay;
EGLConfig eglConfig;
EGLContext eglContext;
QHash<QPlatformSurface *, EGLSurface> surfaceForWindow;
};
QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
: d_ptr(new QWinRTEGLContextPrivate)
{
Q_D(QWinRTEGLContext);
d->format = context->format();
d->format.setRenderableType(QSurfaceFormat::OpenGLES);
}
void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface)
QWinRTEGLContext::~QWinRTEGLContext()
{
#ifdef Q_OS_WINPHONE
const QSize size = surface->surface()->size();
eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface),
0, 0, size.width(), size.height());
#else
eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface));
#endif
Q_D(QWinRTEGLContext);
foreach (const EGLSurface &surface, d->surfaceForWindow)
eglDestroySurface(d->eglDisplay, surface);
if (d->eglContext != EGL_NO_CONTEXT)
eglDestroyContext(d->eglDisplay, d->eglContext);
if (d->eglDisplay != EGL_NO_DISPLAY)
eglTerminate(d->eglDisplay);
}
EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
void QWinRTEGLContext::initialize()
{
if (surface->surface()->surfaceClass() == QSurface::Window) {
// All windows use the same surface
return m_eglSurface;
} else {
// TODO: return EGL surfaces for offscreen surfaces
qWarning("This plugin does not support offscreen surfaces.");
return EGL_NO_SURFACE;
Q_D(QWinRTEGLContext);
eglBindAPI(EGL_OPENGL_ES_API);
d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (d->eglDisplay == EGL_NO_DISPLAY)
qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
if (!eglInitialize(d->eglDisplay, nullptr, nullptr))
qCritical("Failed to initialize EGL: 0x%x", eglGetError());
d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->format);
const EGLint flags = d->format.testOption(QSurfaceFormat::DebugContext)
? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0;
const EGLint attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, d->format.majorVersion(),
EGL_CONTEXT_MINOR_VERSION_KHR, d->format.minorVersion(),
EGL_CONTEXT_FLAGS_KHR, flags,
EGL_NONE
};
d->eglContext = eglCreateContext(d->eglDisplay, d->eglConfig, nullptr, attributes);
if (d->eglContext == EGL_NO_CONTEXT) {
qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError());
return;
}
}
bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface)
{
Q_D(QWinRTEGLContext);
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
EGLSurface surface = d->surfaceForWindow.value(windowSurface);
if (surface == EGL_NO_SURFACE) {
QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() {
surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig,
reinterpret_cast<EGLNativeWindowType>(window->winId()),
nullptr);
if (surface == EGL_NO_SURFACE) {
qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
return E_FAIL;
}
return S_OK;
});
if (FAILED(hr))
return false;
d->surfaceForWindow.insert(windowSurface, surface);
}
const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext);
if (!ok) {
qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
return false;
}
eglSwapInterval(d->eglDisplay, d->format.swapInterval());
return true;
}
void QWinRTEGLContext::doneCurrent()
{
Q_D(const QWinRTEGLContext);
const bool ok = eglMakeCurrent(d->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
}
void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface)
{
Q_D(QWinRTEGLContext);
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface));
}
QSurfaceFormat QWinRTEGLContext::format() const
{
Q_D(const QWinRTEGLContext);
return d->format;
}
QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
{
static QHash<QByteArray, QFunctionPointer> standardFuncs;
@ -221,7 +314,7 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
if (i != standardFuncs.end())
return i.value();
return QEGLPlatformContext::getProcAddress(procName);
return eglGetProcAddress(procName.constData());
}
QT_END_NAMESPACE

View File

@ -37,23 +37,29 @@
#ifndef QWINDOWSEGLCONTEXT_H
#define QWINDOWSEGLCONTEXT_H
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <qpa/qplatformopenglcontext.h>
QT_BEGIN_NAMESPACE
class QWinRTEGLContext : public QEGLPlatformContext
class QWinRTEGLContextPrivate;
class QWinRTEGLContext : public QPlatformOpenGLContext
{
public:
explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config);
explicit QWinRTEGLContext(QOpenGLContext *context);
~QWinRTEGLContext();
void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE;
bool makeCurrent(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
void doneCurrent() Q_DECL_OVERRIDE;
void swapBuffers(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
QSurfaceFormat format() const Q_DECL_OVERRIDE;
QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
protected:
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
private:
EGLSurface m_eglSurface;
QScopedPointer<QWinRTEGLContextPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTEGLContext)
};
QT_END_NAMESPACE

View File

@ -182,135 +182,6 @@ void QWinRTInputContext::hideInputPanel()
qErrnoWarning(hr, "Failed to hide input panel.");
}
#else // Q_OS_WINPHONE
// IRawElementProviderSimple
HRESULT QWinRTInputContext::get_ProviderOptions(ProviderOptions *retVal)
{
*retVal = ProviderOptions_ServerSideProvider|ProviderOptions_UseComThreading;
return S_OK;
}
HRESULT QWinRTInputContext::GetPatternProvider(PATTERNID id, IUnknown **retVal)
{
switch (id) {
case 10002: //UIA_ValuePatternId
return QueryInterface(__uuidof(IValueProvider), (void**)retVal);
break;
case 10014: //UIA_TextPatternId:
return QueryInterface(__uuidof(ITextProvider), (void**)retVal);
case 10029: //UIA_TextChildPatternId:
*retVal = nullptr;
break;
default:
qWarning("Unhandled pattern ID: %d", id);
break;
}
return S_OK;
}
HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal)
{
switch (idProp) {
case 30003: //UIA_ControlTypePropertyId
retVal->vt = VT_I4;
retVal->lVal = 50025; //UIA_CustomControlTypeId
break;
case 30008: //UIA_IsKeyboardFocusablePropertyId
case 30009: //UIA_HasKeyboardFocusPropertyId
// These are probably never actually called
case 30016: //UIA_IsControlElementPropertyId
case 30017: //UIA_IsContentElementPropertyId
retVal->vt = VT_BOOL;
retVal->boolVal = VARIANT_TRUE;
break;
case 30019: //UIA_IsPasswordPropertyId
retVal->vt = VT_BOOL;
retVal->boolVal = VARIANT_FALSE;
break;
case 30020: //UIA_NativeWindowHandlePropertyId
retVal->vt = VT_PTR;
retVal->punkVal = m_screen->coreWindow();
break;
}
return S_OK;
}
HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal)
{
// Return the window's element provider
IInspectable *hostProvider;
HRESULT hr = m_screen->coreWindow()->get_AutomationHostProvider(&hostProvider);
if (SUCCEEDED(hr)) {
hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal));
hostProvider->Release();
}
return hr;
}
// ITextProvider
HRESULT QWinRTInputContext::GetSelection(SAFEARRAY **)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
HRESULT QWinRTInputContext::GetVisibleRanges(SAFEARRAY **)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
HRESULT QWinRTInputContext::RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
HRESULT QWinRTInputContext::RangeFromPoint(UiaPoint, ITextRangeProvider **)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
HRESULT QWinRTInputContext::get_DocumentRange(ITextRangeProvider **)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
HRESULT QWinRTInputContext::get_SupportedTextSelection(SupportedTextSelection *)
{
// To be useful, requires listening to the focus object for a selection change and raising an event
return S_OK;
}
// IValueProvider
HRESULT QWinRTInputContext::SetValue(LPCWSTR)
{
// To be useful, requires listening to the focus object for a value change and raising an event
// May be useful for inputPanel autocomplete, etc.
return S_OK;
}
HRESULT QWinRTInputContext::get_Value(BSTR *)
{
// To be useful, requires listening to the focus object for a value change and raising an event
// May be useful for inputPanel autocomplete, etc.
return S_OK;
}
HRESULT QWinRTInputContext::get_IsReadOnly(BOOL *isReadOnly)
{
// isReadOnly dictates keyboard opening behavior when view is tapped.
// We need to decide if the user tapped within a control which is about to receive focus...
// Since this isn't possible (this function gets called before we receive the touch event),
// the most platform-aligned option is to show the keyboard if an editable item has focus,
// and close the keyboard if it is already open.
*isReadOnly = m_isInputPanelVisible || !inputMethodAccepted();
return S_OK;
}
#endif // !Q_OS_WINPHONE
#endif // Q_OS_WINPHONE
QT_END_NAMESPACE

View File

@ -41,9 +41,6 @@
#include <QtCore/QRectF>
#include <wrl.h>
#ifndef Q_OS_WINPHONE
# include <UIAutomationCore.h>
#endif
namespace ABI {
namespace Windows {
@ -63,11 +60,6 @@ QT_BEGIN_NAMESPACE
class QWinRTScreen;
class QWinRTInputContext : public QPlatformInputContext
#ifndef Q_OS_WINPHONE
, public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
IRawElementProviderSimple, ITextProvider, IValueProvider>
#endif // !Q_OS_WINPHONE
{
public:
explicit QWinRTInputContext(QWinRTScreen *);
@ -79,26 +71,7 @@ public:
#ifdef Q_OS_WINPHONE
void showInputPanel();
void hideInputPanel();
#else // Q_OS_WINPHONE
// IRawElementProviderSimple
HRESULT __stdcall get_ProviderOptions(ProviderOptions *retVal);
HRESULT __stdcall GetPatternProvider(PATTERNID, IUnknown **);
HRESULT __stdcall GetPropertyValue(PROPERTYID idProp, VARIANT *retVal);
HRESULT __stdcall get_HostRawElementProvider(IRawElementProviderSimple **retVal);
// ITextProvider
HRESULT __stdcall GetSelection(SAFEARRAY **);
HRESULT __stdcall GetVisibleRanges(SAFEARRAY **);
HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **);
HRESULT __stdcall RangeFromPoint(UiaPoint, ITextRangeProvider **);
HRESULT __stdcall get_DocumentRange(ITextRangeProvider **);
HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *);
// IValueProvider
HRESULT __stdcall SetValue(LPCWSTR);
HRESULT __stdcall get_Value(BSTR *);
HRESULT __stdcall get_IsReadOnly(BOOL *);
#endif // !Q_OS_WINPHONE
#endif
private:
HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *,

View File

@ -45,37 +45,138 @@
#include "qwinrtfontdatabase.h"
#include "qwinrttheme.h"
#include <QtCore/QCoreApplication>
#include <QtGui/QSurface>
#include <QtGui/QOpenGLContext>
#include <qfunctions_winrt.h>
#include <functional>
#include <wrl.h>
#include <windows.ui.xaml.h>
#include <windows.applicationmodel.h>
#include <windows.applicationmodel.core.h>
#include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h>
#include <Windows.ApplicationModel.core.h>
#include <windows.graphics.display.h>
#ifdef Q_OS_WINPHONE
# include <windows.phone.ui.input.h>
#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::ApplicationModel::Core;
#ifdef Q_OS_WINPHONE
using namespace ABI::Windows::Phone::UI::Input;
#endif
typedef IEventHandler<IInspectable *> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
#ifdef Q_OS_WINPHONE
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
#endif
QT_BEGIN_NAMESPACE
QWinRTIntegration::QWinRTIntegration()
: m_success(false)
, m_fontDatabase(new QWinRTFontDatabase)
, m_services(new QWinRTServices)
{
m_screen = new QWinRTScreen;
screenAdded(m_screen);
typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#ifdef Q_OS_WINPHONE
typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#endif
m_success = true;
class QWinRTIntegrationPrivate
{
public:
QPlatformFontDatabase *fontDatabase;
QPlatformServices *platformServices;
QWinRTScreen *mainScreen;
QScopedPointer<QWinRTInputContext> inputContext;
ComPtr<ICoreApplication> application;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
#ifdef Q_OS_WINPHONE
ComPtr<IHardwareButtonsStatics> hardwareButtons;
QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
#endif
};
QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
{
Q_D(QWinRTIntegration);
d->fontDatabase = new QWinRTFontDatabase;
HRESULT hr;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&d->application));
Q_ASSERT_SUCCEEDED(hr);
hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTIntegration::onSuspended).Get(),
&d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTIntegration::onResume).Get(),
&d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
IID_PPV_ARGS(&d->hardwareButtons));
Q_ASSERT_SUCCEEDED(hr);
hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
&d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
ComPtr<Xaml::IWindowStatics> windowStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Window).Get(),
IID_PPV_ARGS(&windowStatics));
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IWindow> window;
hr = windowStatics->get_Current(&window);
Q_ASSERT_SUCCEEDED(hr);
hr = window->Activate();
Q_ASSERT_SUCCEEDED(hr);
d->mainScreen = new QWinRTScreen(window.Get());
d->inputContext.reset(new QWinRTInputContext(d->mainScreen));
screenAdded(d->mainScreen);
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
}
QWinRTIntegration::~QWinRTIntegration()
{
Q_D(QWinRTIntegration);
HRESULT hr;
#ifdef Q_OS_WINPHONE
for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
hr = (d->hardwareButtons.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
#endif
for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i) {
hr = (d->application.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
destroyScreen(d->mainScreen);
Windows::Foundation::Uninitialize();
}
bool QWinRTIntegration::succeeded() const
{
Q_D(const QWinRTIntegration);
return d->mainScreen;
}
QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const
{
return new QWinRTEventDispatcher;
@ -112,28 +213,31 @@ QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *wi
QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
QWinRTScreen *screen = static_cast<QWinRTScreen *>(context->screen()->handle());
return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface(), screen->eglConfig());
return new QWinRTEGLContext(context);
}
QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const
{
return m_fontDatabase;
Q_D(const QWinRTIntegration);
return d->fontDatabase;
}
QPlatformInputContext *QWinRTIntegration::inputContext() const
{
return m_screen->inputContext();
Q_D(const QWinRTIntegration);
return d->inputContext.data();
}
QPlatformServices *QWinRTIntegration::services() const
{
return m_services;
Q_D(const QWinRTIntegration);
return d->platformServices;
}
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
return m_screen->keyboardModifiers();
Q_D(const QWinRTIntegration);
return d->mainScreen->keyboardModifiers();
}
QStringList QWinRTIntegration::themeNames() const
@ -149,4 +253,45 @@ name) const
return 0;
}
// System-level integration points
#ifdef Q_OS_WINPHONE
HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
Q_D(QWinRTIntegration);
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
backRelease.setAccepted(false);
QWindow *window = d->mainScreen->topWindow();
QObject *receiver = window ? static_cast<QObject *>(window)
: static_cast<QObject *>(QCoreApplication::instance());
// If the event is ignored, the app go to the background
QCoreApplication::sendEvent(receiver, &backPress);
QCoreApplication::sendEvent(receiver, &backRelease);
args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
return S_OK;
}
#endif // Q_OS_WINPHONE
HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
{
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
QWindowSystemInterface::flushWindowSystemEvents();
return S_OK;
}
HRESULT QWinRTIntegration::onResume(IInspectable *, IInspectable *)
{
// First the system invokes onResume and then changes
// the visibility of the screen to be active.
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
return S_OK;
}
QT_END_NAMESPACE

View File

@ -39,11 +39,33 @@
#include <qpa/qplatformintegration.h>
namespace ABI {
namespace Windows {
namespace ApplicationModel {
struct ISuspendingEventArgs;
}
namespace Foundation {
struct IAsyncAction;
}
#ifdef Q_OS_WINPHONE
namespace Phone {
namespace UI {
namespace Input {
struct IBackPressedEventArgs;
}
}
}
#endif
}
}
struct IAsyncInfo;
struct IInspectable;
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
class QWinRTScreen;
class QWinRTIntegrationPrivate;
class QWinRTIntegration : public QPlatformIntegration
{
private:
@ -53,10 +75,12 @@ public:
static QWinRTIntegration *create()
{
QWinRTIntegration *integration = new QWinRTIntegration;
return integration->m_success ? integration : 0;
QScopedPointer<QWinRTIntegration> integration(new QWinRTIntegration);
return integration->succeeded() ? integration.take() : nullptr;
}
bool succeeded() const;
bool hasCapability(QPlatformIntegration::Capability cap) const;
QVariant styleHint(StyleHint hint) const;
@ -71,11 +95,16 @@ public:
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
private:
bool m_success;
QWinRTScreen *m_screen;
QPlatformFontDatabase *m_fontDatabase;
QPlatformServices *m_services;
#ifdef Q_OS_WINPHONE
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
#endif
HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
HRESULT onResume(IInspectable *, IInspectable *);
QScopedPointer<QWinRTIntegrationPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTIntegration)
};
QT_END_NAMESPACE

View File

@ -36,26 +36,18 @@
#include "qwinrtscreen.h"
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/eglext.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#ifndef Q_OS_WINPHONE
#include <dxgi1_3.h>
#endif
#include "qwinrtbackingstore.h"
#include "qwinrtinputcontext.h"
#include "qwinrtcursor.h"
#include "qwinrteglcontext.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QGuiApplication>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qt_windows.h>
#include <QtCore/qfunctions_winrt.h>
#include <functional>
#include <wrl.h>
#include <windows.system.h>
#include <Windows.Applicationmodel.h>
@ -64,12 +56,10 @@
#include <windows.ui.h>
#include <windows.ui.core.h>
#include <windows.ui.input.h>
#include <windows.ui.xaml.h>
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
#include <windows.foundation.h>
#ifdef Q_OS_WINPHONE
#include <windows.phone.ui.input.h>
#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@ -77,17 +67,13 @@ using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System;
using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::Input;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Devices::Input;
using namespace ABI::Windows::Graphics::Display;
#ifdef Q_OS_WINPHONE
using namespace ABI::Windows::Phone::UI::Input;
#endif
typedef IEventHandler<IInspectable*> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs*> SuspendHandler;
typedef ITypedEventHandler<CoreWindow*, WindowActivatedEventArgs*> ActivatedHandler;
typedef ITypedEventHandler<CoreWindow*, CoreWindowEventArgs*> ClosedHandler;
typedef ITypedEventHandler<CoreWindow*, CharacterReceivedEventArgs*> CharacterReceivedHandler;
@ -96,11 +82,7 @@ typedef ITypedEventHandler<CoreWindow*, KeyEventArgs*> KeyHandler;
typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
#ifdef Q_OS_WINPHONE
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
#endif
QT_BEGIN_NAMESPACE
@ -419,33 +401,23 @@ static inline Qt::Key qKeyFromCode(quint32 code, int mods)
return static_cast<Qt::Key>(code & 0xff);
}
typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken);
uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#ifdef Q_OS_WINPHONE
typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#endif
class QWinRTScreenPrivate
{
public:
ComPtr<ICoreApplication> application;
QTouchDevice *touchDevice;
ComPtr<ICoreWindow> coreWindow;
ComPtr<Xaml::IDependencyObject> canvas;
ComPtr<IApplicationView> view;
ComPtr<IDisplayInformation> displayInformation;
#ifdef Q_OS_WINPHONE
ComPtr<IHardwareButtonsStatics> hardwareButtons;
#endif
QScopedPointer<QWinRTCursor> cursor;
#ifdef Q_OS_WINPHONE
QScopedPointer<QWinRTInputContext> inputContext;
#else
ComPtr<QWinRTInputContext> inputContext;
#endif
QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
QSizeF logicalSize;
QSurfaceFormat surfaceFormat;
@ -458,68 +430,30 @@ public:
#ifndef Q_OS_WINPHONE
QHash<quint32, QPair<Qt::Key, QString>> activeKeys;
#endif
QTouchDevice *touchDevice;
QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
EGLDisplay eglDisplay;
EGLSurface eglSurface;
EGLConfig eglConfig;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
#ifdef Q_OS_WINPHONE
QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
#endif
};
QWinRTScreen::QWinRTScreen()
// To be called from the XAML thread
QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
: d_ptr(new QWinRTScreenPrivate)
{
Q_D(QWinRTScreen);
d->orientation = Qt::PrimaryOrientation;
d->touchDevice = Q_NULLPTR;
d->eglDisplay = EGL_NO_DISPLAY;
// Obtain the WinRT Application, view, and window
HRESULT hr;
hr = RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&d->application));
Q_ASSERT_SUCCEEDED(hr);
hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<ICoreApplicationView> view;
hr = d->application->GetCurrentView(&view);
Q_ASSERT_SUCCEEDED(hr);
hr = view->get_CoreWindow(&d->coreWindow);
hr = xamlWindow->get_CoreWindow(&d->coreWindow);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->Activate();
Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
d->inputContext.reset(new QWinRTInputContext(this));
#else
d->inputContext = Make<QWinRTInputContext>(this);
#endif
Rect rect;
hr = d->coreWindow->get_Bounds(&rect);
Q_ASSERT_SUCCEEDED(hr);
d->logicalSize = QSizeF(rect.Width, rect.Height);
d->surfaceFormat.setAlphaBufferSize(0);
d->surfaceFormat.setRedBufferSize(8);
d->surfaceFormat.setGreenBufferSize(8);
d->surfaceFormat.setBlueBufferSize(8);
d->surfaceFormat.setDepthBufferSize(24);
d->surfaceFormat.setStencilBufferSize(8);
d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
d->surfaceFormat.setSamples(1);
d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
@ -538,24 +472,14 @@ QWinRTScreen::QWinRTScreen()
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
Q_ASSERT_SUCCEEDED(hr);
#ifndef Q_OS_WINPHONE
hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
Q_ASSERT_SUCCEEDED(hr);
#endif
hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &d->windowTokens[&ICoreWindow::remove_AutomationProviderRequested]);
Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), IID_PPV_ARGS(&d->hardwareButtons));
Q_ASSERT_SUCCEEDED(hr);
hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
// Orientation handling
ComPtr<IDisplayInformationStatics> displayInformationStatics;
@ -583,45 +507,34 @@ QWinRTScreen::QWinRTScreen()
d->orientation = d->nativeOrientation;
onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (d->eglDisplay == EGL_NO_DISPLAY)
qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
ComPtr<IApplicationViewStatics2> applicationViewStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
IID_PPV_ARGS(&applicationViewStatics));
RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
if (!eglInitialize(d->eglDisplay, NULL, NULL))
qCritical("Failed to initialize EGL: 0x%x", eglGetError());
hr = applicationViewStatics->GetForCurrentView(&d->view);
RETURN_VOID_IF_FAILED("Could not access currentView");
// Check that the device properly supports depth/stencil rendering, and disable them if not
ComPtr<ID3D11Device> d3dDevice;
const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
if (ok && d3dDevice) {
ComPtr<IDXGIDevice> dxgiDevice;
hr = d3dDevice.As(&dxgiDevice);
if (SUCCEEDED(hr)) {
ComPtr<IDXGIAdapter> dxgiAdapter;
hr = dxgiDevice->GetAdapter(&dxgiAdapter);
if (SUCCEEDED(hr)) {
ComPtr<IDXGIAdapter2> dxgiAdapter2;
hr = dxgiAdapter.As(&dxgiAdapter2);
if (SUCCEEDED(hr)) {
DXGI_ADAPTER_DESC2 desc;
hr = dxgiAdapter2->GetDesc2(&desc);
if (SUCCEEDED(hr)) {
// The following GPUs do not render properly with depth/stencil
if ((desc.VendorId == 0x4d4f4351 && desc.DeviceId == 0x32303032)) { // Qualcomm Adreno 225
d->surfaceFormat.setDepthBufferSize(-1);
d->surfaceFormat.setStencilBufferSize(-1);
}
}
}
}
}
}
// Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added
ComPtr<Xaml::Controls::ICanvas> canvas;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IFrameworkElement> frameworkElement;
hr = canvas.As(&frameworkElement);
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Width(d->logicalSize.width());
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Height(d->logicalSize.height());
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IUIElement> uiElement;
hr = canvas.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
hr = xamlWindow->put_Content(uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
hr = canvas.As(&d->canvas);
Q_ASSERT_SUCCEEDED(hr);
d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->surfaceFormat);
d->surfaceFormat = q_glFormatFromConfig(d->eglDisplay, d->eglConfig, d->surfaceFormat);
d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), NULL);
if (d->eglSurface == EGL_NO_SURFACE)
qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
d->cursor.reset(new QWinRTCursor);
}
QWinRTScreen::~QWinRTScreen()
@ -629,16 +542,20 @@ QWinRTScreen::~QWinRTScreen()
Q_D(QWinRTScreen);
// Unregister callbacks
for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i)
(d->application.Get()->*i.key())(i.value());
for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i)
(d->coreWindow.Get()->*i.key())(i.value());
for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i)
(d->displayInformation.Get()->*i.key())(i.value());
#ifdef Q_OS_WINPHONE
for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i)
(d->hardwareButtons.Get()->*i.key())(i.value());
#endif
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i) {
hr = (d->coreWindow.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i) {
hr = (d->displayInformation.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
return hr;
});
RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks");
}
QRect QWinRTScreen::geometry() const
@ -657,12 +574,6 @@ QImage::Format QWinRTScreen::format() const
return QImage::Format_ARGB32_Premultiplied;
}
QSurfaceFormat QWinRTScreen::surfaceFormat() const
{
Q_D(const QWinRTScreen);
return d->surfaceFormat;
}
QSizeF QWinRTScreen::physicalSize() const
{
Q_D(const QWinRTScreen);
@ -682,21 +593,9 @@ qreal QWinRTScreen::scaleFactor() const
return d->scaleFactor;
}
QWinRTInputContext *QWinRTScreen::inputContext() const
{
Q_D(const QWinRTScreen);
#ifdef Q_OS_WINPHONE
return d->inputContext.data();
#else
return d->inputContext.Get();
#endif
}
QPlatformCursor *QWinRTScreen::cursor() const
{
Q_D(const QWinRTScreen);
if (!d->cursor)
const_cast<QWinRTScreenPrivate *>(d)->cursor.reset(new QWinRTCursor);
return d->cursor.data();
}
@ -744,22 +643,10 @@ ICoreWindow *QWinRTScreen::coreWindow() const
return d->coreWindow.Get();
}
EGLDisplay QWinRTScreen::eglDisplay() const
Xaml::IDependencyObject *QWinRTScreen::canvas() const
{
Q_D(const QWinRTScreen);
return d->eglDisplay;
}
EGLSurface QWinRTScreen::eglSurface() const
{
Q_D(const QWinRTScreen);
return d->eglSurface;
}
EGLConfig QWinRTScreen::eglConfig() const
{
Q_D(const QWinRTScreen);
return d->eglConfig;
return d->canvas.Get();
}
QWindow *QWinRTScreen::topWindow() const
@ -809,6 +696,20 @@ void QWinRTScreen::lower(QWindow *window)
handleExpose();
}
void QWinRTScreen::updateWindowTitle()
{
Q_D(QWinRTScreen);
QWindow *window = topWindow();
if (!window)
return;
const QString title = window->title();
HStringReference titleRef(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
HRESULT hr = d->view->put_Title(titleRef.Get());
RETURN_VOID_IF_FAILED("Unable to set window title");
}
void QWinRTScreen::handleExpose()
{
Q_D(QWinRTScreen);
@ -1055,17 +956,6 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
return S_OK;
}
HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
{
#ifndef Q_OS_WINPHONE
Q_D(const QWinRTScreen);
args->put_AutomationProvider(d->inputContext.Get());
#else
Q_UNUSED(args)
#endif
return S_OK;
}
HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *)
{
Q_D(QWinRTScreen);
@ -1075,18 +965,14 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
hr = d->coreWindow->get_Bounds(&size);
RETURN_OK_IF_FAILED("Failed to get window bounds");
QSizeF logicalSize = QSizeF(size.Width, size.Height);
#ifndef Q_OS_WINPHONE // This handler is called from orientation changed, in which case we should always update the size
if (d->logicalSize == logicalSize)
return S_OK;
#endif
d->logicalSize = logicalSize;
if (d->eglDisplay) {
const QRect newGeometry = geometry();
QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
}
return S_OK;
}
@ -1110,31 +996,6 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args
return S_OK;
}
HRESULT QWinRTScreen::onSuspended(IInspectable *, ISuspendingEventArgs *)
{
#ifndef Q_OS_WINPHONE
Q_D(QWinRTScreen);
ComPtr<ID3D11Device> d3dDevice;
const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
if (ok && d3dDevice) {
ComPtr<IDXGIDevice3> dxgiDevice;
if (SUCCEEDED(d3dDevice.As(&dxgiDevice)))
dxgiDevice->Trim();
}
#endif
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
QWindowSystemInterface::flushWindowSystemEvents();
return S_OK;
}
HRESULT QWinRTScreen::onResume(IInspectable *, IInspectable *)
{
// First the system invokes onResume and then changes
// the visibility of the screen to be active.
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
return S_OK;
}
HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
{
foreach (QWindow *w, QGuiApplication::topLevelWindows())
@ -1165,10 +1026,6 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *
d->orientation = newOrientation;
QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
}
#ifdef Q_OS_WINPHONE // The size changed handler is ignored in favor of this callback
onSizeChanged(Q_NULLPTR, Q_NULLPTR);
#endif
return S_OK;
}
@ -1205,27 +1062,4 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
return S_OK;
}
#ifdef Q_OS_WINPHONE
HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
Q_D(QWinRTScreen);
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
backRelease.setAccepted(false);
QObject *receiver = d->visibleWindows.isEmpty()
? static_cast<QObject *>(QGuiApplication::instance())
: static_cast<QObject *>(d->visibleWindows.first());
// If the event is ignored, the app will suspend
QGuiApplication::sendEvent(receiver, &backPress);
QGuiApplication::sendEvent(receiver, &backRelease);
args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
return S_OK;
}
#endif // Q_OS_WINPHONE
QT_END_NAMESPACE

View File

@ -40,8 +40,6 @@
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <EGL/egl.h>
namespace ABI {
namespace Windows {
namespace ApplicationModel {
@ -59,21 +57,16 @@ namespace ABI {
struct IWindowActivatedEventArgs;
struct IWindowSizeChangedEventArgs;
}
namespace Xaml {
struct IDependencyObject;
struct IWindow;
}
}
namespace Graphics {
namespace Display {
struct IDisplayInformation;
}
}
#ifdef Q_OS_WINPHONE
namespace Phone {
namespace UI {
namespace Input {
struct IBackPressedEventArgs;
}
}
}
#endif
}
}
struct IInspectable;
@ -81,23 +74,20 @@ struct IInspectable;
QT_BEGIN_NAMESPACE
class QTouchDevice;
class QWinRTEGLContext;
class QWinRTCursor;
class QWinRTInputContext;
class QWinRTScreenPrivate;
class QWinRTScreen : public QPlatformScreen
{
public:
explicit QWinRTScreen();
explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow);
~QWinRTScreen();
QRect geometry() const;
int depth() const;
QImage::Format format() const;
QSurfaceFormat surfaceFormat() const;
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
qreal scaleFactor() const;
QWinRTInputContext *inputContext() const;
QPlatformCursor *cursor() const;
Qt::KeyboardModifiers keyboardModifiers() const;
@ -110,10 +100,10 @@ public:
void raise(QWindow *window);
void lower(QWindow *window);
void updateWindowTitle();
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
EGLDisplay eglDisplay() const; // To opengl context
EGLSurface eglSurface() const; // To window
EGLConfig eglConfig() const;
ABI::Windows::UI::Xaml::IDependencyObject *canvas() const;
private:
void handleExpose();
@ -127,20 +117,13 @@ private:
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *);
HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
HRESULT onResume(IInspectable *, IInspectable *);
HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *);
HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *);
HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *);
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
#ifdef Q_OS_WINPHONE
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
#endif
QScopedPointer<QWinRTScreenPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTScreen)
};

View File

@ -36,47 +36,138 @@
#include "qwinrtwindow.h"
#include "qwinrtscreen.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformscreen.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLContext>
#include <EGL/egl.h>
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/eglext.h>
#include <qfunctions_winrt.h>
#include <windows.ui.viewmanagement.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLContext>
#include <QtGui/QWindow>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <functional>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
#include <windows.ui.xaml.h>
#include <windows.ui.xaml.controls.h>
#include <windows.ui.viewmanagement.h>
using namespace ABI::Windows::UI::ViewManagement;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::UI;
QT_BEGIN_NAMESPACE
class QWinRTWindowPrivate
{
public:
QWinRTScreen *screen;
QSurfaceFormat surfaceFormat;
QString windowTitle;
ComPtr<Xaml::Controls::ISwapChainPanel> swapChainPanel;
};
QWinRTWindow::QWinRTWindow(QWindow *window)
: QPlatformWindow(window)
, m_screen(static_cast<QWinRTScreen*>(screen()))
, d_ptr(new QWinRTWindowPrivate)
{
Q_D(QWinRTWindow);
d->screen = static_cast<QWinRTScreen *>(screen());
setWindowFlags(window->flags());
setWindowState(window->windowState());
setWindowTitle(window->title());
handleContentOrientationChange(window->contentOrientation());
d->surfaceFormat.setAlphaBufferSize(0);
d->surfaceFormat.setRedBufferSize(8);
d->surfaceFormat.setGreenBufferSize(8);
d->surfaceFormat.setBlueBufferSize(8);
d->surfaceFormat.setDepthBufferSize(24);
d->surfaceFormat.setStencilBufferSize(8);
d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
d->surfaceFormat.setSamples(1);
d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
// Create a new swapchain and place it inside the canvas
HRESULT hr;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
&d->swapChainPanel);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IUIElement> uiElement;
hr = d->swapChainPanel.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
ComPtr<Xaml::Controls::IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVector<Xaml::UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
hr = children->Append(uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
setGeometry(window->geometry());
}
QWinRTWindow::~QWinRTWindow()
{
m_screen->removeWindow(window());
Q_D(QWinRTWindow);
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
HRESULT hr;
ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
ComPtr<Xaml::Controls::IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVector<Xaml::UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IUIElement> uiElement;
hr = d->swapChainPanel.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
quint32 index;
boolean found;
hr = children->IndexOf(uiElement.Get(), &index, &found);
Q_ASSERT_SUCCEEDED(hr);
if (found) {
hr = children->RemoveAt(index);
Q_ASSERT_SUCCEEDED(hr);
}
return S_OK;
});
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
}
QSurfaceFormat QWinRTWindow::format() const
{
return m_screen->surfaceFormat();
Q_D(const QWinRTWindow);
return d->surfaceFormat;
}
bool QWinRTWindow::isActive() const
{
return m_screen->topWindow() == window();
Q_D(const QWinRTWindow);
return d->screen->topWindow() == window();
}
bool QWinRTWindow::isExposed() const
@ -87,55 +178,70 @@ bool QWinRTWindow::isExposed() const
void QWinRTWindow::setGeometry(const QRect &rect)
{
Q_D(QWinRTWindow);
if (window()->isTopLevel()) {
QPlatformWindow::setGeometry(m_screen->geometry());
QPlatformWindow::setGeometry(d->screen->geometry());
QWindowSystemInterface::handleGeometryChange(window(), geometry());
} else {
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
}
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
ComPtr<Xaml::IFrameworkElement> frameworkElement;
hr = d->swapChainPanel.As(&frameworkElement);
Q_ASSERT_SUCCEEDED(hr);
const QSizeF size = QSizeF(geometry().size()) / d->screen->scaleFactor();
hr = frameworkElement->put_Width(size.width());
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Height(size.height());
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
}
void QWinRTWindow::setVisible(bool visible)
{
Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
if (visible)
m_screen->addWindow(window());
d->screen->addWindow(window());
else
m_screen->removeWindow(window());
d->screen->removeWindow(window());
}
void QWinRTWindow::setWindowTitle(const QString &title)
{
ComPtr<IApplicationViewStatics2> statics;
HRESULT hr;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
IID_PPV_ARGS(&statics));
RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
ComPtr<IApplicationView> view;
hr = statics->GetForCurrentView(&view);
RETURN_VOID_IF_FAILED("Could not access currentView");
HStringReference str(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
hr = view->put_Title(str.Get());
RETURN_VOID_IF_FAILED("Unable to set window title");
Q_D(QWinRTWindow);
d->windowTitle = title;
d->screen->updateWindowTitle();
}
void QWinRTWindow::raise()
{
Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
m_screen->raise(window());
d->screen->raise(window());
}
void QWinRTWindow::lower()
{
Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
m_screen->lower(window());
d->screen->lower(window());
}
WId QWinRTWindow::winId() const
{
Q_D(const QWinRTWindow);
return WId(d->swapChainPanel.Get());
}
qreal QWinRTWindow::devicePixelRatio() const

View File

@ -42,8 +42,7 @@
QT_BEGIN_NAMESPACE
class QWinRTScreen;
class QWinRTWindowPrivate;
class QWinRTWindow : public QPlatformWindow
{
public:
@ -59,10 +58,13 @@ public:
void raise();
void lower();
WId winId() const Q_DECL_OVERRIDE;
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
private:
QWinRTScreen *m_screen;
QScopedPointer<QWinRTWindowPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTWindow)
};
QT_END_NAMESPACE

View File

@ -237,7 +237,11 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
QVariant::Type type;
switch (mysqltype) {
case FIELD_TYPE_TINY :
type = static_cast<QVariant::Type>((flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char);
break;
case FIELD_TYPE_SHORT :
type = static_cast<QVariant::Type>((flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short);
break;
case FIELD_TYPE_LONG :
case FIELD_TYPE_INT24 :
type = (flags & UNSIGNED_FLAG) ? QVariant::UInt : QVariant::Int;
@ -316,14 +320,12 @@ static bool qIsBlob(int t)
static bool qIsInteger(int t)
{
return t == MYSQL_TYPE_TINY
|| t == MYSQL_TYPE_SHORT
|| t == MYSQL_TYPE_LONG
|| t == MYSQL_TYPE_LONGLONG
|| t == MYSQL_TYPE_INT24;
return t == QMetaType::Char || t == QMetaType::UChar
|| t == QMetaType::Short || t == QMetaType::UShort
|| t == QMetaType::Int || t == QMetaType::UInt
|| t == QMetaType::LongLong || t == QMetaType::ULongLong;
}
void QMYSQLResultPrivate::bindBlobs()
{
int i;
@ -371,14 +373,9 @@ bool QMYSQLResultPrivate::bindInValues()
// after mysql_stmt_exec() in QMYSQLResult::exec()
fieldInfo->length = 0;
hasBlobs = true;
} else if (qIsInteger(f.type)) {
fieldInfo->length = 8;
} else {
// fieldInfo->length specifies the display width, which may be too
// small to hold valid integer values (see
// http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html ), so
// always use the MAX_BIGINT_WIDTH for integer types
if (qIsInteger(fieldInfo->type)) {
fieldInfo->length = MAX_BIGINT_WIDTH;
}
fieldInfo->type = MYSQL_TYPE_STRING;
}
bind = &inBinds[i];
@ -598,6 +595,9 @@ QVariant QMYSQLResult::data(int field)
if (f.nullIndicator)
return QVariant(f.type);
if (qIsInteger(f.type))
return QVariant(f.type, f.outField);
if (f.type != QVariant::ByteArray)
val = toUnicode(d->driver->d_func()->tc, f.outField, f.bufLength);
} else {
@ -605,18 +605,24 @@ QVariant QMYSQLResult::data(int field)
// NULL value
return QVariant(f.type);
}
fieldLength = mysql_fetch_lengths(d->result)[field];
if (f.type != QVariant::ByteArray)
val = toUnicode(d->driver->d_func()->tc, d->row[field], fieldLength);
}
switch(f.type) {
switch (static_cast<int>(f.type)) {
case QVariant::LongLong:
return QVariant(val.toLongLong());
case QVariant::ULongLong:
return QVariant(val.toULongLong());
case QMetaType::Char:
case QMetaType::Short:
case QVariant::Int:
return QVariant(val.toInt());
case QMetaType::UChar:
case QMetaType::UShort:
case QVariant::UInt:
return QVariant(val.toUInt());
case QVariant::Double: {

View File

@ -40,7 +40,6 @@
QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
class QDocDatabase;

View File

@ -157,11 +157,11 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
synopsis += "(";
if (!func->parameters().isEmpty()) {
//synopsis += QLatin1Char(' ');
QList<Parameter>::ConstIterator p = func->parameters().constBegin();
QVector<Parameter>::ConstIterator p = func->parameters().constBegin();
while (p != func->parameters().constEnd()) {
if (p != func->parameters().constBegin())
synopsis += ", ";
synopsis += typified((*p).leftType());
synopsis += typified((*p).dataType());
if (style != Subpage && !(*p).name().isEmpty())
synopsis +=
"<@param>" + protect((*p).name()) + "</@param>";
@ -328,11 +328,11 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary)
synopsis = name;
synopsis += QLatin1Char('(');
if (!func->parameters().isEmpty()) {
QList<Parameter>::ConstIterator p = func->parameters().constBegin();
QVector<Parameter>::ConstIterator p = func->parameters().constBegin();
while (p != func->parameters().constEnd()) {
if (p != func->parameters().constBegin())
synopsis += ", ";
synopsis += typified((*p).leftType());
synopsis += typified((*p).dataType());
if (!(*p).name().isEmpty()) {
if (!synopsis.endsWith(QLatin1Char('(')))
synopsis += QLatin1Char(' ');

View File

@ -54,6 +54,7 @@ static bool inMacroCommand_ = false;
static bool parsingHeaderFile_ = false;
QStringList CppCodeParser::exampleFiles;
QStringList CppCodeParser::exampleDirs;
CppCodeParser* CppCodeParser::cppParser_ = 0;
/*!
The constructor initializes some regular expressions
@ -63,6 +64,7 @@ CppCodeParser::CppCodeParser()
: varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::")
{
reset();
cppParser_ = this;
}
/*!
@ -374,12 +376,12 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else {
func->setMetaness(FunctionNode::MacroWithParams);
QList<Parameter> params = func->parameters();
QVector<Parameter> params = func->parameters();
for (int i = 0; i < params.size(); ++i) {
Parameter &param = params[i];
if (param.name().isEmpty() && !param.leftType().isEmpty()
&& param.leftType() != "...")
param = Parameter("", "", param.leftType());
if (param.name().isEmpty() && !param.dataType().isEmpty()
&& param.dataType() != "...")
param = Parameter("", "", param.dataType());
}
func->setParameters(params);
}
@ -685,10 +687,10 @@ bool CppCodeParser::splitQmlPropertyArg(const QString& arg,
<type> <QML-type>::<name>(<param>, <param>, ...)
<type> <QML-module>::<QML-type>::<name>(<param>, <param>, ...)
This function splits the argument into one of those two
forms, sets \a module, \a qmlTypeName, and \a name, and returns
true. If the argument doesn't match either form, an error
message is emitted and false is returned.
This function splits the \a{arg}ument into one of those
two forms, sets \a type, \a module, and \a qmlTypeName,
and returns true. If the argument doesn't match either
form, an error message is emitted and false is returned.
\note The two QML types \e{Component} and \e{QtObject} never
have a module qualifier.
@ -698,22 +700,22 @@ bool CppCodeParser::splitQmlMethodArg(const QString& arg,
QString& module,
QString& qmlTypeName)
{
QStringList colonSplit(arg.split("::"));
if (colonSplit.size() > 1) {
QStringList blankSplit = colonSplit[0].split(QLatin1Char(' '));
if (blankSplit.size() > 1) {
type = blankSplit[0];
if (colonSplit.size() > 2) {
module = blankSplit[1];
qmlTypeName = colonSplit[1];
QString name;
int leftParen = arg.indexOf(QChar('('));
if (leftParen > 0)
name = arg.left(leftParen);
else
name = arg;
int firstBlank = name.indexOf(QChar(' '));
if (firstBlank > 0) {
type = name.left(firstBlank);
name = name.right(name.length() - firstBlank - 1);
}
else {
module.clear();
qmlTypeName = blankSplit[1];
}
}
else {
else
type.clear();
QStringList colonSplit(name.split("::"));
if (colonSplit.size() > 1) {
if (colonSplit.size() > 2) {
module = colonSplit[0];
qmlTypeName = colonSplit[1];
@ -722,7 +724,6 @@ bool CppCodeParser::splitQmlMethodArg(const QString& arg,
module.clear();
qmlTypeName = colonSplit[0];
}
}
return true;
}
QString msg = "Unrecognizable QML module/component qualifier for " + arg;
@ -1308,23 +1309,23 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
/*!
Parse the next function parameter, if there is one, and
append it to parameter list \a p. Return true if a parameter
is parsed and appended to \a p. Otherwise return false.
append it to parameter vector \a pvect. Return true if
a parameter is parsed and appended to \a pvect.
Otherwise return false.
*/
bool CppCodeParser::matchParameter(ParsedParameterList& pplist)
bool CppCodeParser::matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSignal)
{
ParsedParameter pp;
if (match(Tok_QPrivateSignal)) {
pp.qPrivateSignal_ = true;
pplist.append(pp);
isQPrivateSignal = true;
return true;
}
Parameter p;
CodeChunk chunk;
if (!matchDataType(&chunk, &pp.name_)) {
if (!matchDataType(&chunk, &p.name_)) {
return false;
}
pp.dataType_ = chunk.toString();
p.dataType_ = chunk.toString();
chunk.clear();
match(Tok_Comment);
if (match(Tok_Equal)) {
@ -1336,8 +1337,8 @@ bool CppCodeParser::matchParameter(ParsedParameterList& pplist)
readToken();
}
}
pp.defaultValue_ = chunk.toString();
pplist.append(pp);
p.defaultValue_ = chunk.toString();
pvect.append(p);
return true;
}
@ -1542,10 +1543,11 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
readToken();
// A left paren was seen. Parse the parameters
ParsedParameterList pplist;
bool isQPrivateSignal = false;
QVector<Parameter> pvect;
if (tok != Tok_RightParen) {
do {
if (!matchParameter(pplist))
if (!matchParameter(pvect, isQPrivateSignal))
return false;
} while (match(Tok_Comma));
}
@ -1629,13 +1631,10 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
func->setStatic(matched_static);
func->setConst(matchedConst);
func->setVirtualness(virtuality);
if (!pplist.isEmpty()) {
foreach (const ParsedParameter& pp, pplist) {
if (pp.qPrivateSignal_)
if (isQPrivateSignal)
func->setPrivateSignal();
else
func->addParameter(Parameter(pp.dataType_, "", pp.name_, pp.defaultValue_));
}
if (!pvect.isEmpty()) {
func->setParameters(pvect);
}
}
if (parentPathPtr != 0)
@ -2416,6 +2415,34 @@ bool CppCodeParser::makeFunctionNode(const QString& signature,
return ok;
}
/*!
This function uses a Tokenizer to parse the \a parameters of a
function into the parameter vector \a {pvect}.
*/
bool CppCodeParser::parseParameters(const QString& parameters,
QVector<Parameter>& pvect,
bool& isQPrivateSignal)
{
Tokenizer* outerTokenizer = tokenizer;
int outerTok = tok;
QByteArray latin1 = parameters.toLatin1();
Tokenizer stringTokenizer(Location(), latin1);
stringTokenizer.setParsingFnOrMacro(true);
tokenizer = &stringTokenizer;
readToken();
inMacroCommand_ = false;
do {
if (!matchParameter(pvect, isQPrivateSignal))
return false;
} while (match(Tok_Comma));
tokenizer = outerTokenizer;
tok = outerTok;
return true;
}
/*!
Create a new FunctionNode for a QML method or signal, as
specified by \a type, as a child of \a parent. \a sig is

View File

@ -51,16 +51,6 @@ class CppCodeParser : public CodeParser
{
Q_DECLARE_TR_FUNCTIONS(QDoc::CppCodeParser)
struct ParsedParameter {
bool qPrivateSignal_;
QString dataType_;
QString name_;
QString defaultValue_;
ParsedParameter() : qPrivateSignal_(false) { }
};
friend class QTypeInfo<ParsedParameter>;
typedef QVector<ParsedParameter> ParsedParameterList;
struct ExtraFuncData {
Aggregate* root; // Used as the parent.
Node::NodeType type; // The node type: Function, etc.
@ -74,6 +64,7 @@ class CppCodeParser : public CodeParser
public:
CppCodeParser();
~CppCodeParser();
static CppCodeParser* cppParser() { return cppParser_; }
virtual void initializeParser(const Config& config) Q_DECL_OVERRIDE;
virtual void terminateParser() Q_DECL_OVERRIDE;
@ -84,6 +75,7 @@ public:
virtual void parseSourceFile(const Location& location, const QString& filePath) Q_DECL_OVERRIDE;
virtual void doneParsingHeaderFiles() Q_DECL_OVERRIDE;
virtual void doneParsingSourceFiles() Q_DECL_OVERRIDE;
bool parseParameters(const QString& parameters, QVector<Parameter>& pvect, bool& isQPrivateSignal);
protected:
const QSet<QString>& topicCommands();
@ -126,7 +118,7 @@ protected:
bool matchTemplateAngles(CodeChunk *type = 0);
bool matchTemplateHeader();
bool matchDataType(CodeChunk *type, QString *var = 0);
bool matchParameter(ParsedParameterList& pplist);
bool matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSignal);
bool matchFunctionDecl(Aggregate *parent,
QStringList *parentPathPtr,
FunctionNode **funcPtr,
@ -184,10 +176,10 @@ protected:
static QStringList exampleFiles;
static QStringList exampleDirs;
static CppCodeParser* cppParser_;
QString exampleNameFilter;
QString exampleImageFilter;
};
Q_DECLARE_TYPEINFO(CppCodeParser::ParsedParameter, Q_MOVABLE_TYPE);
#define COMMAND_ABSTRACT Doc::alias("abstract")
#define COMMAND_CLASS Doc::alias("class")

View File

@ -1839,8 +1839,13 @@
\li \c {\l QWidget} - The name of a class documented with the \l
{class-command} {\\class} command.
\li \c {\l QWidget::sizeHint()} - The name of a member function,
documented with or without an \l {fn-command} {\\fn} command.
\li \c {\l QWidget::sizeHint()} - The signature of a function without
parameters. If a matching function without parameters can't be found,
the link is satisfied with the first matching function found.
\li \c {\l QWidget::removeAction(QAction* action)} - The signature
of a function with parameters. If an exact match is not found, the
link is not satisfied and qdoc reports a \e {Can't link to...} error.
\li \c {\l <QtGlobal>} - The subject of a \l {headerfile-command}
{\\headerfile} command.

View File

@ -804,9 +804,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
else if (node->type() == Node::Function) {
const FunctionNode *func = static_cast<const FunctionNode *>(node);
QSet<QString> definedParams;
QList<Parameter>::ConstIterator p = func->parameters().constBegin();
QVector<Parameter>::ConstIterator p = func->parameters().constBegin();
while (p != func->parameters().constEnd()) {
if ((*p).name().isEmpty() && (*p).leftType() != QLatin1String("...")
if ((*p).name().isEmpty() && (*p).dataType() != QLatin1String("...")
&& func->name() != QLatin1String("operator++")
&& func->name() != QLatin1String("operator--")) {
node->doc().location().warning(tr("Missing parameter name"));
@ -836,7 +836,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
else if (!(*a).isEmpty() && !documentedParams.contains(*a)) {
bool needWarning = (func->status() > Node::Obsolete);
if (func->overloadNumber() > 0) {
FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name());
FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name(), QString());
if (primaryFunc) {
foreach (const Parameter &param,
primaryFunc->parameters()) {
@ -1504,7 +1504,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker)
if (i != 0)
code += ", ";
const Parameter &p = func->parameters().at(i);
code += p.leftType() + p.rightType();
code += p.dataType() + p.rightType();
}
code += ")";
@ -1516,7 +1516,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker)
if (i != 0)
code += ", ";
const Parameter &p = func->parameters().at(i);
code += p.leftType();
code += p.dataType();
if (code[code.size()-1].isLetterOrNumber())
code += " ";
code += p.name() + p.rightType();
@ -2049,14 +2049,14 @@ void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
if (func->name().startsWith("set") && func->name().size() >= 4) {
alternateName = func->name()[3].toLower();
alternateName += func->name().mid(4);
alternateFunc = func->parent()->findFunctionNode(alternateName);
alternateFunc = func->parent()->findFunctionNode(alternateName, QString());
if (!alternateFunc) {
alternateName = "is" + func->name().mid(3);
alternateFunc = func->parent()->findFunctionNode(alternateName);
alternateFunc = func->parent()->findFunctionNode(alternateName, QString());
if (!alternateFunc) {
alternateName = "has" + func->name().mid(3);
alternateFunc = func->parent()->findFunctionNode(alternateName);
alternateFunc = func->parent()->findFunctionNode(alternateName, QString());
}
}
}
@ -2064,7 +2064,7 @@ void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
alternateName = "set";
alternateName += func->name()[0].toUpper();
alternateName += func->name().mid(1);
alternateFunc = func->parent()->findFunctionNode(alternateName);
alternateFunc = func->parent()->findFunctionNode(alternateName, QString());
}
if (alternateFunc && alternateFunc->access() != Node::Private) {

View File

@ -34,11 +34,12 @@
#include "node.h"
#include "tree.h"
#include "codemarker.h"
#include "codeparser.h"
#include "cppcodeparser.h"
#include <quuid.h>
#include "qdocdatabase.h"
#include <qdebug.h>
#include "generator.h"
#include "tokenizer.h"
QT_BEGIN_NAMESPACE
@ -810,9 +811,56 @@ Node* Aggregate::findChildNode(const QString& name, NodeType type)
Find a function node that is a child of this nose, such
that the function node has the specified \a name.
*/
FunctionNode *Aggregate::findFunctionNode(const QString& name) const
FunctionNode *Aggregate::findFunctionNode(const QString& name, const QString& params) const
{
return static_cast<FunctionNode *>(primaryFunctionMap_.value(name));
FunctionNode* pfn = static_cast<FunctionNode*>(primaryFunctionMap_.value(name));
FunctionNode* fn = pfn;
if (fn) {
const QVector<Parameter>* funcParams = &(fn->parameters());
if (params.isEmpty() && funcParams->isEmpty())
return fn;
bool isQPrivateSignal = false; // Not used in the search
QVector<Parameter> testParams;
if (!params.isEmpty()) {
CppCodeParser* cppParser = CppCodeParser::cppParser();
cppParser->parseParameters(params, testParams, isQPrivateSignal);
}
NodeList funcs = secondaryFunctionMap_.value(name);
int i = -1;
while (fn) {
if (testParams.size() == funcParams->size()) {
if (testParams.isEmpty())
return fn;
bool different = false;
for (int j=0; j<testParams.size(); j++) {
if (testParams.at(j).dataType() != funcParams->at(j).dataType()) {
different = true;
break;
}
}
if (!different)
return fn;
}
if (++i < funcs.size()) {
fn = static_cast<FunctionNode*>(funcs.at(i));
funcParams = &(fn->parameters());
}
else
fn = 0;
}
if (!fn && !testParams.empty())
return 0;
}
/*
Most \l commands that link to functions don't include
the parameter declarations in the function signature,
so if the \l is meant to go to a function that does
have parameters, the algorithm above won't find it.
Therefore we must return the pointer to the function
in the primary function map in the cases where the
parameters should have been specified in the \l command.
*/
return (fn ? fn : pfn);
}
/*!
@ -1090,20 +1138,20 @@ void Aggregate::setIncludes(const QStringList& includes)
*/
bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
{
if (f1->parameters().count() != f2->parameters().count())
if (f1->parameters().size() != f2->parameters().size())
return false;
if (f1->isConst() != f2->isConst())
return false;
QList<Parameter>::ConstIterator p1 = f1->parameters().constBegin();
QList<Parameter>::ConstIterator p2 = f2->parameters().constBegin();
QVector<Parameter>::ConstIterator p1 = f1->parameters().constBegin();
QVector<Parameter>::ConstIterator p2 = f2->parameters().constBegin();
while (p2 != f2->parameters().constEnd()) {
if ((*p1).hasType() && (*p2).hasType()) {
if ((*p1).rightType() != (*p2).rightType())
return false;
QString t1 = p1->leftType();
QString t2 = p2->leftType();
QString t1 = p1->dataType();
QString t2 = p2->dataType();
if (t1.length() < t2.length())
qSwap(t1, t2);
@ -1751,33 +1799,40 @@ void TypedefNode::setAssociatedEnum(const EnumNode *enume)
/*!
Constructs this parameter from the left and right types
\a leftType and rightType, the parameter \a name, and the
\a dataType and rightType, the parameter \a name, and the
\a defaultValue. In practice, \a rightType is not used,
and I don't know what is was meant for.
*/
Parameter::Parameter(const QString& leftType,
Parameter::Parameter(const QString& dataType,
const QString& rightType,
const QString& name,
const QString& defaultValue)
: leftType_(leftType), rightType_(rightType), name_(name), defaultValue_(defaultValue)
: dataType_(dataType),
rightType_(rightType),
name_(name),
defaultValue_(defaultValue)
{
// nothing.
}
/*!
The standard copy constructor copies the strings from \a p.
Standard copy constructor copies \p.
*/
Parameter::Parameter(const Parameter& p)
: leftType_(p.leftType_), rightType_(p.rightType_), name_(p.name_), defaultValue_(p.defaultValue_)
: dataType_(p.dataType_),
rightType_(p.rightType_),
name_(p.name_),
defaultValue_(p.defaultValue_)
{
// nothing.
}
/*!
Assigning Parameter \a p to this Parameter copies the
strings across.
standard assignment operator assigns \p.
*/
Parameter& Parameter::operator=(const Parameter& p)
{
leftType_ = p.leftType_;
dataType_ = p.dataType_;
rightType_ = p.rightType_;
name_ = p.name_;
defaultValue_ = p.defaultValue_;
@ -1791,7 +1846,7 @@ Parameter& Parameter::operator=(const Parameter& p)
*/
QString Parameter::reconstruct(bool value) const
{
QString p = leftType_ + rightType_;
QString p = dataType_ + rightType_;
if (!p.endsWith(QChar('*')) && !p.endsWith(QChar('&')) && !p.endsWith(QChar(' ')))
p += QLatin1Char(' ');
p += name_;
@ -1902,8 +1957,8 @@ void FunctionNode::addParameter(const Parameter& parameter)
*/
void FunctionNode::borrowParameterNames(const FunctionNode *source)
{
QList<Parameter>::Iterator t = parameters_.begin();
QList<Parameter>::ConstIterator s = source->parameters_.constBegin();
QVector<Parameter>::Iterator t = parameters_.begin();
QVector<Parameter>::ConstIterator s = source->parameters_.constBegin();
while (s != source->parameters_.constEnd() && t != parameters_.end()) {
if (!(*s).name().isEmpty())
(*t).setName((*s).name());
@ -1958,7 +2013,7 @@ bool FunctionNode::hasActiveAssociatedProperty() const
QStringList FunctionNode::parameterNames() const
{
QStringList names;
QList<Parameter>::ConstIterator p = parameters().constBegin();
QVector<Parameter>::ConstIterator p = parameters().constBegin();
while (p != parameters().constEnd()) {
names << (*p).name();
++p;
@ -1975,7 +2030,7 @@ QString FunctionNode::rawParameters(bool names, bool values) const
{
QString raw;
foreach (const Parameter &parameter, parameters()) {
raw += parameter.leftType() + parameter.rightType();
raw += parameter.dataType() + parameter.rightType();
if (names)
raw += parameter.name();
if (values)
@ -1991,7 +2046,7 @@ QString FunctionNode::rawParameters(bool names, bool values) const
QStringList FunctionNode::reconstructParameters(bool values) const
{
QStringList reconstructedParameters;
QList<Parameter>::ConstIterator p = parameters().constBegin();
QVector<Parameter>::ConstIterator p = parameters().constBegin();
while (p != parameters().constEnd()) {
reconstructedParameters << (*p).reconstruct(values);
++p;

View File

@ -376,7 +376,7 @@ public:
Node* findChildNode(const QString& name, Node::Genus genus) const;
Node* findChildNode(const QString& name, NodeType type);
virtual void findChildren(const QString& name, NodeList& nodes) const Q_DECL_OVERRIDE;
FunctionNode* findFunctionNode(const QString& name) const;
FunctionNode* findFunctionNode(const QString& name, const QString& params) const;
FunctionNode* findFunctionNode(const FunctionNode* clone) const;
void addInclude(const QString &include);
void setIncludes(const QStringList &includes);
@ -815,12 +815,11 @@ inline void EnumNode::setFlagsType(TypedefNode* t)
t->setAssociatedEnum(this);
}
class Parameter
{
public:
Parameter() {}
Parameter(const QString& leftType,
Parameter(const QString& dataType,
const QString& rightType = QString(),
const QString& name = QString(),
const QString& defaultValue = QString());
@ -830,21 +829,24 @@ public:
void setName(const QString& name) { name_ = name; }
bool hasType() const { return leftType_.length() + rightType_.length() > 0; }
const QString& leftType() const { return leftType_; }
bool hasType() const { return dataType_.length() + rightType_.length() > 0; }
const QString& dataType() const { return dataType_; }
const QString& rightType() const { return rightType_; }
const QString& name() const { return name_; }
const QString& defaultValue() const { return defaultValue_; }
QString reconstruct(bool value = false) const;
private:
QString leftType_;
QString rightType_;
public:
QString dataType_;
QString rightType_; // mws says remove this 04/08/2015
QString name_;
QString defaultValue_;
};
//friend class QTypeInfo<Parameter>;
//Q_DECLARE_TYPEINFO(Parameter, Q_MOVABLE_TYPE);
class FunctionNode : public LeafNode
{
public:
@ -874,7 +876,7 @@ public:
void setOverloadNumber(unsigned char n) { overloadNumber_ = n; }
void setReimplemented(bool b);
void addParameter(const Parameter& parameter);
inline void setParameters(const QList<Parameter>& parameters);
inline void setParameters(const QVector<Parameter>& parameters);
void borrowParameterNames(const FunctionNode* source);
void setReimplementedFrom(FunctionNode* from);
@ -907,7 +909,7 @@ public:
virtual bool isJsMethod() const Q_DECL_OVERRIDE {
return (type() == Node::QmlMethod) && (genus() == Node::JS);
}
const QList<Parameter>& parameters() const { return parameters_; }
const QVector<Parameter>& parameters() const { return parameters_; }
void clearParams() { parameters_.clear(); }
QStringList parameterNames() const;
QString rawParameters(bool names = false, bool values = false) const;
@ -957,7 +959,7 @@ private:
bool privateSignal_: 1;
bool overload_ : 1;
unsigned char overloadNumber_;
QList<Parameter> parameters_;
QVector<Parameter> parameters_;
const FunctionNode* reimplementedFrom_;
PropNodeList associatedProperties_;
QList<FunctionNode*> reimplementedBy_;
@ -1030,7 +1032,7 @@ private:
const PropertyNode* overrides_;
};
inline void FunctionNode::setParameters(const QList<Parameter> &p)
inline void FunctionNode::setParameters(const QVector<Parameter> &p)
{
parameters_ = p;
}

View File

@ -380,6 +380,30 @@ QString QDocForest::getLinkCounts(QStringList& strings, QVector<int>& counts)
return depends;
}
/*!
*/
const Node* QDocForest::findFunctionNode(const QString& target,
const Node* relative,
Node::Genus genus)
{
QString function, params;
int length = target.length();
if (target.endsWith(QChar(')'))) {
int position = target.lastIndexOf(QChar('('));
params = target.mid(position+1, length-position-2);
function = target.left(position);
}
else
function = target;
foreach (Tree* t, searchOrder()) {
const Node* n = t->findFunctionNode(function, params, relative, genus);
if (n)
return n;
relative = 0;
}
return 0;
}
/*! \class QDocDatabase
This class provides exclusive access to the qdoc database,
which consists of a forrest of trees and a lot of maps and
@ -1342,8 +1366,16 @@ void QDocDatabase::resolveNamespaces()
}
}
}
#if 0
/*!
*/
const Node* QDocDatabase::findFunctionNode(const QString& target,
const Node* relative,
Node::Genus genus)
{
return forest_.findFunctionNode(target, relative, genus);
}
#endif
/*!
This function is called for autolinking to a \a type,
which could be a function return type or a parameter
@ -1641,6 +1673,8 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q
Atom* atom = const_cast<Atom*>(a);
QStringList targetPath = atom->string().split("#");
QString first = targetPath.first().trimmed();
if (Generator::debugging())
qDebug() << " first:" << first;
Tree* domain = 0;
Node::Genus genus = Node::DontCare;
@ -1659,8 +1693,14 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q
else if (domain) {
if (first.endsWith(".html"))
node = domain->findNodeByNameAndType(QStringList(first), Node::Document);
else if (first.endsWith("()"))
node = domain->findFunctionNode(first, 0, genus);
else if (first.endsWith(QChar(')'))) {
QString function, params;
int length = first.length();
int position = first.lastIndexOf(QChar('('));
params = first.mid(position+1, length-position-2);
function = first.left(position);
node = domain->findFunctionNode(function, params, 0, genus);
}
else {
int flags = SearchBaseClasses | SearchEnumValues;
QStringList nodePath = first.split("::");
@ -1683,8 +1723,11 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q
if (!node && first.contains("/"))
return findNodeForTarget(targetPath, relative, genus, ref);
}
else if (first.endsWith("()"))
else if (first.endsWith(QChar(')'))) {
node = findFunctionNode(first, relative, genus);
if (Generator::debugging())
qDebug() << " node:" << node;
}
else {
node = findNodeForTarget(targetPath, relative, genus, ref);
return node;

View File

@ -141,15 +141,8 @@ class QDocForest
const Node* findFunctionNode(const QString& target,
const Node* relative,
Node::Genus genus) {
foreach (Tree* t, searchOrder()) {
const Node* n = t->findFunctionNode(target, relative, genus);
if (n)
return n;
relative = 0;
}
return 0;
}
Node::Genus genus);
const Node* findNodeForTarget(QStringList& targetPath,
const Node* relative,
Node::Genus genus,

View File

@ -1238,7 +1238,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
for (int i = 0; i < functionNode->parameters().size(); ++i) {
Parameter parameter = functionNode->parameters()[i];
writer.writeStartElement("parameter");
writer.writeAttribute("left", parameter.leftType());
writer.writeAttribute("left", parameter.dataType());
writer.writeAttribute("right", parameter.rightType());
writer.writeAttribute("name", parameter.name());
writer.writeAttribute("default", parameter.defaultValue());

View File

@ -675,7 +675,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiPublicMember *member)
QString name = member->name.toString();
FunctionNode *qmlSignal = new FunctionNode(Node::QmlSignal, current, name, false);
QList<Parameter> parameters;
QVector<Parameter> parameters;
for (QQmlJS::AST::UiParameterList *it = member->parameters; it; it = it->next) {
if (!it->type.isEmpty() && !it->name.isEmpty())
parameters.append(Parameter(it->type.toString(), QString(), it->name.toString()));
@ -754,7 +754,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::FunctionDeclaration* fd)
}
if (overloads > 1)
qmlMethod->setOverloadFlag(true);
QList<Parameter> parameters;
QVector<Parameter> parameters;
QQmlJS::AST::FormalParameterList* formals = fd->formals;
if (formals) {
QQmlJS::AST::FormalParameterList* fpl = formals;

View File

@ -33,6 +33,7 @@
#include "config.h"
#include "tokenizer.h"
#include "generator.h"
#include <qfile.h>
#include <qhash.h>

View File

@ -220,6 +220,7 @@ QmlTypeNode* Tree::findQmlTypeNode(const QStringList& path)
used as the starting point.
*/
const FunctionNode* Tree::findFunctionNode(const QStringList& path,
const QString& params,
const Node* relative,
int findFlags,
Node::Genus genus) const
@ -234,7 +235,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
qcn = static_cast<QmlTypeNode*>(n);
}
if (qcn)
return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2], params));
}
if (!relative)
@ -254,7 +255,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
const Node* next;
if (i == path.size() - 1)
next = ((const Aggregate*) node)->findFunctionNode(path.at(i));
next = ((const Aggregate*) node)->findFunctionNode(path.at(i), params);
else
next = ((const Aggregate*) node)->findChildNode(path.at(i), genus);
@ -262,7 +263,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) {
if (i == path.size() - 1)
next = static_cast<const Aggregate*>(baseClass)->findFunctionNode(path.at(i));
next = static_cast<const Aggregate*>(baseClass)->findFunctionNode(path.at(i), params);
else
next = static_cast<const Aggregate*>(baseClass)->findChildNode(path.at(i), genus);
@ -1452,13 +1453,17 @@ void Tree::insertQmlType(const QString& key, QmlTypeNode* n)
Split \a target on "::" and find the function node with that
path.
*/
const Node* Tree::findFunctionNode(const QString& target, const Node* relative, Node::Genus genus)
const Node* Tree::findFunctionNode(const QString& target,
const QString& params,
const Node* relative,
Node::Genus genus) const
{
QString t = target;
if (t.endsWith("()"))
if (t.endsWith("()")) {
t.chop(2);
}
QStringList path = t.split("::");
const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus);
const FunctionNode* fn = findFunctionNode(path, params, relative, SearchBaseClasses, genus);
if (fn && fn->metaness() != FunctionNode::MacroWithoutParams)
return fn;
return 0;

View File

@ -107,7 +107,10 @@ class Tree
ClassNode* findClassNode(const QStringList& path, const Node* start = 0) const;
NamespaceNode* findNamespaceNode(const QStringList& path) const;
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone);
const Node* findFunctionNode(const QString& target, const Node* relative, Node::Genus genus);
const Node* findFunctionNode(const QString& target,
const QString& params,
const Node* relative,
Node::Genus genus) const;
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
@ -163,6 +166,7 @@ class Tree
NamespaceNode *root() { return &root_; }
const FunctionNode *findFunctionNode(const QStringList &path,
const QString& params,
const Node *relative = 0,
int findFlags = 0,
Node::Genus genus = Node::DontCare) const;

View File

@ -159,23 +159,6 @@ public:
QWindow dummyTransparentWindow;
#endif
#ifdef Q_DEAD_CODE_FROM_QT4_MAC
void openCocoaColorPanel(const QColor &initial,
QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options);
void closeCocoaColorPanel();
void releaseCocoaColorPanelDelegate();
void setCocoaPanelColor(const QColor &color);
inline void done(int result) { q_func()->done(result); }
inline QColorDialog *colorDialog() { return q_func(); }
void *delegate;
static bool sharedColorPanelAvailable;
void _q_macRunNativeAppModalPanel();
void mac_nativeDialogModalHelp();
#endif
private:
virtual void initHelper(QPlatformDialogHelper *h) Q_DECL_OVERRIDE;
virtual void helperPrepareShow(QPlatformDialogHelper *h) Q_DECL_OVERRIDE;
@ -1731,9 +1714,6 @@ void QColorDialogPrivate::init(const QColor &initial)
if (!nativeDialogInUse)
initWidgets();
#ifdef Q_DEAD_CODE_FROM_QT4_MAC
delegate = 0;
#endif
#ifdef Q_OS_WIN32
dummyTransparentWindow.resize(1, 1);
dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint);
@ -2135,11 +2115,6 @@ QColorDialog::ColorDialogOptions QColorDialog::options() const
\sa color, colorSelected()
*/
#ifdef Q_DEAD_CODE_FROM_QT4_MAC
// can only have one Cocoa color panel active
bool QColorDialogPrivate::sharedColorPanelAvailable = true;
#endif
/*!
\fn void QColorDialog::colorSelected(const QColor &color);
@ -2166,23 +2141,6 @@ void QColorDialog::setVisible(bool visible)
if (visible)
d->selectedQColor = QColor();
#if defined(Q_DEAD_CODE_FROM_QT4_MAC)
if (visible) {
if (d->delegate || (QColorDialogPrivate::sharedColorPanelAvailable &&
!(testAttribute(Qt::WA_DontShowOnScreen) || (d->opts & DontUseNativeDialog)))){
d->openCocoaColorPanel(currentColor(), parentWidget(), windowTitle(), options());
QColorDialogPrivate::sharedColorPanelAvailable = false;
setAttribute(Qt::WA_DontShowOnScreen);
}
setWindowFlags(windowModality() == Qt::WindowModal ? Qt::Sheet : DefaultWindowFlags);
} else {
if (d->delegate) {
d->closeCocoaColorPanel();
setAttribute(Qt::WA_DontShowOnScreen, false);
}
}
#else
if (d->nativeDialogInUse) {
d->setNativeDialogVisible(visible);
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
@ -2191,7 +2149,6 @@ void QColorDialog::setVisible(bool visible)
} else {
setAttribute(Qt::WA_DontShowOnScreen, false);
}
#endif
QDialog::setVisible(visible);
}
@ -2267,13 +2224,7 @@ QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent)
QColorDialog::~QColorDialog()
{
#if defined(Q_DEAD_CODE_FROM_QT4_MAC)
Q_D(QColorDialog);
if (d->delegate) {
d->releaseCocoaColorPanelDelegate();
QColorDialogPrivate::sharedColorPanelAvailable = true;
}
#endif
}
/*!

View File

@ -3101,6 +3101,53 @@ void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
remove(index);
}
void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation o)
{
if (docks.count() != sizes.count()) {
qWarning("QMainWidget::resizeDocks: size of the lists are not the same");
return;
}
int count = docks.count();
fallbackToSizeHints = false;
for (int i = 0; i < count; ++i) {
QList<int> path = indexOf(docks[i]);
if (path.isEmpty()) {
qWarning("QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
continue;
}
int size = sizes[i];
if (size <= 0) {
qWarning("QMainWidget::resizeDocks: all sizes need to be larger than 0");
size = 1;
}
while (path.size() > 1) {
QDockAreaLayoutInfo *info = this->info(path);
if (!info->tabbed && info->o == o) {
info->item_list[path.last()].size = size;
int totalSize = 0;
foreach (const QDockAreaLayoutItem &item, info->item_list) {
if (!item.skip()) {
if (totalSize != 0)
totalSize += sep;
totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
}
}
size = totalSize;
}
path.removeLast();
}
const int dockNum = path.first();
Q_ASSERT(dockNum < QInternal::DockCount);
QRect &r = this->docks[dockNum].rect;
QSize s = r.size();
rpick(o, s) = size;
r.setSize(s);
}
}
void QDockAreaLayout::splitDockWidget(QDockWidget *after,
QDockWidget *dockWidget,
Qt::Orientation orientation)

View File

@ -268,6 +268,7 @@ public:
void splitDockWidget(QDockWidget *after, QDockWidget *dockWidget,
Qt::Orientation orientation);
void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
void resizeDocks(const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation o);
void apply(bool animate);

View File

@ -1237,6 +1237,35 @@ void QMainWindow::removeDockWidget(QDockWidget *dockwidget)
Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
{ return d_func()->layout->dockWidgetArea(dockwidget); }
/*!
\since 5.6
Resizes the dock widgets in the list \a docks to the corresponding size in
pixels from the list \a sizes. If \a orientation is Qt::Horizontal, adjusts
the width, otherwise adjusts the height of the dock widgets.
The sizes will be adjusted such that the maximum and the minimum sizes are
respected and the QMainWindow itself will not be resized.
Any additional/missing space is distributed amongst the widgets according
to the relative weight of the sizes.
Example:
\code
resizeDocks({blueWidget, yellowWidget}, {20 , 40}, Qt::Horizontal);
\endcode
If the blue and the yellow widget are nested on the same level they will be
resized such that the yellowWidget is twice as big as the blueWidget
If some widgets are grouped in tabs, only one widget per group should be
specified. Widgets not in the list might be changed to repect the constraints.
*/
void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation orientation)
{
d_func()->layout->layoutState.dockAreaLayout.resizeDocks(docks, sizes, orientation);
d_func()->layout->invalidate();
}
#endif // QT_NO_DOCKWIDGET
/*!

View File

@ -165,6 +165,9 @@ public:
bool restoreDockWidget(QDockWidget *dockwidget);
Qt::DockWidgetArea dockWidgetArea(QDockWidget *dockwidget) const;
void resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation orientation);
#endif // QT_NO_DOCKWIDGET
QByteArray saveState(int version = 0) const;

View File

@ -49,38 +49,44 @@
entry point within the newly created GUI thread.
*/
#if _MSC_VER < 1900
#include <new.h>
typedef struct
{
int newmode;
} _startupinfo;
#endif // _MSC_VER < 1900
extern "C" {
#if _MSC_VER < 1900
int __getmainargs(int *argc, char ***argv, char ***env, int expandWildcards, _startupinfo *info);
#endif
int main(int, char **);
}
#include <qbytearray.h>
#include <qstring.h>
#include <qlist.h>
#include <qvector.h>
#include <qdir.h>
#include <qstandardpaths.h>
#include <qfunctions_winrt.h>
#include <wrl.h>
#include <Windows.ApplicationModel.core.h>
#include <windows.ui.xaml.h>
#include <windows.ui.xaml.controls.h>
using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Activation;
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
#define qHString(x) Wrappers::HString::MakeReference(x).Get()
#define CoreApplicationClass RuntimeClass_Windows_ApplicationModel_Core_CoreApplication
typedef ITypedEventHandler<Core::CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler;
static int g_mainExitCode;
typedef ITypedEventHandler<CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler;
static QtMessageHandler defaultMessageHandler;
static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
@ -103,134 +109,76 @@ static void devMessageHandler(QtMsgType type, const QMessageLogContext &context,
defaultMessageHandler(type, context, message);
}
class AppContainer : public Microsoft::WRL::RuntimeClass<Core::IFrameworkView>
class AppContainer : public RuntimeClass<Xaml::IApplicationOverrides>
{
public:
AppContainer(int argc, char *argv[]) : m_argc(argc), m_deleteArgv0(false)
AppContainer()
{
m_argv.reserve(argc);
for (int i = 0; i < argc; ++i) {
// Workaround for empty argv[0] which occurs when WMAppManifest's ImageParams is used
// The second argument is taken to be the executable
if (i == 0 && argc >= 2 && !qstrlen(argv[0])) {
const QByteArray argv0 = QDir::current()
.absoluteFilePath(QString::fromLatin1(argv[1])).toUtf8();
m_argv.append(qstrdup(argv0.constData()));
m_argc -= 1;
m_deleteArgv0 = true;
++i;
continue;
}
m_argv.append(argv[i]);
}
ComPtr<Xaml::IApplicationFactory> applicationFactory;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(),
IID_PPV_ARGS(&applicationFactory));
Q_ASSERT_SUCCEEDED(hr);
hr = applicationFactory->CreateInstance(this, &base, &core);
RETURN_VOID_IF_FAILED("Failed to create application container instance");
}
~AppContainer()
{
if (m_deleteArgv0)
delete[] m_argv[0];
for (int i = m_argc; i < m_argv.size(); ++i)
delete[] m_argv[i];
}
// IFrameworkView Methods
HRESULT __stdcall Initialize(Core::ICoreApplicationView *view)
int exec(int argc, char **argv)
{
view->add_Activated(Callback<ActivatedHandler>(this, &AppContainer::onActivated).Get(),
&m_activationToken);
args.reserve(argc);
for (int i = 0; i < argc; ++i)
args.append(argv[i]);
mainThread = CreateThread(NULL, 0, [](void *param) -> DWORD {
AppContainer *app = reinterpret_cast<AppContainer *>(param);
int argc = app->args.count();
char **argv = app->args.data();
return main(argc, argv);
}, this, CREATE_SUSPENDED, nullptr);
HRESULT hr;
ComPtr<Xaml::IApplicationStatics> appStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(),
IID_PPV_ARGS(&appStatics));
Q_ASSERT_SUCCEEDED(hr);
hr = appStatics->Start(Callback<Xaml::IApplicationInitializationCallback>([](Xaml::IApplicationInitializationCallbackParams *) {
return S_OK;
}).Get());
Q_ASSERT_SUCCEEDED(hr);
DWORD exitCode;
GetExitCodeThread(mainThread, &exitCode);
return exitCode;
}
HRESULT __stdcall SetWindow(ABI::Windows::UI::Core::ICoreWindow *) { return S_OK; }
HRESULT __stdcall Load(HSTRING) { return S_OK; }
HRESULT __stdcall Run()
private:
HRESULT __stdcall OnActivated(IActivatedEventArgs *args) Q_DECL_OVERRIDE
{
bool develMode = false;
bool debugWait = false;
foreach (const QByteArray &arg, m_argv) {
if (arg == "-qdevel")
develMode = true;
if (arg == "-qdebug")
debugWait = true;
return base->OnActivated(args);
}
if (develMode) {
// Write a PID file to help runner
const QString pidFileName = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
};
// (Unused) handle will automatically be closed when the app exits
CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
// Install the develMode message handler
#ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
HRESULT __stdcall OnLaunched(ILaunchActivatedEventArgs *launchArgs) Q_DECL_OVERRIDE
{
#if _MSC_VER >= 1900
commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8();
#endif
HString launchCommandLine;
launchArgs->get_Arguments(launchCommandLine.GetAddressOf());
if (launchCommandLine.IsValid()) {
quint32 launchCommandLineLength;
const wchar_t *launchCommandLineBuffer = launchCommandLine.GetRawBuffer(&launchCommandLineLength);
if (!commandLine.isEmpty() && launchCommandLineLength)
commandLine += ' ';
if (launchCommandLineLength)
commandLine += QString::fromWCharArray(launchCommandLineBuffer, launchCommandLineLength).toUtf8();
}
// Wait for debugger before continuing
if (debugWait) {
while (!IsDebuggerPresent())
WaitForSingleObjectEx(GetCurrentThread(), 1, true);
}
g_mainExitCode = main(m_argv.count(), m_argv.data());
return S_OK;
}
HRESULT __stdcall Uninitialize() { return S_OK; }
private:
// Activation handler
HRESULT onActivated(Core::ICoreApplicationView *, Activation::IActivatedEventArgs *args)
{
Activation::ILaunchActivatedEventArgs *launchArgs;
if (SUCCEEDED(args->QueryInterface(&launchArgs))) {
for (int i = m_argc; i < m_argv.size(); ++i)
delete[] m_argv[i];
m_argv.resize(m_argc);
HString arguments;
launchArgs->get_Arguments(arguments.GetAddressOf());
if (arguments.IsValid()) {
foreach (const QByteArray &arg, QString::fromWCharArray(
arguments.GetRawBuffer(nullptr)).toLocal8Bit().split(' ')) {
m_argv.append(qstrdup(arg.constData()));
}
}
}
return S_OK;
}
int m_argc;
QVector<char *> m_argv;
bool m_deleteArgv0;
EventRegistrationToken m_activationToken;
};
class AppViewSource : public Microsoft::WRL::RuntimeClass<Core::IFrameworkViewSource>
{
public:
AppViewSource(int argc, char **argv) : m_argc(argc), m_argv(argv) { }
HRESULT __stdcall CreateView(Core::IFrameworkView **frameworkView)
{
return (*frameworkView = Make<AppContainer>(m_argc, m_argv).Detach()) ? S_OK : E_OUTOFMEMORY;
}
private:
int m_argc;
char **m_argv;
};
// Main entry point for Appx containers
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
#if _MSC_VER < 1900
int argc = 0;
char **argv, **env;
_startupinfo info = { _query_new_mode() };
if (int init = __getmainargs(&argc, &argv, &env, false, &info))
return init;
#else
QByteArray commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8();
QVarLengthArray<char *> args;
if (!commandLine.isEmpty())
args.append(commandLine.data());
bool quote = false;
bool escape = false;
for (int i = 0; i < commandLine.size(); ++i) {
@ -260,11 +208,100 @@ int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
break;
}
}
int argc = args.size();
char **argv = args.data();
char **env = Q_NULLPTR;
#endif // _MSC_VER >= 1900
bool develMode = false;
bool debugWait = false;
foreach (const char *arg, args) {
if (strcmp(arg, "-qdevel") == 0)
develMode = true;
if (strcmp(arg, "-qdebug") == 0)
debugWait = true;
}
if (develMode) {
// Write a PID file to help runner
const QString pidFileName = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
};
// (Unused) handle will automatically be closed when the app exits
CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
// Install the develMode message handler
#ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
#endif
}
// Wait for debugger before continuing
if (debugWait) {
while (!IsDebuggerPresent())
WaitForSingleObjectEx(GetCurrentThread(), 1, true);
}
ResumeThread(mainThread);
return S_OK;
}
HRESULT __stdcall OnFileActivated(IFileActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnSearchActivated(ISearchActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnShareTargetActivated(IShareTargetActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnFileOpenPickerActivated(IFileOpenPickerActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnFileSavePickerActivated(IFileSavePickerActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnCachedFileUpdaterActivated(ICachedFileUpdaterActivatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
HRESULT __stdcall OnWindowCreated(Xaml::IWindowCreatedEventArgs *args) Q_DECL_OVERRIDE
{
Q_UNUSED(args);
return S_OK;
}
ComPtr<Xaml::IApplicationOverrides> base;
ComPtr<Xaml::IApplication> core;
QByteArray commandLine;
QVarLengthArray<char *> args;
HANDLE mainThread;
};
// Main entry point for Appx containers
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
int argc = 0;
char **argv = 0, **env = 0;
#if _MSC_VER < 1900
_startupinfo info = { _query_new_mode() };
if (int init = __getmainargs(&argc, &argv, &env, false, &info))
return init;
#endif // _MSC_VER >= 1900
for (int i = 0; env && env[i]; ++i) {
QByteArray var(env[i]);
int split = var.indexOf('=');
@ -275,10 +312,6 @@ int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
if (FAILED(RoInitialize(RO_INIT_MULTITHREADED)))
return 1;
Core::ICoreApplication *appFactory;
if (FAILED(RoGetActivationFactory(qHString(CoreApplicationClass), IID_PPV_ARGS(&appFactory))))
return 2;
appFactory->Run(Make<AppViewSource>(argc, argv).Get());
return g_mainExitCode;
ComPtr<AppContainer> app = Make<AppContainer>();
return app->exec(argc, argv);
}

View File

@ -122,6 +122,7 @@ private slots:
void removeFileWhileProcessIsRunning();
void fileWriterProcess();
void switchReadChannels();
void discardUnwantedOutput();
void setWorkingDirectory();
void setNonExistentWorkingDirectory();
#endif // not Q_OS_WINCE
@ -2228,6 +2229,25 @@ void tst_QProcess::switchReadChannels()
}
#endif
#ifndef Q_OS_WINCE
// Reading and writing to a process is not supported on Qt/CE
void tst_QProcess::discardUnwantedOutput()
{
QProcess process;
process.setProgram("testProcessEcho2/testProcessEcho2");
process.start(QIODevice::WriteOnly);
process.write("Hello, World");
process.closeWriteChannel();
QVERIFY(process.waitForFinished(5000));
process.setReadChannel(QProcess::StandardOutput);
QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
process.setReadChannel(QProcess::StandardError);
QCOMPARE(process.bytesAvailable(), Q_INT64_C(0));
}
#endif
//-----------------------------------------------------------------------------
#ifndef Q_OS_WINCE
// Q_OS_WIN - setWorkingDirectory will chdir before starting the process on unices

View File

@ -1079,7 +1079,7 @@ static bool canSendUnixFd(DBusConnection *connection)
# if DBUS_VERSION-0 >= 0x010400
can_send_type = dbus_connection_can_send_type;
# endif
#else
#elif !defined(QT_NO_LIBRARY)
// run-time check if the next functions are available
can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type");
#endif

View File

@ -94,7 +94,11 @@ static void addFixedTypes()
// the library recognizes this as valid type first.
// The following function was added for Unix FD support, so if it is
// present, so is support for Unix FDs.
# ifndef QT_NO_LIBRARY
bool supportsUnixFds = qdbus_resolve_conditionally("dbus_connection_can_send_type");
# else
bool supportsUnixFds = false;
# endif
# else
bool supportsUnixFds = true;
# endif

View File

@ -107,6 +107,7 @@ private slots:
void premultiply();
void unpremultiply_sse4();
void qrgba64();
void qrgba64MemoryLayout();
void qrgba64Premultiply();
void qrgba64Equivalence();
@ -1495,6 +1496,24 @@ void tst_QColor::qrgba64()
QCOMPARE(rgb64.green(), quint16(0x4422));
}
void tst_QColor::qrgba64MemoryLayout()
{
QRgba64 rgb64 = QRgba64::fromRgba64(0x0123, 0x4567, 0x89ab, 0xcdef);
QCOMPARE(rgb64.red(), quint16(0x0123));
QCOMPARE(rgb64.green(), quint16(0x4567));
QCOMPARE(rgb64.blue(), quint16(0x89ab));
QCOMPARE(rgb64.alpha(), quint16(0xcdef));
// Check in-memory order, so it can be used by things like SSE
Q_STATIC_ASSERT(sizeof(QRgba64) == sizeof(quint64));
quint16 memory[4];
memcpy(memory, &rgb64, sizeof(QRgba64));
QCOMPARE(memory[0], quint16(0x0123));
QCOMPARE(memory[1], quint16(0x4567));
QCOMPARE(memory[2], quint16(0x89ab));
QCOMPARE(memory[3], quint16(0xcdef));
}
void tst_QColor::qrgba64Premultiply()
{
// Tests that qPremultiply(qUnpremultiply(rgba64)) returns rgba64.

View File

@ -4882,8 +4882,12 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceOver << qRgba(85, 0, 0, 85) << 85;
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 120) << 85;
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(85, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(180, 0, 0, 180) << 170;
QTest::newRow("ARGB source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied

View File

@ -47,6 +47,7 @@
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QJsonDocument>
#include <algorithm>
@ -107,6 +108,7 @@ private slots:
void testConfiguration();
void testGlConfiguration();
void testBugList();
void testDefaultWindowsBlacklist();
};
static void dumpConfiguration(QTextStream &str)
@ -284,6 +286,20 @@ void tst_QOpenGlConfig::testBugList()
msgSetMismatch(expectedFeatures, actualFeatures));
}
void tst_QOpenGlConfig::testDefaultWindowsBlacklist()
{
if (qGuiApp->platformName() != QStringLiteral("windows"))
QSKIP("Only applicable to Windows");
QFile f(QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json"));
QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Text));
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(f.readAll(), &err);
QVERIFY2(err.error == 0,
QStringLiteral("Failed to parse built-in Windows GPU blacklist. %1 : %2")
.arg(err.offset).arg(err.errorString()).toLatin1());
}
QTEST_MAIN(tst_QOpenGlConfig)
#include "tst_qopenglconfig.moc"

View File

@ -241,6 +241,10 @@ private slots:
void aggregateFunctionTypes_data() { generic_data(); }
void aggregateFunctionTypes();
void integralTypesMysql_data() { generic_data("QMYSQL"); }
void integralTypesMysql();
private:
// returns all database connections
void generic_data(const QString &engine=QString());
@ -3974,5 +3978,65 @@ void tst_QSqlQuery::aggregateFunctionTypes()
}
}
template<typename T>
void runIntegralTypesMysqlTest(QSqlDatabase &db, const QString &tableName, const QString &type, const bool withPreparedStatement,
const T min = std::numeric_limits<T>::min(), const T max = std::numeric_limits<T>::max())
{
QSqlQuery q(db);
QVERIFY_SQL(q, exec("DROP TABLE IF EXISTS " + tableName));
QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id " + type + ")"));
const int steps = 20;
const T increment = max / steps - min / steps;
// insert some values
QVector<T> values;
values.resize(steps);
T v = min;
if (withPreparedStatement) {
QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (id) VALUES (?)"));
}
for (int i = 0; i < values.size(); ++i) {
if (withPreparedStatement) {
q.bindValue(0, v);
QVERIFY_SQL(q, exec());
} else {
QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (" + QString::number(v) + ")"));
}
values[i] = v;
v += increment;
}
// ensure we can read them back properly
QVERIFY_SQL(q, exec("SELECT id FROM " + tableName));
QVector<T> actualValues;
actualValues.reserve(values.size());
while (q.next()) {
actualValues << q.value(0).value<T>();
}
QCOMPARE(actualValues, values);
}
void tst_QSqlQuery::integralTypesMysql()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
for (int i = 0; i < 2; ++i) {
const bool withPreparedStatement = (i == 1);
runIntegralTypesMysqlTest<char>(db, "tinyIntTest", "TINYINT", withPreparedStatement);
runIntegralTypesMysqlTest<unsigned char>(db, "unsignedTinyIntTest", "TINYINT UNSIGNED", withPreparedStatement);
runIntegralTypesMysqlTest<char>(db, "smallIntTest", "SMALLINT", withPreparedStatement);
runIntegralTypesMysqlTest<unsigned char>(db, "unsignedSmallIntTest", "SMALLINT UNSIGNED", withPreparedStatement);
runIntegralTypesMysqlTest<int>(db, "mediumIntTest", "MEDIUMINT", withPreparedStatement, -(1 << 23), (1 << 23) - 1);
runIntegralTypesMysqlTest<unsigned int>(db, "unsignedMediumIntTest", "MEDIUMINT UNSIGNED", withPreparedStatement, 0, (1 << 24) - 1);
runIntegralTypesMysqlTest<int>(db, "intTest", "INT", withPreparedStatement);
runIntegralTypesMysqlTest<unsigned int>(db, "unsignedIntTest", "INT UNSIGNED", withPreparedStatement);
runIntegralTypesMysqlTest<long long>(db, "bigIntTest", "BIGINT", withPreparedStatement);
runIntegralTypesMysqlTest<unsigned long long>(db, "unsignedBigIntTest", "BIGINT UNSIGNED", withPreparedStatement);
}
}
QTEST_MAIN( tst_QSqlQuery )
#include "tst_qsqlquery.moc"

View File

@ -149,6 +149,8 @@ private slots:
void toggleUnifiedTitleAndToolBarOnMac();
#endif
void QTBUG21378_animationFinished();
void resizeDocks();
void resizeDocks_data();
};
@ -1950,5 +1952,96 @@ void tst_QMainWindow::QTBUG21378_animationFinished()
delete mwClickTimer;
QVERIFY(true);
}
Q_DECLARE_METATYPE(Qt::Orientation)
void tst_QMainWindow::resizeDocks_data()
{
QTest::addColumn<Qt::Orientation>("orientation");
QTest::addColumn<QStringList>("docks");
QTest::addColumn<QList<int> >("sizes");
QTest::newRow("1") << Qt::Horizontal
<< (QStringList() << "blue" << "orange" << "green" << "gray")
<< (QList<int>() << 190 << 190 << 320 << 160);
QTest::newRow("2") << Qt::Vertical
<< (QStringList() << "yellow" << "orange")
<< (QList<int>() << 147 << 133 );
QTest::newRow("3") << Qt::Horizontal
<< (QStringList() << "blue" << "yellow")
<< (QList<int>() << 190 << 600);
}
void tst_QMainWindow::resizeDocks()
{
AddList addList;
addList
<< AddDockWidget("blue", Qt::LeftDockWidgetArea)
<< AddDockWidget("red", Qt::TopDockWidgetArea)
<< AddDockWidget("pink", "red")
<< AddDockWidget("yellow", Qt::RightDockWidgetArea)
<< AddDockWidget("orange", Qt::RightDockWidgetArea)
<< AddDockWidget("green", "orange", Qt::Horizontal)
<< AddDockWidget("gray", "orange", Qt::Horizontal);
/*
+--------------------------------+
| red/pink |
+------+-+-----------------------+
| | | yellow |
| blue + +--------+------+-------+
| | | orange | gray | green |
+------+-+--------+------+-------+
*/
QMainWindow mw(0, Qt::BypassWindowManagerHint);
mw.setDockNestingEnabled(true);
mw.resize(1800, 600);
foreach (const AddDockWidget &i, addList)
i.apply(&mw);
foreach (QDockWidget *dw, mw.findChildren<QDockWidget *>())
dw->setStyleSheet( "* { background-color: " + dw->objectName() +" }");
mw.setCentralWidget(new QTextEdit);
mw.show();
QTest::qWaitForWindowExposed(&mw);
QFETCH(Qt::Orientation, orientation);
QFETCH(QStringList, docks);
QFETCH(QList<int>, sizes);
QList<QDockWidget *> list;
foreach (const QString &name, docks) {
QDockWidget *d = mw.findChild<QDockWidget *>(name);
QVERIFY(d);
list << d;
}
mw.resizeDocks(list, sizes, orientation);
qApp->processEvents();
int totalFromList = 0;
int actualTotal = 0;
for (int i = 0; i < docks.count(); ++i) {
totalFromList += sizes[i];
QSize s = list[i]->size();
actualTotal += (orientation == Qt::Horizontal) ? s.width() : s.height();
// qDebug() << list[i] << list[i]->size() << sizes[i];
}
for (int i = 0; i < docks.count(); ++i) {
QSize s = list[i]->size();
int value = (orientation == Qt::Horizontal) ? s.width() : s.height();
QCOMPARE(value, qRound(sizes[i]*actualTotal/double(totalFromList)));
}
}
QTEST_MAIN(tst_QMainWindow)
#include "tst_qmainwindow.moc"

View File

@ -55,6 +55,8 @@ public slots:
private slots:
void benchmark_data() { generic_data(); }
void benchmark();
void benchmarkSelectPrepared_data() { generic_data(); }
void benchmarkSelectPrepared();
private:
// returns all database connections
@ -264,4 +266,42 @@ void tst_QSqlQuery::benchmark()
tst_Databases::safeDropTable( db, tableName );
}
void tst_QSqlQuery::benchmarkSelectPrepared()
{
QFETCH( QString, dbName );
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
if (tst_Databases::getMySqlVersion(db).section(QChar('.'), 0, 0).toInt() < 5)
QSKIP("Test requires MySQL >= 5.0");
QSqlQuery q(db);
const QString tableName(qTableName("benchmark", __FILE__, db));
tst_Databases::safeDropTable(db, tableName);
QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + "(id INT NOT NULL)"));
const int NUM_ROWS = 1000;
int expectedSum = 0;
QString fillQuery = "INSERT INTO " + tableName + " VALUES (0)";
for (int i = 1; i < NUM_ROWS; ++i) {
fillQuery += ", (" + QString::number(i) + ")";
expectedSum += i;
}
QVERIFY_SQL(q, exec(fillQuery));
QVERIFY_SQL(q, prepare("SELECT id FROM "+tableName));
QBENCHMARK {
QVERIFY_SQL(q, exec());
int sum = 0;
while (q.next())
sum += q.value(0).toInt();
QCOMPARE(sum, expectedSum);
}
tst_Databases::safeDropTable(db, tableName);
}
#include "main.moc"