Skip to content

Commit

Permalink
Allow changing initial url from cli
Browse files Browse the repository at this point in the history
  • Loading branch information
Legend-Master committed Oct 17, 2024
1 parent 698eeb3 commit 6ff4f7f
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,8 +1236,8 @@ impl IOCompositor {

if let Some(panel) = &mut window.panel {
let rect = DeviceIntRect::from_size(size);
panel.rect = rect;
self.on_resize_webview_event(panel.webview_id, rect);
panel.webview.rect = rect;
self.on_resize_webview_event(panel.webview.webview_id, rect);
}

let rect = DeviceIntRect::from_size(size);
Expand Down
40 changes: 39 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,59 @@ use net_traits::{
};
use servo_config::opts::{default_opts, set_options, Opts};

/// Command line arguments.
#[derive(Clone, Debug, Default)]
pub struct CliArgs {
/// Url to load initially.
pub initial_url: Option<url::Url>,
}

/// Configuration of Verso instance.
#[derive(Clone, Debug)]
pub struct Config {
/// Global flag options of Servo.
pub opts: Opts,
/// Path to resources directory.
pub resource_dir: PathBuf,
/// Command line arguments.
pub cli_args: CliArgs,
}

fn parse_cli_args() -> Result<CliArgs, getopts::Fail> {
let args: Vec<String> = std::env::args().collect();

let mut opts = getopts::Options::new();
opts.optopt("", "initial-url", "load this url on start", "url");

let matches = opts.parse(&args[1..])?;
let initial_url = matches
.opt_str("initial-url")
.and_then(|initial_url| match url::Url::parse(&initial_url) {
Ok(url_parsed) => Some(url_parsed),
Err(e) => {
if e == url::ParseError::RelativeUrlWithoutBase {
if let Ok(url_parsed) = url::Url::parse(&format!("https://{initial_url}")) {
return Some(url_parsed);
}
}
log::error!("Invalid initial url: {initial_url}");
None
}
});

Ok(CliArgs { initial_url })
}

impl Config {
/// Create a new configuration for creating Verso instance. It must provide the path of
/// resources directory.
pub fn new(resource_dir: PathBuf) -> Self {
let opts = default_opts();
Self { opts, resource_dir }
Self {
opts,
resource_dir,
cli_args: parse_cli_args().unwrap_or_default(),
}
}

/// Register URL scheme protocols
Expand Down
6 changes: 4 additions & 2 deletions src/verso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ impl Verso {
pub fn new(evl: &ActiveEventLoop, proxy: EventLoopProxy<()>, config: Config) -> Self {
// Initialize configurations and Verso window
let protocols = config.create_protocols();
let initial_url = config.cli_args.initial_url.clone();
config.init();
// Reserving a namespace to create TopLevelBrowsingContextId.
PipelineNamespace::install(PipelineNamespaceId(0));
let (mut window, rendering_context) = Window::new(evl);

let event_loop_waker = Box::new(Waker(proxy));
let opts = opts::get();

Expand Down Expand Up @@ -359,7 +361,7 @@ impl Verso {
opts.debug.convert_mouse_to_touch,
);

window.create_panel(&constellation_sender);
window.create_panel(&constellation_sender, initial_url);

let mut windows = HashMap::new();
windows.insert(window.id(), (window, webrender_document));
Expand Down Expand Up @@ -428,7 +430,7 @@ impl Verso {
) {
let mut window =
Window::new_with_compositor(evl, compositor);
window.create_panel(&self.constellation_sender);
window.create_panel(&self.constellation_sender, None);
let webrender_document = document.clone();
self.windows
.insert(window.id(), (window, webrender_document));
Expand Down
11 changes: 8 additions & 3 deletions src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Window {
send_to_constellation(
sender,
ConstellationMsg::WebDriverCommand(WebDriverCommandMsg::ScriptCommand(
BrowsingContextId::from(panel.webview_id),
BrowsingContextId::from(panel.webview.webview_id),
WebDriverScriptCommand::ExecuteScript(
format!("window.navbar.setNavbarUrl('{}')", url.as_str()),
tx,
Expand Down Expand Up @@ -155,14 +155,19 @@ impl Window {
self.window.request_redraw();
send_to_constellation(sender, ConstellationMsg::FocusWebView(panel_id));

let demo_url = ServoUrl::parse("https://example.com").unwrap();
let demo_id = WebViewId::new();
let size = self.size();
let rect = DeviceIntRect::from_size(size);
let mut webview = WebView::new(demo_id, rect);
webview.set_size(self.get_content_size(rect));
self.webview = Some(webview);
send_to_constellation(sender, ConstellationMsg::NewWebView(demo_url, demo_id));
send_to_constellation(
sender,
ConstellationMsg::NewWebView(
self.panel.as_ref().unwrap().initial_url.clone(),
demo_id,
),
);
log::debug!("Verso Window {:?} adds webview {}", self.id(), demo_id);
}
EmbedderMsg::AllowNavigationRequest(id, _url) => {
Expand Down
62 changes: 43 additions & 19 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,30 @@ use crate::{

use arboard::Clipboard;

/// A panel is a special web view that focus on controlling states around window.
/// It could be treated as the control panel or navigation bar of the window depending on usages.
///
/// At the moment, following Web API is supported:
/// - Close window: `window.close()`
/// - Navigate to previous page: `window.prompt('PREV')`
/// - Navigate to next page: `window.prompt('FORWARD')`
/// - Refresh the page: `window.prompt('REFRESH')`
/// - Minimize the window: `window.prompt('MINIMIZE')`
/// - Maximize the window: `window.prompt('MAXIMIZE')`
/// - Navigate to a specific URL: `window.prompt('NAVIGATE_TO:${url}')`
pub struct Panel {
pub(crate) webview: WebView,
pub(crate) initial_url: servo_url::ServoUrl,
}

/// A Verso window is a Winit window containing several web views.
pub struct Window {
/// Access to Winit window
pub(crate) window: WinitWindow,
/// GL surface of the window
pub(crate) surface: Surface<WindowSurface>,
/// The main panel of this window. A panel is a special web view that focus on controlling states around window.
/// It could be treated as the control panel or navigation bar of the window depending on usages.
///
/// At the moment, following Web API is supported:
/// - Close window: `window.close()`
/// - Navigate to previous page: `window.prompt('PREV')`
/// - Navigate to next page: `window.prompt('FORWARD')`
/// - Refresh the page: `window.prompt('REFRESH')`
/// - Minimize the window: `window.prompt('MINIMIZE')`
/// - Maximize the window: `window.prompt('MAXIMIZE')`
/// - Navigate to a specific URL: `window.prompt('NAVIGATE_TO:${url}')`
pub(crate) panel: Option<WebView>,
/// The main panel of this window.
pub(crate) panel: Option<Panel>,
/// The WebView of this window.
pub(crate) webview: Option<WebView>,
/// The mouse physical position in the web view.
Expand Down Expand Up @@ -154,11 +160,22 @@ impl Window {
}

/// Send the constellation message to start Panel UI
pub fn create_panel(&mut self, constellation_sender: &Sender<ConstellationMsg>) {
pub fn create_panel(
&mut self,
constellation_sender: &Sender<ConstellationMsg>,
initial_url: Option<url::Url>,
) {
let size = self.window.inner_size();
let size = Size2D::new(size.width as i32, size.height as i32);
let panel_id = WebViewId::new();
self.panel = Some(WebView::new(panel_id, DeviceIntRect::from_size(size)));
self.panel = Some(Panel {
webview: WebView::new(panel_id, DeviceIntRect::from_size(size)),
initial_url: if let Some(initial_url) = initial_url {
servo_url::ServoUrl::from_url(initial_url)
} else {
ServoUrl::parse("https://example.com").unwrap()
},
});

let url = ServoUrl::parse("verso://panel.html").unwrap();
send_to_constellation(
Expand Down Expand Up @@ -302,7 +319,7 @@ impl Window {
) -> bool {
// // Handle message in Verso Panel
if let Some(panel) = &self.panel {
if panel.webview_id == webview_id {
if panel.webview.webview_id == webview_id {
return self.handle_servo_messages_with_panel(
webview_id, message, sender, clipboard, compositor,
);
Expand Down Expand Up @@ -336,7 +353,9 @@ impl Window {

/// Check if the window has such webview.
pub fn has_webview(&self, id: WebViewId) -> bool {
self.panel.as_ref().map_or(false, |w| w.webview_id == id)
self.panel
.as_ref()
.map_or(false, |w| w.webview.webview_id == id)
|| self.webview.as_ref().map_or(false, |w| w.webview_id == id)
}

Expand All @@ -347,14 +366,19 @@ impl Window {
id: WebViewId,
compositor: &mut IOCompositor,
) -> (Option<WebView>, bool) {
if self.panel.as_ref().filter(|w| w.webview_id == id).is_some() {
if self
.panel
.as_ref()
.filter(|w| w.webview.webview_id == id)
.is_some()
{
if let Some(w) = self.webview.as_ref() {
send_to_constellation(
&compositor.constellation_chan,
ConstellationMsg::CloseWebView(w.webview_id),
)
}
(self.panel.take(), false)
(self.panel.take().map(|panel| panel.webview), false)
} else if self
.webview
.as_ref()
Expand All @@ -371,7 +395,7 @@ impl Window {
pub fn painting_order(&self) -> Vec<&WebView> {
let mut order = vec![];
if let Some(panel) = &self.panel {
order.push(panel);
order.push(&panel.webview);
}
if let Some(webview) = &self.webview {
order.push(webview);
Expand Down

0 comments on commit 6ff4f7f

Please sign in to comment.