aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-07-25 04:39:50 -0400
committerGitHub <noreply@github.com>2019-07-25 04:39:50 -0400
commit3e90b93b83de03afed0712b7090be99e0193883d (patch)
treecbd5f39e1e006256f323dbbb2d389860f0d5f1ab
parent9f6d134957ffeb27aa33b4e5fcc8b92b96dfbc0f (diff)
parentd0436f16b6abd19306e65de15967b49331d64f13 (diff)
downloadservo-3e90b93b83de03afed0712b7090be99e0193883d.tar.gz
servo-3e90b93b83de03afed0712b7090be99e0193883d.zip
Auto merge of #23845 - paulrouget:cleanup, r=jdm
[hololens] More events, remove most of the statics, better shutdown Depends on #23831 - Buttons are greyed out when necessary - Reload, Stop, Back and Fwd are properly bound - Servo.cpp rewritten in a much cleaner way - Removed most of the statics - Improved (but not full) shutdown <!-- 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/23845) <!-- Reviewable:end -->
-rw-r--r--support/hololens/ServoApp/App.cpp7
-rw-r--r--support/hololens/ServoApp/BrowserPage.cpp332
-rw-r--r--support/hololens/ServoApp/BrowserPage.h34
-rw-r--r--support/hololens/ServoApp/BrowserPage.xaml6
-rw-r--r--support/hololens/ServoApp/Common/DeviceResources.h3
-rw-r--r--support/hololens/ServoApp/Servo.cpp100
-rw-r--r--support/hololens/ServoApp/Servo.h78
-rw-r--r--support/hololens/ServoApp/pch.h1
8 files changed, 343 insertions, 218 deletions
diff --git a/support/hololens/ServoApp/App.cpp b/support/hololens/ServoApp/App.cpp
index e373f05210d..9f6495c49e1 100644
--- a/support/hololens/ServoApp/App.cpp
+++ b/support/hololens/ServoApp/App.cpp
@@ -63,7 +63,12 @@ void App::OnLaunched(LaunchActivatedEventArgs const &e) {
}
void App::OnSuspending([[maybe_unused]] IInspectable const &sender,
- [[maybe_unused]] SuspendingEventArgs const &e) {}
+ [[maybe_unused]] SuspendingEventArgs const &e) {
+ auto content = Window::Current().Content();
+ Frame rootFrame = content.try_as<Frame>();
+ auto page = rootFrame.Content().try_as<BrowserPage>();
+ page->Shutdown();
+}
void App::OnNavigationFailed(IInspectable const &,
NavigationFailedEventArgs const &e) {
diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp
index 2c2c6c6420b..c6fe3d9b969 100644
--- a/support/hololens/ServoApp/BrowserPage.cpp
+++ b/support/hololens/ServoApp/BrowserPage.cpp
@@ -16,96 +16,59 @@ using namespace winrt::Windows::UI::ViewManagement;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Graphics::Holographic;
using namespace concurrency;
-
-static char sWakeupEvent[] = "SIGNAL_WAKEUP";
+using namespace servo;
namespace winrt::ServoApp::implementation {
BrowserPage::BrowserPage() {
- InitializeComponent();
log("BrowserPage::BrowserPage()");
+ InitializeComponent();
Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2));
Window::Current().CoreWindow().VisibilityChanged(
std::bind(&BrowserPage::OnVisibilityChanged, this, _1, _2));
}
+void BrowserPage::Shutdown() {
+ log("BrowserPage::Shutdown()");
+
+ if (mServo != nullptr) {
+ if (!IsLoopRunning()) {
+ // FIXME: this should not happen. In that case, we can't send the
+ // shutdown event to Servo.
+ } else {
+ HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sShutdownEvent);
+ SendEventToServo({{Event::SHUTDOWN}});
+ log("Waiting for Servo to shutdown");
+ ::WaitForSingleObject(hEvent, INFINITE);
+ StopRenderLoop();
+ mServo.reset(); // will call servo::deinit
+ }
+ }
+}
+
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::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;
- Event event = {{Event::SCROLL}};
- event.scrollCoords = {dx, dy, x, y};
- SendEventToServo(event);
- 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;
-
- SendEventToServo({{Event::CLICK}, {x, y}});
-
- e.Handled(true);
-}
-
-void BrowserPage::SendEventToServo(Event event) {
- mEventsMutex.lock();
- mEvents.push_back(event);
- mEventsMutex.unlock();
- Servo::sWakeUp();
-}
-
-void BrowserPage::OnBackButtonClicked(IInspectable const &,
- RoutedEventArgs const &) {
- SendEventToServo({{Event::BACK}});
-}
-
-void BrowserPage::OnForwardButtonClicked(IInspectable const &,
- RoutedEventArgs const &) {
- SendEventToServo({{Event::FORWARD}});
-}
-void BrowserPage::OnImmersiveButtonClicked(IInspectable const &,
- RoutedEventArgs const &) {
- if (HolographicSpace::IsAvailable()) {
- log("Holographic space available");
- auto v =
- winrt::Windows::ApplicationModel::Core::CoreApplication::CreateNewView(
- mImmersiveViewSource);
- auto parentId = ApplicationView::GetForCurrentView().Id();
- v.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [=]() {
- auto winId = ApplicationView::GetForCurrentView().Id();
- ApplicationViewSwitcher::SwitchAsync(winId, parentId);
- log("Immersive view started");
- });
- } else {
- log("Holographic space not available");
- }
-}
-
void BrowserPage::OnVisibilityChanged(CoreWindow const &,
VisibilityChangedEventArgs const &args) {
auto visible = args.Visible();
- if (visible && !IsLoopRunning()) {
- StartRenderLoop();
- }
- if (!visible && IsLoopRunning()) {
- StopRenderLoop();
- }
+
+ // 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 && !IsLoopRunning()) {
+ // StartRenderLoop();
+ //}
+ // if (!visible && IsLoopRunning()) {
+ // StopRenderLoop();
+ //}
}
void BrowserPage::CreateRenderSurface() {
@@ -127,6 +90,8 @@ void BrowserPage::RecoverFromLostDevice() {
StartRenderLoop();
}
+/**** GL THREAD LOOP ****/
+
bool BrowserPage::IsLoopRunning() {
return mLoopTask != nullptr && !mLoopTask->is_done();
}
@@ -136,65 +101,35 @@ void BrowserPage::Loop(cancellation_token cancel) {
HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sWakeupEvent);
- Servo::sOnAlert = [=](std::wstring message) {
- // FIXME: make this sync
- swapChainPanel().Dispatcher().RunAsync(
- Windows::UI::Core::CoreDispatcherPriority::High, [=]() {
- Windows::UI::Popups::MessageDialog msg{message};
- msg.ShowAsync();
- });
- };
-
- Servo::sOnTitleChanged = [=](std::wstring title) {
- swapChainPanel().Dispatcher().RunAsync(CoreDispatcherPriority::High, [=]() {
- ApplicationView::GetForCurrentView().Title(title);
- });
- };
-
- Servo::sOnURLChanged = [=](std::wstring url) {
- swapChainPanel().Dispatcher().RunAsync(CoreDispatcherPriority::High,
- [=]() { urlTextbox().Text(url); });
- };
-
- Servo::sMakeCurrent = [=]() {
- /* EGLint panelWidth = 0; */
- /* EGLint panelHeight = 0; */
- /* mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth,
- * &panelHeight); */
- /* glViewport(0, 0, panelWidth, panelHeight); */
- /* mServo->SetSize(panelWidth, panelHeight); */
- mOpenGLES.MakeCurrent(mRenderSurface);
- };
-
- Servo::sFlush = [=]() {
- 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.
- swapChainPanel().Dispatcher().RunAsync(
- CoreDispatcherPriority::High, [this]() { RecoverFromLostDevice(); });
- }
- };
-
mOpenGLES.MakeCurrent(mRenderSurface);
EGLint panelWidth = 0;
EGLint panelHeight = 0;
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
glViewport(0, 0, panelWidth, panelHeight);
- mServo = std::make_unique<Servo>(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);
- // FIXME: ^ this should be necessary as call perform_update
+ // FIXME: ^ this should be necessary as we call perform_update
// ourself. But enabling batch mode will make clicking a link
// not working because during the click, this thread is not
// waiting on the hEvent object. See the "wakeup" comment.
+ log("Entering loop");
while (!cancel.is_canceled()) {
- // Block until Servo::sWakeUp is called.
- // Or run full speed if animating (see on_animating_changed),
- // it will endup blocking on SwapBuffers to limit rendering to 60FPS
- if (!Servo::sAnimating) {
+ // Block until wakeup is called.
+ // Or run full speed if animating (see OnAnimatingChanged),
+ // it will endup blocking on Flush to limit rendering to 60FPS
+ if (!mAnimating) {
::WaitForSingleObject(hEvent, INFINITE);
}
mEventsMutex.lock();
@@ -216,31 +151,36 @@ void BrowserPage::Loop(cancellation_token cancel) {
case Event::BACK:
mServo->GoBack();
break;
+ case Event::RELOAD:
+ mServo->Reload();
+ break;
+ case Event::STOP:
+ mServo->Stop();
+ break;
+ case Event::SHUTDOWN:
+ log("Requesting Servo to shutdown");
+ mServo->RequestShutdown();
+ break;
}
}
mEvents.clear();
mEventsMutex.unlock();
mServo->PerformUpdates();
}
+ log("Leaving loop");
cancel_current_task();
-}
+} // namespace winrt::ServoApp::implementation
void BrowserPage::StartRenderLoop() {
if (IsLoopRunning()) {
+#if defined _DEBUG
+ throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
+#else
return;
+#endif
}
-
- auto token = mLoopCancel.get_token();
-
- Servo::sWakeUp = []() {
- // FIXME: this won't work if it's triggered while the thread is not
- // waiting. We need a better looping logic.
- HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sWakeupEvent);
- ::SetEvent(hEvent);
- };
-
log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
-
+ auto token = mLoopCancel.get_token();
mLoopTask = std::make_unique<Concurrency::task<void>>(
Concurrency::create_task([=] { Loop(token); }, token));
}
@@ -253,4 +193,144 @@ void BrowserPage::StopRenderLoop() {
}
}
+/**** SERVO CALLBACKS ****/
+
+void BrowserPage::OnLoadStarted() {
+ RunOnUIThread([=] {
+ reloadButton().IsEnabled(false);
+ stopButton().IsEnabled(true);
+ });
+}
+
+void BrowserPage::OnLoadEnded() {
+ RunOnUIThread([=] {
+ reloadButton().IsEnabled(true);
+ stopButton().IsEnabled(false);
+ });
+}
+
+void BrowserPage::OnHistoryChanged(bool back, bool forward) {
+ RunOnUIThread([=] {
+ backButton().IsEnabled(back);
+ forwardButton().IsEnabled(forward);
+ });
+}
+
+void BrowserPage::OnShutdownComplete() {
+ log("Servo notified ShutdownComplete");
+ HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sShutdownEvent);
+ ::SetEvent(hEvent);
+}
+
+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() {
+ // FIXME: this won't work if it's triggered while the thread is not
+ // waiting. We need a better looping logic.
+ HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sWakeupEvent);
+ ::SetEvent(hEvent);
+}
+
+bool BrowserPage::OnAllowNavigation(std::wstring) { return true; }
+
+void BrowserPage::OnAnimatingChanged(bool animating) { mAnimating = animating; }
+
+template <typename Callable> void BrowserPage::RunOnUIThread(Callable cb) {
+ swapChainPanel().Dispatcher().RunAsync(
+ Windows::UI::Core::CoreDispatcherPriority::High, cb);
+}
+
+/**** USER INTERACTIONS WITH UI ****/
+
+void BrowserPage::OnBackButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ SendEventToServo({{Event::BACK}});
+}
+
+void BrowserPage::OnForwardButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ SendEventToServo({{Event::FORWARD}});
+}
+
+void BrowserPage::OnReloadButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ SendEventToServo({{Event::RELOAD}});
+}
+
+void BrowserPage::OnStopButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ SendEventToServo({{Event::STOP}});
+}
+
+void BrowserPage::OnImmersiveButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ if (HolographicSpace::IsAvailable()) {
+ log("Holographic space available");
+ auto v =
+ winrt::Windows::ApplicationModel::Core::CoreApplication::CreateNewView(
+ mImmersiveViewSource);
+ auto parentId = ApplicationView::GetForCurrentView().Id();
+ v.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [=] {
+ auto winId = ApplicationView::GetForCurrentView().Id();
+ ApplicationViewSwitcher::SwitchAsync(winId, parentId);
+ log("Immersive view started");
+ });
+ } else {
+ log("Holographic space not available");
+ }
+}
+
+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;
+ Event event = {{Event::SCROLL}};
+ event.scrollCoords = {dx, dy, x, y};
+ SendEventToServo(event);
+ 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;
+ SendEventToServo({{Event::CLICK}, {x, y}});
+ e.Handled(true);
+}
+
+void BrowserPage::SendEventToServo(Event event) {
+ mEventsMutex.lock();
+ mEvents.push_back(event);
+ mEventsMutex.unlock();
+ WakeUp();
+}
+
} // namespace winrt::ServoApp::implementation
diff --git a/support/hololens/ServoApp/BrowserPage.h b/support/hololens/ServoApp/BrowserPage.h
index 4eca25d363a..efa27ea4215 100644
--- a/support/hololens/ServoApp/BrowserPage.h
+++ b/support/hololens/ServoApp/BrowserPage.h
@@ -11,13 +11,17 @@
namespace winrt::ServoApp::implementation {
+static char sWakeupEvent[] = "SIGNAL_WAKEUP";
+static char sShutdownEvent[] = "SIGNAL_SHUTDOWN";
+
struct Event {
- enum { CLICK, SCROLL, BACK, FORWARD } type;
+ enum { CLICK, SCROLL, BACK, FORWARD, RELOAD, STOP, SHUTDOWN } type;
std::tuple<float, float> clickCoords;
std::tuple<float, float, float, float> scrollCoords;
};
-struct BrowserPage : BrowserPageT<BrowserPage> {
+struct BrowserPage : BrowserPageT<BrowserPage>,
+ public servo::ServoDelegate {
public:
BrowserPage();
@@ -27,7 +31,10 @@ public:
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
OnSurfaceClicked(Windows::Foundation::IInspectable const &,
Windows::UI::Xaml::Input::PointerRoutedEventArgs const &);
@@ -36,13 +43,28 @@ public:
IInspectable const &,
Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs const &e);
+ template <typename Callable> void RunOnUIThread(Callable);
+ 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:
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();
@@ -56,13 +78,15 @@ private:
std::unique_ptr<Concurrency::task<void>> mLoopTask;
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
EGLSurface mRenderSurface{EGL_NO_SURFACE};
- std::unique_ptr<Servo> mServo;
+ std::unique_ptr<servo::Servo> mServo;
void BrowserPage::SendEventToServo(Event event);
std::vector<Event> mEvents;
std::mutex mEventsMutex;
OpenGLES mOpenGLES; // FIXME: shared pointer
+
+ bool mAnimating;
};
} // namespace winrt::ServoApp::implementation
diff --git a/support/hololens/ServoApp/BrowserPage.xaml b/support/hololens/ServoApp/BrowserPage.xaml
index 4247c9a1f68..f6e6e227318 100644
--- a/support/hololens/ServoApp/BrowserPage.xaml
+++ b/support/hololens/ServoApp/BrowserPage.xaml
@@ -20,8 +20,10 @@
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
- <Button Content="Back" Click="OnBackButtonClicked"/>
- <Button Content="Forward" Click="OnForwardButtonClicked"/>
+ <Button x:Name="backButton" IsEnabled="false" Content="Back" Click="OnBackButtonClicked"/>
+ <Button x:Name="forwardButton" IsEnabled="false" Content="Forward" Click="OnForwardButtonClicked"/>
+ <Button x:Name="reloadButton" IsEnabled="false" Content="reload" Click="OnReloadButtonClicked"/>
+ <Button x:Name="stopButton" IsEnabled="false" Content="stop" Click="OnStopButtonClicked"/>
</StackPanel>
<TextBox Text="" AcceptsReturn="True" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" IsReadOnly="True"/>
<StackPanel Orientation="Horizontal" Grid.Column="2">
diff --git a/support/hololens/ServoApp/Common/DeviceResources.h b/support/hololens/ServoApp/Common/DeviceResources.h
index ff0248b221d..f4bb4a0030f 100644
--- a/support/hololens/ServoApp/Common/DeviceResources.h
+++ b/support/hololens/ServoApp/Common/DeviceResources.h
@@ -1,5 +1,4 @@
-
-#pragma once
+#pragma once
#include "CameraResources.h"
diff --git a/support/hololens/ServoApp/Servo.cpp b/support/hololens/ServoApp/Servo.cpp
index b262d420819..4283b66bc11 100644
--- a/support/hololens/ServoApp/Servo.cpp
+++ b/support/hololens/ServoApp/Servo.cpp
@@ -1,55 +1,38 @@
#include "pch.h"
#include "Servo.h"
-void on_load_started() {}
-void on_load_ended() {}
-void on_history_changed(bool, bool) {}
-void on_shutdown_complete() {}
+// FIXME: rename mozilla to something else
+namespace servo {
-std::function<void()> Servo::sFlush = []() {};
-std::function<void()> Servo::sMakeCurrent = []() {};
-std::function<void()> Servo::sWakeUp = []() {};
-std::function<void(std::wstring const &)> Servo::sOnAlert =
- [](std::wstring const &) {};
-std::function<void(std::wstring const &)> Servo::sOnTitleChanged =
- [](std::wstring const &) {};
-std::function<void(std::wstring const &)> Servo::sOnURLChanged =
- [](std::wstring const &) {};
-
-bool Servo::sAnimating = false;
-
-std::wstring char2w(const char *c_str) {
- auto str = std::string(c_str);
- int size_needed =
- MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
- std::wstring str2(size_needed, 0);
- MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0],
- size_needed);
- return str2;
+void on_load_started() { sServo->Delegate().OnLoadStarted(); }
+void on_load_ended() { sServo->Delegate().OnLoadEnded(); }
+void on_history_changed(bool back, bool forward) {
+ sServo->Delegate().OnHistoryChanged(back, forward);
+}
+void on_shutdown_complete() { sServo->Delegate().OnShutdownComplete(); }
+void on_alert(const char *message) {
+ sServo->Delegate().OnAlert(char2w(message));
}
-
-void on_alert(const char *message) { Servo::sOnAlert(char2w(message)); }
-
void on_title_changed(const char *title) {
- Servo::sOnTitleChanged(char2w(title));
+ sServo->Delegate().OnTitleChanged(char2w(title));
+}
+void on_url_changed(const char *url) {
+ sServo->Delegate().OnURLChanged(char2w(url));
+}
+void flush() { sServo->Delegate().Flush(); }
+void make_current() { sServo->Delegate().MakeCurrent(); }
+void wakeup() { sServo->Delegate().WakeUp(); }
+bool on_allow_navigation(const char *url) {
+ return sServo->Delegate().OnAllowNavigation(char2w(url));
+};
+void on_animating_changed(bool aAnimating) {
+ sServo->Delegate().OnAnimatingChanged(aAnimating);
}
-void on_url_changed(const char *url) { Servo::sOnURLChanged(char2w(url)); }
-
-void flush() { Servo::sFlush(); }
-
-void make_current() { Servo::sMakeCurrent(); }
-
-void wakeup() { Servo::sWakeUp(); }
-
-bool on_allow_navigation(const char *url) { return true; };
-
-void on_animating_changed(bool aAnimating) { Servo::sAnimating = aAnimating; }
-
-Servo::Servo(GLsizei width, GLsizei height)
- : mAnimating(false), mWindowHeight(height), mWindowWidth(width) {
+Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
+ : mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
- CInitOptions o;
+ capi::CInitOptions o;
o.args = NULL;
o.url = "https://servo.org";
o.width = mWindowWidth;
@@ -58,7 +41,9 @@ Servo::Servo(GLsizei width, GLsizei height)
o.enable_subpixel_text_antialiasing = false;
o.vr_pointer = NULL;
- CHostCallbacks c;
+ sServo = this; // FIXME;
+
+ capi::CHostCallbacks c;
c.flush = &flush;
c.make_current = &make_current;
c.on_alert = &on_alert;
@@ -74,23 +59,16 @@ Servo::Servo(GLsizei width, GLsizei height)
init_with_egl(o, &wakeup, c);
}
-Servo::~Servo() { deinit(); }
-
-void Servo::PerformUpdates() { perform_updates(); }
-
-void Servo::SetBatchMode(bool mode) { set_batch_mode(mode); }
-
-void Servo::GoForward() { go_forward(); }
-
-void Servo::GoBack() { go_back(); }
+Servo::~Servo() { capi::deinit(); }
-void Servo::SetSize(GLsizei width, GLsizei height) {
- if (width != mWindowWidth || height != mWindowHeight) {
- mWindowWidth = width;
- mWindowHeight = height;
- resize(mWindowWidth, mWindowHeight);
- }
+std::wstring char2w(const char *c_str) {
+ auto str = std::string(c_str);
+ int size_needed =
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+ std::wstring str2(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0],
+ size_needed);
+ return str2;
}
-void Servo::Click(float x, float y) { click(x, y); }
-void Servo::Scroll(float dx, float dy, float x, float y) { scroll(dx, dy, x, y); }
+} // namespace mozilla
diff --git a/support/hololens/ServoApp/Servo.h b/support/hololens/ServoApp/Servo.h
index 2772d5ea20b..17f283cdf56 100644
--- a/support/hololens/ServoApp/Servo.h
+++ b/support/hololens/ServoApp/Servo.h
@@ -5,37 +5,73 @@
#pragma once
#include "pch.h"
+#include "logs.h"
+namespace servo {
+
+namespace capi {
extern "C" {
#include <simpleservo.h>
}
+} // namespace capi
+
+class ServoDelegate {
+public:
+ // Called from any thread
+ virtual void WakeUp() = 0;
+ // Called from GL thread
+ virtual void OnLoadStarted() = 0;
+ virtual void OnLoadEnded() = 0;
+ virtual void OnHistoryChanged(bool, bool) = 0;
+ virtual void OnShutdownComplete() = 0;
+ virtual void OnTitleChanged(std::wstring) = 0;
+ virtual void OnAlert(std::wstring) = 0;
+ virtual void OnURLChanged(std::wstring) = 0;
+ virtual void Flush() = 0;
+ virtual void MakeCurrent() = 0;
+ virtual bool OnAllowNavigation(std::wstring) = 0;
+ virtual void OnAnimatingChanged(bool) = 0;
+
+protected:
+ virtual ~ServoDelegate(){log("A1");};
+};
class Servo {
public:
- Servo(GLsizei width, GLsizei height);
+ Servo(GLsizei, GLsizei, ServoDelegate &);
~Servo();
- void PerformUpdates();
- void Click(float, float);
- void Scroll(float dx, float dy, float x, float y);
- void SetSize(GLsizei width, GLsizei height);
- void SetBatchMode(bool);
- void GoBack();
- void GoForward();
-
- // Static lambas called by Servo callbacks.
-
- // Will be called from any thead
- static std::function<void()> sWakeUp;
- // Will be called from GL thread
- static std::function<void()> sFlush;
- static std::function<void()> sMakeCurrent;
- static std::function<void(std::wstring const &)> sOnAlert;
- static std::function<void(std::wstring const &)> sOnTitleChanged;
- static std::function<void(std::wstring const &)> sOnURLChanged;
- static bool sAnimating;
+ ServoDelegate &Delegate() { return mDelegate; }
+
+ void PerformUpdates() { capi::perform_updates(); }
+ 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 Reload() { capi::reload(); }
+ void Stop() { capi::stop(); }
+ void Scroll(float dx, float dy, float x, float y) {
+ capi::scroll(dx, dy, x, y);
+ }
+ void SetSize(GLsizei width, GLsizei height) {
+ if (width != mWindowWidth || height != mWindowHeight) {
+ mWindowWidth = width;
+ mWindowHeight = height;
+ capi::resize(mWindowWidth, mWindowHeight);
+ }
+ }
private:
+ ServoDelegate &mDelegate;
GLsizei mWindowWidth;
GLsizei mWindowHeight;
- bool mAnimating;
};
+
+// This is sad. We need a static pointer to Servo because we use function
+// pointer as callback in Servo, and these functions need a way to get
+// the Servo instance. See https://github.com/servo/servo/issues/22967
+static Servo *sServo = nullptr;
+
+std::wstring char2w(const char *c_str);
+
+} // namespace servo
diff --git a/support/hololens/ServoApp/pch.h b/support/hololens/ServoApp/pch.h
index c8689fab90e..0b8e6047454 100644
--- a/support/hololens/ServoApp/pch.h
+++ b/support/hololens/ServoApp/pch.h
@@ -1,5 +1,6 @@
#pragma once
+#include <functional>
#include <future>
#include <hstring.h>
#include <map>