diff options
-rw-r--r-- | gtk2_ardour/actions.cc | 57 | ||||
-rw-r--r-- | gtk2_ardour/actions.h | 5 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 48 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 20 | ||||
-rw-r--r-- | gtk2_ardour/keyboard.cc | 66 | ||||
-rw-r--r-- | gtk2_ardour/keyboard.h | 19 | ||||
-rw-r--r-- | gtk2_ardour/mnemonic-us.bindings.in | 24 |
7 files changed, 190 insertions, 49 deletions
diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index 1f5ff658c9..14713ff4ef 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -158,6 +158,50 @@ struct SortActionsByLabel { }; void +ActionManager::get_all_actions (vector<string>& groups, vector<string>& names, vector<AccelKey>& bindings) +{ + /* the C++ API for functions used here appears to be broken in + gtkmm2.6, so we fall back to the C level. + */ + + GList* list = gtk_ui_manager_get_action_groups (ui_manager->gobj()); + GList* node; + GList* acts; + + for (node = list; node; node = g_list_next (node)) { + + GtkActionGroup* group = (GtkActionGroup*) node->data; + + /* first pass: collect them all */ + + typedef std::list<Glib::RefPtr<Gtk::Action> > action_list; + action_list the_acts; + + for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) { + GtkAction* action = (GtkAction*) acts->data; + the_acts.push_back (Glib::wrap (action, true)); + } + + /* now sort by label */ + + SortActionsByLabel cmp; + the_acts.sort (cmp); + + for (action_list::iterator a = the_acts.begin(); a != the_acts.end(); ++a) { + + string accel_path = (*a)->get_accel_path (); + + groups.push_back (gtk_action_group_get_name(group)); + names.push_back (accel_path.substr (accel_path.find_last_of ('/') + 1)); + + AccelKey key; + lookup_entry (accel_path, key); + bindings.push_back (AccelKey (key.get_key(), Gdk::ModifierType (key.get_mod()))); + } + } +} + +void ActionManager::get_all_actions (vector<string>& names, vector<string>& paths, vector<string>& keys, vector<AccelKey>& bindings) { /* the C++ API for functions used here appears to be broken in @@ -223,6 +267,19 @@ ActionManager::get_widget (const char * name) } RefPtr<Action> +ActionManager::get_action (const char* path) +{ + GtkAction* _act; + RefPtr<Action> act; + + if ((_act = gtk_ui_manager_get_action (ui_manager->gobj(), path)) != 0) { + return Glib::wrap (_act, true); + } + + return act; +} + +RefPtr<Action> ActionManager::get_action (const char* group_name, const char* action_name) { /* the C++ API for functions used here appears to be broken in diff --git a/gtk2_ardour/actions.h b/gtk2_ardour/actions.h index 832403f01f..0ff45a7a10 100644 --- a/gtk2_ardour/actions.h +++ b/gtk2_ardour/actions.h @@ -70,6 +70,7 @@ class ActionManager static Gtk::Widget* get_widget (const char * name); static Glib::RefPtr<Gtk::Action> get_action (const char* group, const char* name); + static Glib::RefPtr<Gtk::Action> get_action (const char* path); static void add_action_group (Glib::RefPtr<Gtk::ActionGroup>); @@ -100,6 +101,10 @@ class ActionManager std::vector<std::string>& keys, std::vector<Gtk::AccelKey>& bindings); + static void get_all_actions (std::vector<std::string>& groups, + std::vector<std::string>& paths, + std::vector<Gtk::AccelKey>& bindings); + static void uncheck_toggleaction (const char * actionname); }; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 9c7fb3a074..8f770c7cd5 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -193,53 +193,53 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-1", _("Save View 1"), bind (mem_fun (*this, &Editor::save_visual_state), 0)); + act = ActionManager::register_action (editor_actions, "save-visual-state-1", _("Save View 1"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 0)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-1", _("Goto View 1"), bind (mem_fun (*this, &Editor::goto_visual_state), 0)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-1", _("Goto View 1"), bind (mem_fun (*this, &Editor::start_visual_state_op), 0)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-2", _("Save View 2"), bind (mem_fun (*this, &Editor::save_visual_state), 1)); + act = ActionManager::register_action (editor_actions, "save-visual-state-2", _("Save View 2"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 1)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-2", _("Goto View 2"), bind (mem_fun (*this, &Editor::goto_visual_state), 1)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-2", _("Goto View 2"), bind (mem_fun (*this, &Editor::start_visual_state_op), 1)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-3", _("Save View 3"), bind (mem_fun (*this, &Editor::save_visual_state), 2)); + act = ActionManager::register_action (editor_actions, "save-visual-state-3", _("Save View 3"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 2)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-3", _("Goto View 3"), bind (mem_fun (*this, &Editor::goto_visual_state), 2)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-3", _("Goto View 3"), bind (mem_fun (*this, &Editor::start_visual_state_op), 2)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-4", _("Save View 4"), bind (mem_fun (*this, &Editor::save_visual_state), 3)); + act = ActionManager::register_action (editor_actions, "save-visual-state-4", _("Save View 4"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 3)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-4", _("Goto View 4"), bind (mem_fun (*this, &Editor::goto_visual_state), 3)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-4", _("Goto View 4"), bind (mem_fun (*this, &Editor::start_visual_state_op), 3)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-5", _("Save View 5"), bind (mem_fun (*this, &Editor::save_visual_state), 4)); + act = ActionManager::register_action (editor_actions, "save-visual-state-5", _("Save View 5"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 4)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-5", _("Goto View 5"), bind (mem_fun (*this, &Editor::goto_visual_state), 4)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-5", _("Goto View 5"), bind (mem_fun (*this, &Editor::start_visual_state_op), 4)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-6", _("Save View 6"), bind (mem_fun (*this, &Editor::save_visual_state), 5)); + act = ActionManager::register_action (editor_actions, "save-visual-state-6", _("Save View 6"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 5)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-6", _("Goto View 6"), bind (mem_fun (*this, &Editor::goto_visual_state), 5)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-6", _("Goto View 6"), bind (mem_fun (*this, &Editor::start_visual_state_op), 5)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-7", _("Save View 7"), bind (mem_fun (*this, &Editor::save_visual_state), 6)); + act = ActionManager::register_action (editor_actions, "save-visual-state-7", _("Save View 7"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 6)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-7", _("Goto View 7"), bind (mem_fun (*this, &Editor::goto_visual_state), 6)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-7", _("Goto View 7"), bind (mem_fun (*this, &Editor::start_visual_state_op), 6)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-8", _("Save View 8"), bind (mem_fun (*this, &Editor::save_visual_state), 7)); + act = ActionManager::register_action (editor_actions, "save-visual-state-8", _("Save View 8"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 7)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-8", _("Goto View 8"), bind (mem_fun (*this, &Editor::goto_visual_state), 7)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-8", _("Goto View 8"), bind (mem_fun (*this, &Editor::start_visual_state_op), 7)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-9", _("Save View 9"), bind (mem_fun (*this, &Editor::save_visual_state), 8)); + act = ActionManager::register_action (editor_actions, "save-visual-state-9", _("Save View 9"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 8)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-9", _("Goto View 9"), bind (mem_fun (*this, &Editor::goto_visual_state), 8)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-9", _("Goto View 9"), bind (mem_fun (*this, &Editor::start_visual_state_op), 8)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-10", _("Save View 10"), bind (mem_fun (*this, &Editor::save_visual_state), 9)); + act = ActionManager::register_action (editor_actions, "save-visual-state-10", _("Save View 10"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 9)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-10", _("Goto View 10"), bind (mem_fun (*this, &Editor::goto_visual_state), 9)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-10", _("Goto View 10"), bind (mem_fun (*this, &Editor::start_visual_state_op), 9)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-11", _("Save View 11"), bind (mem_fun (*this, &Editor::save_visual_state), 10)); + act = ActionManager::register_action (editor_actions, "save-visual-state-11", _("Save View 11"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 10)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-11", _("Goto View 11"), bind (mem_fun (*this, &Editor::goto_visual_state), 10)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-11", _("Goto View 11"), bind (mem_fun (*this, &Editor::start_visual_state_op), 10)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "save-visual-state-12", _("Save View 12"), bind (mem_fun (*this, &Editor::save_visual_state), 11)); + act = ActionManager::register_action (editor_actions, "save-visual-state-12", _("Save View 12"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 11)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "goto-visual-state-12", _("Goto View 12"), bind (mem_fun (*this, &Editor::goto_visual_state), 11)); + act = ActionManager::register_action (editor_actions, "goto-visual-state-12", _("Goto View 12"), bind (mem_fun (*this, &Editor::start_visual_state_op), 11)); ActionManager::session_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 407947d90b..76ad82cd9f 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -5926,7 +5926,7 @@ Editor::save_visual_state (uint32_t n) void Editor::goto_visual_state (uint32_t n) { - if (visual_states.size() < n) { + if (visual_states.size() <= n) { return; } @@ -5941,25 +5941,31 @@ void Editor::start_visual_state_op (uint32_t n) { if (visual_state_op_connection.empty()) { - visual_state_op_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::end_visual_state_op), n), 2000); - } else { - cancel_visual_state_op (n); + cerr << "START pending op, for " << n << endl; + visual_state_op_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::end_visual_state_op), n), 1000); } } void Editor::cancel_visual_state_op (uint32_t n) { - - visual_state_op_connection.disconnect(); - goto_visual_state (n); + if (!visual_state_op_connection.empty()) { + cerr << "CANCEL pending op, and goto " << n << endl; + visual_state_op_connection.disconnect(); + goto_visual_state (n); + } else { + cerr << "NOTHING TO DO\n"; + } } bool Editor::end_visual_state_op (uint32_t n) { + cerr << "TIMEOUT HIT, saveing visual state " << n << endl; visual_state_op_connection.disconnect(); save_visual_state (n); + cerr << "vsop empty ? " << visual_state_op_connection.empty() << endl; + // FLASH SCREEN OR SOMETHING return false; // do not call again } diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc index 0899e1f354..44066715db 100644 --- a/gtk2_ardour/keyboard.cc +++ b/gtk2_ardour/keyboard.cc @@ -17,6 +17,7 @@ */ +#include <vector> #include <ardour/ardour.h> #include "ardour_ui.h" @@ -35,11 +36,14 @@ #include "keyboard.h" #include "gui_thread.h" #include "opts.h" +#include "actions.h" #include "i18n.h" using namespace PBD; using namespace ARDOUR; +using namespace Gtk; +using namespace std; #define KBD_DEBUG 0 bool debug_keyboard = false; @@ -73,7 +77,8 @@ bool Keyboard::_some_magic_widget_has_focus = false; std::string Keyboard::user_keybindings_path; bool Keyboard::can_save_keybindings = false; map<string,string> Keyboard::binding_files; -std::string Keyboard::_current_binding_name = _("Unknown"); +string Keyboard::_current_binding_name = _("Unknown"); +map<AccelKey,pair<string,string>,Keyboard::AccelKeyLess> Keyboard::release_keys; /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ @@ -183,6 +188,7 @@ gint Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) { uint32_t keyval; + bool ret = false; #if 0 cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type @@ -212,7 +218,23 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) if (find (state.begin(), state.end(), keyval) == state.end()) { state.push_back (keyval); sort (state.begin(), state.end()); - } + + } else { + + /* key is already down. if its also used for release, + prevent auto-repeat events. + */ + + for (map<AccelKey,two_strings,AccelKeyLess>::iterator k = release_keys.begin(); k != release_keys.end(); ++k) { + + const AccelKey& ak (k->first); + + if (keyval == ak.get_key() && (Gdk::ModifierType)(event->state | Gdk::RELEASE_MASK) == ak.get_mod()) { + ret = true; + break; + } + } + } } else if (event->type == GDK_KEY_RELEASE) { @@ -223,6 +245,20 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) sort (state.begin(), state.end()); } + for (map<AccelKey,two_strings,AccelKeyLess>::iterator k = release_keys.begin(); k != release_keys.end(); ++k) { + + const AccelKey& ak (k->first); + two_strings ts (k->second); + + if (keyval == ak.get_key() && (Gdk::ModifierType)(event->state | Gdk::RELEASE_MASK) == ak.get_mod()) { + Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (ts.first.c_str(), ts.second.c_str()); + if (act) { + act->activate(); + ret = true; + } + break; + } + } } if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, PrimaryModifier)) { @@ -232,7 +268,7 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) } } - return false; + return ret; } bool @@ -552,13 +588,35 @@ Keyboard::load_keybindings (string path) } } - return true; } catch (...) { error << string_compose (_("Ardour key bindings file not found at \"%1\" or contains errors."), path) << endmsg; return false; } + + /* now find all release-driven bindings */ + + vector<string> groups; + vector<string> names; + vector<AccelKey> bindings; + + ActionManager::get_all_actions (groups, names, bindings); + + vector<string>::iterator g; + vector<AccelKey>::iterator b; + vector<string>::iterator n; + + release_keys.clear (); + + for (n = names.begin(), b = bindings.begin(), g = groups.begin(); n != names.end(); ++n, ++b, ++g) { + if ((*b).get_mod() & Gdk::RELEASE_MASK) { + cerr << "Action: " << (*n) << " bound to release of " << (*g) << '+' << (*n) << endl; + release_keys.insert (pair<AccelKey,two_strings> (*b, two_strings (*g, *n))); + } + } + + return true; } diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h index 25955935f3..175208a434 100644 --- a/gtk2_ardour/keyboard.h +++ b/gtk2_ardour/keyboard.h @@ -20,19 +20,20 @@ #ifndef __ardour_keyboard_h__ #define __ardour_keyboard_h__ +#include <map> #include <vector> #include <string> #include <sigc++/signal.h> #include <gtk/gtk.h> #include <gtkmm/window.h> +#include <gtkmm/accelkey.h> #include <ardour/types.h> #include <pbd/stateful.h> #include "selection.h" -using std::vector; using std::string; class Keyboard : public sigc::trackable, Stateful @@ -44,7 +45,7 @@ class Keyboard : public sigc::trackable, Stateful XMLNode& get_state (void); int set_state (const XMLNode&); - typedef vector<uint32_t> State; + typedef std::vector<uint32_t> State; typedef uint32_t ModifierMask; static uint32_t PrimaryModifier; @@ -121,6 +122,16 @@ class Keyboard : public sigc::trackable, Stateful static std::string current_binding_name () { return _current_binding_name; } static std::map<std::string,std::string> binding_files; + struct AccelKeyLess { + bool operator() (const Gtk::AccelKey a, const Gtk::AccelKey b) const { + if (a.get_key() != b.get_key()) { + return a.get_key() < b.get_key(); + } else { + return a.get_mod() < b.get_mod(); + } + } + }; + private: static Keyboard* _the_keyboard; @@ -137,6 +148,10 @@ class Keyboard : public sigc::trackable, Stateful static bool can_save_keybindings; static std::string _current_binding_name; + typedef std::pair<std::string,std::string> two_strings; + + static std::map<Gtk::AccelKey,two_strings,AccelKeyLess> release_keys; + static gint _snooper (GtkWidget*, GdkEventKey*, gpointer); gint snooper (GtkWidget*, GdkEventKey*); diff --git a/gtk2_ardour/mnemonic-us.bindings.in b/gtk2_ardour/mnemonic-us.bindings.in index c2ac948d80..4fb546f0a3 100644 --- a/gtk2_ardour/mnemonic-us.bindings.in +++ b/gtk2_ardour/mnemonic-us.bindings.in @@ -192,18 +192,18 @@ (gtk_accel_path "<Actions>/Editor/goto-visual-state-11" "<%PRIMARY%>F11") (gtk_accel_path "<Actions>/Editor/goto-visual-state-12" "<%PRIMARY%>F12") -(gtk_accel_path "<Actions>/Editor/save-visual-state-1" "<%PRIMARY%><%SECONDARY%>F1") -(gtk_accel_path "<Actions>/Editor/save-visual-state-2" "<%PRIMARY%><%SECONDARY%>F2") -(gtk_accel_path "<Actions>/Editor/save-visual-state-3" "<%PRIMARY%><%SECONDARY%>F3") -(gtk_accel_path "<Actions>/Editor/save-visual-state-4" "<%PRIMARY%><%SECONDARY%>F4") -(gtk_accel_path "<Actions>/Editor/save-visual-state-5" "<%PRIMARY%><%SECONDARY%>F5") -(gtk_accel_path "<Actions>/Editor/save-visual-state-6" "<%PRIMARY%><%SECONDARY%>F6") -(gtk_accel_path "<Actions>/Editor/save-visual-state-7" "<%PRIMARY%><%SECONDARY%>F7") -(gtk_accel_path "<Actions>/Editor/save-visual-state-8" "<%PRIMARY%><%SECONDARY%>F8") -(gtk_accel_path "<Actions>/Editor/save-visual-state-9" "<%PRIMARY%><%SECONDARY%>F9") -(gtk_accel_path "<Actions>/Editor/save-visual-state-10" "<%PRIMARY%><%SECONDARY%>F10") -(gtk_accel_path "<Actions>/Editor/save-visual-state-11" "<%PRIMARY%><%SECONDARY%>F11") -(gtk_accel_path "<Actions>/Editor/save-visual-state-12" "<%PRIMARY%><%SECONDARY%>F12") +(gtk_accel_path "<Actions>/Editor/save-visual-state-1" "<release><%PRIMARY%>F1") +(gtk_accel_path "<Actions>/Editor/save-visual-state-2" "<release><%PRIMARY%>F2") +(gtk_accel_path "<Actions>/Editor/save-visual-state-3" "<release><%PRIMARY%>F3") +(gtk_accel_path "<Actions>/Editor/save-visual-state-4" "<release><%PRIMARY%>F4") +(gtk_accel_path "<Actions>/Editor/save-visual-state-5" "<release><%PRIMARY%>F5") +(gtk_accel_path "<Actions>/Editor/save-visual-state-6" "<release><%PRIMARY%>F6") +(gtk_accel_path "<Actions>/Editor/save-visual-state-7" "<release><%PRIMARY%>F7") +(gtk_accel_path "<Actions>/Editor/save-visual-state-8" "<release><%PRIMARY%>F8") +(gtk_accel_path "<Actions>/Editor/save-visual-state-9" "<release><%PRIMARY%>F9") +(gtk_accel_path "<Actions>/Editor/save-visual-state-10" "<release><%PRIMARY%>F10") +(gtk_accel_path "<Actions>/Editor/save-visual-state-11" "<release><%PRIMARY%>F11") +(gtk_accel_path "<Actions>/Editor/save-visual-state-12" "<release><%PRIMARY%>F12") ;; numbers |