Winit doesn't allow lifetimes

Hi,

I'm trying to write simple winit app. Here is a part of the code. window_manager contains a vector of virtual windows that are drawn in a winit window as rectangles.

struct MyApp<'a> {
    window: Option<Arc<Window>>,
    window_mananger: window_manager::WindowManager<'a>,

}

const WIDTH: i32 = 1280;
const HEIGHT: i32 = 720;

impl<'a> ApplicationHandler for MyApp<'a> {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        let window_attributes = Window::default_attributes().with_inner_size(PhysicalSize::new(WIDTH, HEIGHT));
        let window = event_loop.create_window(window_attributes).unwrap();

        self.window_mananger.create_window(640, 360, (-25, -25));
        self.window_mananger.create_window(640, 360, (665, -25));
        self.window_mananger.create_window(640, 360, (-25, 385));
        self.window_mananger.create_window(640, 360, (665, 385));
    }

    fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
        match event {
            WindowEvent::CloseRequested => {
                println!("The close button was pressed; stopping");
                event_loop.exit();
            },
            ...
            WindowEvent::CursorMoved { position, .. } => {
                let window = self.window_mananger.find_window(position.x, position.y as i32);
            }
            _ => (),
        }
    }
}

The compiler tells:

lifetime may not live long enough
argument requires that `'1` must outlive `'a`

for the line:

 let window = self.window_mananger.find_window(position.x, position.y as i32);

I think I understand what it means. I have to specify a lifetime for &mut self in window_event method. But if I set the lifetime for this parameter, the compiler says:

method not compatible with trait
expected signature `fn(&mut MyApp<'_>, &ActiveEventLoop, WindowId, winit::event::WindowEvent)`
   found signature `fn(&'a mut MyApp<'_>, &ActiveEventLoop, WindowId, winit::event::WindowEvent)

Is the problem with my abstractions or or is this a limitation of winit? Is there any workaround for this?

The problems you are having are most likely with how you have defined WindowManager, not with using it from winit. Please share

  • the definition of WindowManager,
  • the impl block for WindowManager, and
  • the code you use to construct MyApp and WindowManager.

You should probably be designing it in some way that does not have a lifetime, because it is usually a mistake to use borrows in your long-lived application data structures, but I can't say exactly what the specific problem is without more information.

2 Likes

Sure

pub struct WindowManager<'a> {
    pub next_id: AtomicU64,
    pub virtual_windows: Vec<VirtualWindow>,
    pub focused_window: Option<&'a VirtualWindow>
}

impl<'a> Default for WindowManager<'a> {
    fn default() -> Self {
        Self {
            next_id: AtomicU64::new(0),
            virtual_windows: vec![],
            focused_window: None
        }
    }
}

impl<'a> WindowManager<'a> {
    pub fn create_window(&mut self, w: i32, h: i32, position: (i32, i32)) {
        let window = VirtualWindow{
            id: self.get_id(),
            w: w,
            h: h,
            position: position
        };

        self.virtual_windows.push(window);
    }

    fn get_id(&mut self) -> u64 {
        self.next_id.fetch_add(1, Ordering::Relaxed)
    }

    pub fn find_fwindow(&'a mut self, x: i32, y: i32) {
        self.focused_window = self.virtual_windows.iter().find(|w| w.contains(x, y));
    }
}

pub struct VirtualWindow {
    pub id: u64,
    pub position: (i32, i32),
    pub w: i32,
    pub h: i32,
}

impl VirtualWindow {
    pub fn contains(&self, x: i32, y:i32) -> bool {
        let left = self.position.0;
        let top = self.position.1;
        let right = left + self.w;
        let bottom = top + self.h;

        x >= left && x <= right && y >= top && y <= bottom
    }
}

MyApp construction:

   let event_loop = EventLoop::new().unwrap();
    event_loop.set_control_flow(ControlFlow::Poll);

    let mut app = MyApp::default();
    let result = event_loop.run_app(&mut app);

That's a self-referencial struct, which is generally unusable. Store an index or such instead, and lose the lifetime.

1 Like

More broadly, even outside of self-referential cases, it is usually unwise to build your stateful application data structures out of references (unless you know exactly what you’re doing). References should only be used when they are &'static or for temporary access to other things, no longer than a single function call.

1 Like

I see it now, thank you. Switched to using Rc<VirtualWindow> instead.