summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-01-21 08:17:21 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-01-21 08:17:21 +0100
commit158a3a4159bdc5a49caecd63e021dacbc06cf23c (patch)
treec3ed9aee6cabd46e5e8615b3815b92d32857c4da /src/plugins/platforms
parent26ece94a68fb5ae680c5639716b06c4e1ae979a8 (diff)
parent7b2fb038ae4b8b9231ae989ad309b6eca107a858 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts: src/corelib/io/qiodevice_p.h src/corelib/kernel/qvariant_p.h src/corelib/tools/qsimd.cpp src/gui/kernel/qguiapplication.cpp tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp Change-Id: I742a093cbb231b282b43e463ec67173e0d29f57a
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp2
-rw-r--r--src/plugins/platforms/mirclient/mirclient.pro2
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.cpp51
-rw-r--r--src/plugins/platforms/mirclient/qmirclientcursor.cpp201
-rw-r--r--src/plugins/platforms/mirclient/qmirclientcursor.h61
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.cpp14
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.h2
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.cpp95
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.h13
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.cpp62
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.h5
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp29
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.h5
-rw-r--r--src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h10
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplugin.cpp4
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.cpp21
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.h12
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp710
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h33
-rw-r--r--src/plugins/platforms/windows/accessible/accessible.pri17
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp52
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp145
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h42
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp48
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h12
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp97
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.h4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp8
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp37
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
45 files changed, 1318 insertions, 611 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 9e24c4fc9d..11c68efd40 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -50,11 +50,11 @@ QT_USE_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
-static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0)
+static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *offset, NSUInteger *start = 0, NSUInteger *end = 0)
{
- Q_ASSERT(line == -1 || offset == -1);
- Q_ASSERT(line != -1 || offset != -1);
- Q_ASSERT(offset <= text->characterCount());
+ Q_ASSERT(*line == -1 || *offset == -1);
+ Q_ASSERT(*line != -1 || *offset != -1);
+ Q_ASSERT(*offset <= text->characterCount());
int curLine = -1;
int curStart = 0, curEnd = 0;
@@ -81,14 +81,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
if (nextEnd == curEnd)
++curEnd;
}
- } while ((line == -1 || curLine < line) && (offset == -1 || (curEnd <= offset)) && curEnd <= text->characterCount());
+ } while ((*line == -1 || curLine < *line) && (*offset == -1 || (curEnd <= *offset)) && curEnd <= text->characterCount());
curEnd = qMin(curEnd, text->characterCount());
- if (line == -1)
- line = curLine;
- if (offset == -1)
- offset = curStart;
+ if (*line == -1)
+ *line = curLine;
+ if (*offset == -1)
+ *offset = curStart;
Q_ASSERT(curStart >= 0);
Q_ASSERT(curEnd >= 0);
@@ -346,7 +346,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
if (QAccessibleTextInterface *text = iface->textInterface()) {
int line = -1;
int position = text->cursorPosition();
- convertLineOffset(text, line, position);
+ convertLineOffset(text, &line, &position);
return [NSNumber numberWithInt: line];
}
return nil;
@@ -405,7 +405,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
if (index < 0 || index > iface->textInterface()->characterCount())
return nil;
int line = -1;
- convertLineOffset(iface->textInterface(), line, index);
+ convertLineOffset(iface->textInterface(), &line, &index);
return [NSNumber numberWithInt:line];
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
@@ -415,7 +415,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
int lineOffset = -1;
NSUInteger startOffset = 0;
NSUInteger endOffset = 0;
- convertLineOffset(iface->textInterface(), line, lineOffset, &startOffset, &endOffset);
+ convertLineOffset(iface->textInterface(), &line, &lineOffset, &startOffset, &endOffset);
return [NSValue valueWithRange:NSMakeRange(startOffset, endOffset - startOffset)];
}
if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) {
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 06ba4d42c3..0cbdc5d9c8 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -204,7 +204,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// current OS X versions is 22 points. Provide some future-proofing
// by deriving the icon height from the menu height.
const int padding = 4;
- const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
+ const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
const int maxImageHeight = menuHeight - padding;
// Select pixmap based on the device pixel height. Ideally we would use
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
index dcdaccb389..9d754866cc 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
@@ -54,8 +54,8 @@ public:
QWindowsDirect2DBackingStore(QWindow *window);
~QWindowsDirect2DBackingStore();
- void beginPaint(const QRegion &);
- void endPaint();
+ void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+ void endPaint() Q_DECL_OVERRIDE;
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
void flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index b5699e1191..5f65a2313a 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -60,8 +60,7 @@ public:
~QWindowsDirect2DPlatformPixmap();
void resize(int width, int height) Q_DECL_OVERRIDE;
- virtual void fromImage(const QImage &image,
- Qt::ImageConversionFlags flags);
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
void fill(const QColor &color) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
index 20d315955f..79ece86570 100644
--- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
@@ -217,7 +217,7 @@ QDpi QEGLDeviceIntegration::logicalDpi() const
qreal QEGLDeviceIntegration::pixelDensity() const
{
- return logicalDpi().first / qreal(100);
+ return qRound(logicalDpi().first / qreal(100));
}
Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const
diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro
index 033ce579b9..0851e8d719 100644
--- a/src/plugins/platforms/mirclient/mirclient.pro
+++ b/src/plugins/platforms/mirclient/mirclient.pro
@@ -21,6 +21,7 @@ PKGCONFIG += egl mirclient ubuntu-platform-api
SOURCES = \
qmirclientbackingstore.cpp \
qmirclientclipboard.cpp \
+ qmirclientcursor.cpp \
qmirclientglcontext.cpp \
qmirclientinput.cpp \
qmirclientintegration.cpp \
@@ -34,6 +35,7 @@ SOURCES = \
HEADERS = \
qmirclientbackingstore.h \
qmirclientclipboard.h \
+ qmirclientcursor.h \
qmirclientglcontext.h \
qmirclientinput.h \
qmirclientintegration.h \
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
index 4494847b54..4cb2b5f740 100644
--- a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
@@ -87,12 +87,12 @@ void QMirClientClipboard::requestDBusClipboardContents()
if (!mPendingGetContentsCall.isNull())
return;
- QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents");
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("GetContents"));
mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
- QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
- this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*)));
+ QObject::connect(mPendingGetContentsCall.data(), &QDBusPendingCallWatcher::finished,
+ this, &QMirClientClipboard::onDBusClipboardGetContentsFinished);
}
void QMirClientClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call)
@@ -143,17 +143,17 @@ void QMirClientClipboard::setupDBus()
QDBusConnection dbusConnection = QDBusConnection::sessionBus();
bool ok = dbusConnection.connect(
- "com.canonical.QtMir",
- "/com/canonical/QtMir/Clipboard",
- "com.canonical.QtMir.Clipboard",
- "ContentsChanged",
+ QStringLiteral("com.canonical.QtMir"),
+ QStringLiteral("/com/canonical/QtMir/Clipboard"),
+ QStringLiteral("com.canonical.QtMir.Clipboard"),
+ QStringLiteral("ContentsChanged"),
this, SLOT(updateMimeData(QByteArray)));
if (Q_UNLIKELY(!ok))
qCritical("QMirClientClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard.");
- mDBusClipboard = new QDBusInterface("com.canonical.QtMir",
- "/com/canonical/QtMir/Clipboard",
- "com.canonical.QtMir.Clipboard",
+ mDBusClipboard = new QDBusInterface(QStringLiteral("com.canonical.QtMir"),
+ QStringLiteral("/com/canonical/QtMir/Clipboard"),
+ QStringLiteral("com.canonical.QtMir.Clipboard"),
dbusConnection);
mDBusSetupDone = true;
@@ -161,6 +161,8 @@ void QMirClientClipboard::setupDBus()
QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const
{
+ Q_ASSERT(mimeData != nullptr);
+
const QStringList formats = mimeData->formats();
const int formatCount = qMin(formats.size(), maxFormatsCount);
const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int));
@@ -179,12 +181,13 @@ QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const
int offset = headerSize;
header[0] = formatCount;
for (int i = 0; i < formatCount; i++) {
+ const QByteArray data = mimeData->data(formats[i]);
const int formatOffset = offset;
const int formatSize = formats[i].size();
const int dataOffset = offset + formatSize;
- const int dataSize = mimeData->data(formats[i]).size();
+ const int dataSize = data.size();
memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize);
- memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize);
+ memcpy(&buffer[dataOffset], data.data(), dataSize);
header[i*4+1] = formatOffset;
header[i*4+2] = formatSize;
header[i*4+3] = dataOffset;
@@ -264,13 +267,15 @@ void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode
delete mPendingGetContentsCall.data();
}
- QByteArray serializedMimeData = serializeMimeData(mimeData);
- if (!serializedMimeData.isEmpty()) {
- setDBusClipboardContents(serializedMimeData);
- }
+ if (mimeData != nullptr) {
+ QByteArray serializedMimeData = serializeMimeData(mimeData);
+ if (!serializedMimeData.isEmpty()) {
+ setDBusClipboardContents(serializedMimeData);
+ }
- mMimeData = mimeData;
- emitChanged(QClipboard::Clipboard);
+ mMimeData = mimeData;
+ emitChanged(QClipboard::Clipboard);
+ }
}
bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const
@@ -286,6 +291,10 @@ bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const
void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardContents)
{
+ if (!mDBusSetupDone) {
+ setupDBus();
+ }
+
if (!mPendingSetContentsCall.isNull()) {
// Ignore any previous set call as we are going to overwrite it anyway
QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0);
@@ -295,10 +304,10 @@ void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardCo
delete mPendingSetContentsCall.data();
}
- QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents);
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("SetContents"), clipboardContents);
mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
- QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
- this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*)));
+ QObject::connect(mPendingSetContentsCall.data(), &QDBusPendingCallWatcher::finished,
+ this, &QMirClientClipboard::onDBusClipboardSetContentsFinished);
}
diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.cpp b/src/plugins/platforms/mirclient/qmirclientcursor.cpp
new file mode 100644
index 0000000000..1d6ec8391e
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientcursor.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientcursor.h"
+
+#include "qmirclientlogging.h"
+#include "qmirclientwindow.h"
+
+#include <mir_toolkit/mir_client_library.h>
+
+QMirClientCursor::QMirClientCursor(MirConnection *connection)
+ : mConnection(connection)
+{
+ mShapeToCursorName[Qt::ArrowCursor] = "left_ptr";
+ mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow";
+ mShapeToCursorName[Qt::CrossCursor] = "cross";
+ mShapeToCursorName[Qt::WaitCursor] = "watch";
+ mShapeToCursorName[Qt::IBeamCursor] = "xterm";
+ mShapeToCursorName[Qt::SizeVerCursor] = "size_ver";
+ mShapeToCursorName[Qt::SizeHorCursor] = "size_hor";
+ mShapeToCursorName[Qt::SizeBDiagCursor] = "size_bdiag";
+ mShapeToCursorName[Qt::SizeFDiagCursor] = "size_fdiag";
+ mShapeToCursorName[Qt::SizeAllCursor] = "size_all";
+ mShapeToCursorName[Qt::BlankCursor] = "blank";
+ mShapeToCursorName[Qt::SplitVCursor] = "split_v";
+ mShapeToCursorName[Qt::SplitHCursor] = "split_h";
+ mShapeToCursorName[Qt::PointingHandCursor] = "hand";
+ mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden";
+ mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this";
+ mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch";
+ mShapeToCursorName[Qt::OpenHandCursor] = "openhand";
+ mShapeToCursorName[Qt::ClosedHandCursor] = "closedhand";
+ mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy";
+ mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move";
+ mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link";
+}
+
+namespace {
+#if !defined(QT_NO_DEBUG)
+const char *qtCursorShapeToStr(Qt::CursorShape shape)
+{
+ switch (shape) {
+ case Qt::ArrowCursor:
+ return "Arrow";
+ case Qt::UpArrowCursor:
+ return "UpArrow";
+ case Qt::CrossCursor:
+ return "Cross";
+ case Qt::WaitCursor:
+ return "Wait";
+ case Qt::IBeamCursor:
+ return "IBeam";
+ case Qt::SizeVerCursor:
+ return "SizeVer";
+ case Qt::SizeHorCursor:
+ return "SizeHor";
+ case Qt::SizeBDiagCursor:
+ return "SizeBDiag";
+ case Qt::SizeFDiagCursor:
+ return "SizeFDiag";
+ case Qt::SizeAllCursor:
+ return "SizeAll";
+ case Qt::BlankCursor:
+ return "Blank";
+ case Qt::SplitVCursor:
+ return "SplitV";
+ case Qt::SplitHCursor:
+ return "SplitH";
+ case Qt::PointingHandCursor:
+ return "PointingHand";
+ case Qt::ForbiddenCursor:
+ return "Forbidden";
+ case Qt::WhatsThisCursor:
+ return "WhatsThis";
+ case Qt::BusyCursor:
+ return "Busy";
+ case Qt::OpenHandCursor:
+ return "OpenHand";
+ case Qt::ClosedHandCursor:
+ return "ClosedHand";
+ case Qt::DragCopyCursor:
+ return "DragCopy";
+ case Qt::DragMoveCursor:
+ return "DragMove";
+ case Qt::DragLinkCursor:
+ return "DragLink";
+ case Qt::BitmapCursor:
+ return "Bitmap";
+ default:
+ return "???";
+ }
+}
+#endif // !defined(QT_NO_DEBUG)
+} // anonymous namespace
+
+void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window)
+{
+ if (!window) {
+ return;
+ }
+
+ MirSurface *surface = static_cast<QMirClientWindow*>(window->handle())->mirSurface();
+
+ if (!surface) {
+ return;
+ }
+
+
+ if (windowCursor) {
+ DLOG("[ubuntumirclient QPA] changeCursor shape=%s, window=%p\n", qtCursorShapeToStr(windowCursor->shape()), window);
+ if (!windowCursor->pixmap().isNull()) {
+ configureMirCursorWithPixmapQCursor(surface, *windowCursor);
+ } else if (windowCursor->shape() == Qt::BitmapCursor) {
+ // TODO: Implement bitmap cursor support
+ applyDefaultCursorConfiguration(surface);
+ } else {
+ const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr"));
+ auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data());
+ mir_surface_configure_cursor(surface, cursorConfiguration);
+ mir_cursor_configuration_destroy(cursorConfiguration);
+ }
+ } else {
+ applyDefaultCursorConfiguration(surface);
+ }
+
+}
+
+void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor)
+{
+ QImage image = cursor.pixmap().toImage();
+
+ if (image.format() != QImage::Format_ARGB32) {
+ image.convertToFormat(QImage::Format_ARGB32);
+ }
+
+ MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection,
+ image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software);
+
+ {
+ MirGraphicsRegion region;
+ mir_buffer_stream_get_graphics_region(bufferStream, &region);
+
+ char *regionLine = region.vaddr;
+ Q_ASSERT(image.bytesPerLine() <= region.stride);
+ for (int i = 0; i < image.height(); ++i) {
+ memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
+ regionLine += region.stride;
+ }
+ }
+
+ mir_buffer_stream_swap_buffers_sync(bufferStream);
+
+ {
+ auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y());
+ mir_surface_configure_cursor(surface, configuration);
+ mir_cursor_configuration_destroy(configuration);
+ }
+
+ mir_buffer_stream_release_sync(bufferStream);
+}
+
+void QMirClientCursor::applyDefaultCursorConfiguration(MirSurface *surface)
+{
+ auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr");
+ mir_surface_configure_cursor(surface, cursorConfiguration);
+ mir_cursor_configuration_destroy(cursorConfiguration);
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.h b/src/plugins/platforms/mirclient/qmirclientcursor.h
new file mode 100644
index 0000000000..8bb151ddda
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientcursor.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTCURSOR_H
+#define QMIRCLIENTCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+
+#include <QMap>
+#include <QByteArray>
+
+struct MirConnection;
+struct MirSurface;
+
+class QMirClientCursor : public QPlatformCursor
+{
+public:
+ QMirClientCursor(MirConnection *connection);
+ void changeCursor(QCursor *windowCursor, QWindow *window) override;
+private:
+ void configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor);
+ void applyDefaultCursorConfiguration(MirSurface *surface);
+ QMap<int, QByteArray> mShapeToCursorName;
+ MirConnection *mConnection;
+};
+
+#endif // QMIRCLIENTCURSOR_H
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
index bbd7f5ee75..e1e7727486 100644
--- a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
@@ -140,19 +140,7 @@ void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface)
ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
#endif
- // "Technique" copied from mir, in examples/eglapp.c around line 96
- EGLint newBufferWidth = -1;
- EGLint newBufferHeight = -1;
- /*
- * Querying the surface (actually the current buffer) dimensions here is
- * the only truly safe way to be sure that the dimensions we think we
- * have are those of the buffer being rendered to. But this should be
- * improved in future; https://bugs.launchpad.net/mir/+bug/1194384
- */
- eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &newBufferWidth);
- eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &newBufferHeight);
-
- ubuntuWindow->onBuffersSwapped_threadSafe(newBufferWidth, newBufferHeight);
+ ubuntuWindow->onSwapBuffersDone();
}
void (*QMirClientOpenGLContext::getProcAddress(const QByteArray& procName)) ()
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/plugins/platforms/mirclient/qmirclientglcontext.h
index cc40298259..29c196ce5c 100644
--- a/src/plugins/platforms/mirclient/qmirclientglcontext.h
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.h
@@ -53,7 +53,7 @@ public:
bool makeCurrent(QPlatformSurface* surface) override;
void doneCurrent() override;
bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; }
- void (*getProcAddress(const QByteArray& procName)) ();
+ void (*getProcAddress(const QByteArray& procName)) () override;
EGLContext eglContext() const { return mEglContext; }
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp
index 56bc21f420..addeda634c 100644
--- a/src/plugins/platforms/mirclient/qmirclientinput.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp
@@ -163,6 +163,7 @@ QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration)
, mEventFilterType(static_cast<QMirClientNativeInterface*>(
integration->nativeInterface())->genericEventFilterType())
, mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
+ , mLastFocusedWindow(nullptr)
{
// Initialize touch device.
mTouchDevice = new QTouchDevice;
@@ -234,7 +235,7 @@ void QMirClientInput::customEvent(QEvent* event)
switch (mir_event_get_type(nativeEvent))
{
case mir_event_type_input:
- dispatchInputEvent(ubuntuEvent->window->window(), mir_event_get_input_event(nativeEvent));
+ dispatchInputEvent(ubuntuEvent->window, mir_event_get_input_event(nativeEvent));
break;
case mir_event_type_resize:
{
@@ -246,7 +247,7 @@ void QMirClientInput::customEvent(QEvent* event)
mir_resize_event_get_width(resizeEvent),
mir_resize_event_get_height(resizeEvent));
- ubuntuEvent->window->handleSurfaceResize(mir_resize_event_get_width(resizeEvent),
+ ubuntuEvent->window->handleSurfaceResized(mir_resize_event_get_width(resizeEvent),
mir_resize_event_get_height(resizeEvent));
break;
}
@@ -254,8 +255,24 @@ void QMirClientInput::customEvent(QEvent* event)
{
auto surfaceEvent = mir_event_get_surface_event(nativeEvent);
if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) {
- ubuntuEvent->window->handleSurfaceFocusChange(mir_surface_event_get_attribute_value(surfaceEvent) ==
- mir_surface_focused);
+ const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused;
+ // Mir may have sent a pair of focus lost/gained events, so we need to "peek" into the queue
+ // so that we don't deactivate windows prematurely.
+ if (focused) {
+ mPendingFocusGainedEvents--;
+ ubuntuEvent->window->handleSurfaceFocused();
+ QWindowSystemInterface::handleWindowActivated(ubuntuEvent->window->window(), Qt::ActiveWindowFocusReason);
+
+ // NB: Since processing of system events is queued, never check qGuiApp->applicationState()
+ // as it might be outdated. Always call handleApplicationStateChanged() with the latest
+ // state regardless.
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
+
+ } else if (!mPendingFocusGainedEvents) {
+ DLOG("[ubuntumirclient QPA] No windows have focus");
+ QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ }
}
break;
}
@@ -274,6 +291,17 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent
{
QWindow *window = platformWindow->window();
+ const auto eventType = mir_event_get_type(event);
+ if (mir_event_type_surface == eventType) {
+ auto surfaceEvent = mir_event_get_surface_event(event);
+ if (mir_surface_attrib_focus == mir_surface_event_get_attribute(surfaceEvent)) {
+ const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused;
+ if (focused) {
+ mPendingFocusGainedEvents++;
+ }
+ }
+ }
+
QCoreApplication::postEvent(this, new QMirClientEvent(
platformWindow, event, mEventType));
@@ -284,7 +312,7 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent
}
}
-void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *ev)
+void QMirClientInput::dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *ev)
{
switch (mir_input_event_get_type(ev))
{
@@ -302,7 +330,7 @@ void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *e
}
}
-void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev)
+void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev)
{
const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
@@ -333,6 +361,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e
switch (touch_action)
{
case mir_touch_action_down:
+ mLastFocusedWindow = window;
touchPoint.state = Qt::TouchPointPressed;
break;
case mir_touch_action_up:
@@ -347,7 +376,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e
}
ulong timestamp = mir_input_event_get_event_time(ev) / 1000000;
- QWindowSystemInterface::handleTouchEvent(window, timestamp,
+ QWindowSystemInterface::handleTouchEvent(window->window(), timestamp,
mTouchDevice, touchPoints);
}
@@ -390,7 +419,7 @@ Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers)
}
}
-void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event)
+void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event)
{
const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
@@ -404,6 +433,9 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve
QEvent::Type keyType = action == mir_keyboard_action_up
? QEvent::KeyRelease : QEvent::KeyPress;
+ if (action == mir_keyboard_action_down)
+ mLastFocusedWindow = window;
+
char s[2];
int sym = translateKeysym(xk_sym, s, sizeof(s));
QString text = QString::fromLatin1(s);
@@ -420,7 +452,7 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve
}
}
- QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text, is_auto_rep);
+ QWindowSystemInterface::handleKeyEvent(window->window(), timestamp, keyType, sym, modifiers, text, is_auto_rep);
}
namespace
@@ -433,27 +465,54 @@ Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
buttons |= Qt::RightButton;
if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
- buttons |= Qt::MidButton;
+ buttons |= Qt::MiddleButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_back))
+ buttons |= Qt::BackButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_forward))
+ buttons |= Qt::ForwardButton;
- // TODO: Should mir back and forward buttons exist?
- // should they be Qt::X button 1 and 2?
return buttons;
}
}
-void QMirClientInput::dispatchPointerEvent(QWindow *window, const MirInputEvent *ev)
+void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev)
{
+ auto window = platformWindow->window();
auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
auto pev = mir_input_event_get_pointer_event(ev);
+ auto action = mir_pointer_event_action(pev);
+ auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
+ mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
- auto buttons = extract_buttons(pev);
- auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
- mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
+ switch (action) {
+ case mir_pointer_action_button_up:
+ case mir_pointer_action_button_down:
+ case mir_pointer_action_motion:
+ {
+ const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll);
+ const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll);
- QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */,
- buttons, modifiers);
+ if (hDelta != 0 || vDelta != 0) {
+ const QPoint angleDelta = QPoint(hDelta * 15, vDelta * 15);
+ QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint,
+ QPoint(), angleDelta, modifiers, Qt::ScrollUpdate);
+ }
+ auto buttons = extract_buttons(pev);
+ QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */,
+ buttons, modifiers);
+ break;
+ }
+ case mir_pointer_action_enter:
+ QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint);
+ break;
+ case mir_pointer_action_leave:
+ QWindowSystemInterface::handleLeaveEvent(window);
+ break;
+ default:
+ DLOG("Unrecognized pointer event");
+ }
}
#if (LOG_EVENTS != 0)
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h
index c987d18c12..3ed887419e 100644
--- a/src/plugins/platforms/mirclient/qmirclientinput.h
+++ b/src/plugins/platforms/mirclient/qmirclientinput.h
@@ -40,6 +40,7 @@
// Qt
#include <qpa/qwindowsysteminterface.h>
+#include <QAtomicInt>
#include <mir_toolkit/mir_client_library.h>
@@ -59,12 +60,13 @@ public:
void postEvent(QMirClientWindow* window, const MirEvent *event);
QMirClientClientIntegration* integration() const { return mIntegration; }
+ QMirClientWindow *lastFocusedWindow() const {return mLastFocusedWindow; }
protected:
- void dispatchKeyEvent(QWindow *window, const MirInputEvent *event);
- void dispatchPointerEvent(QWindow *window, const MirInputEvent *event);
- void dispatchTouchEvent(QWindow *window, const MirInputEvent *event);
- void dispatchInputEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event);
+ void dispatchPointerEvent(QMirClientWindow *window, const MirInputEvent *event);
+ void dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *event);
+ void dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *event);
void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event);
@@ -73,6 +75,9 @@ private:
QTouchDevice* mTouchDevice;
const QByteArray mEventFilterType;
const QEvent::Type mEventType;
+
+ QMirClientWindow *mLastFocusedWindow;
+ QAtomicInt mPendingFocusGainedEvents;
};
#endif // QMIRCLIENTINPUT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
index 87d2002c56..592c2d803b 100644
--- a/src/plugins/platforms/mirclient/qmirclientintegration.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
@@ -35,28 +35,28 @@
****************************************************************************/
-// Qt
-#include <QGuiApplication>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qplatforminputcontextfactory_p.h>
-#include <qpa/qplatforminputcontext.h>
-#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
-#include <QOpenGLContext>
-
// Local
+#include "qmirclientintegration.h"
#include "qmirclientbackingstore.h"
#include "qmirclientclipboard.h"
#include "qmirclientglcontext.h"
#include "qmirclientinput.h"
-#include "qmirclientintegration.h"
#include "qmirclientlogging.h"
#include "qmirclientnativeinterface.h"
#include "qmirclientscreen.h"
#include "qmirclienttheme.h"
#include "qmirclientwindow.h"
+// Qt
+#include <QGuiApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatforminputcontext.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QOpenGLContext>
+
// platform-api
#include <ubuntu/application/lifecycle_delegate.h>
#include <ubuntu/application/id.h>
@@ -67,8 +67,11 @@ static void resumedCallback(const UApplicationOptions *options, void* context)
Q_UNUSED(options)
Q_UNUSED(context)
DASSERT(context != NULL);
- QCoreApplication::postEvent(QCoreApplication::instance(),
- new QEvent(QEvent::ApplicationActivate));
+ if (qGuiApp->focusWindow()) {
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
+ } else {
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ }
}
static void aboutToStopCallback(UApplicationArchive *archive, void* context)
@@ -76,9 +79,13 @@ static void aboutToStopCallback(UApplicationArchive *archive, void* context)
Q_UNUSED(archive)
DASSERT(context != NULL);
QMirClientClientIntegration* integration = static_cast<QMirClientClientIntegration*>(context);
- integration->inputContext()->hideInputPanel();
- QCoreApplication::postEvent(QCoreApplication::instance(),
- new QEvent(QEvent::ApplicationDeactivate));
+ QPlatformInputContext *inputContext = integration->inputContext();
+ if (inputContext) {
+ inputContext->hideInputPanel();
+ } else {
+ qWarning("QMirClientClientIntegration aboutToStopCallback(): no input context");
+ }
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
}
QMirClientClientIntegration::QMirClientClientIntegration()
@@ -100,6 +107,8 @@ QMirClientClientIntegration::QMirClientClientIntegration()
"running, and the correct socket is being used and is accessible. The shell may have\n"
"rejected the incoming connection, so check its log file");
+ mNativeInterface->setMirConnection(u_application_instance_get_mir_connection(mInstance));
+
// Create default screen.
mScreen = new QMirClientScreen(u_application_instance_get_mir_connection(mInstance));
screenAdded(mScreen);
@@ -176,10 +185,8 @@ QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* wind
QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window)
{
- QPlatformWindow* platformWindow = new QMirClientWindow(
- window, mClipboard, static_cast<QMirClientScreen*>(mScreen), mInput, u_application_instance_get_mir_connection(mInstance));
- platformWindow->requestActivateWindow();
- return platformWindow;
+ return new QMirClientWindow(window, mClipboard, static_cast<QMirClientScreen*>(mScreen),
+ mInput, u_application_instance_get_mir_connection(mInstance));
}
bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -187,11 +194,12 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability
switch (cap) {
case ThreadedPixmaps:
return true;
- break;
case OpenGL:
return true;
- break;
+
+ case ApplicationState:
+ return true;
case ThreadedOpenGL:
if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) {
@@ -200,8 +208,9 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability
DLOG("ubuntumirclient: disabled threaded OpenGL");
return false;
}
- break;
-
+ case MultipleWindows:
+ case NonFullScreenWindows:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -262,3 +271,8 @@ QPlatformClipboard* QMirClientClientIntegration::clipboard() const
{
return mClipboard.data();
}
+
+QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const
+{
+ return mNativeInterface;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h
index 2960209691..e41cbe2cee 100644
--- a/src/plugins/platforms/mirclient/qmirclientintegration.h
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.h
@@ -49,6 +49,7 @@
class QMirClientClipboard;
class QMirClientInput;
+class QMirClientNativeInterface;
class QMirClientScreen;
class QMirClientClientIntegration : public QPlatformIntegration {
@@ -59,7 +60,7 @@ public:
// QPlatformIntegration methods.
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QAbstractEventDispatcher *createEventDispatcher() const override;
- QPlatformNativeInterface* nativeInterface() const override { return mNativeInterface; }
+ QPlatformNativeInterface* nativeInterface() const override;
QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override;
QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override;
QPlatformFontDatabase* fontDatabase() const override { return mFontDb; }
@@ -79,7 +80,7 @@ private:
void setupOptions();
void setupDescription();
- QPlatformNativeInterface* mNativeInterface;
+ QMirClientNativeInterface* mNativeInterface;
QPlatformFontDatabase* mFontDb;
QMirClientPlatformServices* mServices;
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
index a0bb932df3..1b4c20153b 100644
--- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
@@ -35,17 +35,17 @@
****************************************************************************/
+// Local
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclientglcontext.h"
+
// Qt
#include <private/qguiapplication_p.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qscreen.h>
#include <QtCore/QMap>
-// Local
-#include "qmirclientnativeinterface.h"
-#include "qmirclientscreen.h"
-#include "qmirclientglcontext.h"
-
class QMirClientResourceMap : public QMap<QByteArray, QMirClientNativeInterface::ResourceType>
{
public:
@@ -55,6 +55,7 @@ public:
insert("eglcontext", QMirClientNativeInterface::EglContext);
insert("nativeorientation", QMirClientNativeInterface::NativeOrientation);
insert("display", QMirClientNativeInterface::Display);
+ insert("mirconnection", QMirClientNativeInterface::MirConnection);
}
};
@@ -63,6 +64,7 @@ Q_GLOBAL_STATIC(QMirClientResourceMap, ubuntuResourceMap)
QMirClientNativeInterface::QMirClientNativeInterface()
: mGenericEventFilterType(QByteArrayLiteral("Event"))
, mNativeOrientation(nullptr)
+ , mMirConnection(nullptr)
{
}
@@ -72,6 +74,23 @@ QMirClientNativeInterface::~QMirClientNativeInterface()
mNativeOrientation = nullptr;
}
+void* QMirClientNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
+{
+ const QByteArray lowerCaseResource = resourceString.toLower();
+
+ if (!ubuntuResourceMap()->contains(lowerCaseResource)) {
+ return nullptr;
+ }
+
+ const ResourceType resourceType = ubuntuResourceMap()->value(lowerCaseResource);
+
+ if (resourceType == QMirClientNativeInterface::MirConnection) {
+ return mMirConnection;
+ } else {
+ return nullptr;
+ }
+}
+
void* QMirClientNativeInterface::nativeResourceForContext(
const QByteArray& resourceString, QOpenGLContext* context)
{
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
index 84f03bb915..7df646e73a 100644
--- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
@@ -42,12 +42,13 @@
class QMirClientNativeInterface : public QPlatformNativeInterface {
public:
- enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display };
+ enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display, MirConnection };
QMirClientNativeInterface();
~QMirClientNativeInterface();
// QPlatformNativeInterface methods.
+ void* nativeResourceForIntegration(const QByteArray &resource) override;
void* nativeResourceForContext(const QByteArray& resourceString,
QOpenGLContext* context) override;
void* nativeResourceForWindow(const QByteArray& resourceString,
@@ -57,10 +58,12 @@ public:
// New methods.
const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; }
+ void setMirConnection(void *mirConnection) { mMirConnection = mirConnection; }
private:
const QByteArray mGenericEventFilterType;
Qt::ScreenOrientation* mNativeOrientation;
+ void *mMirConnection;
};
#endif // QMIRCLIENTNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
index 24d7307faa..2a1ed9c09f 100644
--- a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
+++ b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
@@ -43,15 +43,7 @@
class OrientationChangeEvent : public QEvent {
public:
- enum Orientation {
- Undefined = 0,
- TopUp,
- TopDown,
- LeftUp,
- RightUp,
- FaceUp,
- FaceDown
- };
+ enum Orientation { TopUp, LeftUp, TopDown, RightUp };
OrientationChangeEvent(QEvent::Type type, Orientation orientation)
: QEvent(type)
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
index 203a1cbfd8..75561f7fd3 100644
--- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
@@ -41,14 +41,14 @@
QStringList QMirClientIntegrationPlugin::keys() const
{
QStringList list;
- list << "mirclient";
+ list << QStringLiteral("mirclient");
return list;
}
QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system,
const QStringList &)
{
- if (system.toLower() == "mirclient") {
+ if (system.toLower() == QLatin1String("mirclient")) {
return new QMirClientClientIntegration;
} else {
return 0;
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
index 5c4b1cd0d6..3eb01f816a 100644
--- a/src/plugins/platforms/mirclient/qmirclientscreen.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Canonical, Ltd.
+** Copyright (C) 2014-2015 Canonical, Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -35,6 +35,11 @@
****************************************************************************/
+// local
+#include "qmirclientscreen.h"
+#include "qmirclientlogging.h"
+#include "qmirclientorientationchangeevent_p.h"
+
#include <mir_toolkit/mir_client_library.h>
// Qt
@@ -45,12 +50,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
-// local
-#include "qmirclientscreen.h"
-#include "qmirclientlogging.h"
-#include "qmirclientorientationchangeevent_p.h"
-
-#include "memory"
+#include <memory>
static const int kSwapInterval = 1;
@@ -149,9 +149,11 @@ static const MirDisplayOutput *find_active_output(
QMirClientScreen::QMirClientScreen(MirConnection *connection)
: mFormat(QImage::Format_RGB32)
, mDepth(32)
+ , mOutputId(0)
, mSurfaceFormat()
, mEglDisplay(EGL_NO_DISPLAY)
, mEglConfig(nullptr)
+ , mCursor(connection)
{
// Initialize EGL.
ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE);
@@ -203,6 +205,11 @@ QMirClientScreen::QMirClientScreen(MirConnection *connection)
auto const displayOutput = find_active_output(displayConfig.get());
ASSERT(displayOutput != nullptr);
+ mOutputId = displayOutput->output_id;
+
+ mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm);
+ DLOG("ubuntumirclient: screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height());
+
const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode];
const int kScreenWidth = mode->horizontal_resolution;
const int kScreenHeight = mode->vertical_resolution;
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h
index 5d9325354f..a6b4f442da 100644
--- a/src/plugins/platforms/mirclient/qmirclientscreen.h
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Canonical, Ltd.
+** Copyright (C) 2014-2015 Canonical, Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -42,6 +42,8 @@
#include <QSurfaceFormat>
#include <EGL/egl.h>
+#include "qmirclientcursor.h"
+
struct MirConnection;
class QMirClientScreen : public QObject, public QPlatformScreen
@@ -56,8 +58,10 @@ public:
int depth() const override { return mDepth; }
QRect geometry() const override { return mGeometry; }
QRect availableGeometry() const override { return mGeometry; }
+ QSizeF physicalSize() const override { return mPhysicalSize; }
Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
+ QPlatformCursor *cursor() const override { return const_cast<QMirClientCursor*>(&mCursor); }
// New methods.
QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; }
@@ -65,20 +69,24 @@ public:
EGLConfig eglConfig() const { return mEglConfig; }
EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
void handleWindowSurfaceResize(int width, int height);
+ uint32_t mirOutputId() const { return mOutputId; }
// QObject methods.
- void customEvent(QEvent* event);
+ void customEvent(QEvent* event) override;
private:
QRect mGeometry;
+ QSizeF mPhysicalSize;
Qt::ScreenOrientation mNativeOrientation;
Qt::ScreenOrientation mCurrentOrientation;
QImage::Format mFormat;
int mDepth;
+ uint32_t mOutputId;
QSurfaceFormat mSurfaceFormat;
EGLDisplay mEglDisplay;
EGLConfig mEglConfig;
EGLNativeDisplayType mEglNativeDisplay;
+ QMirClientCursor mCursor;
};
#endif // QMIRCLIENTSCREEN_H
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
index 3d1e5377e5..9a72c2f9dc 100644
--- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
@@ -36,16 +36,16 @@
// Local
+#include "qmirclientwindow.h"
#include "qmirclientclipboard.h"
#include "qmirclientinput.h"
-#include "qmirclientwindow.h"
#include "qmirclientscreen.h"
#include "qmirclientlogging.h"
+#include <mir_toolkit/mir_client_library.h>
+
// Qt
#include <qpa/qwindowsysteminterface.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <QMutex>
#include <QMutexLocker>
#include <QSize>
#include <QtMath>
@@ -55,25 +55,46 @@
#include <EGL/egl.h>
-#define IS_OPAQUE_FLAG 1
-
namespace
{
+
+// FIXME: this used to be defined by platform-api, but it's been removed in v3. Change ubuntu-keyboard to use
+// a different enum for window roles.
+enum UAUiWindowRole {
+ U_MAIN_ROLE = 1,
+ U_DASH_ROLE,
+ U_INDICATOR_ROLE,
+ U_NOTIFICATIONS_ROLE,
+ U_GREETER_ROLE,
+ U_LAUNCHER_ROLE,
+ U_ON_SCREEN_KEYBOARD_ROLE,
+ U_SHUTDOWN_DIALOG_ROLE,
+};
+
+struct MirSpecDeleter
+{
+ void operator()(MirSurfaceSpec *spec) { mir_surface_spec_release(spec); }
+};
+
+using Spec = std::unique_ptr<MirSurfaceSpec, MirSpecDeleter>;
+
+EGLNativeWindowType nativeWindowFor(MirSurface *surf)
+{
+ auto stream = mir_surface_get_buffer_stream(surf);
+ return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
+}
+
MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
{
switch (state) {
case Qt::WindowNoState:
return mir_surface_state_restored;
-
case Qt::WindowFullScreen:
return mir_surface_state_fullscreen;
-
case Qt::WindowMaximized:
return mir_surface_state_maximized;
-
case Qt::WindowMinimized:
return mir_surface_state_minimized;
-
default:
LOG("Unexpected Qt::WindowState: %d", state);
return mir_surface_state_restored;
@@ -86,117 +107,137 @@ const char *qtWindowStateToStr(Qt::WindowState state)
switch (state) {
case Qt::WindowNoState:
return "NoState";
-
case Qt::WindowFullScreen:
return "FullScreen";
-
case Qt::WindowMaximized:
return "Maximized";
-
case Qt::WindowMinimized:
return "Minimized";
-
default:
return "!?";
}
}
#endif
-} // anonymous namespace
-
-class QMirClientWindowPrivate
+WId makeId()
{
-public:
- void createEGLSurface(EGLNativeWindowType nativeWindow);
- void destroyEGLSurface();
- int panelHeight();
-
- QMirClientScreen* screen;
- EGLSurface eglSurface;
- WId id;
- QMirClientInput* input;
- Qt::WindowState state;
- MirConnection *connection;
- MirSurface* surface;
- QSize bufferSize;
- QMutex mutex;
- QSharedPointer<QMirClientClipboard> clipboard;
-};
-
-static void eventCallback(MirSurface* surface, const MirEvent *event, void* context)
-{
- (void) surface;
- DASSERT(context != NULL);
- QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
- platformWindow->priv()->input->postEvent(platformWindow, event);
+ static int id = 1;
+ return id++;
}
-static void surfaceCreateCallback(MirSurface* surface, void* context)
+MirPixelFormat defaultPixelFormatFor(MirConnection *connection)
{
- DASSERT(context != NULL);
- QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
- platformWindow->priv()->surface = surface;
-
- mir_surface_set_event_handler(surface, eventCallback, context);
+ MirPixelFormat format;
+ unsigned int nformats;
+ mir_connection_get_available_surface_formats(connection, &format, 1, &nformats);
+ return format;
}
-QMirClientWindow::QMirClientWindow(QWindow* w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen* screen,
- QMirClientInput* input, MirConnection* connection)
- : QObject(nullptr), QPlatformWindow(w)
+UAUiWindowRole roleFor(QWindow *window)
{
- DASSERT(screen != NULL);
+ QVariant roleVariant = window->property("role");
+ if (!roleVariant.isValid())
+ return U_MAIN_ROLE;
- d = new QMirClientWindowPrivate;
- d->screen = screen;
- d->eglSurface = EGL_NO_SURFACE;
- d->input = input;
- d->state = window()->windowState();
- d->connection = connection;
- d->clipboard = clipboard;
+ uint role = roleVariant.toUInt();
+ if (role < U_MAIN_ROLE || role > U_SHUTDOWN_DIALOG_ROLE)
+ return U_MAIN_ROLE;
- static int id = 1;
- d->id = id++;
-
- // Use client geometry if set explicitly, use available screen geometry otherwise.
- QPlatformWindow::setGeometry(window()->geometry().isValid() && window()->geometry() != screen->geometry() ?
- window()->geometry() : screen->availableGeometry());
- createWindow();
- DLOG("QMirClientWindow::QMirClientWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input);
+ return static_cast<UAUiWindowRole>(role);
}
-QMirClientWindow::~QMirClientWindow()
+QMirClientWindow *transientParentFor(QWindow *window)
{
- DLOG("QMirClientWindow::~QMirClientWindow");
- d->destroyEGLSurface();
-
- mir_surface_release_sync(d->surface);
-
- delete d;
+ QWindow *parent = window->transientParent();
+ return parent ? static_cast<QMirClientWindow *>(parent->handle()) : nullptr;
}
-void QMirClientWindowPrivate::createEGLSurface(EGLNativeWindowType nativeWindow)
+Spec makeSurfaceSpec(QWindow *window, QMirClientInput *input, MirConnection *connection)
{
- DLOG("QMirClientWindowPrivate::createEGLSurface (this=%p, nativeWindow=%p)",
- this, reinterpret_cast<void*>(nativeWindow));
-
- eglSurface = eglCreateWindowSurface(screen->eglDisplay(), screen->eglConfig(),
- nativeWindow, nullptr);
+ const auto geom = window->geometry();
+ const int width = geom.width() > 0 ? geom.width() : 1;
+ const int height = geom.height() > 0 ? geom.height() : 1;
+ const auto pixelFormat = defaultPixelFormatFor(connection);
+
+ if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
+ return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};
+ }
+
+ const Qt::WindowType type = window->type();
+ if (type == Qt::Popup) {
+ auto parent = transientParentFor(window);
+ if (parent == nullptr) {
+ //NOTE: We cannot have a parentless popup -
+ //try using the last surface to receive input as that will most likely be
+ //the one that caused this popup to be created
+ parent = input->lastFocusedWindow();
+ }
+ if (parent) {
+ auto pos = geom.topLeft();
+ pos -= parent->geometry().topLeft();
+ MirRectangle location{pos.x(), pos.y(), 0, 0};
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height);
+ return Spec{mir_connection_create_spec_for_menu(
+ connection, width, height, pixelFormat, parent->mirSurface(),
+ &location, mir_edge_attachment_any)};
+ } else {
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window);
+ }
+ } else if (type == Qt::Dialog) {
+ auto parent = transientParentFor(window);
+ if (parent) {
+ // Modal dialog
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height);
+ return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())};
+ } else {
+ // TODO: do Qt parentless dialogs have the same semantics as mir?
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height);
+ return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};
+ }
+ }
+ DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height);
+ return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};
+}
- DASSERT(eglSurface != EGL_NO_SURFACE);
+void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment)
+{
+ mir_surface_spec_set_min_width(spec, minSize.width());
+ mir_surface_spec_set_min_height(spec, minSize.height());
+ if (maxSize.width() >= minSize.width()) {
+ mir_surface_spec_set_max_width(spec, maxSize.width());
+ }
+ if (maxSize.height() >= minSize.height()) {
+ mir_surface_spec_set_max_height(spec, maxSize.height());
+ }
+ if (increment.width() > 0) {
+ mir_surface_spec_set_width_increment(spec, increment.width());
+ }
+ if (increment.height() > 0) {
+ mir_surface_spec_set_height_increment(spec, increment.height());
+ }
}
-void QMirClientWindowPrivate::destroyEGLSurface()
+MirSurface *createMirSurface(QWindow *window, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection)
{
- DLOG("QMirClientWindowPrivate::destroyEGLSurface (this=%p)", this);
- if (eglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(screen->eglDisplay(), eglSurface);
- eglSurface = EGL_NO_SURFACE;
+ auto spec = makeSurfaceSpec(window, input, connection);
+ const auto title = window->title().toUtf8();
+ mir_surface_spec_set_name(spec.get(), title.constData());
+
+ setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement());
+
+ if (window->windowState() == Qt::WindowFullScreen) {
+ mir_surface_spec_set_fullscreen_on_output(spec.get(), screen->mirOutputId());
}
+
+ auto surface = mir_surface_create_sync(spec.get());
+ Q_ASSERT(mir_surface_is_valid(surface));
+ return surface;
}
// FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
-// we need to guess the panel height (3GU + 2DP)
-int QMirClientWindowPrivate::panelHeight()
+// we need to guess the panel height (3GU)
+int panelHeight()
{
if (qEnvironmentVariableIsSet("QT_MIRCLIENT_IGNORE_PANEL"))
return 0;
@@ -210,245 +251,412 @@ int QMirClientWindowPrivate::panelHeight()
gridUnit = defaultGridUnit;
}
}
- qreal densityPixelRatio = static_cast<qreal>(gridUnit) / defaultGridUnit;
- return gridUnit * 3 + qFloor(densityPixelRatio) * 2;
+ return gridUnit * 3;
}
-namespace
+} //namespace
+
+class QMirClientSurface
{
-static MirPixelFormat
-mir_choose_default_pixel_format(MirConnection *connection)
+public:
+ QMirClientSurface(QMirClientWindow *platformWindow, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection)
+ : mWindow(platformWindow->window())
+ , mPlatformWindow(platformWindow)
+ , mInput(input)
+ , mConnection(connection)
+ , mMirSurface(createMirSurface(mWindow, screen, input, connection))
+ , mEglDisplay(screen->eglDisplay())
+ , mEglSurface(eglCreateWindowSurface(mEglDisplay, screen->eglConfig(), nativeWindowFor(mMirSurface), nullptr))
+ , mVisible(false)
+ , mNeedsRepaint(false)
+ , mParented(mWindow->transientParent() || mWindow->parent())
+ , mWindowState(mWindow->windowState())
+
+ {
+ mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this);
+
+ // Window manager can give us a final size different from what we asked for
+ // so let's check what we ended up getting
+ MirSurfaceParameters parameters;
+ mir_surface_get_parameters(mMirSurface, &parameters);
+
+ auto geom = mWindow->geometry();
+ geom.setWidth(parameters.width);
+ geom.setHeight(parameters.height);
+ if (mWindowState == Qt::WindowFullScreen) {
+ geom.setY(0);
+ } else {
+ geom.setY(panelHeight());
+ }
+
+ // Assume that the buffer size matches the surface size at creation time
+ mBufferSize = geom.size();
+ platformWindow->QPlatformWindow::setGeometry(geom);
+ QWindowSystemInterface::handleGeometryChange(mWindow, geom);
+
+ DLOG("[ubuntumirclient QPA] created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n",
+ geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow));
+ }
+
+ ~QMirClientSurface()
+ {
+ if (mEglSurface != EGL_NO_SURFACE)
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ if (mMirSurface)
+ mir_surface_release_sync(mMirSurface);
+ }
+
+ QMirClientSurface(QMirClientSurface const&) = delete;
+ QMirClientSurface& operator=(QMirClientSurface const&) = delete;
+
+ void resize(const QSize& newSize);
+ void setState(Qt::WindowState newState);
+ void setVisible(bool state);
+ void updateTitle(const QString& title);
+ void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);
+
+ void onSwapBuffersDone();
+ void handleSurfaceResized(int width, int height);
+ int needsRepaint() const;
+
+ EGLSurface eglSurface() const { return mEglSurface; }
+ MirSurface *mirSurface() const { return mMirSurface; }
+
+private:
+ static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
+ void postEvent(const MirEvent *event);
+ void updateSurface();
+
+ QWindow * const mWindow;
+ QMirClientWindow * const mPlatformWindow;
+ QMirClientInput * const mInput;
+ MirConnection * const mConnection;
+
+ MirSurface * const mMirSurface;
+ const EGLDisplay mEglDisplay;
+ const EGLSurface mEglSurface;
+
+ bool mVisible;
+ bool mNeedsRepaint;
+ bool mParented;
+ Qt::WindowState mWindowState;
+ QSize mBufferSize;
+
+ QMutex mTargetSizeMutex;
+ QSize mTargetSize;
+};
+
+void QMirClientSurface::resize(const QSize& size)
{
- MirPixelFormat format[mir_pixel_formats];
- unsigned int nformats;
+ DLOG("[ubuntumirclient QPA] resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());
+
+ if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {
+ DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
+ return;
+ }
- mir_connection_get_available_surface_formats(connection,
- format, mir_pixel_formats, &nformats);
+ if (size.isEmpty()) {
+ DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, size is empty", mWindow);
+ return;
+ }
- return format[0];
+ Spec spec{mir_connection_create_spec_for_changes(mConnection)};
+ mir_surface_spec_set_width(spec.get(), size.width());
+ mir_surface_spec_set_height(spec.get(), size.height());
+ mir_surface_apply_spec(mMirSurface, spec.get());
}
+
+void QMirClientSurface::setState(Qt::WindowState newState)
+{
+ mir_wait_for(mir_surface_set_state(mMirSurface, qtWindowStateToMirSurfaceState(newState)));
+ mWindowState = newState;
}
-void QMirClientWindow::createWindow()
+void QMirClientSurface::setVisible(bool visible)
{
- DLOG("QMirClientWindow::createWindow (this=%p)", this);
+ if (mVisible == visible)
+ return;
- // FIXME: remove this remnant of an old platform-api enum - needs ubuntu-keyboard update
- const int SCREEN_KEYBOARD_ROLE = 7;
- // Get surface role and flags.
- QVariant roleVariant = window()->property("role");
- int role = roleVariant.isValid() ? roleVariant.toUInt() : 1; // 1 is the default role for apps.
- QVariant opaqueVariant = window()->property("opaque");
- uint flags = opaqueVariant.isValid() ?
- opaqueVariant.toUInt() ? static_cast<uint>(IS_OPAQUE_FLAG) : 0 : 0;
+ mVisible = visible;
- // FIXME(loicm) Opaque flag is forced for now for non-system sessions (applications) for
- // performance reasons.
- flags |= static_cast<uint>(IS_OPAQUE_FLAG);
+ if (mVisible)
+ updateSurface();
+
+ // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
+ // Will have to change qtmir and unity8 for that.
+ const auto newState = visible ? qtWindowStateToMirSurfaceState(mWindowState) : mir_surface_state_minimized;
+ mir_wait_for(mir_surface_set_state(mMirSurface, newState));
+}
+
+void QMirClientSurface::updateTitle(const QString& newTitle)
+{
+ const auto title = newTitle.toUtf8();
+ Spec spec{mir_connection_create_spec_for_changes(mConnection)};
+ mir_surface_spec_set_name(spec.get(), title.constData());
+ mir_surface_apply_spec(mMirSurface, spec.get());
+}
- const QByteArray title = (!window()->title().isNull()) ? window()->title().toUtf8() : "Window 1"; // legacy title
- const int panelHeight = d->panelHeight();
+void QMirClientSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment)
+{
+ Spec spec{mir_connection_create_spec_for_changes(mConnection)};
+ ::setSizingConstraints(spec.get(), minSize, maxSize, increment);
+ mir_surface_apply_spec(mMirSurface, spec.get());
+}
+
+void QMirClientSurface::handleSurfaceResized(int width, int height)
+{
+ QMutexLocker lock(&mTargetSizeMutex);
+
+ // mir's resize event is mainly a signal that we need to redraw our content. We use the
+ // width/height as identifiers to figure out if this is the latest surface resize event
+ // that has posted, discarding any old ones. This avoids issuing too many redraw events.
+ // see TODO in postEvent as the ideal way we should handle this.
+ // The actual buffer size may or may have not changed at this point, so let the rendering
+ // thread drive the window geometry updates.
+ mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height;
+}
+
+int QMirClientSurface::needsRepaint() const
+{
+ if (mNeedsRepaint) {
+ if (mTargetSize != mBufferSize) {
+ //If the buffer hasn't changed yet, we need at least two redraws,
+ //once to get the new buffer size and propagate the geometry changes
+ //and the second to redraw the content at the new size
+ return 2;
+ } else {
+ // The buffer size has already been updated so we only need one redraw
+ // to render at the new size
+ return 1;
+ }
+ }
+ return 0;
+}
+void QMirClientSurface::onSwapBuffersDone()
+{
#if !defined(QT_NO_DEBUG)
- LOG("panelHeight: '%d'", panelHeight);
- LOG("role: '%d'", role);
- LOG("flags: '%s'", (flags & static_cast<uint>(1)) ? "Opaque" : "NotOpaque");
- LOG("title: '%s'", title.constData());
+ static int sFrameNumber = 0;
+ ++sFrameNumber;
#endif
- // Get surface geometry.
- QRect geometry;
- if (d->state == Qt::WindowFullScreen) {
- printf("QMirClientWindow - fullscreen geometry\n");
- geometry = screen()->geometry();
- } else if (d->state == Qt::WindowMaximized) {
- printf("QMirClientWindow - maximized geometry\n");
- geometry = screen()->availableGeometry();
- /*
- * FIXME: Autopilot relies on being able to convert coordinates relative of the window
- * into absolute screen coordinates. Mir does not allow this, see bug lp:1346633
- * Until there's a correct way to perform this transformation agreed, this horrible hack
- * guesses the transformation heuristically.
- *
- * Assumption: this method only used on phone devices!
- */
- geometry.setY(panelHeight);
- } else {
- printf("QMirClientWindow - regular geometry\n");
- geometry = this->geometry();
- geometry.setY(panelHeight);
- }
+ EGLint eglSurfaceWidth = -1;
+ EGLint eglSurfaceHeight = -1;
+ eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth);
+ eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight);
- DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with size (%d, %d) with title '%s'\n",
- geometry.x(), geometry.y(), geometry.width(), geometry.height(), title.data());
+ const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0;
- MirSurfaceSpec *spec;
- if (role == SCREEN_KEYBOARD_ROLE)
- {
- spec = mir_connection_create_spec_for_input_method(d->connection, geometry.width(),
- geometry.height(), mir_choose_default_pixel_format(d->connection));
- }
- else
- {
- spec = mir_connection_create_spec_for_normal_surface(d->connection, geometry.width(),
- geometry.height(), mir_choose_default_pixel_format(d->connection));
- }
- mir_surface_spec_set_name(spec, title.data());
+ if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) {
- // Create platform window
- mir_wait_for(mir_surface_create(spec, surfaceCreateCallback, this));
- mir_surface_spec_release(spec);
+ DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)",
+ mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight);
- DASSERT(d->surface != NULL);
- d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface)));
+ mBufferSize.rwidth() = eglSurfaceWidth;
+ mBufferSize.rheight() = eglSurfaceHeight;
- if (d->state == Qt::WindowFullScreen) {
- // TODO: We could set this on creation once surface spec supports it (mps already up)
- mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_fullscreen));
+ QRect newGeometry = mPlatformWindow->geometry();
+ newGeometry.setSize(mBufferSize);
+
+ mPlatformWindow->QPlatformWindow::setGeometry(newGeometry);
+ QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
+ } else {
+#if 0
+ DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",
+ mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height());
+#endif
}
+}
- // Window manager can give us a final size different from what we asked for
- // so let's check what we ended up getting
- {
- MirSurfaceParameters parameters;
- mir_surface_get_parameters(d->surface, &parameters);
+void QMirClientSurface::surfaceEventCallback(MirSurface *surface, const MirEvent *event, void* context)
+{
+ Q_UNUSED(surface);
+ Q_ASSERT(context != nullptr);
- geometry.setWidth(parameters.width);
- geometry.setHeight(parameters.height);
- }
+ auto s = static_cast<QMirClientSurface *>(context);
+ s->postEvent(event);
+}
- DLOG("[ubuntumirclient QPA] created surface has size (%d, %d)",
- geometry.width(), geometry.height());
+void QMirClientSurface::postEvent(const MirEvent *event)
+{
+ if (mir_event_type_resize == mir_event_get_type(event)) {
+ // TODO: The current event queue just accumulates all resize events;
+ // It would be nicer if we could update just one event if that event has not been dispatched.
+ // As a workaround, we use the width/height as an identifier of this latest event
+ // so the event handler (handleSurfaceResized) can discard/ignore old ones.
+ const auto resizeEvent = mir_event_get_resize_event(event);
+ const auto width = mir_resize_event_get_width(resizeEvent);
+ const auto height = mir_resize_event_get_height(resizeEvent);
+ DLOG("[ubuntumirclient QPA] resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height);
+
+ QMutexLocker lock(&mTargetSizeMutex);
+ mTargetSize.rwidth() = width;
+ mTargetSize.rheight() = height;
+ }
- // Assume that the buffer size matches the surface size at creation time
- d->bufferSize = geometry.size();
+ mInput->postEvent(mPlatformWindow, event);
+}
- // Tell Qt about the geometry.
- QWindowSystemInterface::handleGeometryChange(window(), geometry);
- QPlatformWindow::setGeometry(geometry);
+void QMirClientSurface::updateSurface()
+{
+ DLOG("[ubuntumirclient QPA] updateSurface(window=%p)", mWindow);
+
+ if (!mParented && mWindow->type() == Qt::Dialog) {
+ // The dialog may have been parented after creation time
+ // so morph it into a modal dialog
+ auto parent = transientParentFor(mWindow);
+ if (parent) {
+ DLOG("[ubuntumirclient QPA] updateSurface(window=%p) dialog now parented", mWindow);
+ mParented = true;
+ Spec spec{mir_connection_create_spec_for_changes(mConnection)};
+ mir_surface_spec_set_parent(spec.get(), parent->mirSurface());
+ mir_surface_apply_spec(mMirSurface, spec.get());
+ }
+ }
}
-void QMirClientWindow::moveResize(const QRect& rect)
+QMirClientWindow::QMirClientWindow(QWindow *w, const QSharedPointer<QMirClientClipboard> &clipboard, QMirClientScreen *screen,
+ QMirClientInput *input, MirConnection *connection)
+ : QObject(nullptr)
+ , QPlatformWindow(w)
+ , mId(makeId())
+ , mClipboard(clipboard)
+ , mSurface(new QMirClientSurface{this, screen, input, connection})
{
- (void) rect;
- // TODO: Not yet supported by mir.
+ DLOG("[ubuntumirclient QPA] QMirClientWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());
}
-void QMirClientWindow::handleSurfaceResize(int width, int height)
+QMirClientWindow::~QMirClientWindow()
{
- QMutexLocker(&d->mutex);
- LOG("QMirClientWindow::handleSurfaceResize(width=%d, height=%d)", width, height);
+ DLOG("[ubuntumirclient QPA] ~QMirClientWindow(window=%p)", this);
+}
- // The current buffer size hasn't actually changed. so just render on it and swap
- // buffers in the hope that the next buffer will match the surface size advertised
- // in this event.
- // But since this event is processed by a thread different from the one that swaps
- // buffers, you can never know if this information is already outdated as there's
- // no synchronicity whatsoever between the processing of resize events and the
- // consumption of buffers.
- if (d->bufferSize.width() != width || d->bufferSize.height() != height) {
- QWindowSystemInterface::handleExposeEvent(window(), geometry());
- QWindowSystemInterface::flushWindowSystemEvents();
+void QMirClientWindow::handleSurfaceResized(int width, int height)
+{
+ QMutexLocker lock(&mMutex);
+ DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height);
+
+ mSurface->handleSurfaceResized(width, height);
+
+ // This resize event could have occurred just after the last buffer swap for this window.
+ // This means the client may still be holding a buffer with the older size. The first redraw call
+ // will then render at the old size. After swapping the client now will get a new buffer with the
+ // updated size but it still needs re-rendering so another redraw may be needed.
+ // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
+ auto const numRepaints = mSurface->needsRepaint();
+ DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
+ for (int i = 0; i < numRepaints; i++) {
+ DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
}
-void QMirClientWindow::handleSurfaceFocusChange(bool focused)
+void QMirClientWindow::handleSurfaceFocused()
{
- LOG("QMirClientWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false");
- QWindow *activatedWindow = focused ? window() : nullptr;
+ DLOG("[ubuntumirclient QPA] handleSurfaceFocused(window=%p)", window());
- // System clipboard contents might have changed while this window was unfocused and wihtout
+ // System clipboard contents might have changed while this window was unfocused and without
// this process getting notified about it because it might have been suspended (due to
// application lifecycle policies), thus unable to listen to any changes notified through
// D-Bus.
// Therefore let's ensure we are up to date with the system clipboard now that we are getting
// focused again.
- if (focused) {
- d->clipboard->requestDBusClipboardContents();
- }
-
- QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason);
+ mClipboard->requestDBusClipboardContents();
}
void QMirClientWindow::setWindowState(Qt::WindowState state)
{
- QMutexLocker(&d->mutex);
- DLOG("QMirClientWindow::setWindowState (this=%p, %s)", this, qtWindowStateToStr(state));
+ QMutexLocker lock(&mMutex);
+ DLOG("[ubuntumirclient QPA] setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
+ mSurface->setState(state);
- if (state == d->state)
- return;
+ updatePanelHeightHack(state);
+}
- // TODO: Perhaps we should check if the states are applied?
- mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(state)));
- d->state = state;
+/*
+ FIXME: Mir does not let clients know the position of their windows in the virtual
+ desktop space. So we have this ugly hack that assumes a phone situation where the
+ window is always on the top-left corner, right below the indicators panel if not
+ in fullscreen.
+ */
+void QMirClientWindow::updatePanelHeightHack(Qt::WindowState state)
+{
+ if (state == Qt::WindowFullScreen && geometry().y() != 0) {
+ QRect newGeometry = geometry();
+ newGeometry.setY(0);
+ QPlatformWindow::setGeometry(newGeometry);
+ QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
+ } else if (geometry().y() == 0) {
+ QRect newGeometry = geometry();
+ newGeometry.setY(panelHeight());
+ QPlatformWindow::setGeometry(newGeometry);
+ QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
+ }
}
void QMirClientWindow::setGeometry(const QRect& rect)
{
- DLOG("QMirClientWindow::setGeometry (this=%p)", this);
+ QMutexLocker lock(&mMutex);
+ DLOG("[ubuntumirclient QPA] setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)",
+ window(), rect.x(), rect.y(), rect.width(), rect.height());
- bool doMoveResize;
+ //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates
+ const auto newSize = rect.size();
+ auto newGeometry = geometry();
+ newGeometry.setSize(newSize);
+ QPlatformWindow::setGeometry(newGeometry);
- {
- QMutexLocker(&d->mutex);
- QPlatformWindow::setGeometry(rect);
- doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized;
- }
-
- if (doMoveResize) {
- moveResize(rect);
- }
+ mSurface->resize(newSize);
}
void QMirClientWindow::setVisible(bool visible)
{
- QMutexLocker(&d->mutex);
- DLOG("QMirClientWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false");
+ QMutexLocker lock(&mMutex);
+ DLOG("[ubuntumirclient QPA] setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
- if (visible) {
- mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(d->state)));
+ mSurface->setVisible(visible);
+ const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect();
- QWindowSystemInterface::handleExposeEvent(window(), QRect());
- QWindowSystemInterface::flushWindowSystemEvents();
- } else {
- // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
- // Will have to change qtmir and unity8 for that.
- mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_minimized));
- }
+ lock.unlock();
+ QWindowSystemInterface::handleExposeEvent(window(), exposeRect);
+ QWindowSystemInterface::flushWindowSystemEvents();
}
-void* QMirClientWindow::eglSurface() const
+void QMirClientWindow::setWindowTitle(const QString& title)
{
- return d->eglSurface;
+ QMutexLocker lock(&mMutex);
+ DLOG("[ubuntumirclient QPA] setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
+ mSurface->updateTitle(title);
}
-WId QMirClientWindow::winId() const
+void QMirClientWindow::propagateSizeHints()
{
- return d->id;
+ QMutexLocker lock(&mMutex);
+ const auto win = window();
+ DLOG("[ubuntumirclient QPA] propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)",
+ win, win->minimumSize().width(), win->minimumSize().height(),
+ win->maximumSize().width(), win->maximumSize().height(),
+ win->sizeIncrement().width(), win->sizeIncrement().height());
+ mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());
}
-void QMirClientWindow::onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight)
+void* QMirClientWindow::eglSurface() const
{
- QMutexLocker(&d->mutex);
-
- bool sizeKnown = newBufferWidth > 0 && newBufferHeight > 0;
-
- if (sizeKnown && (d->bufferSize.width() != newBufferWidth ||
- d->bufferSize.height() != newBufferHeight)) {
-
- DLOG("QMirClientWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)",
- d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight);
-
- d->bufferSize.rwidth() = newBufferWidth;
- d->bufferSize.rheight() = newBufferHeight;
+ return mSurface->eglSurface();
+}
- QRect newGeometry;
+MirSurface *QMirClientWindow::mirSurface() const
+{
+ return mSurface->mirSurface();
+}
- newGeometry = geometry();
- newGeometry.setWidth(d->bufferSize.width());
- newGeometry.setHeight(d->bufferSize.height());
+WId QMirClientWindow::winId() const
+{
+ return mId;
+}
- QPlatformWindow::setGeometry(newGeometry);
- QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect());
- }
+void QMirClientWindow::onSwapBuffersDone()
+{
+ QMutexLocker lock(&mMutex);
+ mSurface->onSwapBuffersDone();
}
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h
index f342669544..4ec7879949 100644
--- a/src/plugins/platforms/mirclient/qmirclientwindow.h
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.h
@@ -40,20 +40,23 @@
#include <qpa/qplatformwindow.h>
#include <QSharedPointer>
+#include <QMutex>
-#include <mir_toolkit/mir_client_library.h>
+#include <memory>
class QMirClientClipboard;
class QMirClientInput;
class QMirClientScreen;
-class QMirClientWindowPrivate;
+class QMirClientSurface;
+struct MirConnection;
+struct MirSurface;
class QMirClientWindow : public QObject, public QPlatformWindow
{
Q_OBJECT
public:
- QMirClientWindow(QWindow *w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen *screen,
- QMirClientInput *input, MirConnection *mir_connection);
+ QMirClientWindow(QWindow *w, const QSharedPointer<QMirClientClipboard> &clipboard, QMirClientScreen *screen,
+ QMirClientInput *input, MirConnection *mirConnection);
virtual ~QMirClientWindow();
// QPlatformWindow methods.
@@ -61,20 +64,22 @@ public:
void setGeometry(const QRect&) override;
void setWindowState(Qt::WindowState state) override;
void setVisible(bool visible) override;
+ void setWindowTitle(const QString &title) override;
+ void propagateSizeHints() override;
// New methods.
- void* eglSurface() const;
- void handleSurfaceResize(int width, int height);
- void handleSurfaceFocusChange(bool focused);
- void onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight);
-
- QMirClientWindowPrivate* priv() { return d; }
+ void *eglSurface() const;
+ MirSurface *mirSurface() const;
+ void handleSurfaceResized(int width, int height);
+ void handleSurfaceFocused();
+ void onSwapBuffersDone();
private:
- void createWindow();
- void moveResize(const QRect& rect);
-
- QMirClientWindowPrivate *d;
+ void updatePanelHeightHack(Qt::WindowState);
+ mutable QMutex mMutex;
+ const WId mId;
+ const QSharedPointer<QMirClientClipboard> mClipboard;
+ std::unique_ptr<QMirClientSurface> mSurface;
};
#endif // QMIRCLIENTWINDOW_H
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri
index e26c6614e2..0774d907f2 100644
--- a/src/plugins/platforms/windows/accessible/accessible.pri
+++ b/src/plugins/platforms/windows/accessible/accessible.pri
@@ -1,17 +1,20 @@
SOURCES += \
- $$PWD/qwindowsmsaaaccessible.cpp \
$$PWD/qwindowsaccessibility.cpp \
$$PWD/comutils.cpp
HEADERS += \
- $$PWD/qwindowsmsaaaccessible.h \
$$PWD/qwindowsaccessibility.h \
$$PWD/comutils.h
-!mingw: {
- SOURCES += $$PWD/iaccessible2.cpp
- HEADERS += $$PWD/iaccessible2.h
- include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
+!wince: {
+ SOURCES += $$PWD/qwindowsmsaaaccessible.cpp
+ HEADERS += $$PWD/qwindowsmsaaaccessible.h
+
+ !mingw: {
+ SOURCES += $$PWD/iaccessible2.cpp
+ HEADERS += $$PWD/iaccessible2.h
+ include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
+ }
}
-mingw: LIBS *= -luuid \ No newline at end of file
+mingw: LIBS *= -luuid
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index 44a9030c0c..13eee8e0fa 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -56,10 +56,12 @@
#include <QtGui/qguiapplication.h>
#include "qwindowsaccessibility.h"
-#ifdef Q_CC_MINGW
-# include "qwindowsmsaaaccessible.h"
-#else
-# include "iaccessible2.h"
+#if !defined(Q_OS_WINCE)
+# ifdef Q_CC_MINGW
+# include "qwindowsmsaaaccessible.h"
+# else
+# include "iaccessible2.h"
+# endif
#endif
#include "comutils.h"
@@ -74,8 +76,9 @@
#if !defined(WINABLEAPI)
# if defined(Q_OS_WINCE)
# include <bldver.h>
+# else
+# include <winable.h>
# endif
-# include <winable.h>
#endif
#include <servprov.h>
@@ -199,6 +202,11 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface)
*/
IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(acc);
+
+ return 0;
+#else
if (!acc)
return 0;
@@ -206,14 +214,15 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
if (!QAccessible::uniqueId(acc))
QAccessible::registerAccessibleInterface(acc);
-#ifdef Q_CC_MINGW
+# ifdef Q_CC_MINGW
QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc);
-#else
+# else
QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc);
-#endif
+# endif
IAccessible *iacc = 0;
wacc->QueryInterface(IID_IAccessible, (void**)&iacc);
return iacc;
+#endif // defined(Q_OS_WINCE)
}
/*
@@ -236,6 +245,7 @@ void QWindowsAccessibility::cleanup()
bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
+#if !defined(Q_OS_WINCE)
if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
/* For UI Automation */
} else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) {
@@ -254,9 +264,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W
if (!oleaccChecked) {
oleaccChecked = true;
-#if !defined(Q_OS_WINCE)
ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject");
-#endif
}
if (ptrLresultFromObject) {
@@ -275,6 +283,12 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W
}
}
}
+#else
+ Q_UNUSED(hwnd);
+ Q_UNUSED(wParam);
+ Q_UNUSED(lParam);
+ Q_UNUSED(lResult);
+#endif // !defined(Q_OS_WINCE)
return false;
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 298562e12f..0f41d01716 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -45,6 +45,7 @@
#include <QtGui/QWindow>
#include <QtGui/QPainter>
#include <private/qhighdpiscaling_p.h>
+#include <private/qimage_p.h>
#include <QtCore/QDebug>
@@ -58,7 +59,8 @@ QT_BEGIN_NAMESPACE
*/
QWindowsBackingStore::QWindowsBackingStore(QWindow *window) :
- QPlatformBackingStore(window)
+ QPlatformBackingStore(window),
+ m_alphaNeedsFill(false)
{
qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window;
}
@@ -150,8 +152,16 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
<< " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
}
#endif
- const QImage::Format format = window()->format().hasAlpha() ?
- QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat();
+ QImage::Format format = window()->format().hasAlpha() ?
+ QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat();
+
+ // The backingstore composition (enabling render-to-texture widgets)
+ // punches holes in the backingstores using the alpha channel. Hence
+ // the need for a true alpha format.
+ if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha)
+ m_alphaNeedsFill = true;
+ else // upgrade but here we know app painting does not rely on alpha hence no need to fill
+ format = qt_alphaVersionForPainting(format);
QWindowsNativeImage *oldwni = m_image.data();
QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
@@ -192,7 +202,7 @@ void QWindowsBackingStore::beginPaint(const QRegion &region)
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region;
- if (m_image->image().hasAlphaChannel()) {
+ if (m_alphaNeedsFill) {
QPainter p(&m_image->image());
p.setCompositionMode(QPainter::CompositionMode_Source);
const QColor blank = Qt::transparent;
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index b5b1d8feff..26c79348a9 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -71,6 +71,7 @@ public:
private:
QScopedPointer<QWindowsNativeImage> m_image;
+ bool m_alphaNeedsFill;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 44f3302644..594208ab17 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -882,12 +882,12 @@ public:
inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data);
- virtual void setWindowTitle(const QString &title);
+ void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options);
inline void setDirectory(const QUrl &directory);
inline void updateDirectory() { setDirectory(m_data.directory()); }
inline QString directory() const;
- virtual void doExec(HWND owner = 0);
+ void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
virtual void setNameFilters(const QStringList &f);
inline void selectNameFilter(const QString &filter);
inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
@@ -916,7 +916,7 @@ signals:
void filterSelected(const QString & filter);
public slots:
- virtual void close();
+ void close() Q_DECL_OVERRIDE;
protected:
explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data);
@@ -1466,9 +1466,9 @@ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
public:
explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data)
: QWindowsNativeFileDialogBase(data) {}
- virtual void setNameFilters(const QStringList &f);
- virtual QList<QUrl> selectedFiles() const;
- virtual QList<QUrl> dialogResult() const;
+ void setNameFilters(const QStringList &f) Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
+ QList<QUrl> dialogResult() const Q_DECL_OVERRIDE;
};
// Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo".
@@ -1537,8 +1537,8 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
public:
explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) :
QWindowsNativeFileDialogBase(data) {}
- virtual QList<QUrl> selectedFiles() const;
- virtual QList<QUrl> dialogResult() const;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
+ QList<QUrl> dialogResult() const Q_DECL_OVERRIDE;
private:
inline IFileOpenDialog *openFileDialog() const
@@ -1622,7 +1622,7 @@ public:
virtual QString selectedNameFilter() const Q_DECL_OVERRIDE;
private:
- virtual QWindowsNativeDialogBase *createNativeDialog();
+ QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE;
inline QWindowsNativeFileDialogBase *nativeFileDialog() const
{ return static_cast<QWindowsNativeFileDialogBase *>(nativeDialog()); }
@@ -1750,14 +1750,13 @@ public:
static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
- virtual void setWindowTitle(const QString &t) { m_title = t; }
- virtual void doExec(HWND owner = 0);
- virtual QPlatformDialogHelper::DialogCode result() const { return m_result; }
+ void setWindowTitle(const QString &t) Q_DECL_OVERRIDE { m_title = t; }
+ void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam);
public slots:
- virtual void close() {}
+ void close() Q_DECL_OVERRIDE {}
private:
typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW);
@@ -1993,19 +1992,19 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFile
{
public:
QWindowsXpFileDialogHelper() {}
- virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; }
- virtual bool defaultNameFilterDisables() const
+ bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const Q_DECL_OVERRIDE { return false; }
+ bool defaultNameFilterDisables() const Q_DECL_OVERRIDE
{ return true; }
- virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
- virtual QUrl directory() const Q_DECL_OVERRIDE;
- virtual void selectFile(const QUrl &url) Q_DECL_OVERRIDE;
- virtual QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- virtual void setFilter() Q_DECL_OVERRIDE {}
- virtual void selectNameFilter(const QString &) Q_DECL_OVERRIDE;
- virtual QString selectedNameFilter() const Q_DECL_OVERRIDE;
+ void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
+ QUrl directory() const Q_DECL_OVERRIDE;
+ void selectFile(const QUrl &url) Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
+ void setFilter() Q_DECL_OVERRIDE {}
+ void selectNameFilter(const QString &) Q_DECL_OVERRIDE;
+ QString selectedNameFilter() const Q_DECL_OVERRIDE;
private:
- virtual QWindowsNativeDialogBase *createNativeDialog();
+ QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE;
inline QWindowsXpNativeFileDialog *nativeFileDialog() const
{ return static_cast<QWindowsXpNativeFileDialog *>(nativeDialog()); }
@@ -2079,14 +2078,13 @@ public:
explicit QWindowsNativeColorDialog(const SharedPointerColor &color);
- virtual void setWindowTitle(const QString &) {}
- virtual QPlatformDialogHelper::DialogCode result() const { return m_code; }
+ void setWindowTitle(const QString &) Q_DECL_OVERRIDE {}
public slots:
- virtual void close() {}
+ void close() Q_DECL_OVERRIDE {}
private:
- virtual void doExec(HWND owner = 0);
+ void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
COLORREF m_customColors[CustomColorCount];
QPlatformDialogHelper::DialogCode m_code;
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 8c9882c65a..bde9a77e77 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -84,7 +84,7 @@ public:
void setPixmap(const QPixmap &p);
protected:
- void paintEvent(QPaintEvent *)
+ void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE
{
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 7a64fa987c..988b0012f7 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -49,12 +49,15 @@ QT_BEGIN_NAMESPACE
class QWindowsFontDatabaseFT : public QBasicFontDatabase
{
public:
- void populateFontDatabase();
+ void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
- QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
- QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize,
+ QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE;
- QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint,
+ QChar::Script script) const Q_DECL_OVERRIDE;
QString fontDir() const Q_DECL_OVERRIDE;
QFont defaultFont() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 0f7cfce4f1..75bff00326 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -90,7 +90,7 @@ public:
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
- QPainterPath *path, QTextItem::RenderFlags flags);
+ QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
HGDIOBJ selectDesignFont() const;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index c8417b655b..02b56fc40a 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -526,13 +526,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
int margin,
const QTransform &xform)
{
- glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform);
- // This needs to be kept in sync with alphaMapBoundingBox
- int width = (metrics.width + margin * 2).ceil().toInt() ;
- int height = (metrics.height + margin * 2).ceil().toInt();
-
UINT16 glyphIndex = t;
- FLOAT glyphAdvance = metrics.xoff.toReal();
+ FLOAT glyphAdvance = 0;
DWRITE_GLYPH_OFFSET glyphOffset;
glyphOffset.advanceOffset = 0;
@@ -548,12 +543,9 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
glyphRun.bidiLevel = 0;
glyphRun.glyphOffsets = &glyphOffset;
- QFixed x = margin - metrics.x.floor() + subPixelPosition;
- QFixed y = margin - metrics.y.floor();
-
DWRITE_MATRIX transform;
- transform.dx = x.toReal();
- transform.dy = y.toReal();
+ transform.dx = subPixelPosition.toReal();
+ transform.dy = 0;
transform.m11 = xform.m11();
transform.m12 = xform.m12();
transform.m21 = xform.m21();
@@ -577,46 +569,56 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
if (SUCCEEDED(hr)) {
RECT rect;
- rect.left = 0;
- rect.top = 0;
- rect.right = width;
- rect.bottom = height;
+ glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
- int size = width * height * 3;
- BYTE *alphaValues = new BYTE[size];
- memset(alphaValues, 0, size);
+ rect.left -= margin;
+ rect.top -= margin;
+ rect.right += margin;
+ rect.bottom += margin;
- hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
- &rect,
- alphaValues,
- size);
+ const int width = rect.right - rect.left;
+ const int height = rect.bottom - rect.top;
- if (SUCCEEDED(hr)) {
- QImage img(width, height, QImage::Format_RGB32);
- img.fill(0xffffffff);
+ const int size = width * height * 3;
+ if (size > 0) {
+ BYTE *alphaValues = new BYTE[size];
+ memset(alphaValues, 0, size);
- for (int y=0; y<height; ++y) {
- uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
- BYTE *src = alphaValues + width * 3 * y;
+ hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
+ &rect,
+ alphaValues,
+ size);
- for (int x=0; x<width; ++x) {
- dest[x] = *(src) << 16
- | *(src + 1) << 8
- | *(src + 2);
+ if (SUCCEEDED(hr)) {
+ QImage img(width, height, QImage::Format_RGB32);
+ img.fill(0xffffffff);
- src += 3;
+ for (int y=0; y<height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
+ BYTE *src = alphaValues + width * 3 * y;
+
+ for (int x=0; x<width; ++x) {
+ dest[x] = *(src) << 16
+ | *(src + 1) << 8
+ | *(src + 2);
+
+ src += 3;
+ }
}
- }
- delete[] alphaValues;
- glyphAnalysis->Release();
+ delete[] alphaValues;
+ glyphAnalysis->Release();
+
+ return img;
+ } else {
+ delete[] alphaValues;
+ glyphAnalysis->Release();
- return img;
+ qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
+ }
} else {
- delete[] alphaValues;
glyphAnalysis->Release();
-
- qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
+ qWarning("%s: Glyph has no bounds", __FUNCTION__);
}
} else {
@@ -730,16 +732,65 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
return QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString();
}
-glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
+glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph,
+ QFixed subPixelPosition,
+ const QTransform &matrix,
+ GlyphFormat format)
{
- Q_UNUSED(pos);
Q_UNUSED(format);
+ glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance
+
+ UINT16 glyphIndex = glyph;
+ FLOAT glyphAdvance = 0;
+
+ DWRITE_GLYPH_OFFSET glyphOffset;
+ glyphOffset.advanceOffset = 0;
+ glyphOffset.ascenderOffset = 0;
+
+ DWRITE_GLYPH_RUN glyphRun;
+ glyphRun.fontFace = m_directWriteFontFace;
+ glyphRun.fontEmSize = fontDef.pixelSize;
+ glyphRun.glyphCount = 1;
+ glyphRun.glyphIndices = &glyphIndex;
+ glyphRun.glyphAdvances = &glyphAdvance;
+ glyphRun.isSideways = false;
+ glyphRun.bidiLevel = 0;
+ glyphRun.glyphOffsets = &glyphOffset;
+
+ DWRITE_MATRIX transform;
+ transform.dx = subPixelPosition.toReal();
+ transform.dy = 0;
+ transform.m11 = matrix.m11();
+ transform.m12 = matrix.m12();
+ transform.m21 = matrix.m21();
+ transform.m22 = matrix.m22();
+
+ IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
+ HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
+ &glyphRun,
+ 1.0f,
+ &transform,
+ DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
+ DWRITE_MEASURING_MODE_NATURAL,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
- int margin = glyphMargin(QFontEngine::Format_A32);
- glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
- gm.width += margin * 2;
- gm.height += margin * 2;
- return gm;
+ if (SUCCEEDED(hr)) {
+ RECT rect;
+ glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->Release();
+
+ int margin = glyphMargin(QFontEngine::Format_A32);
+
+ return glyph_metrics_t(rect.left,
+ rect.top,
+ rect.right - rect.left + margin * 2,
+ rect.bottom - rect.top + margin * 2,
+ bbox.xoff, bbox.yoff);
+ } else {
+ return glyph_metrics_t();
+ }
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 99bdb2dd49..25709d8ee1 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -67,35 +67,37 @@ public:
void initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font);
- QFixed lineThickness() const;
- QFixed underlinePosition() const;
- bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
- QFixed emSquareSize() const;
+ QFixed lineThickness() const Q_DECL_OVERRIDE;
+ QFixed underlinePosition() const Q_DECL_OVERRIDE;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE;
+ QFixed emSquareSize() const Q_DECL_OVERRIDE;
glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
- void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
+ ShaperFlags flags) const Q_DECL_OVERRIDE;
+ void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE;
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
- QPainterPath *path, QTextItem::RenderFlags flags);
+ QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
- glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
- glyph_metrics_t boundingBox(glyph_t g);
- glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat);
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed,
+ const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE;
- QFixed ascent() const;
- QFixed descent() const;
- QFixed leading() const;
- QFixed xHeight() const;
- qreal maxCharWidth() const;
+ QFixed ascent() const Q_DECL_OVERRIDE;
+ QFixed descent() const Q_DECL_OVERRIDE;
+ QFixed leading() const Q_DECL_OVERRIDE;
+ QFixed xHeight() const Q_DECL_OVERRIDE;
+ qreal maxCharWidth() const Q_DECL_OVERRIDE;
- bool supportsSubPixelPositions() const;
+ bool supportsSubPixelPositions() const Q_DECL_OVERRIDE;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
- QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE;
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
+ QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE;
- QFontEngine *cloneWithSize(qreal pixelSize) const;
+ QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
const QSharedPointer<QWindowsFontEngineData> &fontEngineData() const { return m_fontEngineData; }
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 73c5f1d517..9658ef711d 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -66,12 +66,12 @@ public:
explicit QWindowsIntegration(const QStringList &paramList);
virtual ~QWindowsIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const;
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QOpenGLContext::OpenGLModuleType openGLModuleType();
+ QOpenGLContext::OpenGLModuleType openGLModuleType() Q_DECL_OVERRIDE;
static QWindowsStaticOpenGLContext *staticOpenGLContext();
#endif
QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
@@ -89,7 +89,7 @@ public:
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QStringList themeNames() const Q_DECL_OVERRIDE;
QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
- QPlatformServices *services() const;
+ QPlatformServices *services() const Q_DECL_OVERRIDE;
QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 8c6ff58aa1..a16397f169 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -903,14 +903,14 @@ public:
QWindowsMimeHtml();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+ QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
private:
int CF_HTML;
@@ -1035,14 +1035,14 @@ class QWindowsMimeImage : public QWindowsMime
public:
QWindowsMimeImage();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+ QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
private:
bool hasOriginalDIBV5(IDataObject *pDataObj) const;
UINT CF_PNG;
@@ -1189,14 +1189,14 @@ public:
QBuiltInMimes();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+ QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
private:
QMap<int, QString> outFormats;
@@ -1309,14 +1309,14 @@ public:
QLastResortMimes();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+ QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
private:
QMap<int, QString> formats;
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 15bb941a9d..45db934e47 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -57,9 +57,9 @@ public:
bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE;
- virtual const QPalette *palette(Palette type = SystemPalette) const
+ const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE
{ return m_palettes[type]; }
- virtual const QFont *font(Font type = SystemFont) const
+ const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE
{ return m_fonts[type]; }
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index a3f072b7a8..8497931b9a 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -177,7 +177,7 @@ public:
void raise() Q_DECL_OVERRIDE;
void lower() Q_DECL_OVERRIDE;
- void windowEvent(QEvent *event);
+ void windowEvent(QEvent *event) Q_DECL_OVERRIDE;
void propagateSizeHints() Q_DECL_OVERRIDE;
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp);
@@ -195,8 +195,8 @@ public:
bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
- void setFrameStrutEventsEnabled(bool enabled);
- bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
+ void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE;
+ bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); }
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
@@ -243,15 +243,15 @@ public:
void setEnabled(bool enabled);
bool isEnabled() const;
- void setWindowIcon(const QIcon &icon);
+ void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void *surface(void *nativeConfig, int *err);
void invalidateSurface() Q_DECL_OVERRIDE;
void aboutToMakeCurrent();
#ifndef Q_OS_WINCE
- void setAlertState(bool enabled);
- bool isAlertState() const { return testFlag(AlertState); }
+ void setAlertState(bool enabled) Q_DECL_OVERRIDE;
+ bool isAlertState() const Q_DECL_OVERRIDE { return testFlag(AlertState); }
void alertWindow(int durationMs = 0);
void stopAlertWindow();
#endif
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 71e92f33ca..2281bf56cc 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -59,10 +59,16 @@
#include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
-#ifdef Q_OS_WINPHONE
+
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
# include <windows.phone.ui.input.h>
+# if _MSC_VER >= 1900
+# include <windows.foundation.metadata.h>
+ using namespace ABI::Windows::Foundation::Metadata;
+# endif
#endif
+
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
@@ -73,13 +79,13 @@ using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::ApplicationModel::Core;
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
using namespace ABI::Windows::Phone::UI::Input;
#endif
typedef IEventHandler<IInspectable *> ResumeHandler;
typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
typedef IEventHandler<CameraEventArgs*> CameraButtonHandler;
#endif
@@ -88,7 +94,7 @@ QT_BEGIN_NAMESPACE
typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken);
@@ -105,11 +111,12 @@ public:
ComPtr<ICoreApplication> application;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
ComPtr<IHardwareButtonsStatics> hardwareButtons;
QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
ComPtr<IHardwareButtonsStatics2> cameraButtons;
QHash<HardwareButtons2CallbackRemover, EventRegistrationToken> cameraTokens;
+ boolean hasHardwareButtons;
bool cameraHalfPressed : 1;
bool cameraPressed : 1;
#endif
@@ -132,31 +139,48 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
&d->applicationTokens[&ICoreApplication::remove_Resuming]);
Q_ASSERT_SUCCEEDED(hr);
-#ifdef Q_OS_WINPHONE
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
- IID_PPV_ARGS(&d->hardwareButtons));
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
- &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
- Q_ASSERT_SUCCEEDED(hr);
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+#if _MSC_VER >= 1900
+ d->hasHardwareButtons = false;
+ ComPtr<IApiInformationStatics> apiInformationStatics;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(),
+ IID_PPV_ARGS(&apiInformationStatics));
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
- IID_PPV_ARGS(&d->cameraButtons));
- Q_ASSERT_SUCCEEDED(hr);
- if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) {
- hr = d->cameraButtons->add_CameraPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraPressed).Get(),
- &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]);
+ if (SUCCEEDED(hr)) {
+ const HStringReference valueRef(L"Windows.Phone.UI.Input.HardwareButtons");
+ hr = apiInformationStatics->IsTypePresent(valueRef.Get(), &d->hasHardwareButtons);
+ }
+#else
+ d->hasHardwareButtons = true;
+#endif // _MSC_VER >= 1900
+
+ if (d->hasHardwareButtons) {
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
+ IID_PPV_ARGS(&d->hardwareButtons));
Q_ASSERT_SUCCEEDED(hr);
- hr = d->cameraButtons->add_CameraHalfPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraHalfPressed).Get(),
- &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]);
+ hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
+ &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
Q_ASSERT_SUCCEEDED(hr);
- hr = d->cameraButtons->add_CameraReleased(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraReleased).Get(),
- &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]);
+
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
+ IID_PPV_ARGS(&d->cameraButtons));
Q_ASSERT_SUCCEEDED(hr);
+ if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) {
+ hr = d->cameraButtons->add_CameraPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraPressed).Get(),
+ &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->cameraButtons->add_CameraHalfPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraHalfPressed).Get(),
+ &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->cameraButtons->add_CameraReleased(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraReleased).Get(),
+ &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ d->cameraPressed = false;
+ d->cameraHalfPressed = false;
}
- d->cameraPressed = false;
- d->cameraHalfPressed = false;
-#endif // Q_OS_WINPHONE
+#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+
QEventDispatcherWinRT::runOnXamlThread([d]() {
d->mainScreen = new QWinRTScreen;
@@ -172,14 +196,17 @@ QWinRTIntegration::~QWinRTIntegration()
{
Q_D(QWinRTIntegration);
HRESULT hr;
-#ifdef Q_OS_WINPHONE
- for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
- hr = (d->hardwareButtons.Get()->*i.key())(i.value());
- Q_ASSERT_SUCCEEDED(hr);
- }
- for (QHash<HardwareButtons2CallbackRemover, EventRegistrationToken>::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) {
- hr = (d->cameraButtons.Get()->*i.key())(i.value());
- Q_ASSERT_SUCCEEDED(hr);
+
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+ if (d->hasHardwareButtons) {
+ for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
+ hr = (d->hardwareButtons.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ for (QHash<HardwareButtons2CallbackRemover, EventRegistrationToken>::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) {
+ hr = (d->cameraButtons.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
}
#endif
// Do not execute this on Windows Phone as the application is already
@@ -289,7 +316,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &name) cons
// System-level integration points
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
Q_D(QWinRTIntegration);
@@ -339,7 +366,7 @@ HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *)
d->cameraPressed = false;
return S_OK;
}
-#endif // Q_OS_WINPHONE
+#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
{
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
index 31a3ce7c1c..9bf5d27973 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.h
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -47,7 +47,7 @@ namespace ABI {
namespace Foundation {
struct IAsyncAction;
}
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
namespace Phone {
namespace UI {
namespace Input {
@@ -100,7 +100,7 @@ public:
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
private:
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
HRESULT onCameraPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *);
HRESULT onCameraHalfPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *);
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index eea7e6a2d4..ff624d9755 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -658,7 +658,13 @@ void QGLXContext::queryDummyContext()
oldSurface = oldContext->surface();
QScopedPointer<QSurface> surface;
- const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
+ Display *display = glXGetCurrentDisplay();
+ if (!display) {
+ // FIXME: Since Qt 5.6 we don't need to check whether primary screen is NULL
+ if (QScreen *screen = QGuiApplication::primaryScreen())
+ display = DISPLAY_FROM_XCB(static_cast<QXcbScreen *>(screen->handle()));
+ }
+ const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
if (glxvendor && !strcmp(glxvendor, "ATI")) {
QWindow *window = new QWindow;
window->resize(64, 64);
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index 38e996fdb4..3e963ccaa8 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -201,7 +201,12 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO
static bool glxPbufferUsable = true;
if (!vendorChecked) {
vendorChecked = true;
- const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
+ Display *display = glXGetCurrentDisplay();
+#ifdef XCB_USE_XLIB
+ if (!display)
+ display = static_cast<Display *>(m_connection->xlib_display());
+#endif
+ const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
if (glxvendor && !strcmp(glxvendor, "ATI"))
glxPbufferUsable = false;
}
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 212fc722c0..e3686ec010 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -73,6 +73,8 @@ public:
QSize size() const { return m_qimage.size(); }
+ bool hasAlpha() const { return m_hasAlpha; }
+
void put(xcb_window_t window, const QPoint &dst, const QRect &source);
void preparePaint(const QRegion &region);
@@ -90,6 +92,8 @@ private:
xcb_window_t m_gc_window;
QRegion m_dirty;
+
+ bool m_hasAlpha;
};
class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer
@@ -179,7 +183,8 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed";
}
- if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::IgnoresAlpha)
+ m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha;
+ if (!m_hasAlpha)
format = qt_alphaVersionForPainting(format);
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
@@ -330,7 +335,7 @@ void QXcbBackingStore::beginPaint(const QRegion &region)
m_paintRegion = region;
m_image->preparePaint(m_paintRegion);
- if (m_image->image()->hasAlphaChannel()) {
+ if (m_image->hasAlpha()) {
QPainter p(paintDevice());
p.setCompositionMode(QPainter::CompositionMode_Source);
const QVector<QRect> rects = m_paintRegion.rects();
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8b6d2fa3d3..e2bf6e8eb4 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -873,6 +873,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
// We do not set "pixel" delta if it is only measured in ticks.
if (scrollingDevice.verticalIncrement > 1)
rawDelta.setY(delta);
+ else if (scrollingDevice.verticalIncrement < -1)
+ rawDelta.setY(-delta);
}
}
if (scrollingDevice.orientations & Qt::Horizontal) {
@@ -883,6 +885,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
// We do not set "pixel" delta if it is only measured in ticks.
if (scrollingDevice.horizontalIncrement > 1)
rawDelta.setX(delta);
+ else if (scrollingDevice.horizontalIncrement < -1)
+ rawDelta.setX(-delta);
}
}
if (!angleDelta.isNull()) {
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 49fc4f1f10..a00c4cb9dc 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1901,6 +1901,17 @@ private:
bool m_pending;
};
+bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion)
+{
+ ExposeCompressor compressor(m_window, &exposeRegion);
+ xcb_generic_event_t *filter = 0;
+ do {
+ filter = connection()->checkEvent(compressor);
+ free(filter);
+ } while (filter);
+ return compressor.pending();
+}
+
bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result)
{
return QWindowSystemInterface::handleNativeEvent(window(),
@@ -1918,15 +1929,10 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
else
m_exposeRegion |= rect;
- ExposeCompressor compressor(m_window, &m_exposeRegion);
- xcb_generic_event_t *filter = 0;
- do {
- filter = connection()->checkEvent(compressor);
- free(filter);
- } while (filter);
+ bool pending = compressExposeEvent(m_exposeRegion);
// if count is non-zero there are more expose events pending
- if (event->count == 0 || !compressor.pending()) {
+ if (event->count == 0 || !pending) {
QWindowSystemInterface::handleExposeEvent(window(), m_exposeRegion);
m_exposeRegion = QRegion();
}
@@ -2013,10 +2019,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
- // The original geometry requested by setGeometry() might be different
- // from what we end up with after applying window constraints.
- QRect requestedGeometry = geometry();
-
const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen)
@@ -2037,15 +2039,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
// will make the comparison later.
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
- // For expose events we have no way of telling QGuiApplication to used the locally
- // cached version of the previous state, so we may in some situations end up with
- // an additional expose event.
- QRect previousGeometry = requestedGeometry != actualGeometry ?
- requestedGeometry : qt_window_private(window())->geometry;
-
- if (m_mapped && actualGeometry.size() != previousGeometry.size())
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
-
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@@ -2112,7 +2105,9 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
if (m_deferredActivation)
requestActivateWindow();
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ QRegion exposeRegion = QRect(QPoint(), geometry().size());
+ compressExposeEvent(exposeRegion);
+ QWindowSystemInterface::handleExposeEvent(window(), exposeRegion);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 9d08103347..0efd78452c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -208,6 +208,8 @@ protected:
void doFocusIn();
void doFocusOut();
+ bool compressExposeEvent(QRegion &exposeRegion);
+
void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);