<NME> mod.rs
<BEF> //! Protocol-related utilities
//!
//! This module contains several handlers to manage the Wayland protocol
//! and the clients.
//!
//! ## General structure
//!
//! Most utilities provided in this module work in the same way:
//!
//! - A module specific `*State` struct will take the wayland display as argument and
//!   insert one or more globals into it through its constructor.
//! - The module-`State` will have to be stored inside your global compositor state.
//!   (The same type you parametrized [`wayland_server::Display`] over.)
//! - You need to implement a module-specific `*Handler`-trait for your compositor state.
//!   This implementation will be called when wayland events require custom handling.
//! - Call the matching `delegate_*!` macro from smithay on your state to implement
//!   some required `wayland_server` traits.
//! - If you want to remove a previously inserted global, just drop the `*State`.
//!
//! ## Provided helpers
//!
//! ### Core functionality
//!
//! The most fundamental module is the [`compositor`] module, which provides the necessary
//! logic to handle the fundamental component by which clients build their windows: surfaces.
//! Following this, the [`shell`] module contains the logic allowing clients to use their
//! surface to build concrete windows with the usual interactions. Different kind of shells
//! exist, but in general you will want to support at least the [`xdg`](shell::xdg) variant,
//! which is the standard used by most applications.
//!
    serial: AtomicUsize::new(0),
};

/// A counter for generating serials, for use in the client protocol
///
/// A global instance of this counter is available as the `SERIAL_COUNTER`

impl SerialCounter {
    /// Retrieve the next serial from the counter
    pub fn next_serial(&self) -> u32 {
        self.serial.fetch_add(1, Ordering::AcqRel) as u32
    }
}

<MSG> Implement Serial type to take wrap-around into account

<DFF> @@ -31,6 +31,47 @@ pub static SERIAL_COUNTER: SerialCounter = SerialCounter {
     serial: AtomicUsize::new(0),
 };
 
+/// A serial type, whose comparison takes into account the wrapping-around behavior of the
+/// underlying counter.
+#[derive(Debug, Copy, Clone)]
+pub struct Serial(u32);
+
+impl PartialEq for Serial {
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl Eq for Serial {}
+
+impl PartialOrd for Serial {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        let distance = if self.0 > other.0 {
+            self.0 - other.0
+        } else {
+            other.0 - self.0
+        };
+        if distance < u32::MAX / 2 {
+            self.0.partial_cmp(&other.0)
+        } else {
+            // wrap-around occured, invert comparison
+            other.0.partial_cmp(&self.0)
+        }
+    }
+}
+
+impl From<u32> for Serial {
+    fn from(n: u32) -> Self {
+        Serial(n)
+    }
+}
+
+impl From<Serial> for u32 {
+    fn from(serial: Serial) -> u32 {
+        serial.0
+    }
+}
+
 /// A counter for generating serials, for use in the client protocol
 ///
 /// A global instance of this counter is available as the `SERIAL_COUNTER`
@@ -46,7 +87,7 @@ pub struct SerialCounter {
 
 impl SerialCounter {
     /// Retrieve the next serial from the counter
-    pub fn next_serial(&self) -> u32 {
-        self.serial.fetch_add(1, Ordering::AcqRel) as u32
+    pub fn next_serial(&self) -> Serial {
+        Serial(self.serial.fetch_add(1, Ordering::AcqRel) as u32)
     }
 }

Implement Serial type to take wrap-around into account