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"
43 #include "virtual_keyboard_window.h"
45 using namespace ARDOUR;
47 using namespace Gtkmm2ext;
48 using namespace ArdourWidgets;
53 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
55 Gtkmm2ext::Bindings* bindings = 0;
56 Gtk::Window* window = 0;
58 if (virtual_keyboard_window && virtual_keyboard_window->is_visible()) {
59 if (gtk_window_propagate_key_event (virtual_keyboard_window->gobj(), ev)) {
64 /* until we get ardour bindings working, we are not handling key
68 if (ev->type != GDK_KEY_PRESS) {
72 if (event_window == &_main_window) {
74 window = event_window;
76 /* find current tab contents */
78 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
80 /* see if it uses the ardour binding system */
83 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
86 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
90 window = event_window;
92 /* see if window uses ardour binding system */
94 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
97 /* An empty binding set is treated as if it doesn't exist */
99 if (bindings && bindings->empty()) {
103 return key_press_focus_accelerator_handler (*window, ev, bindings);
106 static Gtkmm2ext::Bindings*
107 get_bindings_from_widget_heirarchy (GtkWidget** w)
112 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
115 *w = gtk_widget_get_parent (*w);
118 return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
122 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
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));
132 /* some widget has keyboard focus */
134 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
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
141 special_handling_of_unmodified_accelerators = true;
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()));
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",
156 Gtkmm2ext::show_gdk_event_state (ev->state),
157 special_handling_of_unmodified_accelerators,
158 Keyboard::some_magic_widget_has_focus(),
160 (focus ? gtk_widget_get_name (focus) : "no focus widget"),
161 ((ev->state & mask) ? "yes" : "no"),
162 window.get_title()));
164 /* This exists to allow us to override the way GTK handles
165 key events. The normal sequence is:
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
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
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.
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
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.
196 if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
198 /* no special handling or there are modifiers in effect: accelerate first */
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)));
204 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
205 KeyboardKey k (ev->state, ev->keyval);
209 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
211 if (bindings->activate (k, Bindings::Press)) {
212 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
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);
228 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
230 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
231 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
235 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
237 if (gtk_window_propagate_key_event (win, ev)) {
238 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
244 /* no modifiers, propagate first */
246 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
248 if (gtk_window_propagate_key_event (win, ev)) {
249 DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
253 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
254 KeyboardKey k (ev->state, ev->keyval);
258 DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
261 if (bindings->activate (k, Bindings::Press)) {
262 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
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);
278 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
280 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
281 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
286 DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
292 ARDOUR_UI::transport_numpad_timeout ()
294 _numpad_locate_happening = false;
295 if (_numpad_timeout_connection.connected() )
296 _numpad_timeout_connection.disconnect();
301 ARDOUR_UI::transport_numpad_decimal ()
303 _numpad_timeout_connection.disconnect();
305 if (_numpad_locate_happening) {
306 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
307 _numpad_locate_happening = false;
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);
316 ARDOUR_UI::transport_numpad_event (int num)
318 if ( _numpad_locate_happening ) {
319 _pending_locate_num = _pending_locate_num*10 + 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;