Enable some key release event forwarding
[ardour.git] / gtk2_ardour / ardour_window.cc
1 /*
2  * Copyright (C) 2011-2018 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
4  * Copyright (C) 2015 Nick Mainsbridge <mainsbridge@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <iostream>
22 #include <sigc++/bind.h>
23
24 #include <gtkmm2ext/doi.h>
25
26 #include "ardour_window.h"
27 #include "ardour_ui.h"
28 #include "ui_config.h"
29 #include "keyboard.h"
30 #include "utils.h"
31
32 using namespace std;
33 using namespace Gtk;
34 using namespace Gtkmm2ext;
35 using namespace ARDOUR_UI_UTILS;
36
37 ArdourWindow::ArdourWindow (string title)
38         : Window ()
39         , VisibilityTracker (*((Gtk::Window*)this))
40 {
41         set_title (title);
42         init ();
43         set_position (Gtk::WIN_POS_MOUSE);
44 }
45
46 ArdourWindow::ArdourWindow (Gtk::Window& parent, string title)
47         : Window ()
48         , VisibilityTracker (*((Gtk::Window*)this))
49 {
50         init ();
51         set_title (title);
52         set_transient_for (parent);
53         set_position (Gtk::WIN_POS_CENTER_ON_PARENT);
54 }
55
56 ArdourWindow::~ArdourWindow ()
57 {
58 }
59
60 bool
61 ArdourWindow::on_key_press_event (GdkEventKey* ev)
62 {
63         bool handled = Gtk::Window::on_key_press_event (ev);
64
65         if (!handled) {
66                 if (!get_modal()) {
67                         handled = relay_key_press (ev, this);
68                 }
69         }
70
71         return handled;
72 }
73
74 bool
75 ArdourWindow::on_key_release_event (GdkEventKey* ev)
76 {
77         bool handled = Gtk::Window::on_key_press_event (ev);
78
79         if (!handled) {
80                 if (!get_modal()) {
81                         handled = relay_key_press (ev, this);
82                 }
83         }
84
85         return handled;
86 }
87
88 bool
89 ArdourWindow::on_focus_in_event (GdkEventFocus *ev)
90 {
91         Keyboard::the_keyboard().focus_in_window (ev, this);
92         return Window::on_focus_in_event (ev);
93 }
94
95 bool
96 ArdourWindow::on_focus_out_event (GdkEventFocus *ev)
97 {
98         if (!get_modal()) {
99                 Keyboard::the_keyboard().focus_out_window (ev, this);
100         }
101         return Window::on_focus_out_event (ev);
102 }
103
104 void
105 ArdourWindow::on_unmap ()
106 {
107         Keyboard::the_keyboard().leave_window (0, this);
108         Window::on_unmap ();
109 }
110
111 bool
112 ArdourWindow::on_delete_event (GdkEventAny*)
113 {
114         return false;
115 }
116
117 void
118 ArdourWindow::init ()
119 {
120         set_border_width (10);
121         add_events (Gdk::FOCUS_CHANGE_MASK);
122
123         /* ArdourWindows are not dialogs (they have no "OK" or "Close" button) but
124            they should be considered part of the same "window level" as a dialog. This
125            works on X11 in that:
126
127            (a) there are no window "levels"
128            (b) they will float above normal windows without any particular effort
129            (c) present()-ing them will make a utility float over a dialog or
130                vice versa.
131
132            Some X11 Window managers (e.g. KDE) get this wrong, and so we allow the user
133            to select what type of window hint is used.
134
135            GTK+ on OS X uses different levels for DIALOG and UTILITY, and Cocoa has a bug/design
136            issue that it will not transfer keyboard focus across levels when hiding a window.
137            So on OS X, we use DIALOG for all ArdourWindows to ensure that keyboard focus
138            will return to the main window(s) when this window is hidden.
139         */
140
141 #ifdef __APPLE__
142         set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
143 #else
144         if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
145                 set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
146         } else {
147                 set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
148         }
149 #endif
150
151         Gtk::Window* parent = WM::Manager::instance().transient_parent();
152
153         if (parent) {
154                 set_transient_for (*parent);
155         }
156
157         ARDOUR_UI::CloseAllDialogs.connect (sigc::mem_fun (*this, &ArdourWindow::hide));
158 }
159