<NME> xdg_shell.rs
<BEF> use smithay::{
    delegate_xdg_shell,
    desktop::{Kind, Window, WindowSurfaceType},
    reexports::{
        wayland_protocols::xdg::shell::server::xdg_toplevel,
        wayland_server::{
        wayland_protocols::xdg::shell::server::xdg_toplevel,
        wayland_server::{
            protocol::{wl_seat, wl_surface::WlSurface},
    },
    utils::Rectangle,
    wayland::{
        seat::{Focus, PointerGrabStartData, Seat},
        shell::xdg::{PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState},
        Serial,
    },
};

use crate::{
    grabs::{MoveSurfaceGrab, ResizeSurfaceGrab},
    Smallvil,
};

impl XdgShellHandler for Smallvil {
    fn xdg_shell_state(&mut self) -> &mut XdgShellState {
        &mut self.xdg_shell_state
    }

    fn new_toplevel(&mut self, _dh: &DisplayHandle, surface: ToplevelSurface) {
        let window = Window::new(Kind::Xdg(surface.clone()));
        self.space.map_window(&window, (0, 0), None, false);

        surface.send_configure();
    }
    fn new_popup(&mut self, _dh: &DisplayHandle, _surface: PopupSurface, _positioner: PositionerState) {}

        // TODO: Popup handling using PopupManager
    }

    fn move_request(&mut self, surface: ToplevelSurface, seat: wl_seat::WlSeat, serial: Serial) {
        let seat = Seat::from_resource(&seat).unwrap();

        let wl_surface = surface.wl_surface();

        if let Some(start_data) = check_grab(&seat, wl_surface, serial) {
            let pointer = seat.get_pointer().unwrap();

            let window = self
                .space
                .elements()
                .find(|w| w.toplevel().wl_surface() == wl_surface)
                .unwrap()
                .clone();
            let initial_window_location = self.space.element_location(&window).unwrap();

            let grab = MoveSurfaceGrab {
                start_data,
                window,
                initial_window_location,
            };

            pointer.set_grab(self, grab, serial, Focus::Clear);
        }
    }

    fn resize_request(
        &mut self,
        surface: ToplevelSurface,
        seat: wl_seat::WlSeat,
        serial: Serial,
        edges: xdg_toplevel::ResizeEdge,
    ) {
        let seat = Seat::from_resource(&seat).unwrap();

        let wl_surface = surface.wl_surface();

        if let Some(start_data) = check_grab(&seat, wl_surface, serial) {
            let pointer = seat.get_pointer().unwrap();

            let window = self
                .space
                .elements()
                .find(|w| w.toplevel().wl_surface() == wl_surface)
                .unwrap()
                .clone();
            let initial_window_location = self.space.element_location(&window).unwrap();
            let initial_window_size = window.geometry().size;

            surface.with_pending_state(|state| {
                state.states.set(xdg_toplevel::State::Resizing);
            });

            surface.send_configure();

            let grab = ResizeSurfaceGrab::start(
                start_data,
                window,
                edges.into(),
                Rectangle::from_loc_and_size(initial_window_location, initial_window_size),
            );

            pointer.set_grab(self, grab, serial, Focus::Clear);
        }
    }

    fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
        // TODO popup grabs
    }
}

// Xdg Shell
delegate_xdg_shell!(Smallvil);

fn check_grab(
    seat: &Seat<Smallvil>,
    surface: &WlSurface,
    serial: Serial,
) -> Option<PointerGrabStartData<Smallvil>> {
    let pointer = seat.get_pointer()?;

    // Check that this surface has a click grab.
    if !pointer.has_grab(serial) {
        return None;
    }

    let start_data = pointer.grab_start_data()?;

    let (focus, _) = start_data.focus.as_ref()?;
    // If the focus was for a different surface, ignore the request.
    if !focus.id().same_client_as(&surface.id()) {

    Some(start_data)
}

    Some(())
}

<MSG> Merge pull request #649 from cmeissl/fix/smallvil_initial_configure

smallvil: send initial configure on commit
<DFF> @@ -1,6 +1,8 @@
+use std::sync::Mutex;
+
 use smithay::{
     delegate_xdg_shell,
-    desktop::{Kind, Window, WindowSurfaceType},
+    desktop::{Kind, Space, Window, WindowSurfaceType},
     reexports::{
         wayland_protocols::xdg::shell::server::xdg_toplevel,
         wayland_server::{
@@ -10,8 +12,12 @@ use smithay::{
     },
     utils::Rectangle,
     wayland::{
+        compositor::with_states,
         seat::{Focus, PointerGrabStartData, Seat},
-        shell::xdg::{PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState},
+        shell::xdg::{
+            PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
+            XdgToplevelSurfaceRoleAttributes,
+        },
         Serial,
     },
 };
@@ -27,10 +33,8 @@ impl XdgShellHandler for Smallvil {
     }
 
     fn new_toplevel(&mut self, _dh: &DisplayHandle, surface: ToplevelSurface) {
-        let window = Window::new(Kind::Xdg(surface.clone()));
+        let window = Window::new(Kind::Xdg(surface));
         self.space.map_window(&window, (0, 0), None, false);
-
-        surface.send_configure();
     }
     fn new_popup(&mut self, _dh: &DisplayHandle, _surface: PopupSurface, _positioner: PositionerState) {}
 
@@ -131,3 +135,28 @@ fn check_grab(seat: &Seat<Smallvil>, surface: &WlSurface, serial: Serial) -> Opt
 
     Some(start_data)
 }
+
+/// Should be called on `WlSurface::commit`
+pub fn handle_commit(space: &Space, surface: &WlSurface) -> Option<()> {
+    let window = space
+        .window_for_surface(surface, WindowSurfaceType::TOPLEVEL)
+        .cloned()?;
+
+    if let Kind::Xdg(_) = window.toplevel() {
+        let initial_configure_sent = with_states(surface, |states| {
+            states
+                .data_map
+                .get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
+                .unwrap()
+                .lock()
+                .unwrap()
+                .initial_configure_sent
+        });
+
+        if !initial_configure_sent {
+            window.configure();
+        }
+    }
+
+    Some(())
+}

Merge pull request #649 from cmeissl/fix/smallvil_initial_configure