provisional processor control-box tweaks - possible fix for #6519
[ardour.git] / gtk2_ardour / editor_mouse.cc
index 9edef8056ed5f99988b6c77b012dc1a9c7c67f20..5597c5b06e77991f3a2ec0581af67cb9fbb94f25 100644 (file)
@@ -214,10 +214,6 @@ Editor::mouse_mode_object_range_toggled()
        Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
        assert (tact);
 
-       if (tact->get_active()) {
-               m = MouseObject;  //Smart mode turned to ON, force editing to Object mode
-       }
-
        set_mouse_mode(m, true);  //call this so the button styles can get updated
 }
 
@@ -335,37 +331,59 @@ Editor::internal_editing() const
 void
 Editor::update_time_selection_display ()
 {
-       if (smart_mode_action->get_active()) {
-               /* not sure what to do here */
-               if (mouse_mode == MouseObject) {
-               } else {
-               }
-       } else {
-               switch (mouse_mode) {
-               case MouseRange:
-                       selection->clear_objects ();
-                       selection->ClearMidiNoteSelection();  //signal
-                       break;
-               case MouseObject:
-                       selection->clear_objects ();
-                       selection->clear_time ();
-                       selection->clear_tracks ();
-                       selection->ClearMidiNoteSelection();  //signal
-                       break;
-               case MouseContent:
-               case MouseDraw:
-                       //if we go into internal editing, clear everything in the outside world
-                       selection->clear_objects ();
-                       selection->clear_time ();
-                       selection->clear_tracks ();
-                       break;
-               default:
-                       //clear everything
-                       selection->clear_objects ();
-                       selection->clear_time ();
-                       selection->clear_tracks ();
-                       break;
-               }
+       switch (mouse_mode) {
+       case MouseRange:
+               selection->clear_objects ();
+               selection->ClearMidiNoteSelection ();  /* EMIT SIGNAL */
+               break;
+       case MouseObject:
+               selection->clear_time ();
+               selection->clear_tracks ();
+               selection->ClearMidiNoteSelection ();  /* EMIT SIGNAL */
+               break;
+       case MouseDraw:
+               /* Clear regions, but not time or tracks, since that
+                would destroy the range selection rectangle, which we need to stick
+                around for AutomationRangeDrag. */
+               selection->clear_regions ();
+               selection->clear_playlists ();
+               break;
+       case MouseContent:
+               /* This handles internal edit.
+                  Clear everything except points and notes. 
+               */
+               selection->clear_regions();
+               selection->clear_lines();
+               selection->clear_playlists ();
+
+               selection->clear_time ();
+               selection->clear_tracks ();
+               break;
+
+       case MouseTimeFX:
+               /* We probably want to keep region selection */
+               selection->clear_points ();
+               selection->clear_lines();
+               selection->clear_playlists ();
+
+               selection->clear_time ();
+               selection->clear_tracks ();
+               break;
+
+       case MouseAudition:
+               /*Don't lose lines or points if no action in this mode */
+               selection->clear_regions ();
+               selection->clear_playlists ();
+               selection->clear_time ();
+               selection->clear_tracks ();
+               break;
+
+       default:
+               /*Clear everything */
+               selection->clear_objects();
+               selection->clear_time ();
+               selection->clear_tracks ();
+               break;
        }
 }
 
@@ -428,7 +446,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
        if (((mouse_mode != MouseObject) &&
             (mouse_mode != MouseAudition || item_type != RegionItem) &&
             (mouse_mode != MouseTimeFX || item_type != RegionItem) &&
-            (mouse_mode != MouseDraw)) ||
+            (mouse_mode != MouseDraw) &&
+            (mouse_mode != MouseContent || item_type == RegionItem)) ||
            ((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3)) {
                return;
        }
@@ -448,11 +467,15 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
        Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
        bool press = (event->type == GDK_BUTTON_PRESS);
 
+       if (press) {
+               _mouse_changed_selection = false;
+       }
+
        switch (item_type) {
        case RegionItem:
                if (press) {
                        if (eff_mouse_mode != MouseRange) {
-                               set_selected_regionview_from_click (press, op);
+                               _mouse_changed_selection = set_selected_regionview_from_click (press, op);
                        } else {
                                /* don't change the selection unless the
                                   clicked track is not currently selected. if
@@ -465,7 +488,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                        }
                } else {
                        if (eff_mouse_mode != MouseRange) {
-                               set_selected_regionview_from_click (press, op);
+                               _mouse_changed_selection |= set_selected_regionview_from_click (press, op);
                        }
                }
                break;
@@ -483,16 +506,17 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
        case StartCrossFadeItem:
        case EndCrossFadeItem:
                if (get_smart_mode() || eff_mouse_mode != MouseRange) {
-                       set_selected_regionview_from_click (press, op);
+                       _mouse_changed_selection |= set_selected_regionview_from_click (press, op);
                } else if (event->type == GDK_BUTTON_PRESS) {
                        set_selected_track_as_side_effect (op);
                }
                break;
 
        case ControlPointItem:
-               set_selected_track_as_side_effect (op);
+               /* for object/track exclusivity, we don't call set_selected_track_as_side_effect (op); */
+
                if (eff_mouse_mode != MouseRange) {
-                       set_selected_control_point_from_click (press, op);
+                       _mouse_changed_selection |= set_selected_control_point_from_click (press, op);
                }
                break;
 
@@ -501,6 +525,10 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                if (event->button.button == 3) {
                        selection->clear_tracks ();
                        set_selected_track_as_side_effect (op);
+
+                       /* We won't get a release.*/
+                       begin_reversible_selection_op (X_("Button 3 Menu Select"));
+                       commit_reversible_selection_op ();
                }
                break;
 
@@ -511,6 +539,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
        default:
                break;
        }
+
+       if ((!press) && _mouse_changed_selection) {
+               begin_reversible_selection_op (X_("Button Selection"));
+               commit_reversible_selection_op ();
+               _mouse_changed_selection = false;
+       }
 }
 
 bool
@@ -729,21 +763,37 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        }
                        return true;
 
+               case GainLineItem:
+                       _drags->set (new LineDrag (this, item), event);
+                       return true;
+                       break;
+
                case ControlPointItem:
                        _drags->set (new ControlPointDrag (this, item), event);
                        return true;
                        break;
 
+               case AutomationLineItem:
+                       _drags->set (new LineDrag (this, item), event);
+                       return true;
+                       break;
+
                case StreamItem:
-                       if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
-                               _drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
-                               return true;
-                       }
+                       //in the past, we created a new midi region here, but perhaps that is best left to the Draw mode
                        break;
 
                case AutomationTrackItem:
                        /* rubberband drag to select automation points */
                        _drags->set (new EditorRubberbandSelectDrag (this, item), event);
+                       return true;
+                       break;
+
+               case RegionItem:
+                       if (dynamic_cast<AutomationRegionView*>(clicked_regionview)) {
+                               /* rubberband drag to select automation points */
+                               _drags->set (new EditorRubberbandSelectDrag (this, item), event);
+                               return true;
+                       }
                        break;
 
                default:
@@ -915,12 +965,13 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
 
                case SelectionItem:
                {
-                       AudioRegionView* arv = dynamic_cast<AudioRegionView *> (clicked_regionview);
-                       if (arv) {
-                               _drags->set (new AutomationRangeDrag (this, arv, selection->time), event, _cursors->up_down);
+                       if (dynamic_cast<AudioRegionView*>(clicked_regionview) ||
+                           dynamic_cast<AutomationRegionView*>(clicked_regionview)) {
+                               _drags->set (new AutomationRangeDrag (this, clicked_regionview, selection->time),
+                                            event, _cursors->up_down);
                        } else {
                                double const y = event->button.y;
-                               pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
+                               pair<TimeAxisView*, int> tvp = trackview_by_y_position (y, false);
                                if (tvp.first) {
                                        AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
                                        if ( atv) {
@@ -1088,7 +1139,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
        }
 
        //not rolling, range mode click + join_play_range :  locate the PH here
-       if ( !_drags->active () && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && ARDOUR_UI::config()->get_follow_edits() ) {
+       if ( !_drags->active () && _session && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && ARDOUR_UI::config()->get_follow_edits() ) {
                framepos_t where = canvas_event_sample (event);
                snap_to(where);
                _session->request_locate (where, false);
@@ -1149,20 +1200,24 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                return true;
        }
 
-       /* see if we're finishing a drag */
+        bool were_dragging = false;
 
-       bool were_dragging = false;
-       if (_drags->active ()) {
-               bool const r = _drags->end_grab (event);
-               if (r) {
-                       /* grab dragged, so do nothing else */
-                       return true;
-               }
+       if (!Keyboard::is_context_menu_event (&event->button)) {
 
-               were_dragging = true;
-       }
+                /* see if we're finishing a drag */
+                
+                if (_drags->active ()) {
+                        bool const r = _drags->end_grab (event);
+                        if (r) {
+                                /* grab dragged, so do nothing else */
+                                return true;
+                        }
+                        
+                        were_dragging = true;
+                }
 
-       update_region_layering_order_editor ();
+                update_region_layering_order_editor ();
+        }
 
        /* edit events get handled here */
 
@@ -1173,10 +1228,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        break;
 
                case TempoMarkerItem: {
-                       Marker* marker;
+                       ArdourMarker* marker;
                        TempoMarker* tempo_marker;
                        
-                       if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
+                       if ((marker = reinterpret_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
                                fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
                                abort(); /*NOTREACHED*/
                        }
@@ -1191,10 +1246,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                }
 
                case MeterMarkerItem: {
-                       Marker* marker;
+                       ArdourMarker* marker;
                        MeterMarker* meter_marker;
                        
-                       if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
+                       if ((marker = reinterpret_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
                                fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
                                abort(); /*NOTREACHED*/
                        }
@@ -1453,7 +1508,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                default:
                                        break;
                                }
-                       } else {
+                       } else if (_session) {
                                /* make sure we stop */
                                _session->request_transport_speed (0.0);
                        }
@@ -1465,7 +1520,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                }
 
                 /* do any (de)selection operations that should occur on button release */
-                button_selection (item, event, item_type);
+               button_selection (item, event, item_type);
+
                return true;
                break;
 
@@ -1520,7 +1576,7 @@ bool
 Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
        ControlPoint* cp;
-       Marker * marker;
+       ArdourMarker * marker;
        double fraction;
         bool ret = true;
 
@@ -1573,7 +1629,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                break;
 
        case MarkerItem:
-               if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
+               if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
                        break;
                }
                entered_marker = marker;
@@ -1615,6 +1671,14 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case SelectionItem:
                break;
 
+       case WaveItem:
+       {
+               if (entered_regionview) {
+                       entered_regionview->entered();
+               }
+       }
+       break;
+
        default:
                break;
        }
@@ -1646,7 +1710,7 @@ bool
 Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
 {
        AutomationLine* al;
-       Marker *marker;
+       ArdourMarker *marker;
        Location *loc;
        bool is_start;
        bool ret = true;
@@ -1672,7 +1736,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
                break;
 
        case MarkerItem:
-               if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
+               if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
                        break;
                }
                entered_marker = 0;
@@ -1881,7 +1945,6 @@ Editor::edit_control_point (ArdourCanvas::Item* item)
        }
 
        ControlPointDialog d (p);
-       ensure_float (d);
 
        if (d.run () != RESPONSE_ACCEPT) {
                return;
@@ -1901,7 +1964,6 @@ Editor::edit_notes (MidiRegionView* mrv)
 
        EditNoteDialog* d = new EditNoteDialog (mrv, s);
        d->show_all ();
-       ensure_float (*d);
 
        d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &Editor::note_edit_done), d));
 }
@@ -2071,10 +2133,10 @@ Editor::point_trim (GdkEvent* event, framepos_t new_bound)
 void
 Editor::hide_marker (ArdourCanvas::Item* item, GdkEvent* /*event*/)
 {
-       Marker* marker;
+       ArdourMarker* marker;
        bool is_start;
 
-       if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
+       if ((marker = static_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
                fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
                abort(); /*NOTREACHED*/
        }
@@ -2150,7 +2212,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, framepos_t pos)
 
        // playlist is frozen, so we have to update manually XXX this is disgusting
 
-       playlist->RegionAdded (new_region); /* EMIT SIGNAL */
+       //playlist->RegionAdded (new_region); /* EMIT SIGNAL */
 }
 
 gint
@@ -2212,8 +2274,6 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView*
        }
 
        _drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), true, false));
-
-       begin_reversible_command (Operations::drag_region_brush);
 }
 
 /** Start a grab where a time range is selected, track(s) are selected, and the
@@ -2253,7 +2313,6 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
        /* A selection grab currently creates two undo/redo operations, one for
           creating the new region and another for moving it.
        */
-
        begin_reversible_command (Operations::selection_grab);
 
        boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
@@ -2266,6 +2325,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
 
        if (latest_regionviews.empty()) {
                /* something went wrong */
+               abort_reversible_command ();
                return;
        }
 
@@ -2316,7 +2376,7 @@ Editor::update_join_object_range_location (double y)
 
                ArdourCanvas::Duple const item_space = entered_regionview->get_canvas_group()->canvas_to_item (ArdourCanvas::Duple (0, y));
                double const c = item_space.y / entered_regionview->height();
-                       
+
                _join_object_range_state = c <= 0.5 ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
 
                Editor::EnterContext* ctx = get_enter_context(RegionItem);