more changes to Bindings, Keyboard APIs
[ardour.git] / libs / gtkmm2ext / keyboard.cc
1 /*
2     Copyright (C) 2001 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <vector>
21
22 #include <algorithm>
23 #include <cerrno>
24 #include <ctype.h>
25
26 #include "pbd/gstdio_compat.h"
27
28 #include <gtkmm/widget.h>
29 #include <gtkmm/window.h>
30 #include <gtkmm/accelmap.h>
31 #include <gdk/gdkkeysyms.h>
32
33 #include "pbd/error.h"
34 #include "pbd/convert.h"
35 #include "pbd/file_utils.h"
36 #include "pbd/search_path.h"
37 #include "pbd/xml++.h"
38 #include "pbd/debug.h"
39 #include "pbd/unwind.h"
40
41 #include "gtkmm2ext/actions.h"
42 #include "gtkmm2ext/bindings.h"
43 #include "gtkmm2ext/keyboard.h"
44 #include "gtkmm2ext/debug.h"
45
46 #include "i18n.h"
47
48 using namespace PBD;
49 using namespace Gtk;
50 using namespace Gtkmm2ext;
51 using namespace std;
52
53 guint Keyboard::edit_but = 3;
54 guint Keyboard::edit_mod = GDK_CONTROL_MASK;
55 guint Keyboard::delete_but = 3;
56 guint Keyboard::delete_mod = GDK_SHIFT_MASK;
57 guint Keyboard::insert_note_but = 1;
58 guint Keyboard::insert_note_mod = GDK_CONTROL_MASK;
59
60 #ifdef GTKOSX
61
62 uint Keyboard::PrimaryModifier = GDK_MOD2_MASK;   // Command
63 guint Keyboard::SecondaryModifier = GDK_CONTROL_MASK; // Control
64 guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK; // Shift
65 guint Keyboard::Level4Modifier = GDK_MOD1_MASK; // Alt/Option
66 guint Keyboard::CopyModifier = GDK_CONTROL_MASK;      // Control
67 guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK;
68 guint Keyboard::button2_modifiers = Keyboard::SecondaryModifier|Keyboard::Level4Modifier;
69
70 const char* Keyboard::primary_modifier_name() { return _("Command"); }
71 const char* Keyboard::secondary_modifier_name() { return _("Control"); }
72 const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); }
73 const char* Keyboard::level4_modifier_name() { return _("Option"); }
74
75 guint Keyboard::snap_mod = Keyboard::Level4Modifier|Keyboard::TertiaryModifier; // XXX this is probably completely wrong
76 guint Keyboard::snap_delta_mod = Keyboard::Level4Modifier;
77
78 #else
79
80 guint Keyboard::PrimaryModifier = GDK_CONTROL_MASK; // Control
81 guint Keyboard::SecondaryModifier = GDK_MOD1_MASK;  // Alt/Option
82 guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK;  // Shift
83 guint Keyboard::Level4Modifier = GDK_MOD4_MASK;     // Mod4/Windows
84 guint Keyboard::CopyModifier = GDK_CONTROL_MASK;
85 guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK;
86 guint Keyboard::button2_modifiers = 0; /* not used */
87
88 const char* Keyboard::primary_modifier_name() { return _("Control"); }
89 const char* Keyboard::secondary_modifier_name() { return _("Alt"); }
90 const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); }
91 const char* Keyboard::level4_modifier_name() { return _("Windows"); }
92
93 guint Keyboard::snap_mod = Keyboard::SecondaryModifier;
94 guint Keyboard::snap_delta_mod = Keyboard::SecondaryModifier|Keyboard::Level4Modifier;
95
96 #endif
97
98 guint Keyboard::GainFineScaleModifier = Keyboard::PrimaryModifier;
99 guint Keyboard::GainExtraFineScaleModifier = Keyboard::SecondaryModifier;
100
101 guint Keyboard::ScrollZoomVerticalModifier = Keyboard::SecondaryModifier;
102 guint Keyboard::ScrollZoomHorizontalModifier = Keyboard::PrimaryModifier;
103 guint Keyboard::ScrollHorizontalModifier = Keyboard::TertiaryModifier;
104
105 Keyboard*    Keyboard::_the_keyboard = 0;
106 Gtk::Window* Keyboard::current_window = 0;
107 bool         Keyboard::_some_magic_widget_has_focus = false;
108
109 std::string Keyboard::user_keybindings_path;
110 bool Keyboard::can_save_keybindings = false;
111 bool Keyboard::bindings_changed_after_save_became_legal = false;
112 map<string,string> Keyboard::binding_files;
113 string Keyboard::_current_binding_name;
114
115 /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
116 GdkModifierType Keyboard::RelevantModifierKeyMask;
117
118 void
119 Keyboard::magic_widget_grab_focus ()
120 {
121         _some_magic_widget_has_focus = true;
122 }
123
124 void
125 Keyboard::magic_widget_drop_focus ()
126 {
127         _some_magic_widget_has_focus = false;
128 }
129
130 bool
131 Keyboard::some_magic_widget_has_focus ()
132 {
133         return _some_magic_widget_has_focus;
134 }
135
136 Keyboard::Keyboard ()
137 {
138         if (_the_keyboard == 0) {
139                 _the_keyboard = this;
140                 _current_binding_name = _("Unknown");
141         }
142
143         RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask ();
144
145         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | PrimaryModifier);
146         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | SecondaryModifier);
147         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | TertiaryModifier);
148         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | Level4Modifier);
149         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | CopyModifier);
150         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | RangeSelectModifier);
151
152         gtk_accelerator_set_default_mod_mask (RelevantModifierKeyMask);
153
154 #ifdef __APPLE__
155         /* Remove SUPER,HYPER,META.
156          *
157          * GTK on OS X adds META when Command is pressed for various indefensible reasons, since
158          * it also uses MOD2 to indicate Command. Our code assumes that each
159          * modifier (Primary, Secondary etc.) is represented by a single bit in
160          * the modifier mask, but GTK's (STUPID) design uses two (MOD2 + META)
161          * to represent the Command key. Some discussion about this is here:
162          * https://bugzilla.gnome.org/show_bug.cgi?id=692597 
163          *
164          * We cannot do this until AFTER we told GTK what the default modifier
165          * was, because otherwise it will fail to recognize MOD2-META-<key> as
166          * an accelerator.
167          *
168          * Note that in the tabbed branch, we no longer use GTK accelerators
169          * for functional purposes, so this is as critical for that branch.
170          */
171
172         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_SUPER_MASK);
173         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_HYPER_MASK);
174         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~GDK_META_MASK);
175 #endif
176
177         snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
178 }
179
180 Keyboard::~Keyboard ()
181 {
182         gtk_key_snooper_remove (snooper_id);
183 }
184
185 XMLNode&
186 Keyboard::get_state (void)
187 {
188         XMLNode* node = new XMLNode ("Keyboard");
189         char buf[32];
190
191         snprintf (buf, sizeof (buf), "%d", CopyModifier);
192         node->add_property ("copy-modifier", buf);
193         snprintf (buf, sizeof (buf), "%d", edit_but);
194         node->add_property ("edit-button", buf);
195         snprintf (buf, sizeof (buf), "%d", edit_mod);
196         node->add_property ("edit-modifier", buf);
197         snprintf (buf, sizeof (buf), "%d", delete_but);
198         node->add_property ("delete-button", buf);
199         snprintf (buf, sizeof (buf), "%d", delete_mod);
200         node->add_property ("delete-modifier", buf);
201         snprintf (buf, sizeof (buf), "%d", snap_mod);
202         node->add_property ("snap-modifier", buf);
203         snprintf (buf, sizeof (buf), "%d", snap_delta_mod);
204         node->add_property ("snap-delta-modifier", buf);
205         snprintf (buf, sizeof (buf), "%d", insert_note_but);
206         node->add_property ("insert-note-button", buf);
207         snprintf (buf, sizeof (buf), "%d", insert_note_mod);
208         node->add_property ("insert-note-modifier", buf);
209
210         return *node;
211 }
212
213 int
214 Keyboard::set_state (const XMLNode& node, int /*version*/)
215 {
216         const XMLProperty* prop;
217
218         if ((prop = node.property ("copy-modifier")) != 0) {
219                 sscanf (prop->value().c_str(), "%d", &CopyModifier);
220         }
221
222         if ((prop = node.property ("edit-button")) != 0) {
223                 sscanf (prop->value().c_str(), "%d", &edit_but);
224         }
225
226         if ((prop = node.property ("edit-modifier")) != 0) {
227                 sscanf (prop->value().c_str(), "%d", &edit_mod);
228         }
229
230         if ((prop = node.property ("delete-button")) != 0) {
231                 sscanf (prop->value().c_str(), "%d", &delete_but);
232         }
233
234         if ((prop = node.property ("delete-modifier")) != 0) {
235                 sscanf (prop->value().c_str(), "%d", &delete_mod);
236         }
237
238         if ((prop = node.property ("snap-modifier")) != 0) {
239                 sscanf (prop->value().c_str(), "%d", &snap_mod);
240         }
241
242         if ((prop = node.property ("snap-delta-modifier")) != 0) {
243                 sscanf (prop->value().c_str(), "%d", &snap_delta_mod);
244         }
245
246         if ((prop = node.property ("insert-note-button")) != 0) {
247                 sscanf (prop->value().c_str(), "%d", &insert_note_but);
248         }
249
250         if ((prop = node.property ("insert-note-modifier")) != 0) {
251                 sscanf (prop->value().c_str(), "%d", &insert_note_mod);
252         }
253
254         return 0;
255 }
256
257 gint
258 Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
259 {
260         return ((Keyboard *) data)->snooper (widget, event);
261 }
262
263 static string
264 show_gdk_event_state (int state)
265 {
266         string s;
267         if (state & GDK_SHIFT_MASK) {
268                 s += "+SHIFT";
269         }
270         if (state & GDK_LOCK_MASK) {
271                 s += "+LOCK";
272         }
273         if (state & GDK_CONTROL_MASK) {
274                 s += "+CONTROL";
275         }
276         if (state & GDK_MOD1_MASK) {
277                 s += "+MOD1";
278         }
279         if (state & GDK_MOD2_MASK) {
280                 s += "+MOD2";
281         }
282         if (state & GDK_MOD3_MASK) {
283                 s += "+MOD3";
284         }
285         if (state & GDK_MOD4_MASK) {
286                 s += "+MOD4";
287         }
288         if (state & GDK_MOD5_MASK) {
289                 s += "+MOD5";
290         }
291         if (state & GDK_BUTTON1_MASK) {
292                 s += "+BUTTON1";
293         }
294         if (state & GDK_BUTTON2_MASK) {
295                 s += "+BUTTON2";
296         }
297         if (state & GDK_BUTTON3_MASK) {
298                 s += "+BUTTON3";
299         }
300         if (state & GDK_BUTTON4_MASK) {
301                 s += "+BUTTON4";
302         }
303         if (state & GDK_BUTTON5_MASK) {
304                 s += "+BUTTON5";
305         }
306         if (state & GDK_SUPER_MASK) {
307                 s += "+SUPER";
308         }
309         if (state & GDK_HYPER_MASK) {
310                 s += "+HYPER";
311         }
312         if (state & GDK_META_MASK) {
313                 s += "+META";
314         }
315         if (state & GDK_RELEASE_MASK) {
316                 s += "+RELEASE";
317         }
318
319         return s;
320 }
321
322 gint
323 Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
324 {
325         uint32_t keyval;
326         bool ret = false;
327
328         DEBUG_TRACE (
329                 DEBUG::Keyboard,
330                 string_compose (
331                         "Snoop widget %1 name: [%6] key %2 [%8] type %3 state %4 [%7] magic %5\n",
332                         widget, event->keyval, event->type, event->state, _some_magic_widget_has_focus,
333                         gtk_widget_get_name (widget), show_gdk_event_state (event->state), gdk_keyval_name (event->keyval)
334                         )
335                 );
336
337         if (event->keyval == GDK_Shift_R) {
338                 keyval = GDK_Shift_L;
339
340         } else if (event->keyval == GDK_Control_R) {
341                 keyval = GDK_Control_L;
342
343         } else {
344                 keyval = event->keyval;
345         }
346
347         if (event->state & ScrollZoomVerticalModifier) {
348                 /* There is a special and rather hacky situation in Editor which makes
349                    it useful to know when the modifier key for vertical zoom has been
350                    released, so emit a signal here (see Editor::_stepping_axis_view).
351                    Note that the state bit for the modifier key is set for the key-up
352                    event when the modifier is released, but not the key-down when it
353                    is pressed, so we get here on key-up, which is what we want.
354                 */
355                 ZoomVerticalModifierReleased (); /* EMIT SIGNAL */
356         }
357
358         if (event->type == GDK_KEY_PRESS) {
359
360                 if (find (state.begin(), state.end(), keyval) == state.end()) {
361                         state.push_back (keyval);
362                         sort (state.begin(), state.end());
363
364                 } else {
365
366                         /* key is already down. if its also used for release,
367                            prevent auto-repeat events.
368                         */
369
370 #if 0
371                         /* August 2015: we don't have any release bindings
372                          */
373                         
374                         for (map<AccelKey,two_strings,AccelKeyLess>::iterator k = release_keys.begin(); k != release_keys.end(); ++k) {
375
376                                 const AccelKey& ak (k->first);
377
378                                 if (keyval == ak.get_key() && (Gdk::ModifierType)((event->state & Keyboard::RelevantModifierKeyMask) | Gdk::RELEASE_MASK) == ak.get_mod()) {
379                                         DEBUG_TRACE (DEBUG::Keyboard, "Suppress auto repeat\n");
380                                         ret = true;
381                                         break;
382                                 }
383                         }
384 #endif
385                 }
386         }
387
388         /* Special keys that we want to handle in
389            any dialog, no matter whether it uses
390            the regular set of accelerators or not
391         */
392
393         if (event->type == GDK_KEY_RELEASE && modifier_state_equals (event->state, PrimaryModifier)) {
394                 switch (event->keyval) {
395                 case GDK_w:
396                         close_current_dialog ();
397                         ret = true;
398                         break;
399                 }
400         }
401
402         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("snooper returns %1\n", ret));
403
404         return ret;
405 }
406
407 void
408 Keyboard::close_current_dialog ()
409 {
410         if (current_window) {
411                 current_window->hide ();
412                 current_window = 0;
413
414                 if (pre_dialog_active_window) {
415                         pre_dialog_active_window->present ();
416                         pre_dialog_active_window = 0;
417                 }
418         }
419 }
420
421 bool
422 Keyboard::catch_user_event_for_pre_dialog_focus (GdkEvent* ev, Gtk::Window* w)
423 {
424         switch (ev->type) {
425         case GDK_BUTTON_PRESS:
426         case GDK_BUTTON_RELEASE:
427         case GDK_KEY_PRESS:
428         case GDK_KEY_RELEASE:
429                 pre_dialog_active_window = w;
430                 break;
431
432         case GDK_FOCUS_CHANGE:
433                 if (ev->focus_change.in) {
434                         pre_dialog_active_window = w;
435                 }
436                 break;
437
438         default:
439                 break;
440         }
441         return false;
442 }
443
444 bool
445 Keyboard::key_is_down (uint32_t keyval)
446 {
447         return find (state.begin(), state.end(), keyval) != state.end();
448 }
449
450 bool
451 Keyboard::enter_window (GdkEventCrossing *, Gtk::Window* win)
452 {
453         current_window = win;
454         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Entering window, title = %1\n", win->get_title()));
455         return false;
456 }
457
458 bool
459 Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* /*win*/)
460 {
461         if (ev) {
462                 switch (ev->detail) {
463                 case GDK_NOTIFY_INFERIOR:
464                         DEBUG_TRACE (DEBUG::Keyboard, "INFERIOR crossing ... out\n");
465                         break;
466
467                 case GDK_NOTIFY_VIRTUAL:
468                         DEBUG_TRACE (DEBUG::Keyboard, "VIRTUAL crossing ... out\n");
469                         /* fallthru */
470
471                 default:
472                         DEBUG_TRACE (DEBUG::Keyboard, "REAL crossing ... out\n");
473                         DEBUG_TRACE (DEBUG::Keyboard, "Clearing current target\n");
474                         state.clear ();
475                         current_window = 0;
476                 }
477         } else {
478                 current_window = 0;
479         }
480
481         return false;
482 }
483
484 bool
485 Keyboard::focus_in_window (GdkEventFocus *, Gtk::Window* win)
486 {
487         current_window = win;
488         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Focusing in window, title = %1\n", win->get_title()));
489         return false;
490 }
491
492 bool
493 Keyboard::focus_out_window (GdkEventFocus * ev, Gtk::Window* win)
494 {
495         if (ev) {
496                 state.clear ();
497                 current_window = 0;
498         }  else {
499                 current_window = 0;
500         }
501
502         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Foucusing out window, title = %1\n", win->get_title()));
503
504         return false;
505 }
506
507 void
508 Keyboard::set_edit_button (guint but)
509 {
510         edit_but = but;
511 }
512
513 void
514 Keyboard::set_edit_modifier (guint mod)
515 {
516         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod);
517         edit_mod = mod;
518         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod);
519 }
520
521 void
522 Keyboard::set_delete_button (guint but)
523 {
524         delete_but = but;
525 }
526
527 void
528 Keyboard::set_delete_modifier (guint mod)
529 {
530         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod);
531         delete_mod = mod;
532         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod);
533 }
534
535 void
536 Keyboard::set_insert_note_button (guint but)
537 {
538         insert_note_but = but;
539 }
540
541 void
542 Keyboard::set_insert_note_modifier (guint mod)
543 {
544         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~insert_note_mod);
545         insert_note_mod = mod;
546         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | insert_note_mod);
547 }
548
549
550 void
551 Keyboard::set_modifier (uint32_t newval, uint32_t& var)
552 {
553         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~var);
554         var = newval;
555         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | var);
556 }
557
558 void
559 Keyboard::set_snap_modifier (guint mod)
560 {
561         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod);
562         snap_mod = mod;
563         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
564 }
565
566 void
567 Keyboard::set_snap_delta_modifier (guint mod)
568 {
569         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_delta_mod);
570         snap_delta_mod = mod;
571         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_delta_mod);
572 }
573
574 bool
575 Keyboard::is_edit_event (GdkEventButton *ev)
576 {
577         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
578                 (ev->button == Keyboard::edit_button()) &&
579                 ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
580 }
581
582 bool
583 Keyboard::is_insert_note_event (GdkEventButton *ev)
584 {
585         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
586                 (ev->button == Keyboard::insert_note_button()) &&
587                 ((ev->state & RelevantModifierKeyMask) == Keyboard::insert_note_modifier());
588 }
589
590 bool
591 Keyboard::is_button2_event (GdkEventButton* ev)
592 {
593 #ifdef GTKOSX
594         return (ev->button == 2) ||
595                 ((ev->button == 1) &&
596                  ((ev->state & Keyboard::button2_modifiers) == Keyboard::button2_modifiers));
597 #else
598         return ev->button == 2;
599 #endif
600 }
601
602 bool
603 Keyboard::is_delete_event (GdkEventButton *ev)
604 {
605         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
606                 (ev->button == Keyboard::delete_button()) &&
607                 ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier());
608 }
609
610 bool
611 Keyboard::is_context_menu_event (GdkEventButton *ev)
612 {
613         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
614                 (ev->button == 3) &&
615                 ((ev->state & RelevantModifierKeyMask) == 0);
616 }
617
618 bool
619 Keyboard::no_modifiers_active (guint state)
620 {
621         return (state & RelevantModifierKeyMask) == 0;
622 }
623
624 bool
625 Keyboard::modifier_state_contains (guint state, ModifierMask mask)
626 {
627         return (state & mask) == (guint) mask;
628 }
629
630 bool
631 Keyboard::modifier_state_equals (guint state, ModifierMask mask)
632 {
633         return (state & RelevantModifierKeyMask) == (guint) mask;
634 }
635
636 void
637 Keyboard::keybindings_changed ()
638 {
639         if (Keyboard::can_save_keybindings) {
640                 Keyboard::bindings_changed_after_save_became_legal = true;
641         }
642
643         Keyboard::save_keybindings ();
644 }
645
646 void
647 Keyboard::set_can_save_keybindings (bool yn)
648 {
649         can_save_keybindings = yn;
650 }
651
652 void
653 Keyboard::save_keybindings ()
654 {
655         if (can_save_keybindings && bindings_changed_after_save_became_legal) {
656                 /* Call to specific implementation to save bindings to path */
657                 store_keybindings (user_keybindings_path);
658         }
659 }
660
661 bool
662 Keyboard::load_keybindings (string const & path)
663 {
664         try {
665                 info << "Loading bindings from " << path << endl;
666
667                 /* Call to specific implementation to load bindings from path */
668                 read_keybindings (path);
669                 
670                 _current_binding_name = _("Unknown");
671
672                 for (map<string,string>::iterator x = binding_files.begin(); x != binding_files.end(); ++x) {
673                         if (path == x->second) {
674                                 _current_binding_name = x->first;
675                                 break;
676                         }
677                 }
678
679
680         } catch (...) {
681                 error << string_compose (_("key bindings file not found at \"%2\" or contains errors."), path)
682                       << endmsg;
683                 return false;
684         }
685
686         return true;
687 }
688
689 int
690 Keyboard::read_keybindings (string const & path)
691 {
692         XMLTree tree;
693
694         if (!tree.read (path.c_str())) {
695                 return -1;
696         }
697
698         /* toplevel node is "BindingSet; children are "Bindings" */
699         
700         XMLNodeList const& children = tree.root()->children();
701
702         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
703                 if ((*i)->name() == X_("Bindings")) {
704                         XMLProperty const* name = (*i)->property (X_("name"));
705                         if (!name) {
706                                 warning << _("Keyboard binding found without a name") << endmsg;
707                                 continue;
708                         }
709                         
710                         Bindings* b = new Bindings (name->value());
711                         b->load (**i);
712                 }
713         }
714         
715         return 0;
716 }
717
718 int
719 Keyboard::store_keybindings (string const & path)
720 {
721         XMLNode* node = new XMLNode (X_("BindingSet"));
722         XMLNode* bnode;
723         int ret = 0;
724
725         for (list<Bindings*>::const_iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
726                 bnode = new XMLNode (X_("Bindings"));
727                 bnode->add_property (X_("name"), (*b)->name());
728                 (*b)->save (*bnode);
729                 node->add_child_nocopy (*bnode);
730         }
731
732         XMLTree tree;
733         tree.set_root (node); /* tree now owns root and will delete it */
734
735         if (!tree.write (path)) {
736                 error << string_compose (_("Cannot save key bindings to %1"), path) << endmsg;
737                 ret = -1;
738         }
739         
740         return ret;
741 }
742
743 int
744 Keyboard::reset_bindings ()
745 {
746         if (Glib::file_test (user_keybindings_path,  Glib::FILE_TEST_EXISTS)) {
747
748                 string new_path = user_keybindings_path;
749                 new_path += ".old";
750
751                 if (::g_rename (user_keybindings_path.c_str(), new_path.c_str())) {
752                         error << string_compose (_("Cannot rename your own keybinding file (%1)"), strerror (errno)) << endmsg;
753                         return -1;
754                 }
755         }
756
757         {
758                 PBD::Unwinder<bool> uw (can_save_keybindings, false);
759                 setup_keybindings ();
760                 Bindings::associate_all ();
761         }
762
763         return 0;
764 }