mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-10-06 07:00:16 +08:00
Implement configurable accelerators support for wxQt
Use the new API, i.e. call ClaimsKeyBeforeAccelerator() and send wxEVT_ACCELERATOR_KEY, in wxQt too. Update wxComboBox to override ClaimsKeyBeforeAccelerator() too. Note that wxTextCtrl and wxSpinCtrl don't need to be modified because they already do this in the base class. This actually simplifies the existing code as we don't need wxWindow::m_processingShortcut any more.
This commit is contained in:
@@ -85,6 +85,11 @@ public:
|
||||
|
||||
virtual bool QtHandleFocusEvent(QWidget *handler, QFocusEvent *event) override;
|
||||
protected:
|
||||
#if wxUSE_ACCEL
|
||||
// Reserve the keys used for editing the text in this control.
|
||||
virtual bool ClaimsKeyBeforeAccelerator(const wxKeyEvent& event,
|
||||
int command) const override;
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
// From wxTextEntry:
|
||||
virtual wxString DoGetValue() const override;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
#include <QtGui/QCloseEvent>
|
||||
#include <QtGui/QKeyEvent>
|
||||
|
||||
#include "wx/log.h"
|
||||
#include "wx/window.h"
|
||||
@@ -366,6 +367,44 @@ protected:
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
#if wxUSE_ACCEL
|
||||
case QEvent::ShortcutOverride:
|
||||
// Qt sends this event before using the key for a shortcut,
|
||||
// which allows us to decide whether it should really be used.
|
||||
//
|
||||
// Note that this event is also sent to all the parents of the
|
||||
// focused widget, but we only need to handle it once, in the
|
||||
// window which is going to get the key event.
|
||||
if ( this->hasFocus() )
|
||||
{
|
||||
if ( wxWindow* const handler = this->GetHandler() )
|
||||
{
|
||||
auto* const keyEvent = static_cast<QKeyEvent*>(event);
|
||||
|
||||
switch ( handler->QtShouldUseAccelerator(keyEvent) )
|
||||
{
|
||||
case wxWindow::AcceleratorVerdict::Nothing:
|
||||
// There is no accelerator defined anyhow.
|
||||
break;
|
||||
|
||||
case wxWindow::AcceleratorVerdict::Accel:
|
||||
// Allow the shortcut to be used and prevent
|
||||
// the widget itself from claiming this key, as
|
||||
// e.g. QLineEdit does for Ctrl-C.
|
||||
event->ignore();
|
||||
return true;
|
||||
|
||||
case wxWindow::AcceleratorVerdict::Window:
|
||||
// Accepting means that we will get the key
|
||||
// events (and the shortcut won't be used).
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
case QEvent::Gesture:
|
||||
return gestureEvent(static_cast<QGestureEvent*>(event), event);
|
||||
|
||||
|
||||
+10
-1
@@ -184,6 +184,16 @@ public:
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
virtual void QtHandleShortcut ( int command );
|
||||
|
||||
// Called when Qt is about to use a shortcut for the given key to decide
|
||||
// what should really happen with it.
|
||||
enum class AcceleratorVerdict
|
||||
{
|
||||
Nothing, // No accelerator defined for this key event.
|
||||
Accel, // The accelerator should be used.
|
||||
Window // Window claims the key event and will process it itself.
|
||||
};
|
||||
AcceleratorVerdict QtShouldUseAccelerator ( QKeyEvent *event );
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
@@ -267,7 +277,6 @@ private:
|
||||
#if wxUSE_ACCEL
|
||||
wxVector<QShortcut*> m_qtShortcuts; // owned by whatever GetHandle() returns
|
||||
std::unique_ptr<wxQtShortcutHandler> m_qtShortcutHandler; // always allocated
|
||||
bool m_processingShortcut;
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_COPY( wxWindowQt );
|
||||
|
||||
@@ -153,6 +153,21 @@ bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
|
||||
return wxChoiceBase::Create( parent, id, pos, size, style, validator, name );
|
||||
}
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
|
||||
bool
|
||||
wxComboBox::ClaimsKeyBeforeAccelerator(const wxKeyEvent& event,
|
||||
int WXUNUSED(command)) const
|
||||
{
|
||||
// We don't need any keys if we're not editing any text at all.
|
||||
if ( IsReadOnly() )
|
||||
return false;
|
||||
|
||||
return IsUsedForEditing(event);
|
||||
}
|
||||
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
bool wxComboBox::IsReadOnly() const
|
||||
{
|
||||
return HasFlag( wxCB_READONLY );
|
||||
|
||||
+23
-33
@@ -327,7 +327,6 @@ void wxWindowQt::Init()
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
m_qtShortcutHandler.reset(new wxQtShortcutHandler(this));
|
||||
m_processingShortcut = false;
|
||||
#endif
|
||||
m_qtWindow = nullptr;
|
||||
m_qtContainer = nullptr;
|
||||
@@ -1655,6 +1654,29 @@ void wxWindowQt::QtFillKeyEvent( wxKeyEvent& e, const QKeyEvent *event ) const
|
||||
wxQtFillKeyboardModifiers( event->modifiers(), &e );
|
||||
}
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
|
||||
wxWindowQt::AcceleratorVerdict
|
||||
wxWindowQt::QtShouldUseAccelerator ( QKeyEvent *event )
|
||||
{
|
||||
wxKeyEvent e( wxEVT_KEY_DOWN );
|
||||
QtFillKeyEvent( e, event );
|
||||
|
||||
wxAcceleratorEntry entry;
|
||||
if ( !FindAcceleratorForKey(e, entry, nullptr) )
|
||||
{
|
||||
// This key is not used by any accelerator anyhow.
|
||||
return AcceleratorVerdict::Nothing;
|
||||
}
|
||||
|
||||
if ( ShouldUseAcceleratorForKey(e, entry.GetCommand(), entry.GetMenuItem()) )
|
||||
return AcceleratorVerdict::Accel;
|
||||
|
||||
return AcceleratorVerdict::Window;
|
||||
}
|
||||
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
bool wxWindowQt::QtHandleKeyEvent ( QWidget *WXUNUSED( handler ), QKeyEvent *event )
|
||||
{
|
||||
// qt sends keyup and keydown events for autorepeat, but this is not
|
||||
@@ -1663,18 +1685,6 @@ bool wxWindowQt::QtHandleKeyEvent ( QWidget *WXUNUSED( handler ), QKeyEvent *eve
|
||||
if ( event->isAutoRepeat() && event->type() == QEvent::KeyRelease )
|
||||
return true;
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
if ( m_processingShortcut )
|
||||
{
|
||||
/* Enter here when a shortcut isn't handled by Qt.
|
||||
* Return true to avoid Qt-processing of the event
|
||||
* Instead, use the flag to indicate that it wasn't processed */
|
||||
m_processingShortcut = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
bool handled = false;
|
||||
|
||||
// Build the event
|
||||
@@ -1686,26 +1696,6 @@ bool wxWindowQt::QtHandleKeyEvent ( QWidget *WXUNUSED( handler ), QKeyEvent *eve
|
||||
// On key presses, send the EVT_CHAR event
|
||||
if ( !handled && event->type() == QEvent::KeyPress )
|
||||
{
|
||||
#if wxUSE_ACCEL
|
||||
// Check for accelerators
|
||||
if ( !m_processingShortcut )
|
||||
{
|
||||
/* The call to notify() will try to execute a shortcut. If it fails
|
||||
* it will call keyPressEvent() in our wxQtWidget which calls back
|
||||
* to this function. We use the m_processingShortcut flag to avoid
|
||||
* processing that recursive call and return back to this one. */
|
||||
m_processingShortcut = true;
|
||||
|
||||
QApplication::instance()->notify( GetHandle(), event );
|
||||
|
||||
handled = m_processingShortcut;
|
||||
m_processingShortcut = false;
|
||||
|
||||
if ( handled )
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
// For compatibility with wxMSW, don't generate wxEVT_CHAR event for
|
||||
// the following keys: SHIFT, CONTROL, MENU, CAPITAL, NUMLOCK and SCROLL.
|
||||
switch ( event->key() )
|
||||
|
||||
Reference in New Issue
Block a user