libservo: Add WebViewDelegate and ServoDelegate and port winit_minimal (#35196)

This change adds the second major part of the new API: delegates which
have methods called by the Servo loop. When a delegate is set on a
`WebView` or on `Servo` itself, the event loop will call into
appropriate delegate methods. Applications can implement the delegate on
their own structs to add special behavior per-`WebView` or for all
`WebView`s.

In addition, each delegate has a default implementation, which
automatically exposes "reasonable" behavior such as by-default allowing
navigation.

There's a lot more work to do here, such as refining the delegate
methods so that they all have nice interfaces, particulary with regard
to delegate methods that need an asynchronous response. This will be
handed gradually as we keep working on the API.

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Delan Azabani 2025-02-05 18:08:40 +08:00 committed by GitHub
parent 789736590b
commit 175f28866d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1005 additions and 198 deletions

View file

@ -249,7 +249,7 @@ impl App {
// Take any new embedder messages from Servo.
let servo = self.servo.as_mut().expect("Servo should be running.");
let mut embedder_messages: Vec<_> = servo.get_events().collect();
let mut embedder_messages = servo.get_events();
let mut need_present = false;
let mut need_update = false;
loop {
@ -271,7 +271,7 @@ impl App {
}
// Take any new embedder messages from Servo itself.
embedder_messages = servo.get_events().collect();
embedder_messages = servo.get_events();
if embedder_messages.is_empty() {
break;
}

View file

@ -28,7 +28,7 @@ use servo::{
PermissionRequest, PromptCredentialsInput, PromptDefinition, PromptOrigin, PromptResult, Servo,
TouchEventType,
};
use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo};
use tinyfiledialogs::{self, MessageBoxIcon, OkCancel};
use super::dialog::Dialog;
use super::keyutils::CMD_OR_CONTROL;
@ -487,9 +487,6 @@ impl WebViewManager {
let res = if opts.headless {
match definition {
PromptDefinition::Alert(_message, sender) => sender.send(()),
PromptDefinition::YesNo(_message, sender) => {
sender.send(PromptResult::Primary)
},
PromptDefinition::OkCancel(_message, sender) => {
sender.send(PromptResult::Primary)
},
@ -518,21 +515,6 @@ impl WebViewManager {
);
sender.send(())
},
PromptDefinition::YesNo(mut message, sender) => {
if origin == PromptOrigin::Untrusted {
message = tiny_dialog_escape(&message);
}
let result = tinyfiledialogs::message_box_yes_no(
"",
&message,
MessageBoxIcon::Warning,
YesNo::No,
);
sender.send(match result {
YesNo::Yes => PromptResult::Primary,
YesNo::No => PromptResult::Secondary,
})
},
PromptDefinition::OkCancel(mut message, sender) => {
if origin == PromptOrigin::Untrusted {
message = tiny_dialog_escape(&message);
@ -824,6 +806,8 @@ impl WebViewManager {
#[cfg(target_os = "linux")]
fn prompt_user(prompt: PermissionPrompt) -> PermissionRequest {
use tinyfiledialogs::YesNo;
let message = match prompt {
PermissionPrompt::Request(permission_name) => {
format!("Do you want to grant permission for {:?}?", permission_name)

View file

@ -455,7 +455,7 @@ impl ServoGlue {
fn handle_servo_events(&mut self) -> Result<(), &'static str> {
let mut need_update = false;
let messages: Vec<_> = self.servo.get_events().collect();
let messages = self.servo.get_events();
for message in messages {
match message {
EmbedderMsg::ChangePageTitle(_, title) => {
@ -514,9 +514,6 @@ impl ServoGlue {
PromptDefinition::OkCancel(message, sender) => {
sender.send(cb.prompt_ok_cancel(message, trusted))
},
PromptDefinition::YesNo(message, sender) => {
sender.send(cb.prompt_yes_no(message, trusted))
},
PromptDefinition::Input(message, default, sender) => {
sender.send(cb.prompt_input(message, default, trusted))
},