Fit the split on a double-click only once the handle's drag ends
The split's own drag is still going during the second press of a double-click, so the least movement before the release put the handle back under the pointer right after it was fitted. The fit now waits for that drag to end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+26
-7
@@ -227,10 +227,30 @@ Gtk::Widget& EffectorWindow::buildChainTab() {
|
||||
auto click = Gtk::GestureClick::create();
|
||||
click->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
|
||||
// The split's drag ends every press on the handle, which starts the
|
||||
// click's count over, so the second press is counted here.
|
||||
// click's count over, so the second press is counted here. And that
|
||||
// drag is still going on during the second press -- the least jitter
|
||||
// puts the handle back under the pointer -- so the fit waits for it
|
||||
// to end.
|
||||
std::vector<Glib::RefPtr<Gtk::GestureDrag>> drags;
|
||||
const auto controllers = split->observe_controllers();
|
||||
for (guint i = 0; i < controllers->get_n_items(); ++i) {
|
||||
auto other = std::dynamic_pointer_cast<Gtk::Gesture>(controllers->get_object(i));
|
||||
if (other) click->group(other);
|
||||
if (auto drag = std::dynamic_pointer_cast<Gtk::GestureDrag>(other)) drags.push_back(drag);
|
||||
}
|
||||
auto lastPress = std::make_shared<guint32>(0);
|
||||
auto refitPending = std::make_shared<bool>(false);
|
||||
for (const auto& drag : drags) {
|
||||
drag->signal_drag_end().connect([this, refitPending](double, double) {
|
||||
if (!*refitPending) return;
|
||||
*refitPending = false;
|
||||
refitChainSplit();
|
||||
});
|
||||
}
|
||||
auto* gesture = click.get(); // not the RefPtr: the gesture owns this slot
|
||||
click->signal_pressed().connect([this, split, handle, gesture, lastPress](int, double x, double y) {
|
||||
const bool waitForDrag = !drags.empty();
|
||||
click->signal_pressed().connect(
|
||||
[this, split, handle, gesture, lastPress, refitPending, waitForDrag](int, double x, double y) {
|
||||
// The handle is thin, and the drag takes presses a little past it.
|
||||
const auto bounds = handle->compute_bounds(*split);
|
||||
constexpr double slack = 6.0;
|
||||
@@ -244,16 +264,15 @@ Gtk::Widget& EffectorWindow::buildChainTab() {
|
||||
const int doubleClick = Gtk::Settings::get_default()->property_gtk_double_click_time();
|
||||
if (*lastPress != 0 && now - *lastPress <= static_cast<guint32>(doubleClick)) {
|
||||
*lastPress = 0;
|
||||
if (waitForDrag) {
|
||||
*refitPending = true;
|
||||
} else {
|
||||
refitChainSplit();
|
||||
}
|
||||
} else {
|
||||
*lastPress = now;
|
||||
}
|
||||
});
|
||||
const auto controllers = split->observe_controllers();
|
||||
for (guint i = 0; i < controllers->get_n_items(); ++i) {
|
||||
auto drag = std::dynamic_pointer_cast<Gtk::Gesture>(controllers->get_object(i));
|
||||
if (drag) click->group(drag);
|
||||
}
|
||||
split->add_controller(click);
|
||||
}
|
||||
rebuildChainRows();
|
||||
|
||||
Reference in New Issue
Block a user