More help regarding a webview wrapper


#1

I have this cross-platform webview wrapper (works well on Linux and Windows so far), but I’m not sure if its API is correct. Does anyone have any advice?

impl Context {
    /// Initializes the application, can only be run once, or it returns an error.
    pub fn init() -> io::Result<Context>;
    /// Runs the main loop until all windows are closed.
    pub fn run(&mut self);
    /// Make a new window.
    pub fn window<H: Fn(Window, Event)>(&mut self, options: Options, handler: H) -> io::Result<Window>;
}

impl Window {
    /// Load a HTML string.
    pub fn load(&self, html: &str);
    /// Execute some JavaScript on the page.
    pub fn eval(&self, js: &str);
    /// Close the window.
    pub fn close(&self);
}

/// Window is reference-counted.
impl Clone for Window { ... }

The main problem I can see is that you can’t open a window from inside the handler. Possible solutions:

  • Make the context reference counted, too. Unfortunately, this would also let the user call Context::run(&self) from the window, so it won’t work.
  • Duplicate Context::window on the Window object. The problem with this is that it’s very confusing, but I think it succeeds at ensuring that the Window is only ever created on the same thread that Context::init was called on, which I think is the only necessary constraint. Maybe it could also be made less confusing by naming it child or something.

#2

I’d expect fn close(self) to enforce it can’t be used after it’s closed.

Do you have a reason to offer refcounted clone yourself, rather than leave it to user to have Arc/Rc<Window>?

Maybe have RunLoop as an object, and Window::open_in_run_loop(r)?


#3

I’d expect fn close(self) to enforce it can’t be used after it’s closed.

That would be sensible if the developer had complete control over when the window is closed, but they don’t - the user could close it, and so could all kinds of other events out of this simple wrapper’s control. So it’s simpler to just say “if it’s already closed, this function does nothing”.

Do you have a reason to offer refcounted clone yourself, rather than leave it to user to have Arc/Rc?

No, but all the native libraries that this library is wrapping around offer reference counting anyway, so it’d be a waste not to take advantage of that.

Maybe have RunLoop as an object, and Window::open_in_run_loop(r)?

Consider the two cases:

  • If run mutably borrows self, then I can’t use RunLoop in the event loop while it’s running, so that still won’t allow me to open a window from inside the loop.
  • If run immutably borrows self, then I can call run from inside the event loop, which is bad.

So either way, it doesn’t work out.