diff options
author | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-08-17 19:55:41 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-08-17 19:55:41 +0200 |
commit | 5a039bf53e88a727cc52bfedb21796ebfade01a1 (patch) | |
tree | abce106bf1cb1042dcacd249152a11343caa0313 | |
parent | dbcf5730ac2d4f61f872e50126d3ce73e3f6031e (diff) | |
parent | 89302b8b88b2bfa9581bb15c1caa052cb6d76988 (diff) |
Merge dev into 5.6
Change-Id: I061f2513ef58f696e75b11928d89aaaf059659a3
95 files changed, 2408 insertions, 1387 deletions
@@ -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"` diff --git a/examples/widgets/mainwindows/application/mainwindow.cpp b/examples/widgets/mainwindows/application/mainwindow.cpp index 7a93a0cd22..86dfae166f 100644 --- a/examples/widgets/mainwindows/application/mainwindow.cpp +++ b/examples/widgets/mainwindows/application/mainwindow.cpp @@ -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] diff --git a/examples/widgets/mainwindows/sdi/mainwindow.cpp b/examples/widgets/mainwindows/sdi/mainwindow.cpp index 29618f9ac2..f59172f172 100644 --- a/examples/widgets/mainwindows/sdi/mainwindow.cpp +++ b/examples/widgets/mainwindows/sdi/mainwindow.cpp @@ -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() diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index 4a87488014..84515f4c6c 100644..100755 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -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); } 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 dc539cf66e..0af2cf12c6 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 fa9a69c5a1..f45a077d97 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 59df9d5a6c..87cdfe6f22 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 2bf48c5d94..e83f47929f 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 575bdf8a58..f0534077ae 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 53899dbb30..0b48b54334 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, ¤tPanelSize); - } + 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(¤tSize); + 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 caf327d913..5debd2fd0b 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_ diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index e942db2717..51223aef1f 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -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 */ diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index ba3ecfecd6..ee196f1aef 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -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,7 +312,9 @@ public class QtActivityDelegate if ((inputHints & (ImhEmailCharactersOnly | ImhUrlCharactersOnly)) != 0) { if ((inputHints & ImhUrlCharactersOnly) != 0) { inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI; - imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO; + + 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); diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 5d7918ea54..a1e7dac4d4 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -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); } }); } diff --git a/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch b/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch new file mode 100644 index 0000000000..cf383d7106 --- /dev/null +++ b/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch @@ -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, ¤tPanelSize); +- } ++ 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(¤tSize); ++ 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 + diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 51dd64c7cc..f8f306f614 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -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 diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index dfde5f236d..cdae149678 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -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; diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 04848a38e5..8828e09e8f 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -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>" diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index b1d5821a97..0a13f94f05 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -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")); - } + dirs.append(QCoreApplication::applicationDirPath()); + dirs.append(QCoreApplication::applicationDirPath() + QLatin1String("/data")); #endif } break; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e9fdb8c8ef..00d618745b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -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; - *(coreappdata()->manual_libpaths) = paths; + 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); } diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index eceba8d002..f771974a24 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -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,10 +289,11 @@ 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 = d->timerFactory->CreatePeriodicTimerWithCompletion( + HRESULT hr = runOnXamlThread([&]() { + IThreadPoolTimer *timer; + HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion( Callback<ITimerElapsedHandler>([handle, cancelHandle](IThreadPoolTimer *timer) { DWORD cancelResult = WaitForSingleObjectEx(cancelHandle, 0, TRUE); if (cancelResult == WAIT_OBJECT_0) { @@ -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) diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h index fd3d259c96..073aa1c121 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt_p.h +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -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(); diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index a9a790c14c..d3e7d51efd 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -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 diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 87a59c67c8..1f3ea36121 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -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. diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 509afadfc2..8ed0da7ca0 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -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. diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index f7aa7332dd..e49a1a098d 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -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. diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f240153f9f..5e2a5b86a4 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1935,6 +1935,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE } } #endif + e->eventAccepted = ev.isAccepted(); } void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index d10bd1e9eb..0430d5a4c6 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -690,6 +690,14 @@ QRect QPlatformWindow::windowGeometry() const } /*! + 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 implement heightForWidth(). diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 692ae862db..1b283dbb4f 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -138,6 +138,7 @@ public: QSize windowBaseSize() const; QSize windowSizeIncrement() const; QRect windowGeometry() const; + QRect windowFrameGeometry() const; QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const; protected: diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3ab2f59661..88cf2dac93 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -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(); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 453dbe81cf..ace1a4fe24 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -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, diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index cbc3bad7cd..cc0ca6bf81 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -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; diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 68ed3eae6e..8a5a6d4fcf 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -182,7 +182,8 @@ void QBackingStore::beginPaint(const QRegion ®ion) 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() diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index dbdd82e432..0898a20998 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -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; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 07e5a3d19b..0cf7e20605 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -1252,25 +1252,54 @@ 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); - buffer += 2; - vr = _mm_srli_epi64(vs, 6); - vg = _mm_srli_epi64(vs, 16 + 6 - 10); - vb = _mm_srli_epi64(vs, 32 + 6); - vr = _mm_and_si128(vr, cmask); - vg = _mm_and_si128(vg, gmask); - vb = _mm_and_si128(vb, cmask); - va = _mm_srli_epi64(vs, 48 + 14); - if (PixelOrder == PixelOrderRGB) - vr = _mm_slli_epi32(vr, 20); - else - vb = _mm_slli_epi32(vb, 20); - va = _mm_slli_epi32(va, 30); - __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va)); - vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0)); - _mm_storel_epi64((__m128i*)dest, vd); - dest += 2; + 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); + vb = _mm_srli_epi64(vs, 32 + 6); + vr = _mm_and_si128(vr, cmask); + vg = _mm_and_si128(vg, gmask); + vb = _mm_and_si128(vb, cmask); + va = _mm_srli_epi64(vs, 48 + 14); + if (PixelOrder == PixelOrderRGB) + vr = _mm_slli_epi32(vr, 20); + else + vb = _mm_slli_epi32(vb, 20); + va = _mm_slli_epi32(va, 30); + __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va)); + vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0)); + _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) diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 2c222b97c2..2fb9e7760c 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -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; diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index 290501047d..b701b224be 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -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 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 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 bool isOpaque() const + { + return (rgba & alphaMask()) == alphaMask(); + } + Q_DECL_CONSTEXPR bool isTransparent() const + { + return (rgba & alphaMask()) == 0; + } + + 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(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); } }; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 37be0afccf..246df127ad 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -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; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 7b28a4064f..b81e51bf2e 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -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; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index d2174c5e06..6b98c14205 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -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; diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 088cb80653..3e720ef597 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -115,8 +115,6 @@ public: QNetworkReplyImplPrivate(); void _q_startOperation(); - void _q_sourceReadyRead(); - void _q_sourceReadChannelFinished(); void _q_copyReadyRead(); void _q_copyReadChannelFinished(); void _q_bufferOutgoingData(); diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 35b541d739..371b9e0264 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -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; } /*! diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index b433c7e97f..23f0d26cbd 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -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; diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index c41061a9fd..b04ae8ee52 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -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; } diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri index f67f00672a..ebb64d15b4 100644 --- a/src/platformsupport/fontdatabases/mac/coretext.pri +++ b/src/platformsupport/fontdatabases/mac/coretext.pri @@ -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 diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 75c4065d66..1f000421cc 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -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 diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index a423ed5ae2..95af1210b3 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -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(); diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index be5e969d2b..b410e5f68e 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -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 } diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h index b5a2ef06e4..d737dc9c98 100644 --- a/src/plugins/platforms/android/androidjniinput.h +++ b/src/plugins/platforms/android/androidjniinput.h @@ -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(); diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index d264f74d66..b44340106d 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -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) diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm index e6c1ed79b2..43ff715161 100644 --- a/src/plugins/platforms/cocoa/main.mm +++ b/src/plugins/platforms/cocoa/main.mm @@ -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; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 3b8730151e..32a08dbb0d 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -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 ¶mList); ~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 diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 545e920057..2e6bfc95db 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -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 ¶mList) +{ + QCocoaIntegration::Options options; + foreach (const QString ¶m, 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 ¶mList) + : 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 */ diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp index 94ce23bd2c..707f3bf0ba 100644 --- a/src/plugins/platforms/winrt/qwinrtcursor.cpp +++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp @@ -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: - coreWindow->put_PointerCursor(Q_NULLPTR); + 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); } diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index 42ffe8f716..44aab266ca 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -35,38 +35,131 @@ ****************************************************************************/ #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); +} + +QWinRTEGLContext::~QWinRTEGLContext() { + 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); } -void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface) +void QWinRTEGLContext::initialize() { -#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); + + 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; + } } -EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface) { - 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); + 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) @@ -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 diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h index 958d623c4c..31a2124b03 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.h +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -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; - QFunctionPointer getProcAddress(const QByteArray &procName) 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; -protected: - EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface); + QSurfaceFormat format() const Q_DECL_OVERRIDE; + QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; private: - EGLSurface m_eglSurface; + QScopedPointer<QWinRTEGLContextPrivate> d_ptr; + Q_DECLARE_PRIVATE(QWinRTEGLContext) }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index c94b53ef1c..7bd9e87ca6 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -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 diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h index ce7fbabf49..cc3bce435f 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.h +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h @@ -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 *, diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 70ee6dbe6a..7079d46523 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -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) +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 + +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) { - m_screen = new QWinRTScreen; - screenAdded(m_screen); + 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); - m_success = true; +#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 diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index bbd6c1e41b..0115e034b5 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -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 diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 1d36bb31f6..89ad33657b 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -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()); - - if (!eglInitialize(d->eglDisplay, NULL, NULL)) - qCritical("Failed to initialize EGL: 0x%x", eglGetError()); - - // 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); - } - } - } - } - } - } + 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"); - 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()); + hr = applicationViewStatics->GetForCurrentView(&d->view); + RETURN_VOID_IF_FAILED("Could not access currentView"); + + // 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->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 -{ - Q_D(const QWinRTScreen); - return d->eglDisplay; -} - -EGLSurface QWinRTScreen::eglSurface() const -{ - Q_D(const QWinRTScreen); - return d->eglSurface; -} - -EGLConfig QWinRTScreen::eglConfig() const +Xaml::IDependencyObject *QWinRTScreen::canvas() 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(); - } + 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 diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index d34ce75748..796e6abb80 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -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) }; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index adc5dfb776..634d62ef24 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -36,47 +36,138 @@ #include "qwinrtwindow.h" #include "qwinrtscreen.h" +#include <private/qeventdispatcher_winrt_p.h> -#include <qpa/qwindowsysteminterface.h> +#include <EGL/egl.h> +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/eglext.h> + +#include <qfunctions_winrt.h> #include <qpa/qplatformscreen.h> +#include <qpa/qwindowsysteminterface.h> #include <QtGui/QGuiApplication> -#include <QtGui/QWindow> #include <QtGui/QOpenGLContext> +#include <QtGui/QWindow> +#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <qfunctions_winrt.h> -#include <windows.ui.viewmanagement.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 diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 3cfe346ab2..88c149b080 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -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 diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 086a232746..ea8a918dcf 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -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: { diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h index 379deb7e23..9d9e9286ec 100644 --- a/src/tools/qdoc/codeparser.h +++ b/src/tools/qdoc/codeparser.h @@ -40,7 +40,6 @@ QT_BEGIN_NAMESPACE class Config; -class Node; class QString; class QDocDatabase; diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 868b249290..774ff115b9 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -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(' '); diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index cab416370a..0f70777256 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -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 ¶m = 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,30 +700,29 @@ bool CppCodeParser::splitQmlMethodArg(const QString& arg, QString& module, QString& qmlTypeName) { - QStringList colonSplit(arg.split("::")); + 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 + type.clear(); + + QStringList colonSplit(name.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]; - } - else { - module.clear(); - qmlTypeName = blankSplit[1]; - } + if (colonSplit.size() > 2) { + module = colonSplit[0]; + qmlTypeName = colonSplit[1]; } else { - type.clear(); - if (colonSplit.size() > 2) { - module = colonSplit[0]; - qmlTypeName = colonSplit[1]; - } - else { - module.clear(); - qmlTypeName = colonSplit[0]; - } + module.clear(); + qmlTypeName = colonSplit[0]; } return true; } @@ -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_) - func->setPrivateSignal(); - else - func->addParameter(Parameter(pp.dataType_, "", pp.name_, pp.defaultValue_)); - } + if (isQPrivateSignal) + func->setPrivateSignal(); + if (!pvect.isEmpty()) { + func->setParameters(pvect); } } if (parentPathPtr != 0) @@ -2417,6 +2416,34 @@ bool CppCodeParser::makeFunctionNode(const QString& signature, } /*! + 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 the complete signature, and if \a attached is true, the diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h index 733418e27a..ec04482321 100644 --- a/src/tools/qdoc/cppcodeparser.h +++ b/src/tools/qdoc/cppcodeparser.h @@ -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") diff --git a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc index 0f9ca463bb..49cbfc0654 100644 --- a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc @@ -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. diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 5153b0de5c..7dfbbb1cb8 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -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 ¶m, 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) { diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index ebb54735d4..c803acbf60 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -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 -{ - return static_cast<FunctionNode *>(primaryFunctionMap_.value(name)); +FunctionNode *Aggregate::findFunctionNode(const QString& name, const QString& params) const +{ + 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 ¶meter, 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; diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index e9816dad19..596a71b6d5 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -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; } diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 5f2a61bb76..7f2e64b00c 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -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; diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h index 5d55ea48e1..80a92af4ed 100644 --- a/src/tools/qdoc/qdocdatabase.h +++ b/src/tools/qdoc/qdocdatabase.h @@ -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, diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 37194b911c..8db901bbc7 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -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()); diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp index 6f63624bf0..155e1de054 100644 --- a/src/tools/qdoc/qmlvisitor.cpp +++ b/src/tools/qdoc/qmlvisitor.cpp @@ -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; diff --git a/src/tools/qdoc/tokenizer.cpp b/src/tools/qdoc/tokenizer.cpp index a85c3b00d8..987fff548c 100644 --- a/src/tools/qdoc/tokenizer.cpp +++ b/src/tools/qdoc/tokenizer.cpp @@ -33,6 +33,7 @@ #include "config.h" #include "tokenizer.h" +#include "generator.h" #include <qfile.h> #include <qhash.h> diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index e0fd68d2e7..d64903e61e 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -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; diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h index 9e195c90ae..1fef15bc6d 100644 --- a/src/tools/qdoc/tree.h +++ b/src/tools/qdoc/tree.h @@ -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; diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 914ee8ec9c..2ebbaaee10 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -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 + } /*! diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index c61984a457..0a00086138 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -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) diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h index 93b005f64f..5d352f0124 100644 --- a/src/widgets/widgets/qdockarealayout_p.h +++ b/src/widgets/widgets/qdockarealayout_p.h @@ -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); diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 5d53e7def4..ff4bb3cc98 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -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 /*! diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h index ab6ee22748..70d78a7904 100644 --- a/src/widgets/widgets/qmainwindow.h +++ b/src/widgets/widgets/qmainwindow.h @@ -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; diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 141e3ed135..d9f8c8f991 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -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,53 +109,112 @@ 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); - return S_OK; + 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; + } + +private: + HRESULT __stdcall OnActivated(IActivatedEventArgs *args) Q_DECL_OVERRIDE + { + return base->OnActivated(args); } - HRESULT __stdcall SetWindow(ABI::Windows::UI::Core::ICoreWindow *) { return S_OK; } - HRESULT __stdcall Load(HSTRING) { return S_OK; } - HRESULT __stdcall Run() + + 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(); + } + if (!commandLine.isEmpty()) + args.append(commandLine.data()); + + bool quote = false; + bool escape = false; + for (int i = 0; i < commandLine.size(); ++i) { + switch (commandLine.at(i)) { + case '\\': + escape = true; + break; + case '"': + if (escape) { + escape = false; + break; + } + quote = !quote; + commandLine[i] = '\0'; + break; + case ' ': + if (quote) + break; + commandLine[i] = '\0'; + if (args.last()[0] != '\0') + args.append(commandLine.data() + i + 1); + // fall through + default: + if (args.last()[0] == '\0') + args.last() = commandLine.data() + i; + escape = false; // only quotes are escaped + break; + } + } + bool develMode = false; bool debugWait = false; - foreach (const QByteArray &arg, m_argv) { - if (arg == "-qdevel") + foreach (const char *arg, args) { + if (strcmp(arg, "-qdevel") == 0) develMode = true; - if (arg == "-qdebug") + if (strcmp(arg, "-qdebug") == 0) debugWait = true; } if (develMode) { @@ -173,98 +238,70 @@ public: while (!IsDebuggerPresent()) WaitForSingleObjectEx(GetCurrentThread(), 1, true); } - g_mainExitCode = main(m_argv.count(), m_argv.data()); + + ResumeThread(mainThread); return S_OK; } - HRESULT __stdcall Uninitialize() { return S_OK; } -private: - // Activation handler - HRESULT onActivated(Core::ICoreApplicationView *, Activation::IActivatedEventArgs *args) + HRESULT __stdcall OnFileActivated(IFileActivatedEventArgs *args) Q_DECL_OVERRIDE { - 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())); - } - } - } + Q_UNUSED(args); return S_OK; } - int m_argc; - QVector<char *> m_argv; - bool m_deleteArgv0; - EventRegistrationToken m_activationToken; -}; + HRESULT __stdcall OnSearchActivated(ISearchActivatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } -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) + HRESULT __stdcall OnShareTargetActivated(IShareTargetActivatedEventArgs *args) Q_DECL_OVERRIDE { - return (*frameworkView = Make<AppContainer>(m_argc, m_argv).Detach()) ? S_OK : E_OUTOFMEMORY; + Q_UNUSED(args); + return S_OK; } -private: - int m_argc; - char **m_argv; + + 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) { -#if _MSC_VER < 1900 int argc = 0; - char **argv, **env; + 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; -#else - QByteArray commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8(); - QVarLengthArray<char *> args; - args.append(commandLine.data()); - bool quote = false; - bool escape = false; - for (int i = 0; i < commandLine.size(); ++i) { - switch (commandLine.at(i)) { - case '\\': - escape = true; - break; - case '"': - if (escape) { - escape = false; - break; - } - quote = !quote; - commandLine[i] = '\0'; - break; - case ' ': - if (quote) - break; - commandLine[i] = '\0'; - if (args.last()[0] != '\0') - args.append(commandLine.data() + i + 1); - // fall through - default: - if (args.last()[0] == '\0') - args.last() = commandLine.data() + i; - escape = false; // only quotes are escaped - break; - } - } - int argc = args.size(); - char **argv = args.data(); - char **env = Q_NULLPTR; #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); } diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 0ffac21186..e810f48d6c 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -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 diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp index a07247316e..b681f9829a 100644 --- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp @@ -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 diff --git a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp index 63444b61ad..4408729e7c 100644 --- a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp +++ b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp @@ -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 diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp index b9d17bae62..b81a4e2c4c 100644 --- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp +++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp @@ -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. diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 3e98e630c2..e8d90edd2d 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -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 diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp index 3bf59910f3..48a15641b2 100644 --- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp +++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp @@ -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" diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 61586eb841..b98ab68ae9 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -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" diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index e8c533f301..6282028746 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -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" diff --git a/tests/benchmarks/sql/kernel/qsqlquery/main.cpp b/tests/benchmarks/sql/kernel/qsqlquery/main.cpp index 63aa6f7250..b5937b76b0 100644 --- a/tests/benchmarks/sql/kernel/qsqlquery/main.cpp +++ b/tests/benchmarks/sql/kernel/qsqlquery/main.cpp @@ -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" |