<NME> winit.rs
<BEF> #[macro_use]
extern crate glium;
extern crate rand;
#[macro_use]
extern crate slog;
extern crate slog_async;
extern crate slog_term;
#[macro_use(define_roles)]
extern crate smithay;
extern crate wayland_server;

mod helpers;

use glium::Surface;
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap};
use slog::{Drain, Logger};
use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent,
                              PointerButtonEvent, PointerMotionAbsoluteEvent};
use smithay::backend::winit;
use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction};
use smithay::wayland::compositor::roles::Role;
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell;
use std::rc::Rc;
use wayland_server::Display;
use wayland_server::protocol::{wl_output, wl_pointer};

struct WinitInputHandler {
    log: Logger,
        SwapBuffersError,
    },
    input::pointer::{CursorImageAttributes, CursorImageStatus},
    output::{Mode, Output, PhysicalProperties, Subpixel},
    reexports::{
        calloop::EventLoop,
        wayland_server::{protocol::wl_surface, Display},
    },
    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(feature = "egl")]
impl DmabufHandler for AnvilState<WinitData> {
    fn dmabuf_state(&mut self) -> &mut DmabufState {
        &mut self.backend_data.dmabuf_state.as_mut().unwrap().0
    }

    fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<(), ImportError> {
        self.backend_data
            .backend
            .renderer()
            .import_dmabuf(&dmabuf, None)
            .map(|_| ())
            .map_err(|_| ImportError::Failed)
    }
}
#[cfg(feature = "egl")]
delegate_dmabuf!(AnvilState<WinitData>);

impl Backend for WinitData {
    fn seat_name(&self) -> String {
        String::from("winit")
    }
    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;
    }
    fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) {
        let source = match evt.source() {
            input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
            input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel,
            _ => unreachable!(), //winit does not have more specific sources
        };
        let horizontal_amount = evt.amount(&input::Axis::Horizontal)
            size: (0, 0).into(),
            subpixel: Subpixel::Unknown,
            make: "Smithay".into(),
            model: "Winit".into(),
        },
        log.clone(),
    );
    let _global = output.create_global::<AnvilState<WinitData>>(&display.handle());
            event.source(source);
            if horizontal_amount != 0.0 {
                event.value(
                    wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
                    horizontal_amount,
                    evt.time(),
                );
                if let Some(discrete) = horizontal_amount_discrete {
                    event.discrete(
                        wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
                        discrete as i32,
                    );
                }
            }
            if vertical_amount != 0.0 {
                event.value(
                    wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
                    vertical_amount,
                    evt.time(),
                );
                if let Some(discrete) = vertical_amount_discrete {
                    event.discrete(
                        wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
                        discrete as i32,
                    );
                }
            let global = state.create_global::<AnvilState<WinitData>, _>(
                &display.handle(),
                dmabuf_formats,
                log.clone(),
            );
            Some((state, global))
        } else {
            None
        };

        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(),
        }
    }
}

fn main() {
    // A logger facility, here we use the terminal for this example
    let log = Logger::root(
        slog_async::Async::default(slog_term::term_full().fuse()).fuse(),
        o!(),
    );

    // Initialize a simple backend for testing
    let (renderer, mut input) = winit::init(log.clone()).unwrap();

    let (mut display, mut event_loop) = wayland_server::Display::new();

    let egl_display = Rc::new(RefCell::new(
        if let Ok(egl_display) = renderer.bind_wl_display(&display) {

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

    while state.running.load(Ordering::SeqCst) {
        if winit
            .dispatch_new_events(|event| match event {
                WinitEvent::Resized { size, .. } => {
    let (w, h) = renderer.get_framebuffer_dimensions();
    let drawer = GliumDrawer::from(renderer);

    /*
     * Initialize the globals
     */

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

    let (compositor_token, _, _, window_map) =
        init_shell(&mut display, event_loop.token(), log.clone(), egl_display);

    let (mut seat, _) = Seat::new(
        &mut display,
        event_loop.token(),
        "winit".into(),
        log.clone(),

        // drawing logic
        {
            let backend = &mut state.backend_data.backend;
        .expect("Failed to initialize the keyboard");

    let (output, _) = Output::new(
        &mut display,
        event_loop.token(),
        "Winit".into(),
        PhysicalProperties {
                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()
        serial: 0,
    });

    /*
     * Add a listening socket:
     */
    let name = display.add_socket_auto().unwrap().into_string().unwrap();
    println!("Listening on socket: {}", name);

    loop {
        input.dispatch_new_events().unwrap();
            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 {
                                            },
                                            (x, y),
                                            screen_dimensions,
                                            glium::Blend {
                                                color: glium::BlendingFunction::Addition {
                                                    source: glium::LinearBlendingFactor::One,
                                                    destination:
                                                        glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                                },
                                                alpha: glium::BlendingFunction::Addition {
                                                    source: glium::LinearBlendingFactor::One,
                                                    destination:
                                                        glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                                },
                                                ..Default::default()
                                            },
            }
        }

        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")]

        window_map.borrow_mut().refresh();
    }
}

<MSG> move examples into our own compositor: anvil

<DFF> @@ -1,33 +1,25 @@
-#[macro_use]
-extern crate glium;
-extern crate rand;
-#[macro_use]
-extern crate slog;
-extern crate slog_async;
-extern crate slog_term;
-#[macro_use(define_roles)]
-extern crate smithay;
-extern crate wayland_server;
-
-mod helpers;
+use std::cell::RefCell;
+use std::rc::Rc;
 
-use glium::Surface;
-use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap};
-use slog::{Drain, Logger};
-use smithay::backend::graphics::egl::EGLGraphicsBackend;
-use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
-use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent,
-                              PointerButtonEvent, PointerMotionAbsoluteEvent};
-use smithay::backend::winit;
+use smithay::wayland::shm::init_shm_global;
+use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
 use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction};
 use smithay::wayland::compositor::roles::Role;
 use smithay::wayland::output::{Mode, Output, PhysicalProperties};
-use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
-use smithay::wayland::shm::init_shm_global;
-use std::cell::RefCell;
-use std::rc::Rc;
-use wayland_server::Display;
-use wayland_server::protocol::{wl_output, wl_pointer};
+use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent,
+                              PointerButtonEvent, PointerMotionAbsoluteEvent};
+use smithay::backend::winit;
+use smithay::backend::graphics::egl::EGLGraphicsBackend;
+use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
+use smithay::wayland_server::{Display, EventLoop};
+use smithay::wayland_server::protocol::{wl_pointer, wl_output};
+
+use glium::Surface;
+
+use slog::Logger;
+
+use glium_drawer::GliumDrawer;
+use shell::{init_shell, MyWindowMap, Buffer};
 
 struct WinitInputHandler {
     log: Logger,
@@ -102,8 +94,8 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
     }
     fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) {
         let source = match evt.source() {
-            input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
-            input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel,
+            input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
+            input::AxisSource::Wheel => wl_pointer::AxisSource::Wheel,
             _ => unreachable!(), //winit does not have more specific sources
         };
         let horizontal_amount = evt.amount(&input::Axis::Horizontal)
@@ -118,26 +110,26 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
             event.source(source);
             if horizontal_amount != 0.0 {
                 event.value(
-                    wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
+                    wl_pointer::Axis::HorizontalScroll,
                     horizontal_amount,
                     evt.time(),
                 );
                 if let Some(discrete) = horizontal_amount_discrete {
                     event.discrete(
-                        wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
+                        wl_pointer::Axis::HorizontalScroll,
                         discrete as i32,
                     );
                 }
             }
             if vertical_amount != 0.0 {
                 event.value(
-                    wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
+                    wl_pointer::Axis::VerticalScroll,
                     vertical_amount,
                     evt.time(),
                 );
                 if let Some(discrete) = vertical_amount_discrete {
                     event.discrete(
-                        wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
+                        wl_pointer::Axis::VerticalScroll,
                         discrete as i32,
                     );
                 }
@@ -165,17 +157,8 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
     }
 }
 
-fn main() {
-    // A logger facility, here we use the terminal for this example
-    let log = Logger::root(
-        slog_async::Async::default(slog_term::term_full().fuse()).fuse(),
-        o!(),
-    );
-
-    // Initialize a simple backend for testing
-    let (renderer, mut input) = winit::init(log.clone()).unwrap();
-
-    let (mut display, mut event_loop) = wayland_server::Display::new();
+pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> {
+    let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
 
     let egl_display = Rc::new(RefCell::new(
         if let Ok(egl_display) = renderer.bind_wl_display(&display) {
@@ -189,17 +172,21 @@ fn main() {
     let (w, h) = renderer.get_framebuffer_dimensions();
     let drawer = GliumDrawer::from(renderer);
 
+    let name = display.add_socket_auto().unwrap().into_string().unwrap();
+    info!(log, "Listening on wayland socket"; "name" => name.clone());
+    ::std::env::set_var("WAYLAND_DISPLAY", name);
+
     /*
      * Initialize the globals
      */
 
-    init_shm_global(&mut display, event_loop.token(), vec![], log.clone());
+    init_shm_global(display, event_loop.token(), vec![], log.clone());
 
     let (compositor_token, _, _, window_map) =
-        init_shell(&mut display, event_loop.token(), log.clone(), egl_display);
+        init_shell(display, event_loop.token(), log.clone(), egl_display);
 
     let (mut seat, _) = Seat::new(
-        &mut display,
+        display,
         event_loop.token(),
         "winit".into(),
         log.clone(),
@@ -210,7 +197,7 @@ fn main() {
         .expect("Failed to initialize the keyboard");
 
     let (output, _) = Output::new(
-        &mut display,
+        display,
         event_loop.token(),
         "Winit".into(),
         PhysicalProperties {
@@ -247,11 +234,7 @@ fn main() {
         serial: 0,
     });
 
-    /*
-     * Add a listening socket:
-     */
-    let name = display.add_socket_auto().unwrap().into_string().unwrap();
-    println!("Listening on socket: {}", name);
+    info!(log, "Initialization completed, starting the main loop.");
 
     loop {
         input.dispatch_new_events().unwrap();
@@ -317,16 +300,16 @@ fn main() {
                                             },
                                             (x, y),
                                             screen_dimensions,
-                                            glium::Blend {
-                                                color: glium::BlendingFunction::Addition {
-                                                    source: glium::LinearBlendingFactor::One,
+                                            ::glium::Blend {
+                                                color: ::glium::BlendingFunction::Addition {
+                                                    source: ::glium::LinearBlendingFactor::One,
                                                     destination:
-                                                        glium::LinearBlendingFactor::OneMinusSourceAlpha,
+                                                        ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                                 },
-                                                alpha: glium::BlendingFunction::Addition {
-                                                    source: glium::LinearBlendingFactor::One,
+                                                alpha: ::glium::BlendingFunction::Addition {
+                                                    source: ::glium::LinearBlendingFactor::One,
                                                     destination:
-                                                        glium::LinearBlendingFactor::OneMinusSourceAlpha,
+                                                        ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                                 },
                                                 ..Default::default()
                                             },
@@ -349,4 +332,4 @@ fn main() {
 
         window_map.borrow_mut().refresh();
     }
-}
+}
\ No newline at end of file

move examples into our own compositor: anvil