Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow changing initial url from cli #204

Merged
merged 3 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
}
Legend-Master marked this conversation as resolved.
Show resolved Hide resolved

/// 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,
Legend-Master marked this conversation as resolved.
Show resolved Hide resolved
}

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");
Legend-Master marked this conversation as resolved.
Show resolved Hide resolved

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,
Legend-Master marked this conversation as resolved.
Show resolved Hide resolved
}

/// 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