mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #23981 - paulrouget:servocontrol, r=manishearth
Implement Servo Control Template This wraps the swapchain in its own control, making it possible to better control the widget behavior. In the future, we could package that control into a nuget package allowing any app to use Servo. Fix #23894 Fix #23916 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23981) <!-- Reviewable:end -->
This commit is contained in:
commit
17f423723c
14 changed files with 522 additions and 336 deletions
|
@ -7,261 +7,78 @@
|
||||||
#include "BrowserPage.h"
|
#include "BrowserPage.h"
|
||||||
#include "BrowserPage.g.cpp"
|
#include "BrowserPage.g.cpp"
|
||||||
#include "ImmersiveView.h"
|
#include "ImmersiveView.h"
|
||||||
#include "OpenGLES.h"
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
using namespace winrt::Windows::UI::Core;
|
using namespace winrt::Windows::UI::Core;
|
||||||
using namespace winrt::Windows::UI::ViewManagement;
|
using namespace winrt::Windows::UI::ViewManagement;
|
||||||
using namespace winrt::Windows::Foundation;
|
|
||||||
using namespace winrt::Windows::Graphics::Holographic;
|
using namespace winrt::Windows::Graphics::Holographic;
|
||||||
using namespace concurrency;
|
using namespace winrt::Windows::ApplicationModel::Core;
|
||||||
using namespace servo;
|
|
||||||
|
|
||||||
namespace winrt::ServoApp::implementation {
|
namespace winrt::ServoApp::implementation {
|
||||||
BrowserPage::BrowserPage() {
|
BrowserPage::BrowserPage() {
|
||||||
log("BrowserPage::BrowserPage()");
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
InitializeConditionVariable(&mGLCondVar);
|
BindServoEvents();
|
||||||
InitializeCriticalSection(&mGLLock);
|
|
||||||
Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2));
|
|
||||||
Window::Current().CoreWindow().VisibilityChanged(
|
|
||||||
std::bind(&BrowserPage::OnVisibilityChanged, this, _1, _2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::Shutdown() {
|
void BrowserPage::BindServoEvents() {
|
||||||
log("BrowserPage::Shutdown()");
|
servoControl().OnURLChanged(
|
||||||
|
[=](const auto &, hstring url) { urlTextbox().Text(url); });
|
||||||
if (mServo != nullptr) {
|
servoControl().OnTitleChanged([=](const auto &, hstring title) {});
|
||||||
if (!mLooping) {
|
servoControl().OnHistoryChanged([=](bool back, bool forward) {
|
||||||
// FIXME: this should not happen. In that case, we can't send the
|
backButton().IsEnabled(back);
|
||||||
// shutdown event to Servo.
|
forwardButton().IsEnabled(forward);
|
||||||
} else {
|
});
|
||||||
RunOnGLThread([=] { mServo->RequestShutdown(); });
|
servoControl().OnLoadStarted([=] {
|
||||||
mLoopTask->wait();
|
|
||||||
mLoopTask.reset();
|
|
||||||
mServo.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnPageLoaded(IInspectable const &, RoutedEventArgs const &) {
|
|
||||||
log("BrowserPage::OnPageLoaded()");
|
|
||||||
CreateRenderSurface();
|
|
||||||
StartRenderLoop();
|
|
||||||
swapChainPanel().PointerReleased(
|
|
||||||
std::bind(&BrowserPage::OnSurfaceClicked, this, _1, _2));
|
|
||||||
swapChainPanel().ManipulationDelta(
|
|
||||||
std::bind(&BrowserPage::OnSurfaceManipulationDelta, this, _1, _2));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnVisibilityChanged(CoreWindow const &,
|
|
||||||
VisibilityChangedEventArgs const &args) {
|
|
||||||
auto visible = args.Visible();
|
|
||||||
|
|
||||||
// FIXME: for now, this is disabled as we get this message before shutdown,
|
|
||||||
// stopping the event loop, which we can't recover from yet (see comment in
|
|
||||||
// Loop())
|
|
||||||
|
|
||||||
// if (visible && !mLooping) {
|
|
||||||
// StartRenderLoop();
|
|
||||||
//}
|
|
||||||
// if (!visible && mLooping) {
|
|
||||||
// StopRenderLoop();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::CreateRenderSurface() {
|
|
||||||
if (mRenderSurface == EGL_NO_SURFACE) {
|
|
||||||
mRenderSurface = mOpenGLES.CreateSurface(swapChainPanel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::DestroyRenderSurface() {
|
|
||||||
mOpenGLES.DestroySurface(mRenderSurface);
|
|
||||||
mRenderSurface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::RecoverFromLostDevice() {
|
|
||||||
StopRenderLoop();
|
|
||||||
DestroyRenderSurface();
|
|
||||||
mOpenGLES.Reset();
|
|
||||||
CreateRenderSurface();
|
|
||||||
StartRenderLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** GL THREAD LOOP ****/
|
|
||||||
|
|
||||||
void BrowserPage::Loop() {
|
|
||||||
log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId());
|
|
||||||
|
|
||||||
mOpenGLES.MakeCurrent(mRenderSurface);
|
|
||||||
|
|
||||||
EGLint panelWidth = 0;
|
|
||||||
EGLint panelHeight = 0;
|
|
||||||
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
|
|
||||||
glViewport(0, 0, panelWidth, panelHeight);
|
|
||||||
|
|
||||||
if (mServo == nullptr) {
|
|
||||||
log("Entering loop");
|
|
||||||
ServoDelegate *sd = static_cast<ServoDelegate *>(this);
|
|
||||||
mServo = std::make_unique<Servo>(panelWidth, panelHeight, *sd);
|
|
||||||
} else {
|
|
||||||
// FIXME: this will fail since create_task didn't pick the thread
|
|
||||||
// where Servo was running initially.
|
|
||||||
throw winrt::hresult_error(E_FAIL, L"Recovering loop unimplemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
mServo->SetBatchMode(true);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
EnterCriticalSection(&mGLLock);
|
|
||||||
while (mTasks.size() == 0 && !mAnimating && mLooping) {
|
|
||||||
SleepConditionVariableCS(&mGLCondVar, &mGLLock, INFINITE);
|
|
||||||
}
|
|
||||||
if (!mLooping) {
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (auto &&task : mTasks) {
|
|
||||||
task();
|
|
||||||
}
|
|
||||||
mTasks.clear();
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
mServo->PerformUpdates();
|
|
||||||
}
|
|
||||||
mServo->DeInit();
|
|
||||||
cancel_current_task();
|
|
||||||
} // namespace winrt::ServoApp::implementation
|
|
||||||
|
|
||||||
void BrowserPage::StartRenderLoop() {
|
|
||||||
if (mLooping) {
|
|
||||||
#if defined _DEBUG
|
|
||||||
throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
mLooping = true;
|
|
||||||
log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
|
|
||||||
auto task = Concurrency::create_task([=] { Loop(); });
|
|
||||||
mLoopTask = std::make_unique<Concurrency::task<void>>(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::StopRenderLoop() {
|
|
||||||
if (mLooping) {
|
|
||||||
EnterCriticalSection(&mGLLock);
|
|
||||||
mLooping = false;
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
WakeConditionVariable(&mGLCondVar);
|
|
||||||
mLoopTask->wait();
|
|
||||||
mLoopTask.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** SERVO CALLBACKS ****/
|
|
||||||
|
|
||||||
void BrowserPage::OnLoadStarted() {
|
|
||||||
RunOnUIThread([=] {
|
|
||||||
reloadButton().IsEnabled(false);
|
reloadButton().IsEnabled(false);
|
||||||
stopButton().IsEnabled(true);
|
stopButton().IsEnabled(true);
|
||||||
});
|
});
|
||||||
}
|
servoControl().OnLoadEnded([=] {
|
||||||
|
|
||||||
void BrowserPage::OnLoadEnded() {
|
|
||||||
RunOnUIThread([=] {
|
|
||||||
reloadButton().IsEnabled(true);
|
reloadButton().IsEnabled(true);
|
||||||
stopButton().IsEnabled(false);
|
stopButton().IsEnabled(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnHistoryChanged(bool back, bool forward) {
|
void BrowserPage::Shutdown() {
|
||||||
RunOnUIThread([=] {
|
servoControl().Shutdown();
|
||||||
backButton().IsEnabled(back);
|
|
||||||
forwardButton().IsEnabled(forward);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnShutdownComplete() {
|
|
||||||
EnterCriticalSection(&mGLLock);
|
|
||||||
mLooping = false;
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnAlert(std::wstring message) {
|
|
||||||
// FIXME: make this sync
|
|
||||||
RunOnUIThread([=] {
|
|
||||||
Windows::UI::Popups::MessageDialog msg{message};
|
|
||||||
msg.ShowAsync();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnTitleChanged(std::wstring title) {
|
|
||||||
RunOnUIThread([=] { ApplicationView::GetForCurrentView().Title(title); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnURLChanged(std::wstring url) {
|
|
||||||
RunOnUIThread([=] { urlTextbox().Text(url); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::Flush() {
|
|
||||||
if (mOpenGLES.SwapBuffers(mRenderSurface) != GL_TRUE) {
|
|
||||||
// The call to eglSwapBuffers might not be successful (i.e. due to Device
|
|
||||||
// Lost) If the call fails, then we must reinitialize EGL and the GL
|
|
||||||
// resources.
|
|
||||||
RunOnUIThread([=] { RecoverFromLostDevice(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::MakeCurrent() { mOpenGLES.MakeCurrent(mRenderSurface); }
|
|
||||||
|
|
||||||
void BrowserPage::WakeUp() {
|
|
||||||
RunOnGLThread([=] { });
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BrowserPage::OnAllowNavigation(std::wstring) { return true; }
|
|
||||||
|
|
||||||
void BrowserPage::OnAnimatingChanged(bool animating) {
|
|
||||||
EnterCriticalSection(&mGLLock);
|
|
||||||
mAnimating = animating;
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
WakeConditionVariable(&mGLCondVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable> void BrowserPage::RunOnUIThread(Callable cb) {
|
|
||||||
swapChainPanel().Dispatcher().RunAsync(
|
|
||||||
Windows::UI::Core::CoreDispatcherPriority::High, cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** USER INTERACTIONS WITH UI ****/
|
/**** USER INTERACTIONS WITH UI ****/
|
||||||
|
|
||||||
void BrowserPage::OnBackButtonClicked(IInspectable const &,
|
void BrowserPage::OnBackButtonClicked(IInspectable const &,
|
||||||
RoutedEventArgs const &) {
|
RoutedEventArgs const &) {
|
||||||
RunOnGLThread([=] { mServo->GoBack(); });
|
servoControl().GoBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnForwardButtonClicked(IInspectable const &,
|
void BrowserPage::OnForwardButtonClicked(IInspectable const &,
|
||||||
RoutedEventArgs const &) {
|
RoutedEventArgs const &) {
|
||||||
RunOnGLThread([=] { mServo->GoForward(); });
|
servoControl().GoForward();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnReloadButtonClicked(IInspectable const &,
|
void BrowserPage::OnReloadButtonClicked(IInspectable const &,
|
||||||
RoutedEventArgs const &) {
|
RoutedEventArgs const &) {
|
||||||
RunOnGLThread([=] { mServo->Reload(); });
|
servoControl().Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnStopButtonClicked(IInspectable const &,
|
void BrowserPage::OnStopButtonClicked(IInspectable const &,
|
||||||
RoutedEventArgs const &) {
|
RoutedEventArgs const &) {
|
||||||
RunOnGLThread([=] { mServo->Stop(); });
|
servoControl().Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserPage::OnURLEdited(IInspectable const &sender,
|
||||||
|
Input::KeyRoutedEventArgs const &e) {
|
||||||
|
if (e.Key() == Windows::System::VirtualKey::Enter) {
|
||||||
|
servoControl().Focus(FocusState::Programmatic);
|
||||||
|
auto input = urlTextbox().Text();
|
||||||
|
auto uri = servoControl().LoadURIOrSearch(input);
|
||||||
|
urlTextbox().Text(uri.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnImmersiveButtonClicked(IInspectable const &,
|
void BrowserPage::OnImmersiveButtonClicked(IInspectable const &,
|
||||||
RoutedEventArgs const &) {
|
RoutedEventArgs const &) {
|
||||||
if (HolographicSpace::IsAvailable()) {
|
if (HolographicSpace::IsAvailable()) {
|
||||||
log("Holographic space available");
|
log("Holographic space available");
|
||||||
auto v =
|
auto v = CoreApplication::CreateNewView(mImmersiveViewSource);
|
||||||
winrt::Windows::ApplicationModel::Core::CoreApplication::CreateNewView(
|
|
||||||
mImmersiveViewSource);
|
|
||||||
auto parentId = ApplicationView::GetForCurrentView().Id();
|
auto parentId = ApplicationView::GetForCurrentView().Id();
|
||||||
v.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [=] {
|
v.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [=] {
|
||||||
auto winId = ApplicationView::GetForCurrentView().Id();
|
auto winId = ApplicationView::GetForCurrentView().Id();
|
||||||
|
@ -273,30 +90,4 @@ void BrowserPage::OnImmersiveButtonClicked(IInspectable const &,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnSurfaceManipulationDelta(
|
|
||||||
IInspectable const &, Input::ManipulationDeltaRoutedEventArgs const &e) {
|
|
||||||
auto x = e.Position().X;
|
|
||||||
auto y = e.Position().Y;
|
|
||||||
auto dx = e.Delta().Translation.X;
|
|
||||||
auto dy = e.Delta().Translation.Y;
|
|
||||||
RunOnGLThread([=] { mServo->Scroll(dx, dy, x, y); });
|
|
||||||
e.Handled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::OnSurfaceClicked(IInspectable const &,
|
|
||||||
Input::PointerRoutedEventArgs const &e) {
|
|
||||||
auto coords = e.GetCurrentPoint(swapChainPanel());
|
|
||||||
auto x = coords.Position().X;
|
|
||||||
auto y = coords.Position().Y;
|
|
||||||
RunOnGLThread([=] { mServo->Click(x, y); });
|
|
||||||
e.Handled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserPage::RunOnGLThread(std::function<void()> task) {
|
|
||||||
EnterCriticalSection(&mGLLock);
|
|
||||||
mTasks.push_back(task);
|
|
||||||
LeaveCriticalSection(&mGLLock);
|
|
||||||
WakeConditionVariable(&mGLCondVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace winrt::ServoApp::implementation
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
|
@ -6,13 +6,12 @@
|
||||||
|
|
||||||
#include "BrowserPage.g.h"
|
#include "BrowserPage.g.h"
|
||||||
#include "ImmersiveView.h"
|
#include "ImmersiveView.h"
|
||||||
#include "OpenGLES.h"
|
#include "ServoControl\ServoControl.h"
|
||||||
#include "Servo.h"
|
|
||||||
|
|
||||||
namespace winrt::ServoApp::implementation {
|
namespace winrt::ServoApp::implementation {
|
||||||
|
|
||||||
struct BrowserPage : BrowserPageT<BrowserPage>,
|
struct BrowserPage : BrowserPageT<BrowserPage> {
|
||||||
public servo::ServoDelegate {
|
|
||||||
public:
|
public:
|
||||||
BrowserPage();
|
BrowserPage();
|
||||||
|
|
||||||
|
@ -26,59 +25,13 @@ public:
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
void OnStopButtonClicked(Windows::Foundation::IInspectable const &,
|
void OnStopButtonClicked(Windows::Foundation::IInspectable const &,
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
void
|
void OnURLEdited(Windows::Foundation::IInspectable const &,
|
||||||
OnSurfaceClicked(Windows::Foundation::IInspectable const &,
|
Windows::UI::Xaml::Input::KeyRoutedEventArgs const &);
|
||||||
Windows::UI::Xaml::Input::PointerRoutedEventArgs const &);
|
|
||||||
|
|
||||||
void BrowserPage::OnSurfaceManipulationDelta(
|
|
||||||
IInspectable const &,
|
|
||||||
Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs const &e);
|
|
||||||
|
|
||||||
template <typename Callable> void RunOnUIThread(Callable);
|
|
||||||
void RunOnGLThread(std::function<void()>);
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
virtual void WakeUp();
|
|
||||||
virtual void OnLoadStarted();
|
|
||||||
virtual void OnLoadEnded();
|
|
||||||
virtual void OnHistoryChanged(bool, bool);
|
|
||||||
virtual void OnShutdownComplete();
|
|
||||||
virtual void OnTitleChanged(std::wstring);
|
|
||||||
virtual void OnAlert(std::wstring);
|
|
||||||
virtual void OnURLChanged(std::wstring);
|
|
||||||
virtual void Flush();
|
|
||||||
virtual void MakeCurrent();
|
|
||||||
virtual bool OnAllowNavigation(std::wstring);
|
|
||||||
virtual void OnAnimatingChanged(bool);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnVisibilityChanged(
|
|
||||||
Windows::UI::Core::CoreWindow const &,
|
|
||||||
Windows::UI::Core::VisibilityChangedEventArgs const &args);
|
|
||||||
void OnPageLoaded(Windows::Foundation::IInspectable const &,
|
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
|
||||||
void CreateRenderSurface();
|
|
||||||
void DestroyRenderSurface();
|
|
||||||
void RecoverFromLostDevice();
|
|
||||||
|
|
||||||
void StartRenderLoop();
|
|
||||||
void StopRenderLoop();
|
|
||||||
void Loop();
|
|
||||||
|
|
||||||
std::unique_ptr<Concurrency::task<void>> mLoopTask;
|
|
||||||
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
|
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
|
||||||
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
void BindServoEvents();
|
||||||
std::unique_ptr<servo::Servo> mServo;
|
|
||||||
|
|
||||||
std::vector<std::function<void()>> mTasks;
|
|
||||||
|
|
||||||
CRITICAL_SECTION mGLLock;
|
|
||||||
CONDITION_VARIABLE mGLCondVar;
|
|
||||||
|
|
||||||
bool mAnimating = false;
|
|
||||||
bool mLooping = false;
|
|
||||||
|
|
||||||
OpenGLES mOpenGLES; // FIXME: shared pointer
|
|
||||||
};
|
};
|
||||||
} // namespace winrt::ServoApp::implementation
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
||||||
|
|
|
@ -20,17 +20,16 @@
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="0">
|
<StackPanel Orientation="Horizontal" Grid.Column="0">
|
||||||
<Button x:Name="backButton" IsEnabled="false" Content="Back" Click="OnBackButtonClicked"/>
|
<Button x:Name="backButton" IsTabStop="true" IsEnabled="false" Content="Back" Click="OnBackButtonClicked"/>
|
||||||
<Button x:Name="forwardButton" IsEnabled="false" Content="Forward" Click="OnForwardButtonClicked"/>
|
<Button x:Name="forwardButton" IsTabStop="true" IsEnabled="false" Content="Forward" Click="OnForwardButtonClicked"/>
|
||||||
<Button x:Name="reloadButton" IsEnabled="false" Content="reload" Click="OnReloadButtonClicked"/>
|
<Button x:Name="reloadButton" IsTabStop="true" IsEnabled="false" Content="reload" Click="OnReloadButtonClicked"/>
|
||||||
<Button x:Name="stopButton" IsEnabled="false" Content="stop" Click="OnStopButtonClicked"/>
|
<Button x:Name="stopButton" IsTabStop="true" IsEnabled="false" Content="stop" Click="OnStopButtonClicked"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<TextBox Text="" AcceptsReturn="True" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" IsReadOnly="True"/>
|
<TextBox Text="" IsTabStop="true" InputScope="Url" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" KeyUp="OnURLEdited"/>
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="2">
|
<StackPanel Orientation="Horizontal" Grid.Column="2">
|
||||||
<Button x:Name="immersiveButton" Click="OnImmersiveButtonClicked">Run Immersive</Button>
|
<Button x:Name="immersiveButton" Click="OnImmersiveButtonClicked">Run Immersive</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<SwapChainPanel x:Name="swapChainPanel" MinHeight="200" MinWidth="200" Grid.Row="1" ManipulationMode="All">
|
<local:ServoControl TabIndex="0" x:Name="servoControl" Grid.Row="1"/>
|
||||||
</SwapChainPanel>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "OpenGLES.h"
|
|
||||||
#include "Common/DeviceResources.h"
|
#include "Common/DeviceResources.h"
|
||||||
#include "ImmersiveMain.h"
|
#include "ImmersiveMain.h"
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,6 @@
|
||||||
<ClInclude Include="ImmersiveMain.h" />
|
<ClInclude Include="ImmersiveMain.h" />
|
||||||
<ClInclude Include="ImmersiveView.h" />
|
<ClInclude Include="ImmersiveView.h" />
|
||||||
<ClInclude Include="logs.h" />
|
<ClInclude Include="logs.h" />
|
||||||
<ClInclude Include="OpenGLES.h" />
|
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="App.h">
|
<ClInclude Include="App.h">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
@ -159,7 +158,9 @@
|
||||||
<ClInclude Include="BrowserPage.h">
|
<ClInclude Include="BrowserPage.h">
|
||||||
<DependentUpon>BrowserPage.xaml</DependentUpon>
|
<DependentUpon>BrowserPage.xaml</DependentUpon>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Servo.h" />
|
<ClInclude Include="ServoControl\OpenGLES.h" />
|
||||||
|
<ClInclude Include="ServoControl\Servo.h" />
|
||||||
|
<ClInclude Include="ServoControl\ServoControl.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ApplicationDefinition Include="App.xaml">
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
@ -168,6 +169,9 @@
|
||||||
<Page Include="BrowserPage.xaml">
|
<Page Include="BrowserPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Themes\Generic.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
|
@ -294,7 +298,6 @@
|
||||||
<ClCompile Include="Content\SpinningCubeRenderer.cpp" />
|
<ClCompile Include="Content\SpinningCubeRenderer.cpp" />
|
||||||
<ClCompile Include="ImmersiveMain.cpp" />
|
<ClCompile Include="ImmersiveMain.cpp" />
|
||||||
<ClCompile Include="ImmersiveView.cpp" />
|
<ClCompile Include="ImmersiveView.cpp" />
|
||||||
<ClCompile Include="OpenGLES.cpp" />
|
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -306,7 +309,9 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
<ClCompile Include="logs.cpp" />
|
<ClCompile Include="logs.cpp" />
|
||||||
<ClCompile Include="Servo.cpp" />
|
<ClCompile Include="ServoControl\OpenGLES.cpp" />
|
||||||
|
<ClCompile Include="ServoControl\Servo.cpp" />
|
||||||
|
<ClCompile Include="ServoControl\ServoControl.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Midl Include="App.idl">
|
<Midl Include="App.idl">
|
||||||
|
@ -315,6 +320,7 @@
|
||||||
<Midl Include="BrowserPage.idl">
|
<Midl Include="BrowserPage.idl">
|
||||||
<DependentUpon>BrowserPage.xaml</DependentUpon>
|
<DependentUpon>BrowserPage.xaml</DependentUpon>
|
||||||
</Midl>
|
</Midl>
|
||||||
|
<Midl Include="ServoControl\ServoControl.idl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
@ -352,4 +358,4 @@
|
||||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
<Error Condition="!Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.13\build\native\ANGLE.WindowsStore.Servo.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.Servo.2.1.13\build\native\ANGLE.WindowsStore.Servo.targets'))" />
|
<Error Condition="!Exists('..\packages\ANGLE.WindowsStore.Servo.2.1.13\build\native\ANGLE.WindowsStore.Servo.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.Servo.2.1.13\build\native\ANGLE.WindowsStore.Servo.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Midl Include="BrowserPage.idl" />
|
<Midl Include="BrowserPage.idl" />
|
||||||
<Midl Include="App.idl" />
|
<Midl Include="App.idl" />
|
||||||
|
<Midl Include="ServoControl\ServoControl.idl">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</Midl>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="pch.cpp" />
|
<ClCompile Include="pch.cpp" />
|
||||||
|
@ -10,8 +13,6 @@
|
||||||
<ClCompile Include="logs.cpp" />
|
<ClCompile Include="logs.cpp" />
|
||||||
<ClCompile Include="ImmersiveView.cpp" />
|
<ClCompile Include="ImmersiveView.cpp" />
|
||||||
<ClCompile Include="BrowserPage.cpp" />
|
<ClCompile Include="BrowserPage.cpp" />
|
||||||
<ClCompile Include="Servo.cpp" />
|
|
||||||
<ClCompile Include="OpenGLES.cpp" />
|
|
||||||
<ClCompile Include="App.cpp" />
|
<ClCompile Include="App.cpp" />
|
||||||
<ClCompile Include="Common\CameraResources.cpp">
|
<ClCompile Include="Common\CameraResources.cpp">
|
||||||
<Filter>Common</Filter>
|
<Filter>Common</Filter>
|
||||||
|
@ -26,14 +27,21 @@
|
||||||
<Filter>Content</Filter>
|
<Filter>Content</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="ImmersiveMain.cpp" />
|
<ClCompile Include="ImmersiveMain.cpp" />
|
||||||
|
<ClCompile Include="ServoControl\OpenGLES.cpp">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ServoControl\Servo.cpp">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ServoControl\ServoControl.cpp">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="logs.h" />
|
<ClInclude Include="logs.h" />
|
||||||
<ClInclude Include="ImmersiveView.h" />
|
<ClInclude Include="ImmersiveView.h" />
|
||||||
<ClInclude Include="BrowserPage.h" />
|
<ClInclude Include="BrowserPage.h" />
|
||||||
<ClInclude Include="Servo.h" />
|
|
||||||
<ClInclude Include="OpenGLES.h" />
|
|
||||||
<ClInclude Include="App.h" />
|
<ClInclude Include="App.h" />
|
||||||
<ClInclude Include="Common\CameraResources.h">
|
<ClInclude Include="Common\CameraResources.h">
|
||||||
<Filter>Common</Filter>
|
<Filter>Common</Filter>
|
||||||
|
@ -57,6 +65,15 @@
|
||||||
<Filter>Content</Filter>
|
<Filter>Content</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="ImmersiveMain.h" />
|
<ClInclude Include="ImmersiveMain.h" />
|
||||||
|
<ClInclude Include="ServoControl\OpenGLES.h">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ServoControl\Servo.h">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ServoControl\ServoControl.h">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="Assets\Wide310x150Logo.scale-200.png">
|
<Image Include="Assets\Wide310x150Logo.scale-200.png">
|
||||||
|
@ -191,12 +208,18 @@
|
||||||
<Filter Include="ReleaseARM64ServoDLLs">
|
<Filter Include="ReleaseARM64ServoDLLs">
|
||||||
<UniqueIdentifier>{384b4019-d076-4301-994d-a891969a3036}</UniqueIdentifier>
|
<UniqueIdentifier>{384b4019-d076-4301-994d-a891969a3036}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="ServoControl">
|
||||||
|
<UniqueIdentifier>{d21a959c-19d1-4a54-b942-692c27e5b3a6}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="PropertySheet.props" />
|
<None Include="PropertySheet.props" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Include="BrowserPage.xaml" />
|
<Page Include="BrowserPage.xaml" />
|
||||||
|
<Page Include="Themes\Generic.xaml">
|
||||||
|
<Filter>ServoControl</Filter>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<FxCompile Include="Content\GeometryShader.hlsl">
|
<FxCompile Include="Content\GeometryShader.hlsl">
|
||||||
|
@ -215,4 +238,4 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ApplicationDefinition Include="App.xaml" />
|
<ApplicationDefinition Include="App.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Servo.h"
|
#include "Servo.h"
|
||||||
|
|
||||||
namespace servo {
|
namespace winrt::servo {
|
||||||
|
|
||||||
void on_load_started() { sServo->Delegate().OnLoadStarted(); }
|
void on_load_started() { sServo->Delegate().OnServoLoadStarted(); }
|
||||||
void on_load_ended() { sServo->Delegate().OnLoadEnded(); }
|
void on_load_ended() { sServo->Delegate().OnServoLoadEnded(); }
|
||||||
void on_history_changed(bool back, bool forward) {
|
void on_history_changed(bool back, bool forward) {
|
||||||
sServo->Delegate().OnHistoryChanged(back, forward);
|
sServo->Delegate().OnServoHistoryChanged(back, forward);
|
||||||
}
|
}
|
||||||
void on_shutdown_complete() { sServo->Delegate().OnShutdownComplete(); }
|
void on_shutdown_complete() { sServo->Delegate().OnServoShutdownComplete(); }
|
||||||
void on_alert(const char *message) {
|
void on_alert(const char *message) {
|
||||||
sServo->Delegate().OnAlert(char2w(message));
|
sServo->Delegate().OnServoAlert(char2hstring(message));
|
||||||
}
|
}
|
||||||
void on_title_changed(const char *title) {
|
void on_title_changed(const char *title) {
|
||||||
sServo->Delegate().OnTitleChanged(char2w(title));
|
sServo->Delegate().OnServoTitleChanged(char2hstring(title));
|
||||||
}
|
}
|
||||||
void on_url_changed(const char *url) {
|
void on_url_changed(const char *url) {
|
||||||
sServo->Delegate().OnURLChanged(char2w(url));
|
sServo->Delegate().OnServoURLChanged(char2hstring(url));
|
||||||
}
|
}
|
||||||
void flush() { sServo->Delegate().Flush(); }
|
void flush() { sServo->Delegate().Flush(); }
|
||||||
void make_current() { sServo->Delegate().MakeCurrent(); }
|
void make_current() { sServo->Delegate().MakeCurrent(); }
|
||||||
void wakeup() { sServo->Delegate().WakeUp(); }
|
void wakeup() { sServo->Delegate().WakeUp(); }
|
||||||
bool on_allow_navigation(const char *url) {
|
bool on_allow_navigation(const char *url) {
|
||||||
return sServo->Delegate().OnAllowNavigation(char2w(url));
|
return sServo->Delegate().OnServoAllowNavigation(char2hstring(url));
|
||||||
};
|
};
|
||||||
void on_animating_changed(bool aAnimating) {
|
void on_animating_changed(bool aAnimating) {
|
||||||
sServo->Delegate().OnAnimatingChanged(aAnimating);
|
sServo->Delegate().OnServoAnimatingChanged(aAnimating);
|
||||||
}
|
}
|
||||||
|
|
||||||
Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
|
Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
|
||||||
|
@ -60,14 +60,14 @@ Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
|
||||||
|
|
||||||
Servo::~Servo() { sServo = nullptr; }
|
Servo::~Servo() { sServo = nullptr; }
|
||||||
|
|
||||||
std::wstring char2w(const char *c_str) {
|
winrt::hstring char2hstring(const char *c_str) {
|
||||||
|
// FIXME: any better way of doing this?
|
||||||
auto str = std::string(c_str);
|
auto str = std::string(c_str);
|
||||||
int size_needed =
|
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
|
||||||
std::wstring str2(size_needed, 0);
|
std::wstring str2(size_needed, 0);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0],
|
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0], size_needed);
|
||||||
size_needed);
|
winrt::hstring str3 {str2};
|
||||||
return str2;
|
return str3;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace servo
|
} // namespace servo
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace servo {
|
namespace winrt::servo {
|
||||||
|
|
||||||
namespace capi {
|
namespace capi {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -20,17 +21,17 @@ public:
|
||||||
// Called from any thread
|
// Called from any thread
|
||||||
virtual void WakeUp() = 0;
|
virtual void WakeUp() = 0;
|
||||||
// Called from GL thread
|
// Called from GL thread
|
||||||
virtual void OnLoadStarted() = 0;
|
virtual void OnServoLoadStarted() = 0;
|
||||||
virtual void OnLoadEnded() = 0;
|
virtual void OnServoLoadEnded() = 0;
|
||||||
virtual void OnHistoryChanged(bool, bool) = 0;
|
virtual void OnServoHistoryChanged(bool, bool) = 0;
|
||||||
virtual void OnShutdownComplete() = 0;
|
virtual void OnServoShutdownComplete() = 0;
|
||||||
virtual void OnTitleChanged(std::wstring) = 0;
|
virtual void OnServoTitleChanged(hstring) = 0;
|
||||||
virtual void OnAlert(std::wstring) = 0;
|
virtual void OnServoAlert(hstring) = 0;
|
||||||
virtual void OnURLChanged(std::wstring) = 0;
|
virtual void OnServoURLChanged(hstring) = 0;
|
||||||
|
virtual bool OnServoAllowNavigation(hstring) = 0;
|
||||||
|
virtual void OnServoAnimatingChanged(bool) = 0;
|
||||||
virtual void Flush() = 0;
|
virtual void Flush() = 0;
|
||||||
virtual void MakeCurrent() = 0;
|
virtual void MakeCurrent() = 0;
|
||||||
virtual bool OnAllowNavigation(std::wstring) = 0;
|
|
||||||
virtual void OnAnimatingChanged(bool) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~ServoDelegate(){};
|
virtual ~ServoDelegate(){};
|
||||||
|
@ -51,6 +52,14 @@ public:
|
||||||
void Click(float x, float y) { capi::click(x, y); }
|
void Click(float x, float y) { capi::click(x, y); }
|
||||||
void Reload() { capi::reload(); }
|
void Reload() { capi::reload(); }
|
||||||
void Stop() { capi::stop(); }
|
void Stop() { capi::stop(); }
|
||||||
|
void LoadUri(hstring uri) {
|
||||||
|
const wchar_t* wc = uri.c_str();
|
||||||
|
size_t size = uri.size() + 1;
|
||||||
|
char* str = new char[size];
|
||||||
|
size_t converted = 0;
|
||||||
|
wcstombs_s(&converted, str, size, wc, uri.size());
|
||||||
|
capi::load_uri(str);
|
||||||
|
}
|
||||||
void Scroll(float dx, float dy, float x, float y) {
|
void Scroll(float dx, float dy, float x, float y) {
|
||||||
capi::scroll(dx, dy, x, y);
|
capi::scroll(dx, dy, x, y);
|
||||||
}
|
}
|
||||||
|
@ -73,6 +82,6 @@ private:
|
||||||
// the Servo instance. See https://github.com/servo/servo/issues/22967
|
// the Servo instance. See https://github.com/servo/servo/issues/22967
|
||||||
static Servo *sServo = nullptr;
|
static Servo *sServo = nullptr;
|
||||||
|
|
||||||
std::wstring char2w(const char *c_str);
|
hstring char2hstring(const char *c_str);
|
||||||
|
|
||||||
} // namespace servo
|
} // namespace servo
|
257
support/hololens/ServoApp/ServoControl/ServoControl.cpp
Normal file
257
support/hololens/ServoApp/ServoControl/ServoControl.cpp
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
#include "pch.h"
|
||||||
|
#include "ServoControl.h"
|
||||||
|
#include "ServoControl.g.cpp"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace std::placeholders;
|
||||||
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
|
using namespace winrt::Windows::UI::Core;
|
||||||
|
using namespace winrt::Windows::Foundation;
|
||||||
|
using namespace concurrency;
|
||||||
|
using namespace winrt::servo;
|
||||||
|
|
||||||
|
namespace winrt::ServoApp::implementation {
|
||||||
|
|
||||||
|
ServoControl::ServoControl() {
|
||||||
|
DefaultStyleKey(winrt::box_value(L"ServoApp.ServoControl"));
|
||||||
|
Loaded(std::bind(&ServoControl::OnLoaded, this, _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::Shutdown() {
|
||||||
|
if (mServo != nullptr) {
|
||||||
|
if (!mLooping) {
|
||||||
|
// FIXME: this should not happen. In that case, we can't send the
|
||||||
|
// shutdown event to Servo.
|
||||||
|
} else {
|
||||||
|
RunOnGLThread([=] { mServo->RequestShutdown(); });
|
||||||
|
mLoopTask->wait();
|
||||||
|
mLoopTask.reset();
|
||||||
|
mServo.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
|
||||||
|
Panel().PointerReleased(
|
||||||
|
std::bind(&ServoControl::OnSurfaceClicked, this, _1, _2));
|
||||||
|
Panel().ManipulationDelta(
|
||||||
|
std::bind(&ServoControl::OnSurfaceManipulationDelta, this, _1, _2));
|
||||||
|
InitializeConditionVariable(&mGLCondVar);
|
||||||
|
InitializeCriticalSection(&mGLLock);
|
||||||
|
CreateRenderSurface();
|
||||||
|
StartRenderLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls::SwapChainPanel ServoControl::Panel() {
|
||||||
|
// FIXME: is there a better way of doing this?
|
||||||
|
return GetTemplateChild(L"swapChainPanel")
|
||||||
|
.as<Controls::SwapChainPanel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::CreateRenderSurface() {
|
||||||
|
if (mRenderSurface == EGL_NO_SURFACE) {
|
||||||
|
mRenderSurface = mOpenGLES.CreateSurface(Panel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::DestroyRenderSurface() {
|
||||||
|
mOpenGLES.DestroySurface(mRenderSurface);
|
||||||
|
mRenderSurface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::RecoverFromLostDevice() {
|
||||||
|
StopRenderLoop();
|
||||||
|
DestroyRenderSurface();
|
||||||
|
mOpenGLES.Reset();
|
||||||
|
CreateRenderSurface();
|
||||||
|
StartRenderLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnSurfaceManipulationDelta(
|
||||||
|
IInspectable const &, Input::ManipulationDeltaRoutedEventArgs const &e) {
|
||||||
|
auto x = e.Position().X;
|
||||||
|
auto y = e.Position().Y;
|
||||||
|
auto dx = e.Delta().Translation.X;
|
||||||
|
auto dy = e.Delta().Translation.Y;
|
||||||
|
RunOnGLThread([=] { mServo->Scroll(dx, dy, x, y); });
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnSurfaceClicked(IInspectable const &,
|
||||||
|
Input::PointerRoutedEventArgs const &e) {
|
||||||
|
auto coords = e.GetCurrentPoint(Panel());
|
||||||
|
auto x = coords.Position().X;
|
||||||
|
auto y = coords.Position().Y;
|
||||||
|
RunOnGLThread([=] { mServo->Click(x, y); });
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::GoBack() {
|
||||||
|
RunOnGLThread([=] { mServo->GoBack(); });
|
||||||
|
}
|
||||||
|
void ServoControl::GoForward() {
|
||||||
|
RunOnGLThread([=] { mServo->GoForward(); });
|
||||||
|
}
|
||||||
|
void ServoControl::Reload() {
|
||||||
|
RunOnGLThread([=] { mServo->Reload(); });
|
||||||
|
}
|
||||||
|
void ServoControl::Stop() {
|
||||||
|
RunOnGLThread([=] { mServo->Stop(); });
|
||||||
|
}
|
||||||
|
Uri ServoControl::LoadURIOrSearch(hstring input) {
|
||||||
|
auto uri = TryParseURI(input);
|
||||||
|
if (uri == std::nullopt) {
|
||||||
|
bool has_dot = wcsstr(input.c_str(), L".") != nullptr;
|
||||||
|
hstring input2 = L"https://" + input;
|
||||||
|
uri = TryParseURI(input2);
|
||||||
|
if (uri == std::nullopt || !has_dot) {
|
||||||
|
hstring input3 = L"https://duckduckgo.com/html/?q=" + Uri::EscapeComponent(input);
|
||||||
|
uri = TryParseURI(input3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto finalUri = uri.value();
|
||||||
|
RunOnGLThread([=] { mServo->LoadUri(finalUri.ToString()); });
|
||||||
|
return finalUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::RunOnGLThread(std::function<void()> task) {
|
||||||
|
EnterCriticalSection(&mGLLock);
|
||||||
|
mTasks.push_back(task);
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
WakeConditionVariable(&mGLCondVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** GL THREAD LOOP ****/
|
||||||
|
|
||||||
|
void ServoControl::Loop() {
|
||||||
|
log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId());
|
||||||
|
|
||||||
|
mOpenGLES.MakeCurrent(mRenderSurface);
|
||||||
|
|
||||||
|
EGLint panelWidth = 0;
|
||||||
|
EGLint panelHeight = 0;
|
||||||
|
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
|
||||||
|
glViewport(0, 0, panelWidth, panelHeight);
|
||||||
|
|
||||||
|
if (mServo == nullptr) {
|
||||||
|
log("Entering loop");
|
||||||
|
ServoDelegate *sd = static_cast<ServoDelegate *>(this);
|
||||||
|
mServo = std::make_unique<Servo>(panelWidth, panelHeight, *sd);
|
||||||
|
} else {
|
||||||
|
// FIXME: this will fail since create_task didn't pick the thread
|
||||||
|
// where Servo was running initially.
|
||||||
|
throw winrt::hresult_error(E_FAIL, L"Recovering loop unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
mServo->SetBatchMode(true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
EnterCriticalSection(&mGLLock);
|
||||||
|
while (mTasks.size() == 0 && !mAnimating && mLooping) {
|
||||||
|
SleepConditionVariableCS(&mGLCondVar, &mGLLock, INFINITE);
|
||||||
|
}
|
||||||
|
if (!mLooping) {
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (auto &&task : mTasks) {
|
||||||
|
task();
|
||||||
|
}
|
||||||
|
mTasks.clear();
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
mServo->PerformUpdates();
|
||||||
|
}
|
||||||
|
mServo->DeInit();
|
||||||
|
cancel_current_task();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::StartRenderLoop() {
|
||||||
|
if (mLooping) {
|
||||||
|
#if defined _DEBUG
|
||||||
|
throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
mLooping = true;
|
||||||
|
log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
|
||||||
|
auto task = Concurrency::create_task([=] { Loop(); });
|
||||||
|
mLoopTask = std::make_unique<Concurrency::task<void>>(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::StopRenderLoop() {
|
||||||
|
if (mLooping) {
|
||||||
|
EnterCriticalSection(&mGLLock);
|
||||||
|
mLooping = false;
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
WakeConditionVariable(&mGLCondVar);
|
||||||
|
mLoopTask->wait();
|
||||||
|
mLoopTask.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** SERVO CALLBACKS ****/
|
||||||
|
|
||||||
|
void ServoControl::OnServoLoadStarted() {
|
||||||
|
RunOnUIThread([=] { mOnLoadStartedEvent(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoLoadEnded() {
|
||||||
|
RunOnUIThread([=] { mOnLoadEndedEvent(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoHistoryChanged(bool back, bool forward) {
|
||||||
|
RunOnUIThread([=] { mOnHistoryChangedEvent(back, forward); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoShutdownComplete() {
|
||||||
|
EnterCriticalSection(&mGLLock);
|
||||||
|
mLooping = false;
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoAlert(hstring message) {
|
||||||
|
// FIXME: make this sync
|
||||||
|
RunOnUIThread([=] {
|
||||||
|
Windows::UI::Popups::MessageDialog msg{message};
|
||||||
|
msg.ShowAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoTitleChanged(hstring title) {
|
||||||
|
RunOnUIThread([=] { mOnTitleChangedEvent(*this, title); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoURLChanged(hstring url) {
|
||||||
|
RunOnUIThread([=] { mOnURLChangedEvent(*this, url); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::Flush() {
|
||||||
|
if (mOpenGLES.SwapBuffers(mRenderSurface) != GL_TRUE) {
|
||||||
|
// The call to eglSwapBuffers might not be successful (i.e. due to Device
|
||||||
|
// Lost) If the call fails, then we must reinitialize EGL and the GL
|
||||||
|
// resources.
|
||||||
|
RunOnUIThread([=] { RecoverFromLostDevice(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::MakeCurrent() { mOpenGLES.MakeCurrent(mRenderSurface); }
|
||||||
|
|
||||||
|
void ServoControl::WakeUp() {
|
||||||
|
RunOnGLThread([=] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServoControl::OnServoAllowNavigation(hstring) { return true; }
|
||||||
|
|
||||||
|
void ServoControl::OnServoAnimatingChanged(bool animating) {
|
||||||
|
EnterCriticalSection(&mGLLock);
|
||||||
|
mAnimating = animating;
|
||||||
|
LeaveCriticalSection(&mGLLock);
|
||||||
|
WakeConditionVariable(&mGLCondVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) {
|
||||||
|
Dispatcher().RunAsync(CoreDispatcherPriority::High, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::ServoApp::implementation
|
110
support/hololens/ServoApp/ServoControl/ServoControl.h
Normal file
110
support/hololens/ServoApp/ServoControl/ServoControl.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
#include "ServoControl.g.h"
|
||||||
|
#include "OpenGLES.h"
|
||||||
|
#include "Servo.h"
|
||||||
|
|
||||||
|
namespace winrt::ServoApp::implementation {
|
||||||
|
struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
|
|
||||||
|
ServoControl();
|
||||||
|
|
||||||
|
void GoBack();
|
||||||
|
void GoForward();
|
||||||
|
void Reload();
|
||||||
|
void Stop();
|
||||||
|
void Shutdown();
|
||||||
|
Windows::Foundation::Uri LoadURIOrSearch(hstring);
|
||||||
|
|
||||||
|
void OnLoaded(IInspectable const &, Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
|
||||||
|
winrt::event_token
|
||||||
|
OnURLChanged(Windows::Foundation::EventHandler<hstring> const &handler){
|
||||||
|
return mOnURLChangedEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnURLChanged(winrt::event_token const& token) noexcept { mOnURLChangedEvent.remove(token); }
|
||||||
|
|
||||||
|
winrt::event_token
|
||||||
|
OnTitleChanged(Windows::Foundation::EventHandler<hstring> const &handler){
|
||||||
|
return mOnTitleChangedEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnTitleChanged(winrt::event_token const& token) noexcept { mOnTitleChangedEvent.remove(token); }
|
||||||
|
|
||||||
|
winrt::event_token OnHistoryChanged(HistoryChangedDelegate const &handler){
|
||||||
|
return mOnHistoryChangedEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnHistoryChanged(winrt::event_token const& token) noexcept { mOnHistoryChangedEvent.remove(token); }
|
||||||
|
|
||||||
|
winrt::event_token OnLoadStarted(LoadStatusChangedDelegate const &handler){
|
||||||
|
return mOnLoadStartedEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnLoadStarted(winrt::event_token const& token) noexcept { mOnLoadStartedEvent.remove(token); }
|
||||||
|
|
||||||
|
winrt::event_token OnLoadEnded(LoadStatusChangedDelegate const &handler){
|
||||||
|
return mOnLoadEndedEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnLoadEnded(winrt::event_token const& token) noexcept { mOnLoadEndedEvent.remove(token); }
|
||||||
|
|
||||||
|
virtual void WakeUp();
|
||||||
|
virtual void OnServoLoadStarted();
|
||||||
|
virtual void OnServoLoadEnded();
|
||||||
|
virtual void OnServoHistoryChanged(bool, bool);
|
||||||
|
virtual void OnServoShutdownComplete();
|
||||||
|
virtual void OnServoTitleChanged(winrt::hstring);
|
||||||
|
virtual void OnServoAlert(winrt::hstring);
|
||||||
|
virtual void OnServoURLChanged(winrt::hstring);
|
||||||
|
virtual void Flush();
|
||||||
|
virtual void MakeCurrent();
|
||||||
|
virtual bool OnServoAllowNavigation(winrt::hstring);
|
||||||
|
virtual void OnServoAnimatingChanged(bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnURLChangedEvent;
|
||||||
|
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnTitleChangedEvent;
|
||||||
|
winrt::event<HistoryChangedDelegate> mOnHistoryChangedEvent;
|
||||||
|
winrt::event<LoadStatusChangedDelegate> mOnLoadStartedEvent;
|
||||||
|
winrt::event<LoadStatusChangedDelegate> mOnLoadEndedEvent;
|
||||||
|
|
||||||
|
Windows::UI::Xaml::Controls::SwapChainPanel ServoControl::Panel();
|
||||||
|
void CreateRenderSurface();
|
||||||
|
void DestroyRenderSurface();
|
||||||
|
void RecoverFromLostDevice();
|
||||||
|
|
||||||
|
void StartRenderLoop();
|
||||||
|
void StopRenderLoop();
|
||||||
|
void Loop();
|
||||||
|
|
||||||
|
std::optional<Windows::Foundation::Uri> TryParseURI(hstring input) {
|
||||||
|
try {
|
||||||
|
return Windows::Foundation::Uri(input);
|
||||||
|
} catch (hresult_invalid_argument const &e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OnSurfaceClicked(IInspectable const &,
|
||||||
|
Windows::UI::Xaml::Input::PointerRoutedEventArgs const &);
|
||||||
|
|
||||||
|
void OnSurfaceManipulationDelta(
|
||||||
|
IInspectable const &,
|
||||||
|
Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs const &e);
|
||||||
|
|
||||||
|
template <typename Callable> void RunOnUIThread(Callable);
|
||||||
|
void RunOnGLThread(std::function<void()>);
|
||||||
|
|
||||||
|
std::unique_ptr<servo::Servo> mServo;
|
||||||
|
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
||||||
|
OpenGLES mOpenGLES;
|
||||||
|
bool mAnimating = false;
|
||||||
|
bool mLooping = false;
|
||||||
|
std::vector<std::function<void()>> mTasks;
|
||||||
|
CRITICAL_SECTION mGLLock;
|
||||||
|
CONDITION_VARIABLE mGLCondVar;
|
||||||
|
std::unique_ptr<Concurrency::task<void>> mLoopTask;
|
||||||
|
};
|
||||||
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
||||||
|
namespace winrt::ServoApp::factory_implementation {
|
||||||
|
struct ServoControl
|
||||||
|
: ServoControlT<ServoControl, implementation::ServoControl> {};
|
||||||
|
} // namespace winrt::ServoApp::factory_implementation
|
20
support/hololens/ServoApp/ServoControl/ServoControl.idl
Normal file
20
support/hololens/ServoApp/ServoControl/ServoControl.idl
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
namespace ServoApp {
|
||||||
|
|
||||||
|
delegate void LoadStatusChangedDelegate();
|
||||||
|
delegate void HistoryChangedDelegate(Boolean back, Boolean forward);
|
||||||
|
|
||||||
|
runtimeclass ServoControl : Windows.UI.Xaml.Controls.Control {
|
||||||
|
ServoControl();
|
||||||
|
void GoBack();
|
||||||
|
void GoForward();
|
||||||
|
void Reload();
|
||||||
|
void Stop();
|
||||||
|
Windows.Foundation.Uri LoadURIOrSearch(String url);
|
||||||
|
void Shutdown();
|
||||||
|
event LoadStatusChangedDelegate OnLoadStarted;
|
||||||
|
event LoadStatusChangedDelegate OnLoadEnded;
|
||||||
|
event HistoryChangedDelegate OnHistoryChanged;
|
||||||
|
event Windows.Foundation.EventHandler<String> OnTitleChanged;
|
||||||
|
event Windows.Foundation.EventHandler<String> OnURLChanged;
|
||||||
|
}
|
||||||
|
} // namespace ServoApp
|
19
support/hololens/ServoApp/Themes/Generic.xaml
Normal file
19
support/hololens/ServoApp/Themes/Generic.xaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!-- \Themes\Generic.xaml -->
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:ServoApp">
|
||||||
|
|
||||||
|
<Style TargetType="local:ServoControl" >
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="local:ServoControl">
|
||||||
|
<Grid>
|
||||||
|
<SwapChainPanel x:Name="swapChainPanel" MinHeight="200" MinWidth="200" ManipulationMode="All">
|
||||||
|
</SwapChainPanel>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
Loading…
Add table
Add a link
Reference in a new issue