2 Copyright (C) 2001 Paul Davis
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.
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.
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.
21 #include "ardour_ui.h"
28 #include <X11/keysymdef.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <pbd/error.h>
34 #include "keyboard_target.h"
35 #include "ardour_dialog.h"
36 #include "gui_thread.h"
41 bool debug_keyboard = false;
43 guint Keyboard::edit_but = 3;
44 guint Keyboard::edit_mod = GDK_CONTROL_MASK;
45 guint Keyboard::delete_but = 3;
46 guint Keyboard::delete_mod = GDK_SHIFT_MASK;
47 guint Keyboard::snap_mod = GDK_MOD3_MASK;
49 uint32_t Keyboard::Control = GDK_CONTROL_MASK;
50 uint32_t Keyboard::Shift = GDK_SHIFT_MASK;
51 uint32_t Keyboard::Alt = GDK_MOD1_MASK;
52 uint32_t Keyboard::Meta = GDK_MOD2_MASK;
54 Keyboard* Keyboard::_the_keyboard = 0;
56 /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
58 GdkModifierType Keyboard::RelevantModifierKeyMask =
59 GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD3_MASK);
64 if (_the_keyboard == 0) {
70 _queue_events = false;
72 playback_ignore_count = 0;
73 focus_allowed = false;
74 collecting_prefix = false;
77 get_modifier_masks ();
79 snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
81 /* some global key actions */
83 KeyboardTarget::add_action ("close-dialog", mem_fun(*this, &Keyboard::close_current_dialog));
85 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
89 Keyboard::~Keyboard ()
91 gtk_key_snooper_remove (snooper_id);
92 delete [] modifier_masks;
96 Keyboard::get_state (void)
98 XMLNode* node = new XMLNode ("Keyboard");
101 snprintf (buf, sizeof (buf), "%d", edit_but);
102 node->add_property ("edit-button", buf);
103 snprintf (buf, sizeof (buf), "%d", edit_mod);
104 node->add_property ("edit-modifier", buf);
105 snprintf (buf, sizeof (buf), "%d", delete_but);
106 node->add_property ("delete-button", buf);
107 snprintf (buf, sizeof (buf), "%d", delete_mod);
108 node->add_property ("delete-modifier", buf);
109 snprintf (buf, sizeof (buf), "%d", snap_mod);
110 node->add_property ("snap-modifier", buf);
116 Keyboard::set_state (const XMLNode& node)
118 const XMLProperty* prop;
120 if ((prop = node.property ("edit-button")) != 0) {
121 sscanf (prop->value().c_str(), "%d", &edit_but);
124 if ((prop = node.property ("edit-modifier")) != 0) {
125 sscanf (prop->value().c_str(), "%d", &edit_mod);
128 if ((prop = node.property ("delete-button")) != 0) {
129 sscanf (prop->value().c_str(), "%d", &delete_but);
132 if ((prop = node.property ("delete-modifier")) != 0) {
133 sscanf (prop->value().c_str(), "%d", &delete_mod);
136 if ((prop = node.property ("snap-modifier")) != 0) {
137 sscanf (prop->value().c_str(), "%d", &snap_mod);
144 Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
146 return ((Keyboard *) data)->snooper (widget, event);
150 Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
152 bool handled = false;
156 if (debug_keyboard) {
157 cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type
158 << " focus allowed? " << focus_allowed << " current dialog = " << current_dialog
163 /* Only allow key events to propagate to the
164 usual GTK model when specifically allowed.
165 Returning FALSE here does that.
172 if (event->keyval == GDK_Shift_R) {
173 keyval = GDK_Shift_L;
175 } else if (event->keyval == GDK_Control_R) {
176 keyval = GDK_Control_L;
179 keyval = event->keyval;
183 if (event->type == GDK_KEY_PRESS) {
184 bool was_prefix = false;
186 if (collecting_prefix) {
189 current_prefix += '0';
193 current_prefix += '1';
197 current_prefix += '2';
201 current_prefix += '3';
205 current_prefix += '4';
209 current_prefix += '5';
213 current_prefix += '6';
217 current_prefix += '7';
221 current_prefix += '8';
225 current_prefix += '9';
229 current_prefix += '.';
234 collecting_prefix = false;
239 if (find (state.begin(), state.end(), keyval) == state.end()) {
240 state.push_back (keyval);
241 sort (state.begin(), state.end());
245 if (debug_keyboard) {
247 for (State::iterator i = state.begin(); i != state.end(); ++i) {
256 bool old_collecting_prefix = collecting_prefix;
260 if (debug_keyboard) {
261 cerr << "PRESS: delivering to target " << target << endl;
264 target->key_press_event (event, state, handled);
267 if (!handled && default_target) {
269 if (debug_keyboard) {
270 cerr << "PRESS: not handled, delivering to default target " << default_target << endl;
273 default_target->key_press_event (event, state, handled);
277 if (debug_keyboard) {
278 cerr << "PRESS: handled ? " << handled << endl;
284 /* don't reset collecting prefix is start_prefix()
285 was called by the handler.
288 if (collecting_prefix == old_collecting_prefix) {
289 collecting_prefix = false;
295 } else if (event->type == GDK_KEY_RELEASE) {
299 if ((i = find (state.begin(), state.end(), keyval)) != state.end()) {
301 sort (state.begin(), state.end());
306 if (debug_keyboard) {
307 cerr << "RELEASE: delivering to target " << target << endl;
310 target->key_release_event (event, state);
313 if (default_target) {
315 if (debug_keyboard) {
316 cerr << "RELEASE: delivering to default target " << default_target << endl;
319 default_target->key_release_event (event, state);
327 Keyboard::key_is_down (uint32_t keyval)
329 return find (state.begin(), state.end(), keyval) != state.end();
333 Keyboard::set_target (KeyboardTarget *kt)
335 /* XXX possible thread issues here */
340 Keyboard::maybe_unset_target (KeyboardTarget* kt)
348 Keyboard::set_default_target (KeyboardTarget *kt)
350 /* XXX possible thread issues here */
356 Keyboard::allow_focus (bool yn)
362 Keyboard::translate_key_name (const string& name)
366 string::size_type len;
368 string::size_type hyphen;
370 string whatevers_left;
380 whatevers_left = name.substr (i);
382 if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) {
384 /* no hyphen, so use the whole thing */
386 keyname = whatevers_left;
391 /* There is a hyphen. */
393 if (hyphen == 0 && whatevers_left.length() == 1) {
394 /* its the first and only character */
401 /* use the text before the hypen */
403 keyname = whatevers_left.substr (0, hyphen);
405 if (hyphen == len - 1) {
414 if (keyname.length() == 1 && isupper (keyname[0])) {
415 result.push_back (GDK_Shift_L);
418 if ((keycode = gdk_keyval_from_name(get_real_keyname (keyname).c_str())) == GDK_VoidSymbol) {
419 error << string_compose(_("KeyboardTarget: keyname \"%1\" is unknown."), keyname) << endmsg;
424 result.push_back (keycode);
427 sort (result.begin(), result.end());
433 Keyboard::get_real_keyname (const string& name)
436 if (name == "Control" || name == "Ctrl") {
439 if (name == "Meta" || name == "MetaL") {
442 if (name == "MetaR") {
445 if (name == "Alt" || name == "AltL") {
448 if (name == "AltR") {
451 if (name == "Shift") {
454 if (name == "Shift_R") {
530 return "bracketleft";
536 return "bracketright";
539 return "asciicircum";
567 Keyboard::get_prefix (float& val, bool& was_floating)
569 if (current_prefix.length()) {
570 if (current_prefix.find ('.') != string::npos) {
573 was_floating = false;
575 if (sscanf (current_prefix.c_str(), "%f", &val) == 1) {
584 Keyboard::start_prefix ()
586 collecting_prefix = true;
591 Keyboard::clear_modifier_state ()
597 Keyboard::check_modifier_state ()
602 clear_modifier_state ();
603 XQueryKeymap (GDK_DISPLAY(), keys);
605 for (i = 0; i < 32; ++i) {
606 for (j = 0; j < 8; ++j) {
608 if (keys[i] & (1<<j)) {
609 modifier_mask |= modifier_masks[(i*8)+j];
616 Keyboard::check_meta_numlock (char keycode, guint mod, string modname)
618 guint alternate_meta_mod;
619 string alternate_meta_modname;
623 guint keysym = XKeycodeToKeysym (GDK_DISPLAY(), keycode, 0);
625 if (keysym == GDK_Num_Lock) {
629 alternate_meta_mod = GDK_MOD3_MASK;
630 alternate_meta_modname = "Mod3";
633 alternate_meta_mod = GDK_MOD2_MASK;
634 alternate_meta_modname = "Mod2";
637 alternate_meta_mod = GDK_MOD2_MASK;
638 alternate_meta_modname = "Mod2";
641 alternate_meta_mod = GDK_MOD2_MASK;
642 alternate_meta_modname = "Mod2";
645 error << string_compose (_("Your system is completely broken - NumLock uses \"%1\""
646 "as its modifier. This is madness - see the man page "
647 "for xmodmap to find out how to fix this."),
653 warning << string_compose (_("Your system generates \"%1\" when the NumLock key "
654 "is pressed. This can cause problems when editing "
655 "so Ardour will use %2 to mean Meta rather than %1"),
656 modname, alternate_meta_modname)
659 set_meta_modifier (alternate_meta_mod);
665 Keyboard::get_modifier_masks ()
667 XModifierKeymap *modifiers;
672 XDisplayKeycodes (GDK_DISPLAY(), &min_keycode, &max_keycode);
674 /* This function builds a lookup table to provide rapid answers to
675 the question: what, if any, modmask, is associated with a given
679 modifiers = XGetModifierMapping (GDK_DISPLAY());
681 modifier_masks = new int32_t [max_keycode+1];
683 keycode = modifiers->modifiermap;
685 for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */
687 modifier_masks[*keycode] = GDK_SHIFT_MASK;
688 // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
693 for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */
695 for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */
697 modifier_masks[*keycode] = GDK_CONTROL_MASK;
698 // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
704 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */
706 modifier_masks[*keycode] = GDK_MOD1_MASK;
707 // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
712 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
714 warning << string_compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg;
718 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */
720 modifier_masks[*keycode] = GDK_MOD2_MASK;
721 check_meta_numlock (*keycode, GDK_MOD2_MASK, "Mod2");
722 //cerr << "Mod2 = " << std::hex << (int) *keycode << std::dec << " = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
727 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
729 warning << string_compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg;
733 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */
735 modifier_masks[*keycode] = GDK_MOD3_MASK;
736 check_meta_numlock (*keycode, GDK_MOD3_MASK, "Mod3");
737 // cerr << "Mod3 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
742 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
744 warning << string_compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg;
748 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */
750 modifier_masks[*keycode] = GDK_MOD4_MASK;
751 check_meta_numlock (*keycode, GDK_MOD4_MASK, "Mod4");
752 // cerr << "Mod4 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
757 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
759 warning << string_compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg;
763 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */
765 modifier_masks[*keycode] = GDK_MOD5_MASK;
766 check_meta_numlock (*keycode, GDK_MOD5_MASK, "Mod5");
767 // cerr << "Mod5 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
772 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
774 warning << string_compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg;
778 XFreeModifiermap (modifiers);
782 Keyboard::enter_window (GdkEventCrossing *ev, KeyboardTarget *kt)
784 switch (ev->detail) {
785 case GDK_NOTIFY_INFERIOR:
786 if (debug_keyboard) {
787 cerr << "INFERIOR crossing to " << kt->name() << endl;
791 case GDK_NOTIFY_VIRTUAL:
792 if (debug_keyboard) {
793 cerr << "VIRTUAL crossing to " << kt->name() << endl;
798 if (debug_keyboard) {
799 cerr << "REAL crossing to " << kt->name() << endl;
800 cerr << "set current target to " << kt->name() << endl;
804 check_modifier_state ();
811 Keyboard::leave_window (GdkEventCrossing *ev)
813 switch (ev->detail) {
814 case GDK_NOTIFY_INFERIOR:
815 if (debug_keyboard) {
816 cerr << "INFERIOR crossing ... out\n";
820 case GDK_NOTIFY_VIRTUAL:
821 if (debug_keyboard) {
822 cerr << "VIRTUAL crossing ... out\n";
827 if (debug_keyboard) {
828 cerr << "REAL CROSSING ... out\n";
829 cerr << "clearing current target\n";
834 clear_modifier_state ();
841 Keyboard::register_target (KeyboardTarget *kt)
843 /* do not register the default - its not meant to be
844 an actual window, just a fallback if the current
845 target for keyboard events doesn't handle an event.
848 if (kt->name() == X_("default")) {
852 kt->window().signal_enter_notify_event().connect (bind (mem_fun(*this, &Keyboard::enter_window), kt));
853 kt->window().signal_leave_notify_event().connect (mem_fun(*this, &Keyboard::leave_window));
855 kt->GoingAway.connect (bind (mem_fun(*this, &Keyboard::maybe_unset_target), kt));
856 kt->Hiding.connect (bind (mem_fun(*this, &Keyboard::maybe_unset_target), kt));
860 Keyboard::set_current_dialog (ArdourDialog* dialog)
862 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Keyboard::set_current_dialog), dialog));
864 current_dialog = dialog;
866 if (current_dialog) {
868 if (find (known_dialogs.begin(), known_dialogs.end(), dialog) == known_dialogs.end()) {
870 current_dialog->GoingAway.connect
871 (bind (mem_fun(*this, &Keyboard::set_current_dialog),
872 reinterpret_cast<ArdourDialog *>(0)));
873 current_dialog->Hiding.connect
874 (bind (mem_fun(*this, &Keyboard::set_current_dialog),
875 reinterpret_cast<ArdourDialog *>(0)));
877 current_dialog->signal_unmap_event().connect (mem_fun(*this, &Keyboard::current_dialog_vanished));
879 known_dialogs.push_back (dialog);
885 Keyboard::current_dialog_vanished (GdkEventAny *ev)
889 focus_allowed = false;
890 clear_modifier_state ();
897 Keyboard::close_current_dialog ()
899 if (current_dialog) {
900 current_dialog->hide ();
905 Keyboard::set_edit_button (guint but)
911 Keyboard::set_edit_modifier (guint mod)
913 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod);
915 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod);
919 Keyboard::set_delete_button (guint but)
925 Keyboard::set_delete_modifier (guint mod)
927 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod);
929 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod);
933 Keyboard::set_meta_modifier (guint mod)
935 /* we don't include Meta in the RelevantModifierKeyMask because its not used
936 in the same way as snap_mod, delete_mod etc. the only reason we allow it to be
937 set at all is that X Window has no convention for the keyboard modifier
938 that Meta should use. Some Linux distributions bind NumLock to Mod2, which
939 is our default Meta modifier, and this causes severe problems.
945 Keyboard::set_snap_modifier (guint mod)
947 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod);
949 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
953 Keyboard::is_edit_event (GdkEventButton *ev)
955 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
956 (ev->button == Keyboard::edit_button()) &&
957 ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
961 Keyboard::is_delete_event (GdkEventButton *ev)
963 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
964 (ev->button == Keyboard::delete_button()) &&
965 ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier());
969 Keyboard::is_context_menu_event (GdkEventButton *ev)
971 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
973 ((ev->state & RelevantModifierKeyMask) == 0);
977 Keyboard::no_modifiers_active (guint state)
979 return (state & RelevantModifierKeyMask) == 0;
983 Keyboard::modifier_state_contains (guint state, ModifierMask mask)
985 return (state & mask) == (guint) mask;
989 Keyboard::modifier_state_equals (guint state, ModifierMask mask)
991 return (state & RelevantModifierKeyMask) == (guint) mask;
995 Keyboard::focus_in_handler (GdkEventFocus* ev)
1002 Keyboard::focus_out_handler (GdkEventFocus* ev)
1004 allow_focus (false);