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 "gui_thread.h"
39 bool debug_keyboard = false;
41 guint Keyboard::edit_but = 3;
42 guint Keyboard::edit_mod = GDK_CONTROL_MASK;
43 guint Keyboard::delete_but = 3;
44 guint Keyboard::delete_mod = GDK_SHIFT_MASK;
45 guint Keyboard::snap_mod = GDK_MOD3_MASK;
47 uint32_t Keyboard::Control = GDK_CONTROL_MASK;
48 uint32_t Keyboard::Shift = GDK_SHIFT_MASK;
49 uint32_t Keyboard::Alt = GDK_MOD1_MASK;
50 uint32_t Keyboard::Meta = GDK_MOD2_MASK;
52 Keyboard* Keyboard::_the_keyboard = 0;
54 /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
56 GdkModifierType Keyboard::RelevantModifierKeyMask =
57 GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD3_MASK);
62 if (_the_keyboard == 0) {
66 collecting_prefix = false;
68 get_modifier_masks ();
70 snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
72 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
76 Keyboard::~Keyboard ()
78 gtk_key_snooper_remove (snooper_id);
79 delete [] modifier_masks;
83 Keyboard::get_state (void)
85 XMLNode* node = new XMLNode ("Keyboard");
88 snprintf (buf, sizeof (buf), "%d", edit_but);
89 node->add_property ("edit-button", buf);
90 snprintf (buf, sizeof (buf), "%d", edit_mod);
91 node->add_property ("edit-modifier", buf);
92 snprintf (buf, sizeof (buf), "%d", delete_but);
93 node->add_property ("delete-button", buf);
94 snprintf (buf, sizeof (buf), "%d", delete_mod);
95 node->add_property ("delete-modifier", buf);
96 snprintf (buf, sizeof (buf), "%d", snap_mod);
97 node->add_property ("snap-modifier", buf);
103 Keyboard::set_state (const XMLNode& node)
105 const XMLProperty* prop;
107 if ((prop = node.property ("edit-button")) != 0) {
108 sscanf (prop->value().c_str(), "%d", &edit_but);
111 if ((prop = node.property ("edit-modifier")) != 0) {
112 sscanf (prop->value().c_str(), "%d", &edit_mod);
115 if ((prop = node.property ("delete-button")) != 0) {
116 sscanf (prop->value().c_str(), "%d", &delete_but);
119 if ((prop = node.property ("delete-modifier")) != 0) {
120 sscanf (prop->value().c_str(), "%d", &delete_mod);
123 if ((prop = node.property ("snap-modifier")) != 0) {
124 sscanf (prop->value().c_str(), "%d", &snap_mod);
131 Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
133 return ((Keyboard *) data)->snooper (widget, event);
137 Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
142 if (debug_keyboard) {
143 cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type
148 if (event->keyval == GDK_Shift_R) {
149 keyval = GDK_Shift_L;
151 } else if (event->keyval == GDK_Control_R) {
152 keyval = GDK_Control_L;
155 keyval = event->keyval;
158 if (event->type == GDK_KEY_PRESS) {
159 bool was_prefix = false;
161 if (collecting_prefix) {
164 current_prefix += '0';
168 current_prefix += '1';
172 current_prefix += '2';
176 current_prefix += '3';
180 current_prefix += '4';
184 current_prefix += '5';
188 current_prefix += '6';
192 current_prefix += '7';
196 current_prefix += '8';
200 current_prefix += '9';
204 current_prefix += '.';
209 collecting_prefix = false;
214 if (find (state.begin(), state.end(), keyval) == state.end()) {
215 state.push_back (keyval);
216 sort (state.begin(), state.end());
219 } else if (event->type == GDK_KEY_RELEASE) {
223 if ((i = find (state.begin(), state.end(), keyval)) != state.end()) {
225 sort (state.begin(), state.end());
234 Keyboard::key_is_down (uint32_t keyval)
236 return find (state.begin(), state.end(), keyval) != state.end();
240 Keyboard::translate_key_name (const string& name)
244 string::size_type len;
246 string::size_type hyphen;
248 string whatevers_left;
258 whatevers_left = name.substr (i);
260 if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) {
262 /* no hyphen, so use the whole thing */
264 keyname = whatevers_left;
269 /* There is a hyphen. */
271 if (hyphen == 0 && whatevers_left.length() == 1) {
272 /* its the first and only character */
279 /* use the text before the hypen */
281 keyname = whatevers_left.substr (0, hyphen);
283 if (hyphen == len - 1) {
292 if (keyname.length() == 1 && isupper (keyname[0])) {
293 result.push_back (GDK_Shift_L);
296 if ((keycode = gdk_keyval_from_name(get_real_keyname (keyname).c_str())) == GDK_VoidSymbol) {
297 error << string_compose(_("KeyboardTarget: keyname \"%1\" is unknown."), keyname) << endmsg;
302 result.push_back (keycode);
305 sort (result.begin(), result.end());
311 Keyboard::get_real_keyname (const string& name)
314 if (name == "Control" || name == "Ctrl") {
317 if (name == "Meta" || name == "MetaL") {
320 if (name == "MetaR") {
323 if (name == "Alt" || name == "AltL") {
326 if (name == "AltR") {
329 if (name == "Shift") {
332 if (name == "Shift_R") {
408 return "bracketleft";
414 return "bracketright";
417 return "asciicircum";
445 Keyboard::get_prefix (float& val, bool& was_floating)
447 if (current_prefix.length()) {
448 if (current_prefix.find ('.') != string::npos) {
451 was_floating = false;
453 if (sscanf (current_prefix.c_str(), "%f", &val) == 1) {
462 Keyboard::start_prefix ()
464 collecting_prefix = true;
469 Keyboard::clear_modifier_state ()
475 Keyboard::check_modifier_state ()
480 clear_modifier_state ();
481 XQueryKeymap (GDK_DISPLAY(), keys);
483 for (i = 0; i < 32; ++i) {
484 for (j = 0; j < 8; ++j) {
486 if (keys[i] & (1<<j)) {
487 modifier_mask |= modifier_masks[(i*8)+j];
494 Keyboard::check_meta_numlock (char keycode, guint mod, string modname)
496 guint alternate_meta_mod;
497 string alternate_meta_modname;
501 guint keysym = XKeycodeToKeysym (GDK_DISPLAY(), keycode, 0);
503 if (keysym == GDK_Num_Lock) {
507 alternate_meta_mod = GDK_MOD3_MASK;
508 alternate_meta_modname = "Mod3";
511 alternate_meta_mod = GDK_MOD2_MASK;
512 alternate_meta_modname = "Mod2";
515 alternate_meta_mod = GDK_MOD2_MASK;
516 alternate_meta_modname = "Mod2";
519 alternate_meta_mod = GDK_MOD2_MASK;
520 alternate_meta_modname = "Mod2";
523 error << string_compose (_("Your system is completely broken - NumLock uses \"%1\""
524 "as its modifier. This is madness - see the man page "
525 "for xmodmap to find out how to fix this."),
531 warning << string_compose (_("Your system generates \"%1\" when the NumLock key "
532 "is pressed. This can cause problems when editing "
533 "so Ardour will use %2 to mean Meta rather than %1"),
534 modname, alternate_meta_modname)
537 set_meta_modifier (alternate_meta_mod);
543 Keyboard::get_modifier_masks ()
545 XModifierKeymap *modifiers;
550 XDisplayKeycodes (GDK_DISPLAY(), &min_keycode, &max_keycode);
552 /* This function builds a lookup table to provide rapid answers to
553 the question: what, if any, modmask, is associated with a given
557 modifiers = XGetModifierMapping (GDK_DISPLAY());
559 modifier_masks = new int32_t [max_keycode+1];
561 keycode = modifiers->modifiermap;
563 for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */
565 modifier_masks[*keycode] = GDK_SHIFT_MASK;
566 // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
571 for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */
573 for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */
575 modifier_masks[*keycode] = GDK_CONTROL_MASK;
576 // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
582 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */
584 modifier_masks[*keycode] = GDK_MOD1_MASK;
585 // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
590 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
592 warning << string_compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg;
596 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */
598 modifier_masks[*keycode] = GDK_MOD2_MASK;
599 check_meta_numlock (*keycode, GDK_MOD2_MASK, "Mod2");
600 //cerr << "Mod2 = " << std::hex << (int) *keycode << std::dec << " = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
605 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
607 warning << string_compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg;
611 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */
613 modifier_masks[*keycode] = GDK_MOD3_MASK;
614 check_meta_numlock (*keycode, GDK_MOD3_MASK, "Mod3");
615 // cerr << "Mod3 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
620 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
622 warning << string_compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg;
626 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */
628 modifier_masks[*keycode] = GDK_MOD4_MASK;
629 check_meta_numlock (*keycode, GDK_MOD4_MASK, "Mod4");
630 // cerr << "Mod4 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
635 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
637 warning << string_compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg;
641 for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */
643 modifier_masks[*keycode] = GDK_MOD5_MASK;
644 check_meta_numlock (*keycode, GDK_MOD5_MASK, "Mod5");
645 // cerr << "Mod5 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
650 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
652 warning << string_compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg;
656 XFreeModifiermap (modifiers);
660 Keyboard::enter_window (GdkEventCrossing *ev)
662 switch (ev->detail) {
663 case GDK_NOTIFY_INFERIOR:
666 case GDK_NOTIFY_VIRTUAL:
670 check_modifier_state ();
677 Keyboard::leave_window (GdkEventCrossing *ev)
679 switch (ev->detail) {
680 case GDK_NOTIFY_INFERIOR:
681 if (debug_keyboard) {
682 cerr << "INFERIOR crossing ... out\n";
686 case GDK_NOTIFY_VIRTUAL:
687 if (debug_keyboard) {
688 cerr << "VIRTUAL crossing ... out\n";
693 if (debug_keyboard) {
694 cerr << "REAL CROSSING ... out\n";
695 cerr << "clearing current target\n";
698 clear_modifier_state ();
705 Keyboard::set_edit_button (guint but)
711 Keyboard::set_edit_modifier (guint mod)
713 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod);
715 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod);
719 Keyboard::set_delete_button (guint but)
725 Keyboard::set_delete_modifier (guint mod)
727 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod);
729 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod);
733 Keyboard::set_meta_modifier (guint mod)
735 /* we don't include Meta in the RelevantModifierKeyMask because its not used
736 in the same way as snap_mod, delete_mod etc. the only reason we allow it to be
737 set at all is that X Window has no convention for the keyboard modifier
738 that Meta should use. Some Linux distributions bind NumLock to Mod2, which
739 is our default Meta modifier, and this causes severe problems.
745 Keyboard::set_snap_modifier (guint mod)
747 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod);
749 RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
753 Keyboard::is_edit_event (GdkEventButton *ev)
755 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
756 (ev->button == Keyboard::edit_button()) &&
757 ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
761 Keyboard::is_delete_event (GdkEventButton *ev)
763 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
764 (ev->button == Keyboard::delete_button()) &&
765 ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier());
769 Keyboard::is_context_menu_event (GdkEventButton *ev)
771 return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
773 ((ev->state & RelevantModifierKeyMask) == 0);
777 Keyboard::no_modifiers_active (guint state)
779 return (state & RelevantModifierKeyMask) == 0;
783 Keyboard::modifier_state_contains (guint state, ModifierMask mask)
785 return (state & mask) == (guint) mask;
789 Keyboard::modifier_state_equals (guint state, ModifierMask mask)
791 return (state & RelevantModifierKeyMask) == (guint) mask;