diff options
author | bors-servo <servo-ops@mozilla.com> | 2020-06-10 03:46:21 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-10 03:46:21 -0400 |
commit | 60ee588c71c6bba9871efaaf0ef68ae05e3e175f (patch) | |
tree | 4e57d1be53143071d4d6bb217754fdcf9cd58105 /support | |
parent | 554af02ab44f6dc96b8ebc570cdb01708a5a44bb (diff) | |
parent | 0d8afd9f0cced6fabafb09a84a043a287908526c (diff) | |
download | servo-60ee588c71c6bba9871efaaf0ef68ae05e3e175f.tar.gz servo-60ee588c71c6bba9871efaaf0ef68ae05e3e175f.zip |
Auto merge of #26793 - paulrouget:prefAPI, r=Manishearth
Pref api
Needs a bit more tweaking, but this should be ready soon.
Fix #26445
<img width="991" alt="Screen Shot 2020-06-03 at 14 59 57" src="https://user-images.githubusercontent.com/373579/83848819-b538ca00-a70e-11ea-9da8-67c9c2fe60d8.png">
Diffstat (limited to 'support')
-rw-r--r-- | support/hololens/ServoApp/App.h | 22 | ||||
-rw-r--r-- | support/hololens/ServoApp/App.xaml | 4 | ||||
-rw-r--r-- | support/hololens/ServoApp/Assets/UI/cross.png (renamed from support/hololens/ServoApp/Assets/UI/stop.png) | bin | 1827 -> 1827 bytes | |||
-rw-r--r-- | support/hololens/ServoApp/BrowserPage.cpp | 184 | ||||
-rw-r--r-- | support/hololens/ServoApp/BrowserPage.h | 47 | ||||
-rw-r--r-- | support/hololens/ServoApp/BrowserPage.xaml | 56 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoApp.vcxproj | 6 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoApp.vcxproj.filters | 4 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoControl/Servo.cpp | 151 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoControl/Servo.h | 89 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoControl/ServoControl.cpp | 27 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoControl/ServoControl.h | 52 | ||||
-rw-r--r-- | support/hololens/ServoApp/ServoControl/ServoControl.idl | 15 | ||||
-rw-r--r-- | support/hololens/ServoApp/packages.config | 1 | ||||
-rw-r--r-- | support/hololens/ServoApp/pch.h | 5 |
15 files changed, 545 insertions, 118 deletions
diff --git a/support/hololens/ServoApp/App.h b/support/hololens/ServoApp/App.h index 4772306e91f..3820da8b952 100644 --- a/support/hololens/ServoApp/App.h +++ b/support/hololens/ServoApp/App.h @@ -6,19 +6,19 @@ #include "App.xaml.g.h" namespace winrt::ServoApp::implementation { +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Activation; + struct App : AppT<App> { App(); - void createRootFrame(winrt::Windows::UI::Xaml::Controls::Frame &, bool, - winrt::Windows::Foundation::IInspectable const &); - void OnLaunched( - Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &); - void App::OnActivated( - Windows::ApplicationModel::Activation::IActivatedEventArgs const &); - void OnSuspending(IInspectable const &, - Windows::ApplicationModel::SuspendingEventArgs const &); - void OnNavigationFailed( - IInspectable const &, - Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const &); + void createRootFrame(Controls::Frame &, bool, IInspectable const &); + void OnLaunched(LaunchActivatedEventArgs const &); + void App::OnActivated(IActivatedEventArgs const &); + void OnSuspending(IInspectable const &, SuspendingEventArgs const &); + void OnNavigationFailed(IInspectable const &, + Navigation::NavigationFailedEventArgs const &); }; } // namespace winrt::ServoApp::implementation diff --git a/support/hololens/ServoApp/App.xaml b/support/hololens/ServoApp/App.xaml index 015f637b3df..333b37f88b7 100644 --- a/support/hololens/ServoApp/App.xaml +++ b/support/hololens/ServoApp/App.xaml @@ -4,4 +4,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ServoApp"> + <Application.Resources> + <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" /> + </Application.Resources> + </Application> diff --git a/support/hololens/ServoApp/Assets/UI/stop.png b/support/hololens/ServoApp/Assets/UI/cross.png Binary files differindex 181ede7b298..181ede7b298 100644 --- a/support/hololens/ServoApp/Assets/UI/stop.png +++ b/support/hololens/ServoApp/Assets/UI/cross.png diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp index e8ba12ba2b3..a2b13bf60b9 100644 --- a/support/hololens/ServoApp/BrowserPage.cpp +++ b/support/hololens/ServoApp/BrowserPage.cpp @@ -8,6 +8,11 @@ #include "BrowserPage.g.cpp" #include "DefaultUrl.h" +#include "winrt/Microsoft.UI.Xaml.Controls.h" +#include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h" +#include "winrt/Windows.UI.Text.h" +#include "winrt/Windows.UI.Xaml.Documents.h" // For Run.Text() + using namespace std::placeholders; using namespace winrt::Windows::Foundation; using namespace winrt::Windows::UI::Xaml; @@ -18,6 +23,7 @@ using namespace winrt::Windows::UI::Notifications; using namespace winrt::Windows::Data::Xml::Dom; namespace winrt::ServoApp::implementation { + BrowserPage::BrowserPage() { InitializeComponent(); BindServoEvents(); @@ -84,13 +90,12 @@ void BrowserPage::BindServoEvents() { }); } -void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) { +void BrowserPage::OnURLFocused(IInspectable const &) { urlTextbox().SelectAll(); } void BrowserPage::OnURLKeyboardAccelerator( - Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::Input::KeyboardAcceleratorInvokedEventArgs const &) { + IInspectable const &, Input::KeyboardAcceleratorInvokedEventArgs const &) { urlTextbox().Focus(FocusState::Programmatic); } @@ -116,10 +121,7 @@ void BrowserPage::SetTransientMode(bool transient) { void BrowserPage::SetArgs(hstring args) { servoControl().SetArgs(args); } -void BrowserPage::Shutdown() { - ToastNotificationManager::History().Clear(); - servoControl().Shutdown(); -} +void BrowserPage::Shutdown() { servoControl().Shutdown(); } /**** USER INTERACTIONS WITH UI ****/ @@ -148,23 +150,153 @@ void BrowserPage::OnHomeButtonClicked(IInspectable const &, servoControl().LoadURIOrSearch(DEFAULT_URL); } +// Given a pref, update its associated UI control. +void BrowserPage::UpdatePref(ServoApp::Pref pref, Controls::Control ctrl) { + auto value = pref.Value(); + auto type = value.as<IPropertyValue>().Type(); + if (type == PropertyType::Boolean) { + ctrl.as<Controls::CheckBox>().IsChecked(unbox_value<bool>(value)); + } else if (type == PropertyType::Double) { + ctrl.as<Microsoft::UI::Xaml::Controls::NumberBox>().Value( + unbox_value<double>(value)); + } else if (type == PropertyType::Int64) { + ctrl.as<Microsoft::UI::Xaml::Controls::NumberBox>().Value( + (double)unbox_value<int64_t>(value)); + } else if (type == PropertyType::String) { + ctrl.as<Controls::TextBox>().Text(unbox_value<hstring>(value)); + } + auto stack = ctrl.Parent().as<Controls::StackPanel>(); + auto font = winrt::Windows::UI::Text::FontWeights::Normal(); + if (!pref.IsDefault()) { + font = winrt::Windows::UI::Text::FontWeights::Bold(); + } + stack.Children().GetAt(0).as<Controls::TextBlock>().FontWeight(font); + stack.Children().GetAt(2).as<Controls::Button>().IsEnabled(!pref.IsDefault()); +} + +// Retrieve the preference list from Servo and build the preference table. +void BrowserPage::BuildPrefList() { + // It would be better to use a template and bindings, but the + // <ListView> takes too long to generate all the items, and + // it's pretty difficiult to have different controls depending + // on the pref type. + prefList().Children().Clear(); + for (auto pref : ServoControl().Preferences()) { + auto value = pref.Value(); + auto type = value.as<IPropertyValue>().Type(); + std::optional<Controls::Control> ctrl; + if (type == PropertyType::Boolean) { + auto checkbox = Controls::CheckBox(); + checkbox.IsChecked(unbox_value<bool>(value)); + checkbox.Click([=](const auto &, auto const &) { + auto upref = ServoControl().SetBoolPref( + pref.Key(), checkbox.IsChecked().GetBoolean()); + UpdatePref(upref, checkbox); + }); + ctrl = checkbox; + } else if (type == PropertyType::String) { + auto textbox = Controls::TextBox(); + textbox.Text(unbox_value<hstring>(value)); + textbox.KeyUp([=](const auto &, Input::KeyRoutedEventArgs const &e) { + if (e.Key() == Windows::System::VirtualKey::Enter) { + auto upref = ServoControl().SetStringPref(pref.Key(), textbox.Text()); + UpdatePref(upref, textbox); + } + }); + ctrl = textbox; + } else if (type == PropertyType::Int64) { + // Note: These are *not* under Windows::UI:Xaml namespace. + auto nbox = Microsoft::UI::Xaml::Controls::NumberBox(); + nbox.Value((double)unbox_value<int64_t>(value)); + nbox.SpinButtonPlacementMode( + Microsoft::UI::Xaml::Controls::NumberBoxSpinButtonPlacementMode:: + Inline); + nbox.ValueChanged([=](const auto &, const auto &) { + int val = (int)nbox.Value(); + auto upref = ServoControl().SetIntPref(pref.Key(), val); + UpdatePref(upref, nbox); + }); + ctrl = nbox; + } else if (type == PropertyType::Double) { + auto nbox = Microsoft::UI::Xaml::Controls::NumberBox(); + nbox.Value(unbox_value<double>(value)); + nbox.ValueChanged([=](const auto &, const auto &) { + auto upref = + ServoControl().SetIntPref(pref.Key(), (int64_t)nbox.Value()); + UpdatePref(upref, (Controls::Control &)nbox); + }); + ctrl = nbox; + } + if (ctrl.has_value()) { + auto stack = Controls::StackPanel(); + stack.Tag(winrt::box_value(pref.Key())); + stack.Padding({4, 4, 4, 4}); + stack.Orientation(Controls::Orientation::Horizontal); + auto key = Controls::TextBlock(); + key.Text(pref.Key()); + key.Width(350); + if (!pref.IsDefault()) { + auto font = winrt::Windows::UI::Text::FontWeights::Bold(); + key.FontWeight(font); + } + stack.Children().Append(key); + ctrl->Width(300); + ctrl->Margin({4, 0, 40, 0}); + stack.Children().Append(*ctrl); + auto reset = Controls::Button(); + reset.Content(winrt::box_value(L"reset")); + reset.IsEnabled(!pref.IsDefault()); + reset.Click([=](const auto &, auto const &) { + auto upref = ServoControl().ResetPref(pref.Key()); + UpdatePref(upref, *ctrl); + }); + stack.Children().Append(reset); + prefList().Children().Append(stack); + } + } +} + +void BrowserPage::OnPrefererenceSearchboxEdited( + IInspectable const &, Input::KeyRoutedEventArgs const &) { + auto input = preferenceSearchbox().Text(); + for (auto element : prefList().Children()) { + auto ctrl = (Controls::Control &)element; + if (input.size() == 0) { + ctrl.Visibility(Visibility::Visible); + } else { + auto tag = ctrl.Tag(); + std::wstring key = static_cast<std::wstring>(unbox_value<hstring>(tag)); + bool not_found = key.find(input) == std::wstring::npos; + ctrl.Visibility(not_found ? Visibility::Collapsed : Visibility::Visible); + } + } +} + void BrowserPage::OnDevtoolsButtonClicked(IInspectable const &, RoutedEventArgs const &) { - auto toastTemplate = ToastTemplateType::ToastText01; - auto toastXml = ToastNotificationManager::GetTemplateContent(toastTemplate); - auto toastTextElements = toastXml.GetElementsByTagName(L"text"); - std::wstring message; - if (mDevtoolsStatus == DevtoolsStatus::Stopped) { - message = L"Devtools server hasn't started"; - } else if (mDevtoolsStatus == DevtoolsStatus::Running) { - message = L"DevTools server has started on port " + - std::to_wstring(mDevtoolsPort); - } else if (mDevtoolsStatus == DevtoolsStatus::Failed) { - message = L"Error: could not start DevTools"; + if (toolbox().Visibility() == Visibility::Visible) { + prefList().Children().Clear(); + toolbox().Visibility(Visibility::Collapsed); + return; + } + + toolbox().Visibility(Visibility::Visible); + + BuildPrefList(); + + // FIXME: we could use template + binding for this. + auto ok = mDevtoolsStatus == DevtoolsStatus::Running ? Visibility::Visible + : Visibility::Collapsed; + auto ko = mDevtoolsStatus == DevtoolsStatus::Failed ? Visibility::Visible + : Visibility::Collapsed; + auto wip = mDevtoolsStatus == DevtoolsStatus::Stopped ? Visibility::Visible + : Visibility::Collapsed; + DevtoolsStatusOK().Visibility(ok); + DevtoolsStatusKO().Visibility(ko); + DevtoolsStatusWIP().Visibility(wip); + if (mDevtoolsStatus == DevtoolsStatus::Running) { + DevtoolsPort().Text(std::to_wstring(mDevtoolsPort)); } - toastTextElements.Item(0).InnerText(message); - auto toast = ToastNotification(toastXml); - ToastNotificationManager::CreateToastNotifier().Show(toast); } void BrowserPage::OnURLEdited(IInspectable const &, @@ -177,15 +309,13 @@ void BrowserPage::OnURLEdited(IInspectable const &, } } -void BrowserPage::OnMediaControlsPlayClicked( - Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &) { +void BrowserPage::OnMediaControlsPlayClicked(IInspectable const &, + RoutedEventArgs const &) { servoControl().SendMediaSessionAction( static_cast<int32_t>(servo::Servo::MediaSessionActionType::Play)); } -void BrowserPage::OnMediaControlsPauseClicked( - Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &) { +void BrowserPage::OnMediaControlsPauseClicked(IInspectable const &, + RoutedEventArgs const &) { servoControl().SendMediaSessionAction( static_cast<int32_t>(servo::Servo::MediaSessionActionType::Pause)); } diff --git a/support/hololens/ServoApp/BrowserPage.h b/support/hololens/ServoApp/BrowserPage.h index bb57afad68a..bae31d22ff3 100644 --- a/support/hololens/ServoApp/BrowserPage.h +++ b/support/hololens/ServoApp/BrowserPage.h @@ -9,6 +9,10 @@ namespace winrt::ServoApp::implementation { +using namespace winrt::Windows; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::UI::Xaml; + static const hstring SERVO_SCHEME = L"fxr"; static const hstring SERVO_SCHEME_SLASH_SLASH = L"fxr://"; @@ -16,35 +20,32 @@ struct BrowserPage : BrowserPageT<BrowserPage> { public: BrowserPage(); - void OnForwardButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnBackButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnReloadButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnStopButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnHomeButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnDevtoolsButtonClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnURLEdited(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::Input::KeyRoutedEventArgs const &); - void OnURLFocused(Windows::Foundation::IInspectable const &); - void OnURLKeyboardAccelerator( - Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::Input::KeyboardAcceleratorInvokedEventArgs const &); + void OnForwardButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnBackButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnReloadButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnStopButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnHomeButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnDevtoolsButtonClicked(IInspectable const &, RoutedEventArgs const &); + void OnURLEdited(IInspectable const &, Input::KeyRoutedEventArgs const &); + void OnURLFocused(IInspectable const &); + void + OnURLKeyboardAccelerator(IInspectable const &, + Input::KeyboardAcceleratorInvokedEventArgs const &); void Shutdown(); - void LoadServoURI(Windows::Foundation::Uri uri); + void LoadServoURI(Uri uri); void SetTransientMode(bool); void SetArgs(hstring); - void OnMediaControlsPlayClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); - void OnMediaControlsPauseClicked(Windows::Foundation::IInspectable const &, - Windows::UI::Xaml::RoutedEventArgs const &); + void OnMediaControlsPlayClicked(IInspectable const &, + RoutedEventArgs const &); + void OnMediaControlsPauseClicked(IInspectable const &, + RoutedEventArgs const &); + void OnPrefererenceSearchboxEdited(IInspectable const &, + Input::KeyRoutedEventArgs const &); private: + void UpdatePref(ServoApp::Pref, Controls::Control); void BindServoEvents(); + void BuildPrefList(); DevtoolsStatus mDevtoolsStatus = DevtoolsStatus::Stopped; unsigned int mDevtoolsPort = 0; }; diff --git a/support/hololens/ServoApp/BrowserPage.xaml b/support/hololens/ServoApp/BrowserPage.xaml index 3fa6cf84982..da4ea5c9792 100644 --- a/support/hololens/ServoApp/BrowserPage.xaml +++ b/support/hololens/ServoApp/BrowserPage.xaml @@ -6,7 +6,11 @@ xmlns:local="using:ServoApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:muxc="using:Microsoft.UI.Xaml.Controls" mc:Ignorable="d"> + + + <Page.Resources> <Style x:Key="NavigationBarButton" TargetType="Button"> <Setter Property="Background" Value="Transparent"/> @@ -82,7 +86,9 @@ <Grid VerticalAlignment="Stretch"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> - <RowDefinition Height="*"/> + <RowDefinition Height="*" MinHeight="200"/> + <RowDefinition Height="auto"/> + <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid Grid.Row="0" x:Name="navigationBar" Background="{ThemeResource InkToolbarButtonBackgroundThemeBrush}"> @@ -111,7 +117,7 @@ </Button.KeyboardAccelerators> </Button> <Button Style="{StaticResource NavigationBarButton}" x:Name="stopButton" IsTabStop="true" IsEnabled="false" Visibility="Collapsed" Click="OnStopButtonClicked" AutomationProperties.Name="Stop" ToolTipService.ToolTip="Stop"> - <Image Source="Assets/UI/stop.png" Height="18"></Image> + <Image Source="Assets/UI/cross.png" Height="18"></Image> <Button.KeyboardAccelerators> <KeyboardAccelerator Key="Escape" Modifiers="None" /> </Button.KeyboardAccelerators> @@ -132,9 +138,49 @@ <ProgressRing x:Name="urlbarLoadingIndicator" Margin="10,0"/> </StackPanel> </Grid> - <local:ServoControl TabIndex="0" x:Name="servoControl" Grid.Row="1"/> - <ProgressBar x:Name="transientLoadingIndicator" Visibility="Collapsed" Grid.Row="2"/> - <CommandBar Grid.Row="2" x:Name="mediaControls" Visibility="Collapsed"> + <local:ServoControl Grid.Row="1" TabIndex="0" x:Name="servoControl"/> + <muxc:TabView x:Name="toolbox" IsAddTabButtonVisible="False" Grid.Row="2" Visibility="Collapsed" Height="300"> + <muxc:TabView.TabStripFooter> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="Auto"/> + </Grid.ColumnDefinitions> + <Button Grid.Column="1" Style="{StaticResource NavigationBarButton}" x:Name="toolboxCloseButton" IsTabStop="true" Click="OnDevtoolsButtonClicked"> + <Image Source="Assets/UI/cross.png" Height="18"></Image> + </Button> + </Grid> + </muxc:TabView.TabStripFooter> + <muxc:TabViewItem Header="Devtools Server" IsClosable="False"> + <StackPanel> + <TextBlock x:Name="DevtoolsStatusOK" Visibility="Collapsed" Margin="10"> + <Run>Devtools server is listening on port </Run> + <Run FontWeight="Bold" x:Name="DevtoolsPort"></Run> + <Run>.</Run> + </TextBlock> + <TextBlock x:Name="DevtoolsStatusKO" Visibility="Collapsed"> + <Run>Devtools server failed to start.</Run> + </TextBlock> + <TextBlock x:Name="DevtoolsStatusWIP" Visibility="Collapsed"> + <Run>Devtools server is starting..</Run> + </TextBlock> + </StackPanel> + </muxc:TabViewItem> + <muxc:TabViewItem Header="Preferences" IsClosable="False"> + <Grid VerticalAlignment="Stretch"> + <Grid.RowDefinitions> + <RowDefinition Height="auto"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <TextBox Grid.Row="0" Text="" IsTabStop="true" PlaceholderText="Search preferences" x:Name="preferenceSearchbox" VerticalAlignment="Center" KeyUp="OnPrefererenceSearchboxEdited" IsSpellCheckEnabled="False" Margin="3"/> + <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto"> + <StackPanel x:Name="prefList"/> + </ScrollViewer> + </Grid> + </muxc:TabViewItem> + </muxc:TabView> + <ProgressBar x:Name="transientLoadingIndicator" Visibility="Collapsed" Grid.Row="3"/> + <CommandBar Grid.Row="4" x:Name="mediaControls" Visibility="Collapsed"> <AppBarButton Icon="Play" Label="Play" x:Name="playButton" Visibility="Collapsed" Click="OnMediaControlsPlayClicked"/> <AppBarButton Icon="Pause" Label="Pause" x:Name="pauseButton" Click="OnMediaControlsPauseClicked"/> </CommandBar> diff --git a/support/hololens/ServoApp/ServoApp.vcxproj b/support/hololens/ServoApp/ServoApp.vcxproj index b005f746086..9d0c1c7716b 100644 --- a/support/hololens/ServoApp/ServoApp.vcxproj +++ b/support/hololens/ServoApp/ServoApp.vcxproj @@ -907,7 +907,7 @@ <Image Include="Assets\UI\forward.png" /> <Image Include="Assets\UI\home.png" /> <Image Include="Assets\UI\reload.png" /> - <Image Include="Assets\UI\stop.png" /> + <Image Include="Assets\UI\cross.png" /> <Image Include="Assets\Wide310x150Logo.scale-100.png" /> <Image Include="Assets\Wide310x150Logo.scale-200.png" /> <Image Include="Assets\Wide310x150Logo.scale-400.png" /> @@ -948,6 +948,7 @@ <Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets')" /> <Import Project="..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.targets" Condition="Exists('..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.targets')" /> <Import Project="..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets" Condition="Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets')" /> + <Import Project="..\packages\Microsoft.UI.Xaml.2.4.2\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\packages\Microsoft.UI.Xaml.2.4.2\build\native\Microsoft.UI.Xaml.targets')" /> </ImportGroup> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <PropertyGroup> @@ -958,5 +959,6 @@ <Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.props'))" /> <Error Condition="!Exists('..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\OpenXR.Loader.1.0.6.2\build\native\OpenXR.Loader.targets'))" /> <Error Condition="!Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.Servo.2.1.19\build\native\ANGLE.WindowsStore.Servo.targets'))" /> + <Error Condition="!Exists('..\packages\Microsoft.UI.Xaml.2.4.2\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.UI.Xaml.2.4.2\build\native\Microsoft.UI.Xaml.targets'))" /> </Target> -</Project>
\ No newline at end of file +</Project> diff --git a/support/hololens/ServoApp/ServoApp.vcxproj.filters b/support/hololens/ServoApp/ServoApp.vcxproj.filters index aa50cafbcd4..39acc9fc3c3 100644 --- a/support/hololens/ServoApp/ServoApp.vcxproj.filters +++ b/support/hololens/ServoApp/ServoApp.vcxproj.filters @@ -148,7 +148,7 @@ <Image Include="Assets\UI\reload.png"> <Filter>Assets\UI</Filter> </Image> - <Image Include="Assets\UI\stop.png"> + <Image Include="Assets\UI\cross.png"> <Filter>Assets\UI</Filter> </Image> <Image Include="Assets\UI\home.png"> @@ -901,4 +901,4 @@ <ItemGroup> <ApplicationDefinition Include="App.xaml" /> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/support/hololens/ServoApp/ServoControl/Servo.cpp b/support/hololens/ServoApp/ServoControl/Servo.cpp index 83d926087fb..a53ea2489f1 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.cpp +++ b/support/hololens/ServoApp/ServoControl/Servo.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "Servo.h" #include <EGL/egl.h> +#include "../DefaultUrl.h" namespace winrt::servo { @@ -130,10 +131,64 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height, : mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) { SetEnvironmentVariableA("PreviewRuntimeEnabled", "1"); + Windows::Storage::ApplicationDataContainer localSettings = + Windows::Storage::ApplicationData::Current().LocalSettings(); + if (!localSettings.Containers().HasKey(L"servoUserPrefs")) { + Windows::Storage::ApplicationDataContainer container = + localSettings.CreateContainer( + L"servoUserPrefs", + Windows::Storage::ApplicationDataCreateDisposition::Always); + } + + auto prefs = localSettings.Containers().Lookup(L"servoUserPrefs"); + + if (!prefs.Values().HasKey(L"shell.homepage")) { + prefs.Values().Insert(L"shell.homepage", box_value(DEFAULT_URL)); + } + + if (!prefs.Values().HasKey(L"dom.webxr.enabled")) { + prefs.Values().Insert(L"dom.webxr.enabled", box_value(true)); + } + + std::vector<capi::CPref> cprefs; + + for (auto pref : prefs.Values()) { + auto key = *hstring2char(pref.Key()); + auto value = pref.Value(); + auto type = value.as<Windows::Foundation::IPropertyValue>().Type(); + capi::CPref pref; + pref.key = key; + pref.pref_type = capi::CPrefType::Missing; + pref.value = NULL; + if (type == Windows::Foundation::PropertyType::Boolean) { + pref.pref_type = capi::CPrefType::Bool; + auto val = unbox_value<bool>(value); + pref.value = &val; + } else if (type == Windows::Foundation::PropertyType::String) { + pref.pref_type = capi::CPrefType::Str; + pref.value = *hstring2char(unbox_value<hstring>(value)); + } else if (type == Windows::Foundation::PropertyType::Int64) { + pref.pref_type = capi::CPrefType::Int; + auto val = unbox_value<int64_t>(value); + pref.value = &val; + } else if (type == Windows::Foundation::PropertyType::Double) { + pref.pref_type = capi::CPrefType::Float; + auto val = unbox_value<double>(value); + pref.value = &val; + } else if (type == Windows::Foundation::PropertyType::Empty) { + pref.pref_type = capi::CPrefType::Missing; + } else { + log("skipping pref %s. Unknown type", key); + continue; + } + cprefs.push_back(pref); + } + + capi::CPrefList prefsList = {cprefs.size(), cprefs.data()}; + capi::CInitOptions o; - hstring defaultPrefs = L" --pref dom.webxr.enabled --devtools"; - o.args = *hstring2char(args + defaultPrefs); - o.url = *hstring2char(url); + o.prefs = &prefsList; + o.args = *hstring2char(args + L"--devtools"); o.width = mWindowWidth; o.height = mWindowHeight; o.density = dpi; @@ -221,6 +276,96 @@ Servo::~Servo() { CloseHandle(sLogHandle); } +Servo::PrefTuple Servo::SetFloatPref(hstring key, double val) { + auto ckey = *hstring2char(key); + capi::set_float_pref(ckey, val); + auto updatedPref = WrapPref(capi::get_pref(ckey)); + SaveUserPref(updatedPref); + return updatedPref; +} + +Servo::PrefTuple Servo::SetIntPref(hstring key, int64_t val) { + auto ckey = *hstring2char(key); + capi::set_int_pref(ckey, val); + auto updatedPref = WrapPref(capi::get_pref(ckey)); + SaveUserPref(updatedPref); + return updatedPref; +} + +Servo::PrefTuple Servo::SetBoolPref(hstring key, bool val) { + auto ckey = *hstring2char(key); + capi::set_bool_pref(ckey, val); + auto updatedPref = WrapPref(capi::get_pref(ckey)); + SaveUserPref(updatedPref); + return updatedPref; +} + +Servo::PrefTuple Servo::SetStringPref(hstring key, hstring val) { + auto ckey = *hstring2char(key); + auto cval = *hstring2char(val); + capi::set_str_pref(ckey, cval); + auto updatedPref = WrapPref(capi::get_pref(ckey)); + SaveUserPref(updatedPref); + return updatedPref; +} + +Servo::PrefTuple Servo::ResetPref(hstring key) { + auto ckey = *hstring2char(key); + capi::reset_pref(ckey); + auto updatedPref = WrapPref(capi::get_pref(ckey)); + SaveUserPref(updatedPref); + return updatedPref; +} + +void Servo::SaveUserPref(PrefTuple pref) { + auto localSettings = + Windows::Storage::ApplicationData::Current().LocalSettings(); + auto values = localSettings.Containers().Lookup(L"servoUserPrefs").Values(); + auto [key, val, isDefault] = pref; + if (isDefault) { + values.Remove(key); + } else { + values.Insert(key, val); + } +} + +Servo::PrefTuple Servo::WrapPref(capi::CPref pref) { + winrt::Windows::Foundation::IInspectable val; + if (pref.pref_type == capi::CPrefType::Bool) { + val = box_value(*(capi::get_pref_as_bool(pref.value))); + } else if (pref.pref_type == capi::CPrefType::Int) { + val = box_value(*(capi::get_pref_as_int(pref.value))); + } else if (pref.pref_type == capi::CPrefType::Float) { + val = box_value(*(capi::get_pref_as_float(pref.value))); + } else if (pref.pref_type == capi::CPrefType::Str) { + val = box_value(char2hstring(capi::get_pref_as_str(pref.value))); + } + auto key = char2hstring(pref.key); + auto isDefault = pref.is_default; + Servo::PrefTuple t{key, val, isDefault}; + return t; +} + +Servo::PrefTuple Servo::GetPref(hstring key) { + auto ckey = *hstring2char(key); + return WrapPref(capi::get_pref(ckey)); +} + +std::vector<Servo::PrefTuple> Servo::GetPrefs() { + if (sServo == nullptr) { + return {}; + } + auto prefs = capi::get_prefs(); + std::vector< + std::tuple<hstring, winrt::Windows::Foundation::IInspectable, bool>> + vec; + for (auto i = 0; i < prefs.len; i++) { + auto pref = WrapPref(prefs.list[i]); + vec.push_back(pref); + } + return vec; +} + winrt::hstring char2hstring(const char *c_str) { // FIXME: any better way of doing this? auto str = std::string(c_str); diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h index a61adf81f49..025b0f30c3f 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.h +++ b/support/hololens/ServoApp/ServoControl/Servo.h @@ -17,6 +17,8 @@ extern "C" { } } // namespace capi +using namespace capi; + hstring char2hstring(const char *); std::unique_ptr<char *> hstring2char(hstring); @@ -29,62 +31,67 @@ public: ~Servo(); ServoDelegate &Delegate() { return mDelegate; } - typedef capi::CMouseButton MouseButton; - typedef capi::CPromptResult PromptResult; - typedef capi::CContextMenuResult ContextMenuResult; - typedef capi::CMediaSessionActionType MediaSessionActionType; - typedef capi::CMediaSessionPlaybackState MediaSessionPlaybackState; - typedef capi::CDevtoolsServerState DevtoolsServerState; - - void PerformUpdates() { capi::perform_updates(); } - void DeInit() { capi::deinit(); } - void RequestShutdown() { capi::request_shutdown(); } - void SetBatchMode(bool mode) { capi::set_batch_mode(mode); } - void GoForward() { capi::go_forward(); } - void GoBack() { capi::go_back(); } - void Click(float x, float y) { capi::click(x, y); } - void MouseDown(float x, float y, capi::CMouseButton b) { - capi::mouse_down(x, y, b); - } - void MouseUp(float x, float y, capi::CMouseButton b) { - capi::mouse_up(x, y, b); - } - void TouchDown(float x, float y, int32_t id) { capi::touch_down(x, y, id); } - void TouchUp(float x, float y, int32_t id) { capi::touch_up(x, y, id); } - void TouchMove(float x, float y, int32_t id) { capi::touch_move(x, y, id); } - void TouchCancel(float x, float y, int32_t id) { - capi::touch_cancel(x, y, id); - } - void MouseMove(float x, float y) { capi::mouse_move(x, y); } - - void Reload() { capi::reload(); } - void Stop() { capi::stop(); } - bool LoadUri(hstring uri) { return capi::load_uri(*hstring2char(uri)); } - void ChangeVisibility(bool visible) { capi::change_visibility(visible); } - bool IsUriValid(hstring uri) { - return capi::is_uri_valid(*hstring2char(uri)); - } + typedef std::tuple<hstring, winrt::Windows::Foundation::IInspectable, bool> + PrefTuple; + static std::vector<PrefTuple> GetPrefs(); + static PrefTuple GetPref(hstring key); + static PrefTuple SetBoolPref(hstring key, bool val); + static PrefTuple SetStringPref(hstring key, hstring val); + static PrefTuple SetIntPref(hstring key, int64_t val); + static PrefTuple SetFloatPref(hstring key, double val); + static PrefTuple ResetPref(hstring key); + + typedef CMouseButton MouseButton; + typedef CPromptResult PromptResult; + typedef CContextMenuResult ContextMenuResult; + typedef CMediaSessionActionType MediaSessionActionType; + typedef CMediaSessionPlaybackState MediaSessionPlaybackState; + typedef CDevtoolsServerState DevtoolsServerState; + typedef CPrefType CPrefType; + + void PerformUpdates() { perform_updates(); } + void DeInit() { deinit(); } + void RequestShutdown() { request_shutdown(); } + void SetBatchMode(bool mode) { set_batch_mode(mode); } + void GoForward() { go_forward(); } + void GoBack() { go_back(); } + void Click(float x, float y) { click(x, y); } + void MouseDown(float x, float y, CMouseButton b) { mouse_down(x, y, b); } + void MouseUp(float x, float y, CMouseButton b) { mouse_up(x, y, b); } + void TouchDown(float x, float y, int32_t id) { touch_down(x, y, id); } + void TouchUp(float x, float y, int32_t id) { touch_up(x, y, id); } + void TouchMove(float x, float y, int32_t id) { touch_move(x, y, id); } + void TouchCancel(float x, float y, int32_t id) { touch_cancel(x, y, id); } + void MouseMove(float x, float y) { mouse_move(x, y); } + + void Reload() { reload(); } + void Stop() { stop(); } + bool LoadUri(hstring uri) { return load_uri(*hstring2char(uri)); } + void ChangeVisibility(bool visible) { change_visibility(visible); } + bool IsUriValid(hstring uri) { return is_uri_valid(*hstring2char(uri)); } void Scroll(float dx, float dy, float x, float y) { - capi::scroll((int32_t)dx, (int32_t)dy, (int32_t)x, (int32_t)y); + scroll((int32_t)dx, (int32_t)dy, (int32_t)x, (int32_t)y); } void SetSize(GLsizei width, GLsizei height) { if (width != mWindowWidth || height != mWindowHeight) { mWindowWidth = width; mWindowHeight = height; - capi::resize(mWindowWidth, mWindowHeight); + resize(mWindowWidth, mWindowHeight); } } - void SendMediaSessionAction(capi::CMediaSessionActionType action) { - capi::media_session_action(action); + void SendMediaSessionAction(CMediaSessionActionType action) { + media_session_action(action); } - void ContextMenuClosed(capi::CContextMenuResult res, unsigned int idx) { - capi::on_context_menu_closed(res, idx); + void ContextMenuClosed(CContextMenuResult res, unsigned int idx) { + on_context_menu_closed(res, idx); } private: ServoDelegate &mDelegate; GLsizei mWindowWidth; GLsizei mWindowHeight; + static void SaveUserPref(PrefTuple); + static PrefTuple WrapPref(CPref cpref); }; class ServoDelegate { diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp index eae5016181c..cca58cce0ac 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp +++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "ServoControl.h" #include "ServoControl.g.cpp" +#include "Pref.g.cpp" #include <stdlib.h> using namespace std::placeholders; @@ -275,10 +276,19 @@ hstring ServoControl::LoadURIOrSearch(hstring input) { } // Doesn't look like a URI. Let's search for the string. - hstring searchUri = - L"https://duckduckgo.com/html/?q=" + Uri::EscapeComponent(input); - TryLoadUri(searchUri); - return searchUri; + auto escapedInput = Uri::EscapeComponent(input); + std::wstring searchUri = + unbox_value<hstring>(std::get<1>(Servo::GetPref(L"shell.searchpage"))) + .c_str(); + std::wstring keyword = L"%s"; + size_t start_pos = searchUri.find(keyword); + if (start_pos == std::string::npos) + searchUri = searchUri + escapedInput; + else + searchUri.replace(start_pos, keyword.length(), escapedInput); + hstring finalUri{searchUri}; + TryLoadUri(finalUri); + return finalUri; } void ServoControl::SendMediaSessionAction(int32_t action) { @@ -580,4 +590,13 @@ template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) { Dispatcher().RunAsync(CoreDispatcherPriority::High, cb); } +Collections::IVector<ServoApp::Pref> ServoControl::Preferences() { + std::vector<ServoApp::Pref> prefs; + for (auto [key, val, isDefault] : Servo::GetPrefs()) { + prefs.push_back(ServoApp::Pref(key, val, isDefault)); + } + return winrt::single_threaded_observable_vector<ServoApp::Pref>( + std::move(prefs)); +} + } // namespace winrt::ServoApp::implementation diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h index dbc9e91ca92..6b0d09bafc5 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.h +++ b/support/hololens/ServoApp/ServoControl/ServoControl.h @@ -1,5 +1,6 @@ #pragma once #include "ServoControl.g.h" +#include "Pref.g.h" #include "OpenGLES.h" #include "Servo.h" #include "DefaultUrl.h" @@ -7,10 +8,30 @@ using namespace winrt::Windows::Foundation::Collections; namespace winrt::ServoApp::implementation { + +struct Pref : PrefT<Pref> { +public: + Pref(hstring key, IInspectable value, bool isDefault) { + mKey = key; + mValue = value; + mIsDefault = isDefault; + }; + IInspectable Value() { return mValue; } + hstring Key() { return mKey; } + bool IsDefault() { return mIsDefault; } + +private: + hstring mKey; + IInspectable mValue; + bool mIsDefault; +}; + struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate { ServoControl(); + Windows::Foundation::Collections::IVector<ServoApp::Pref> Preferences(); + void GoBack(); void GoForward(); void Reload(); @@ -20,6 +41,36 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate { hstring LoadURIOrSearch(hstring); void SendMediaSessionAction(int32_t); + ServoApp::Pref SetBoolPref(hstring aKey, bool aVal) { + auto [key, val, isDefault] = servo::Servo::SetBoolPref(aKey, aVal); + return ServoApp::Pref(key, val, isDefault); + } + + ServoApp::Pref SetStringPref(hstring aKey, hstring aVal) { + auto [key, val, isDefault] = servo::Servo::SetStringPref(aKey, aVal); + return ServoApp::Pref(key, val, isDefault); + } + + ServoApp::Pref SetIntPref(hstring aKey, int64_t aVal) { + auto [key, val, isDefault] = servo::Servo::SetIntPref(aKey, aVal); + return ServoApp::Pref(key, val, isDefault); + } + + ServoApp::Pref SetFloatPref(hstring aKey, double aVal) { + auto [key, val, isDefault] = servo::Servo::SetFloatPref(aKey, aVal); + return ServoApp::Pref(key, val, isDefault); + } + + ServoApp::Pref ResetPref(hstring aKey) { + auto [key, val, isDefault] = servo::Servo::ResetPref(aKey); + return ServoApp::Pref(key, val, isDefault); + } + + ServoApp::Pref GetPref(hstring aKey) { + auto [key, val, isDefault] = servo::Servo::GetPref(aKey); + return ServoApp::Pref(key, val, isDefault); + } + void OnLoaded(IInspectable const &, Windows::UI::Xaml::RoutedEventArgs const &); @@ -223,4 +274,5 @@ private: namespace winrt::ServoApp::factory_implementation { struct ServoControl : ServoControlT<ServoControl, implementation::ServoControl> {}; +struct Pref : PrefT<Pref, implementation::Pref> {}; } // namespace winrt::ServoApp::factory_implementation diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.idl b/support/hololens/ServoApp/ServoControl/ServoControl.idl index 5e5da81bc29..99f411a9be4 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.idl +++ b/support/hololens/ServoApp/ServoControl/ServoControl.idl @@ -11,6 +11,14 @@ namespace ServoApp { Failed, }; + runtimeclass Pref + { + Pref(String key, IInspectable val, Boolean isDefault); + IInspectable Value { get; }; + String Key { get; }; + Boolean IsDefault { get; }; + } + runtimeclass ServoControl : Windows.UI.Xaml.Controls.Control { ServoControl(); void GoBack(); @@ -33,5 +41,12 @@ namespace ServoApp { event Windows.Foundation.EventHandler<String> OnURLChanged; event MediaSessionMetadataDelegate OnMediaSessionMetadata; event Windows.Foundation.EventHandler<int> OnMediaSessionPlaybackStateChange; + Windows.Foundation.Collections.IVector<Pref> Preferences { get; }; + Pref GetPref(String key); + Pref SetBoolPref(String key, Boolean val); + Pref SetIntPref(String key, Int64 val); + Pref SetFloatPref(String key, Double val); + Pref SetStringPref(String key, String val); + Pref ResetPref(String key); } } // namespace ServoApp diff --git a/support/hololens/ServoApp/packages.config b/support/hololens/ServoApp/packages.config index 2a6918a8e78..c6bb3977b3c 100644 --- a/support/hololens/ServoApp/packages.config +++ b/support/hololens/ServoApp/packages.config @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="ANGLE.WindowsStore.Servo" version="2.1.19" targetFramework="native" /> + <package id="Microsoft.UI.Xaml" version="2.4.2" targetFramework="native" /> <package id="Microsoft.Windows.CppWinRT" version="2.0.200316.3" targetFramework="native" /> <package id="OpenXR.Loader" version="1.0.6.2" targetFramework="native" /> </packages>
\ No newline at end of file diff --git a/support/hololens/ServoApp/pch.h b/support/hololens/ServoApp/pch.h index 59a4cd3ca8a..04ea55755e9 100644 --- a/support/hololens/ServoApp/pch.h +++ b/support/hololens/ServoApp/pch.h @@ -54,3 +54,8 @@ #include <winrt/Windows.UI.Xaml.Navigation.h> #include <winrt/Windows.UI.Notifications.h> #include <winrt/Windows.Data.Xml.Dom.h> + +#include "winrt/Microsoft.UI.Xaml.Automation.Peers.h" +#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h" +#include "winrt/Microsoft.UI.Xaml.Media.h" +#include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h"
\ No newline at end of file |