canvas: fix an issue with event coordinate translation by ScrollGroup

If there's a grabbed item (GtkCanvas only at present) then unless it belongs to the scroll
group used for scroll offset translation, the event coordinates should not be translated,
even if the mouse pointer moves into the scroll group.
This commit is contained in:
Paul Davis 2021-12-10 18:17:58 -07:00
parent 3efd26e864
commit 6f91dc0799
2 changed files with 23 additions and 1 deletions

View File

@ -299,6 +299,7 @@ Canvas::window_to_canvas (Duple const & d) const
{
ScrollGroup* best_group = 0;
ScrollGroup* sg = 0;
bool grabbed_item_inside = false;
/* if the coordinates are negative, clamp to zero and find the item
* that covers that "edge" position.
@ -329,7 +330,11 @@ Canvas::window_to_canvas (Duple const & d) const
only group.
*/
if (!best_group || sg->sensitivity() > best_group->sensitivity()) {
best_group = sg;
grabbed_item_inside = check_grabbed_item_inside (sg);
if (sg->sensitivity() == (ScrollGroup::ScrollsVertically | ScrollGroup::ScrollsHorizontally)) {
/* Can't do any better than this. */
break;
@ -338,7 +343,7 @@ Canvas::window_to_canvas (Duple const & d) const
}
}
if (best_group) {
if (best_group && (!have_grab() || grabbed_item_inside)) {
return d.translate (best_group->scroll_offset());
}
@ -1512,6 +1517,16 @@ GtkCanvas::resize_handler ()
return false;
}
bool
GtkCanvas::check_grabbed_item_inside (Item* possible_parent) const
{
if (!_grabbed_item) {
return false;
}
return _grabbed_item->is_descendant_of (*possible_parent);
}
/** Create a GtkCanvaSViewport.
* @param hadj Adjustment to use for horizontal scrolling.
* @param vadj Adjustment to use for vertica scrolling.
@ -1549,3 +1564,4 @@ GtkCanvasViewport::on_size_request (Gtk::Requisition* req)
req->width = width;
req->height = height;
}

View File

@ -91,6 +91,9 @@ public:
/** called to ask the canvas' host to drop keyboard focus on an item */
virtual void unfocus (Item*) = 0;
virtual bool have_grab() const { return false; }
virtual bool check_grabbed_item_inside (Item*) const { return false; }
void render (Rect const &, Cairo::RefPtr<Cairo::Context> const &) const;
void prepare_for_render (Rect const &) const;
@ -214,6 +217,9 @@ public:
void focus (Item *);
void unfocus (Item*);
bool have_grab() const { return _grabbed_item; }
bool check_grabbed_item_inside (Item*) const;
Rect visible_area () const;
Coord width() const;
Coord height() const;