<NME> winit.rs
<BEF> use std::{
    sync::{atomic::Ordering, Mutex},
    time::Duration,
};

use slog::Logger;
#[cfg(feature = "debug")]
use smithay::backend::renderer::ImportMem;
#[cfg(feature = "egl")]
use smithay::{
        wayland_server::{protocol::wl_output, Display},
    },
    wayland::{
        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
        output::{Mode, Output, PhysicalProperties},
        seat::{CursorImageStatus, Seat, XkbConfig},
        shm::init_shm_global,
    },
};

        renderer::{
            damage::{DamageTrackedRenderer, DamageTrackedRendererError},
use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::init_shell;
use crate::AnvilState;

pub fn run_winit(
    display: Rc<RefCell<Display>>,
    mut event_loop: EventLoop<AnvilState>,
    log: Logger,
) -> Result<(), ()> {
    let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
    },
    utils::{IsAlive, Point, Scale, Transform},
    wayland::{compositor, input_method::InputMethodSeat},
};

use crate::state::{AnvilState, Backend, CalloopData};
use crate::{drawing::*, render::*};

pub const OUTPUT_NAME: &str = "winit";

pub struct WinitData {
    backend: WinitGraphicsBackend,
    damage_tracked_renderer: DamageTrackedRenderer,
    #[cfg(feature = "egl")]
    dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
    full_redraw: u8,
    #[cfg(feature = "debug")]
    pub fps: fps_ticker::Fps,
}
    #[cfg(not(feature = "egl"))]
    let buffer_utils = BufferUtils::new(log.clone());

    let name = display
        .borrow_mut()
        .add_socket_auto()
        .unwrap()
        .into_string()
        .unwrap();
    info!(log, "Listening on wayland socket"; "name" => name.clone());
    ::std::env::set_var("WAYLAND_DISPLAY", name);

    let mut state = AnvilState::default();

    /*
     * Initialize the globals
     */

    init_shm_global(&mut display.borrow_mut(), vec![], log.clone());

    let (compositor_token, _, _, window_map) =
        init_shell(&mut display.borrow_mut(), buffer_utils, log.clone());

    let dnd_icon = Arc::new(Mutex::new(None));

    let dnd_icon2 = dnd_icon.clone();
    init_data_device(
        &mut display.borrow_mut(),
        move |event| match event {
            DataDeviceEvent::DnDStarted { icon, .. } => {
                *dnd_icon2.lock().unwrap() = icon;
            }
            DataDeviceEvent::DnDDropped => {
                *dnd_icon2.lock().unwrap() = None;
            }
            _ => {}
        },
        default_action_chooser,
        compositor_token,
        log.clone(),
    );

    let (mut seat, _) = Seat::new(
        &mut display.borrow_mut(),
        "winit".into(),
        compositor_token,
        log.clone(),
    );

    let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));

    let cursor_status2 = cursor_status.clone();
    let pointer = seat.add_pointer(compositor_token.clone(), move |new_status| {
        // TODO: hide winit system cursor when relevant
        *cursor_status2.lock().unwrap() = new_status
    });
    fn reset_buffers(&mut self, _output: &Output) {
        self.full_redraw = 4;
    }
    fn early_import(&mut self, _surface: &wl_surface::WlSurface) {}
}

pub fn run_winit(log: Logger) {
    let mut event_loop = EventLoop::try_new().unwrap();
    let mut display = Display::new().unwrap();

    #[cfg_attr(not(feature = "egl"), allow(unused_mut))]
    let (mut backend, mut winit) = match winit::init(log.clone()) {
        Ok(ret) => ret,
        Err(err) => {
            slog::crit!(log, "Failed to initialize Winit backend: {}", err);
            return;
        }
    };
    let size = backend.window_size().physical_size;

    let mode = Mode {
        size,
        refresh: 60_000,
    };
    let output = Output::new(
        OUTPUT_NAME.to_string(),
        PhysicalProperties {
            size: (0, 0).into(),
            subpixel: Subpixel::Unknown,
            make: "Smithay".into(),
            model: "Winit".into(),
        },
        log.clone(),
    );
    let _global = output.create_global::<AnvilState<WinitData>>(&display.handle());
    output.change_current_state(Some(mode), Some(Transform::Flipped180), None, Some((0, 0).into()));
    output.set_preferred(mode);

        log.clone(),
        pointer,
        keyboard,
        window_map.clone(),
        (0, 0),
        state.running.clone(),
        pointer_location.clone(),
        .renderer()
        .import_memory(
            &fps_image.to_rgba8(),
            (fps_image.width() as i32, fps_image.height() as i32).into(),
            false,
        )
        .expect("Unable to upload FPS texture");
    #[cfg(feature = "debug")]
    let mut fps_element = FpsElement::new(fps_texture);

    let data = {
            frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);

            // draw the windows
            drawer.draw_windows(&mut frame, &*window_map.borrow(), compositor_token);

            let (x, y) = *pointer_location.borrow();
            // draw the dnd icon if any
            {
                let guard = dnd_icon.lock().unwrap();
                if let Some(ref surface) = *guard {
                    if surface.as_ref().is_alive() {
                        drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), compositor_token);
                    }
                }
            }
        let damage_tracked_renderer = DamageTrackedRenderer::from_output(&output);

        WinitData {
            backend,
            damage_tracked_renderer,
            #[cfg(feature = "egl")]
            dmabuf_state,
            full_redraw: 0,
            #[cfg(feature = "debug")]
            fps: fps_ticker::Fps::default(),
                }
                // draw as relevant
                if let CursorImageStatus::Image(ref surface) = *guard {
                    drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), compositor_token);
                }
            }


    info!(log, "Initialization completed, starting the main loop.");

    let mut pointer_element = PointerElement::<Gles2Texture>::default();

    while state.running.load(Ordering::SeqCst) {
        if winit
            .dispatch_new_events(|event| match event {
                WinitEvent::Resized { size, .. } => {
            state.running.store(false, Ordering::SeqCst);
        } else {
            display.borrow_mut().flush_clients(&mut state);
            window_map.borrow_mut().refresh();
        }
    }

    // Cleanup stuff
    window_map.borrow_mut().clear();

    Ok(())
}
                    state.process_input_event_windowed(&display.handle(), event, OUTPUT_NAME)
                }
                _ => (),
            })
            .is_err()
        {
            state.running.store(false, Ordering::SeqCst);
            break;
        }

        // drawing logic
        {
            let backend = &mut state.backend_data.backend;

            let mut cursor_guard = state.cursor_status.lock().unwrap();

            // draw the cursor as relevant
            // reset the cursor if the surface is no longer alive
            let mut reset = false;
            if let CursorImageStatus::Surface(ref surface) = *cursor_guard {
                reset = !surface.alive();
            }
            if reset {
                *cursor_guard = CursorImageStatus::Default;
            }
            let cursor_visible = !matches!(*cursor_guard, CursorImageStatus::Surface(_));

            pointer_element.set_status(cursor_guard.clone());

            #[cfg(feature = "debug")]
            let fps = state.backend_data.fps.avg().round() as u32;
            #[cfg(feature = "debug")]
            fps_element.update_fps(fps);

            let full_redraw = &mut state.backend_data.full_redraw;
            *full_redraw = full_redraw.saturating_sub(1);
            let space = &mut state.space;
            let damage_tracked_renderer = &mut state.backend_data.damage_tracked_renderer;

            let input_method = state.seat.input_method().unwrap();
            let dnd_icon = state.dnd_icon.as_ref();

            let scale = Scale::from(output.current_scale().fractional_scale());
            let cursor_hotspot = if let CursorImageStatus::Surface(ref surface) = *cursor_guard {
                compositor::with_states(surface, |states| {
                    states
                        .data_map
                        .get::<Mutex<CursorImageAttributes>>()
                        .unwrap()
                        .lock()
                        .unwrap()
                        .hotspot
                })
            } else {
                (0, 0).into()
            };
            let cursor_pos = state.pointer_location - cursor_hotspot.to_f64();
            let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round();

            let render_res = backend.bind().and_then(|_| {
                let age = if *full_redraw > 0 {
                    0
                } else {
                    backend.buffer_age().unwrap_or(0)
                };

                let renderer = backend.renderer();

                let mut elements = Vec::<CustomRenderElements<Gles2Renderer>>::new();

                elements.extend(pointer_element.render_elements(cursor_pos_scaled, scale));

                // draw input method surface if any
                let rectangle = input_method.coordinates();
                let position = Point::from((
                    rectangle.loc.x + rectangle.size.w,
                    rectangle.loc.y + rectangle.size.h,
                ));
                input_method.with_surface(|surface| {
                    elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
                        &smithay::desktop::space::SurfaceTree::from_surface(surface),
                        position.to_physical_precise_round(scale),
                        scale,
                    ));
                });

                // draw the dnd icon if any
                if let Some(surface) = dnd_icon {
                    if surface.alive() {
                        elements.extend(AsRenderElements::<Gles2Renderer>::render_elements(
                            &smithay::desktop::space::SurfaceTree::from_surface(surface),
                            cursor_pos_scaled,
                            scale,
                        ));
                    }
                }

                #[cfg(feature = "debug")]
                elements.push(CustomRenderElements::Fps(fps_element.clone()));

                render_output(
                    &output,
                    space,
                    &elements,
                    renderer,
                    damage_tracked_renderer,
                    age,
                    &log,
                )
                .map_err(|err| match err {
                    DamageTrackedRendererError::Rendering(err) => err.into(),
                    _ => unreachable!(),
                })
            });

            match render_res {
                Ok((damage, states)) => {
                    if let Some(damage) = damage {
                        if let Err(err) = backend.submit(Some(&*damage)) {
                            warn!(log, "Failed to submit buffer: {}", err);
                        }
                    }
                    backend.window().set_cursor_visible(cursor_visible);

                    // Send frame events so that client start drawing their next frame
                    state.send_frames(&output, &states);
                }
                Err(SwapBuffersError::ContextLost(err)) => {
                    error!(log, "Critical Rendering Error: {}", err);
                    state.running.store(false, Ordering::SeqCst);
                }
                Err(err) => warn!(log, "Rendering error: {}", err),
            }
        }

        let mut calloop_data = CalloopData { state, display };
        let result = event_loop.dispatch(Some(Duration::from_millis(16)), &mut calloop_data);
        CalloopData { state, display } = calloop_data;

        if result.is_err() {
            state.running.store(false, Ordering::SeqCst);
        } else {
            state.space.refresh();
            state.popups.cleanup();
            display.flush_clients().unwrap();
        }

        #[cfg(feature = "debug")]
        state.backend_data.fps.tick();
    }
}

<MSG> anvil: move common logic into AnvilState

<DFF> @@ -11,10 +11,9 @@ use smithay::{
         wayland_server::{protocol::wl_output, Display},
     },
     wayland::{
-        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
+        data_device::set_data_device_focus,
         output::{Mode, Output, PhysicalProperties},
         seat::{CursorImageStatus, Seat, XkbConfig},
-        shm::init_shm_global,
     },
 };
 
@@ -23,12 +22,11 @@ use slog::Logger;
 use crate::buffer_utils::BufferUtils;
 use crate::glium_drawer::GliumDrawer;
 use crate::input_handler::AnvilInputHandler;
-use crate::shell::init_shell;
 use crate::AnvilState;
 
 pub fn run_winit(
     display: Rc<RefCell<Display>>,
-    mut event_loop: EventLoop<AnvilState>,
+    event_loop: &mut EventLoop<AnvilState>,
     log: Logger,
 ) -> Result<(), ()> {
     let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
@@ -54,56 +52,23 @@ pub fn run_winit(
     #[cfg(not(feature = "egl"))]
     let buffer_utils = BufferUtils::new(log.clone());
 
-    let name = display
-        .borrow_mut()
-        .add_socket_auto()
-        .unwrap()
-        .into_string()
-        .unwrap();
-    info!(log, "Listening on wayland socket"; "name" => name.clone());
-    ::std::env::set_var("WAYLAND_DISPLAY", name);
-
-    let mut state = AnvilState::default();
-
     /*
      * Initialize the globals
      */
 
-    init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
-
-    let (compositor_token, _, _, window_map) =
-        init_shell(&mut display.borrow_mut(), buffer_utils, log.clone());
-
-    let dnd_icon = Arc::new(Mutex::new(None));
-
-    let dnd_icon2 = dnd_icon.clone();
-    init_data_device(
-        &mut display.borrow_mut(),
-        move |event| match event {
-            DataDeviceEvent::DnDStarted { icon, .. } => {
-                *dnd_icon2.lock().unwrap() = icon;
-            }
-            DataDeviceEvent::DnDDropped => {
-                *dnd_icon2.lock().unwrap() = None;
-            }
-            _ => {}
-        },
-        default_action_chooser,
-        compositor_token,
-        log.clone(),
-    );
+    let mut state = AnvilState::init(display.clone(), event_loop.handle(), buffer_utils, log.clone());
 
     let (mut seat, _) = Seat::new(
         &mut display.borrow_mut(),
         "winit".into(),
-        compositor_token,
+        state.ctoken,
         log.clone(),
     );
 
     let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
 
     let cursor_status2 = cursor_status.clone();
-    let pointer = seat.add_pointer(compositor_token.clone(), move |new_status| {
+    let pointer = seat.add_pointer(state.ctoken.clone(), move |new_status| {
         // TODO: hide winit system cursor when relevant
         *cursor_status2.lock().unwrap() = new_status
     });
@@ -148,7 +113,7 @@ pub fn run_winit(
         log.clone(),
         pointer,
         keyboard,
-        window_map.clone(),
+        state.window_map.clone(),
         (0, 0),
         state.running.clone(),
         pointer_location.clone(),
@@ -166,15 +131,15 @@ pub fn run_winit(
             frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
 
             // draw the windows
-            drawer.draw_windows(&mut frame, &*window_map.borrow(), compositor_token);
+            drawer.draw_windows(&mut frame, &*state.window_map.borrow(), state.ctoken);
 
             let (x, y) = *pointer_location.borrow();
             // draw the dnd icon if any
             {
-                let guard = dnd_icon.lock().unwrap();
+                let guard = state.dnd_icon.lock().unwrap();
                 if let Some(ref surface) = *guard {
                     if surface.as_ref().is_alive() {
-                        drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), compositor_token);
+                        drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), state.ctoken);
                     }
                 }
             }
@@ -191,7 +156,7 @@ pub fn run_winit(
                 }
                 // draw as relevant
                 if let CursorImageStatus::Image(ref surface) = *guard {
-                    drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), compositor_token);
+                    drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), state.ctoken);
                 }
             }
 
@@ -207,12 +172,12 @@ pub fn run_winit(
             state.running.store(false, Ordering::SeqCst);
         } else {
             display.borrow_mut().flush_clients(&mut state);
-            window_map.borrow_mut().refresh();
+            state.window_map.borrow_mut().refresh();
         }
     }
 
     // Cleanup stuff
-    window_map.borrow_mut().clear();
+    state.window_map.borrow_mut().clear();
 
     Ok(())
 }

anvil: move common logic into AnvilState