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