Vkeybd: grab all key-events and use timer instead of key-repeat
This fixes an issue with arrow-keys (up/down, left/right). Those were previously only handled when the Virtual Keyboard window itself had focus. Also key-repeat for pitch-bend is now ignored and a dedicated timer is used to queue events. This fixes an issue with the first repeat taking longer than successive ones, and makes this feature independent of any desktop user settings.
This commit is contained in:
parent
2add730263
commit
322e6e08c4
@ -558,12 +558,69 @@ get_keycode (GdkEventKey* event)
|
||||
return gdk_keyval_name (gdk_keyval_to_lower (keyval));
|
||||
}
|
||||
|
||||
bool
|
||||
APianoKeyboard::handle_fixed_keys (GdkEventKey* ev)
|
||||
{
|
||||
if (ev->type == GDK_KEY_PRESS) {
|
||||
switch (ev->keyval) {
|
||||
case GDK_KEY_Left:
|
||||
SwitchOctave (false);
|
||||
return true;
|
||||
case GDK_KEY_Right:
|
||||
SwitchOctave (true);
|
||||
return true;
|
||||
case GDK_KEY_F1:
|
||||
PitchBend (0, false);
|
||||
return true;
|
||||
case GDK_KEY_F2:
|
||||
PitchBend (4096, false);
|
||||
return true;
|
||||
case GDK_KEY_F3:
|
||||
PitchBend (12288, false);
|
||||
return true;
|
||||
case GDK_KEY_F4:
|
||||
PitchBend (16383, false);
|
||||
return true;
|
||||
case GDK_KEY_Down:
|
||||
PitchBend (0, true);
|
||||
return true;
|
||||
case GDK_KEY_Up:
|
||||
PitchBend (16383, true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (ev->type == GDK_KEY_RELEASE) {
|
||||
switch (ev->keyval) {
|
||||
case GDK_KEY_F1:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F2:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F3:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F4:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_Up:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_Down:
|
||||
PitchBend (8192, false);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
APianoKeyboard::on_key_press_event (GdkEventKey* event)
|
||||
{
|
||||
if (Gtkmm2ext::Keyboard::modifier_state_contains (event->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
|
||||
return false;
|
||||
}
|
||||
if (handle_fixed_keys (event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char const* key = get_keycode (event);
|
||||
int note = key_binding (key);
|
||||
@ -603,6 +660,10 @@ APianoKeyboard::on_key_release_event (GdkEventKey* event)
|
||||
if (Gtkmm2ext::Keyboard::modifier_state_contains (event->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
|
||||
return false;
|
||||
}
|
||||
if (handle_fixed_keys (event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char const* key = get_keycode (event);
|
||||
|
||||
if (!key) {
|
||||
|
@ -31,10 +31,12 @@ public:
|
||||
APianoKeyboard ();
|
||||
~APianoKeyboard ();
|
||||
|
||||
sigc::signal<void, int, int> NoteOn;
|
||||
sigc::signal<void, int> NoteOff;
|
||||
sigc::signal<void> Rest;
|
||||
sigc::signal<void,bool> SustainChanged;
|
||||
sigc::signal<void, int, int> NoteOn;
|
||||
sigc::signal<void, int> NoteOff;
|
||||
sigc::signal<void> Rest;
|
||||
sigc::signal<void,bool> SustainChanged;
|
||||
sigc::signal<void, int, bool> PitchBend;
|
||||
sigc::signal<void, bool> SwitchOctave;
|
||||
|
||||
enum Layout {
|
||||
QWERTY,
|
||||
@ -79,6 +81,8 @@ private:
|
||||
|
||||
void queue_note_draw (int note);
|
||||
|
||||
bool handle_fixed_keys (GdkEventKey*);
|
||||
|
||||
void press_key (int key, int vel);
|
||||
void release_key (int key);
|
||||
void stop_sustained_notes ();
|
||||
|
@ -243,6 +243,8 @@ VirtualKeyboardWindow::VirtualKeyboardWindow ()
|
||||
|
||||
_piano.NoteOn.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::note_on_event_handler));
|
||||
_piano.NoteOff.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::note_off_event_handler));
|
||||
_piano.SwitchOctave.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::octave_key_event_handler));
|
||||
_piano.PitchBend.connect (sigc::mem_fun (*this, &VirtualKeyboardWindow::pitch_bend_key_event_handler));
|
||||
|
||||
update_velocity_settings (0);
|
||||
update_octave_range ();
|
||||
@ -379,41 +381,6 @@ VirtualKeyboardWindow::on_key_press_event (GdkEventKey* ev)
|
||||
|
||||
_piano.grab_focus ();
|
||||
|
||||
/* handle up/down */
|
||||
// XXX consider to handle these in APianoKeyboard::on_key_press_event
|
||||
// and use signals. -- also subscribe SustainChanged, indicate sustain.
|
||||
// TODO: pitch-bend shortcuts
|
||||
if (ev->type == GDK_KEY_PRESS) {
|
||||
switch (ev->keyval) {
|
||||
case GDK_KEY_Left:
|
||||
_piano_octave_key.set_value (_piano_octave_key.get_value_as_int () - 1);
|
||||
return true;
|
||||
case GDK_KEY_Right:
|
||||
_piano_octave_key.set_value (_piano_octave_key.get_value_as_int () + 1);
|
||||
return true;
|
||||
case GDK_KEY_F1:
|
||||
_pitch_adjustment.set_value (0);
|
||||
return true;
|
||||
case GDK_KEY_F2:
|
||||
_pitch_adjustment.set_value (4096);
|
||||
return true;
|
||||
case GDK_KEY_F3:
|
||||
_pitch_adjustment.set_value (12288);
|
||||
return true;
|
||||
case GDK_KEY_F4:
|
||||
_pitch_adjustment.set_value (16383);
|
||||
return true;
|
||||
case GDK_KEY_Down:
|
||||
_pitch_adjustment.set_value (std::max(0., _pitch_adjustment.get_value() - 1024));
|
||||
return true;
|
||||
case GDK_KEY_Up:
|
||||
_pitch_adjustment.set_value (std::min(16383., _pitch_adjustment.get_value() + 1024));
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ARDOUR_UI_UTILS::relay_key_press (ev, this);
|
||||
}
|
||||
|
||||
@ -429,26 +396,6 @@ VirtualKeyboardWindow::on_key_release_event (GdkEventKey* ev)
|
||||
|
||||
_piano.grab_focus ();
|
||||
|
||||
if (ev->type == GDK_KEY_RELEASE) {
|
||||
switch (ev->keyval) {
|
||||
case GDK_KEY_F1:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F2:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F3:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_F4:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_Up:
|
||||
/* fallthrough */
|
||||
case GDK_KEY_Down:
|
||||
_pitch_adjustment.set_value (8192);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ArdourWindow::on_key_release_event (ev);
|
||||
}
|
||||
|
||||
@ -604,6 +551,51 @@ VirtualKeyboardWindow::update_sensitivity ()
|
||||
_piano.grab_focus ();
|
||||
}
|
||||
|
||||
void
|
||||
VirtualKeyboardWindow::octave_key_event_handler (bool up)
|
||||
{
|
||||
if (up) {
|
||||
_piano_octave_key.set_value (_piano_octave_key.get_value_as_int () - 1);
|
||||
} else {
|
||||
_piano_octave_key.set_value (_piano_octave_key.get_value_as_int () + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VirtualKeyboardWindow::pitch_bend_key_event_handler (int target, bool interpolate)
|
||||
{
|
||||
if (_pitch_adjustment.get_value() == target) {
|
||||
return;
|
||||
}
|
||||
if (interpolate) {
|
||||
_pitch_bend_target = target;
|
||||
if (!_bender_connection.connected ()){
|
||||
_bender_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &VirtualKeyboardWindow::pitch_bend_timeout), 50 /*ms*/);
|
||||
} else {
|
||||
}
|
||||
return;
|
||||
}
|
||||
_bender_connection.disconnect ();
|
||||
_pitch_adjustment.set_value (target);
|
||||
_pitch_bend_target = target;
|
||||
}
|
||||
|
||||
bool
|
||||
VirtualKeyboardWindow::pitch_bend_timeout ()
|
||||
{
|
||||
int cur = _pitch_adjustment.get_value();
|
||||
int target;
|
||||
if (cur < _pitch_bend_target) {
|
||||
target = std::min (_pitch_bend_target, cur + 1024);
|
||||
} else if (cur > _pitch_bend_target) {
|
||||
target = std::max (_pitch_bend_target, cur - 1024);
|
||||
} else {
|
||||
target = _pitch_bend_target;
|
||||
}
|
||||
_pitch_adjustment.set_value (target);
|
||||
return _pitch_bend_target != target;
|
||||
}
|
||||
|
||||
void
|
||||
VirtualKeyboardWindow::pitch_slider_adjusted ()
|
||||
{
|
||||
|
@ -104,6 +104,10 @@ private:
|
||||
void note_off_event_handler (int);
|
||||
void control_change_event_handler (int, int);
|
||||
|
||||
void octave_key_event_handler (bool);
|
||||
void pitch_bend_key_event_handler (int, bool);
|
||||
bool pitch_bend_timeout ();
|
||||
|
||||
void pitch_bend_event_handler (int);
|
||||
void pitch_bend_release ();
|
||||
void pitch_bend_update_tooltip (int);
|
||||
@ -158,6 +162,9 @@ private:
|
||||
ArdourWidgets::ArdourDropdown _cc_key[VKBD_NCTRLS];
|
||||
|
||||
PBD::ScopedConnectionList _cc_connections;
|
||||
|
||||
sigc::connection _bender_connection;
|
||||
int _pitch_bend_target;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user