Auto merge of #24534 - ferjm:uwp.cli.args, r=paulrouget

Launch UWP app from command line

- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors

This PR makes it possible to launch the UWP app from the command line by executing (on any path) the `Servo` command. It requires building and launching Servo once on VS, so the command alias is properly registered.

It also allows passing command line arguments. So we can do for example `Servo --pref dom.webxr.enabled`.

Debugging is also possible when launching the app from the command line. It requires setting the `Launch Application` option (right click on `ServoApp (Universal Windows`) on the Solution Explorer view -> Properties ->  Configuration Properties -> Debugging) to `No`.
This commit is contained in:
bors-servo 2019-10-25 10:02:32 -04:00 committed by GitHub
commit 9117e979b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 57 additions and 26 deletions

View file

@ -31,8 +31,9 @@ App::App() {
#endif #endif
} }
void App::OnLaunched(LaunchActivatedEventArgs const &e) { void App::createRootFrame(
Frame rootFrame{nullptr}; Frame &rootFrame, bool prelaunchActivated,
winrt::Windows::Foundation::IInspectable const &args) {
auto content = Window::Current().Content(); auto content = Window::Current().Content();
if (content) { if (content) {
rootFrame = content.try_as<Frame>(); rootFrame = content.try_as<Frame>();
@ -43,26 +44,42 @@ void App::OnLaunched(LaunchActivatedEventArgs const &e) {
rootFrame.NavigationFailed({this, &App::OnNavigationFailed}); rootFrame.NavigationFailed({this, &App::OnNavigationFailed});
if (e.PrelaunchActivated() == false) { if (prelaunchActivated == false) {
if (rootFrame.Content() == nullptr) { if (rootFrame.Content() == nullptr) {
rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), args);
box_value(e.Arguments()));
} }
Window::Current().Content(rootFrame); Window::Current().Content(rootFrame);
Window::Current().Activate(); Window::Current().Activate();
} }
} else { } else {
if (e.PrelaunchActivated() == false) { if (prelaunchActivated == false) {
if (rootFrame.Content() == nullptr) { if (rootFrame.Content() == nullptr) {
rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), args);
box_value(e.Arguments()));
} }
Window::Current().Activate(); Window::Current().Activate();
} }
} }
} }
void App::OnLaunched(LaunchActivatedEventArgs const &e) {
Frame rootFrame{nullptr};
this->createRootFrame(rootFrame, e.PrelaunchActivated(),
box_value(e.Arguments()));
}
void App::OnActivated(IActivatedEventArgs const &args) { void App::OnActivated(IActivatedEventArgs const &args) {
if (args.Kind() == Windows::ApplicationModel::Activation::ActivationKind::
CommandLineLaunch) {
auto cmdLineArgs{args.as<Windows::ApplicationModel::Activation::
CommandLineActivatedEventArgs>()};
auto cmdLineStr = cmdLineArgs.Operation().Arguments();
Frame rootFrame{nullptr};
this->createRootFrame(rootFrame, false, nullptr);
auto page = rootFrame.Content().try_as<BrowserPage>();
page->SetArgs(cmdLineStr);
return;
}
if (args.Kind() == if (args.Kind() ==
Windows::ApplicationModel::Activation::ActivationKind::Protocol) { Windows::ApplicationModel::Activation::ActivationKind::Protocol) {
auto protocolActivatedEventArgs{args.as< auto protocolActivatedEventArgs{args.as<
@ -73,10 +90,7 @@ void App::OnActivated(IActivatedEventArgs const &args) {
auto content = Window::Current().Content(); auto content = Window::Current().Content();
bool isRunning = content != nullptr; bool isRunning = content != nullptr;
if (!isRunning) { if (!isRunning) {
rootFrame = Frame(); this->createRootFrame(rootFrame, false, nullptr);
rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>());
Window::Current().Content(rootFrame);
Window::Current().Activate();
} else { } else {
rootFrame = content.try_as<Frame>(); rootFrame = content.try_as<Frame>();
} }

View file

@ -9,10 +9,12 @@ namespace winrt::ServoApp::implementation {
struct App : AppT<App> { struct App : AppT<App> {
App(); App();
void createRootFrame(winrt::Windows::UI::Xaml::Controls::Frame &, bool,
winrt::Windows::Foundation::IInspectable const &);
void OnLaunched( void OnLaunched(
Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &); Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &);
void App::OnActivated( void App::OnActivated(
Windows::ApplicationModel::Activation::IActivatedEventArgs const &args); Windows::ApplicationModel::Activation::IActivatedEventArgs const &);
void OnSuspending(IInspectable const &, void OnSuspending(IInspectable const &,
Windows::ApplicationModel::SuspendingEventArgs const &); Windows::ApplicationModel::SuspendingEventArgs const &);
void OnNavigationFailed( void OnNavigationFailed(

View file

@ -67,6 +67,8 @@ void BrowserPage::SetTransientMode(bool transient) {
: Visibility::Visible); : Visibility::Visible);
} }
void BrowserPage::SetArgs(hstring args) { servoControl().SetArgs(args); }
void BrowserPage::Shutdown() { servoControl().Shutdown(); } void BrowserPage::Shutdown() { servoControl().Shutdown(); }
/**** USER INTERACTIONS WITH UI ****/ /**** USER INTERACTIONS WITH UI ****/

View file

@ -29,6 +29,7 @@ public:
void Shutdown(); void Shutdown();
void LoadServoURI(Windows::Foundation::Uri uri); void LoadServoURI(Windows::Foundation::Uri uri);
void SetTransientMode(bool); void SetTransientMode(bool);
void SetArgs(hstring);
private: private:
void BindServoEvents(); void BindServoEvents();

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp"> <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" IgnorableNamespaces="uap mp uap5">
<Identity Name="1d265729-8836-4bd3-9992-4cb111d1068b" Publisher="CN=Allizom" Version="1.0.0.0" /> <Identity Name="1d265729-8836-4bd3-9992-4cb111d1068b" Publisher="CN=Allizom" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="1d265729-8836-4bd3-9992-4cb111d1068b" PhonePublisherId="00000000-0000-0000-0000-000000000000" /> <mp:PhoneIdentity PhoneProductId="1d265729-8836-4bd3-9992-4cb111d1068b" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties> <Properties>
@ -32,6 +32,14 @@
<uap:DisplayName>Firefox Reality URL</uap:DisplayName> <uap:DisplayName>Firefox Reality URL</uap:DisplayName>
</uap:Protocol> </uap:Protocol>
</uap:Extension> </uap:Extension>
<uap5:Extension
Category="windows.appExecutionAlias"
Executable="ServoApp.exe"
EntryPoint="ServoApp.App">
<uap5:AppExecutionAlias>
<uap5:ExecutionAlias Alias="Servo.exe" />
</uap5:AppExecutionAlias>
</uap5:Extension>
</Extensions> </Extensions>
</Application> </Application>
</Applications> </Applications>

View file

@ -56,12 +56,13 @@ const char* get_clipboard_contents() {
return nullptr; return nullptr;
} }
Servo::Servo(hstring url, GLsizei width, GLsizei height, float dpi, Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height, float dpi,
ServoDelegate &aDelegate) ServoDelegate &aDelegate)
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) { : mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
capi::CInitOptions o; capi::CInitOptions o;
o.args = "--pref dom.webxr.enabled"; hstring defaultPrefs = L" --pref dom.webxr.enabled";
o.args = *hstring2char(args + defaultPrefs);
o.url = *hstring2char(url); o.url = *hstring2char(url);
o.width = mWindowWidth; o.width = mWindowWidth;
o.height = mWindowHeight; o.height = mWindowHeight;

View file

@ -43,7 +43,7 @@ protected:
class Servo { class Servo {
public: public:
Servo(hstring, GLsizei, GLsizei, float, ServoDelegate &); Servo(hstring, hstring, GLsizei, GLsizei, float, ServoDelegate &);
~Servo(); ~Servo();
ServoDelegate &Delegate() { return mDelegate; } ServoDelegate &Delegate() { return mDelegate; }

View file

@ -40,20 +40,19 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
std::bind(&ServoControl::OnSurfaceClicked, this, _1, _2)); std::bind(&ServoControl::OnSurfaceClicked, this, _1, _2));
panel.ManipulationStarted( panel.ManipulationStarted(
[=](IInspectable const &, [=](IInspectable const &,
Input::ManipulationStartedRoutedEventArgs const &e) { Input::ManipulationStartedRoutedEventArgs const &e) {
mOnCaptureGesturesStartedEvent(); mOnCaptureGesturesStartedEvent();
e.Handled(true); e.Handled(true);
}); });
panel.ManipulationCompleted( panel.ManipulationCompleted(
[=](IInspectable const &, [=](IInspectable const &,
Input::ManipulationCompletedRoutedEventArgs const &e) { Input::ManipulationCompletedRoutedEventArgs const &e) {
mOnCaptureGesturesEndedEvent(); mOnCaptureGesturesEndedEvent();
e.Handled(true); e.Handled(true);
}); });
panel.ManipulationDelta( panel.ManipulationDelta(
std::bind(&ServoControl::OnSurfaceManipulationDelta, this, _1, _2)); std::bind(&ServoControl::OnSurfaceManipulationDelta, this, _1, _2));
Panel().SizeChanged( Panel().SizeChanged(std::bind(&ServoControl::OnSurfaceResized, this, _1, _2));
std::bind(&ServoControl::OnSurfaceResized, this, _1, _2));
InitializeConditionVariable(&mGLCondVar); InitializeConditionVariable(&mGLCondVar);
InitializeCriticalSection(&mGLLock); InitializeCriticalSection(&mGLLock);
CreateRenderSurface(); CreateRenderSurface();
@ -166,7 +165,8 @@ void ServoControl::Loop() {
if (mServo == nullptr) { if (mServo == nullptr) {
log("Entering loop"); log("Entering loop");
ServoDelegate *sd = static_cast<ServoDelegate *>(this); ServoDelegate *sd = static_cast<ServoDelegate *>(this);
mServo = std::make_unique<Servo>(mInitialURL, panelWidth, panelHeight, mDPI, *sd); mServo = std::make_unique<Servo>(mInitialURL, mArgs, panelWidth, panelHeight, mDPI,
*sd);
} else { } else {
// FIXME: this will fail since create_task didn't pick the thread // FIXME: this will fail since create_task didn't pick the thread
// where Servo was running initially. // where Servo was running initially.
@ -273,9 +273,7 @@ void ServoControl::WakeUp() {
bool ServoControl::OnServoAllowNavigation(hstring uri) { bool ServoControl::OnServoAllowNavigation(hstring uri) {
if (mTransient) { if (mTransient) {
RunOnUIThread([=] { RunOnUIThread([=] { Launcher::LaunchUriAsync(Uri{uri}); });
Launcher::LaunchUriAsync(Uri{uri});
});
} }
return !mTransient; return !mTransient;
} }
@ -288,7 +286,8 @@ void ServoControl::OnServoAnimatingChanged(bool animating) {
} }
void ServoControl::OnServoIMEStateChanged(bool aShow) { void ServoControl::OnServoIMEStateChanged(bool aShow) {
// FIXME: https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange // FIXME:
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange
} }
template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) { template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) {

View file

@ -72,6 +72,8 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
void SetTransientMode(bool transient) { mTransient = transient; } void SetTransientMode(bool transient) { mTransient = transient; }
void SetArgs(hstring args) { mArgs = args; }
virtual void WakeUp(); virtual void WakeUp();
virtual void OnServoLoadStarted(); virtual void OnServoLoadStarted();
virtual void OnServoLoadEnded(); virtual void OnServoLoadEnded();
@ -139,6 +141,7 @@ private:
CRITICAL_SECTION mGLLock; CRITICAL_SECTION mGLLock;
CONDITION_VARIABLE mGLCondVar; CONDITION_VARIABLE mGLCondVar;
std::unique_ptr<Concurrency::task<void>> mLoopTask; std::unique_ptr<Concurrency::task<void>> mLoopTask;
hstring mArgs;
}; };
} // namespace winrt::ServoApp::implementation } // namespace winrt::ServoApp::implementation

View file

@ -11,6 +11,7 @@ namespace ServoApp {
void Stop(); void Stop();
Windows.Foundation.Uri LoadURIOrSearch(String url); Windows.Foundation.Uri LoadURIOrSearch(String url);
void SetTransientMode(Boolean transient); void SetTransientMode(Boolean transient);
void SetArgs(String args);
void Shutdown(); void Shutdown();
event EventDelegate OnLoadStarted; event EventDelegate OnLoadStarted;
event EventDelegate OnLoadEnded; event EventDelegate OnLoadEnded;