404 SPItem *item_at_point =
nullptr, *group_at_point =
nullptr, *item_in_group =
nullptr;
406 auto selection = _desktop->getSelection();
411 sp_select_context_abort();
418 if (event.num_press == 2 && event.button == 1) {
419 if (!selection->isEmpty()) {
420 SPItem *clicked_item = selection->items().front();
422 if (is<SPGroup>(clicked_item) && !is<SPBox3D>(clicked_item)) {
423 _desktop->layerManager().setCurrentLayer(clicked_item);
424 _desktop->getSelection()->clear();
426 discard_delayed_snap_event();
429 Geom::Point const p(_desktop->w2d(event.pos));
430 set_active_tool(_desktop, clicked_item, p);
433 sp_select_context_up_one_layer(_desktop);
438 if (event.num_press == 1 && event.button == 1) {
440 saveDragOrigin(event.pos);
447 auto const [
mode, handle] = get_default_rubberband_state();
448 rubberband->setMode(
mode);
449 rubberband->setHandle(handle);
453 rubberband->start(_desktop, p);
460 grabbed = _desktop->getCanvasCatchall();
468 button_press_state =
event.modifiers;
475 }
else if (event.button == 3) {
477 sp_select_context_abort();
481 if (grabbed && event.modifiers & (GDK_SHIFT_MASK | GDK_ALT_MASK)) {
482 _desktop->getSnapIndicator()->remove_snaptarget();
485 tolerance = prefs->getIntLimited(
"/options/dragtolerance/value", 0, 0, 100);
490 if (event.modifiers & GDK_BUTTON1_MASK) {
491 if (!checkDragMoved(event.pos)) {
497 if (force_drag && !always_box && !selection->isEmpty()) {
501 set_cursor(
"select-dragging.svg");
511 defaultMessageContext()->clear();
514 item_at_point = _desktop->getItemAtPoint(xyp,
false);
516 if (item_at_point || moved || force_drag) {
519 item_in_group = _desktop->getItemAtPoint(event.pos,
true);
520 group_at_point = _desktop->getGroupAtPoint(event.pos);
523 auto selGroup = cast<SPGroup>(selection->single());
525 group_at_point = selGroup;
531 if (group_at_point != item_in_group &&
532 !(group_at_point && item_at_point &&
533 group_at_point->isAncestorOf(item_at_point))) {
534 group_at_point =
nullptr;
538 if ((!item_in_group || !selection->includes(item_in_group)) &&
539 (!group_at_point || !selection->includes(group_at_point)) && !force_drag) {
541 if (!_seltrans->isEmpty()) {
542 _seltrans->resetState();
546 if (item_at_point && !selection->includes(item_at_point)) {
547 selection->set(item_at_point);
551 _seltrans->grab(p, -1, -1,
false,
true);
555 if (!_seltrans->isEmpty()) {
557 _seltrans->moveTo(p, event.modifiers);
560 _desktop->getCanvas()->enable_autoscroll();
565 discard_delayed_snap_event();
585 _(
"<b>Draw over</b> objects to select them; press <b>%s</b> to deselect them; release <b>%s</b> to switch to rubberband selection"), remove_from.c_str(), touch_path.c_str());
588 _(
"<b>Drag near</b> objects to select them; press <b>%s</b> to deselect them; press <b>%s</b> to switch to touch selection"), remove_from.c_str(), touch_path.c_str());
591 _(
"<b>Drag around</b> objects to select them; press <b>%s</b> to deselect them; press <b>%s</b> to switch to touch selection"), remove_from.c_str(), touch_path.c_str());
599 [&] (ButtonReleaseEvent
const &event) {
602 if ((event.button == 1) && (grabbed)) {
608 }
else if (
item && !drag_escaped) {
610 if (!selection->isEmpty()) {
613 _seltrans->resetState();
614 selection->toggle(
item);
616 SPObject* single = selection->single();
617 auto singleGroup = cast<SPGroup>(single);
619 if (selection->includes(
item)) {
620 _seltrans->increaseState();
622 _seltrans->increaseState();
624 _seltrans->resetState();
625 selection->set(
item);
629 _seltrans->resetState();
630 selection->set(
item);
637 if (_force_dragging) {
638 set_cursor(_default_cursor);
639 _force_dragging =
false;
641 set_cursor(
"select-mouseover.svg");
645 discard_delayed_snap_event();
655 if (r->
isStarted() && !within_tolerance) {
657 set_cursor(_default_cursor);
658 std::vector<SPItem*>
items;
662 items = _desktop->getDocument()->getItemsInBox(_desktop->dkey, (*b) * _desktop->dt2doc());
665 items = _desktop->getDocument()->getItemsPartiallyInBox(_desktop->dkey, (*b) * _desktop->dt2doc());
667 bool topmost_items_only = prefs->getBool(
"/options/selection/touchsel_topmost_only");
668 items = _desktop->getDocument()->getItemsAtPoints(_desktop->dkey, r->
getPoints(),
true, topmost_items_only);
671 _seltrans->resetState();
673 defaultMessageContext()->clear();
677 selection->removeList(
items);
680 selection->addList(
items);
683 selection->setList(
items);
693 if (add_to && !rb_escaped && !drag_escaped) {
696 SPItem *local_item =
nullptr;
707 selection->toggle(local_item);
710 }
else if ((in_groups || force_drag) && !rb_escaped && !drag_escaped) {
714 if (selection->includes(local_item)) {
715 _seltrans->increaseState();
717 _seltrans->resetState();
718 selection->set(local_item);
722 if (!selection->isEmpty()) {
723 if (!(rb_escaped) && !(drag_escaped) && !force_drag) {
740 if (event.button == 1) {
744 button_press_state = 0;
746 [&] (ScrollEvent
const &event) {
756 SPItem *local_item = _desktop->getItemAtPoint(p,
true,
nullptr);
757 cycling_items.clear();
760 while(local_item !=
nullptr) {
761 cycling_items.push_back(local_item);
762 local_item = _desktop->getItemAtPoint(p,
true, local_item);
763 if (local_item && selection->includes(local_item)) tmp = local_item;
767 bool item_lists_differ = cycling_items != cycling_items_cmp;
769 if(item_lists_differ) {
770 sp_select_context_reset_opacities();
771 for (
auto l : cycling_items_cmp)
773 cycling_items_cmp = (cycling_items);
776 for(
auto cycling_item : cycling_items) {
783 if(!cycling_cur_item) cycling_cur_item = tmp;
785 cycling_wrap = prefs->getBool(
"/options/selection/cycleWrap",
true);
788 sp_select_context_cycle_through_items(selection, event);
793 GtkWindow *
w = GTK_WINDOW(gtk_widget_get_root(_desktop->getCanvas()->Gtk::Widget::gobj()));
795 gtk_window_present(
w);
796 _desktop->getCanvas()->grab_focus();
799 [&] (KeyPressEvent
const &event) {
804 bool alt = keyval == GDK_KEY_Alt_L ||
805 keyval == GDK_KEY_Alt_R ||
806 keyval == GDK_KEY_Meta_L ||
807 keyval == GDK_KEY_Meta_R;
812 if (!key_is_a_modifier (keyval)) {
813 defaultMessageContext()->clear();
814 }
else if (grabbed || _seltrans->isGrabbed()) {
820 rubberband->move(_desktop->point());
839 if (alt && !selection->isEmpty() && !_desktop->isWaitingCursor()) {
840 set_cursor(
"select-dragging.svg");
841 _force_dragging =
true;
842 _default_cursor =
"select.svg";
847 gdouble
const nudge = prefs->getDoubleLimited(
"/options/nudgedistance/value", 2, 0, 1000,
"px");
848 auto const y_dir = _desktop->yaxisdir();
850 bool const rotated = prefs->getBool(
"/options/moverotated/value",
true);
867 case GDK_KEY_KP_Left:
869 _desktop->getSelection()->move(-
delta * mul, 0, rotated, screen);
877 _desktop->getSelection()->move(0, -
delta * mul * y_dir, rotated, screen);
883 case GDK_KEY_KP_Right:
885 _desktop->getSelection()->move(
delta * mul, 0, rotated, screen);
891 case GDK_KEY_KP_Down:
893 _desktop->getSelection()->move(0,
delta * mul * y_dir, rotated, screen);
899 if (!sp_select_context_abort()) {
918 if (dragging && grabbed) {
919 _seltrans->stamp(keyval != GDK_KEY_space);
927 _desktop->setToolboxFocusTo(
"select-x");
934 if (selection->singleItem()) {
935 SPItem *clicked_item = selection->singleItem();
936 auto clickedGroup = cast<SPGroup>(clicked_item);
937 if ( (clickedGroup && (clickedGroup->layerMode() !=
SPGroup::LAYER)) || is<SPBox3D>(clicked_item)) {
938 _desktop->layerManager().setCurrentLayer(clicked_item);
939 _desktop->getSelection()->clear();
949 case GDK_KEY_BackSpace:
959 if (!selection->isEmpty()) {
960 _seltrans->increaseState();
970 _desktop->getSelection()->toGuides();
979 [&] (KeyReleaseEvent
const &event) {
982 if (key_is_a_modifier (keyval)) {
983 defaultMessageContext()->clear();
987 bool alt = keyval == GDK_KEY_Alt_L ||
988 keyval == GDK_KEY_Alt_R ||
989 keyval == GDK_KEY_Meta_L ||
990 keyval == GDK_KEY_Meta_R;
998 auto const [
mode, handle] = get_default_rubberband_state();
999 rubberband->setMode(
mode);
1000 rubberband->setHandle(handle);
1006 rubberband->move(_desktop->point());
1012 sp_select_context_reset_opacities();
1019 if (alt && !(grabbed || _seltrans->isGrabbed()) && !selection->isEmpty() && !_desktop->isWaitingCursor()) {
1020 set_cursor(_default_cursor);
1021 _force_dragging =
false;
1024 [&] (CanvasEvent
const &event) {}
1027 return ret || ToolBase::root_handler(event);