Fix DSP load sorting with inactive plugins
[ardour.git] / gtk2_ardour / ardour_ui_keys.cc
1 /*
2  * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
3  * Copyright (C) 2005-2017 Tim Mayberry <mojofunk@gmail.com>
4  * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
6  * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
7  * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
8  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
9  * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
10  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
11  * Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
12  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
13  * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
14  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
15  * Copyright (C) 2015 AndrĂ© Nusser <andre.nusser@googlemail.com>
16  * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
17  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along
30  * with this program; if not, write to the Free Software Foundation, Inc.,
31  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32  */
33
34 #ifdef WAF_BUILD
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
37 #endif
38
39 #include "ardour_ui.h"
40 #include "debug.h"
41 #include "keyboard.h"
42 #include "public_editor.h"
43 #include "virtual_keyboard_window.h"
44
45 using namespace ARDOUR;
46 using namespace PBD;
47 using namespace Gtkmm2ext;
48 using namespace ArdourWidgets;
49 using namespace Gtk;
50 using namespace std;
51
52 bool
53 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
54 {
55         Gtkmm2ext::Bindings* bindings = 0;
56         Gtk::Window* window = 0;
57
58         if (virtual_keyboard_window && virtual_keyboard_window->is_visible()) {
59                 if (gtk_window_propagate_key_event (virtual_keyboard_window->gobj(), ev)) {
60                         return true;
61                 }
62         }
63
64         /* until we get ardour bindings working, we are not handling key
65          * releases yet.
66          */
67
68         if (ev->type != GDK_KEY_PRESS) {
69                 return false;
70         }
71
72         if (event_window == &_main_window) {
73
74                 window = event_window;
75
76                 /* find current tab contents */
77
78                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
79
80                 /* see if it uses the ardour binding system */
81
82                 if (w) {
83                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
84                 }
85
86                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
87
88         } else {
89
90                 window = event_window;
91
92                 /* see if window uses ardour binding system */
93
94                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
95         }
96
97         /* An empty binding set is treated as if it doesn't exist */
98
99         if (bindings && bindings->empty()) {
100                 bindings = 0;
101         }
102
103         return key_press_focus_accelerator_handler (*window, ev, bindings);
104 }
105
106 static Gtkmm2ext::Bindings*
107 get_bindings_from_widget_heirarchy (GtkWidget** w)
108 {
109         void* p = NULL;
110
111         while (*w) {
112                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
113                         break;
114                 }
115                 *w = gtk_widget_get_parent (*w);
116         }
117
118         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
119 }
120
121 bool
122 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
123 {
124         GtkWindow* win = window.gobj();
125         GtkWidget* focus = gtk_window_get_focus (win);
126         GtkWidget* binding_widget = focus;
127         bool special_handling_of_unmodified_accelerators = false;
128         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
129
130         if (focus) {
131
132                 /* some widget has keyboard focus */
133
134                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
135
136                         /* A particular kind of focusable widget currently has keyboard
137                          * focus. All unmodified key events should go to that widget
138                          * first and not be used as an accelerator by default
139                          */
140
141                         special_handling_of_unmodified_accelerators = true;
142
143                 } else {
144
145                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
146                         if (focus_bindings) {
147                                 bindings = focus_bindings;
148                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
149                         }
150                 }
151         }
152
153         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
154                                                           win,
155                                                           ev->keyval,
156                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
157                                                           special_handling_of_unmodified_accelerators,
158                                                           Keyboard::some_magic_widget_has_focus(),
159                                                           focus,
160                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
161                                                           ((ev->state & mask) ? "yes" : "no"),
162                                                           window.get_title()));
163
164         /* This exists to allow us to override the way GTK handles
165            key events. The normal sequence is:
166
167            a) event is delivered to a GtkWindow
168            b) accelerators/mnemonics are activated
169            c) if (b) didn't handle the event, propagate to
170                the focus widget and/or focus chain
171
172            The problem with this is that if the accelerators include
173            keys without modifiers, such as the space bar or the
174            letter "e", then pressing the key while typing into
175            a text entry widget results in the accelerator being
176            activated, instead of the desired letter appearing
177            in the text entry.
178
179            There is no good way of fixing this, but this
180            represents a compromise. The idea is that
181            key events involving modifiers (not Shift)
182            get routed into the activation pathway first, then
183            get propagated to the focus widget if necessary.
184
185            If the key event doesn't involve modifiers,
186            we deliver to the focus widget first, thus allowing
187            it to get "normal text" without interference
188            from acceleration.
189
190            Of course, this can also be problematic: if there
191            is a widget with focus, then it will swallow
192            all "normal text" accelerators.
193         */
194
195
196         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
197
198                 /* no special handling or there are modifiers in effect: accelerate first */
199
200                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
201                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
202                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
203
204                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
205                 KeyboardKey k (ev->state, ev->keyval);
206
207                 while (bindings) {
208
209                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
210
211                         if (bindings->activate (k, Bindings::Press)) {
212                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
213                                 return true;
214                         }
215
216                         if (binding_widget) {
217                                 binding_widget = gtk_widget_get_parent (binding_widget);
218                                 if (binding_widget) {
219                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
220                                 } else {
221                                         bindings = 0;
222                                 }
223                         } else {
224                                 bindings = 0;
225                         }
226                 }
227
228                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
229
230                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
231                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
232                         return true;
233                 }
234
235                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
236
237                 if (gtk_window_propagate_key_event (win, ev)) {
238                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
239                         return true;
240                 }
241
242         } else {
243
244                 /* no modifiers, propagate first */
245
246                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
247
248                 if (gtk_window_propagate_key_event (win, ev)) {
249                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
250                         return true;
251                 }
252
253                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
254                 KeyboardKey k (ev->state, ev->keyval);
255
256                 while (bindings) {
257
258                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
259
260
261                         if (bindings->activate (k, Bindings::Press)) {
262                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
263                                 return true;
264                         }
265
266                         if (binding_widget) {
267                                 binding_widget = gtk_widget_get_parent (binding_widget);
268                                 if (binding_widget) {
269                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
270                                 } else {
271                                         bindings = 0;
272                                 }
273                         } else {
274                                 bindings = 0;
275                         }
276                 }
277
278                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
279
280                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
281                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
282                         return true;
283                 }
284         }
285
286         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
287         return true;
288 }
289
290
291 gint
292 ARDOUR_UI::transport_numpad_timeout ()
293 {
294         _numpad_locate_happening = false;
295         if (_numpad_timeout_connection.connected() )
296                 _numpad_timeout_connection.disconnect();
297         return 1;
298 }
299
300 void
301 ARDOUR_UI::transport_numpad_decimal ()
302 {
303         _numpad_timeout_connection.disconnect();
304
305         if (_numpad_locate_happening) {
306                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
307                 _numpad_locate_happening = false;
308         } else {
309                 _pending_locate_num = 0;
310                 _numpad_locate_happening = true;
311                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
312         }
313 }
314
315 void
316 ARDOUR_UI::transport_numpad_event (int num)
317 {
318         if ( _numpad_locate_happening ) {
319                 _pending_locate_num = _pending_locate_num*10 + num;
320         } else {
321                 switch (num) {
322                         case 0: toggle_roll(false, false);                           break;
323                         case 1: transport_rewind(1);                                 break;
324                         case 2: transport_forward(1);                                break;
325                         case 3: transport_record(true);                              break;
326                         case 4: toggle_session_auto_loop();                          break;
327                         case 5: transport_record(false); toggle_session_auto_loop(); break;
328                         case 6: toggle_punch();                                      break;
329                         case 7: toggle_click();                                      break;
330                         case 8: toggle_auto_return();                                break;
331                         case 9: toggle_follow_edits();                               break;
332                 }
333         }
334 }