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>
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.
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.
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.
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
39 #include "ardour_ui.h"
42 #include "public_editor.h"
44 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace ArdourWidgets;
52 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
54 Gtkmm2ext::Bindings* bindings = 0;
55 Gtk::Window* window = 0;
57 /* until we get ardour bindings working, we are not handling key
61 if (ev->type != GDK_KEY_PRESS) {
65 if (event_window == &_main_window) {
67 window = event_window;
69 /* find current tab contents */
71 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
73 /* see if it uses the ardour binding system */
76 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
79 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
83 window = event_window;
85 /* see if window uses ardour binding system */
87 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
90 /* An empty binding set is treated as if it doesn't exist */
92 if (bindings && bindings->empty()) {
96 return key_press_focus_accelerator_handler (*window, ev, bindings);
99 static Gtkmm2ext::Bindings*
100 get_bindings_from_widget_heirarchy (GtkWidget** w)
105 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
108 *w = gtk_widget_get_parent (*w);
111 return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
115 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
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));
125 /* some widget has keyboard focus */
127 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
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
134 special_handling_of_unmodified_accelerators = true;
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()));
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",
149 Gtkmm2ext::show_gdk_event_state (ev->state),
150 special_handling_of_unmodified_accelerators,
151 Keyboard::some_magic_widget_has_focus(),
153 (focus ? gtk_widget_get_name (focus) : "no focus widget"),
154 ((ev->state & mask) ? "yes" : "no"),
155 window.get_title()));
157 /* This exists to allow us to override the way GTK handles
158 key events. The normal sequence is:
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
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
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.
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
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.
189 if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
191 /* no special handling or there are modifiers in effect: accelerate first */
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)));
197 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
198 KeyboardKey k (ev->state, ev->keyval);
202 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
204 if (bindings->activate (k, Bindings::Press)) {
205 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
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);
221 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
223 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
224 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
228 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
230 if (gtk_window_propagate_key_event (win, ev)) {
231 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
237 /* no modifiers, propagate first */
239 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
241 if (gtk_window_propagate_key_event (win, ev)) {
242 DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
246 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
247 KeyboardKey k (ev->state, ev->keyval);
251 DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
254 if (bindings->activate (k, Bindings::Press)) {
255 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
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);
271 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
273 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
274 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
279 DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
285 ARDOUR_UI::transport_numpad_timeout ()
287 _numpad_locate_happening = false;
288 if (_numpad_timeout_connection.connected() )
289 _numpad_timeout_connection.disconnect();
294 ARDOUR_UI::transport_numpad_decimal ()
296 _numpad_timeout_connection.disconnect();
298 if (_numpad_locate_happening) {
299 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
300 _numpad_locate_happening = false;
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);
309 ARDOUR_UI::transport_numpad_event (int num)
311 if ( _numpad_locate_happening ) {
312 _pending_locate_num = _pending_locate_num*10 + 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;