diff --git a/lib/matplotlib/tests/test_text.py b/lib/matplotlib/tests/test_text.py index c26edeb55abd..10685f62db85 100644 --- a/lib/matplotlib/tests/test_text.py +++ b/lib/matplotlib/tests/test_text.py @@ -6,6 +6,7 @@ import pytest import matplotlib +from matplotlib.backend_bases import MouseEvent import matplotlib.patches as mpatches import matplotlib.pyplot as plt from matplotlib.testing.decorators import image_comparison @@ -204,13 +205,10 @@ def test_afm_kerning(): @image_comparison(baseline_images=['text_contains'], extensions=['png']) def test_contains(): - import matplotlib.backend_bases as mbackend - fig = plt.figure() ax = plt.axes() - mevent = mbackend.MouseEvent( - 'button_press_event', fig.canvas, 0.5, 0.5, 1, None) + mevent = MouseEvent('button_press_event', fig.canvas, 0.5, 0.5, 1, None) xs = np.linspace(0.25, 0.75, 30) ys = np.linspace(0.25, 0.75, 30) @@ -236,6 +234,19 @@ def test_contains(): ax.viewLim.set(vl) +def test_annotation_contains(): + # Check that Annotation.contains looks at the bboxes of the text and the + # arrow separately, not at the joint bbox. + fig, ax = plt.subplots() + ann = ax.annotate( + "hello", xy=(.4, .4), xytext=(.6, .6), arrowprops={"arrowstyle": "->"}) + fig.canvas.draw() # Needed for the same reason as in test_contains. + event = MouseEvent( + "button_press_event", fig.canvas, + *ax.transData.transform_point((.5, .6))) + assert ann.contains(event) == (False, {}) + + @image_comparison(baseline_images=['titles']) def test_titles(): # left and right side titles diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index b5a3567dfe70..8450b60d0891 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -200,7 +200,10 @@ def contains(self, mouseevent): if not self.get_visible() or self._renderer is None: return False, {} - l, b, w, h = self.get_window_extent().bounds + # Explicitly use Text.get_window_extent(self) and not + # self.get_window_extent() so that Annotation.contains does not + # accidentally cover the entire annotation bounding box. + l, b, w, h = Text.get_window_extent(self).bounds r, t = l + w, b + h x, y = mouseevent.x, mouseevent.y @@ -2187,11 +2190,12 @@ def transform(renderer) -> Transform self.arrow_patch = None def contains(self, event): + if self._contains is not None: + return self._contains(self, event) contains, tinfo = Text.contains(self, event) if self.arrow_patch is not None: in_patch, _ = self.arrow_patch.contains(event) contains = contains or in_patch - return contains, tinfo @property