Prepare session-metadata export to external command
[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 guint Keyboard::PrimaryModifier = 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|GDK_SUPER_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 sigc::signal0<void> Keyboard::RelevantModifierKeysChanged;
131
132 void
133 Keyboard::magic_widget_grab_focus ()
134 {
135         _some_magic_widget_has_focus = true;
136 }
137
138 void
139 Keyboard::magic_widget_drop_focus ()
140 {
141         _some_magic_widget_has_focus = false;
142 }
143
144 bool
145 Keyboard::some_magic_widget_has_focus ()
146 {
147         return _some_magic_widget_has_focus;
148 }
149
150 Keyboard::Keyboard ()
151 {
152         if (_the_keyboard == 0) {
153                 _the_keyboard = this;
154                 _current_binding_name = _("Unknown");
155         }
156
157         reset_relevant_modifier_key_mask();
158
159         snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
160 }
161
162 Keyboard::~Keyboard ()
163 {
164         gtk_key_snooper_remove (snooper_id);
165 }
166
167 XMLNode&
168 Keyboard::get_state (void)
169 {
170         XMLNode* node = new XMLNode ("Keyboard");
171
172         node->set_property ("copy-modifier", CopyModifier);
173         node->set_property ("edit-button", edit_but);
174         node->set_property ("edit-modifier", edit_mod);
175         node->set_property ("delete-button", delete_but);
176         node->set_property ("delete-modifier", delete_mod);
177         node->set_property ("snap-modifier", snap_mod);
178         node->set_property ("snap-delta-modifier", snap_delta_mod);
179         node->set_property ("insert-note-button", insert_note_but);
180         node->set_property ("insert-note-modifier", insert_note_mod);
181
182         return *node;
183 }
184
185 int
186 Keyboard::set_state (const XMLNode& node, int /*version*/)
187 {
188         node.get_property ("copy-modifier", CopyModifier);
189         node.get_property ("edit-button", edit_but);
190         node.get_property ("edit-modifier", edit_mod);
191         node.get_property ("delete-button", delete_but);
192         node.get_property ("delete-modifier", delete_mod);
193         node.get_property ("snap-modifier", snap_mod);
194         node.get_property ("snap-delta-modifier", snap_delta_mod);
195         node.get_property ("insert-note-button", insert_note_but);
196         node.get_property ("insert-note-modifier", insert_note_mod);
197
198         return 0;
199 }
200
201 gint
202 Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
203 {
204         return ((Keyboard *) data)->snooper (widget, event);
205 }
206
207
208 gint
209 Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
210 {
211         uint32_t keyval;
212         bool ret = false;
213
214         DEBUG_TRACE (
215                 DEBUG::Keyboard,
216                 string_compose (
217                         "Snoop widget %1 name: [%6] key %2 [%8] type %3 state %4 [%7] magic %5\n",
218                         widget, event->keyval, event->type, event->state, _some_magic_widget_has_focus,
219                         gtk_widget_get_name (widget), show_gdk_event_state (event->state), gdk_keyval_name (event->keyval)
220                         )
221                 );
222
223         if (event->keyval == GDK_Shift_R) {
224                 keyval = GDK_Shift_L;
225
226         } else if (event->keyval == GDK_Control_R) {
227                 keyval = GDK_Control_L;
228
229         } else {
230                 keyval = event->keyval;
231         }
232
233         if (event->state & ScrollZoomVerticalModifier) {
234                 /* There is a special and rather hacky situation in Editor which makes
235                    it useful to know when the modifier key for vertical zoom has been
236                    released, so emit a signal here (see Editor::_stepping_axis_view).
237                    Note that the state bit for the modifier key is set for the key-up
238                    event when the modifier is released, but not the key-down when it
239                    is pressed, so we get here on key-up, which is what we want.
240                 */
241                 ZoomVerticalModifierReleased (); /* EMIT SIGNAL */
242         }
243
244         if (event->type == GDK_KEY_PRESS) {
245
246                 if (find (state.begin(), state.end(), keyval) == state.end()) {
247                         state.push_back (keyval);
248                         sort (state.begin(), state.end());
249
250                 } else {
251
252                         /* key is already down. if its also used for release,
253                            prevent auto-repeat events.
254                         */
255
256 #if 0
257                         /* August 2015: we don't have any release bindings
258                          */
259
260                         for (map<AccelKey,two_strings,AccelKeyLess>::iterator k = release_keys.begin(); k != release_keys.end(); ++k) {
261
262                                 const AccelKey& ak (k->first);
263
264                                 if (keyval == ak.get_key() && (Gdk::ModifierType)((event->state & Keyboard::RelevantModifierKeyMask) | Gdk::RELEASE_MASK) == ak.get_mod()) {
265                                         DEBUG_TRACE (DEBUG::Keyboard, "Suppress auto repeat\n");
266                                         ret = true;
267                                         break;
268                                 }
269                         }
270 #endif
271                 }
272         }
273
274         if (event->type == GDK_KEY_RELEASE) {
275
276                 State::iterator k = find (state.begin(), state.end(), keyval);
277
278                 if (k != state.end()) {
279                         /* this cannot change the ordering, so need to sort */
280                         state.erase (k);
281                         if (state.empty()) {
282                                 DEBUG_TRACE (DEBUG::Keyboard, "no keys down\n");
283                         } else {
284 #ifndef NDEBUG
285                                 if (DEBUG_ENABLED(DEBUG::Keyboard)) {
286                                         DEBUG_STR_DECL(a);
287                                         DEBUG_STR_APPEND(a, "keyboard, keys still down: ");
288                                         for (State::iterator i = state.begin(); i != state.end(); ++i) {
289                                                 DEBUG_STR_APPEND(a, gdk_keyval_name (*i));
290                                                 DEBUG_STR_APPEND(a, ',');
291                                         }
292                                         DEBUG_STR_APPEND(a, '\n');
293                                         DEBUG_TRACE (DEBUG::Keyboard, DEBUG_STR(a).str());
294                                 }
295 #endif /* NDEBUG */
296                         }
297                 }
298
299                 if (modifier_state_equals (event->state, PrimaryModifier)) {
300
301                         /* Special keys that we want to handle in
302                            any dialog, no matter whether it uses
303                            the regular set of accelerators or not
304                         */
305
306                         switch (event->keyval) {
307                         case GDK_w:
308                                 close_current_dialog ();
309                                 ret = true;
310                                 break;
311                         }
312                 }
313         }
314
315         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("snooper returns %1\n", ret));
316
317         return ret;
318 }
319
320 void
321 Keyboard::reset_relevant_modifier_key_mask ()
322 {
323         RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask ();
324
325         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | PrimaryModifier);
326         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | SecondaryModifier);
327         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | TertiaryModifier);
328         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | Level4Modifier);
329         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | CopyModifier);
330         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | RangeSelectModifier);
331
332         gtk_accelerator_set_default_mod_mask (RelevantModifierKeyMask);
333
334         RelevantModifierKeysChanged(); /* EMIT SIGNAL */
335 }
336
337 void
338 Keyboard::close_current_dialog ()
339 {
340         if (current_window) {
341                 current_window->hide ();
342                 current_window = 0;
343
344                 if (pre_dialog_active_window) {
345                         pre_dialog_active_window->present ();
346                         pre_dialog_active_window = 0;
347                 }
348         }
349 }
350
351 bool
352 Keyboard::catch_user_event_for_pre_dialog_focus (GdkEvent* ev, Gtk::Window* w)
353 {
354         switch (ev->type) {
355         case GDK_BUTTON_PRESS:
356         case GDK_BUTTON_RELEASE:
357         case GDK_KEY_PRESS:
358         case GDK_KEY_RELEASE:
359                 pre_dialog_active_window = w;
360                 break;
361
362         case GDK_FOCUS_CHANGE:
363                 if (ev->focus_change.in) {
364                         pre_dialog_active_window = w;
365                 }
366                 break;
367
368         default:
369                 break;
370         }
371         return false;
372 }
373
374 bool
375 Keyboard::key_is_down (uint32_t keyval)
376 {
377         return find (state.begin(), state.end(), keyval) != state.end();
378 }
379
380 bool
381 Keyboard::enter_window (GdkEventCrossing *, Gtk::Window* win)
382 {
383         current_window = win;
384         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Entering window, title = %1\n", win->get_title()));
385         return false;
386 }
387
388 bool
389 Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* /*win*/)
390 {
391         if (ev) {
392                 switch (ev->detail) {
393                 case GDK_NOTIFY_INFERIOR:
394                         DEBUG_TRACE (DEBUG::Keyboard, "INFERIOR crossing ... out\n");
395                         break;
396
397                 case GDK_NOTIFY_VIRTUAL:
398                         DEBUG_TRACE (DEBUG::Keyboard, "VIRTUAL crossing ... out\n");
399                         /* fallthru */
400
401                 default:
402                         DEBUG_TRACE (DEBUG::Keyboard, "REAL crossing ... out\n");
403                         DEBUG_TRACE (DEBUG::Keyboard, "Clearing current target\n");
404                         state.clear ();
405                         current_window = 0;
406                 }
407         } else {
408                 DEBUG_TRACE (DEBUG::Keyboard, "LEAVE window without event\n");
409                 current_window = 0;
410         }
411
412         return false;
413 }
414
415 bool
416 Keyboard::focus_in_window (GdkEventFocus *, Gtk::Window* win)
417 {
418         current_window = win;
419         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Focusing in window, title = %1\n", win->get_title()));
420         return false;
421 }
422
423 bool
424 Keyboard::focus_out_window (GdkEventFocus * ev, Gtk::Window* win)
425 {
426         if (ev) {
427                 state.clear ();
428                 current_window = 0;
429         }  else {
430                 if (win == current_window) {
431                         current_window = 0;
432                 }
433         }
434
435         DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Foucusing out window, title = %1\n", win->get_title()));
436
437         return false;
438 }
439
440 void
441 Keyboard::set_edit_button (guint but)
442 {
443         edit_but = but;
444 }
445
446 void
447 Keyboard::set_edit_modifier (guint mod)
448 {
449         edit_mod = mod;
450         reset_relevant_modifier_key_mask();
451 }
452
453 void
454 Keyboard::set_delete_button (guint but)
455 {
456         delete_but = but;
457 }
458
459 void
460 Keyboard::set_delete_modifier (guint mod)
461 {
462         delete_mod = mod;
463         reset_relevant_modifier_key_mask();
464 }
465
466 void
467 Keyboard::set_insert_note_button (guint but)
468 {
469         insert_note_but = but;
470 }
471
472 void
473 Keyboard::set_insert_note_modifier (guint mod)
474 {
475         insert_note_mod = mod;
476         reset_relevant_modifier_key_mask();
477 }
478
479
480 void
481 Keyboard::set_modifier (uint32_t newval, uint32_t& var)
482 {
483         var = newval;
484         reset_relevant_modifier_key_mask();
485 }
486
487 void
488 Keyboard::set_snap_modifier (guint mod)
489 {
490         snap_mod = mod;
491         reset_relevant_modifier_key_mask();
492 }
493
494 void
495 Keyboard::set_snap_delta_modifier (guint mod)
496 {
497         snap_delta_mod = mod;
498         reset_relevant_modifier_key_mask();
499 }
500
501 bool
502 Keyboard::is_edit_event (GdkEventButton *ev)
503 {
504         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
505                 (ev->button == Keyboard::edit_button()) &&
506                 ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
507 }
508
509 bool
510 Keyboard::is_insert_note_event (GdkEventButton *ev)
511 {
512         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
513                 (ev->button == Keyboard::insert_note_button()) &&
514                 ((ev->state & RelevantModifierKeyMask) == Keyboard::insert_note_modifier());
515 }
516
517 bool
518 Keyboard::is_button2_event (GdkEventButton* ev)
519 {
520 #ifdef __APPLE__
521         return (ev->button == 2) ||
522                 ((ev->button == 1) &&
523                  ((ev->state & Keyboard::button2_modifiers) == Keyboard::button2_modifiers));
524 #else
525         return ev->button == 2;
526 #endif
527 }
528
529 bool
530 Keyboard::is_delete_event (GdkEventButton *ev)
531 {
532         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
533                 (ev->button == Keyboard::delete_button()) &&
534                 ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier());
535 }
536
537 bool
538 Keyboard::is_context_menu_event (GdkEventButton *ev)
539 {
540         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
541                 (ev->button == 3) &&
542                 ((ev->state & RelevantModifierKeyMask) == 0);
543 }
544
545 bool
546 Keyboard::no_modifiers_active (guint state)
547 {
548         return (state & RelevantModifierKeyMask) == 0;
549 }
550
551 bool
552 Keyboard::modifier_state_contains (guint state, ModifierMask mask)
553 {
554         return (state & mask) == (guint) mask;
555 }
556
557 bool
558 Keyboard::modifier_state_equals (guint state, ModifierMask mask)
559 {
560         return (state & RelevantModifierKeyMask) == (guint) mask;
561 }
562
563 void
564 Keyboard::keybindings_changed ()
565 {
566         if (Keyboard::can_save_keybindings) {
567                 Keyboard::bindings_changed_after_save_became_legal = true;
568         }
569
570         Keyboard::save_keybindings ();
571 }
572
573 void
574 Keyboard::set_can_save_keybindings (bool yn)
575 {
576         can_save_keybindings = yn;
577 }
578
579 void
580 Keyboard::save_keybindings ()
581 {
582         if (can_save_keybindings && bindings_changed_after_save_became_legal) {
583                 /* Call to specific implementation to save bindings to path */
584                 store_keybindings (user_keybindings_path);
585         }
586 }
587
588 bool
589 Keyboard::load_keybindings (string const & path)
590 {
591         try {
592                 info << "Loading bindings from " << path << endl;
593
594                 /* Call to specific implementation to load bindings from path */
595                 read_keybindings (path);
596
597                 _current_binding_name = _("Unknown");
598
599                 for (map<string,string>::iterator x = binding_files.begin(); x != binding_files.end(); ++x) {
600                         if (path == x->second) {
601                                 _current_binding_name = x->first;
602                                 break;
603                         }
604                 }
605
606
607         } catch (...) {
608                 error << string_compose (_("key bindings file not found at \"%2\" or contains errors."), path)
609                       << endmsg;
610                 return false;
611         }
612
613         return true;
614 }
615
616 int
617 Keyboard::read_keybindings (string const & path)
618 {
619         XMLTree tree;
620
621         if (!tree.read (path.c_str())) {
622                 return -1;
623         }
624
625         /* toplevel node is "BindingSet; children are "Bindings" */
626
627         XMLNodeList const& children = tree.root()->children();
628
629         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
630                 XMLNode const * child = *i;
631                 if (child->name() == X_("Bindings")) {
632                         XMLProperty const* name = child->property (X_("name"));
633                         if (!name) {
634                                 warning << _("Keyboard binding found without a name") << endmsg;
635                                 continue;
636                         }
637
638                         Bindings* b = new Bindings (name->value());
639                         b->load (**i);
640                 }
641         }
642
643         return 0;
644 }
645
646 int
647 Keyboard::store_keybindings (string const & path)
648 {
649         XMLNode* node = new XMLNode (X_("BindingSet"));
650         XMLNode* bnode;
651         int ret = 0;
652
653         for (list<Bindings*>::const_iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
654                 bnode = new XMLNode (X_("Bindings"));
655                 bnode->set_property (X_("name"), (*b)->name());
656                 (*b)->save (*bnode);
657                 node->add_child_nocopy (*bnode);
658         }
659
660         XMLTree tree;
661         tree.set_root (node); /* tree now owns root and will delete it */
662
663         if (!tree.write (path)) {
664                 error << string_compose (_("Cannot save key bindings to %1"), path) << endmsg;
665                 ret = -1;
666         }
667
668         return ret;
669 }
670
671 int
672 Keyboard::reset_bindings ()
673 {
674         if (Glib::file_test (user_keybindings_path,  Glib::FILE_TEST_EXISTS)) {
675
676                 string new_path = user_keybindings_path;
677                 new_path += ".old";
678
679                 if (::g_rename (user_keybindings_path.c_str(), new_path.c_str())) {
680                         error << string_compose (_("Cannot rename your own keybinding file (%1)"), strerror (errno)) << endmsg;
681                         return -1;
682                 }
683         }
684
685         {
686                 PBD::Unwinder<bool> uw (can_save_keybindings, false);
687                 Bindings::reset_bindings ();
688                 setup_keybindings ();
689                 Bindings::associate_all ();
690         }
691
692         return 0;
693 }