I'm writing a general purpose window management library and I've been torn on one major design decision that I have to make before making it available for others to use. This crate doesn't handle drawing to windows, but I'm also writing other crates for drawing with APIs such as OpenGL. This crate is only responsible for creating and modifying windows and polling for events.
Currently there is a Display
struct that must be available when creating a window or polling for events. I consider the display to be a "resource" as well as the windows created by it, so it seemed like a good idea to subject it to Rust's ownership and borrowing system. When starting out, I felt that this was the cleanest and most "rusty" solution. The problem is that people who use the library may find it cumbersome to keep the Display
around, but it helps to keep the relevant data in one thread. It would be easy to move this into thread local storage while keeping it available only to the first thread that requests it, but that feels like it may just be a lazy solution.
The provided example currently looks like:
fn main () {
let mut display = Display::open().unwrap();
let _window = Window::builder()
.bg_color(Color::white())
.title("Hello World")
.visible()
.build(&mut display).unwrap();
loop {
match display.wait_event().unwrap() {
Event::CloseRequest(_) => { break; },
_ => {},
}
}
}
If the Display
object is removed, it will look more like:
fn main () {
let _window = Window::builder()
.bg_color(Color::white())
.title("Hello World")
.visible()
.build().unwrap();
loop {
match wait_event().unwrap() {
Event::CloseRequest(_) => { break; },
_ => {},
}
}
}
In such a simple program, it doesn't make a huge distance, but I could imagine it being cumbersome to pass the Display
reference all the time in a complicated program that has more than one dependency that uses this library. For example, even showing a modal message box would require a mutable reference to the display. This is a choice between cleanliness and ergonomics. What do you think? Would it turn people off to a library if they had to pass around a library object in some of the places where it's used?
Edit: Another important detail that I forgot to mention is that only one Display
is allowed in a program. If the program tries to open another one, an error is returned. The reason for this is that Cocoa, which is one of the planned back ends, is not very thread safe and only allows windows to be used from the main thread. I guess there is a third option which allows multiple Display
objects as long as they're all in the same thread.