mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
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 -->
This commit is contained in:
commit
3e90b93b83
8 changed files with 342 additions and 217 deletions
|
@ -63,7 +63,12 @@ void App::OnLaunched(LaunchActivatedEventArgs const &e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::OnSuspending([[maybe_unused]] IInspectable const &sender,
|
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 &,
|
void App::OnNavigationFailed(IInspectable const &,
|
||||||
NavigationFailedEventArgs const &e) {
|
NavigationFailedEventArgs const &e) {
|
||||||
|
|
|
@ -16,96 +16,59 @@ using namespace winrt::Windows::UI::ViewManagement;
|
||||||
using namespace winrt::Windows::Foundation;
|
using namespace winrt::Windows::Foundation;
|
||||||
using namespace winrt::Windows::Graphics::Holographic;
|
using namespace winrt::Windows::Graphics::Holographic;
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
|
using namespace servo;
|
||||||
static char sWakeupEvent[] = "SIGNAL_WAKEUP";
|
|
||||||
|
|
||||||
namespace winrt::ServoApp::implementation {
|
namespace winrt::ServoApp::implementation {
|
||||||
BrowserPage::BrowserPage() {
|
BrowserPage::BrowserPage() {
|
||||||
InitializeComponent();
|
|
||||||
log("BrowserPage::BrowserPage()");
|
log("BrowserPage::BrowserPage()");
|
||||||
|
InitializeComponent();
|
||||||
Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2));
|
Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2));
|
||||||
Window::Current().CoreWindow().VisibilityChanged(
|
Window::Current().CoreWindow().VisibilityChanged(
|
||||||
std::bind(&BrowserPage::OnVisibilityChanged, this, _1, _2));
|
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 &) {
|
void BrowserPage::OnPageLoaded(IInspectable const &, RoutedEventArgs const &) {
|
||||||
log("BrowserPage::OnPageLoaded()");
|
log("BrowserPage::OnPageLoaded()");
|
||||||
CreateRenderSurface();
|
CreateRenderSurface();
|
||||||
StartRenderLoop();
|
StartRenderLoop();
|
||||||
|
|
||||||
swapChainPanel().PointerReleased(
|
swapChainPanel().PointerReleased(
|
||||||
std::bind(&BrowserPage::OnSurfaceClicked, this, _1, _2));
|
std::bind(&BrowserPage::OnSurfaceClicked, this, _1, _2));
|
||||||
|
|
||||||
swapChainPanel().ManipulationDelta(
|
swapChainPanel().ManipulationDelta(
|
||||||
std::bind(&BrowserPage::OnSurfaceManipulationDelta, this, _1, _2));
|
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 &,
|
void BrowserPage::OnVisibilityChanged(CoreWindow const &,
|
||||||
VisibilityChangedEventArgs const &args) {
|
VisibilityChangedEventArgs const &args) {
|
||||||
auto visible = args.Visible();
|
auto visible = args.Visible();
|
||||||
if (visible && !IsLoopRunning()) {
|
|
||||||
StartRenderLoop();
|
// 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
|
||||||
if (!visible && IsLoopRunning()) {
|
// Loop())
|
||||||
StopRenderLoop();
|
|
||||||
}
|
// if (visible && !IsLoopRunning()) {
|
||||||
|
// StartRenderLoop();
|
||||||
|
//}
|
||||||
|
// if (!visible && IsLoopRunning()) {
|
||||||
|
// StopRenderLoop();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::CreateRenderSurface() {
|
void BrowserPage::CreateRenderSurface() {
|
||||||
|
@ -127,6 +90,8 @@ void BrowserPage::RecoverFromLostDevice() {
|
||||||
StartRenderLoop();
|
StartRenderLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**** GL THREAD LOOP ****/
|
||||||
|
|
||||||
bool BrowserPage::IsLoopRunning() {
|
bool BrowserPage::IsLoopRunning() {
|
||||||
return mLoopTask != nullptr && !mLoopTask->is_done();
|
return mLoopTask != nullptr && !mLoopTask->is_done();
|
||||||
}
|
}
|
||||||
|
@ -136,65 +101,35 @@ void BrowserPage::Loop(cancellation_token cancel) {
|
||||||
|
|
||||||
HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sWakeupEvent);
|
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);
|
mOpenGLES.MakeCurrent(mRenderSurface);
|
||||||
|
|
||||||
EGLint panelWidth = 0;
|
EGLint panelWidth = 0;
|
||||||
EGLint panelHeight = 0;
|
EGLint panelHeight = 0;
|
||||||
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
|
mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
|
||||||
glViewport(0, 0, 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);
|
// 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
|
// ourself. But enabling batch mode will make clicking a link
|
||||||
// not working because during the click, this thread is not
|
// not working because during the click, this thread is not
|
||||||
// waiting on the hEvent object. See the "wakeup" comment.
|
// waiting on the hEvent object. See the "wakeup" comment.
|
||||||
|
|
||||||
|
log("Entering loop");
|
||||||
while (!cancel.is_canceled()) {
|
while (!cancel.is_canceled()) {
|
||||||
// Block until Servo::sWakeUp is called.
|
// Block until wakeup is called.
|
||||||
// Or run full speed if animating (see on_animating_changed),
|
// Or run full speed if animating (see OnAnimatingChanged),
|
||||||
// it will endup blocking on SwapBuffers to limit rendering to 60FPS
|
// it will endup blocking on Flush to limit rendering to 60FPS
|
||||||
if (!Servo::sAnimating) {
|
if (!mAnimating) {
|
||||||
::WaitForSingleObject(hEvent, INFINITE);
|
::WaitForSingleObject(hEvent, INFINITE);
|
||||||
}
|
}
|
||||||
mEventsMutex.lock();
|
mEventsMutex.lock();
|
||||||
|
@ -216,31 +151,36 @@ void BrowserPage::Loop(cancellation_token cancel) {
|
||||||
case Event::BACK:
|
case Event::BACK:
|
||||||
mServo->GoBack();
|
mServo->GoBack();
|
||||||
break;
|
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();
|
mEvents.clear();
|
||||||
mEventsMutex.unlock();
|
mEventsMutex.unlock();
|
||||||
mServo->PerformUpdates();
|
mServo->PerformUpdates();
|
||||||
}
|
}
|
||||||
|
log("Leaving loop");
|
||||||
cancel_current_task();
|
cancel_current_task();
|
||||||
}
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
||||||
void BrowserPage::StartRenderLoop() {
|
void BrowserPage::StartRenderLoop() {
|
||||||
if (IsLoopRunning()) {
|
if (IsLoopRunning()) {
|
||||||
|
#if defined _DEBUG
|
||||||
|
throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
|
||||||
|
#else
|
||||||
return;
|
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());
|
log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
|
||||||
|
auto token = mLoopCancel.get_token();
|
||||||
mLoopTask = std::make_unique<Concurrency::task<void>>(
|
mLoopTask = std::make_unique<Concurrency::task<void>>(
|
||||||
Concurrency::create_task([=] { Loop(token); }, token));
|
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
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
|
@ -11,13 +11,17 @@
|
||||||
|
|
||||||
namespace winrt::ServoApp::implementation {
|
namespace winrt::ServoApp::implementation {
|
||||||
|
|
||||||
|
static char sWakeupEvent[] = "SIGNAL_WAKEUP";
|
||||||
|
static char sShutdownEvent[] = "SIGNAL_SHUTDOWN";
|
||||||
|
|
||||||
struct Event {
|
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> clickCoords;
|
||||||
std::tuple<float, float, float, float> scrollCoords;
|
std::tuple<float, float, float, float> scrollCoords;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BrowserPage : BrowserPageT<BrowserPage> {
|
struct BrowserPage : BrowserPageT<BrowserPage>,
|
||||||
|
public servo::ServoDelegate {
|
||||||
public:
|
public:
|
||||||
BrowserPage();
|
BrowserPage();
|
||||||
|
|
||||||
|
@ -27,7 +31,10 @@ public:
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
void OnBackButtonClicked(Windows::Foundation::IInspectable const &,
|
void OnBackButtonClicked(Windows::Foundation::IInspectable const &,
|
||||||
Windows::UI::Xaml::RoutedEventArgs 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
|
void
|
||||||
OnSurfaceClicked(Windows::Foundation::IInspectable const &,
|
OnSurfaceClicked(Windows::Foundation::IInspectable const &,
|
||||||
Windows::UI::Xaml::Input::PointerRoutedEventArgs const &);
|
Windows::UI::Xaml::Input::PointerRoutedEventArgs const &);
|
||||||
|
@ -36,13 +43,28 @@ public:
|
||||||
IInspectable const &,
|
IInspectable const &,
|
||||||
Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs const &e);
|
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:
|
private:
|
||||||
void OnVisibilityChanged(
|
void OnVisibilityChanged(
|
||||||
Windows::UI::Core::CoreWindow const &,
|
Windows::UI::Core::CoreWindow const &,
|
||||||
Windows::UI::Core::VisibilityChangedEventArgs const &args);
|
Windows::UI::Core::VisibilityChangedEventArgs const &args);
|
||||||
void OnPageLoaded(Windows::Foundation::IInspectable const &,
|
void OnPageLoaded(Windows::Foundation::IInspectable const &,
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
|
||||||
void CreateRenderSurface();
|
void CreateRenderSurface();
|
||||||
void DestroyRenderSurface();
|
void DestroyRenderSurface();
|
||||||
void RecoverFromLostDevice();
|
void RecoverFromLostDevice();
|
||||||
|
@ -56,13 +78,15 @@ private:
|
||||||
std::unique_ptr<Concurrency::task<void>> mLoopTask;
|
std::unique_ptr<Concurrency::task<void>> mLoopTask;
|
||||||
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
|
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
|
||||||
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
EGLSurface mRenderSurface{EGL_NO_SURFACE};
|
||||||
std::unique_ptr<Servo> mServo;
|
std::unique_ptr<servo::Servo> mServo;
|
||||||
|
|
||||||
void BrowserPage::SendEventToServo(Event event);
|
void BrowserPage::SendEventToServo(Event event);
|
||||||
std::vector<Event> mEvents;
|
std::vector<Event> mEvents;
|
||||||
std::mutex mEventsMutex;
|
std::mutex mEventsMutex;
|
||||||
|
|
||||||
OpenGLES mOpenGLES; // FIXME: shared pointer
|
OpenGLES mOpenGLES; // FIXME: shared pointer
|
||||||
|
|
||||||
|
bool mAnimating;
|
||||||
};
|
};
|
||||||
} // namespace winrt::ServoApp::implementation
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="0">
|
<StackPanel Orientation="Horizontal" Grid.Column="0">
|
||||||
<Button Content="Back" Click="OnBackButtonClicked"/>
|
<Button x:Name="backButton" IsEnabled="false" Content="Back" Click="OnBackButtonClicked"/>
|
||||||
<Button Content="Forward" Click="OnForwardButtonClicked"/>
|
<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>
|
</StackPanel>
|
||||||
<TextBox Text="" AcceptsReturn="True" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" IsReadOnly="True"/>
|
<TextBox Text="" AcceptsReturn="True" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" IsReadOnly="True"/>
|
||||||
<StackPanel Orientation="Horizontal" Grid.Column="2">
|
<StackPanel Orientation="Horizontal" Grid.Column="2">
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
#pragma once
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CameraResources.h"
|
#include "CameraResources.h"
|
||||||
|
|
||||||
|
|
|
@ -1,55 +1,38 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Servo.h"
|
#include "Servo.h"
|
||||||
|
|
||||||
void on_load_started() {}
|
// FIXME: rename mozilla to something else
|
||||||
void on_load_ended() {}
|
namespace servo {
|
||||||
void on_history_changed(bool, bool) {}
|
|
||||||
void on_shutdown_complete() {}
|
|
||||||
|
|
||||||
std::function<void()> Servo::sFlush = []() {};
|
void on_load_started() { sServo->Delegate().OnLoadStarted(); }
|
||||||
std::function<void()> Servo::sMakeCurrent = []() {};
|
void on_load_ended() { sServo->Delegate().OnLoadEnded(); }
|
||||||
std::function<void()> Servo::sWakeUp = []() {};
|
void on_history_changed(bool back, bool forward) {
|
||||||
std::function<void(std::wstring const &)> Servo::sOnAlert =
|
sServo->Delegate().OnHistoryChanged(back, forward);
|
||||||
[](std::wstring const &) {};
|
}
|
||||||
std::function<void(std::wstring const &)> Servo::sOnTitleChanged =
|
void on_shutdown_complete() { sServo->Delegate().OnShutdownComplete(); }
|
||||||
[](std::wstring const &) {};
|
void on_alert(const char *message) {
|
||||||
std::function<void(std::wstring const &)> Servo::sOnURLChanged =
|
sServo->Delegate().OnAlert(char2w(message));
|
||||||
[](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_alert(const char *message) { Servo::sOnAlert(char2w(message)); }
|
|
||||||
|
|
||||||
void on_title_changed(const char *title) {
|
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)); }
|
Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
|
||||||
|
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
||||||
|
|
||||||
void flush() { Servo::sFlush(); }
|
capi::CInitOptions o;
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
CInitOptions o;
|
|
||||||
o.args = NULL;
|
o.args = NULL;
|
||||||
o.url = "https://servo.org";
|
o.url = "https://servo.org";
|
||||||
o.width = mWindowWidth;
|
o.width = mWindowWidth;
|
||||||
|
@ -58,7 +41,9 @@ Servo::Servo(GLsizei width, GLsizei height)
|
||||||
o.enable_subpixel_text_antialiasing = false;
|
o.enable_subpixel_text_antialiasing = false;
|
||||||
o.vr_pointer = NULL;
|
o.vr_pointer = NULL;
|
||||||
|
|
||||||
CHostCallbacks c;
|
sServo = this; // FIXME;
|
||||||
|
|
||||||
|
capi::CHostCallbacks c;
|
||||||
c.flush = &flush;
|
c.flush = &flush;
|
||||||
c.make_current = &make_current;
|
c.make_current = &make_current;
|
||||||
c.on_alert = &on_alert;
|
c.on_alert = &on_alert;
|
||||||
|
@ -74,23 +59,16 @@ Servo::Servo(GLsizei width, GLsizei height)
|
||||||
init_with_egl(o, &wakeup, c);
|
init_with_egl(o, &wakeup, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Servo::~Servo() { deinit(); }
|
Servo::~Servo() { capi::deinit(); }
|
||||||
|
|
||||||
void Servo::PerformUpdates() { perform_updates(); }
|
std::wstring char2w(const char *c_str) {
|
||||||
|
auto str = std::string(c_str);
|
||||||
void Servo::SetBatchMode(bool mode) { set_batch_mode(mode); }
|
int size_needed =
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||||
void Servo::GoForward() { go_forward(); }
|
std::wstring str2(size_needed, 0);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0],
|
||||||
void Servo::GoBack() { go_back(); }
|
size_needed);
|
||||||
|
return str2;
|
||||||
void Servo::SetSize(GLsizei width, GLsizei height) {
|
|
||||||
if (width != mWindowWidth || height != mWindowHeight) {
|
|
||||||
mWindowWidth = width;
|
|
||||||
mWindowHeight = height;
|
|
||||||
resize(mWindowWidth, mWindowHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::Click(float x, float y) { click(x, y); }
|
} // namespace mozilla
|
||||||
void Servo::Scroll(float dx, float dy, float x, float y) { scroll(dx, dy, x, y); }
|
|
||||||
|
|
|
@ -5,37 +5,73 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
#include "logs.h"
|
||||||
|
|
||||||
|
namespace servo {
|
||||||
|
|
||||||
|
namespace capi {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <simpleservo.h>
|
#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 {
|
class Servo {
|
||||||
public:
|
public:
|
||||||
Servo(GLsizei width, GLsizei height);
|
Servo(GLsizei, GLsizei, ServoDelegate &);
|
||||||
~Servo();
|
~Servo();
|
||||||
void PerformUpdates();
|
ServoDelegate &Delegate() { return mDelegate; }
|
||||||
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.
|
void PerformUpdates() { capi::perform_updates(); }
|
||||||
|
void RequestShutdown() { capi::request_shutdown(); }
|
||||||
// Will be called from any thead
|
void SetBatchMode(bool mode) { capi::set_batch_mode(mode); }
|
||||||
static std::function<void()> sWakeUp;
|
void GoForward() { capi::go_forward(); }
|
||||||
// Will be called from GL thread
|
void GoBack() { capi::go_back(); }
|
||||||
static std::function<void()> sFlush;
|
void Click(float x, float y) { capi::click(x, y); }
|
||||||
static std::function<void()> sMakeCurrent;
|
void Reload() { capi::reload(); }
|
||||||
static std::function<void(std::wstring const &)> sOnAlert;
|
void Stop() { capi::stop(); }
|
||||||
static std::function<void(std::wstring const &)> sOnTitleChanged;
|
void Scroll(float dx, float dy, float x, float y) {
|
||||||
static std::function<void(std::wstring const &)> sOnURLChanged;
|
capi::scroll(dx, dy, x, y);
|
||||||
static bool sAnimating;
|
}
|
||||||
|
void SetSize(GLsizei width, GLsizei height) {
|
||||||
|
if (width != mWindowWidth || height != mWindowHeight) {
|
||||||
|
mWindowWidth = width;
|
||||||
|
mWindowHeight = height;
|
||||||
|
capi::resize(mWindowWidth, mWindowHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ServoDelegate &mDelegate;
|
||||||
GLsizei mWindowWidth;
|
GLsizei mWindowWidth;
|
||||||
GLsizei mWindowHeight;
|
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
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <hstring.h>
|
#include <hstring.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue