5#include "private/qobject_p.h"
12#include <private/qkeymapper_p.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qscopeguard.h>
46 {
return keyseq <
f.keyseq; }
58#ifdef Dump_QShortcutMap
66 return dbg <<
"QShortcutEntry(0x0)";
68 <<
"QShortcutEntry(" << se->
keyseq
70 <<
"), owner(" << se->
owner <<
')';
125 Q_ASSERT_X(owner,
"QShortcutMap::addShortcut",
"All shortcuts need an owner");
126 Q_ASSERT_X(!
key.isEmpty(),
"QShortcutMap::addShortcut",
"Cannot add keyless shortcuts to map");
130 const auto it = std::upper_bound(
d->sequences.begin(),
d->sequences.end(), newEntry);
131 d->sequences.insert(
it, newEntry);
132 qCDebug(lcShortcutMap).nospace()
133 <<
"QShortcutMap::addShortcut(" << owner <<
", "
134 <<
key <<
", " <<
context <<
") added shortcut with ID " <<
d->currentId;
150 int itemsRemoved = 0;
151 bool allOwners = (owner ==
nullptr);
153 bool allIds =
id == 0;
156 qCDebug(lcShortcutMap).nospace()
157 <<
"QShortcutMap::removeShortcut(" <<
id <<
", " << owner <<
", "
158 <<
key <<
") removed " << itemsRemoved <<
" shortcuts(s)";
162 if (allOwners &&
allKeys && allIds) {
163 itemsRemoved =
d->sequences.size();
164 d->sequences.clear();
168 int i =
d->sequences.size()-1;
172 int entryId =
entry.id;
173 if ((allOwners ||
entry.owner == owner)
176 d->sequences.removeAt(
i);
197 int itemsChanged = 0;
198 bool allOwners = (owner ==
nullptr);
200 bool allIds =
id == 0;
202 int i =
d->sequences.size()-1;
206 if ((allOwners ||
entry.owner == owner)
216 qCDebug(lcShortcutMap).nospace()
217 <<
"QShortcutMap::setShortcutEnabled(" <<
enable <<
", " <<
id <<
", "
218 << owner <<
", " <<
key <<
") = " << itemsChanged;
233 int itemsChanged = 0;
234 bool allOwners = (owner ==
nullptr);
236 bool allIds =
id == 0;
238 int i =
d->sequences.size()-1;
242 if ((allOwners ||
entry.owner == owner)
245 d->sequences[
i].autorepeat = on;
252 qCDebug(lcShortcutMap).nospace()
253 <<
"QShortcutMap::setShortcutAutoRepeat(" << on <<
", " <<
id <<
", "
254 << owner <<
", " <<
key <<
") = " << itemsChanged;
261void QShortcutMap::resetState()
265 clearSequence(
d->currentSequences);
274 return d->currentState;
295 switch (nextState(
e)) {
308 const int identicalMatches =
d->identicals.size();
313 return identicalMatches > 0;
316 Q_UNREACHABLE_RETURN(
false);
331 return d->currentState;
336 d->identicals.clear();
353 clearSequence(
d->currentSequences);
356 qCDebug(lcShortcutMap).nospace() <<
"QShortcutMap::nextState(" <<
e <<
") = " <<
result;
368 const auto itEnd =
d->sequences.cend();
369 auto it = std::lower_bound(
d->sequences.cbegin(), itEnd,
entry);
371 for (;
it != itEnd; ++
it) {
391 if (!
d->sequences.size())
394 createNewSequences(
e,
d->newEntries, ignoredModifiers);
395 qCDebug(lcShortcutMap) <<
"Possible shortcut key sequences:" <<
d->newEntries;
398 if (
d->newEntries ==
d->currentSequences) {
400 "QShortcutMap::find",
"New sequence to find identical to previous");
405 d->identicals.clear();
407 bool partialFound =
false;
408 bool identicalDisabledFound =
false;
411 for (
int i =
d->newEntries.size()-1;
i >= 0 ; --
i) {
414 const auto itEnd =
d->sequences.constEnd();
415 auto it = std::lower_bound(
d->sequences.constBegin(), itEnd,
entry);
422 tempRes = matches(
entry.keyseq, (*it).keyseq);
423 oneKSResult =
qMax(oneKSResult, tempRes);
424 qCDebug(lcShortcutMap) <<
" - matches returned" << tempRes <<
"for" <<
entry.keyseq <<
it->keyseq
425 <<
"- correctContext()?" <<
it->correctContext();
429 d->identicals.append(&*
it);
431 identicalDisabledFound =
true;
434 if (
d->identicals.size())
438 partialFound |= (*it).enabled;
449 if (oneKSResult >
result) {
451 qCDebug(lcShortcutMap) <<
"Found better match (" <<
d->newEntries <<
"), clearing key sequence list";
453 if (oneKSResult && oneKSResult >=
result) {
454 okEntries <<
d->newEntries.at(
i);
455 qCDebug(lcShortcutMap) <<
"Added ok key sequence" <<
d->newEntries;
459 if (
d->identicals.size()) {
461 }
else if (partialFound) {
463 }
else if (identicalDisabledFound) {
466 clearSequence(
d->currentSequences);
470 d->currentSequences = okEntries;
471 qCDebug(lcShortcutMap) <<
"Returning shortcut match == " <<
result;
483 d_func()->newEntries.clear();
494 qCDebug(lcShortcutMap) <<
"Creating new sequences for" <<
e
495 <<
"with ignoredModifiers=" << Qt::KeyboardModifiers(ignoredModifiers);
496 int pkTotal = possibleKeys.
size();
500 int ssActual =
d->currentSequences.size();
501 int ssTotal =
qMax(1, ssActual);
503 ksl.
resize(pkTotal * ssTotal);
505 int index = ssActual ?
d->currentSequences.at(0).count() : 0;
506 for (
int pkNum = 0; pkNum < pkTotal; ++pkNum) {
507 for (
int ssNum = 0; ssNum < ssTotal; ++ssNum) {
508 int i = (pkNum * ssTotal) + ssNum;
512 curKsl.setKey(curSeq[0], 0);
513 curKsl.setKey(curSeq[1], 1);
514 curKsl.setKey(curSeq[2], 2);
515 curKsl.setKey(curSeq[3], 3);
547 for (
uint i = 0;
i < userN; ++
i) {
548 int userKey = seq1[
i].toCombined(),
549 sequenceKey = seq2[
i].toCombined();
554 if (userKey != sequenceKey)
564int QShortcutMap::translateModifiers(Qt::KeyboardModifiers
modifiers)
584 return d->identicals;
593 if (!
d->identicals.size())
597 if (
d->prevSequence != curKey) {
599 d->prevSequence = curKey;
603 int i = 0, enabledShortcuts = 0;
605 while(i < d->identicals.size()) {
606 current =
d->identicals.at(
i);
609 if (lcShortcutMap().isDebugEnabled())
610 ambiguousShortcuts.
append(current);
611 if (enabledShortcuts >
d->ambigCount + 1)
617 d->ambigCount = (
d->identicals.size() ==
i ? 0 :
d->ambigCount + 1);
620 if (!
next || (
e->isAutoRepeat() && !
next->autorepeat))
623 if (lcShortcutMap().isDebugEnabled()) {
624 if (ambiguousShortcuts.
size() > 1) {
625 qCDebug(lcShortcutMap) <<
"The following shortcuts are about to be activated ambiguously:";
627 qCDebug(lcShortcutMap).nospace() <<
"- " <<
entry->keyseq <<
" (belonging to " <<
entry->owner <<
")";
630 qCDebug(lcShortcutMap).nospace()
631 <<
"QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
632 <<
next->keyseq.toString() <<
"\", " <<
next->id <<
", "
633 <<
static_cast<bool>(enabledShortcuts>1) <<
") to object(" <<
next->owner <<
')';
643 for (
auto sequence :
d->sequences) {
644 bool addSequence =
false;
645 if (sequence.enabled) {
650 QObject *possibleWindow = sequence.owner;
651 while (possibleWindow) {
654 possibleWindow = possibleWindow->
parent();
661 while (possibleWidget->
parent()) {
662 possibleWidget = possibleWidget->
parent();
663 if (possibleWidget == sequence.owner) {
672 keys << sequence.keyseq;
683#if defined(Dump_QShortcutMap)
684void QShortcutMap::dumpMap()
const
687 for (
int i = 0;
i <
d->sequences.size(); ++
i)
688 qDebug().nospace() << &(
d->sequences.at(
i));
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
static constexpr QKeyCombination fromCombined(int combined)
The QKeyEvent class describes a key event.
static QList< int > possibleKeys(QKeyEvent *e)
The QKeySequence class encapsulates a key sequence as used by shortcuts.
SequenceMatch
\value NoMatch The key sequences are different; not even partially matching.
int count() const
Returns the number of keys in the key sequence.
qsizetype size() const noexcept
const_reference at(qsizetype i) const noexcept
void reserve(qsizetype size)
void resize(qsizetype size)
void append(parameter_type t)
QObject * parent() const
Returns a pointer to the parent object.
The QShortcutEvent class provides an event which is generated when the user presses a key combination...
QList< QShortcutEntry > sequences
QList< QKeySequence > newEntries
QKeySequence prevSequence
QList< const QShortcutEntry * > identicals
QList< QKeySequence > currentSequences
QShortcutMapPrivate(QShortcutMap *parent)
QKeySequence::SequenceMatch currentState
bool hasShortcutForKeySequence(const QKeySequence &seq) const
int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key=QKeySequence())
int removeShortcut(int id, QObject *owner, const QKeySequence &key=QKeySequence())
int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key=QKeySequence())
int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher)
bool tryShortcut(QKeyEvent *e)
QList< QKeySequence > keySequences(bool getAll=false) const
QKeySequence::SequenceMatch state()
bool(* ContextMatcher)(QObject *object, Qt::ShortcutContext context)
EGLImageKHR int int EGLuint64KHR * modifiers
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ WidgetWithChildrenShortcut
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
bool(* ContextMatcher)(QObject *, Qt::ShortcutContext)
#define Q_ASSERT_X(cond, x, msg)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result, REGSAM access=0)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
QWindow * qobject_cast< QWindow * >(QObject *o)
static const auto matcher
[0]
QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m)
bool correctContext() const
QShortcutEntry(const QKeySequence &k)
Qt::ShortcutContext context
QShortcutMap::ContextMatcher contextMatcher
bool operator<(const QShortcutEntry &f) const
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent