mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Merge 676feadee9
into b422a65a00
This commit is contained in:
commit
506e7bf98d
6 changed files with 75 additions and 33 deletions
|
@ -7,15 +7,14 @@ use std::collections::HashMap;
|
|||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use euclid::{Point2D, Vector2D};
|
||||
use image::{DynamicImage, ImageFormat};
|
||||
use euclid::Vector2D;
|
||||
use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher};
|
||||
use log::{error, info};
|
||||
use servo::base::id::WebViewId;
|
||||
use servo::config::pref;
|
||||
use servo::ipc_channel::ipc::IpcSender;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||
use servo::{
|
||||
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
|
||||
LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType,
|
||||
|
@ -28,6 +27,7 @@ use super::dialog::Dialog;
|
|||
use super::gamepad::GamepadSupport;
|
||||
use super::keyutils::CMD_OR_CONTROL;
|
||||
use super::window_trait::{LINE_HEIGHT, WindowPortsMethods};
|
||||
use crate::output_image::save_output_image_if_necessary;
|
||||
use crate::prefs::ServoShellPreferences;
|
||||
|
||||
pub(crate) enum AppState {
|
||||
|
@ -140,31 +140,6 @@ impl RunningAppState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn save_output_image_if_necessary(&self) {
|
||||
let Some(output_path) = self.servoshell_preferences.output_image_path.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let inner = self.inner();
|
||||
let size = inner.window.rendering_context().size2d().to_i32();
|
||||
let viewport_rect = DeviceIntRect::from_origin_and_size(Point2D::origin(), size);
|
||||
let Some(image) = inner
|
||||
.window
|
||||
.rendering_context()
|
||||
.read_to_image(viewport_rect)
|
||||
else {
|
||||
error!("Failed to read output image.");
|
||||
return;
|
||||
};
|
||||
|
||||
let image_format = ImageFormat::from_path(output_path).unwrap_or(ImageFormat::Png);
|
||||
if let Err(error) =
|
||||
DynamicImage::ImageRgba8(image).save_with_format(output_path, image_format)
|
||||
{
|
||||
error!("Failed to save {output_path}: {error}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Repaint the Servo view is necessary, returning true if anything was actually
|
||||
/// painted or false otherwise. Something may not be painted if Servo is waiting
|
||||
/// for a stable image to paint.
|
||||
|
@ -179,9 +154,10 @@ impl RunningAppState {
|
|||
return;
|
||||
}
|
||||
|
||||
// This needs to be done before presenting(), because `ReneringContext::read_to_image` reads
|
||||
// from the back buffer.
|
||||
self.save_output_image_if_necessary();
|
||||
save_output_image_if_necessary(
|
||||
&self.servoshell_preferences,
|
||||
&self.inner().window.rendering_context(),
|
||||
);
|
||||
|
||||
let mut inner_mut = self.inner_mut();
|
||||
inner_mut.window.rendering_context().present();
|
||||
|
|
|
@ -25,6 +25,7 @@ use servo::{
|
|||
use url::Url;
|
||||
|
||||
use crate::egl::host_trait::HostTrait;
|
||||
use crate::output_image::save_output_image_if_necessary;
|
||||
use crate::prefs::ServoShellPreferences;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -718,8 +719,14 @@ impl RunningAppState {
|
|||
pub fn present_if_needed(&self) {
|
||||
if self.inner().need_present {
|
||||
self.inner_mut().need_present = false;
|
||||
self.active_webview().paint();
|
||||
if !self.active_webview().paint() {
|
||||
return;
|
||||
}
|
||||
save_output_image_if_necessary(&self.servoshell_preferences, &self.rendering_context);
|
||||
self.rendering_context.present();
|
||||
if self.servoshell_preferences.exit_after_stable_image {
|
||||
self.request_shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,8 @@ const PROMPT_QUEUE_SIZE: usize = 4;
|
|||
static SET_URL_BAR_CB: OnceLock<
|
||||
ThreadsafeFunction<String, (), String, false, false, UPDATE_URL_QUEUE_SIZE>,
|
||||
> = OnceLock::new();
|
||||
static TERMINATE_CALLBACK: OnceLock<ThreadsafeFunction<(), (), (), false, false, 1>> =
|
||||
OnceLock::new();
|
||||
static PROMPT_TOAST: OnceLock<
|
||||
ThreadsafeFunction<String, (), String, false, false, PROMPT_QUEUE_SIZE>,
|
||||
> = OnceLock::new();
|
||||
|
@ -601,6 +603,15 @@ pub fn register_url_callback(callback: Function<String, ()>) -> napi_ohos::Resul
|
|||
})
|
||||
}
|
||||
|
||||
#[napi(js_name = "registerTerminateCallback")]
|
||||
pub fn register_terminate_callback(callback: Function<(), ()>) -> napi_ohos::Result<()> {
|
||||
let tsfn_builder = callback.build_threadsafe_function();
|
||||
let function = tsfn_builder.max_queue_size::<1>().build()?;
|
||||
TERMINATE_CALLBACK
|
||||
.set(function)
|
||||
.map_err(|_| napi_ohos::Error::from_reason("Failed to set terminate function"))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn register_prompt_toast_callback(callback: Function<String, ()>) -> napi_ohos::Result<()> {
|
||||
debug!("register_prompt_toast_callback called!");
|
||||
|
@ -850,7 +861,13 @@ impl HostTrait for HostCallbacks {
|
|||
// todo: should we tell the vsync thread that it should perform updates?
|
||||
}
|
||||
|
||||
fn on_shutdown_complete(&self) {}
|
||||
fn on_shutdown_complete(&self) {
|
||||
if let Some(terminate_fn) = TERMINATE_CALLBACK.get() {
|
||||
terminate_fn.call((), ThreadsafeFunctionCallMode::Blocking);
|
||||
} else {
|
||||
error!("Could not shut down despite servo shutting down");
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows the Inputmethod
|
||||
///
|
||||
|
|
|
@ -15,6 +15,7 @@ mod crash_handler;
|
|||
pub(crate) mod desktop;
|
||||
#[cfg(any(target_os = "android", target_env = "ohos"))]
|
||||
mod egl;
|
||||
mod output_image;
|
||||
#[cfg(not(any(target_os = "android", target_env = "ohos")))]
|
||||
mod panic_hook;
|
||||
mod parser;
|
||||
|
|
39
ports/servoshell/output_image.rs
Normal file
39
ports/servoshell/output_image.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use euclid::Point2D;
|
||||
use image::{DynamicImage, ImageFormat};
|
||||
use log::error;
|
||||
use servo::RenderingContext;
|
||||
use servo::webrender_api::units::DeviceIntRect;
|
||||
|
||||
use crate::prefs::ServoShellPreferences;
|
||||
|
||||
// This needs to be done before presenting(), because `ReneringContext::read_to_image` reads
|
||||
// from the back buffer.
|
||||
pub(crate) fn save_output_image_if_necessary<T>(
|
||||
prefs: &ServoShellPreferences,
|
||||
rendering_context: &Rc<T>,
|
||||
) where
|
||||
T: RenderingContext + ?Sized,
|
||||
{
|
||||
let Some(output_path) = prefs.output_image_path.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let size = rendering_context.size2d().to_i32();
|
||||
let viewport_rect = DeviceIntRect::from_origin_and_size(Point2D::origin(), size);
|
||||
let Some(image) = rendering_context.read_to_image(viewport_rect) else {
|
||||
error!("Failed to read output image.");
|
||||
return;
|
||||
};
|
||||
|
||||
let image_format = ImageFormat::from_path(output_path).unwrap_or(ImageFormat::Png);
|
||||
if let Err(error) = DynamicImage::ImageRgba8(image).save_with_format(output_path, image_format)
|
||||
{
|
||||
error!("Failed to save {output_path}: {error}.");
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ interface ServoXComponentInterface {
|
|||
goBack(): void;
|
||||
goForward(): void;
|
||||
registerURLcallback(callback: (url: string) => void): void;
|
||||
registerTerminateCallback(callback: () => void): void;
|
||||
registerPromptToastCallback(callback: (msg: string) => void): void
|
||||
initServo(options: InitOpts): void;
|
||||
}
|
||||
|
@ -130,6 +131,7 @@ struct Index {
|
|||
console.info('New URL from native: ', new_url)
|
||||
this.urlToLoad = new_url
|
||||
})
|
||||
this.xComponentContext.registerTerminateCallback(() => { this.context?.terminateSelf(); })
|
||||
this.xComponentContext.registerPromptToastCallback(prompt_toast)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue