From ebc2b963aa9e8ce2e983ef08c9b503ccc1702fdb Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 5 Aug 2015 08:15:06 +0300 Subject: 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 --- src/winmain/qtmain_winrt.cpp | 263 ++++++++++++++++++++++++------------------- 1 file 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 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 #include -#include -#include #include #include +#include #include #include +#include +#include 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 ActivatedHandler; - -static int g_mainExitCode; +typedef ITypedEventHandler 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 +class AppContainer : public RuntimeClass { 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 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(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(param); + int argc = app->args.count(); + char **argv = app->args.data(); + return main(argc, argv); + }, this, CREATE_SUSPENDED, nullptr); + + HRESULT hr; + ComPtr appStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(), + IID_PPV_ARGS(&appStatics)); + Q_ASSERT_SUCCEEDED(hr); + hr = appStatics->Start(Callback([](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 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 -{ -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(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 base; + ComPtr core; + QByteArray commandLine; + QVarLengthArray 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 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(argc, argv).Get()); - return g_mainExitCode; + ComPtr app = Make(); + return app->exec(argc, argv); } -- cgit v1.2.3