From fc0f784e54d5dce72cc6a7e4b1fad243dadfcd76 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 30 Sep 2013 01:31:27 +0300 Subject: Windows RT and Windows Phone QPA Change-Id: I6ab8af31f73439172e43fb709831821482b1cc99 Done-with: Kamil Trzcinski Done-with: Oliver Wolff Reviewed-by: Friedemann Kleint --- src/plugins/platforms/platforms.pro | 3 +- src/plugins/platforms/winrt/blit.hlsl | 14 + src/plugins/platforms/winrt/main.cpp | 74 ++ src/plugins/platforms/winrt/qwinrtbackingstore.cpp | 393 ++++++++ src/plugins/platforms/winrt/qwinrtbackingstore.h | 77 ++ src/plugins/platforms/winrt/qwinrtcursor.cpp | 153 +++ src/plugins/platforms/winrt/qwinrtcursor.h | 77 ++ src/plugins/platforms/winrt/qwinrteglcontext.cpp | 63 ++ src/plugins/platforms/winrt/qwinrteglcontext.h | 63 ++ .../platforms/winrt/qwinrteventdispatcher.cpp | 79 ++ .../platforms/winrt/qwinrteventdispatcher.h | 80 ++ src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 64 ++ src/plugins/platforms/winrt/qwinrtfontdatabase.h | 57 ++ src/plugins/platforms/winrt/qwinrtinputcontext.cpp | 300 ++++++ src/plugins/platforms/winrt/qwinrtinputcontext.h | 121 +++ src/plugins/platforms/winrt/qwinrtintegration.cpp | 192 ++++ src/plugins/platforms/winrt/qwinrtintegration.h | 86 ++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 1012 ++++++++++++++++++++ src/plugins/platforms/winrt/qwinrtscreen.h | 163 ++++ src/plugins/platforms/winrt/qwinrtservices.cpp | 138 +++ src/plugins/platforms/winrt/qwinrtservices.h | 80 ++ src/plugins/platforms/winrt/qwinrtwindow.cpp | 119 +++ src/plugins/platforms/winrt/qwinrtwindow.h | 72 ++ src/plugins/platforms/winrt/winrt.json | 3 + src/plugins/platforms/winrt/winrt.pro | 55 ++ 25 files changed, 3537 insertions(+), 1 deletion(-) create mode 100644 src/plugins/platforms/winrt/blit.hlsl create mode 100644 src/plugins/platforms/winrt/main.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtbackingstore.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtbackingstore.h create mode 100644 src/plugins/platforms/winrt/qwinrtcursor.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtcursor.h create mode 100644 src/plugins/platforms/winrt/qwinrteglcontext.cpp create mode 100644 src/plugins/platforms/winrt/qwinrteglcontext.h create mode 100644 src/plugins/platforms/winrt/qwinrteventdispatcher.cpp create mode 100644 src/plugins/platforms/winrt/qwinrteventdispatcher.h create mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.h create mode 100644 src/plugins/platforms/winrt/qwinrtinputcontext.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtinputcontext.h create mode 100644 src/plugins/platforms/winrt/qwinrtintegration.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtintegration.h create mode 100644 src/plugins/platforms/winrt/qwinrtscreen.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtscreen.h create mode 100644 src/plugins/platforms/winrt/qwinrtservices.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtservices.h create mode 100644 src/plugins/platforms/winrt/qwinrtwindow.cpp create mode 100644 src/plugins/platforms/winrt/qwinrtwindow.h create mode 100644 src/plugins/platforms/winrt/winrt.json create mode 100644 src/plugins/platforms/winrt/winrt.pro (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 377ca32e64..4a7c3b279f 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -15,7 +15,8 @@ mac { else: SUBDIRS += cocoa } -win32: SUBDIRS += windows +win32:!winrt: SUBDIRS += windows +winrt: SUBDIRS += winrt qnx { SUBDIRS += qnx diff --git a/src/plugins/platforms/winrt/blit.hlsl b/src/plugins/platforms/winrt/blit.hlsl new file mode 100644 index 0000000000..170e7f40ca --- /dev/null +++ b/src/plugins/platforms/winrt/blit.hlsl @@ -0,0 +1,14 @@ +uniform SamplerState Sampler : register(s0); +uniform Texture2D Texture : register(t0); + +void blitvs(in float4 pos0 : TEXCOORD0, in float2 tex0 : TEXCOORD1, + out float4 gl_Position : SV_POSITION, out float2 coord : TEXCOORD0) +{ + coord = tex0; + gl_Position = pos0 * float4(1.0, -1.0, 1.0, 1.0); +} + +float4 blitps(in float4 gl_Position : SV_POSITION, in float2 coord : TEXCOORD0) : SV_TARGET0 +{ + return Texture.Sample(Sampler, coord); +} diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp new file mode 100644 index 0000000000..89d560dbe3 --- /dev/null +++ b/src/plugins/platforms/winrt/main.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtintegration.h" + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "winrt.json") + +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWinRTIntegrationPlugin::keys() const +{ + return QStringList(QStringLiteral("WinRT")); +} + +QPlatformIntegration *QWinRTIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (!system.compare(QLatin1String("winrt"), Qt::CaseInsensitive)) + return QWinRTIntegration::create(); + + return 0; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp new file mode 100644 index 0000000000..b219548788 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -0,0 +1,393 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtbackingstore.h" + +#include "qwinrtscreen.h" +#include "qwinrtwindow.h" +#include "qwinrteglcontext.h" +#include + +#include +#include + +#include + +// Generated shader headers +#include "blitps.h" +#include "blitvs.h" + +namespace { // Utility namespace for writing out an ANGLE-compatible binary blob + +// Must match packaged ANGLE +enum : quint32 { + AngleMajorVersion = 1, + AngleMinorVersion = 2, + AngleBuildRevision = 2446, + AngleVersion = ((AngleMajorVersion << 24) | (AngleMinorVersion << 16) | AngleBuildRevision), + AngleOptimizationLevel = (1 << 14) +}; + +struct ShaderString +{ + ShaderString(const char *data = 0) : data(data) { } + const char *data; +}; + +// ANGLE stream compatibility - when size_t is 32-bit, QDataStream::writeBytes() also works +QDataStream &operator<<(QDataStream &stream, const ShaderString &shaderString) +{ + if (!shaderString.data) + return stream << size_t(0); + + size_t len = strlen(shaderString.data); + stream << len; + stream.writeRawData(shaderString.data, int(len)); + return stream; +} + +struct Attribute +{ + Attribute(GLenum type = 0, const char *name = 0, quint32 index = 0) + : type(type), name(name), index(index) { } + GLenum type; + ShaderString name; + quint32 index; +}; + +struct Sampler +{ + enum TextureType { Texture2D, TextureCube }; + Sampler(bool active = false, GLint unit = 0, TextureType type = Texture2D) + : active(active), unit(unit), type(type) { } + bool active; + GLint unit; + TextureType type; +}; + +struct Uniform +{ + Uniform() { } + Uniform(GLenum type, quint32 precision, const char *name, quint32 arraySize, + quint32 psRegisterIndex, quint32 vsRegisterIndex, quint32 registerCount) + : type(type), precision(precision), name(name), arraySize(arraySize) + , psRegisterIndex(psRegisterIndex), vsRegisterIndex(vsRegisterIndex), registerCount(registerCount) { } + GLenum type; + quint32 precision; + ShaderString name; + quint32 arraySize; + quint32 psRegisterIndex; + quint32 vsRegisterIndex; + quint32 registerCount; +}; + +struct UniformIndex +{ + UniformIndex(const char *name = 0, quint32 element = 0, quint32 index = 0) + : name(name), element(element), index(index) { } + ShaderString name; + quint32 element; + quint32 index; +}; + +static const QByteArray createAngleBinary( + const QVector &attributes, + const QVector &textureSamplers, + const QVector &vertexSamplers, + const QVector &uniforms, + const QVector &uniformIndex, + const QByteArray &pixelShader, + const QByteArray &vertexShader, + const QByteArray &geometryShader = QByteArray(), + bool usesPointSize = false) +{ + QByteArray binary; + + QDataStream stream(&binary, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + + stream << quint32(GL_PROGRAM_BINARY_ANGLE) + << quint32(AngleVersion) + << quint32(AngleOptimizationLevel); + + // Vertex attributes + for (int i = 0; i < 16; ++i) { + if (i < attributes.size()) + stream << quint32(attributes[i].type) << attributes[i].name << attributes[i].index; + else + stream << quint32(GL_NONE) << ShaderString() << qint32(-1); + } + + // Texture units + for (int i = 0; i < 16; ++i) { + if (i < textureSamplers.size()) + stream << textureSamplers[i].active << textureSamplers[i].unit << qint32(textureSamplers[i].type); + else + stream << false << qint32(0) << qint32(Sampler::Texture2D); + } + + // Vertex texture units + for (int i = 0; i < 16; ++i) { + if (i < vertexSamplers.size()) + stream << vertexSamplers[i].active << vertexSamplers[i].unit << qint32(vertexSamplers[i].type); + else + stream << false << qint32(0) << qint32(Sampler::Texture2D); + } + + stream << vertexSamplers.size() + << textureSamplers.size() + << usesPointSize; + + stream << size_t(uniforms.size()); + foreach (const Uniform &uniform, uniforms) { + stream << uniform.type << uniform.precision << uniform.name << uniform.arraySize + << uniform.psRegisterIndex << uniform.vsRegisterIndex << uniform.registerCount; + } + + stream << size_t(uniformIndex.size()); + foreach (const UniformIndex &index, uniformIndex) + stream << index.name << index.element << index.index; + + stream << quint32(pixelShader.size()) + << quint32(vertexShader.size()) + << quint32(geometryShader.size()); + + // ANGLE requires that we query the adapter for its LUID. Later on, it may be useful + // for checking feature level support, picking the best adapter on the system, etc. + IDXGIFactory1 *dxgiFactory; + if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) { + qCritical("QWinRTBackingStore: failed to create DXGI factory."); + return QByteArray(); + } + IDXGIAdapter *dxgiAdapter; + if (FAILED(dxgiFactory->EnumAdapters(0, &dxgiAdapter))) { + qCritical("QWinRTBackingStore:: failed to enumerate adapter."); + dxgiFactory->Release(); + return QByteArray(); + } + DXGI_ADAPTER_DESC desc; + dxgiAdapter->GetDesc(&desc); + dxgiAdapter->Release(); + QByteArray guid(sizeof(GUID), '\0'); + memcpy(guid.data(), &desc.AdapterLuid, sizeof(LUID)); + stream.writeRawData(guid.constData(), guid.size()); + stream.writeRawData(pixelShader.constData(), pixelShader.size()); + stream.writeRawData(vertexShader.constData(), vertexShader.size()); + if (!geometryShader.isEmpty()) + stream.writeRawData(geometryShader.constData(), geometryShader.size()); + + return binary; +} + +} // namespace + +QT_BEGIN_NAMESPACE + +static const GLfloat normCoords[] = { -1, 1, 1, 1, 1, -1, -1, -1 }; +static const GLfloat quadCoords[] = { 0, 0, 1, 0, 1, 1, 0, 1 }; + +QWinRTBackingStore::QWinRTBackingStore(QWindow *window) + : QPlatformBackingStore(window) + , m_context(new QOpenGLContext) + , m_shaderProgram(0) + , m_fbo(0) + , m_texture(0) + , m_screen(static_cast(window->screen()->handle())) +{ + window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap + + m_context->setFormat(window->requestedFormat()); + m_context->setScreen(window->screen()); + m_context->create(); + + m_context->makeCurrent(window); + glGenFramebuffers(1, &m_fbo); + glGenRenderbuffers(1, &m_rbo); + glGenTextures(1, &m_texture); + m_shaderProgram = glCreateProgram(); + +#if 0 // Standard GLES passthrough shader program + static const char *vertexShaderSource = + "attribute vec4 pos0;\n" + "attribute vec2 tex0;\n" + "varying vec2 coord;\n" + "void main() {\n" + " coord = tex0;\n" + " gl_Position = pos0;\n" + "}\n"; + static const char *fragmentShaderSource = + "uniform sampler2D texture;\n" + "varying highp vec2 coord;\n" + "void main() {\n" + " gl_FragColor = texture2D(texture, coord);\n" + "}\n"; + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + glAttachShader(m_shaderProgram, vertexShader); + glAttachShader(m_shaderProgram, fragmentShader); + glLinkProgram(m_shaderProgram); +#else // Precompiled passthrough shader + QVector attributes = QVector() << Attribute(GL_FLOAT_VEC4, "pos0", 0) + << Attribute(GL_FLOAT_VEC2, "tex0", 1); + QVector textureSamplers = QVector() << Sampler(true, 0, Sampler::Texture2D); + QVector vertexSamplers; + QVector uniforms = QVector() << Uniform(GL_SAMPLER_2D, 0, "texture", 0, 0, -1, 1); + QVector uniformsIndex = QVector() << UniformIndex("texture", 0, 0); + QByteArray pixelShader(reinterpret_cast(q_blitps), sizeof(q_blitps)); + QByteArray vertexShader(reinterpret_cast(q_blitvs), sizeof(q_blitvs)); + QByteArray binary = createAngleBinary(attributes, textureSamplers, vertexSamplers, + uniforms, uniformsIndex, pixelShader, vertexShader); + glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size()); +#endif + m_context->doneCurrent(); + resize(window->size(), QRegion()); +} + +QWinRTBackingStore::~QWinRTBackingStore() +{ + glDeleteBuffers(1, &m_fbo); + glDeleteRenderbuffers(1, &m_rbo); + glDeleteTextures(1, &m_texture); + glDeleteProgram(m_shaderProgram); +} + +QPaintDevice *QWinRTBackingStore::paintDevice() +{ + return m_paintDevice.data(); +} + +void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset) + + const QImage *image = static_cast(m_paintDevice.data()); + + m_context->makeCurrent(window); + + // Blitting the entire image width trades zero image copy/relayout for a larger texture upload. + // Since we're blitting the whole width anyway, the boundingRect() is used in the assumption that + // we don't repeat upload. This is of course dependent on the distance between update regions. + // Ideally, we would use the GL_EXT_unpack_subimage extension, which should be possible to implement + // since D3D11_MAPPED_SUBRESOURCE supports RowPitch (see below). + // Note that single-line blits in a loop are *very* slow, so reducing calls to glTexSubImage2D + // is probably a good idea anyway. + glBindTexture(GL_TEXTURE_2D, m_texture); + QRect bounds = region.boundingRect(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), m_size.width(), bounds.height(), + GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y())); + // TODO: Implement GL_EXT_unpack_subimage in ANGLE for more minimal uploads + //glPixelStorei(GL_UNPACK_ROW_LENGTH, image->bytesPerLine()); + //glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x(), bounds.y(), bounds.width(), bounds.height(), + // GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y()) + bounds.x() * 4); + + // Bind render buffer + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); + + // Bind position + glUseProgram(m_shaderProgram); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, normCoords); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quadCoords); + + // Render + glViewport(0, 0, m_size.width(), m_size.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // Unbind + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glUseProgram(0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + // fast blit - TODO: perform the blit inside swap buffers instead + glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0); + glBlitFramebufferANGLE(0, 0, m_size.width(), m_size.height(), // TODO: blit only the changed rectangle + 0, 0, m_size.width(), m_size.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_context->swapBuffers(window); + m_context->doneCurrent(); +} + +void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents) +{ + Q_UNUSED(staticContents) + if (m_size == size) + return; + + m_size = size; + m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied)); + + m_context->makeCurrent(window()); + // Input texture + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, m_size.width(), m_size.height(), + 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + // Render buffer + glBindRenderbuffer(GL_RENDERBUFFER, m_rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, m_size.width(), m_size.height()); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + m_context->doneCurrent(); +} + +void QWinRTBackingStore::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region) +} + +void QWinRTBackingStore::endPaint() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h new file mode 100644 index 0000000000..8be549b441 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTBACKINGSTORE_H +#define QWINRTBACKINGSTORE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWinRTScreen; +class QOpenGLContext; + +class QWinRTBackingStore : public QPlatformBackingStore +{ +public: + explicit QWinRTBackingStore(QWindow *window); + ~QWinRTBackingStore(); + QPaintDevice *paintDevice(); + void beginPaint(const QRegion &); + void endPaint(); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size, const QRegion &staticContents); + +private: + QSize m_size; + QScopedPointer m_paintDevice; + QScopedPointer m_context; + quint32 m_shaderProgram; + quint32 m_fbo; + quint32 m_rbo; + quint32 m_texture; + QWinRTScreen *m_screen; +}; + +QT_END_NAMESPACE + +#endif // QWINRTBACKINGSTORE_H diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp new file mode 100644 index 0000000000..8241560cef --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtcursor.h" + +#include +#include +#include +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +QWinRTCursor::QWinRTCursor(ICoreWindow *window) : m_window(window), m_cursorFactory(nullptr) +{ +#ifndef Q_OS_WINPHONE + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), &m_cursorFactory); +#endif +} + +QWinRTCursor::~QWinRTCursor() +{ + if (m_cursorFactory) + m_cursorFactory->Release(); +} + +#ifndef QT_NO_CURSOR +void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *) +{ +#ifndef Q_OS_WINPHONE + if (!m_cursorFactory) + return; + + CoreCursorType type; + switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) { + case Qt::BlankCursor: + m_window->put_PointerCursor(nullptr); + return; + default: + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: + case Qt::DragLinkCursor: + // (unavailable) + case Qt::ArrowCursor: + type = CoreCursorType_Arrow; + break; + case Qt::UpArrowCursor: + type = CoreCursorType_UpArrow; + break; + case Qt::CrossCursor: + type = CoreCursorType_Cross; + break; + case Qt::WaitCursor: + case Qt::BusyCursor: + type = CoreCursorType_Wait; + break; + case Qt::IBeamCursor: + type = CoreCursorType_IBeam; + break; + case Qt::SizeVerCursor: + case Qt::SplitVCursor: + type = CoreCursorType_SizeNorthSouth; + break; + case Qt::SizeHorCursor: + case Qt::SplitHCursor: + type = CoreCursorType_SizeWestEast; + break; + case Qt::SizeBDiagCursor: + type = CoreCursorType_SizeNortheastSouthwest; + break; + case Qt::SizeFDiagCursor: + type = CoreCursorType_SizeNorthwestSoutheast; + break; + case Qt::SizeAllCursor: + type = CoreCursorType_SizeAll; + break; + case Qt::PointingHandCursor: + type = CoreCursorType_Hand; + break; + case Qt::ForbiddenCursor: + type = CoreCursorType_UniversalNo; + break; + case Qt::WhatsThisCursor: + type = CoreCursorType_Help; + break; + case Qt::BitmapCursor: + case Qt::CustomCursor: + // TODO: figure out if arbitrary bitmaps can be made into resource IDs + // For now, we don't get enough info from QCursor to set a custom cursor + type = CoreCursorType_Custom; + break; + } + + ICoreCursor *cursor; + if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor))) + m_window->put_PointerCursor(cursor); +#endif // Q_OS_WINPHONE +} +#endif // QT_NO_CURSOR + +QPoint QWinRTCursor::pos() const +{ +#ifdef Q_OS_WINPHONE + return QPlatformCursor::pos(); +#else + Point point; + m_window->get_PointerPosition(&point); + return QPoint(point.X, point.Y); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h new file mode 100644 index 0000000000..f7b301a98b --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtcursor.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTCURSOR_H +#define QWINRTCURSOR_H + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreWindow; + struct ICoreCursorFactory; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTCursor : public QPlatformCursor +{ +public: + explicit QWinRTCursor(ABI::Windows::UI::Core::ICoreWindow *window); + ~QWinRTCursor(); +#ifndef QT_NO_CURSOR + void changeCursor(QCursor * windowCursor, QWindow *); +#endif + QPoint pos() const; + +private: + ABI::Windows::UI::Core::ICoreWindow *m_window; + ABI::Windows::UI::Core::ICoreCursorFactory *m_cursorFactory; +}; + +QT_END_NAMESPACE + +#endif // QWINRTCURSOR_H diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp new file mode 100644 index 0000000000..014378f896 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrteglcontext.h" + +QT_BEGIN_NAMESPACE + +QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface) + : QEGLPlatformContext(format, share, display, EGL_OPENGL_ES_API), m_eglSurface(surface) +{ +} + +EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +{ + 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; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h new file mode 100644 index 0000000000..c065847374 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSEGLCONTEXT_H +#define QWINDOWSEGLCONTEXT_H + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTEGLContext : public QEGLPlatformContext +{ +public: + explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface); + +protected: + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface); + +private: + EGLSurface m_eglSurface; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSEGLCONTEXT_H diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp new file mode 100644 index 0000000000..3fada75b25 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrteventdispatcher.h" +#include +#include +#include +#include +#include + +#include +#include + +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::Foundation; + +QT_BEGIN_NAMESPACE + +QWinRTEventDispatcher::QWinRTEventDispatcher(ICoreDispatcher *dispatcher, QObject *parent) + : QEventDispatcherWinRT(parent) + , m_dispatcher(dispatcher) +{ +} + +bool QWinRTEventDispatcher::hasPendingEvents() +{ + return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued(); +} + +bool QWinRTEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + if (m_dispatcher) + m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent); + + const bool didProcess = QWindowSystemInterface::sendWindowSystemEvents(flags); + + return QEventDispatcherWinRT::processEvents(flags & ~QEventLoop::WaitForMoreEvents) || didProcess; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h new file mode 100644 index 0000000000..275a508b3c --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTEVENTDISPATCHER_H +#define QWINRTEVENTDISPATCHER_H + +#include +#include + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreDispatcher; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTEventDispatcher : public QEventDispatcherWinRT +{ + Q_OBJECT +public: + explicit QWinRTEventDispatcher(ABI::Windows::UI::Core::ICoreDispatcher *dispatcher, QObject *parent = 0); + +protected: + bool hasPendingEvents(); + bool processEvents(QEventLoop::ProcessEventsFlags flags); + +private: + ABI::Windows::UI::Core::ICoreDispatcher *m_dispatcher; + + friend class QWinRTIntegration; +}; + +QT_END_NAMESPACE + +#endif // QWINRTEVENTDISPATCHER_H diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp new file mode 100644 index 0000000000..c7fa339fad --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtfontdatabase.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QString QWinRTFontDatabase::fontDir() const +{ + QString fontDirectory = QBasicFontDatabase::fontDir(); + if (!QFile::exists(fontDirectory)) { + // Fall back to app directory + fonts, and just app directory after that + const QString applicationDirPath = QCoreApplication::applicationDirPath(); + fontDirectory = applicationDirPath + QLatin1String("/fonts"); + if (!QFile::exists(fontDirectory)) { + qWarning("No fonts directory found in application package."); + fontDirectory = applicationDirPath; + } + } + return fontDirectory; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h new file mode 100644 index 0000000000..49e32470c2 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTFONTDATABASE_H +#define QWINRTFONTDATABASE_H + +#include + +QT_BEGIN_NAMESPACE + +class QWinRTFontDatabase : public QBasicFontDatabase +{ +public: + QString fontDir() const; +}; + +QT_END_NAMESPACE + +#endif // QWINRTFONTDATABASE_H diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp new file mode 100644 index 0000000000..bc15f1e448 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtinputcontext.h" +#include + +#include +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::ViewManagement; +using namespace ABI::Windows::UI::Core; + +#ifdef Q_OS_WINPHONE +#include +using namespace ABI::Windows::Phone::UI::Core; +#endif + +typedef ITypedEventHandler InputPaneVisibilityHandler; + +QT_BEGIN_NAMESPACE + +/*! + \class QWinRTInputContext + \brief Manages Input Method visibility + \internal + \ingroup qt-qpa-winrt + + Listens to the native virtual keyboard for hide/show events and provides + hints to the OS for showing/hiding. On WinRT, showInputPanel()/hideInputPanel() + have no effect because WinRT dictates that keyboard presence is user-driven: + (http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx) + Windows Phone, however, supports direct hiding/showing of the keyboard. +*/ + +QWinRTInputContext::QWinRTInputContext(ICoreWindow *window) + : m_window(window) +{ + IInputPaneStatics *statics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), + &statics))) { + qWarning(Q_FUNC_INFO ": failed to retrieve input pane statics."); + return; + } + + IInputPane *inputPane; + statics->GetForCurrentView(&inputPane); + statics->Release(); + if (inputPane) { + EventRegistrationToken showToken, hideToken; + inputPane->add_Showing(Callback( + this, &QWinRTInputContext::onShowing).Get(), &showToken); + inputPane->add_Hiding(Callback( + this, &QWinRTInputContext::onHiding).Get(), &hideToken); + + Rect rect; + inputPane->get_OccludedRect(&rect); + m_keyboardRect = QRectF(rect.X, rect.Y, rect.Width, rect.Height); + m_isInputPanelVisible = !m_keyboardRect.isEmpty(); + } else { + qWarning(Q_FUNC_INFO ": failed to retrieve InputPane."); + } +} + +QRectF QWinRTInputContext::keyboardRect() const +{ + return m_keyboardRect; +} + +bool QWinRTInputContext::isInputPanelVisible() const +{ + return m_isInputPanelVisible; +} + +HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEventArgs *) +{ + m_isInputPanelVisible = true; + emitInputPanelVisibleChanged(); + + Rect rect; + pane->get_OccludedRect(&rect); + setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height)); + + return S_OK; +} + +HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEventArgs *) +{ + m_isInputPanelVisible = false; + emitInputPanelVisibleChanged(); + + Rect rect; + pane->get_OccludedRect(&rect); + setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height)); + + return S_OK; +} + +void QWinRTInputContext::setKeyboardRect(const QRectF rect) +{ + if (m_keyboardRect == rect) + return; + + m_keyboardRect = rect; + emitKeyboardRectChanged(); +} + +#ifdef Q_OS_WINPHONE + +void QWinRTInputContext::showInputPanel() +{ + ICoreWindowKeyboardInput *input; + if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { + input->put_IsKeyboardInputEnabled(true); + input->Release(); + } +} + +void QWinRTInputContext::hideInputPanel() +{ + ICoreWindowKeyboardInput *input; + if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) { + input->put_IsKeyboardInputEnabled(false); + input->Release(); + } +} + +#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_window; + break; + } + return S_OK; +} + +HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal) +{ + // Return the window's element provider + IInspectable *hostProvider; + HRESULT hr = m_window->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 + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h new file mode 100644 index 0000000000..0a35f9b6e1 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTINPUTCONTEXT_H +#define QWINRTINPUTCONTEXT_H + +#include +#include + +#include +#ifndef Q_OS_WINPHONE +# include +#endif + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct ICoreWindow; + } + namespace ViewManagement { + struct IInputPane; + struct IInputPaneVisibilityEventArgs; + } + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTInputContext : public QPlatformInputContext +#ifndef Q_OS_WINPHONE + , public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + IRawElementProviderSimple, ITextProvider, IValueProvider> +#endif // !Q_OS_WINPHONE +{ +public: + explicit QWinRTInputContext(ABI::Windows::UI::Core::ICoreWindow *window); + + QRectF keyboardRect() const; + + bool isInputPanelVisible() const; + +#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 + +private: + HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *, + ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *); + HRESULT onHiding(ABI::Windows::UI::ViewManagement::IInputPane *, + ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *); + void setKeyboardRect(const QRectF rect); + + ABI::Windows::UI::Core::ICoreWindow *m_window; + QRectF m_keyboardRect; + bool m_isInputPanelVisible; +}; + +QT_END_NAMESPACE + +#endif // QWINRTINPUTCONTEXT_H diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp new file mode 100644 index 0000000000..9113ffeb19 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtintegration.h" +#include "qwinrtwindow.h" +#include "qwinrteventdispatcher.h" +#include "qwinrtbackingstore.h" +#include "qwinrtscreen.h" +#include "qwinrtinputcontext.h" +#include "qwinrtservices.h" +#include "qwinrteglcontext.h" +#include "qwinrtfontdatabase.h" + +#include + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::ViewManagement; +using namespace ABI::Windows::ApplicationModel::Core; + +static IUISettings *getSettings() +{ + static IUISettings *settings = 0; + if (!settings) { + if (FAILED(RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(), + reinterpret_cast(&settings)))) { + qWarning("Could not activate UISettings."); + } + } + return settings; +} + +QT_BEGIN_NAMESPACE + +QWinRTIntegration::QWinRTIntegration() + : m_success(false) + , m_fontDatabase(new QWinRTFontDatabase) + , m_services(new QWinRTServices) +{ + // Obtain the WinRT Application, view, and window + ICoreApplication *application; + if (FAILED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + IID_PPV_ARGS(&application)))) + qCritical("Could not attach to the application factory."); + + ICoreApplicationView *view; + if (FAILED(application->GetCurrentView(&view))) { + qCritical("Could not obtain the application view - have you started outside of WinRT?"); + return; + } + + // Get core window (will act as our screen) + ICoreWindow *window; + if (FAILED(view->get_CoreWindow(&window))) { + qCritical("Could not obtain the application window - have you started outside of WinRT?"); + return; + } + window->Activate(); + m_screen = new QWinRTScreen(window); + screenAdded(m_screen); + + // Get event dispatcher + ICoreDispatcher *dispatcher; + if (FAILED(window->get_Dispatcher(&dispatcher))) + qCritical("Could not capture UI Dispatcher"); + m_eventDispatcher = new QWinRTEventDispatcher(dispatcher); + + m_success = true; +} + +QWinRTIntegration::~QWinRTIntegration() +{ + Windows::Foundation::Uninitialize(); +} + +QAbstractEventDispatcher *QWinRTIntegration::guiThreadEventDispatcher() const +{ + return m_eventDispatcher; +} + +bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: + case OpenGL: + case ApplicationState: + return true; + default: + return QPlatformIntegration::hasCapability(cap); + } +} + +QVariant QWinRTIntegration::styleHint(StyleHint hint) const +{ + switch (hint) { + case CursorFlashTime: + if (IUISettings *settings = getSettings()) { + quint32 blinkRate; + settings->get_CaretBlinkRate(&blinkRate); + return blinkRate; + } + break; + case MouseDoubleClickInterval: + if (IUISettings *settings = getSettings()) { + quint32 doubleClickTime; + settings->get_DoubleClickTime(&doubleClickTime); + return doubleClickTime; + } + case ShowIsFullScreen: + return true; + default: + break; + } + return QPlatformIntegration::styleHint(hint); +} + +QPlatformWindow *QWinRTIntegration::createPlatformWindow(QWindow *window) const +{ + return new QWinRTWindow(window); +} + +QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *window) const +{ + return new QWinRTBackingStore(window); +} + +QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QWinRTScreen *screen = static_cast(context->screen()->handle()); + return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface()); +} + +QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const +{ + return m_fontDatabase; +} + +QPlatformInputContext *QWinRTIntegration::inputContext() const +{ + return m_screen->inputContext(); +} + +QPlatformServices *QWinRTIntegration::services() const +{ + return m_services; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h new file mode 100644 index 0000000000..b53c1cf7d2 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTINTEGRATION_H +#define QWINRTINTEGRATION_H + +#include + +QT_BEGIN_NAMESPACE + +class QAbstractEventDispatcher; +class QWinRTScreen; + +class QWinRTIntegration : public QPlatformIntegration +{ +private: + explicit QWinRTIntegration(); +public: + ~QWinRTIntegration(); + + static QWinRTIntegration *create() + { + QWinRTIntegration *integration = new QWinRTIntegration; + return integration->m_success ? integration : 0; + } + + bool hasCapability(QPlatformIntegration::Capability cap) const; + QVariant styleHint(StyleHint hint) const; + + QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QAbstractEventDispatcher *guiThreadEventDispatcher() const; + QPlatformFontDatabase *fontDatabase() const; + QPlatformInputContext *inputContext() const; + QPlatformServices *services() const; + +private: + bool m_success; + QWinRTScreen *m_screen; + QAbstractEventDispatcher *m_eventDispatcher; + QPlatformFontDatabase *m_fontDatabase; + QPlatformServices *m_services; +}; + +QT_END_NAMESPACE + +#endif // QWINRTINTEGRATION_H diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp new file mode 100644 index 0000000000..93c2736238 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtscreen.h" + +#include "qwinrtbackingstore.h" +#include "qwinrtinputcontext.h" +#include "qwinrtcursor.h" +#include "qwinrteglcontext.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::System; +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; + +typedef ITypedEventHandler ActivatedHandler; +typedef ITypedEventHandler ClosedHandler; +typedef ITypedEventHandler CharacterReceivedHandler; +typedef ITypedEventHandler InputEnabledHandler; +typedef ITypedEventHandler KeyHandler; +typedef ITypedEventHandler PointerHandler; +typedef ITypedEventHandler SizeChangedHandler; +typedef ITypedEventHandler VisibilityChangedHandler; +typedef ITypedEventHandler AutomationProviderRequestedHandler; + +QT_BEGIN_NAMESPACE + +static inline Qt::ScreenOrientation qOrientationFromNative(DisplayOrientations orientation) +{ + switch (orientation) { + default: + case DisplayOrientations_None: + return Qt::PrimaryOrientation; + case DisplayOrientations_Landscape: + return Qt::LandscapeOrientation; + case DisplayOrientations_LandscapeFlipped: + return Qt::InvertedLandscapeOrientation; + case DisplayOrientations_Portrait: + return Qt::PortraitOrientation; + case DisplayOrientations_PortraitFlipped: + return Qt::InvertedPortraitOrientation; + } +} + +static inline Qt::KeyboardModifiers qKeyModifiers(ICoreWindow *window) +{ + Qt::KeyboardModifiers mods; + CoreVirtualKeyStates mod; + window->GetAsyncKeyState(VirtualKey_Shift, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ShiftModifier; + window->GetAsyncKeyState(VirtualKey_Menu, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::AltModifier; + window->GetAsyncKeyState(VirtualKey_Control, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::ControlModifier; + window->GetAsyncKeyState(VirtualKey_LeftWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) { + mods |= Qt::MetaModifier; + } else { + window->GetAsyncKeyState(VirtualKey_RightWindows, &mod); + if (mod == CoreVirtualKeyStates_Down) + mods |= Qt::MetaModifier; + } + return mods; +} + +// Return Qt meta key from VirtualKey (discard character keys) +static inline Qt::Key qMetaKeyFromVirtual(VirtualKey key) +{ + switch (key) { + + default: + return Qt::Key_unknown; + + // Modifiers + case VirtualKey_Shift: + case VirtualKey_LeftShift: + case VirtualKey_RightShift: + return Qt::Key_Shift; + case VirtualKey_Control: + case VirtualKey_LeftControl: + case VirtualKey_RightControl: + return Qt::Key_Control; + case VirtualKey_Menu: + case VirtualKey_LeftMenu: + case VirtualKey_RightMenu: + return Qt::Key_Alt; + case VirtualKey_LeftWindows: + case VirtualKey_RightWindows: + return Qt::Key_Meta; + + // Toggle keys + case VirtualKey_CapitalLock: + return Qt::Key_CapsLock; + case VirtualKey_NumberKeyLock: + return Qt::Key_NumLock; + case VirtualKey_Scroll: + return Qt::Key_ScrollLock; + + // East-Asian language keys + case VirtualKey_Kana: + //case VirtualKey_Hangul: // Same enum as Kana + return Qt::Key_Kana_Shift; + case VirtualKey_Junja: + return Qt::Key_Hangul_Jeonja; + case VirtualKey_Kanji: + //case VirtualKey_Hanja: // Same enum as Kanji + return Qt::Key_Kanji; + case VirtualKey_ModeChange: + return Qt::Key_Mode_switch; + case VirtualKey_Convert: + return Qt::Key_Henkan; + case VirtualKey_NonConvert: + return Qt::Key_Muhenkan; + + // Misc. keys + case VirtualKey_Cancel: + return Qt::Key_Cancel; + case VirtualKey_Back: + return Qt::Key_Back; + case VirtualKey_Clear: + return Qt::Key_Clear; + case VirtualKey_Application: + return Qt::Key_ApplicationLeft; + case VirtualKey_Sleep: + return Qt::Key_Sleep; + case VirtualKey_Pause: + return Qt::Key_Pause; + case VirtualKey_Space: + return Qt::Key_Space; + case VirtualKey_PageUp: + return Qt::Key_PageUp; + case VirtualKey_PageDown: + return Qt::Key_PageDown; + case VirtualKey_End: + return Qt::Key_End; + case VirtualKey_Home: + return Qt::Key_Home; + case VirtualKey_Left: + return Qt::Key_Left; + case VirtualKey_Up: + return Qt::Key_Up; + case VirtualKey_Right: + return Qt::Key_Right; + case VirtualKey_Down: + return Qt::Key_Down; + case VirtualKey_Select: + return Qt::Key_Select; + case VirtualKey_Print: + return Qt::Key_Print; + case VirtualKey_Execute: + return Qt::Key_Execute; + case VirtualKey_Insert: + return Qt::Key_Insert; + case VirtualKey_Delete: + return Qt::Key_Delete; + case VirtualKey_Help: + return Qt::Key_Help; + case VirtualKey_Snapshot: + return Qt::Key_Camera; + case VirtualKey_Escape: + return Qt::Key_Escape; + + // Function Keys + case VirtualKey_F1: + return Qt::Key_F1; + case VirtualKey_F2: + return Qt::Key_F2; + case VirtualKey_F3: + return Qt::Key_F3; + case VirtualKey_F4: + return Qt::Key_F4; + case VirtualKey_F5: + return Qt::Key_F5; + case VirtualKey_F6: + return Qt::Key_F6; + case VirtualKey_F7: + return Qt::Key_F7; + case VirtualKey_F8: + return Qt::Key_F8; + case VirtualKey_F9: + return Qt::Key_F9; + case VirtualKey_F10: + return Qt::Key_F10; + case VirtualKey_F11: + return Qt::Key_F11; + case VirtualKey_F12: + return Qt::Key_F12; + case VirtualKey_F13: + return Qt::Key_F13; + case VirtualKey_F14: + return Qt::Key_F14; + case VirtualKey_F15: + return Qt::Key_F15; + case VirtualKey_F16: + return Qt::Key_F16; + case VirtualKey_F17: + return Qt::Key_F17; + case VirtualKey_F18: + return Qt::Key_F18; + case VirtualKey_F19: + return Qt::Key_F19; + case VirtualKey_F20: + return Qt::Key_F20; + case VirtualKey_F21: + return Qt::Key_F21; + case VirtualKey_F22: + return Qt::Key_F22; + case VirtualKey_F23: + return Qt::Key_F23; + case VirtualKey_F24: + return Qt::Key_F24; + + /* Character keys - pass through. + case VirtualKey_Enter: + case VirtualKey_Tab: + case VirtualKey_Number0: + case VirtualKey_Number1: + case VirtualKey_Number2: + case VirtualKey_Number3: + case VirtualKey_Number4: + case VirtualKey_Number5: + case VirtualKey_Number6: + case VirtualKey_Number7: + case VirtualKey_Number8: + case VirtualKey_Number9: + case VirtualKey_A: + case VirtualKey_B: + case VirtualKey_C: + case VirtualKey_D: + case VirtualKey_E: + case VirtualKey_F: + case VirtualKey_G: + case VirtualKey_H: + case VirtualKey_I: + case VirtualKey_J: + case VirtualKey_K: + case VirtualKey_L: + case VirtualKey_M: + case VirtualKey_N: + case VirtualKey_O: + case VirtualKey_P: + case VirtualKey_Q: + case VirtualKey_R: + case VirtualKey_S: + case VirtualKey_T: + case VirtualKey_U: + case VirtualKey_V: + case VirtualKey_W: + case VirtualKey_X: + case VirtualKey_Y: + case VirtualKey_Z: + case VirtualKey_Multiply: + case VirtualKey_Add: + case VirtualKey_Separator: + case VirtualKey_Subtract: + case VirtualKey_Decimal: + case VirtualKey_Divide:*/ + + /* NumberPad keys. No special Alt handling is needed, as WinRT doesn't send events if Alt is pressed. + case VirtualKey_NumberPad0: + case VirtualKey_NumberPad1: + case VirtualKey_NumberPad2: + case VirtualKey_NumberPad3: + case VirtualKey_NumberPad4: + case VirtualKey_NumberPad5: + case VirtualKey_NumberPad6: + case VirtualKey_NumberPad7: + case VirtualKey_NumberPad8: + case VirtualKey_NumberPad9:*/ + + /* Keys with no matching Qt enum (?) + case VirtualKey_None: + case VirtualKey_LeftButton: + case VirtualKey_RightButton: + case VirtualKey_MiddleButton: + case VirtualKey_XButton1: + case VirtualKey_XButton2: + case VirtualKey_Final: + case VirtualKey_Accept:*/ + } +} + +// Map Qt keys from char +static inline Qt::Key qKeyFromChar(quint32 code, Qt::KeyboardModifiers mods = Qt::NoModifier) +{ + switch (code) { + case 0x1: + case 'a': + case 'A': + return Qt::Key_A; + case 0x2: + case 'b': + case 'B': + return Qt::Key_B; + case 0x3: + case 'c': + case 'C': + return Qt::Key_C; + case 0x4: + case 'd': + case 'D': + return Qt::Key_D; + case 0x5: + case 'e': + case 'E': + return Qt::Key_E; + case 0x6: + case 'f': + case 'F': + return Qt::Key_F; + case 0x7: + case 'g': + case 'G': + return Qt::Key_G; + case 0x8: + //case '\b': + return mods & Qt::ControlModifier ? Qt::Key_H : Qt::Key_Backspace; + case 'h': + case 'H': + return Qt::Key_H; + case 0x9: + //case '\t': + return mods & Qt::ControlModifier ? Qt::Key_I : Qt::Key_Tab; + case 'i': + case 'I': + return Qt::Key_I; + case 0xa: + //case '\n': + return mods & Qt::ControlModifier ? Qt::Key_J : Qt::Key_Enter; + case 'j': + case 'J': + return Qt::Key_J; + case 0xb: + case 'k': + case 'K': + return Qt::Key_K; + case 0xc: + case 'l': + case 'L': + return Qt::Key_L; + case 0xd: + case 'm': + case 'M': + return Qt::Key_M; + case 0xe: + case 'n': + case 'N': + return Qt::Key_N; + case 0xf: + case 'o': + case 'O': + return Qt::Key_O; + case 0x10: + case 'p': + case 'P': + return Qt::Key_P; + case 0x11: + case 'q': + case 'Q': + return Qt::Key_Q; + case 0x12: + case 'r': + case 'R': + return Qt::Key_R; + case 0x13: + case 's': + case 'S': + return Qt::Key_S; + case 0x14: + case 't': + case 'T': + return Qt::Key_T; + case 0x15: + case 'u': + case 'U': + return Qt::Key_U; + case 0x16: + case 'v': + case 'V': + return Qt::Key_V; + case 0x17: + case 'w': + case 'W': + return Qt::Key_W; + case 0x18: + case 'x': + case 'X': + return Qt::Key_X; + case 0x19: + case 'y': + case 'Y': + return Qt::Key_Y; + case 0x1A: + case 'z': + case 'Z': + return Qt::Key_Z; + } + return Qt::Key_unknown; +} + +QWinRTScreen::QWinRTScreen(ICoreWindow *window) + : m_coreWindow(window) + , m_depth(32) + , m_format(QImage::Format_ARGB32_Premultiplied) +#ifdef Q_OS_WINPHONE + , m_inputContext(new QWinRTInputContext(m_coreWindow)) +#else + , m_inputContext(Make(m_coreWindow).Detach()) +#endif + , m_cursor(new QWinRTCursor(window)) + , m_orientation(Qt::PrimaryOrientation) +{ +#ifdef Q_OS_WINPHONE // On phone, there can be only one touch device + QTouchDevice *touchDevice = new QTouchDevice; + touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); + touchDevice->setType(QTouchDevice::TouchScreen); + touchDevice->setName(QStringLiteral("WinPhoneTouchScreen")); + Pointer pointer = { Pointer::TouchScreen, touchDevice }; + m_pointers.insert(0, pointer); + QWindowSystemInterface::registerTouchDevice(touchDevice); +#endif + + Rect rect; + window->get_Bounds(&rect); + m_geometry = QRect(0, 0, rect.Width, rect.Height); + + m_surfaceFormat.setAlphaBufferSize(0); + m_surfaceFormat.setRedBufferSize(8); + m_surfaceFormat.setGreenBufferSize(8); + m_surfaceFormat.setBlueBufferSize(8); + + m_surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); + m_surfaceFormat.setSamples(1); + m_surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + m_surfaceFormat.setDepthBufferSize(24); + m_surfaceFormat.setStencilBufferSize(8); + + m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (m_eglDisplay == EGL_NO_DISPLAY) + qFatal("Qt WinRT platform plugin: failed to initialize EGL display."); + + if (!eglInitialize(m_eglDisplay, NULL, NULL)) + qFatal("Qt WinRT platform plugin: failed to initialize EGL. This can happen if you haven't included the D3D compiler DLL in your application package."); + + // TODO: move this to Window + m_eglSurface = eglCreateWindowSurface(m_eglDisplay, q_configFromGLFormat(m_eglDisplay, m_surfaceFormat), window, NULL); + if (m_eglSurface == EGL_NO_SURFACE) + qFatal("Could not create EGL surface, error 0x%X", eglGetError()); + + // Event handlers mapped to QEvents + m_coreWindow->add_KeyDown(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyPress]); + m_coreWindow->add_KeyUp(Callback(this, &QWinRTScreen::onKey).Get(), &m_tokens[QEvent::KeyRelease]); + m_coreWindow->add_CharacterReceived(Callback(this, &QWinRTScreen::onCharacterReceived).Get(), &m_tokens[QEvent::User]); + m_coreWindow->add_PointerEntered(Callback(this, &QWinRTScreen::onPointerEntered).Get(), &m_tokens[QEvent::Enter]); + m_coreWindow->add_PointerExited(Callback(this, &QWinRTScreen::onPointerExited).Get(), &m_tokens[QEvent::Leave]); + m_coreWindow->add_PointerMoved(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseMove]); + m_coreWindow->add_PointerPressed(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonPress]); + m_coreWindow->add_PointerReleased(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonRelease]); + m_coreWindow->add_PointerWheelChanged(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::Wheel]); + m_coreWindow->add_SizeChanged(Callback(this, &QWinRTScreen::onSizeChanged).Get(), &m_tokens[QEvent::Resize]); + + // Window event handlers + m_coreWindow->add_Activated(Callback(this, &QWinRTScreen::onActivated).Get(), &m_tokens[QEvent::WindowActivate]); + m_coreWindow->add_Closed(Callback(this, &QWinRTScreen::onClosed).Get(), &m_tokens[QEvent::WindowDeactivate]); + m_coreWindow->add_VisibilityChanged(Callback(this, &QWinRTScreen::onVisibilityChanged).Get(), &m_tokens[QEvent::Show]); + m_coreWindow->add_AutomationProviderRequested(Callback(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &m_tokens[QEvent::InputMethodQuery]); + + // Orientation handling + if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), + &m_displayProperties))) { + // Set native orientation + DisplayOrientations displayOrientation; + m_displayProperties->get_NativeOrientation(&displayOrientation); + m_nativeOrientation = qOrientationFromNative(displayOrientation); + + // Set initial orientation + onOrientationChanged(0); + + m_displayProperties->add_OrientationChanged(Callback(this, &QWinRTScreen::onOrientationChanged).Get(), + &m_tokens[QEvent::OrientationChange]); + } + +#ifndef Q_OS_WINPHONE + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(), + &m_applicationView); +#endif +} + +QRect QWinRTScreen::geometry() const +{ + return m_geometry; +} + +int QWinRTScreen::depth() const +{ + return m_depth; +} + +QImage::Format QWinRTScreen::format() const +{ + return m_format; +} + +QSurfaceFormat QWinRTScreen::surfaceFormat() const +{ + return m_surfaceFormat; +} + +QWinRTInputContext *QWinRTScreen::inputContext() const +{ + return m_inputContext; +} + +QPlatformCursor *QWinRTScreen::cursor() const +{ + return m_cursor; +} + +Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const +{ + return m_nativeOrientation; +} + +Qt::ScreenOrientation QWinRTScreen::orientation() const +{ + return m_orientation; +} + +ICoreWindow *QWinRTScreen::coreWindow() const +{ + return m_coreWindow; +} + +EGLDisplay QWinRTScreen::eglDisplay() const +{ + return m_eglDisplay; +} + +EGLSurface QWinRTScreen::eglSurface() const +{ + return m_eglSurface; +} + +QWindow *QWinRTScreen::topWindow() const +{ + return m_visibleWindows.isEmpty() ? 0 : m_visibleWindows.first(); +} + +void QWinRTScreen::addWindow(QWindow *window) +{ + if (window == topWindow()) + return; + m_visibleWindows.prepend(window); + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::removeWindow(QWindow *window) +{ + const bool wasTopWindow = window == topWindow(); + if (!m_visibleWindows.removeAll(window)) + return; + if (wasTopWindow) + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::raise(QWindow *window) +{ + m_visibleWindows.removeAll(window); + addWindow(window); +} + +void QWinRTScreen::lower(QWindow *window) +{ + const bool wasTopWindow = window == topWindow(); + if (wasTopWindow && m_visibleWindows.size() == 1) + return; + m_visibleWindows.removeAll(window); + m_visibleWindows.append(window); + if (wasTopWindow) + QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + handleExpose(); +} + +void QWinRTScreen::handleExpose() +{ + if (m_visibleWindows.isEmpty()) + return; + QList::const_iterator it = m_visibleWindows.constBegin(); + QWindowSystemInterface::handleExposeEvent(*it, m_geometry); + while (++it != m_visibleWindows.constEnd()) + QWindowSystemInterface::handleExposeEvent(*it, QRegion()); + QWindowSystemInterface::flushWindowSystemEvents(); +} + +HRESULT QWinRTScreen::onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args) +{ + Q_UNUSED(window); + + // Windows Phone documentation claims this will throw, but doesn't seem to + CorePhysicalKeyStatus keyStatus; + args->get_KeyStatus(&keyStatus); + + VirtualKey virtualKey; + args->get_VirtualKey(&virtualKey); + + // Filter meta keys + Qt::Key key = qMetaKeyFromVirtual(virtualKey); + + // Get keyboard modifiers. This could alternatively be tracked by key presses, but + // WinRT doesn't send key events for Alt unless Ctrl is also pressed. + // If the key that caused this event is a modifier, it is not returned in the flags. + Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); + + if (m_activeKeys.contains(keyStatus.ScanCode)) { // Handle tracked keys (release/repeat) + QString text = keyStatus.IsKeyReleased ? m_activeKeys.take(keyStatus.ScanCode) : m_activeKeys.value(keyStatus.ScanCode); + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); + + if (!keyStatus.IsKeyReleased) // Repeating key + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); + + } else if (keyStatus.IsKeyReleased) { // Unlikely, but possible if key is held before application is focused + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods); + + } else { // Handle key presses + if (key != Qt::Key_unknown) // Handle non-character key presses here, others in onCharacterReceived + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods); + + m_activeKeys.insert(keyStatus.ScanCode, QString()); + } + + return S_OK; +} + +HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceivedEventArgs *args) +{ + Q_UNUSED(window); + + quint32 keyCode; + args->get_KeyCode(&keyCode); + + // Windows Phone documentation claims this will throw, but doesn't seem to + CorePhysicalKeyStatus keyStatus; + args->get_KeyStatus(&keyStatus); + + QString text = QChar(keyCode); + + Qt::KeyboardModifiers mods = qKeyModifiers(m_coreWindow); + Qt::Key key = qKeyFromChar(keyCode, mods); + + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); + + // Note that we can receive a character without corresponding press/release events, such as + // the case of an Alt-combo. In this case, we should send the release immediately. + if (m_activeKeys.contains(keyStatus.ScanCode)) + m_activeKeys.insert(keyStatus.ScanCode, text); + else + QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); + + return S_OK; +} + +HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + IPointerPoint *pointerPoint; + if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) { + // Assumes full-screen window + Point point; + pointerPoint->get_Position(&point); + QPoint pos(point.X, point.Y); + + QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); + pointerPoint->Release(); + } + return S_OK; +} + +HRESULT QWinRTScreen::onPointerExited(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + QWindowSystemInterface::handleLeaveEvent(0); + return S_OK; +} + +HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *args) +{ + Q_UNUSED(window); + + IPointerPoint *pointerPoint; + if (FAILED(args->get_CurrentPoint(&pointerPoint))) + return E_INVALIDARG; + + // Common traits - point, modifiers, properties + Point point; + pointerPoint->get_Position(&point); + QPointF pos(point.X, point.Y); + + VirtualKeyModifiers modifiers; + args->get_KeyModifiers(&modifiers); + Qt::KeyboardModifiers mods; + if (modifiers & VirtualKeyModifiers_Control) + mods |= Qt::ControlModifier; + if (modifiers & VirtualKeyModifiers_Menu) + mods |= Qt::AltModifier; + if (modifiers & VirtualKeyModifiers_Shift) + mods |= Qt::ShiftModifier; + if (modifiers & VirtualKeyModifiers_Windows) + mods |= Qt::MetaModifier; + + IPointerPointProperties *properties; + if (FAILED(pointerPoint->get_Properties(&properties))) + return E_INVALIDARG; + +#ifdef Q_OS_WINPHONE + quint32 pointerId = 0; + Pointer pointer = m_pointers.value(pointerId); +#else + Pointer pointer = { Pointer::Unknown, 0 }; + quint32 pointerId; + pointerPoint->get_PointerId(&pointerId); + if (m_pointers.contains(pointerId)) { + pointer = m_pointers.value(pointerId); + } else { // We have not yet enumerated this device. Do so now... + IPointerDevice *device; + if (SUCCEEDED(pointerPoint->get_PointerDevice(&device))) { + PointerDeviceType type; + device->get_PointerDeviceType(&type); + switch (type) { + case PointerDeviceType_Touch: + pointer.type = Pointer::TouchScreen; + pointer.device = new QTouchDevice; + pointer.device->setName(QStringLiteral("WinRT TouchScreen ") + QString::number(pointerId)); + // TODO: We may want to probe the device usage flags for more accurate values for these next two + pointer.device->setType(QTouchDevice::TouchScreen); + pointer.device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure); + QWindowSystemInterface::registerTouchDevice(pointer.device); + break; + + case PointerDeviceType_Pen: + pointer.type = Pointer::Tablet; + break; + + case PointerDeviceType_Mouse: + pointer.type = Pointer::Mouse; + break; + } + + m_pointers.insert(pointerId, pointer); + device->Release(); + } + } +#endif + switch (pointer.type) { + case Pointer::Mouse: { + qint32 delta; + properties->get_MouseWheelDelta(&delta); + if (delta) { + boolean isHorizontal; + properties->get_IsHorizontalMouseWheel(&isHorizontal); + QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta); + QWindowSystemInterface::handleWheelEvent(topWindow(), pos, pos, QPoint(), angleDelta, mods); + break; + } + + boolean isPressed; + Qt::MouseButtons buttons = Qt::NoButton; + properties->get_IsLeftButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::LeftButton; + + properties->get_IsMiddleButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::MiddleButton; + + properties->get_IsRightButtonPressed(&isPressed); + if (isPressed) + buttons |= Qt::RightButton; + + properties->get_IsXButton1Pressed(&isPressed); + if (isPressed) + buttons |= Qt::XButton1; + + properties->get_IsXButton2Pressed(&isPressed); + if (isPressed) + buttons |= Qt::XButton2; + + QWindowSystemInterface::handleMouseEvent(topWindow(), pos, pos, buttons, mods); + + break; + } + case Pointer::TouchScreen: { + quint32 id; + pointerPoint->get_PointerId(&id); + + Rect area; + properties->get_ContactRect(&area); + + float pressure; + properties->get_Pressure(&pressure); + + QHash::iterator it = m_touchPoints.find(id); + if (it != m_touchPoints.end()) { + boolean isPressed; + pointerPoint->get_IsInContact(&isPressed); + it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased; + } else { + it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); + it.value().state = Qt::TouchPointPressed; + it.value().id = id; + } + it.value().area = QRectF(area.X, area.Y, area.Width, area.Height); + it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height()); + it.value().pressure = pressure; + + QWindowSystemInterface::handleTouchEvent(topWindow(), pointer.device, m_touchPoints.values(), mods); + + // Remove released points, station others + for (QHash::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) { + if (i.value().state == Qt::TouchPointReleased) + i = m_touchPoints.erase(i); + else + (i++).value().state = Qt::TouchPointStationary; + } + + break; + } + case Pointer::Tablet: { + quint32 id; + pointerPoint->get_PointerId(&id); + + boolean isPressed; + pointerPoint->get_IsInContact(&isPressed); + + boolean isEraser; + properties->get_IsEraser(&isEraser); + int pointerType = isEraser ? 3 : 1; + + float pressure; + properties->get_Pressure(&pressure); + + float xTilt; + properties->get_XTilt(&xTilt); + + float yTilt; + properties->get_YTilt(&yTilt); + + float rotation; + properties->get_Twist(&rotation); + + QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, pointerId, + pointerType, pressure, xTilt, yTilt, + 0, rotation, 0, id, mods); + + break; + } + } + + properties->Release(); + pointerPoint->Release(); + + return S_OK; +} + +HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args) +{ +#ifndef Q_OS_WINPHONE + args->put_AutomationProvider(m_inputContext); +#endif + return S_OK; +} + +HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEventArgs *args) +{ + Q_UNUSED(window); + + Size size; + if (FAILED(args->get_Size(&size))) { + qWarning(Q_FUNC_INFO ": failed to get size"); + return S_OK; + } + + // Regardless of state, all top-level windows are viewport-sized - this might change if + // a more advanced compositor is written. + m_geometry.setSize(QSize(size.Width, size.Height)); + QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry); + QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry); + QPlatformScreen::resizeMaximizedWindows(); + handleExpose(); + + return S_OK; +} + +HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs *args) +{ + Q_UNUSED(window); + + CoreWindowActivationState activationState; + args->get_WindowActivationState(&activationState); + if (activationState == CoreWindowActivationState_Deactivated) { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + return S_OK; + } + + // Activate topWindow + if (!m_visibleWindows.isEmpty()) { + Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated + ? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason; + QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason); + } + return S_OK; +} + +HRESULT QWinRTScreen::onClosed(ICoreWindow *window, ICoreWindowEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + QWindowSystemInterface::handleCloseEvent(w); + return S_OK; +} + +HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChangedEventArgs *args) +{ + Q_UNUSED(window); + Q_UNUSED(args); + + boolean visible; + args->get_Visible(&visible); + QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); + return S_OK; +} + +HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) +{ + DisplayOrientations displayOrientation; + m_displayProperties->get_CurrentOrientation(&displayOrientation); + Qt::ScreenOrientation newOrientation = qOrientationFromNative(displayOrientation); + if (m_orientation != newOrientation) { + m_orientation = newOrientation; + QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + } + + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h new file mode 100644 index 0000000000..d0ac53d56d --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTSCREEN_H +#define QWINRTSCREEN_H + +#include +#include + +#include +#include +#include + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Core { + struct IAutomationProviderRequestedEventArgs; + struct ICharacterReceivedEventArgs; + struct ICoreWindow; + struct ICoreWindowEventArgs; + struct IKeyEventArgs; + struct IPointerEventArgs; + struct IVisibilityChangedEventArgs; + struct IWindowActivatedEventArgs; + struct IWindowSizeChangedEventArgs; + } + namespace ViewManagement { + struct IApplicationViewStatics; + } + } + namespace Graphics { + namespace Display { + struct IDisplayPropertiesStatics; + } + } + } +} +struct IInspectable; + +QT_BEGIN_NAMESPACE + +class QTouchDevice; +class QWinRTEGLContext; +class QWinRTPageFlipper; +class QWinRTCursor; +class QWinRTInputContext; + +struct Pointer { + enum Type { Unknown, Mouse, TouchScreen, Tablet }; + Type type; + QTouchDevice *device; +}; + +class QWinRTScreen : public QPlatformScreen +{ +public: + explicit QWinRTScreen(ABI::Windows::UI::Core::ICoreWindow *window); + QRect geometry() const; + int depth() const; + QImage::Format format() const; + QSurfaceFormat surfaceFormat() const; + QWinRTInputContext *inputContext() const; + QPlatformCursor *cursor() const; + + Qt::ScreenOrientation nativeOrientation() const; + Qt::ScreenOrientation orientation() const; + + QWindow *topWindow() const; + void addWindow(QWindow *window); + void removeWindow(QWindow *window); + void raise(QWindow *window); + void lower(QWindow *window); + + ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; + EGLDisplay eglDisplay() const; // To opengl context + EGLSurface eglSurface() const; // To window + +private: + void handleExpose(); + + // Event handlers + QHash m_tokens; + + HRESULT onKey(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args); + HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *args); + HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args); + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *args); + + HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *args); + HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *args); + HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *args); + HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *args); + + HRESULT onOrientationChanged(IInspectable *); + + ABI::Windows::UI::Core::ICoreWindow *m_coreWindow; + ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView; + QRect m_geometry; + QImage::Format m_format; + QSurfaceFormat m_surfaceFormat; + int m_depth; + QWinRTInputContext *m_inputContext; + QWinRTCursor *m_cursor; + QList m_visibleWindows; + + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + + ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayProperties; + Qt::ScreenOrientation m_nativeOrientation; + Qt::ScreenOrientation m_orientation; + + QHash m_activeKeys; + QHash m_pointers; + QHash m_touchPoints; +}; + +QT_END_NAMESPACE + +#endif // QWINRTSCREEN_H diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp new file mode 100644 index 0000000000..8f0a1d55bb --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtservices.h" +#include +#include +#include + +#include +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::System; + +QT_BEGIN_NAMESPACE + +QWinRTServices::QWinRTServices() +{ + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), &m_uriFactory); + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(), &m_fileFactory); + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), &m_launcher); +} + +QWinRTServices::~QWinRTServices() +{ + if (m_uriFactory) + m_uriFactory->Release(); + + if (m_fileFactory) + m_fileFactory->Release(); + + if (m_launcher) + m_launcher->Release(); +} + +bool QWinRTServices::openUrl(const QUrl &url) +{ + if (!(m_uriFactory && m_launcher)) + return QPlatformServices::openUrl(url); + + IUriRuntimeClass *uri; + QString urlString = url.toString(); HSTRING uriString; HSTRING_HEADER header; + WindowsCreateStringReference((const wchar_t*)urlString.utf16(), urlString.length(), &header, &uriString); + m_uriFactory->CreateUri(uriString, &uri); + if (!uri) + return false; + + IAsyncOperation *launchOp; + m_launcher->LaunchUriAsync(uri, &launchOp); + uri->Release(); + if (!launchOp) + return false; + + boolean result = false; + while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + launchOp->Release(); + + return result; +} + +bool QWinRTServices::openDocument(const QUrl &url) +{ + if (!(m_fileFactory && m_launcher)) + return QPlatformServices::openDocument(url); + + QString pathString = QDir::toNativeSeparators( + QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme)))); + HSTRING_HEADER header; HSTRING path; + WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path); + IAsyncOperation *fileOp; + m_fileFactory->GetFileFromPathAsync(path, &fileOp); + if (!fileOp) + return false; + + IStorageFile *file = nullptr; + while (fileOp->GetResults(&file) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + fileOp->Release(); + if (!file) + return false; + + IAsyncOperation *launchOp; + m_launcher->LaunchFileAsync(file, &launchOp); + if (!launchOp) + return false; + + boolean result = false; + while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL) + QCoreApplication::processEvents(); + launchOp->Release(); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h new file mode 100644 index 0000000000..9cc917030a --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtservices.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTSERVICES_H +#define QWINRTSERVICES_H + +#include + +namespace ABI { + namespace Windows { + namespace Foundation { + struct IUriRuntimeClassFactory; + } + namespace Storage { + struct IStorageFileStatics; + } + namespace System { + struct ILauncherStatics; + } + } +} + +QT_BEGIN_NAMESPACE + +class QWinRTServices : public QPlatformServices +{ +public: + explicit QWinRTServices(); + ~QWinRTServices(); + + bool openUrl(const QUrl &url); + bool openDocument(const QUrl &url); + +private: + ABI::Windows::Foundation::IUriRuntimeClassFactory *m_uriFactory; + ABI::Windows::Storage::IStorageFileStatics *m_fileFactory; + ABI::Windows::System::ILauncherStatics *m_launcher; +}; + +QT_END_NAMESPACE + +#endif // QWINRTSERVICES_H diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp new file mode 100644 index 0000000000..88b753b463 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtwindow.h" +#include "qwinrtscreen.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QWinRTWindow::QWinRTWindow(QWindow *window) + : QPlatformWindow(window) + , m_screen(static_cast(screen())) +{ + setWindowFlags(window->flags()); + setWindowState(window->windowState()); + handleContentOrientationChange(window->contentOrientation()); + setGeometry(window->geometry()); +} + +QWinRTWindow::~QWinRTWindow() +{ + m_screen->removeWindow(window()); +} + +QSurfaceFormat QWinRTWindow::format() const +{ + return m_screen->surfaceFormat(); +} + +bool QWinRTWindow::isActive() const +{ + return m_screen->topWindow() == window(); +} + +bool QWinRTWindow::isExposed() const +{ + const bool exposed = isActive(); + return exposed; +} + +void QWinRTWindow::setGeometry(const QRect &rect) +{ + if (window()->isTopLevel()) { + QPlatformWindow::setGeometry(m_screen->geometry()); + QWindowSystemInterface::handleGeometryChange(window(), geometry()); + } else { + QPlatformWindow::setGeometry(rect); + QWindowSystemInterface::handleGeometryChange(window(), rect); + } +} + +void QWinRTWindow::setVisible(bool visible) +{ + if (!window()->isTopLevel()) + return; + if (visible) + m_screen->addWindow(window()); + else + m_screen->removeWindow(window()); +} + +void QWinRTWindow::raise() +{ + if (!window()->isTopLevel()) + return; + m_screen->raise(window()); +} + +void QWinRTWindow::lower() +{ + if (!window()->isTopLevel()) + return; + m_screen->lower(window()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h new file mode 100644 index 0000000000..1f19b4f2d5 --- /dev/null +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTWINDOW_H +#define QWINRTWINDOW_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWinRTScreen; + +class QWinRTWindow : public QPlatformWindow +{ +public: + QWinRTWindow(QWindow *window); + ~QWinRTWindow(); + + QSurfaceFormat format() const; + bool isActive() const; + bool isExposed() const; + void setGeometry(const QRect &rect); + void setVisible(bool visible); + void raise(); + void lower(); + +private: + QWinRTScreen *m_screen; +}; + +QT_END_NAMESPACE + +#endif // QWINRTWINDOW_H diff --git a/src/plugins/platforms/winrt/winrt.json b/src/plugins/platforms/winrt/winrt.json new file mode 100644 index 0000000000..962747b697 --- /dev/null +++ b/src/plugins/platforms/winrt/winrt.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "winrt" ] +} diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro new file mode 100644 index 0000000000..ea5ff93d00 --- /dev/null +++ b/src/plugins/platforms/winrt/winrt.pro @@ -0,0 +1,55 @@ +TARGET = qwinrt +CONFIG -= precompile_header + +PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private + +DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES + +LIBS += $$QMAKE_LIBS_CORE -ldxgi + +SOURCES = \ + main.cpp \ + qwinrtbackingstore.cpp \ + qwinrtcursor.cpp \ + qwinrteglcontext.cpp \ + qwinrteventdispatcher.cpp \ + qwinrtfontdatabase.cpp \ + qwinrtinputcontext.cpp \ + qwinrtintegration.cpp \ + qwinrtscreen.cpp \ + qwinrtservices.cpp \ + qwinrtwindow.cpp + +HEADERS = \ + qwinrtbackingstore.h \ + qwinrtcursor.h \ + qwinrteglcontext.h \ + qwinrteventdispatcher.h \ + qwinrtfontdatabase.h \ + qwinrtinputcontext.h \ + qwinrtintegration.h \ + qwinrtscreen.h \ + qwinrtservices.h \ + qwinrtwindow.h + +BLIT_INPUT = $$PWD/blit.hlsl +fxc_blitps.commands = fxc.exe /nologo /T ps_4_0_level_9_1 /E blitps /Vn q_blitps /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +fxc_blitps.output = $$OUT_PWD/blitps.h +fxc_blitps.input = BLIT_INPUT +fxc_blitps.dependency_type = TYPE_C +fxc_blitps.variable_out = HEADERS +fxc_blitps.CONFIG += target_predeps +fxc_blitvs.commands = fxc.exe /nologo /T vs_4_0_level_9_1 /E blitvs /Vn q_blitvs /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +fxc_blitvs.output = $$OUT_PWD/blitvs.h +fxc_blitvs.input = BLIT_INPUT +fxc_blitvs.dependency_type = TYPE_C +fxc_blitvs.variable_out = HEADERS +fxc_blitvs.CONFIG += target_predeps +QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs + +OTHER_FILES += winrt.json \ + blit.hlsl -- cgit v1.2.3