Rust. GTK3. get_screen() method not found in `gtk::Window` - rust

I want to use css for my window using "add_provider_for_screen" method.
pub fn add_provider_for_screen(screen: &gdk::Screen, provider: &impl IsA<StyleProvider>, priority: u32)
To do this, I need to convert the window to a GdkScreen using the get_screen() method. However, when I try to do so, I get error: method not found in &gtk::Window . https://docs.gtk.org/gtk3/method.Window.get_screen.html
main.rs code:
use std::process::exit;
use gdk_pixbuf::Pixbuf;
use gtk::{Window, Image, Orientation, WindowType, CssProvider};
use gtk::prelude::{GtkWindowExt, WidgetExt, ContainerExt, ButtonExt, CssProviderExt};
fn main() {
gtk::init().unwrap();
init_window();
gtk::main();
}
fn init_css(win: &gtk::Window) {
let css = CssProvider::new();
css.load_from_path("main.css").unwrap();
let screen = win.gtk_window_get_screen().unwrap();
gtk::StyleContext::add_provider_for_screen(screen, &css, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
}
fn init_window() {
let window = gtk::Window::new(WindowType::Toplevel);
init_css(&window);
// ....
}
Also, if i trying create GdkScreen in fn init_window(), I get a similar error: method not found in gtk::Window
let screen = window.gtk_screen().unwrap();
Cargo.toml content:
[dependencies]
gtk="0.15.5"
gdk="0.15.4"
gdk-pixbuf="0.15.11"

From the documentation, from a Widgnet, use method WidgetExt::screen:
Get the gdk::Screen from the toplevel window associated with this
widget. This function can only be called after the widget has been
added to a widget hierarchy with a Window at the top.

Related

Issue when trying to use the rodio audio crate with a glutin event loop closure

I have a glutin window and OpenGL context and am trying to add sound to my program. I stumbled upon rodio as it seemed the best fit for my project.
Following the docs, I wrote a helper function for loading a file as a sound source and implemented it in my program:
use rodio::Decoder;
use std::{
fs::File,
io::BufReader,
error:Error
}
fn load_sound_file(path: &str) -> Result<Decoder<BufReader<File>>, Box<dyn Error>> {
// load a sound from a file
let file = BufReader::new(File::open(path)?);
// decode that sound into a source
let source = Decoder::new(file)?;
Ok(source)
}
use glutin::event_loop::EventLoop;
use rodio::{ OutputStream, Sink };
fn main() {
let el = EventLoop::new();
...
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let sink = Sink::try_new(&stream_handle).unwrap();
let beep_sound = load_sound_file("beep.ogg").unwrap();
...
el.run(move |event, _, control_flow| {
sink.append(beep_sound);
...
}
}
This doesn't work however, as the compiler complains that it cannot move out of `beep_sound`, a captured variable in an FnMut closure because beep_sound has type Decoder<BufReader<File>> which doesn't implement the Copy trait.
I then tried using a clone of beep_sound:
...
el.run(move |event, _, control_flow| {
let beep_clone = beep_sound.clone();
sink.append(beep_clone);
...
}
But then the compiler complains that there's no method named `clone` found for struct `Decoder<BufReader<File>>` in the current scope.
I'm still inexperienced when it comes to Rust closures and ownership and some help would be much appreciated.

Is there a way to simplify the access to an inner functionality of web_sys?

After reading the Rust book, I've decided to give it a try with Web Assembly. I'm creating a simple tracker script to practice and learn more about it. There are a couple of methods that need to access the window, navigator or cookie API. Every time I have to access any of those there are a lot of boiler plate code involved:
pub fn start() {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let html = document.dyn_into::<web_sys::HtmlDocument>().unwrap();
let cookie = html_document.cookie().unwrap();
}
That's unpractical and bothers me. Is there a smart way to solve this? I've in fact tried to use lazy_static to have all of this in a global.rs file:
#[macro_use]
extern crate lazy_static;
use web_sys::*;
lazy_static! {
static ref WINDOW: window = {
web_sys::window().unwrap()
};
}
But the compile fails with: *mut u8 cannot be shared between threads safely`.
You could use the ? operator instead of unwrapping.
Instead of writing
pub fn start() {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let html = document.dyn_into::<web_sys::HtmlDocument>().unwrap();
let cookie = html_document.cookie().unwrap();
}
You can write
pub fn start() -> Result<()> {
let cookie = web_sys::window()?
.document()?
.dyn_into<web_sys::HtmlDocument>()?
.cookie()?;
Ok(())
}
It's the same number of lines, but less boilerplate and for simpler cases a one-liner.
If you really don't want to return a result you can wrap the whole thing in a lambda, (or a try block if you're happy using unstable features).
pub fn start() {
let cookie = (|| Result<Cookie)> {
web_sys::window()?
.document()?
.dyn_into<web_sys::HtmlDocument>()?
.cookie()
}).unwrap();
}
if you find you don't like repeating this frequently - you can use functions
fn document() -> Result<Document> {
web_sys::window()?.document()
}
fn html() -> Result<web_sys::HtmlDocument> {
document()?.dyn_into<web_sys::HtmlDocument>()
}
fn cookie() -> Result<Cookie> {
html()?.cookie()
}
pub fn start() {
let cookie = cookie()?;
}
That's unpractical and bothers me.
Unsure what's your issue here, but if you access the same cookie again and again in your application, perhaps you can save it in a struct and just use that struct? In my recent WebAssembly project I saved some of the elements I've used in a struct and used them by passing it around.
I also think that perhaps explaining your specific use case might lead to more specific answers :)

Is there a way to avoid cloning when passing a WebView to multiple gtk::Button callbacks?

I'm making a mini web browser with gtk. This code works fine, but I want to avoid all the cloning that is using.
I can't just use the web_view object multiple times because of ownership errors on the closures.
extern crate gio;
extern crate gtk;
extern crate webkit2gtk;
use gio::prelude::*;
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Button, Entry};
use webkit2gtk::{WebView, WebViewExt};
fn main() {
let application =
Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default())
.expect("failed to initialize GTK application");
application.connect_activate(|app| {
let window = ApplicationWindow::new(app);
window.set_title("Web Browser");
window.set_default_size(1024, 768);
let button_back = Button::new_with_label("Back");
let button_next = Button::new_with_label("Next");
let button_reload = Button::new_with_label("Reload");
let url_entry = Entry::new();
url_entry.set_text("https://www.google.com");
let button_go = Button::new_with_label("Go");
let web_view = WebView::new();
web_view.load_uri("https://www.google.com");
let clone1: WebView = web_view.clone();
let clone2: WebView = web_view.clone();
let clone3: WebView = web_view.clone();
let clone4: WebView = web_view.clone();
button_back.connect_clicked(move |_| {
clone1.go_back();
});
button_next.connect_clicked(move |_| {
clone2.go_forward();
});
button_reload.connect_clicked(move |_| {
clone3.reload();
});
button_go.connect_clicked(move |_| {
clone4.load_uri(&url_entry.get_buffer().get_text());
});
window.show_all();
});
application.run(&[]);
}
These are my dependency versions:
[dependencies]
gtk = "0.8.1"
gio = "0.8.1"
webkit2gtk = "0.9.2"
The signature for the method connect_clicked of the trait gtk::ButtonExt is
fn connect_clicked<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId
No, there isn't.
'static on the callback definition forbids it from referencing any temporary variables, and forces it to move and own any values it uses. That's deliberate, because the callback will outlive the function that creates it.
gtk's WebView behaves like Rc, so the clone is very cheap, and doesn't make a copy of anything. It only performs bookkeeping to help the callbacks agree which one of them will be the last to be destroyed, and therefore the one to free the underlying WebView data.
There's a clone! macro in glib that helps making these clones without having to name extra variables by hand.

Is there a way to get the file and the module path of where a procedural macro is attached at compile-time?

I'm looking for the equivalent of file!() & module_path!() in a procedural macro context.
For example, the following doesn't work:
file.rs:
#[some_attribute]
const A: bool = true;
macro.rs:
#[proc_macro_attribute]
pub fn some_attribute(attr: TokenStream, input: TokenStream) -> TokenStream {
println!("{}", file!());
input
}
This prints macro.rs which makes sense, but what I want is file.rs. Is there a way to achieve this? Is there also a similar way for module_path!()?
A requirement of this is that has to happen at compile-time.
I'm trying to create a file in the OUT_DIR containing constant values where the attribute is added with the module and the file that they are in.
I had the same problem and found out that Rust added a new experimential API to Rust macros (#54725) which allows exaclty what you want:
#![feature(proc_macro_span)]
#[proc_macro]
pub(crate) fn do_something(item: TokenStream) -> TokenStream {
let span = Span::call_site();
let source = span.source_file();
format!("println!(r#\"Path: {}\"#)", source.path().to_str().unwrap())
.parse()
.unwrap()
}
use my_macro_crate::*;
fn main() {
println!("Hello, world!");
do_something!();
}
Will output:
Hello, world!
Path: src\main.rs
Important
Apart from this API being experimential, the path might not be a real OS path. This can be the case if the Span was generated by a macro. Visit the documentation here.
The problem here is that println!("{}", file!()); is executed at compile time and not at runtime. Similar to an answer that was recently given here, you can edit the original function and insert your code at the beginning of it, which will be executed at runtime this time. You can still use the procedural macros file!() and module_path!(). Here is a macro.rs with this approach:
#[proc_macro_attribute]
pub fn some_attribute(_attr: TokenStream, input: TokenStream) -> TokenStream {
// prefix to be added to the function's body
let mut prefix: TokenStream = "
println!(\"Called from {:?} inside module path {:?}\",
file!(), module_path!());
".parse().unwrap();
// edit TokenStream
input.into_iter().map(|tt| {
match tt {
TokenTree::Group(ref g) // match function body
if g.delimiter() == proc_macro::Delimiter::Brace => {
// add logic before function body
prefix.extend(g.stream());
// return new function body as TokenTree
TokenTree::Group(proc_macro::Group::new(
proc_macro::Delimiter::Brace, prefix.clone()))
},
other => other, // else just forward
}
}).collect()
}
You can use it like this in your main.rs:
use mylib::some_attribute;
#[some_attribute]
fn yo() -> () { println!("yo"); }
fn main() { yo(); }
Note that the code is added before what's inside of the function's body. We could have inserted it at the end, but this would break the possibility of returning a value without a semicolon.
EDIT: Later realized that the OP wants it to run at compile time.

Can't figure out a function to return a reference to a given type stored in RefCell<Box<Any>>

Most of this is boilerplate, provided as a compilable example. Scroll down.
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::any::{Any, AnyRefExt};
struct Shared {
example: int,
}
struct Widget {
parent: Option<Weak<Box<Widget>>>,
specific: RefCell<Box<Any>>,
shared: RefCell<Shared>,
}
impl Widget {
fn new(specific: Box<Any>,
parent: Option<Rc<Box<Widget>>>) -> Rc<Box<Widget>> {
let parent_option = match parent {
Some(parent) => Some(parent.downgrade()),
None => None,
};
let shared = Shared{pos: 10};
Rc::new(box Widget{
parent: parent_option,
specific: RefCell::new(specific),
shared: RefCell::new(shared)})
}
}
struct Woo {
foo: int,
}
impl Woo {
fn new() -> Box<Any> {
box Woo{foo: 10} as Box<Any>
}
}
fn main() {
let widget = Widget::new(Woo::new(), None);
{
// This is a lot of work...
let cell_borrow = widget.specific.borrow();
let woo = cell_borrow.downcast_ref::<Woo>().unwrap();
println!("{}", woo.foo);
}
// Can the above be made into a function?
// let woo = widget.get_specific::<Woo>();
}
I'm learning Rust and trying to figure out some workable way of doing a widget hierarchy. The above basically does what I need, but it is a bit cumbersome. Especially vexing is the fact that I have to use two statements to convert the inner widget (specific member of Widget). I tried several ways of writing a function that does it all, but the amount of reference and lifetime wizardry is just beyond me.
Can it be done? Can the commented out method at the bottom of my example code be made into reality?
Comments regarding better ways of doing this entire thing are appreciated, but put it in the comments section (or create a new question and link it)
I'll just present a working simplified and more idiomatic version of your code and then explain all the changed I made there:
use std::rc::{Rc, Weak};
use std::any::{Any, AnyRefExt};
struct Shared {
example: int,
}
struct Widget {
parent: Option<Weak<Widget>>,
specific: Box<Any>,
shared: Shared,
}
impl Widget {
fn new(specific: Box<Any>, parent: Option<Rc<Widget>>) -> Widget {
let parent_option = match parent {
Some(parent) => Some(parent.downgrade()),
None => None,
};
let shared = Shared { example: 10 };
Widget{
parent: parent_option,
specific: specific,
shared: shared
}
}
fn get_specific<T: 'static>(&self) -> Option<&T> {
self.specific.downcast_ref::<T>()
}
}
struct Woo {
foo: int,
}
impl Woo {
fn new() -> Woo {
Woo { foo: 10 }
}
}
fn main() {
let widget = Widget::new(box Woo::new() as Box<Any>, None);
let specific = widget.get_specific::<Woo>().unwrap();
println!("{}", specific.foo);
}
First of all, there are needless RefCells inside your structure. RefCells are needed very rarely - only when you need to mutate internal state of an object using only & reference (instead of &mut). This is useful tool for implementing abstractions, but it is almost never needed in application code. Because it is not clear from your code that you really need it, I assume that it was used mistakingly and can be removed.
Next, Rc<Box<Something>> when Something is a struct (like in your case where Something = Widget) is redundant. Putting an owned box into a reference-counted box is just an unnecessary double indirection and allocation. Plain Rc<Widget> is the correct way to express this thing. When dynamically sized types land, it will be also true for trait objects.
Finally, you should try to always return unboxed values. Returning Rc<Box<Widget>> (or even Rc<Widget>) is unnecessary limiting for the callers of your code. You can go from Widget to Rc<Widget> easily, but not the other way around. Rust optimizes by-value returns automatically; if your callers need Rc<Widget> they can box the return value themselves:
let rc_w = box(RC) Widget::new(...);
Same thing is also true for Box<Any> returned by Woo::new().
You can see that in the absence of RefCells your get_specific() method can be implemented very easily. However, you really can't do it with RefCell because RefCell uses RAII for dynamic borrow checks, so you can't return a reference to its internals from a method. You'll have to return core::cell::Refs, and your callers will need to downcast_ref() themselves. This is just another reason to use RefCells sparingly.

Resources