X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fgtkmm2ext%2Fkeyboard.cc;h=5280c526f3ffcd6087143bc83a6f57621b666f99;hb=e307094af33ccf19ea152dd4870011fe9da9be74;hp=b1f5d5561a665236a6d52ec96db66ea3e7cbe943;hpb=f028a6bffb5626af40bd65a1a2293d2a13673c31;p=ardour.git diff --git a/libs/gtkmm2ext/keyboard.cc b/libs/gtkmm2ext/keyboard.cc index b1f5d5561a..5280c526f3 100644 --- a/libs/gtkmm2ext/keyboard.cc +++ b/libs/gtkmm2ext/keyboard.cc @@ -42,8 +42,9 @@ #include "gtkmm2ext/bindings.h" #include "gtkmm2ext/keyboard.h" #include "gtkmm2ext/debug.h" +#include "gtkmm2ext/utils.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace PBD; using namespace Gtk; @@ -57,9 +58,9 @@ guint Keyboard::delete_mod = GDK_SHIFT_MASK; guint Keyboard::insert_note_but = 1; guint Keyboard::insert_note_mod = GDK_CONTROL_MASK; -#ifdef GTKOSX +#ifdef __APPLE__ -uint Keyboard::PrimaryModifier = GDK_MOD2_MASK; // Command +guint Keyboard::PrimaryModifier = GDK_MOD2_MASK; // Command guint Keyboard::SecondaryModifier = GDK_CONTROL_MASK; // Control guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK; // Shift guint Keyboard::Level4Modifier = GDK_MOD1_MASK; // Alt/Option @@ -72,6 +73,11 @@ const char* Keyboard::secondary_modifier_name() { return _("Control"); } const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); } const char* Keyboard::level4_modifier_name() { return _("Option"); } +const char* Keyboard::primary_modifier_short_name() { return _("Cmd"); } +const char* Keyboard::secondary_modifier_short_name() { return _("Ctrl"); } +const char* Keyboard::tertiary_modifier_short_name() { return S_("Key|Shift"); } +const char* Keyboard::level4_modifier_short_name() { return _("Opt"); } + guint Keyboard::snap_mod = Keyboard::Level4Modifier|Keyboard::TertiaryModifier; // XXX this is probably completely wrong guint Keyboard::snap_delta_mod = Keyboard::Level4Modifier; @@ -80,7 +86,7 @@ guint Keyboard::snap_delta_mod = Keyboard::Level4Modifier; guint Keyboard::PrimaryModifier = GDK_CONTROL_MASK; // Control guint Keyboard::SecondaryModifier = GDK_MOD1_MASK; // Alt/Option guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK; // Shift -guint Keyboard::Level4Modifier = GDK_MOD4_MASK; // Mod4/Windows +guint Keyboard::Level4Modifier = GDK_MOD4_MASK|GDK_SUPER_MASK; // Mod4/Windows guint Keyboard::CopyModifier = GDK_CONTROL_MASK; guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK; guint Keyboard::button2_modifiers = 0; /* not used */ @@ -90,6 +96,11 @@ const char* Keyboard::secondary_modifier_name() { return _("Alt"); } const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); } const char* Keyboard::level4_modifier_name() { return _("Windows"); } +const char* Keyboard::primary_modifier_short_name() { return _("Ctrl"); } +const char* Keyboard::secondary_modifier_short_name() { return _("Alt"); } +const char* Keyboard::tertiary_modifier_short_name() { return S_("Key|Shift"); } +const char* Keyboard::level4_modifier_short_name() { return _("Win"); } + guint Keyboard::snap_mod = Keyboard::SecondaryModifier; guint Keyboard::snap_delta_mod = Keyboard::SecondaryModifier|Keyboard::Level4Modifier; @@ -111,11 +122,12 @@ bool Keyboard::can_save_keybindings = false; bool Keyboard::bindings_changed_after_save_became_legal = false; map Keyboard::binding_files; string Keyboard::_current_binding_name; +string Keyboard::binding_filename_suffix = X_(".keys"); Gtk::Window* Keyboard::pre_dialog_active_window = 0; -XMLNode* Keyboard::_bindings_node = 0; /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ GdkModifierType Keyboard::RelevantModifierKeyMask; +sigc::signal0 Keyboard::RelevantModifierKeysChanged; void Keyboard::magic_widget_grab_focus () @@ -142,39 +154,7 @@ Keyboard::Keyboard () _current_binding_name = _("Unknown"); } - RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask (); - - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | PrimaryModifier); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | SecondaryModifier); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | TertiaryModifier); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | Level4Modifier); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | CopyModifier); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | RangeSelectModifier); - - gtk_accelerator_set_default_mod_mask (RelevantModifierKeyMask); - -#ifdef __APPLE__ - /* Remove SUPER,HYPER,META. - * - * GTK on OS X adds META when Command is pressed for various indefensible reasons, since - * it also uses MOD2 to indicate Command. Our code assumes that each - * modifier (Primary, Secondary etc.) is represented by a single bit in - * the modifier mask, but GTK's (STUPID) design uses two (MOD2 + META) - * to represent the Command key. Some discussion about this is here: - * https://bugzilla.gnome.org/show_bug.cgi?id=692597 - * - * We cannot do this until AFTER we told GTK what the default modifier - * was, because otherwise it will fail to recognize MOD2-META- as - * an accelerator. - * - * Note that in the tabbed branch, we no longer use GTK accelerators - * for functional purposes, so this is as critical for that branch. - */ - - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_SUPER_MASK); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_HYPER_MASK); - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_META_MASK); -#endif + reset_relevant_modifier_key_mask(); snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this); } @@ -215,7 +195,7 @@ Keyboard::get_state (void) int Keyboard::set_state (const XMLNode& node, int /*version*/) { - const XMLProperty* prop; + XMLProperty const * prop; if ((prop = node.property ("copy-modifier")) != 0) { sscanf (prop->value().c_str(), "%d", &CopyModifier); @@ -262,64 +242,6 @@ Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data) return ((Keyboard *) data)->snooper (widget, event); } -static string -show_gdk_event_state (int state) -{ - string s; - if (state & GDK_SHIFT_MASK) { - s += "+SHIFT"; - } - if (state & GDK_LOCK_MASK) { - s += "+LOCK"; - } - if (state & GDK_CONTROL_MASK) { - s += "+CONTROL"; - } - if (state & GDK_MOD1_MASK) { - s += "+MOD1"; - } - if (state & GDK_MOD2_MASK) { - s += "+MOD2"; - } - if (state & GDK_MOD3_MASK) { - s += "+MOD3"; - } - if (state & GDK_MOD4_MASK) { - s += "+MOD4"; - } - if (state & GDK_MOD5_MASK) { - s += "+MOD5"; - } - if (state & GDK_BUTTON1_MASK) { - s += "+BUTTON1"; - } - if (state & GDK_BUTTON2_MASK) { - s += "+BUTTON2"; - } - if (state & GDK_BUTTON3_MASK) { - s += "+BUTTON3"; - } - if (state & GDK_BUTTON4_MASK) { - s += "+BUTTON4"; - } - if (state & GDK_BUTTON5_MASK) { - s += "+BUTTON5"; - } - if (state & GDK_SUPER_MASK) { - s += "+SUPER"; - } - if (state & GDK_HYPER_MASK) { - s += "+HYPER"; - } - if (state & GDK_META_MASK) { - s += "+META"; - } - if (state & GDK_RELEASE_MASK) { - s += "+RELEASE"; - } - - return s; -} gint Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) @@ -372,7 +294,7 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) #if 0 /* August 2015: we don't have any release bindings */ - + for (map::iterator k = release_keys.begin(); k != release_keys.end(); ++k) { const AccelKey& ak (k->first); @@ -387,17 +309,44 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) } } - /* Special keys that we want to handle in - any dialog, no matter whether it uses - the regular set of accelerators or not - */ + if (event->type == GDK_KEY_RELEASE) { + + State::iterator k = find (state.begin(), state.end(), keyval); + + if (k != state.end()) { + /* this cannot change the ordering, so need to sort */ + state.erase (k); + if (state.empty()) { + DEBUG_TRACE (DEBUG::Keyboard, "no keys down\n"); + } else { +#ifndef NDEBUG + if (DEBUG_ENABLED(DEBUG::Keyboard)) { + DEBUG_STR_DECL(a); + DEBUG_STR_APPEND(a, "keyboard, keys still down: "); + for (State::iterator i = state.begin(); i != state.end(); ++i) { + DEBUG_STR_APPEND(a, gdk_keyval_name (*i)); + DEBUG_STR_APPEND(a, ','); + } + DEBUG_STR_APPEND(a, '\n'); + DEBUG_TRACE (DEBUG::Keyboard, DEBUG_STR(a).str()); + } +#endif /* NDEBUG */ + } + } - if (event->type == GDK_KEY_RELEASE && modifier_state_equals (event->state, PrimaryModifier)) { - switch (event->keyval) { - case GDK_w: - close_current_dialog (); - ret = true; - break; + if (modifier_state_equals (event->state, PrimaryModifier)) { + + /* Special keys that we want to handle in + any dialog, no matter whether it uses + the regular set of accelerators or not + */ + + switch (event->keyval) { + case GDK_w: + close_current_dialog (); + ret = true; + break; + } } } @@ -406,6 +355,23 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) return ret; } +void +Keyboard::reset_relevant_modifier_key_mask () +{ + RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask (); + + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | PrimaryModifier); + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | SecondaryModifier); + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | TertiaryModifier); + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | Level4Modifier); + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | CopyModifier); + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | RangeSelectModifier); + + gtk_accelerator_set_default_mod_mask (RelevantModifierKeyMask); + + RelevantModifierKeysChanged(); /* EMIT SIGNAL */ +} + void Keyboard::close_current_dialog () { @@ -477,6 +443,7 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* /*win*/) current_window = 0; } } else { + DEBUG_TRACE (DEBUG::Keyboard, "LEAVE window without event\n"); current_window = 0; } @@ -498,7 +465,9 @@ Keyboard::focus_out_window (GdkEventFocus * ev, Gtk::Window* win) state.clear (); current_window = 0; } else { - current_window = 0; + if (win == current_window) { + current_window = 0; + } } DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Foucusing out window, title = %1\n", win->get_title())); @@ -515,9 +484,8 @@ Keyboard::set_edit_button (guint but) void Keyboard::set_edit_modifier (guint mod) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod); edit_mod = mod; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod); + reset_relevant_modifier_key_mask(); } void @@ -529,9 +497,8 @@ Keyboard::set_delete_button (guint but) void Keyboard::set_delete_modifier (guint mod) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod); delete_mod = mod; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod); + reset_relevant_modifier_key_mask(); } void @@ -543,34 +510,30 @@ Keyboard::set_insert_note_button (guint but) void Keyboard::set_insert_note_modifier (guint mod) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~insert_note_mod); insert_note_mod = mod; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | insert_note_mod); + reset_relevant_modifier_key_mask(); } void Keyboard::set_modifier (uint32_t newval, uint32_t& var) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~var); var = newval; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | var); + reset_relevant_modifier_key_mask(); } void Keyboard::set_snap_modifier (guint mod) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod); snap_mod = mod; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod); + reset_relevant_modifier_key_mask(); } void Keyboard::set_snap_delta_modifier (guint mod) { - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_delta_mod); snap_delta_mod = mod; - RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_delta_mod); + reset_relevant_modifier_key_mask(); } bool @@ -592,7 +555,7 @@ Keyboard::is_insert_note_event (GdkEventButton *ev) bool Keyboard::is_button2_event (GdkEventButton* ev) { -#ifdef GTKOSX +#ifdef __APPLE__ return (ev->button == 2) || ((ev->button == 1) && ((ev->state & Keyboard::button2_modifiers) == Keyboard::button2_modifiers)); @@ -668,7 +631,7 @@ Keyboard::load_keybindings (string const & path) /* Call to specific implementation to load bindings from path */ read_keybindings (path); - + _current_binding_name = _("Unknown"); for (map::iterator x = binding_files.begin(); x != binding_files.end(); ++x) { @@ -697,8 +660,24 @@ Keyboard::read_keybindings (string const & path) return -1; } - _bindings_node = new XMLNode (*tree.root ()); /* copy operation. Sorry */ - + /* toplevel node is "BindingSet; children are "Bindings" */ + + XMLNodeList const& children = tree.root()->children(); + + for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) { + XMLNode const * child = *i; + if (child->name() == X_("Bindings")) { + XMLProperty const* name = child->property (X_("name")); + if (!name) { + warning << _("Keyboard binding found without a name") << endmsg; + continue; + } + + Bindings* b = new Bindings (name->value()); + b->load (**i); + } + } + return 0; } @@ -709,10 +688,10 @@ Keyboard::store_keybindings (string const & path) XMLNode* bnode; int ret = 0; - for (map::const_iterator c = Bindings::bindings_for_state.begin(); c != Bindings::bindings_for_state.end(); ++c) { + for (list::const_iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) { bnode = new XMLNode (X_("Bindings")); - bnode->add_property (X_("name"), c->first); - c->second->save (*bnode); + bnode->add_property (X_("name"), (*b)->name()); + (*b)->save (*bnode); node->add_child_nocopy (*bnode); } @@ -723,7 +702,7 @@ Keyboard::store_keybindings (string const & path) error << string_compose (_("Cannot save key bindings to %1"), path) << endmsg; ret = -1; } - + return ret; } @@ -743,7 +722,9 @@ Keyboard::reset_bindings () { PBD::Unwinder uw (can_save_keybindings, false); + Bindings::reset_bindings (); setup_keybindings (); + Bindings::associate_all (); } return 0;