4 #include "pbd/convert.h"
6 #include "gtkmm2ext/actions.h"
7 #include "gtkmm2ext/bindings.h"
8 #include "gtkmm2ext/keyboard.h"
15 using namespace Gtkmm2ext;
17 uint32_t Bindings::_ignored_state = 0;
19 MouseButton::MouseButton (uint32_t state, uint32_t keycode)
21 uint32_t ignore = Bindings::ignored_state();
23 if (gdk_keyval_is_upper (keycode) && gdk_keyval_is_lower (keycode)) {
24 /* key is not subject to case, so ignore SHIFT
26 ignore |= GDK_SHIFT_MASK;
29 _val = (state & ~ignore);
35 MouseButton::make_button (const string& str, MouseButton& b)
39 if (str.find ("Primary") != string::npos) {
40 s |= Keyboard::PrimaryModifier;
43 if (str.find ("Secondary") != string::npos) {
44 s |= Keyboard::SecondaryModifier;
47 if (str.find ("Tertiary") != string::npos) {
48 s |= Keyboard::TertiaryModifier;
51 if (str.find ("Level4") != string::npos) {
52 s |= Keyboard::Level4Modifier;
55 string::size_type lastmod = str.find_last_of ('-');
56 uint32_t button_number;
58 if (lastmod == string::npos) {
59 button_number = PBD::atoi (str);
61 button_number = PBD::atoi (str.substr (lastmod+1));
64 b = MouseButton (s, button_number);
69 MouseButton::name () const
75 if (s & Keyboard::PrimaryModifier) {
78 if (s & Keyboard::SecondaryModifier) {
84 if (s & Keyboard::TertiaryModifier) {
90 if (s & Keyboard::Level4Modifier) {
102 snprintf (buf, sizeof (buf), "%u", button());
108 KeyboardKey::KeyboardKey (uint32_t state, uint32_t keycode)
110 uint32_t ignore = Bindings::ignored_state();
112 if (gdk_keyval_is_upper (keycode) && gdk_keyval_is_lower (keycode)) {
113 /* key is not subject to case, so ignore SHIFT
115 ignore |= GDK_SHIFT_MASK;
118 _val = (state & ~ignore);
125 KeyboardKey::name () const
131 if (s & Keyboard::PrimaryModifier) {
134 if (s & Keyboard::SecondaryModifier) {
140 if (s & Keyboard::TertiaryModifier) {
146 if (s & Keyboard::Level4Modifier) {
157 str += gdk_keyval_name (key());
163 KeyboardKey::make_key (const string& str, KeyboardKey& k)
167 if (str.find ("Primary") != string::npos) {
168 s |= Keyboard::PrimaryModifier;
171 if (str.find ("Secondary") != string::npos) {
172 s |= Keyboard::SecondaryModifier;
175 if (str.find ("Tertiary") != string::npos) {
176 s |= Keyboard::TertiaryModifier;
179 if (str.find ("Level4") != string::npos) {
180 s |= Keyboard::Level4Modifier;
183 string::size_type lastmod = str.find_last_of ('-');
186 if (lastmod == string::npos) {
187 keyval = gdk_keyval_from_name (str.c_str());
189 keyval = gdk_keyval_from_name (str.substr (lastmod+1).c_str());
192 if (keyval == GDK_VoidSymbol) {
196 k = KeyboardKey (s, keyval);
200 Bindings::Bindings ()
205 Bindings::~Bindings()
210 Bindings::set_action_map (ActionMap& am)
213 press_bindings.clear ();
214 release_bindings.clear ();
218 Bindings::activate (KeyboardKey kb, Operation op)
220 KeybindingMap* kbm = 0;
224 kbm = &press_bindings;
227 kbm = &release_bindings;
231 KeybindingMap::iterator k = kbm->find (kb);
233 if (k == kbm->end()) {
234 /* no entry for this key in the state map */
240 k->second->activate ();
245 Bindings::add (KeyboardKey kb, Operation op, RefPtr<Action> what)
247 KeybindingMap* kbm = 0;
251 kbm = &press_bindings;
254 kbm = &release_bindings;
258 KeybindingMap::iterator k = kbm->find (kb);
260 if (k == kbm->end()) {
261 pair<KeyboardKey,RefPtr<Action> > newpair (kb, what);
262 kbm->insert (newpair);
263 // cerr << "Bindings added " << kb.key() << " w/ " << kb.state() << " => " << what->get_name() << endl;
270 Bindings::remove (KeyboardKey kb, Operation op)
272 KeybindingMap* kbm = 0;
276 kbm = &press_bindings;
279 kbm = &release_bindings;
283 KeybindingMap::iterator k = kbm->find (kb);
285 if (k != kbm->end()) {
291 Bindings::activate (MouseButton bb, Operation op)
293 MouseButtonBindingMap* bbm = 0;
297 bbm = &button_press_bindings;
300 bbm = &button_release_bindings;
304 MouseButtonBindingMap::iterator b = bbm->find (bb);
306 if (b == bbm->end()) {
307 /* no entry for this key in the state map */
313 b->second->activate ();
318 Bindings::add (MouseButton bb, Operation op, RefPtr<Action> what)
320 MouseButtonBindingMap* bbm = 0;
324 bbm = &button_press_bindings;
327 bbm = &button_release_bindings;
331 MouseButtonBindingMap::iterator b = bbm->find (bb);
333 if (b == bbm->end()) {
334 pair<MouseButton,RefPtr<Action> > newpair (bb, what);
335 bbm->insert (newpair);
336 // cerr << "Bindings added mouse button " << bb.button() << " w/ " << bb.state() << " => " << what->get_name() << endl;
343 Bindings::remove (MouseButton bb, Operation op)
345 MouseButtonBindingMap* bbm = 0;
349 bbm = &button_press_bindings;
352 bbm = &button_release_bindings;
356 MouseButtonBindingMap::iterator b = bbm->find (bb);
358 if (b != bbm->end()) {
364 Bindings::save (const string& path)
367 XMLNode* root = new XMLNode (X_("Bindings"));
368 tree.set_root (root);
372 if (!tree.write (path)) {
373 ::unlink (path.c_str());
381 Bindings::save (XMLNode& root)
383 XMLNode* presses = new XMLNode (X_("Press"));
384 root.add_child_nocopy (*presses);
386 for (KeybindingMap::iterator k = press_bindings.begin(); k != press_bindings.end(); ++k) {
388 child = new XMLNode (X_("Binding"));
389 child->add_property (X_("key"), k->first.name());
390 string ap = k->second->get_accel_path();
391 child->add_property (X_("action"), ap.substr (ap.find ('/') + 1));
392 presses->add_child_nocopy (*child);
395 for (MouseButtonBindingMap::iterator k = button_press_bindings.begin(); k != button_press_bindings.end(); ++k) {
397 child = new XMLNode (X_("Binding"));
398 child->add_property (X_("button"), k->first.name());
399 string ap = k->second->get_accel_path();
400 child->add_property (X_("action"), ap.substr (ap.find ('/') + 1));
401 presses->add_child_nocopy (*child);
404 XMLNode* releases = new XMLNode (X_("Release"));
405 root.add_child_nocopy (*releases);
407 for (KeybindingMap::iterator k = release_bindings.begin(); k != release_bindings.end(); ++k) {
409 child = new XMLNode (X_("Binding"));
410 child->add_property (X_("key"), k->first.name());
411 string ap = k->second->get_accel_path();
412 child->add_property (X_("action"), ap.substr (ap.find ('/') + 1));
413 releases->add_child_nocopy (*child);
416 for (MouseButtonBindingMap::iterator k = button_release_bindings.begin(); k != button_release_bindings.end(); ++k) {
418 child = new XMLNode (X_("Binding"));
419 child->add_property (X_("button"), k->first.name());
420 string ap = k->second->get_accel_path();
421 child->add_property (X_("action"), ap.substr (ap.find ('/') + 1));
422 releases->add_child_nocopy (*child);
428 Bindings::load (const string& path)
436 if (!tree.read (path)) {
440 press_bindings.clear ();
441 release_bindings.clear ();
443 XMLNode& root (*tree.root());
444 const XMLNodeList& children (root.children());
446 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
454 Bindings::load (const XMLNode& node)
456 if (node.name() == X_("Press") || node.name() == X_("Release")) {
460 if (node.name() == X_("Press")) {
466 const XMLNodeList& children (node.children());
468 for (XMLNodeList::const_iterator p = children.begin(); p != children.end(); ++p) {
474 ap = (*p)->property ("action");
475 kp = (*p)->property ("key");
476 bp = (*p)->property ("button");
478 if (!ap || (!kp && !bp)) {
485 act = action_map->find_action (ap->value());
489 string::size_type slash = ap->value().find ('/');
490 if (slash != string::npos) {
491 string group = ap->value().substr (0, slash);
492 string action = ap->value().substr (slash+1);
493 act = ActionManager::get_action (group.c_str(), action.c_str());
503 if (!KeyboardKey::make_key (kp->value(), k)) {
509 if (!MouseButton::make_button (bp->value(), b)) {
519 ActionMap::find_action (const string& name)
521 _ActionMap::iterator a = actions.find (name);
523 if (a != actions.end()) {
527 return RefPtr<Action>();
531 ActionMap::register_action (const char* path,
532 const char* name, const char* label, sigc::slot<void> sl)
536 RefPtr<Action> act = Action::create (name, label);
538 act->signal_activate().connect (sl);
544 actions.insert (_ActionMap::value_type (fullpath, act));
549 ActionMap::register_radio_action (const char* path, Gtk::RadioAction::Group& rgroup,
550 const char* name, const char* label,
551 sigc::slot<void,GtkAction*> sl,
556 RefPtr<Action> act = RadioAction::create (rgroup, name, label);
557 RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
558 ract->property_value() = value;
560 act->signal_activate().connect (sigc::bind (sl, act->gobj()));
566 actions.insert (_ActionMap::value_type (fullpath, act));
571 ActionMap::register_toggle_action (const char* path,
572 const char* name, const char* label, sigc::slot<void> sl)
576 RefPtr<Action> act = ToggleAction::create (name, label);
578 act->signal_activate().connect (sl);
584 actions.insert (_ActionMap::value_type (fullpath, act));