split apart ardour_ui.cc into a series of distinct source modules.
[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
44 using namespace ARDOUR;
45 using namespace PBD;
46 using namespace Gtkmm2ext;
47 using namespace ArdourWidgets;
48 using namespace Gtk;
49 using namespace std;
50
51 bool
52 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
53 {
54         Gtkmm2ext::Bindings* bindings = 0;
55         Gtk::Window* window = 0;
56
57         /* until we get ardour bindings working, we are not handling key
58          * releases yet.
59          */
60
61         if (ev->type != GDK_KEY_PRESS) {
62                 return false;
63         }
64
65         if (event_window == &_main_window) {
66
67                 window = event_window;
68
69                 /* find current tab contents */
70
71                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
72
73                 /* see if it uses the ardour binding system */
74
75                 if (w) {
76                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
77                 }
78
79                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
80
81         } else {
82
83                 window = event_window;
84
85                 /* see if window uses ardour binding system */
86
87                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
88         }
89
90         /* An empty binding set is treated as if it doesn't exist */
91
92         if (bindings && bindings->empty()) {
93                 bindings = 0;
94         }
95
96         return key_press_focus_accelerator_handler (*window, ev, bindings);
97 }
98
99 static Gtkmm2ext::Bindings*
100 get_bindings_from_widget_heirarchy (GtkWidget** w)
101 {
102         void* p = NULL;
103
104         while (*w) {
105                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
106                         break;
107                 }
108                 *w = gtk_widget_get_parent (*w);
109         }
110
111         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
112 }
113
114 bool
115 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
116 {
117         GtkWindow* win = window.gobj();
118         GtkWidget* focus = gtk_window_get_focus (win);
119         GtkWidget* binding_widget = focus;
120         bool special_handling_of_unmodified_accelerators = false;
121         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
122
123         if (focus) {
124
125                 /* some widget has keyboard focus */
126
127                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
128
129                         /* A particular kind of focusable widget currently has keyboard
130                          * focus. All unmodified key events should go to that widget
131                          * first and not be used as an accelerator by default
132                          */
133
134                         special_handling_of_unmodified_accelerators = true;
135
136                 } else {
137
138                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
139                         if (focus_bindings) {
140                                 bindings = focus_bindings;
141                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
142                         }
143                 }
144         }
145
146         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",
147                                                           win,
148                                                           ev->keyval,
149                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
150                                                           special_handling_of_unmodified_accelerators,
151                                                           Keyboard::some_magic_widget_has_focus(),
152                                                           focus,
153                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
154                                                           ((ev->state & mask) ? "yes" : "no"),
155                                                           window.get_title()));
156
157         /* This exists to allow us to override the way GTK handles
158            key events. The normal sequence is:
159
160            a) event is delivered to a GtkWindow
161            b) accelerators/mnemonics are activated
162            c) if (b) didn't handle the event, propagate to
163                the focus widget and/or focus chain
164
165            The problem with this is that if the accelerators include
166            keys without modifiers, such as the space bar or the
167            letter "e", then pressing the key while typing into
168            a text entry widget results in the accelerator being
169            activated, instead of the desired letter appearing
170            in the text entry.
171
172            There is no good way of fixing this, but this
173            represents a compromise. The idea is that
174            key events involving modifiers (not Shift)
175            get routed into the activation pathway first, then
176            get propagated to the focus widget if necessary.
177
178            If the key event doesn't involve modifiers,
179            we deliver to the focus widget first, thus allowing
180            it to get "normal text" without interference
181            from acceleration.
182
183            Of course, this can also be problematic: if there
184            is a widget with focus, then it will swallow
185            all "normal text" accelerators.
186         */
187
188
189         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
190
191                 /* no special handling or there are modifiers in effect: accelerate first */
192
193                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
194                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
195                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
196
197                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
198                 KeyboardKey k (ev->state, ev->keyval);
199
200                 while (bindings) {
201
202                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
203
204                         if (bindings->activate (k, Bindings::Press)) {
205                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
206                                 return true;
207                         }
208
209                         if (binding_widget) {
210                                 binding_widget = gtk_widget_get_parent (binding_widget);
211                                 if (binding_widget) {
212                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
213                                 } else {
214                                         bindings = 0;
215                                 }
216                         } else {
217                                 bindings = 0;
218                         }
219                 }
220
221                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
222
223                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
224                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
225                         return true;
226                 }
227
228                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
229
230                 if (gtk_window_propagate_key_event (win, ev)) {
231                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
232                         return true;
233                 }
234
235         } else {
236
237                 /* no modifiers, propagate first */
238
239                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
240
241                 if (gtk_window_propagate_key_event (win, ev)) {
242                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
243                         return true;
244                 }
245
246                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
247                 KeyboardKey k (ev->state, ev->keyval);
248
249                 while (bindings) {
250
251                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
252
253
254                         if (bindings->activate (k, Bindings::Press)) {
255                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
256                                 return true;
257                         }
258
259                         if (binding_widget) {
260                                 binding_widget = gtk_widget_get_parent (binding_widget);
261                                 if (binding_widget) {
262                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
263                                 } else {
264                                         bindings = 0;
265                                 }
266                         } else {
267                                 bindings = 0;
268                         }
269                 }
270
271                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
272
273                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
274                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
275                         return true;
276                 }
277         }
278
279         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
280         return true;
281 }
282
283
284 gint
285 ARDOUR_UI::transport_numpad_timeout ()
286 {
287         _numpad_locate_happening = false;
288         if (_numpad_timeout_connection.connected() )
289                 _numpad_timeout_connection.disconnect();
290         return 1;
291 }
292
293 void
294 ARDOUR_UI::transport_numpad_decimal ()
295 {
296         _numpad_timeout_connection.disconnect();
297
298         if (_numpad_locate_happening) {
299                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
300                 _numpad_locate_happening = false;
301         } else {
302                 _pending_locate_num = 0;
303                 _numpad_locate_happening = true;
304                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
305         }
306 }
307
308 void
309 ARDOUR_UI::transport_numpad_event (int num)
310 {
311         if ( _numpad_locate_happening ) {
312                 _pending_locate_num = _pending_locate_num*10 + num;
313         } else {
314                 switch (num) {
315                         case 0: toggle_roll(false, false);                           break;
316                         case 1: transport_rewind(1);                                 break;
317                         case 2: transport_forward(1);                                break;
318                         case 3: transport_record(true);                              break;
319                         case 4: toggle_session_auto_loop();                          break;
320                         case 5: transport_record(false); toggle_session_auto_loop(); break;
321                         case 6: toggle_punch();                                      break;
322                         case 7: toggle_click();                                      break;
323                         case 8: toggle_auto_return();                                break;
324                         case 9: toggle_follow_edits();                               break;
325                 }
326         }
327 }