X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_mouse.cc;h=928801d0b213cda746af011ff2c70dca01ac73e4;hb=e36f74e071d4c14862d23da5ff0d49df0940d536;hp=cb23e7d2d127f495a401bab5b383822b139d2e4e;hpb=f00b3b7f111e36537d773daef0ae77b03d11f82f;p=ardour.git diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index cb23e7d2d1..928801d0b2 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -126,13 +126,13 @@ Editor::mouse_frame (framepos_t& where, bool& in_track_canvas) const event.button.x = x; event.button.y = y; - where = window_event_frame (&event, 0, 0); + where = window_event_sample (&event, 0, 0); return true; } framepos_t -Editor::window_event_frame (GdkEvent const * event, double* pcx, double* pcy) const +Editor::window_event_sample (GdkEvent const * event, double* pcx, double* pcy) const { double x; double y; @@ -159,7 +159,7 @@ Editor::window_event_frame (GdkEvent const * event, double* pcx, double* pcy) co } framepos_t -Editor::canvas_event_frame (GdkEvent const * event, double* pcx, double* pcy) const +Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) const { double x; double y; @@ -179,12 +179,12 @@ Editor::canvas_event_frame (GdkEvent const * event, double* pcx, double* pcy) co *pcy = y; } - /* note that pixel_to_sample() never returns less than zero, so even if the pixel + /* note that pixel_to_sample_from_event() never returns less than zero, so even if the pixel position is negative (as can be the case with motion events in particular), the frame location is always positive. */ - return pixel_to_sample (x); + return pixel_to_sample_from_event (x); } Gdk::Cursor* @@ -346,9 +346,11 @@ Editor::mouse_mode_object_range_toggled() assert (act); Glib::RefPtr tact = Glib::RefPtr::cast_dynamic (act); assert (tact); - if (tact->get_active()) + + 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 } @@ -497,10 +499,32 @@ Editor::mouse_mode_toggled (MouseMode m) set_canvas_cursor (); set_gain_envelope_visibility (); + + update_time_selection_display (); MouseModeChanged (); /* EMIT SIGNAL */ } +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 (); + break; + default: + selection->clear_time (); + break; + } + } +} + void Editor::step_mouse_mode (bool next) { @@ -599,6 +623,15 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp to cut notes or regions. */ + MouseMode eff_mouse_mode = mouse_mode; + + if (get_smart_mode() && eff_mouse_mode == MouseRange && event->button.button == 3 && item_type == RegionItem) { + /* context clicks are always about object properties, even if + we're in range mode within smart mode. + */ + eff_mouse_mode = MouseObject; + } + if (((mouse_mode != MouseObject) && (mouse_mode != MouseAudition || item_type != RegionItem) && (mouse_mode != MouseTimeFX || item_type != RegionItem) && @@ -627,25 +660,23 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp switch (item_type) { case RegionItem: - if (!get_smart_mode() || (_join_object_range_state != JOIN_OBJECT_RANGE_RANGE)) { - if (press) { - if (mouse_mode != MouseRange) { - set_selected_regionview_from_click (press, op); - } else { - /* don't change the selection unless the - clicked track is not currently selected. if - so, "collapse" the selection to just this - track - */ - if (!selection->selected (clicked_axisview)) { - set_selected_track_as_side_effect (Selection::Set); - } - } + if (press) { + if (eff_mouse_mode != MouseRange) { + set_selected_regionview_from_click (press, op); } else { - if (mouse_mode != MouseRange) { - set_selected_regionview_from_click (press, op); + /* don't change the selection unless the + clicked track is not currently selected. if + so, "collapse" the selection to just this + track + */ + if (!selection->selected (clicked_axisview)) { + set_selected_track_as_side_effect (Selection::Set); } } + } else { + if (eff_mouse_mode != MouseRange) { + set_selected_regionview_from_click (press, op); + } } break; @@ -653,7 +684,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp case RegionViewName: case LeftFrameHandle: case RightFrameHandle: - if ( mouse_mode != MouseRange ) { + if (eff_mouse_mode != MouseRange) { set_selected_regionview_from_click (press, op); } else if (event->type == GDK_BUTTON_PRESS) { set_selected_track_as_side_effect (op); @@ -666,7 +697,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp case FadeOutItem: case StartCrossFadeItem: case EndCrossFadeItem: - if ( mouse_mode != MouseRange ) { + if (eff_mouse_mode != MouseRange) { + cerr << "Should be setting selected regionview\n"; set_selected_regionview_from_click (press, op); } else if (event->type == GDK_BUTTON_PRESS) { set_selected_track_as_side_effect (op); @@ -675,7 +707,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp case ControlPointItem: set_selected_track_as_side_effect (op); - if ( mouse_mode != MouseRange ) { + if (eff_mouse_mode != MouseRange) { set_selected_control_point_from_click (press, op); } break; @@ -723,38 +755,30 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT { TempoMarker* m = reinterpret_cast (item->get_data ("marker")); assert (m); - if (m->tempo().movable ()) { - _drags->set ( - new TempoMarkerDrag ( - this, - item, - Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) - ), - event - ); - return true; - } else { - return false; - } + _drags->set ( + new TempoMarkerDrag ( + this, + item, + Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + ), + event + ); + return true; } case MeterMarkerItem: { MeterMarker* m = reinterpret_cast (item->get_data ("marker")); assert (m); - if (m->meter().movable ()) { - _drags->set ( - new MeterMarkerDrag ( - this, - item, - Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) - ), - event - ); - return true; - } else { - return false; - } + _drags->set ( + new MeterMarkerDrag ( + this, + item, + Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + ), + event + ); + return true; } case VideoBarItem: @@ -902,17 +926,18 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseDraw: switch (item_type) { case NoteItem: + /* Existing note: allow trimming/motion */ if (internal_editing()) { /* trim notes if we're in internal edit mode and near the ends of the note */ NoteBase* cn = reinterpret_cast(item->get_data ("notebase")); assert (cn); - if (cn && cn->big_enough_to_trim() && cn->mouse_near_ends()) { + if (cn->big_enough_to_trim() && cn->mouse_near_ends()) { _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); } else { _drags->set (new NoteDrag (this, item), event); } return true; - } + } break; case StreamItem: if (internal_editing()) { @@ -931,10 +956,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseObject: switch (item_type) { case NoteItem: + /* Existing note: allow trimming/motion */ if (internal_editing()) { NoteBase* cn = reinterpret_cast (item->get_data ("notebase")); assert (cn); - if (cn->mouse_near_ends()) { + if (cn->big_enough_to_trim() && cn->mouse_near_ends()) { _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); } else { _drags->set (new NoteDrag (this, item), event); @@ -1071,7 +1097,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT _drags->set (new RegionCreateDrag (this, item, parent), event); } else { /* See if there's a region before the click that we can extend, and extend it if so */ - framepos_t const t = canvas_event_frame (event); + framepos_t const t = canvas_event_sample (event); boost::shared_ptr prev = pl->find_next_region (t, End, -1); if (!prev) { _drags->set (new RegionCreateDrag (this, item, parent), event); @@ -1109,7 +1135,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT boost::shared_ptr pl = t->playlist (); if (pl) { - boost::shared_ptr r = pl->top_region_at (canvas_event_frame (event)); + boost::shared_ptr r = pl->top_region_at (canvas_event_sample (event)); if (r) { RegionView* rv = rtv->view()->find_view (r); clicked_selection = select_range (rv->region()->position(), @@ -1182,9 +1208,13 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case MouseTimeFX: - if (internal_editing() && item_type == NoteItem) { + if (internal_editing() && item_type == NoteItem ) { /* drag notes if we're in internal edit mode */ - _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); + NoteBase* cn = reinterpret_cast(item->get_data ("notebase")); + assert (cn); + if (cn->big_enough_to_trim()) { + _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor); + } return true; } else if (clicked_regionview) { /* do time-FX */ @@ -1276,9 +1306,9 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseZoom: if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { - temporal_zoom_to_frame (false, canvas_event_frame (event)); + temporal_zoom_to_frame (false, canvas_event_sample (event)); } else { - temporal_zoom_to_frame (true, canvas_event_frame(event)); + temporal_zoom_to_frame (true, canvas_event_sample(event)); } return true; break; @@ -1293,6 +1323,12 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT bool Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + if (event->type == GDK_2BUTTON_PRESS) { + _drags->mark_double_click (); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + return true; + } + if (event->type != GDK_BUTTON_PRESS) { return false; } @@ -1313,7 +1349,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp } pre_press_cursor = current_canvas_cursor; - + _track_canvas->grab_focus(); if (_session && _session->actively_recording()) { @@ -1371,7 +1407,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 ) && Config->get_always_play_range() ) { - framepos_t where = canvas_event_frame (event, 0, 0); + framepos_t where = canvas_event_sample (event); snap_to(where); _session->request_locate (where, false); } @@ -1420,7 +1456,7 @@ Editor::button_release_dispatch (GdkEventButton* ev) bool Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - framepos_t where = canvas_event_frame (event, 0, 0); + framepos_t where = canvas_event_sample (event); AutomationTimeAxisView* atv = 0; if (pre_press_cursor) { @@ -1447,7 +1483,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT were_dragging = true; } - update_region_layering_order_editor (); + update_region_layering_order_editor (); /* edit events get handled here */ @@ -1457,13 +1493,40 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT show_region_properties (); break; - case TempoMarkerItem: - edit_tempo_marker (item); + case TempoMarkerItem: { + Marker* marker; + TempoMarker* tempo_marker; + + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((tempo_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg; + /*NOTREACHED*/ + } + + edit_tempo_marker (*tempo_marker); break; + } - case MeterMarkerItem: - edit_meter_marker (item); + case MeterMarkerItem: { + Marker* marker; + MeterMarker* meter_marker; + + if ((marker = reinterpret_cast (item->get_data ("marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((meter_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for meter is not a meter marker!") << endmsg; + /*NOTREACHED*/ + } + edit_meter_marker (*meter_marker); break; + } case RegionViewName: if (clicked_regionview->name_active()) { @@ -1657,7 +1720,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case AutomationTrackItem: atv = dynamic_cast(clicked_axisview); if (atv) { - atv->add_automation_event (event, where, event->button.y); + bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier); + atv->add_automation_event (event, where, event->button.y, with_guard_points); } return true; break; @@ -1676,17 +1740,20 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT */ AudioRegionView* arv = dynamic_cast (clicked_regionview); if (!were_dragging && arv) { - arv->add_gain_point_event (item, event); + bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier); + arv->add_gain_point_event (item, event, with_guard_points); } return true; break; } - case AutomationTrackItem: + case AutomationTrackItem: { + bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier); dynamic_cast(clicked_axisview)-> - add_automation_event (event, where, event->button.y); + add_automation_event (event, where, event->button.y, with_guard_points); return true; break; + } default: break; } @@ -1778,7 +1845,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case ControlPointItem: if (mouse_mode == MouseGain || mouse_mode == MouseObject) { cp = static_cast(item->get_data ("control_point")); - cp->set_visible (true); + cp->show (); double at_x, at_y; at_x = cp->get_x(); @@ -1836,6 +1903,17 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } break; + case RegionItem: + switch (effective_mouse_mode()) { + case MouseRange: + set_canvas_cursor (_cursors->selector); + break; + default: + set_canvas_cursor (which_grabber_cursor()); + break; + } + break; + case StartSelectionTrimItem: if (is_drawable()) { set_canvas_cursor (_cursors->left_side_trim); @@ -1860,6 +1938,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } break; + case RegionViewName: /* when the name is not an active item, the entire name highlight is for trimming */ @@ -1927,9 +2006,10 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ if (mouse_mode == MouseObject && !internal_editing()) { ArdourCanvas::Rectangle *rect = dynamic_cast (item); if (rect) { - rect->set_fill_color (0xBBBBBBAA); + RegionView* rv = static_cast(item->get_data ("regionview")); + rect->set_fill_color (rv->get_fill_color()); + set_canvas_cursor (_cursors->fade_in); } - set_canvas_cursor (_cursors->fade_in); } break; @@ -1937,9 +2017,10 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ if (mouse_mode == MouseObject && !internal_editing()) { ArdourCanvas::Rectangle *rect = dynamic_cast (item); if (rect) { - rect->set_fill_color (0xBBBBBBAA); + RegionView* rv = static_cast(item->get_data ("regionview")); + rect->set_fill_color (rv->get_fill_color ()); + set_canvas_cursor (_cursors->fade_out); } - set_canvas_cursor (_cursors->fade_out); } break; case FeatureLineItem: @@ -1948,7 +2029,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ line->set_outline_color (0xFF0000FF); } break; - + case SelectionItem: if ( get_smart_mode() ) { set_canvas_cursor (); @@ -1986,7 +2067,6 @@ bool Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type) { AutomationLine* al; - ControlPoint* cp; Marker *marker; Location *loc; RegionView* rv; @@ -1995,13 +2075,6 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type) switch (item_type) { case ControlPointItem: - cp = reinterpret_cast(item->get_data ("control_point")); - if (cp->line().the_list()->interpolation() != AutomationList::Discrete) { - if (cp->line().npoints() > 1 && !cp->get_selected()) { - cp->set_visible (false); - } - } - if (is_drawable()) { set_canvas_cursor (current_canvas_cursor); } @@ -2083,7 +2156,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type) { ArdourCanvas::Rectangle *rect = dynamic_cast (item); if (rect) { - rect->set_fill_color (rv->get_fill_color()); + rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_InactiveFadeHandle()); } } set_canvas_cursor (current_canvas_cursor); @@ -2841,8 +2914,6 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv) return; } - assert (rv); - ArdourCanvas::Group* g = rv->get_canvas_group (); ArdourCanvas::Group* p = g->parent (); @@ -2854,21 +2925,28 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv) assert (item_bbox); ArdourCanvas::Rect parent_bbox = g->item_to_parent (item_bbox.get ()); - /* Halfway across the region */ - double const h = (parent_bbox.x0 + parent_bbox.x1) / 2; + /* First or last 10% of region is used for trimming, if the whole + region is wider than 20 pixels at the current zoom level. + */ - Trimmable::CanTrim ct = rv->region()->can_trim (); - if (x <= h) { - if (ct & Trimmable::FrontTrimEarlier) { - set_canvas_cursor (_cursors->left_side_trim); - } else { - set_canvas_cursor (_cursors->left_side_trim_right_only); - } - } else { - if (ct & Trimmable::EndTrimLater) { - set_canvas_cursor (_cursors->right_side_trim); - } else { - set_canvas_cursor (_cursors->right_side_trim_left_only); + double const w = parent_bbox.width(); + + if (w > 20.0 && x >= parent_bbox.x0 && x < parent_bbox.x1) { + + Trimmable::CanTrim ct = rv->region()->can_trim (); + + if (((x - parent_bbox.x0) / w) < 0.10) { + if (ct & Trimmable::FrontTrimEarlier) { + set_canvas_cursor (_cursors->left_side_trim, true); + } else { + set_canvas_cursor (_cursors->left_side_trim_right_only, true); + } + } else if (((parent_bbox.x1 - x) / w) < 0.10) { + if (ct & Trimmable::EndTrimLater) { + set_canvas_cursor (_cursors->right_side_trim, true); + } else { + set_canvas_cursor (_cursors->right_side_trim_left_only, true); + } } } }