fix compose mess, and a number of 64 bit printf specs
[ardour.git] / gtk2_ardour / 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     $Id$
19 */
20
21 #include "ardour_ui.h"
22
23 #include <algorithm>
24 #include <fstream>
25
26 #include <ctype.h>
27
28 #include <X11/keysymdef.h>
29 #include <gdk/gdkx.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <pbd/error.h>
32
33 #include "keyboard.h"
34 #include "keyboard_target.h"
35 #include "ardour_dialog.h"
36 #include "gui_thread.h"
37
38 #include "i18n.h"
39
40 #define KBD_DEBUG 1
41 bool debug_keyboard = false;
42
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;
48
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;
53
54 Keyboard* Keyboard::_the_keyboard = 0;
55
56 /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
57
58 GdkModifierType Keyboard::RelevantModifierKeyMask = 
59                                GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD3_MASK);
60
61
62 Keyboard::Keyboard ()
63 {
64         if (_the_keyboard == 0) {
65                 _the_keyboard = this;
66         }
67
68         target = 0;
69         default_target = 0;
70         _queue_events = false;
71         _flush_queue = false;
72         playback_ignore_count = 0;
73         focus_allowed = false;
74         collecting_prefix = false;
75         current_dialog = 0;
76
77         get_modifier_masks ();
78
79         snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
80
81         /* some global key actions */
82
83         KeyboardTarget::add_action ("close-dialog", mem_fun(*this, &Keyboard::close_current_dialog));
84
85         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
86         set_state (*node);
87 }
88
89 Keyboard::~Keyboard ()
90 {
91         gtk_key_snooper_remove (snooper_id);
92         delete [] modifier_masks;
93 }
94
95 XMLNode& 
96 Keyboard::get_state (void)
97 {
98         XMLNode* node = new XMLNode ("Keyboard");
99         char buf[32];
100
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);
111
112         return *node;
113 }
114
115 int 
116 Keyboard::set_state (const XMLNode& node)
117 {
118         const XMLProperty* prop;
119
120         if ((prop = node.property ("edit-button")) != 0) {
121                 sscanf (prop->value().c_str(), "%d", &edit_but);
122         } 
123
124         if ((prop = node.property ("edit-modifier")) != 0) {
125                 sscanf (prop->value().c_str(), "%d", &edit_mod);
126         } 
127
128         if ((prop = node.property ("delete-button")) != 0) {
129                 sscanf (prop->value().c_str(), "%d", &delete_but);
130         } 
131
132         if ((prop = node.property ("delete-modifier")) != 0) {
133                 sscanf (prop->value().c_str(), "%d", &delete_mod);
134         } 
135
136         if ((prop = node.property ("snap-modifier")) != 0) {
137                 sscanf (prop->value().c_str(), "%d", &snap_mod);
138         } 
139
140         return 0;
141 }
142
143 gint
144 Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
145 {
146         return ((Keyboard *) data)->snooper (widget, event);
147 }
148
149 gint
150 Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
151 {
152         bool handled = false;
153         uint32_t keyval;
154
155 #if KBD_DEBUG
156         if (debug_keyboard) {
157                 cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type 
158                      << " focus allowed? " << focus_allowed << " current dialog = " << current_dialog
159                      << endl;
160         }
161 #endif
162
163         /* Only allow key events to propagate to the
164            usual GTK model when specifically allowed. 
165            Returning FALSE here does that.
166         */
167
168         if (focus_allowed) {
169                 return FALSE;
170         }
171         
172         if (event->keyval == GDK_Shift_R) {
173                 keyval = GDK_Shift_L;
174
175         } else  if (event->keyval == GDK_Control_R) {
176                 keyval = GDK_Control_L;
177
178         } else {
179                 keyval = event->keyval;
180         }
181         
182                 
183         if (event->type == GDK_KEY_PRESS) {
184                 bool was_prefix = false;
185
186                 if (collecting_prefix) {
187                         switch (keyval) {
188                         case GDK_0:
189                                 current_prefix += '0';
190                                 was_prefix = true;
191                                 break;
192                         case GDK_1:
193                                 current_prefix += '1';
194                                 was_prefix = true;
195                                 break;
196                         case GDK_2:
197                                 current_prefix += '2';
198                                 was_prefix = true;
199                                 break;
200                         case GDK_3:
201                                 current_prefix += '3';
202                                 was_prefix = true;
203                                 break;
204                         case GDK_4:
205                                 current_prefix += '4';
206                                 was_prefix = true;
207                                 break;
208                         case GDK_5:
209                                 current_prefix += '5';
210                                 was_prefix = true;
211                                 break;
212                         case GDK_6:
213                                 current_prefix += '6';
214                                 was_prefix = true;
215                                 break;
216                         case GDK_7:
217                                 current_prefix += '7';
218                                 was_prefix = true;
219                                 break;
220                         case GDK_8:
221                                 current_prefix += '8';
222                                 was_prefix = true;
223                                 break;
224                         case GDK_9:
225                                 current_prefix += '9';
226                                 was_prefix = true;
227                                 break;
228                         case GDK_period:
229                                 current_prefix += '.';
230                                 was_prefix = true;
231                                 break;
232                         default:
233                                 was_prefix = false;
234                                 collecting_prefix = false;
235                                 break;
236                         }
237                 }
238
239                 if (find (state.begin(), state.end(), keyval) == state.end()) {
240                         state.push_back (keyval);
241                         sort (state.begin(), state.end());
242                 }
243
244 #if KBD_DEBUG
245                 if (debug_keyboard) {
246                         cerr << "STATE: ";
247                         for (State::iterator i = state.begin(); i != state.end(); ++i) {
248                                 cerr << (*i) << ' ';
249                         }
250                         cerr << endl;
251                 }
252 #endif
253
254                 if (!was_prefix) {
255
256                         bool old_collecting_prefix = collecting_prefix;
257
258                         if (target) {
259 #if KBD_DEBUG
260                                 if (debug_keyboard) {
261                                         cerr << "PRESS: delivering to target " << target << endl;
262                                 }
263 #endif
264                                 target->key_press_event (event, state, handled);
265                         }
266                         
267                         if (!handled && default_target) {
268 #if KBD_DEBUG
269                                 if (debug_keyboard) {
270                                         cerr << "PRESS: not handled, delivering to default target " << default_target << endl;
271                                 }
272 #endif
273                                 default_target->key_press_event (event, state, handled);
274                         }
275
276 #if KBD_DEBUG
277                         if (debug_keyboard) {
278                                 cerr << "PRESS: handled ? " << handled << endl;
279                         }
280 #endif
281
282                         if (handled) {
283                                 
284                                 /* don't reset collecting prefix is start_prefix()
285                                    was called by the handler.
286                                 */
287                                 
288                                 if (collecting_prefix == old_collecting_prefix) {
289                                         collecting_prefix = false;
290                                         current_prefix = "";
291                                 }
292                         }
293                 }
294
295         } else if (event->type == GDK_KEY_RELEASE) {
296
297                 State::iterator i;
298                 
299                 if ((i = find (state.begin(), state.end(), keyval)) != state.end()) {
300                         state.erase (i);
301                         sort (state.begin(), state.end());
302                 } 
303
304                 if (target) {
305 #if KBD_DEBUG
306                         if (debug_keyboard) {
307                                 cerr << "RELEASE: delivering to target " << target << endl;
308                         }
309 #endif
310                         target->key_release_event (event, state);
311                 } 
312
313                 if (default_target) {
314 #if KBD_DEBUG
315                         if (debug_keyboard) {
316                                 cerr << "RELEASE: delivering to default target " << default_target << endl;
317                         }
318 #endif
319                         default_target->key_release_event (event, state);
320                 }
321         }
322
323         return TRUE;
324 }
325
326 bool
327 Keyboard::key_is_down (uint32_t keyval)
328 {
329         return find (state.begin(), state.end(), keyval) != state.end();
330 }
331
332 void
333 Keyboard::set_target (KeyboardTarget *kt)
334 {
335         /* XXX possible thread issues here */
336         target = kt;
337 }
338
339 void
340 Keyboard::maybe_unset_target (KeyboardTarget* kt)
341 {
342         if (target == kt) {
343                 target = 0;
344         }
345 }
346
347 void
348 Keyboard::set_default_target (KeyboardTarget *kt)
349 {
350         /* XXX possible thread issues here */
351
352         default_target = kt;
353 }
354
355 void
356 Keyboard::allow_focus (bool yn)
357 {
358         focus_allowed = yn;
359 }
360
361 Keyboard::State
362 Keyboard::translate_key_name (const string& name)
363
364 {
365         string::size_type i;
366         string::size_type len;
367         bool at_end;
368         string::size_type hyphen;
369         string keyname;
370         string whatevers_left;
371         State result;
372         guint keycode;
373         
374         i = 0;
375         len = name.length();
376         at_end = (len == 0);
377
378         while (!at_end) {
379
380                 whatevers_left = name.substr (i);
381
382                 if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) {
383                         
384                         /* no hyphen, so use the whole thing */
385                         
386                         keyname = whatevers_left;
387                         at_end = true;
388
389                 } else {
390
391                         /* There is a hyphen. */
392                         
393                         if (hyphen == 0 && whatevers_left.length() == 1) {
394                                 /* its the first and only character */
395                         
396                                 keyname = "-";
397                                 at_end = true;
398
399                         } else {
400
401                                 /* use the text before the hypen */
402                                 
403                                 keyname = whatevers_left.substr (0, hyphen);
404                                 
405                                 if (hyphen == len - 1) {
406                                         at_end = true;
407                                 } else {
408                                         i += hyphen + 1;
409                                         at_end = (i >= len);
410                                 }
411                         }
412                 }
413                 
414                 if (keyname.length() == 1 && isupper (keyname[0])) {
415                         result.push_back (GDK_Shift_L);
416                 }
417                 
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;
420                         result.clear();
421                         return result;
422                 }
423                 
424                 result.push_back (keycode);
425         }
426
427         sort (result.begin(), result.end());
428
429         return result;
430 }
431
432 string
433 Keyboard::get_real_keyname (const string& name)
434 {
435
436         if (name == "Control" || name == "Ctrl") {
437                 return "Control_L";
438         } 
439         if (name == "Meta" || name == "MetaL") {
440                 return "Meta_L";
441         } 
442         if (name == "MetaR") {
443                 return "Meta_R";
444         } 
445         if (name == "Alt" || name == "AltL") {
446                 return "Alt_L";
447         } 
448         if (name == "AltR") {
449                 return "Alt_R";
450         } 
451         if (name == "Shift") {
452                 return "Shift_L";
453         }
454         if (name == "Shift_R") {
455                 return "Shift_L";
456         }
457         if (name == " ") {
458                 return "space";
459         }
460         if (name == "!") {
461                 return "exclam";
462         }
463         if (name == "\"") {
464                 return "quotedbl";
465         }
466         if (name == "#") {
467                 return "numbersign";
468         }
469         if (name == "$") {
470                 return "dollar";
471         }
472         if (name == "%") {
473                 return "percent";
474         }
475         if (name == "&") {
476                 return "ampersand";
477         }
478         if (name == "'") {
479                 return "apostrophe";
480         }
481         if (name == "'") {
482                 return "quoteright";
483         }
484         if (name == "(") {
485                 return "parenleft";
486         }
487         if (name == ")") {
488                 return "parenright";
489         }
490         if (name == "*") {
491                 return "asterisk";
492         }
493         if (name == "+") {
494                 return "plus";
495         }
496         if (name == ",") {
497                 return "comma";
498         }
499         if (name == "-") {
500                 return "minus";
501         }
502         if (name == ".") {
503                 return "period";
504         }
505         if (name == "/") {
506                 return "slash";
507         }
508         if (name == ":") {
509                 return "colon";
510         }
511         if (name == ";") {
512                 return "semicolon";
513         }
514         if (name == "<") {
515                 return "less";
516         }
517         if (name == "=") {
518                 return "equal";
519         }
520         if (name == ">") {
521                 return "greater";
522         }
523         if (name == "?") {
524                 return "question";
525         }
526         if (name == "@") {
527                 return "at";
528         }
529         if (name == "[") {
530                 return "bracketleft";
531         }
532         if (name == "\\") {
533                 return "backslash";
534         }
535         if (name == "]") {
536                 return "bracketright";
537         }
538         if (name == "^") {
539                 return "asciicircum";
540         }
541         if (name == "_") {
542                 return "underscore";
543         }
544         if (name == "`") {
545                 return "grave";
546         }
547         if (name == "`") {
548                 return "quoteleft";
549         }
550         if (name == "{") {
551                 return "braceleft";
552         }
553         if (name == "|") {
554                 return "bar";
555         }
556         if (name == "}") {
557                 return "braceright";
558         }
559         if (name == "~") {
560                 return "asciitilde";
561         }
562
563         return name;
564 }
565
566 int
567 Keyboard::get_prefix (float& val, bool& was_floating)
568 {
569         if (current_prefix.length()) {
570                 if (current_prefix.find ('.') != string::npos) {
571                         was_floating = true;
572                 } else {
573                         was_floating = false;
574                 }
575                 if (sscanf (current_prefix.c_str(), "%f", &val) == 1) {
576                         return 0;
577                 }
578                 current_prefix = "";
579         }
580         return -1;
581 }
582
583 void
584 Keyboard::start_prefix ()
585 {
586         collecting_prefix = true;
587         current_prefix = "";
588 }
589
590 void
591 Keyboard::clear_modifier_state ()
592 {
593         modifier_mask = 0;
594 }
595
596 void
597 Keyboard::check_modifier_state ()
598 {
599         char keys[32];
600         int i, j;
601
602         clear_modifier_state ();
603         XQueryKeymap (GDK_DISPLAY(), keys);
604
605         for (i = 0; i < 32; ++i) {
606                 for (j = 0; j < 8; ++j) {
607
608                         if (keys[i] & (1<<j)) {
609                                 modifier_mask |= modifier_masks[(i*8)+j];
610                         }
611                 }
612         }
613 }
614
615 void
616 Keyboard::check_meta_numlock (char keycode, guint mod, string modname)
617 {
618         guint alternate_meta_mod;
619         string alternate_meta_modname;
620
621         if (mod == Meta) {
622                 
623                 guint keysym = XKeycodeToKeysym  (GDK_DISPLAY(), keycode, 0);
624                 
625                 if (keysym == GDK_Num_Lock) {
626
627                         switch (mod) {
628                         case GDK_MOD2_MASK:
629                                 alternate_meta_mod = GDK_MOD3_MASK;
630                                 alternate_meta_modname = "Mod3";
631                                 break;
632                         case GDK_MOD3_MASK:
633                                 alternate_meta_mod = GDK_MOD2_MASK;
634                                 alternate_meta_modname = "Mod2";
635                                 break;
636                         case GDK_MOD4_MASK:
637                                 alternate_meta_mod = GDK_MOD2_MASK;
638                                 alternate_meta_modname = "Mod2";
639                                 break;
640                         case GDK_MOD5_MASK:
641                                 alternate_meta_mod = GDK_MOD2_MASK;
642                                 alternate_meta_modname = "Mod2";
643                                 break;
644                         default:
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."),
648                                                   modname)
649                                       << endmsg;
650                                 return;
651                         }
652
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)
657                                 << endmsg;
658
659                         set_meta_modifier (alternate_meta_mod);
660                 }
661         }
662 }
663
664 void
665 Keyboard::get_modifier_masks ()
666 {
667         XModifierKeymap *modifiers;
668         KeyCode *keycode;
669         int i;
670         int bound;
671
672         XDisplayKeycodes (GDK_DISPLAY(), &min_keycode, &max_keycode);
673
674         /* This function builds a lookup table to provide rapid answers to
675            the question: what, if any, modmask, is associated with a given
676            keycode ?
677         */
678         
679         modifiers = XGetModifierMapping (GDK_DISPLAY());
680         
681         modifier_masks = new int32_t [max_keycode+1];
682         
683         keycode = modifiers->modifiermap;
684
685         for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */
686                 if (*keycode) {
687                         modifier_masks[*keycode] = GDK_SHIFT_MASK;
688                         // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym  (GDK_DISPLAY(), *keycode, 0)) << endl;
689                 }
690                 keycode++;
691         }
692     
693         for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */
694     
695         for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */
696                 if (*keycode) {
697                         modifier_masks[*keycode] = GDK_CONTROL_MASK;
698                         // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym  (GDK_DISPLAY(), *keycode, 0)) << endl;
699                 }
700                 keycode++;
701         }
702
703         bound = 0;
704         for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */
705                 if (*keycode) {
706                         modifier_masks[*keycode] = GDK_MOD1_MASK;
707                         // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym  (GDK_DISPLAY(), *keycode, 0)) << endl;
708                         bound++;
709                 }
710                 keycode++;
711         }
712 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
713         if (bound > 1) {
714                 warning << string_compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg;
715         }
716 #endif
717         bound = 0;
718         for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */
719                 if (*keycode) {
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;
723                         bound++;
724                 }
725                 keycode++; 
726         }
727 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
728         if (bound > 1) {
729                 warning << string_compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg;
730         }
731 #endif
732         bound = 0;
733         for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */
734                 if (*keycode) {
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;
738                         bound++;
739                 }
740                 keycode++; 
741         }
742 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
743         if (bound > 1) {
744                 warning << string_compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg;
745         }
746 #endif
747         bound = 0;
748         for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */
749                 if (*keycode) {
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;
753                         bound++;
754                 }
755                 keycode++;
756         }
757 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
758         if (bound > 1) {
759                 warning << string_compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg;
760         }
761 #endif
762         bound = 0;
763         for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */
764                 if (*keycode) {
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;
768                         bound++;
769                 }
770                 keycode++;
771         }
772 #ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
773         if (bound > 1) {
774                 warning << string_compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg;
775         }
776 #endif
777
778         XFreeModifiermap (modifiers);
779 }
780
781 gint
782 Keyboard::enter_window (GdkEventCrossing *ev, KeyboardTarget *kt)
783 {
784         switch (ev->detail) {
785         case GDK_NOTIFY_INFERIOR:
786                 if (debug_keyboard) {
787                         cerr << "INFERIOR crossing to " << kt->name() << endl;
788                 }
789                 break;
790
791         case GDK_NOTIFY_VIRTUAL:
792                 if (debug_keyboard) {
793                         cerr << "VIRTUAL crossing to " << kt->name() << endl;
794                 }
795                 /* fallthru */
796
797         default:
798                 if (debug_keyboard) {
799                         cerr << "REAL crossing to " << kt->name() << endl;
800                         cerr << "set current target to " << kt->name() << endl;
801                 }
802
803                 set_target (kt);
804                 check_modifier_state ();
805         }
806
807         return FALSE;
808 }
809
810 gint
811 Keyboard::leave_window (GdkEventCrossing *ev)
812 {
813         switch (ev->detail) {
814         case GDK_NOTIFY_INFERIOR:
815                 if (debug_keyboard) {
816                         cerr << "INFERIOR crossing ... out\n";
817                 }
818                 break;
819
820         case GDK_NOTIFY_VIRTUAL:
821                 if (debug_keyboard) {
822                         cerr << "VIRTUAL crossing ... out\n";
823                 }
824                 /* fallthru */
825
826         default:
827                 if (debug_keyboard) {
828                         cerr << "REAL CROSSING ... out\n";
829                         cerr << "clearing current target\n";
830                 }
831
832                 set_target (0);
833                 state.clear ();
834                 clear_modifier_state ();
835         }
836         return FALSE;
837
838 }
839
840 void
841 Keyboard::register_target (KeyboardTarget *kt)
842 {
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.
846         */
847
848         if (kt->name() == X_("default")) {
849                 return;
850         }
851
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));
854
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));
857 }
858
859 void
860 Keyboard::set_current_dialog (ArdourDialog* dialog)
861 {
862         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Keyboard::set_current_dialog), dialog));
863         
864         current_dialog = dialog;
865
866         if (current_dialog) {
867
868                 if (find (known_dialogs.begin(), known_dialogs.end(), dialog) == known_dialogs.end()) {
869                         
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)));
876                         
877                         current_dialog->signal_unmap_event().connect (mem_fun(*this, &Keyboard::current_dialog_vanished));
878                         
879                         known_dialogs.push_back (dialog);
880                 }
881         }
882 }
883
884 gint
885 Keyboard::current_dialog_vanished (GdkEventAny *ev)
886 {
887         current_dialog = 0;
888         state.clear ();
889         focus_allowed = false;
890         clear_modifier_state ();
891         current_prefix = "";
892
893         return FALSE;
894 }
895
896 void
897 Keyboard::close_current_dialog ()
898 {
899         if (current_dialog) {
900                 current_dialog->hide ();
901         }
902 }
903
904 void
905 Keyboard::set_edit_button (guint but)
906 {
907         edit_but = but;
908 }
909
910 void
911 Keyboard::set_edit_modifier (guint mod)
912 {
913         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod);
914         edit_mod = mod;
915         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod);
916 }
917
918 void
919 Keyboard::set_delete_button (guint but)
920 {
921         delete_but = but;
922 }
923
924 void
925 Keyboard::set_delete_modifier (guint mod)
926 {
927         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod);
928         delete_mod = mod;
929         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod);
930 }
931
932 void
933 Keyboard::set_meta_modifier (guint mod)
934 {
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.
940         */
941         Meta = mod;
942 }
943
944 void
945 Keyboard::set_snap_modifier (guint mod)
946 {
947         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod);
948         snap_mod = mod;
949         RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
950 }
951
952 bool
953 Keyboard::is_edit_event (GdkEventButton *ev)
954 {
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());
958 }
959
960 bool
961 Keyboard::is_delete_event (GdkEventButton *ev)
962 {
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());
966 }
967
968 bool
969 Keyboard::is_context_menu_event (GdkEventButton *ev)
970 {
971         return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) && 
972                 (ev->button == 3) && 
973                 ((ev->state & RelevantModifierKeyMask) == 0);
974 }
975
976 bool 
977 Keyboard::no_modifiers_active (guint state)
978 {
979         return (state & RelevantModifierKeyMask) == 0;
980 }
981
982 bool
983 Keyboard::modifier_state_contains (guint state, ModifierMask mask)
984 {
985         return (state & mask) == (guint) mask;
986 }
987
988 bool
989 Keyboard::modifier_state_equals (guint state, ModifierMask mask)
990 {
991         return (state & RelevantModifierKeyMask) == (guint) mask;
992 }
993
994 gint
995 Keyboard::focus_in_handler (GdkEventFocus* ev)
996 {
997         allow_focus (true);
998         return FALSE;
999 }
1000
1001 gint
1002 Keyboard::focus_out_handler (GdkEventFocus* ev)
1003 {
1004         allow_focus (false);
1005         return FALSE;
1006 }