Does TextEditor prevent MouseArea from detecting release?

I have a TextEditor in a MouseArea and I’m doing some custom selection logic. The MouseArea is there to detect when the left mouse button is released (since as far as I’m aware this can’t be detected by any of the text_area::Actions).

mouse_area(
    text_editor(&state.srcbuf)
        .wrapping(iced::widget::text::Wrapping::None)
        .on_action(Message::ClickSrc)
        .width(500)
)
.on_release(Message::ReleaseSrc)

The problem is that when I release the left mouse button while hovering over the TextEditor/MouseArea, no Message::ReleaseSrc is generated. Can someone tell me what I’m doing wrong?

In case anyone runs into this in the future, here is how I solved it (with the help of a kind soul in the Rust Community Discord server).

It turns out that TextEditor captures the mouse event and MouseArea says “alright, that’s handled then” and ignores it. So I wrapped the text_editor in a custom Widget (based on the code of MouseArea) that never reports an event as captured.

// main.rs

mouse_area(
    no_capture(
        text_editor(&state.srcbuf)
            .wrapping(iced::widget::text::Wrapping::None)
            .on_action(Message::ClickSrc)
            .width(500)
    )
)
.on_release(Message::ReleaseSrc)
// no_capture.rs

//! A container that ignores event captures.
//! Copied (and trimmed) from iced::widget::MouseArea.

use iced::advanced::layout;
use iced::advanced::mouse;
use iced::advanced::overlay;
use iced::advanced::renderer;
use iced::advanced::widget::{tree, Operation, Tree};
use iced::advanced::{Clipboard, Layout, Shell, Widget};
use iced::event::{self, Event};
use iced::{Element, Length, Rectangle, Size, Vector};

pub fn no_capture<'a, Message, Theme, Renderer>(
    content: impl Into<Element<'a, Message, Theme, Renderer>>,
) -> NoCapture<'a, Message, Theme, Renderer> {
    NoCapture {
        content: content.into(),
    }
}

/// Emit messages on mouse events.
#[allow(missing_debug_implementations)]
pub struct NoCapture<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer> {
    content: Element<'a, Message, Theme, Renderer>,
}

impl<'a, Message, Theme, Renderer> NoCapture<'a, Message, Theme, Renderer> {
    /// Creates a [`NoCapture`] with the given content.
    pub fn new(content: impl Into<Element<'a, Message, Theme, Renderer>>) -> Self {
        NoCapture {
            content: content.into(),
        }
    }
}

#[derive(Default)]
enum State {
    #[default]
    None,
}

impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
    for NoCapture<'_, Message, Theme, Renderer>
where
    Renderer: renderer::Renderer,
    Message: Clone,
{
    fn tag(&self) -> tree::Tag {
        tree::Tag::of::<State>()
    }

    fn state(&self) -> tree::State {
        tree::State::new(State::default())
    }

    fn children(&self) -> Vec<Tree> {
        vec![Tree::new(&self.content)]
    }

    fn diff(&self, tree: &mut Tree) {
        tree.diff_children(std::slice::from_ref(&self.content));
    }

    fn size(&self) -> Size<Length> {
        self.content.as_widget().size()
    }

    fn layout(
        &self,
        tree: &mut Tree,
        renderer: &Renderer,
        limits: &layout::Limits,
    ) -> layout::Node {
        self.content
            .as_widget()
            .layout(&mut tree.children[0], renderer, limits)
    }

    fn operate(
        &self,
        tree: &mut Tree,
        layout: Layout<'_>,
        renderer: &Renderer,
        operation: &mut dyn Operation,
    ) {
        self.content
            .as_widget()
            .operate(&mut tree.children[0], layout, renderer, operation);
    }

    fn on_event(
        &mut self,
        tree: &mut Tree,
        event: Event,
        layout: Layout<'_>,
        cursor: mouse::Cursor,
        renderer: &Renderer,
        clipboard: &mut dyn Clipboard,
        shell: &mut Shell<'_, Message>,
        viewport: &Rectangle,
    ) -> event::Status {
        self.content.as_widget_mut().on_event(
            &mut tree.children[0],
            event.clone(),
            layout,
            cursor,
            renderer,
            clipboard,
            shell,
            viewport,
        );
        event::Status::Ignored
    }

    fn mouse_interaction(
        &self,
        tree: &Tree,
        layout: Layout<'_>,
        cursor: mouse::Cursor,
        viewport: &Rectangle,
        renderer: &Renderer,
    ) -> mouse::Interaction {
        self.content.as_widget().mouse_interaction(
            &tree.children[0],
            layout,
            cursor,
            viewport,
            renderer,
        )
    }

    fn draw(
        &self,
        tree: &Tree,
        renderer: &mut Renderer,
        theme: &Theme,
        renderer_style: &renderer::Style,
        layout: Layout<'_>,
        cursor: mouse::Cursor,
        viewport: &Rectangle,
    ) {
        self.content.as_widget().draw(
            &tree.children[0],
            renderer,
            theme,
            renderer_style,
            layout,
            cursor,
            viewport,
        );
    }

    fn overlay<'b>(
        &'b mut self,
        tree: &'b mut Tree,
        layout: Layout<'_>,
        renderer: &Renderer,
        translation: Vector,
    ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
        self.content
            .as_widget_mut()
            .overlay(&mut tree.children[0], layout, renderer, translation)
    }
}

impl<'a, Message, Theme, Renderer> From<NoCapture<'a, Message, Theme, Renderer>>
    for Element<'a, Message, Theme, Renderer>
where
    Message: 'a + Clone,
    Theme: 'a,
    Renderer: 'a + renderer::Renderer,
{
    fn from(
        area: NoCapture<'a, Message, Theme, Renderer>,
    ) -> Element<'a, Message, Theme, Renderer> {
        Element::new(area)
    }
}