From 67e67ea42fcfd2a0805fd96f44a2435992a3320e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 23 May 2018 23:51:09 +0100 Subject: [PATCH] Try another way of fixing accelerators stealing text control arrow keys (#1263). --- src/tools/dcpomatic.cc | 53 +++++++++++++++------------------------ src/wx/dcp_panel.cc | 3 +++ src/wx/focus_manager.cc | 55 +++++++++++++++++++++++++++++++++++++++++ src/wx/focus_manager.h | 51 ++++++++++++++++++++++++++++++++++++++ src/wx/wscript | 1 + 5 files changed, 130 insertions(+), 33 deletions(-) create mode 100644 src/wx/focus_manager.cc create mode 100644 src/wx/focus_manager.h diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 33e90aef3..4f034b2b5 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -44,6 +44,7 @@ #include "wx/nag_dialog.h" #include "wx/export_dialog.h" #include "wx/paste_dialog.h" +#include "wx/focus_manager.h" #include "lib/film.h" #include "lib/config.h" #include "lib/util.h" @@ -331,6 +332,15 @@ public: overall_panel->SetSizer (main_sizer); + UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this)); + + FocusManager::instance()->SetFocus.connect (boost::bind (&DOMFrame::remove_accelerators, this)); + FocusManager::instance()->KillFocus.connect (boost::bind (&DOMFrame::add_accelerators, this)); + add_accelerators (); + } + + void add_accelerators () + { #ifdef __WXOSX__ int accelerators = 7; #else @@ -348,15 +358,18 @@ public: #endif Bind (wxEVT_MENU, boost::bind (&ContentPanel::add_file_clicked, _film_editor->content_panel()), ID_add_file); Bind (wxEVT_MENU, boost::bind (&DOMFrame::remove_clicked, this, _1), ID_remove); - Bind (wxEVT_MENU, boost::bind (&DOMFrame::start_stop_pressed, this, _1), ID_start_stop); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::start_stop_pressed, this), ID_start_stop); Bind (wxEVT_MENU, boost::bind (&DOMFrame::timeline_pressed, this), ID_timeline); - Bind (wxEVT_MENU, boost::bind (&DOMFrame::back_frame, this, _1), ID_back_frame); - Bind (wxEVT_MENU, boost::bind (&DOMFrame::forward_frame, this, _1), ID_forward_frame); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::back_frame, this), ID_back_frame); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::forward_frame, this), ID_forward_frame); wxAcceleratorTable accel_table (accelerators, accel); SetAcceleratorTable (accel_table); delete[] accel; + } - UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this)); + void remove_accelerators () + { + SetAcceleratorTable (wxAcceleratorTable ()); } void remove_clicked (wxCommandEvent& ev) @@ -1213,26 +1226,8 @@ private: _update_news_requested = false; } - /** Skip the given event if we're focussed in a TextCtrl, so that hotkeys don't - * steal from text controls. - */ - bool maybe_pass (wxCommandEvent& ev) + void start_stop_pressed () { - wxWindow* f = wxWindow::FindFocus(); - if (!f || !dynamic_cast(f)) { - return false; - } - - ev.Skip(); - return true; - } - - void start_stop_pressed (wxCommandEvent& ev) - { - if (maybe_pass(ev)) { - return; - } - if (_film_viewer->playing()) { _film_viewer->stop(); } else { @@ -1245,21 +1240,13 @@ private: _film_editor->content_panel()->timeline_clicked (); } - void back_frame (wxCommandEvent& ev) + void back_frame () { - if (maybe_pass(ev)) { - return; - } - _film_viewer->back_frame (); } - void forward_frame (wxCommandEvent& ev) + void forward_frame () { - if (maybe_pass(ev)) { - return; - } - _film_viewer->forward_frame (); } diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc index 397a29d48..f2783af6b 100644 --- a/src/wx/dcp_panel.cc +++ b/src/wx/dcp_panel.cc @@ -23,6 +23,7 @@ #include "key_dialog.h" #include "isdcf_metadata_dialog.h" #include "audio_dialog.h" +#include "focus_manager.h" #include "lib/ratio.h" #include "lib/config.h" #include "lib/dcp_content_type.h" @@ -74,6 +75,8 @@ DCPPanel::DCPPanel (wxNotebook* n, boost::shared_ptr film) grid->Add (_name, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND | wxLEFT | wxRIGHT); ++r; + FocusManager::instance()->add(_name); + int flags = wxALIGN_CENTER_VERTICAL; #ifdef __WXOSX__ flags |= wxALIGN_RIGHT; diff --git a/src/wx/focus_manager.cc b/src/wx/focus_manager.cc new file mode 100644 index 000000000..f4f23cb28 --- /dev/null +++ b/src/wx/focus_manager.cc @@ -0,0 +1,55 @@ +/* + Copyright (C) 2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "focus_manager.h" +#include + +FocusManager* FocusManager::_instance; + +FocusManager * +FocusManager::instance() +{ + if (!_instance) { + _instance = new FocusManager(); + } + + return _instance; +} + +void +FocusManager::set_focus (wxFocusEvent& ev) +{ + SetFocus(); + ev.Skip(); +} + +void +FocusManager::kill_focus (wxFocusEvent& ev) +{ + KillFocus(); + ev.Skip(); +} + +void +FocusManager::add(wxTextCtrl* c) +{ + c->Bind(wxEVT_SET_FOCUS, boost::bind(&FocusManager::set_focus, this, _1)); + c->Bind(wxEVT_KILL_FOCUS, boost::bind(&FocusManager::kill_focus, this, _1)); +} diff --git a/src/wx/focus_manager.h b/src/wx/focus_manager.h new file mode 100644 index 000000000..3c91c22fa --- /dev/null +++ b/src/wx/focus_manager.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include + +class wxTextCtrl; +class wxFocusEvent; + +/** @class FocusManager class + * @brief A central point for notifications about when wxTextCtrls get focus in the main window. + * + * This allows us to turn off accelerators for the duration of the focus so that they don't steal + * keypresses. It's a hack but the only way I could make it work on all platforms (looking for + * the focussed thing and doing ev.Skip() if it's a wxTextCtrl did not work for me on Windows: + * ev.Skip() did not cause the event to be delivered). + */ +class FocusManager +{ +public: + /** emitted when any add()ed TextCtrl gets focus */ + boost::signals2::signal SetFocus; + /** emitted when any add()ed TextCtrl loses focus */ + boost::signals2::signal KillFocus; + + void add(wxTextCtrl* c); + + static FocusManager* instance(); + +private: + void set_focus(wxFocusEvent &); + void kill_focus(wxFocusEvent &); + + static FocusManager* _instance; +}; diff --git a/src/wx/wscript b/src/wx/wscript index 476cd468a..35861db00 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -57,6 +57,7 @@ sources = """ film_viewer.cc filter_dialog.cc filter_editor.cc + focus_manager.cc fonts_dialog.cc font_files_dialog.cc full_config_dialog.cc -- 2.30.2