Implement native message box for WinRT

Added a basic theme class, which creates accessors for the
QPlatformMessageDialogHelper. This handles creation of the
native dialog, but also spawning an event loop around it.

There are some limitations shared with the Android implementation.
First you cannot create custom labelled buttons and also selecting
the default button is not possible. This will be added at a later
point.

Note that Windows Phone is not supported.

Change-Id: I2dec83dcded7919835a6dcdf8dc2a56282024a7e
Reviewed-by: Andrew Knight <andrew.knight@digia.com>
This commit is contained in:
Maurice Kalinowski 2014-02-11 23:54:19 +02:00 committed by The Qt Project
parent db98d65415
commit ff23fb6cf7
7 changed files with 447 additions and 0 deletions

View File

@ -48,6 +48,7 @@
#include "qwinrtservices.h"
#include "qwinrteglcontext.h"
#include "qwinrtfontdatabase.h"
#include "qwinrtplatformtheme.h"
#include <QtGui/QOpenGLContext>
@ -191,4 +192,17 @@ Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
return m_screen->keyboardModifiers();
}
QStringList QWinRTIntegration::themeNames() const
{
return QStringList(QLatin1String("winrt"));
}
QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &
name) const
{
if (name == QLatin1String("winrt"))
return new QWinRTPlatformTheme();
return 0;
}
QT_END_NAMESPACE

View File

@ -74,6 +74,8 @@ public:
QPlatformServices *services() const;
Qt::KeyboardModifiers queryKeyboardModifiers() const;
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
private:
bool m_success;
QWinRTScreen *m_screen;

View File

@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwinrtplatformmessagedialoghelper.h"
#include <QtGui/QGuiApplication>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
#include <asyncinfo.h>
#include <windows.ui.popups.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
#include <wrl.h>
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::UI::Popups;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
QT_BEGIN_NAMESPACE
struct QWinRTPlatformMessageDialogInfo
{
ComPtr<IAsyncInfo> info;
};
QWinRTPlatformMessageDialogHelper::QWinRTPlatformMessageDialogHelper() :
QPlatformMessageDialogHelper(),
m_info(new QWinRTPlatformMessageDialogInfo),
m_shown(false)
{
}
QWinRTPlatformMessageDialogHelper::~QWinRTPlatformMessageDialogHelper()
{
if (m_shown)
hide();
delete m_info;
}
void QWinRTPlatformMessageDialogHelper::exec()
{
if (!m_shown)
show(Qt::Dialog, Qt::ApplicationModal, 0);
m_loop.exec();
}
bool QWinRTPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
{
Q_UNUSED(windowFlags)
Q_UNUSED(windowModality)
Q_UNUSED(parent)
QSharedPointer<QMessageDialogOptions> options = this->options();
const QString informativeText = options->informativeText();
const QString title = options->windowTitle();
const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);
ComPtr<IMessageDialogFactory> dialogFactory;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_MessageDialog).Get(), &dialogFactory)))
return false;
ComPtr<IUICommandFactory> commandFactory;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_UICommand).Get(), &commandFactory)))
return false;
HString nativeText;
nativeText.Set(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
ComPtr<IMessageDialog> dialog;
if (!title.isEmpty()) {
HString nativeTitle;
nativeTitle.Set(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
if (FAILED(dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog)))
return false;
} else {
if (FAILED(dialogFactory->Create(nativeText.Get(), &dialog)))
return false;
}
// Add Buttons
ComPtr<IVector<IUICommand*> > dialogCommands;
if (FAILED(dialog->get_Commands(&dialogCommands)))
return false;
// If no button is specified we need to create one to get close notification
int buttons = options->standardButtons();
if (buttons == 0)
buttons = QMessageDialogOptions::Ok;
for (int i = QMessageDialogOptions::FirstButton; i < QMessageDialogOptions::LastButton; i<<=1) {
if (buttons & i) {
// Add native command
const QString label = QGuiApplicationPrivate::platformTheme()->standardButtonText(i);
HString hLabel;
hLabel.Set(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
ABI::Windows::UI::Popups::IUICommand *command;
if (FAILED(commandFactory->CreateWithHandler(hLabel.Get(),
Callback<IUICommandInvokedHandler>(this, &QWinRTPlatformMessageDialogHelper::onInvoked).Get(),
&command)))
return false;
dialogCommands->Append(command);
}
}
ComPtr<IAsyncOperation<IUICommand*> > op;
if (FAILED(dialog->ShowAsync(&op)))
return false;
m_shown = true;
if (FAILED(op.As(&m_info->info))) {
m_shown = false;
// The dialog is shown already, so we cannot return false
qWarning("Failed to acquire AsyncInfo for MessageDialog");
}
return true;
}
void QWinRTPlatformMessageDialogHelper::hide()
{
if (!m_shown)
return;
m_info->info->Cancel();
m_shown = false;
}
HRESULT QWinRTPlatformMessageDialogHelper::onInvoked(ABI::Windows::UI::Popups::IUICommand *command)
{
HSTRING hLabel;
UINT32 labelLength;
command->get_Label(&hLabel);
QString label = QString::fromWCharArray(::WindowsGetStringRawBuffer(hLabel, &labelLength));
int buttonId = -1;
for (int i = QMessageDialogOptions::FirstButton; i < QMessageDialogOptions::LastButton; i<<=1) {
if ( options()->standardButtons() & i ) {
if (QGuiApplicationPrivate::platformTheme()->standardButtonText(i) == label) {
buttonId = i;
break;
}
}
}
if (m_loop.isRunning())
m_loop.exit();
m_shown = false;
if (buttonId < 0) {
emit reject();
return S_OK;
}
QMessageDialogOptions::StandardButton standardButton = static_cast<QMessageDialogOptions::StandardButton>(buttonId);
QMessageDialogOptions::ButtonRole role = QMessageDialogOptions::buttonRole(standardButton);
emit clicked(standardButton, role);
return S_OK;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINRTPLATFORMMESSAGEDIALOGHELPER_H
#define QWINRTPLATFORMMESSAGEDIALOGHELPER_H
#include <qpa/qplatformdialoghelper.h>
#include <QtCore/QEventLoop>
#include <QtCore/qt_windows.h>
namespace ABI {
namespace Windows {
namespace UI {
namespace Popups {
struct IUICommand;
}
}
}
}
QT_BEGIN_NAMESPACE
struct QWinRTPlatformMessageDialogInfo;
class QWinRTPlatformMessageDialogHelper : public QPlatformMessageDialogHelper
{
Q_OBJECT
public:
explicit QWinRTPlatformMessageDialogHelper();
~QWinRTPlatformMessageDialogHelper();
void exec();
bool show(Qt::WindowFlags windowFlags,
Qt::WindowModality windowModality,
QWindow *parent);
void hide();
HRESULT onInvoked(ABI::Windows::UI::Popups::IUICommand *command);
private:
QWinRTPlatformMessageDialogInfo *m_info;
QEventLoop m_loop;
bool m_shown;
};
QT_END_NAMESPACE
#endif // QWINRTPLATFORMMESSAGEDIALOGHELPER_H

View File

@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwinrtplatformtheme.h"
#include "qwinrtplatformmessagedialoghelper.h"
QT_BEGIN_NAMESPACE
QWinRTPlatformTheme::QWinRTPlatformTheme()
{
}
bool QWinRTPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
{
#ifndef Q_OS_WINPHONE
if (type == QPlatformTheme::MessageDialog)
return true;
#endif // Q_OS_WINPHONE
return false;
}
QPlatformDialogHelper *QWinRTPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const
{
#ifndef Q_OS_WINPHONE
switch (type) {
case QPlatformTheme::MessageDialog:
return new QWinRTPlatformMessageDialogHelper();
default:
return QPlatformTheme::createPlatformDialogHelper(type);
}
#else
return QPlatformTheme::createPlatformDialogHelper(type);
#endif // Q_OS_WINPHONE
}
QT_END_NAMESPACE

View File

@ -0,0 +1,60 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINRTPLATFORMTHEME_H
#define QWINRTPLATFORMTHEME_H
#include <qpa/qplatformtheme.h>
QT_BEGIN_NAMESPACE
class QWinRTPlatformTheme : public QPlatformTheme
{
public:
QWinRTPlatformTheme();
bool usePlatformNativeDialog(DialogType type) const;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
};
QT_END_NAMESPACE
#endif // QWINRTPLATFORMTHEME_H

View File

@ -20,6 +20,8 @@ SOURCES = \
qwinrtfontdatabase.cpp \
qwinrtinputcontext.cpp \
qwinrtintegration.cpp \
qwinrtplatformmessagedialoghelper.cpp \
qwinrtplatformtheme.cpp \
qwinrtscreen.cpp \
qwinrtservices.cpp \
qwinrtwindow.cpp
@ -32,6 +34,8 @@ HEADERS = \
qwinrtfontdatabase.h \
qwinrtinputcontext.h \
qwinrtintegration.h \
qwinrtplatformmessagedialoghelper.h \
qwinrtplatformtheme.h \
qwinrtscreen.h \
qwinrtservices.h \
qwinrtwindow.h
@ -51,5 +55,10 @@ fxc_blitvs.variable_out = HEADERS
fxc_blitvs.CONFIG += target_predeps
QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs
winphone {
SOURCES -= qwinrtplatformmessagedialoghelper.cpp
HEADERS -= qwinrtplatformmessagedialoghelper.h
}
OTHER_FILES += winrt.json \
blit.hlsl