various fixes to MidiRegionView selection handling, key handling, drawing of ghost... 3.0-alpha10
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Aug 2011 12:46:42 +0000 (12:46 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Aug 2011 12:46:42 +0000 (12:46 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10000 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h
gtk2_ardour/utils.cc
libs/gtkmm2ext/gtkmm2ext/keyboard.h

index f82f309c819a17f2a3461fb9d906b6921008674f..dd9f686561d23a2e53a8deba6e446be473eae406 100644 (file)
@@ -363,25 +363,30 @@ MidiRegionView::enter_notify (GdkEventCrossing* ev)
 {
        trackview.editor().MouseModeChanged.connect (
                _mouse_mode_connection, invalidator (*this), ui_bind (&MidiRegionView::mouse_mode_changed, this), gui_context ()
-                                                    );
-
-       Keyboard::magic_widget_grab_focus();
-       group->grab_focus();
+               );
 
        if (trackview.editor().current_mouse_mode() == MouseRange) {
                create_ghost_note (ev->x, ev->y);
        }
 
+       if (!trackview.editor().internal_editing()) {
+               Keyboard::magic_widget_drop_focus();
+       } else {
+               Keyboard::magic_widget_grab_focus();
+               group->grab_focus();
+       }
+
        return false;
 }
 
 bool
-MidiRegionView::leave_notify (GdkEventCrossing*)
+MidiRegionView::leave_notify (GdkEventCrossing* ev)
 {
        _mouse_mode_connection.disconnect ();
 
        trackview.editor().verbose_cursor()->hide ();
        remove_ghost_note ();
+
        return false;
 }
 
@@ -394,6 +399,13 @@ MidiRegionView::mouse_mode_changed ()
                remove_ghost_note ();
                trackview.editor().verbose_cursor()->hide ();
        }
+
+       if (!trackview.editor().internal_editing()) {
+               Keyboard::magic_widget_drop_focus();
+       } else {
+               Keyboard::magic_widget_grab_focus();
+               group->grab_focus();
+       }
 }
 
 bool
@@ -661,7 +673,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
                                _drag_rect->property_y1() = event_y;
                        }
 
-                       update_drag_selection(_drag_start_x, event_x, _drag_start_y, event_y);
+                       update_drag_selection(_drag_start_x, event_x, _drag_start_y, event_y, Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
                }
 
                _last_x = event_x;
@@ -705,15 +717,17 @@ MidiRegionView::key_press (GdkEventKey* ev)
           repeated presses, carry out key actions at key press, not release.
        */
 
-       if (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R) {
+       bool unmodified = Keyboard::no_modifier_keys_pressed (ev);
+       
+       if (unmodified && (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R)) {
                _mouse_state = SelectTouchDragging;
                return true;
 
-       } else if (ev->keyval == GDK_Escape) {
+       } else if (ev->keyval == GDK_Escape && unmodified) {
                clear_selection();
                _mouse_state = None;
 
-       } else if (ev->keyval == GDK_comma || ev->keyval == GDK_period) {
+       } else if (unmodified && (ev->keyval == GDK_comma || ev->keyval == GDK_period)) {
 
                bool start = (ev->keyval == GDK_comma);
                bool end = (ev->keyval == GDK_period);
@@ -724,7 +738,7 @@ MidiRegionView::key_press (GdkEventKey* ev)
 
                return true;
 
-       } else if (ev->keyval == GDK_Delete) {
+       } else if (ev->keyval == GDK_Delete && unmodified) {
 
                delete_selection();
                return true;
@@ -775,20 +789,17 @@ MidiRegionView::key_press (GdkEventKey* ev)
                }
                return true;
 
-       } else if (ev->keyval == GDK_Left) {
+       } else if (ev->keyval == GDK_Left && unmodified) {
 
                nudge_notes (false);
                return true;
 
-       } else if (ev->keyval == GDK_Right) {
+       } else if (ev->keyval == GDK_Right && unmodified) {
 
                nudge_notes (true);
                return true;
 
-       } else if (ev->keyval == GDK_Control_L) {
-               return true;
-
-       } else if (ev->keyval == GDK_c) {
+       } else if (ev->keyval == GDK_c && unmodified) {
                channel_edit ();
                return true;
        }
@@ -799,7 +810,7 @@ MidiRegionView::key_press (GdkEventKey* ev)
 bool
 MidiRegionView::key_release (GdkEventKey* ev)
 {
-       if (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R) {
+       if ((_mouse_state == SelectTouchDragging) && (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R)) {
                _mouse_state = None;
                return true;
        }
@@ -1930,40 +1941,37 @@ MidiRegionView::delete_note (boost::shared_ptr<NoteType> n)
 }
 
 void
-MidiRegionView::clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev)
-{
-       for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
-               if ((*i)->selected() && (*i) != ev) {
-                       (*i)->set_selected(false);
-                       (*i)->hide_velocity();
-               }
-       }
-
-       _selection.clear();
-}
-
-void
-MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev)
+MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev)
 {
        for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
                if ((*i) != ev) {
-
                        Selection::iterator tmp = i;
                        ++tmp;
 
                        (*i)->set_selected (false);
+                       (*i)->hide_velocity ();
                        _selection.erase (i);
-
+                       
                        i = tmp;
-
                } else {
                        ++i;
                }
        }
 
-       /* don't bother with removing this regionview from the editor selection,
-          since we're about to add another note, and thus put/keep this
-          regionview in the editor selection.
+       /* this does not change the status of this regionview w.r.t the editor
+          selection.
+       */
+}
+
+void
+MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev)
+{
+       clear_selection_except (ev);
+
+       /* don't bother with checking to see if we should remove this
+          regionview from the editor selection, since we're about to add
+          another note, and thus put/keep this regionview in the editor
+          selection anyway.
        */
 
        if (!ev->selected()) {
@@ -2071,10 +2079,14 @@ MidiRegionView::toggle_matching_notes (uint8_t notenum, uint16_t channel_mask)
 }
 
 void
-MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend)
+MidiRegionView::note_selected (ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend)
 {
        if (!add) {
-               clear_selection_except(ev);
+               clear_selection_except (ev);
+               if (!_selection.empty()) {
+                       PublicEditor& editor (trackview.editor());
+                       editor.get_selection().add (this);
+               }
        }
 
        if (!extend) {
@@ -2126,7 +2138,7 @@ MidiRegionView::note_deselected(ArdourCanvas::CanvasNoteEvent* ev)
 }
 
 void
-MidiRegionView::update_drag_selection(double x1, double x2, double y1, double y2)
+MidiRegionView::update_drag_selection(double x1, double x2, double y1, double y2, bool extend)
 {
        if (x1 > x2) {
                swap (x1, x2);
@@ -2163,7 +2175,7 @@ MidiRegionView::update_drag_selection(double x1, double x2, double y1, double y2
                        if (!(*i)->selected()) {
                                add_to_selection (*i);
                        }
-               } else if ((*i)->selected()) {
+               } else if ((*i)->selected() && !extend) {
                        // Not inside rectangle
                        remove_from_selection (*i);
                }
@@ -3333,7 +3345,7 @@ MidiRegionView::update_ghost_note (double x, double y)
        /* note that this sets the time of the ghost note in beats relative to
           the start of the region.
        */
-       _ghost_note->note()->set_time (region_frames_to_region_beats (f - _region->position()));
+       _ghost_note->note()->set_time (region_frames_to_region_beats (f));
        _ghost_note->note()->set_length (length);
        _ghost_note->note()->set_note (midi_stream_view()->y_to_note (y));
        _ghost_note->note()->set_channel (mtv->get_channel_for_add ());
index 69cddd2fc52f714e8ae2a41bd1700ade42cd5a85..29a5d648da3251cff7611cca59a80cc54f186f2e 100644 (file)
@@ -344,9 +344,9 @@ private:
        void trim_note(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::TimeType start_delta,
                       ARDOUR::MidiModel::TimeType end_delta);
 
-       void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev);
-       void clear_selection() { clear_selection_except(NULL); }
-       void update_drag_selection(double last_x, double x, double last_y, double y);
+       void clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev);
+       void clear_selection() { clear_selection_except (0); }
+       void update_drag_selection (double last_x, double x, double last_y, double y, bool extend);
 
        void add_to_selection (ArdourCanvas::CanvasNoteEvent*);
        void remove_from_selection (ArdourCanvas::CanvasNoteEvent*);
index 90f79239165fa50645d0aca8658d01635f99616e..8177e7facc1d274774c135d17a7f1a4d56f8c471 100644 (file)
@@ -599,6 +599,8 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        GtkWidget* focus = gtk_window_get_focus (win);
        bool special_handling_of_unmodified_accelerators = false;
        bool allow_activating = true;
+       /* consider all relevant modifiers but not LOCK or SHIFT */
+       const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
 
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
@@ -654,42 +656,38 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        */
 
 #ifdef GTKOSX
-       if (!special_handling_of_unmodified_accelerators) {
-               if (ev->state & GDK_MOD1_MASK) {
-                       /* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character"
-                          text-style handling of alt-<key>. change the keyval back to what it would be without
-                          the alt key. this way, we see <alt>-v rather than <alt>-radical and so on.
-                       */
-                       guint keyval_without_alt = osx_keyval_without_alt (ev->keyval);
-
-                       if (keyval_without_alt != GDK_VoidSymbol) {
-                                DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Remapped %1 to %2\n", gdk_keyval_name (ev->keyval), gdk_keyval_name (keyval_without_alt)));
-                               ev->keyval = keyval_without_alt;
-                       }
+       if (!special_handling_of_unmodified_accelerators && (ev->state & Keyboard::SecondaryModifier)) {
+               /* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character"
+                  text-style handling of alt-<key>. change the keyval back to what it would be without
+                  the alt key. this way, we see <alt>-v rather than <alt>-radical and so on.
+               */
+               guint keyval_without_alt = osx_keyval_without_alt (ev->keyval);
+               
+               if (keyval_without_alt != GDK_VoidSymbol) {
+                       DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Remapped %1 to %2\n", gdk_keyval_name (ev->keyval), gdk_keyval_name (keyval_without_alt)));
+                       ev->keyval = keyval_without_alt;
                }
        }
+       
 #endif
-
-       if (!special_handling_of_unmodified_accelerators) {
+       
+       if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
 
                /* pretend that certain key events that GTK does not allow
                   to be used as accelerators are actually something that
-                  it does allow.
+                  it does allow. but only where there are no modifiers.
                */
 
                uint32_t fakekey = ev->keyval;
 
                if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
                        if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
+                               DEBUG_TRACE (DEBUG::Accelerators, "\taccel group activated by fakekey\n");
                                return true;
                        }
                }
        }
 
-       /* consider all relevant modifiers but not LOCK or SHIFT */
-
-       guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
-
        if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
 
                /* no special handling or there are modifiers in effect: accelerate first */
@@ -700,6 +698,8 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                        if (gtk_window_activate_key (win, ev)) {
                                return true;
                        }
+               } else {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n");
                }
 
                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
@@ -715,6 +715,8 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
                if (allow_activating) {
                        return gtk_window_activate_key (win, ev);
+               } else {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n");
                }
 
        } else {
index db5f9ef3de579c060f07666c7caa4e7de417e192..db8100c0814367a25e98c24277510596650adf95 100644 (file)
@@ -91,6 +91,10 @@ class Keyboard : public sigc::trackable, PBD::Stateful
                return (ev->state & RelevantModifierKeyMask) == 0;
        }
 
+       static bool no_modifier_keys_pressed(GdkEventKey* ev) {
+               return (ev->state & RelevantModifierKeyMask) == 0;
+       }
+
        bool leave_window (GdkEventCrossing *ev, Gtk::Window*);
        bool enter_window (GdkEventCrossing *ev, Gtk::Window*);