diff options
author | Andrew Knight <andrew.knight@intopalo.com> | 2015-08-05 08:15:06 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@intopalo.com> | 2015-08-13 16:12:18 +0000 |
commit | ebc2b963aa9e8ce2e983ef08c9b503ccc1702fdb (patch) | |
tree | 30ad3f1000f92b8555fb4e6d10f2b24786e93137 /src/winmain | |
parent | 130083a7fc07fb8f98e4199832b6c20685a1ea70 (diff) |
winrtmain: Start in XAML mode
This allows the platform plugin to start using XAML interfaces in the
windowing system.
Change-Id: Ifcd29b8b8d83b138af69786dfc6a1adec21be37e
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
Diffstat (limited to 'src/winmain')
-rw-r--r-- | src/winmain/qtmain_winrt.cpp | 263 |
1 files changed, 148 insertions, 115 deletions
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index 141e3ed135..d9f8c8f991 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -49,38 +49,44 @@ entry point within the newly created GUI thread. */ +#if _MSC_VER < 1900 #include <new.h> typedef struct { int newmode; } _startupinfo; +#endif // _MSC_VER < 1900 extern "C" { +#if _MSC_VER < 1900 int __getmainargs(int *argc, char ***argv, char ***env, int expandWildcards, _startupinfo *info); +#endif int main(int, char **); } #include <qbytearray.h> #include <qstring.h> -#include <qlist.h> -#include <qvector.h> #include <qdir.h> #include <qstandardpaths.h> +#include <qfunctions_winrt.h> #include <wrl.h> #include <Windows.ApplicationModel.core.h> +#include <windows.ui.xaml.h> +#include <windows.ui.xaml.controls.h> using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::Activation; +using namespace ABI::Windows::ApplicationModel::Core; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; #define qHString(x) Wrappers::HString::MakeReference(x).Get() #define CoreApplicationClass RuntimeClass_Windows_ApplicationModel_Core_CoreApplication -typedef ITypedEventHandler<Core::CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler; - -static int g_mainExitCode; +typedef ITypedEventHandler<CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler; static QtMessageHandler defaultMessageHandler; static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) @@ -103,53 +109,112 @@ static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, defaultMessageHandler(type, context, message); } -class AppContainer : public Microsoft::WRL::RuntimeClass<Core::IFrameworkView> +class AppContainer : public RuntimeClass<Xaml::IApplicationOverrides> { public: - AppContainer(int argc, char *argv[]) : m_argc(argc), m_deleteArgv0(false) + AppContainer() { - m_argv.reserve(argc); - for (int i = 0; i < argc; ++i) { - // Workaround for empty argv[0] which occurs when WMAppManifest's ImageParams is used - // The second argument is taken to be the executable - if (i == 0 && argc >= 2 && !qstrlen(argv[0])) { - const QByteArray argv0 = QDir::current() - .absoluteFilePath(QString::fromLatin1(argv[1])).toUtf8(); - m_argv.append(qstrdup(argv0.constData())); - m_argc -= 1; - m_deleteArgv0 = true; - ++i; - continue; - } - m_argv.append(argv[i]); - } + ComPtr<Xaml::IApplicationFactory> applicationFactory; + HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(), + IID_PPV_ARGS(&applicationFactory)); + Q_ASSERT_SUCCEEDED(hr); + + hr = applicationFactory->CreateInstance(this, &base, &core); + RETURN_VOID_IF_FAILED("Failed to create application container instance"); } ~AppContainer() { - if (m_deleteArgv0) - delete[] m_argv[0]; - for (int i = m_argc; i < m_argv.size(); ++i) - delete[] m_argv[i]; } - // IFrameworkView Methods - HRESULT __stdcall Initialize(Core::ICoreApplicationView *view) + int exec(int argc, char **argv) { - view->add_Activated(Callback<ActivatedHandler>(this, &AppContainer::onActivated).Get(), - &m_activationToken); - return S_OK; + args.reserve(argc); + for (int i = 0; i < argc; ++i) + args.append(argv[i]); + + mainThread = CreateThread(NULL, 0, [](void *param) -> DWORD { + AppContainer *app = reinterpret_cast<AppContainer *>(param); + int argc = app->args.count(); + char **argv = app->args.data(); + return main(argc, argv); + }, this, CREATE_SUSPENDED, nullptr); + + HRESULT hr; + ComPtr<Xaml::IApplicationStatics> appStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(), + IID_PPV_ARGS(&appStatics)); + Q_ASSERT_SUCCEEDED(hr); + hr = appStatics->Start(Callback<Xaml::IApplicationInitializationCallback>([](Xaml::IApplicationInitializationCallbackParams *) { + return S_OK; + }).Get()); + Q_ASSERT_SUCCEEDED(hr); + + DWORD exitCode; + GetExitCodeThread(mainThread, &exitCode); + return exitCode; + } + +private: + HRESULT __stdcall OnActivated(IActivatedEventArgs *args) Q_DECL_OVERRIDE + { + return base->OnActivated(args); } - HRESULT __stdcall SetWindow(ABI::Windows::UI::Core::ICoreWindow *) { return S_OK; } - HRESULT __stdcall Load(HSTRING) { return S_OK; } - HRESULT __stdcall Run() + + HRESULT __stdcall OnLaunched(ILaunchActivatedEventArgs *launchArgs) Q_DECL_OVERRIDE { +#if _MSC_VER >= 1900 + commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8(); +#endif + HString launchCommandLine; + launchArgs->get_Arguments(launchCommandLine.GetAddressOf()); + if (launchCommandLine.IsValid()) { + quint32 launchCommandLineLength; + const wchar_t *launchCommandLineBuffer = launchCommandLine.GetRawBuffer(&launchCommandLineLength); + if (!commandLine.isEmpty() && launchCommandLineLength) + commandLine += ' '; + if (launchCommandLineLength) + commandLine += QString::fromWCharArray(launchCommandLineBuffer, launchCommandLineLength).toUtf8(); + } + if (!commandLine.isEmpty()) + args.append(commandLine.data()); + + bool quote = false; + bool escape = false; + for (int i = 0; i < commandLine.size(); ++i) { + switch (commandLine.at(i)) { + case '\\': + escape = true; + break; + case '"': + if (escape) { + escape = false; + break; + } + quote = !quote; + commandLine[i] = '\0'; + break; + case ' ': + if (quote) + break; + commandLine[i] = '\0'; + if (args.last()[0] != '\0') + args.append(commandLine.data() + i + 1); + // fall through + default: + if (args.last()[0] == '\0') + args.last() = commandLine.data() + i; + escape = false; // only quotes are escaped + break; + } + } + bool develMode = false; bool debugWait = false; - foreach (const QByteArray &arg, m_argv) { - if (arg == "-qdevel") + foreach (const char *arg, args) { + if (strcmp(arg, "-qdevel") == 0) develMode = true; - if (arg == "-qdebug") + if (strcmp(arg, "-qdebug") == 0) debugWait = true; } if (develMode) { @@ -173,98 +238,70 @@ public: while (!IsDebuggerPresent()) WaitForSingleObjectEx(GetCurrentThread(), 1, true); } - g_mainExitCode = main(m_argv.count(), m_argv.data()); + + ResumeThread(mainThread); return S_OK; } - HRESULT __stdcall Uninitialize() { return S_OK; } -private: - // Activation handler - HRESULT onActivated(Core::ICoreApplicationView *, Activation::IActivatedEventArgs *args) + HRESULT __stdcall OnFileActivated(IFileActivatedEventArgs *args) Q_DECL_OVERRIDE { - Activation::ILaunchActivatedEventArgs *launchArgs; - if (SUCCEEDED(args->QueryInterface(&launchArgs))) { - for (int i = m_argc; i < m_argv.size(); ++i) - delete[] m_argv[i]; - m_argv.resize(m_argc); - HString arguments; - launchArgs->get_Arguments(arguments.GetAddressOf()); - if (arguments.IsValid()) { - foreach (const QByteArray &arg, QString::fromWCharArray( - arguments.GetRawBuffer(nullptr)).toLocal8Bit().split(' ')) { - m_argv.append(qstrdup(arg.constData())); - } - } - } + Q_UNUSED(args); return S_OK; } - int m_argc; - QVector<char *> m_argv; - bool m_deleteArgv0; - EventRegistrationToken m_activationToken; -}; + HRESULT __stdcall OnSearchActivated(ISearchActivatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } -class AppViewSource : public Microsoft::WRL::RuntimeClass<Core::IFrameworkViewSource> -{ -public: - AppViewSource(int argc, char **argv) : m_argc(argc), m_argv(argv) { } - HRESULT __stdcall CreateView(Core::IFrameworkView **frameworkView) + HRESULT __stdcall OnShareTargetActivated(IShareTargetActivatedEventArgs *args) Q_DECL_OVERRIDE { - return (*frameworkView = Make<AppContainer>(m_argc, m_argv).Detach()) ? S_OK : E_OUTOFMEMORY; + Q_UNUSED(args); + return S_OK; } -private: - int m_argc; - char **m_argv; + + HRESULT __stdcall OnFileOpenPickerActivated(IFileOpenPickerActivatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } + + HRESULT __stdcall OnFileSavePickerActivated(IFileSavePickerActivatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } + + HRESULT __stdcall OnCachedFileUpdaterActivated(ICachedFileUpdaterActivatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } + + HRESULT __stdcall OnWindowCreated(Xaml::IWindowCreatedEventArgs *args) Q_DECL_OVERRIDE + { + Q_UNUSED(args); + return S_OK; + } + + ComPtr<Xaml::IApplicationOverrides> base; + ComPtr<Xaml::IApplication> core; + QByteArray commandLine; + QVarLengthArray<char *> args; + HANDLE mainThread; }; // Main entry point for Appx containers int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { -#if _MSC_VER < 1900 int argc = 0; - char **argv, **env; + char **argv = 0, **env = 0; +#if _MSC_VER < 1900 _startupinfo info = { _query_new_mode() }; if (int init = __getmainargs(&argc, &argv, &env, false, &info)) return init; -#else - QByteArray commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8(); - QVarLengthArray<char *> args; - args.append(commandLine.data()); - bool quote = false; - bool escape = false; - for (int i = 0; i < commandLine.size(); ++i) { - switch (commandLine.at(i)) { - case '\\': - escape = true; - break; - case '"': - if (escape) { - escape = false; - break; - } - quote = !quote; - commandLine[i] = '\0'; - break; - case ' ': - if (quote) - break; - commandLine[i] = '\0'; - if (args.last()[0] != '\0') - args.append(commandLine.data() + i + 1); - // fall through - default: - if (args.last()[0] == '\0') - args.last() = commandLine.data() + i; - escape = false; // only quotes are escaped - break; - } - } - int argc = args.size(); - char **argv = args.data(); - char **env = Q_NULLPTR; #endif // _MSC_VER >= 1900 - for (int i = 0; env && env[i]; ++i) { QByteArray var(env[i]); int split = var.indexOf('='); @@ -275,10 +312,6 @@ int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) if (FAILED(RoInitialize(RO_INIT_MULTITHREADED))) return 1; - Core::ICoreApplication *appFactory; - if (FAILED(RoGetActivationFactory(qHString(CoreApplicationClass), IID_PPV_ARGS(&appFactory)))) - return 2; - - appFactory->Run(Make<AppViewSource>(argc, argv).Get()); - return g_mainExitCode; + ComPtr<AppContainer> app = Make<AppContainer>(); + return app->exec(argc, argv); } |