mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #24927 - ferjm:hololens.mediasession, r=paulrouget
Basic Media Session UI for Hololens - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #24807 This PR implements a extremely basic Media Session UI. The media controls are part of the main window, which is not very nice, but it is what we can do until #24873 is done.
This commit is contained in:
commit
c90dd15fec
11 changed files with 179 additions and 12 deletions
|
@ -7,7 +7,8 @@ extern crate log;
|
||||||
|
|
||||||
pub mod gl_glue;
|
pub mod gl_glue;
|
||||||
|
|
||||||
pub use servo::script_traits::MouseButton;
|
pub use servo::embedder_traits::MediaSessionPlaybackState;
|
||||||
|
pub use servo::script_traits::{MediaSessionActionType, MouseButton};
|
||||||
|
|
||||||
use getopts::Options;
|
use getopts::Options;
|
||||||
use servo::compositing::windowing::{
|
use servo::compositing::windowing::{
|
||||||
|
@ -133,7 +134,7 @@ pub trait HostTrait {
|
||||||
/// Called when we get the media session metadata/
|
/// Called when we get the media session metadata/
|
||||||
fn on_media_session_metadata(&self, title: String, artist: String, album: String);
|
fn on_media_session_metadata(&self, title: String, artist: String, album: String);
|
||||||
/// Called when the media session playback state changes.
|
/// Called when the media session playback state changes.
|
||||||
fn on_media_session_playback_state_change(&self, state: i32);
|
fn on_media_session_playback_state_change(&self, state: MediaSessionPlaybackState);
|
||||||
/// Called when the media session position state is set.
|
/// Called when the media session position state is set.
|
||||||
fn on_media_session_set_position_state(&self, duration: f64, position: f64, playback_rate: f64);
|
fn on_media_session_set_position_state(&self, duration: f64, position: f64, playback_rate: f64);
|
||||||
}
|
}
|
||||||
|
@ -472,9 +473,12 @@ impl ServoGlue {
|
||||||
self.process_event(WindowEvent::Keyboard(key_event))
|
self.process_event(WindowEvent::Keyboard(key_event))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn media_session_action(&mut self, action: i32) -> Result<(), &'static str> {
|
pub fn media_session_action(
|
||||||
|
&mut self,
|
||||||
|
action: MediaSessionActionType,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
info!("Media session action {:?}", action);
|
info!("Media session action {:?}", action);
|
||||||
self.process_event(WindowEvent::MediaSessionAction(action.into()))
|
self.process_event(WindowEvent::MediaSessionAction(action))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> {
|
fn process_event(&mut self, event: WindowEvent) -> Result<(), &'static str> {
|
||||||
|
@ -595,7 +599,7 @@ impl ServoGlue {
|
||||||
MediaSessionEvent::PlaybackStateChange(state) => self
|
MediaSessionEvent::PlaybackStateChange(state) => self
|
||||||
.callbacks
|
.callbacks
|
||||||
.host_callbacks
|
.host_callbacks
|
||||||
.on_media_session_playback_state_change(state as i32),
|
.on_media_session_playback_state_change(state),
|
||||||
MediaSessionEvent::SetPositionState(position_state) => self
|
MediaSessionEvent::SetPositionState(position_state) => self
|
||||||
.callbacks
|
.callbacks
|
||||||
.host_callbacks
|
.host_callbacks
|
||||||
|
|
|
@ -17,7 +17,8 @@ use env_logger;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
||||||
use simpleservo::{
|
use simpleservo::{
|
||||||
Coordinates, EventLoopWaker, HostTrait, InitOptions, MouseButton, VRInitOptions,
|
Coordinates, EventLoopWaker, HostTrait, InitOptions, MediaSessionActionType,
|
||||||
|
MediaSessionPlaybackState, MouseButton, VRInitOptions,
|
||||||
};
|
};
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -218,7 +219,7 @@ pub struct CHostCallbacks {
|
||||||
pub set_clipboard_contents: extern "C" fn(contents: *const c_char),
|
pub set_clipboard_contents: extern "C" fn(contents: *const c_char),
|
||||||
pub on_media_session_metadata:
|
pub on_media_session_metadata:
|
||||||
extern "C" fn(title: *const c_char, album: *const c_char, artist: *const c_char),
|
extern "C" fn(title: *const c_char, album: *const c_char, artist: *const c_char),
|
||||||
pub on_media_session_playback_state_change: extern "C" fn(state: i32),
|
pub on_media_session_playback_state_change: extern "C" fn(state: CMediaSessionPlaybackState),
|
||||||
pub on_media_session_set_position_state:
|
pub on_media_session_set_position_state:
|
||||||
extern "C" fn(duration: f64, position: f64, playback_rate: f64),
|
extern "C" fn(duration: f64, position: f64, playback_rate: f64),
|
||||||
}
|
}
|
||||||
|
@ -254,6 +255,52 @@ impl CMouseButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum CMediaSessionPlaybackState {
|
||||||
|
None = 1,
|
||||||
|
Playing,
|
||||||
|
Paused,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MediaSessionPlaybackState> for CMediaSessionPlaybackState {
|
||||||
|
fn from(state: MediaSessionPlaybackState) -> Self {
|
||||||
|
match state {
|
||||||
|
MediaSessionPlaybackState::None_ => CMediaSessionPlaybackState::None,
|
||||||
|
MediaSessionPlaybackState::Playing => CMediaSessionPlaybackState::Playing,
|
||||||
|
MediaSessionPlaybackState::Paused => CMediaSessionPlaybackState::Paused,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum CMediaSessionActionType {
|
||||||
|
Play = 1,
|
||||||
|
Pause,
|
||||||
|
SeekBackward,
|
||||||
|
SeekForward,
|
||||||
|
PreviousTrack,
|
||||||
|
NextTrack,
|
||||||
|
SkipAd,
|
||||||
|
Stop,
|
||||||
|
SeekTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CMediaSessionActionType {
|
||||||
|
pub fn convert(&self) -> MediaSessionActionType {
|
||||||
|
match self {
|
||||||
|
CMediaSessionActionType::Play => MediaSessionActionType::Play,
|
||||||
|
CMediaSessionActionType::Pause => MediaSessionActionType::Pause,
|
||||||
|
CMediaSessionActionType::SeekBackward => MediaSessionActionType::SeekBackward,
|
||||||
|
CMediaSessionActionType::SeekForward => MediaSessionActionType::SeekForward,
|
||||||
|
CMediaSessionActionType::PreviousTrack => MediaSessionActionType::PreviousTrack,
|
||||||
|
CMediaSessionActionType::NextTrack => MediaSessionActionType::NextTrack,
|
||||||
|
CMediaSessionActionType::SkipAd => MediaSessionActionType::SkipAd,
|
||||||
|
CMediaSessionActionType::Stop => MediaSessionActionType::Stop,
|
||||||
|
CMediaSessionActionType::SeekTo => MediaSessionActionType::SeekTo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The returned string is not freed. This will leak.
|
/// The returned string is not freed. This will leak.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn servo_version() -> *const c_char {
|
pub extern "C" fn servo_version() -> *const c_char {
|
||||||
|
@ -607,6 +654,14 @@ pub extern "C" fn click(x: f32, y: f32) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn media_session_action(action: CMediaSessionActionType) {
|
||||||
|
catch_any_panic(|| {
|
||||||
|
debug!("media_session_action");
|
||||||
|
call(|s| s.media_session_action(action.convert()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WakeupCallback(extern "C" fn());
|
pub struct WakeupCallback(extern "C" fn());
|
||||||
|
|
||||||
impl WakeupCallback {
|
impl WakeupCallback {
|
||||||
|
@ -725,9 +780,9 @@ impl HostTrait for HostCallbacks {
|
||||||
(self.0.on_media_session_metadata)(title.as_ptr(), artist.as_ptr(), album.as_ptr());
|
(self.0.on_media_session_metadata)(title.as_ptr(), artist.as_ptr(), album.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_media_session_playback_state_change(&self, state: i32) {
|
fn on_media_session_playback_state_change(&self, state: MediaSessionPlaybackState) {
|
||||||
debug!("on_media_session_playback_state_change {:?}", state);
|
debug!("on_media_session_playback_state_change {:?}", state);
|
||||||
(self.0.on_media_session_playback_state_change)(state);
|
(self.0.on_media_session_playback_state_change)(state.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_media_session_set_position_state(
|
fn on_media_session_set_position_state(
|
||||||
|
|
|
@ -15,7 +15,9 @@ use jni::{errors, JNIEnv, JavaVM};
|
||||||
use libc::{dup2, pipe, read};
|
use libc::{dup2, pipe, read};
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
||||||
use simpleservo::{Coordinates, EventLoopWaker, HostTrait, InitOptions, VRInitOptions};
|
use simpleservo::{
|
||||||
|
Coordinates, EventLoopWaker, HostTrait, InitOptions, MediaSessionPlaybackState, VRInitOptions,
|
||||||
|
};
|
||||||
use std::os::raw::{c_char, c_int, c_void};
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
use std::ptr::{null, null_mut};
|
use std::ptr::{null, null_mut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -340,7 +342,7 @@ pub fn Java_org_mozilla_servoview_JNIServo_mediaSessionAction(
|
||||||
action: jint,
|
action: jint,
|
||||||
) {
|
) {
|
||||||
debug!("mediaSessionAction");
|
debug!("mediaSessionAction");
|
||||||
call(&env, |s| s.media_session_action(action as i32));
|
call(&env, |s| s.media_session_action((action as i32).into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WakeupCallback {
|
pub struct WakeupCallback {
|
||||||
|
@ -548,9 +550,10 @@ impl HostTrait for HostCallbacks {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_media_session_playback_state_change(&self, state: i32) {
|
fn on_media_session_playback_state_change(&self, state: MediaSessionPlaybackState) {
|
||||||
info!("on_media_session_playback_state_change {:?}", state);
|
info!("on_media_session_playback_state_change {:?}", state);
|
||||||
let env = self.jvm.get_env().unwrap();
|
let env = self.jvm.get_env().unwrap();
|
||||||
|
let state = state as i32;
|
||||||
let state = JValue::Int(state as jint);
|
let state = JValue::Int(state as jint);
|
||||||
env.call_method(
|
env.call_method(
|
||||||
self.callbacks.as_obj(),
|
self.callbacks.as_obj(),
|
||||||
|
|
|
@ -70,6 +70,24 @@ void BrowserPage::BindServoEvents() {
|
||||||
servoControl().OnCaptureGesturesEnded(
|
servoControl().OnCaptureGesturesEnded(
|
||||||
[=] { navigationBar().IsHitTestVisible(true); });
|
[=] { navigationBar().IsHitTestVisible(true); });
|
||||||
urlTextbox().GotFocus(std::bind(&BrowserPage::OnURLFocused, this, _1));
|
urlTextbox().GotFocus(std::bind(&BrowserPage::OnURLFocused, this, _1));
|
||||||
|
servoControl().OnMediaSessionMetadata(
|
||||||
|
[=](hstring title, hstring artist, hstring album) {});
|
||||||
|
servoControl().OnMediaSessionPlaybackStateChange(
|
||||||
|
[=](const auto &, int state) {
|
||||||
|
if (state == servo::Servo::MediaSessionPlaybackState::None) {
|
||||||
|
mediaControls().Visibility(Visibility::Collapsed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mediaControls().Visibility(Visibility::Visible);
|
||||||
|
playButton().Visibility(
|
||||||
|
state == servo::Servo::MediaSessionPlaybackState::Paused
|
||||||
|
? Visibility::Visible
|
||||||
|
: Visibility::Collapsed);
|
||||||
|
pauseButton().Visibility(
|
||||||
|
state == servo::Servo::MediaSessionPlaybackState::Paused
|
||||||
|
? Visibility::Collapsed
|
||||||
|
: Visibility::Visible);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) {
|
void BrowserPage::OnURLFocused(Windows::Foundation::IInspectable const &) {
|
||||||
|
@ -143,4 +161,17 @@ void BrowserPage::OnURLEdited(IInspectable const &,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserPage::OnMediaControlsPlayClicked(
|
||||||
|
Windows::Foundation::IInspectable const &,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const &) {
|
||||||
|
servoControl().SendMediaSessionAction(
|
||||||
|
static_cast<int32_t>(servo::Servo::MediaSessionActionType::Play));
|
||||||
|
}
|
||||||
|
void BrowserPage::OnMediaControlsPauseClicked(
|
||||||
|
Windows::Foundation::IInspectable const &,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const &) {
|
||||||
|
servoControl().SendMediaSessionAction(
|
||||||
|
static_cast<int32_t>(servo::Servo::MediaSessionActionType::Pause));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace winrt::ServoApp::implementation
|
} // namespace winrt::ServoApp::implementation
|
||||||
|
|
|
@ -41,6 +41,10 @@ public:
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
void OnXRPkgWarningDismissClick(Windows::Foundation::IInspectable const &,
|
void OnXRPkgWarningDismissClick(Windows::Foundation::IInspectable const &,
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
void OnMediaControlsPlayClicked(Windows::Foundation::IInspectable const &,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
void OnMediaControlsPauseClicked(Windows::Foundation::IInspectable const &,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BindServoEvents();
|
void BindServoEvents();
|
||||||
|
|
|
@ -137,5 +137,10 @@
|
||||||
<Button Margin="0,10,10,0" Click="OnXRPkgWarningDismissClick">Dismiss</Button>
|
<Button Margin="0,10,10,0" Click="OnXRPkgWarningDismissClick">Dismiss</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<CommandBar Grid.Row="3" x:Name="mediaControls" Visibility="Collapsed">
|
||||||
|
<AppBarButton Icon="Play" Label="Play" x:Name="playButton" Visibility="Collapsed" Click="OnMediaControlsPlayClicked"/>
|
||||||
|
<AppBarButton Icon="Pause" Label="Pause" x:Name="pauseButton" Click="OnMediaControlsPauseClicked"/>
|
||||||
|
</CommandBar>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
@ -56,6 +56,17 @@ const char *get_clipboard_contents() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_media_session_metadata(const char *title, const char *album,
|
||||||
|
const char *artist) {
|
||||||
|
return sServo->Delegate().OnServoMediaSessionMetadata(
|
||||||
|
char2hstring(title), char2hstring(album), char2hstring(artist));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_media_session_playback_state_change(
|
||||||
|
const capi::CMediaSessionPlaybackState state) {
|
||||||
|
return sServo->Delegate().OnServoMediaSessionPlaybackStateChange(state);
|
||||||
|
}
|
||||||
|
|
||||||
Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
||||||
float dpi, ServoDelegate &aDelegate)
|
float dpi, ServoDelegate &aDelegate)
|
||||||
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
|
||||||
|
@ -110,6 +121,9 @@ Servo::Servo(hstring url, hstring args, GLsizei width, GLsizei height,
|
||||||
c.on_ime_state_changed = &on_ime_state_changed;
|
c.on_ime_state_changed = &on_ime_state_changed;
|
||||||
c.get_clipboard_contents = &get_clipboard_contents;
|
c.get_clipboard_contents = &get_clipboard_contents;
|
||||||
c.set_clipboard_contents = &set_clipboard_contents;
|
c.set_clipboard_contents = &set_clipboard_contents;
|
||||||
|
c.on_media_session_metadata = &on_media_session_metadata;
|
||||||
|
c.on_media_session_playback_state_change =
|
||||||
|
&on_media_session_playback_state_change;
|
||||||
|
|
||||||
capi::register_panic_handler(&on_panic);
|
capi::register_panic_handler(&on_panic);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
virtual void OnServoIMEStateChanged(bool) = 0;
|
virtual void OnServoIMEStateChanged(bool) = 0;
|
||||||
virtual void Flush() = 0;
|
virtual void Flush() = 0;
|
||||||
virtual void MakeCurrent() = 0;
|
virtual void MakeCurrent() = 0;
|
||||||
|
virtual void OnServoMediaSessionMetadata(hstring, hstring, hstring) = 0;
|
||||||
|
virtual void OnServoMediaSessionPlaybackStateChange(int) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~ServoDelegate(){};
|
virtual ~ServoDelegate(){};
|
||||||
|
@ -48,6 +50,8 @@ public:
|
||||||
ServoDelegate &Delegate() { return mDelegate; }
|
ServoDelegate &Delegate() { return mDelegate; }
|
||||||
|
|
||||||
typedef capi::CMouseButton MouseButton;
|
typedef capi::CMouseButton MouseButton;
|
||||||
|
typedef capi::CMediaSessionActionType MediaSessionActionType;
|
||||||
|
typedef capi::CMediaSessionPlaybackState MediaSessionPlaybackState;
|
||||||
|
|
||||||
void PerformUpdates() { capi::perform_updates(); }
|
void PerformUpdates() { capi::perform_updates(); }
|
||||||
void DeInit() { capi::deinit(); }
|
void DeInit() { capi::deinit(); }
|
||||||
|
@ -86,6 +90,9 @@ public:
|
||||||
capi::resize(mWindowWidth, mWindowHeight);
|
capi::resize(mWindowWidth, mWindowHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void SendMediaSessionAction(capi::CMediaSessionActionType action) {
|
||||||
|
capi::media_session_action(action);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ServoDelegate &mDelegate;
|
ServoDelegate &mDelegate;
|
||||||
|
|
|
@ -271,6 +271,13 @@ hstring ServoControl::LoadURIOrSearch(hstring input) {
|
||||||
return searchUri;
|
return searchUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServoControl::SendMediaSessionAction(int32_t action) {
|
||||||
|
RunOnGLThread([=] {
|
||||||
|
mServo->SendMediaSessionAction(
|
||||||
|
static_cast<Servo::MediaSessionActionType>(action));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ServoControl::TryLoadUri(hstring input) {
|
void ServoControl::TryLoadUri(hstring input) {
|
||||||
if (!mLooping) {
|
if (!mLooping) {
|
||||||
mInitialURL = input;
|
mInitialURL = input;
|
||||||
|
@ -432,6 +439,15 @@ void ServoControl::OnServoIMEStateChanged(bool aShow) {
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange
|
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoMediaSessionMetadata(hstring title, hstring artist,
|
||||||
|
hstring album) {
|
||||||
|
RunOnUIThread([=] { mOnMediaSessionMetadataEvent(title, artist, album); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServoControl::OnServoMediaSessionPlaybackStateChange(int state) {
|
||||||
|
RunOnUIThread([=] { mOnMediaSessionPlaybackStateChangeEvent(*this, state); });
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) {
|
template <typename Callable> void ServoControl::RunOnUIThread(Callable cb) {
|
||||||
Dispatcher().RunAsync(CoreDispatcherPriority::High, cb);
|
Dispatcher().RunAsync(CoreDispatcherPriority::High, cb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
void Stop();
|
void Stop();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
hstring LoadURIOrSearch(hstring);
|
hstring LoadURIOrSearch(hstring);
|
||||||
|
void SendMediaSessionAction(int32_t);
|
||||||
|
|
||||||
void OnLoaded(IInspectable const &,
|
void OnLoaded(IInspectable const &,
|
||||||
Windows::UI::Xaml::RoutedEventArgs const &);
|
Windows::UI::Xaml::RoutedEventArgs const &);
|
||||||
|
@ -70,6 +71,23 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
mOnCaptureGesturesEndedEvent.remove(token);
|
mOnCaptureGesturesEndedEvent.remove(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
winrt::event_token
|
||||||
|
OnMediaSessionMetadata(MediaSessionMetadataDelegate const &handler) {
|
||||||
|
return mOnMediaSessionMetadataEvent.add(handler);
|
||||||
|
};
|
||||||
|
void OnMediaSessionMetadata(winrt::event_token const &token) noexcept {
|
||||||
|
mOnMediaSessionMetadataEvent.remove(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::event_token OnMediaSessionPlaybackStateChange(
|
||||||
|
Windows::Foundation::EventHandler<int> const &handler) {
|
||||||
|
return mOnMediaSessionPlaybackStateChangeEvent.add(handler);
|
||||||
|
};
|
||||||
|
void
|
||||||
|
OnMediaSessionPlaybackStateChange(winrt::event_token const &token) noexcept {
|
||||||
|
mOnMediaSessionPlaybackStateChangeEvent.remove(token);
|
||||||
|
}
|
||||||
|
|
||||||
void SetTransientMode(bool transient) { mTransient = transient; }
|
void SetTransientMode(bool transient) { mTransient = transient; }
|
||||||
|
|
||||||
void SetArgs(hstring args) { mArgs = args; }
|
void SetArgs(hstring args) { mArgs = args; }
|
||||||
|
@ -87,6 +105,9 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
|
||||||
virtual bool OnServoAllowNavigation(winrt::hstring);
|
virtual bool OnServoAllowNavigation(winrt::hstring);
|
||||||
virtual void OnServoAnimatingChanged(bool);
|
virtual void OnServoAnimatingChanged(bool);
|
||||||
virtual void OnServoIMEStateChanged(bool);
|
virtual void OnServoIMEStateChanged(bool);
|
||||||
|
virtual void OnServoMediaSessionMetadata(winrt::hstring, winrt::hstring,
|
||||||
|
winrt::hstring);
|
||||||
|
virtual void OnServoMediaSessionPlaybackStateChange(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnURLChangedEvent;
|
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnURLChangedEvent;
|
||||||
|
@ -96,6 +117,9 @@ private:
|
||||||
winrt::event<EventDelegate> mOnLoadEndedEvent;
|
winrt::event<EventDelegate> mOnLoadEndedEvent;
|
||||||
winrt::event<EventDelegate> mOnCaptureGesturesStartedEvent;
|
winrt::event<EventDelegate> mOnCaptureGesturesStartedEvent;
|
||||||
winrt::event<EventDelegate> mOnCaptureGesturesEndedEvent;
|
winrt::event<EventDelegate> mOnCaptureGesturesEndedEvent;
|
||||||
|
winrt::event<MediaSessionMetadataDelegate> mOnMediaSessionMetadataEvent;
|
||||||
|
winrt::event<Windows::Foundation::EventHandler<int>>
|
||||||
|
mOnMediaSessionPlaybackStateChangeEvent;
|
||||||
|
|
||||||
float mDPI = 1;
|
float mDPI = 1;
|
||||||
hstring mInitialURL = DEFAULT_URL;
|
hstring mInitialURL = DEFAULT_URL;
|
||||||
|
|
|
@ -2,6 +2,7 @@ namespace ServoApp {
|
||||||
|
|
||||||
delegate void EventDelegate();
|
delegate void EventDelegate();
|
||||||
delegate void HistoryChangedDelegate(Boolean back, Boolean forward);
|
delegate void HistoryChangedDelegate(Boolean back, Boolean forward);
|
||||||
|
delegate void MediaSessionMetadataDelegate(String title, String artist, String album);
|
||||||
|
|
||||||
runtimeclass ServoControl : Windows.UI.Xaml.Controls.Control {
|
runtimeclass ServoControl : Windows.UI.Xaml.Controls.Control {
|
||||||
ServoControl();
|
ServoControl();
|
||||||
|
@ -13,6 +14,7 @@ namespace ServoApp {
|
||||||
void SetTransientMode(Boolean transient);
|
void SetTransientMode(Boolean transient);
|
||||||
void SetArgs(String args);
|
void SetArgs(String args);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
void SendMediaSessionAction(UInt32 action);
|
||||||
event EventDelegate OnLoadStarted;
|
event EventDelegate OnLoadStarted;
|
||||||
event EventDelegate OnLoadEnded;
|
event EventDelegate OnLoadEnded;
|
||||||
event EventDelegate OnCaptureGesturesStarted;
|
event EventDelegate OnCaptureGesturesStarted;
|
||||||
|
@ -20,5 +22,7 @@ namespace ServoApp {
|
||||||
event HistoryChangedDelegate OnHistoryChanged;
|
event HistoryChangedDelegate OnHistoryChanged;
|
||||||
event Windows.Foundation.EventHandler<String> OnTitleChanged;
|
event Windows.Foundation.EventHandler<String> OnTitleChanged;
|
||||||
event Windows.Foundation.EventHandler<String> OnURLChanged;
|
event Windows.Foundation.EventHandler<String> OnURLChanged;
|
||||||
|
event MediaSessionMetadataDelegate OnMediaSessionMetadata;
|
||||||
|
event Windows.Foundation.EventHandler<int> OnMediaSessionPlaybackStateChange;
|
||||||
}
|
}
|
||||||
} // namespace ServoApp
|
} // namespace ServoApp
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue