diff --git a/api/lua/examples/default/default_config.lua b/api/lua/examples/default/default_config.lua
index 517b744..1a601e2 100644
--- a/api/lua/examples/default/default_config.lua
+++ b/api/lua/examples/default/default_config.lua
@@ -54,6 +54,16 @@ Pinnacle.setup(function()
     end
 
     if Snowcap then
+        Input.keybind({
+            mods = { mod_key },
+            key = "u",
+            on_press = function()
+                require("pinnacle.experimental").mouse_area.new():show()
+            end,
+            group = "Testing",
+            description = "MouseAreaTester"
+        })
+
         -- mod_key + shift + q = Quit Prompt
         Input.keybind({
             mods = { mod_key, "shift" },
diff --git a/api/lua/pinnacle/experimental.lua b/api/lua/pinnacle/experimental.lua
index 3f025f5..61d4114 100644
--- a/api/lua/pinnacle/experimental.lua
+++ b/api/lua/pinnacle/experimental.lua
@@ -1,3 +1,4 @@
+local Log = require("pinnacle.log")
 ---Experimental APIs.
 ---
 ---IMPORTANT: These are unstable and may change at any moment.
@@ -18,6 +19,7 @@ end
 
 ---Input grabbing.
 local input_grab = nil
+local mouse_area = nil
 
 if require("pinnacle.snowcap") then
     input_grab = {}
@@ -59,9 +61,86 @@ if require("pinnacle.snowcap") then
             with_input(grabber, key, mods)
         end)
     end
+
+    mouse_area = {}
+
+    local MouseArea = {}
+
+    function MouseArea:view()
+        local Widget = require("snowcap.widget")
+
+        local area = Widget.mouse_area({
+            child = Widget.container({
+                width = Widget.length.Fixed(220),
+                height = Widget.length.Fixed(120),
+                valign = Widget.alignment.CENTER,
+                halign = Widget.alignment.CENTER,
+                style = {
+                    background_color = Widget.color.from_rgba(0.15, 0.03, 0.1, 0.65),
+                },
+                child = Widget.text({
+                    text = ""
+                }),
+            }),
+            callbacks = {
+                on_press = { msg = "Press" },
+                on_release = { msg = "Release" },
+                on_double_click = { msg = "DoubleClick" },
+                on_right_press = { msg = "RightPress" },
+                on_right_release = { msg = "RightRelease" },
+                on_middle_press = { msg = "MiddlePress" },
+                on_middle_release = { msg = "MiddleRelease" },
+                on_scroll = function(scroll) return { msg = "Scroll", scroll = scroll } end,
+                on_enter = { msg = "Enter" },
+                on_move = function(move) return { msg = "Move", move = move } end,
+                on_exit = { msg = "Exit" }
+            },
+        })
+
+        return area
+    end
+
+    function MouseArea:update(msg)
+        Log.warn("MouseArea:update()")
+        if msg.msg then
+            require("pinnacle.log").warn("Got message " .. msg.msg)
+        end
+    end
+
+    function MouseArea:show()
+        Log.warn("MouseArea:show()")
+        local Layer = require("snowcap.layer")
+        local area = Layer.new_widget({
+            program = self,
+            anchor = nil,
+            keyboard_interactivity = Layer.keyboard_interactivity.EXCLUSIVE,
+            exclusive_zone = "respect",
+            layer = Layer.zlayer.OVERLAY,
+        })
+
+        if not area then
+            return
+        end
+
+        area:on_key_press(function(_, key)
+            if key == require("snowcap.input.keys").Escape then
+                area:close()
+            end
+        end)
+    end
+
+    function mouse_area.new()
+        Log.warn("New mouse area")
+        local area = {}
+        setmetatable(area, { __index = MouseArea })
+
+        return area
+    end
 end
 
 ---Input grabbing.
 experimental.input_grab = input_grab
 
+experimental.mouse_area = mouse_area
+
 return experimental
diff --git a/api/rust/examples/default_config/main.rs b/api/rust/examples/default_config/main.rs
index 4d9f697..98c803f 100644
--- a/api/rust/examples/default_config/main.rs
+++ b/api/rust/examples/default_config/main.rs
@@ -60,6 +60,13 @@ async fn config() {
     //------------------------
     // Keybinds              |
     //------------------------
+    #[cfg(feature = "snowcap")]
+    input::keybind(mod_key, "u")
+        .on_press(|| {
+            pinnacle_api::experimental::mouse_area::MouseAreaTester::new().show()
+        })
+        .group("Testing")
+        .description("MouseAreaTester");
 
     // `mod_key + s` shows the bindings overlay
     #[cfg(feature = "snowcap")]
diff --git a/api/rust/src/experimental.rs b/api/rust/src/experimental.rs
index 2282200..70d89d4 100644
--- a/api/rust/src/experimental.rs
+++ b/api/rust/src/experimental.rs
@@ -87,3 +87,86 @@ pub mod input_grab {
         });
     }
 }
+
+#[cfg(feature = "snowcap")]
+pub mod mouse_area {
+    use snowcap_api::{layer::{ExclusiveZone, KeyboardInteractivity, ZLayer}, widget::{container::Container, mouse_area::MouseArea, text::Text, Alignment, Length, Program}};
+
+    /// Test MouseArea
+    pub struct MouseAreaTester;
+
+    #[derive(Debug, Clone)]
+    pub enum Event {
+        Press,
+        Release,
+        DoubleClick,
+        RightPress,
+        RightRelease,
+        MiddlePress,
+        MiddleRelease,
+        Scroll(snowcap_api::widget::mouse_area::ScrollDelta),
+        Enter,
+        Move(snowcap_api::widget::mouse_area::Point),
+        Exit,
+    }
+
+    impl Program for MouseAreaTester {
+        type Message = Event;
+
+        fn view(&self) -> snowcap_api::widget::WidgetDef<Self::Message> {
+            println!("view called");
+            let widget =
+                MouseArea::new(Container::new(Text::new(""))
+                    .width(Length::Fixed(220.0))
+                    .height(Length::Fixed(120.0))
+                    .vertical_alignment(Alignment::Center)
+                    .horizontal_alignment(Alignment::Center)
+                    .style(snowcap_api::widget::container::Style {
+                        text_color: None,
+                        background_color: Some([0.15, 0.03, 0.1, 0.65].into()),
+                        border: None,
+                    })
+                )
+                .interaction(snowcap_api::widget::mouse_area::Interaction::Grab)
+                .on_press(Event::Press)
+                .on_release(Event::Release)
+                .on_double_click(Event::DoubleClick)
+                .on_right_press(Event::RightPress)
+                .on_right_release(Event::RightRelease)
+                .on_middle_press(Event::MiddlePress)
+                .on_middle_release(Event::MiddleRelease)
+                .on_scroll(|evt| Event::Scroll(evt))
+                .on_enter(Event::Enter)
+                .on_move(|evt| Event::Move(evt))
+                .on_exit(Event::Exit);
+
+            widget.into()
+        }
+
+        fn update(&mut self, msg: Self::Message) {
+            println!("UPDATE {msg:#?}");
+        }
+    }
+
+    impl MouseAreaTester {
+        /// Create a MouseAreaTester
+        pub fn new() -> Self {
+            Self
+        }
+
+        /// Shows this MouseAreaTester
+        pub fn show(self) {
+            snowcap_api::layer::new_widget(
+                self,
+                None,
+                KeyboardInteractivity::Exclusive,
+                ExclusiveZone::Respect,
+                ZLayer::Overlay
+            )
+            .unwrap()
+            .on_key_press(|hndl, _key, _mods| {
+                hndl.close();
+            });
+        }
+    }
+}
diff --git a/snowcap/api/rust/src/layer.rs b/snowcap/api/rust/src/layer.rs
index 6f5e794..be8eebc 100644
--- a/snowcap/api/rust/src/layer.rs
+++ b/snowcap/api/rust/src/layer.rs
@@ -169,6 +169,7 @@ where
 
     tokio::spawn(async move {
         loop {
+            let curr_id = format!("{:?}", callbacks.keys());
             tokio::select! {
                 Some(Ok(response)) = event_stream.next() => {
                     for widget_event in response.widget_events {
@@ -197,6 +198,7 @@ where
                         };
 
                         let Some(msg) = msg else {
+                            println!("dropped event {id:?}\navail id: {curr_id:?}");
                             continue;
                         };
 
