Fix zoom cursor SNAFU (#274). Increase move threshold for zoom drags so that clicks...
[ardour.git] / gtk2_ardour / editor_mouse.cc
index 51064f87cceac18e1220c2210e46ee92ed159df6..f2d49fa1d711ce812f303b97bb75a697b2174777 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "ardour_ui.h"
 #include "actions.h"
+#include "canvas-note.h"
 #include "editor.h"
 #include "time_axis_view.h"
 #include "audio_time_axis.h"
@@ -197,6 +198,10 @@ Editor::which_grabber_cursor ()
                        c = grabber_edit_point_cursor;
                        break;
                default:
+                        boost::shared_ptr<Movable> m = _movable.lock();
+                        if (m && m->locked()) {
+                                c = speaker_cursor;
+                        } 
                        break;
                }
        }
@@ -204,6 +209,29 @@ Editor::which_grabber_cursor ()
        return c;
 }
 
+void
+Editor::set_current_trimmable (boost::shared_ptr<Trimmable> t)
+{
+        boost::shared_ptr<Trimmable> st = _trimmable.lock();
+
+        if (!st || st == t) {
+                _trimmable = t;
+                set_canvas_cursor ();
+        } 
+        
+}
+
+void
+Editor::set_current_movable (boost::shared_ptr<Movable> m)
+{
+        boost::shared_ptr<Movable> sm = _movable.lock();
+
+        if (!sm || sm != m) {
+                _movable = m;
+                set_canvas_cursor ();
+        }
+}
+
 void
 Editor::set_canvas_cursor ()
 {
@@ -242,7 +270,11 @@ Editor::set_canvas_cursor ()
                        break;
 
                case MouseZoom:
-                       current_canvas_cursor = zoom_cursor;
+                       if (Keyboard::the_keyboard().key_is_down (GDK_Control_L)) {
+                               current_canvas_cursor = zoom_out_cursor;
+                       } else {
+                               current_canvas_cursor = zoom_in_cursor;
+                       }
                        break;
 
                case MouseTimeFX:
@@ -276,9 +308,7 @@ Editor::set_canvas_cursor ()
                }
        }
 
-       if (is_drawable()) {
-               track_canvas->get_window()->set_cursor(*current_canvas_cursor);
-       }
+        set_canvas_cursor (current_canvas_cursor, true);
 }
 
 void
@@ -677,14 +707,17 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                 case NoteItem:
                         if (internal_editing()) {
                                 /* trim notes if we're in internal edit mode and near the ends of the note */
-                                _drags->set (new NoteResizeDrag (this, item), event);
+                                ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
+                                cerr << "NoteItem button press, cursor = " << current_canvas_cursor << endl;
+                                if (cn->mouse_near_ends()) {
+                                        _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
+                                } else {
+                                        _drags->set (new NoteDrag (this, item), event);
+                                }
                         }
                        return true;
 
                 case StreamItem:
-                        cerr << "press on stream item, internal? " << internal_editing() << " MIDI ? "
-                             << dynamic_cast<MidiTimeAxisView*>(clicked_axisview)
-                             << endl;
                         if (internal_editing()) {
                                if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
                                        _drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
@@ -699,12 +732,12 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                 case RegionViewNameHighlight:
                 case LeftFrameHandle:
                 case RightFrameHandle:
-                {
-                        RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
-                        _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
-                        return true;
+                        if (!clicked_regionview->region()->locked()) {
+                                RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
+                                _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
+                                return true;
+                        }
                         break;
-                }
 
                default:
                         if (!internal_editing()) {
@@ -718,7 +751,12 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                switch (item_type) {
                case NoteItem:
                        if (internal_editing()) {
-                               _drags->set (new NoteDrag (this, item), event);
+                                ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
+                                if (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;
@@ -768,6 +806,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                        */
                                        break;
                                }
+
+                               if (internal_editing ()) {
+                                       /* no region drags in internal edit mode */
+                                       break;
+                               }
                                
                                /* click on a normal region view */
                                if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
@@ -789,7 +832,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        case RegionViewNameHighlight:
                        case LeftFrameHandle:
                         case RightFrameHandle:
-                               if (!internal_editing ()) {
+                               if (!internal_editing () && !clicked_regionview->region()->locked()) {
                                        RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
                                        _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
                                        return true;
@@ -964,7 +1007,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
        case MouseTimeFX:
                if (internal_editing() && item_type == NoteItem) {
                        /* drag notes if we're in internal edit mode */
-                       _drags->set (new NoteResizeDrag (this, item), event);
+                       _drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
                        return true;
                } else if ((!internal_editing() || dynamic_cast<AudioRegionView*> (clicked_regionview)) && clicked_regionview) {
                        /* do time-FX if we're not in internal edit mode, or we are but we clicked on an audio region */
@@ -979,7 +1022,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                scrub_reverse_distance = 0;
                last_scrub_x = event->button.x;
                scrubbing_direction = 0;
-               track_canvas->get_window()->set_cursor (*transparent_cursor);
+               set_canvas_cursor (transparent_cursor);
                return true;
                break;
 
@@ -1080,6 +1123,8 @@ 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()) {
@@ -1123,6 +1168,11 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
        framepos_t where = event_frame (event, 0, 0);
        AutomationTimeAxisView* atv = 0;
 
+        if (pre_press_cursor) {
+                set_canvas_cursor (pre_press_cursor);
+                pre_press_cursor = 0;
+        }
+
        /* no action if we're recording */
 
        if (_session && _session->actively_recording()) {
@@ -1142,14 +1192,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                were_dragging = true;
        }
 
-        update_region_layering_order_editor (where);
+        update_region_layering_order_editor ();
 
        /* edit events get handled here */
 
        if (!_drags->active () && Keyboard::is_edit_event (&event->button)) {
                switch (item_type) {
                case RegionItem:
-                       edit_region ();
+                       show_region_properties ();
                        break;
 
                case TempoMarkerItem:
@@ -1398,7 +1448,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        break;
 
                case MouseAudition:
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                        if (scrubbing_direction == 0) {
                                /* no drag, just a click */
                                switch (item_type) {
@@ -1492,7 +1542,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        fraction = 1.0 - (cp->get_y() / cp->line().height());
 
                        if (is_drawable() && !_drags->active ()) {
-                               track_canvas->get_window()->set_cursor (*fader_cursor);
+                               set_canvas_cursor (fader_cursor);
                        }
 
                        set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y);
@@ -1506,7 +1556,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        if (line)
                                line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredGainLine.get();
                        if (is_drawable()) {
-                               track_canvas->get_window()->set_cursor (*fader_cursor);
+                               set_canvas_cursor (fader_cursor);
                        }
                }
                break;
@@ -1519,26 +1569,36 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                                        line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredAutomationLine.get();
                        }
                        if (is_drawable()) {
-                               track_canvas->get_window()->set_cursor (*fader_cursor);
+                               set_canvas_cursor (fader_cursor);
                        }
                }
                break;
 
        case RegionViewNameHighlight:
                if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
-                       track_canvas->get_window()->set_cursor (*trimmer_cursor);
+                       set_canvas_cursor (trimmer_cursor);
                }
                break;
 
        case LeftFrameHandle:
                if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
-                       track_canvas->get_window()->set_cursor (*left_side_trim_cursor);
+                        if (entered_regionview) {
+                                Trimmable::CanTrim ct = entered_regionview->region()->can_trim();
+                                if ((ct & Trimmable::EndTrimEarlier) || (ct & Trimmable::EndTrimLater)) {
+                                        set_canvas_cursor (left_side_trim_cursor);
+                                }
+                        }
                }
                 break;
 
        case RightFrameHandle:
                if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
-                       track_canvas->get_window()->set_cursor (*right_side_trim_cursor);
+                        if (entered_regionview) {
+                                Trimmable::CanTrim ct = entered_regionview->region()->can_trim();
+                                if ((ct & Trimmable::FrontTrimEarlier) || (ct & Trimmable::FrontTrimLater)) {
+                                        set_canvas_cursor (right_side_trim_cursor);
+                                }
+                        }
                }
                 break;
 
@@ -1553,7 +1613,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 #endif
 
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*trimmer_cursor);
+                       set_canvas_cursor (trimmer_cursor);
                }
                break;
 
@@ -1561,10 +1621,10 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                if (is_drawable()) {
                        switch (_edit_point) {
                        case EditAtMouse:
-                               track_canvas->get_window()->set_cursor (*grabber_edit_point_cursor);
+                               set_canvas_cursor (grabber_edit_point_cursor);
                                break;
                        default:
-                               track_canvas->get_window()->set_cursor (*grabber_cursor);
+                               set_canvas_cursor (grabber_cursor);
                                break;
                        }
                }
@@ -1576,7 +1636,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
                if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
                        if (mouse_mode == MouseObject && is_drawable()) {
-                               track_canvas->get_window()->set_cursor (*trimmer_cursor);
+                               set_canvas_cursor (trimmer_cursor);
                        }
                }
                break;
@@ -1590,14 +1650,14 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                                cursor = selector_cursor;
                                break;
                        case MouseZoom:
-                               cursor = zoom_cursor;
+                               cursor = zoom_in_cursor;
                                break;
                        default:
                                cursor = cross_hair_cursor;
                                break;
                        }
 
-                       track_canvas->get_window()->set_cursor (*cursor);
+                       set_canvas_cursor (cursor);
 
                        AutomationTimeAxisView* atv;
                        if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
@@ -1614,7 +1674,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case MeterBarItem:
        case TempoBarItem:
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*timebar_cursor);
+                       set_canvas_cursor (timebar_cursor);
                }
                break;
 
@@ -1628,7 +1688,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case MeterMarkerItem:
        case TempoMarkerItem:
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*timebar_cursor);
+                       set_canvas_cursor (timebar_cursor);
                }
                break;
 
@@ -1638,7 +1698,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        if (rect) {
                                rect->property_fill_color_rgba() = 0xBBBBBBAA;
                        }
-                       track_canvas->get_window()->set_cursor (*fade_in_cursor);
+                       set_canvas_cursor (fade_in_cursor);
                }
                 break;
 
@@ -1648,7 +1708,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        if (rect) {
                                rect->property_fill_color_rgba() = 0xBBBBBBAA;
                        }
-                       track_canvas->get_window()->set_cursor (*fade_out_cursor);
+                       set_canvas_cursor (fade_out_cursor);
                }
                break;
        case FeatureLineItem:
@@ -1711,7 +1771,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                }
 
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                }
 
                hide_verbose_canvas_cursor ();
@@ -1732,7 +1792,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 #endif
 
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                }
                break;
 
@@ -1745,7 +1805,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                                line->property_fill_color_rgba() = al->get_line_color();
                }
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                }
                break;
 
@@ -1753,7 +1813,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                /* see enter_handler() for notes */
                if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
                        if (is_drawable() && mouse_mode == MouseObject) {
-                               track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                                set_canvas_cursor (current_canvas_cursor);
                        }
                }
                break;
@@ -1765,7 +1825,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case TempoBarItem:
        case MarkerBarItem:
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                }
                break;
 
@@ -1782,7 +1842,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case TempoMarkerItem:
 
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*timebar_cursor);
+                       set_canvas_cursor (timebar_cursor);
                }
 
                break;
@@ -1797,12 +1857,12 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                                rect->property_outline_pixels() = 0;
                        }
                }
-               track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                set_canvas_cursor (current_canvas_cursor);
                break;
 
        case AutomationTrackItem:
                if (is_drawable()) {
-                       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+                        set_canvas_cursor (current_canvas_cursor);
                        clear_entered_track = true;
                        Glib::signal_idle().connect (sigc::mem_fun(*this, &Editor::left_automation_track));
                }
@@ -2760,9 +2820,11 @@ Editor::update_join_object_range_location (double x, double y)
                        double cy = y;
                        rtv->canvas_display()->w2i (cx, cy);
 
-                       bool const top_half = cy < rtv->current_height () / 2;
-                       
-                       _join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
+                       double const c = cy / rtv->view()->child_height();
+                       double d;
+                       double const f = modf (c, &d);
+
+                       _join_object_range_state = f < 0.5 ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
                }
        }
 }