diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index f4bab1262..6632c6118 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -32,7 +32,9 @@ To configure Auto-Type sequences for your entries, perform the following steps: 1. Navigate to the entries list and open the desired entry for editing. Click the _Auto-Type_ item from the left-hand menu bar *(1)*. Press the kbd:[+] button *(2)* to add a new sequence entry. Select the desired window using the drop-down menu, or simply type a window title in the box *(3)*. + -TIP: You can use an asterisk (`\*`) to match any value (e.g., when a window title contains a dynamic filename or website name). Set the window title to `*` to match all windows. Leave the window title blank to offer additional default Auto-Type sequences, such as custom attributes. +TIP: You can use an asterisk (`\*`) as a wildcard (e.g., when a window title contains a dynamic file or website name). Set the window title to `*` to match all windows. Leave the window title blank to offer additional sequences for every matching window. This is useful for typing individual custom attributes, for example. ++ +TIP: To use a standard regular expression for window title matching, the window title must start and end with two forward slashes (e.g., `//^Secure Login - .*$//`). + .Auto-Type entry sequences image::autotype_entry_sequences.png[] diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index cd7d2b261..d43c2cedd 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -334,12 +334,15 @@ QList Entry::autoTypeSequences(const QString& windowTitle) const }; QList sequenceList; + QList emptyWindowSequences; // Add window association matches const auto assocList = autoTypeAssociations()->getAll(); for (const auto& assoc : assocList) { auto window = resolveMultiplePlaceholders(assoc.window); - if (!assoc.window.isEmpty() && windowMatches(window)) { + if (assoc.window.isEmpty()) { + emptyWindowSequences << assoc.sequence; + } else if (windowMatches(window)) { if (!assoc.sequence.isEmpty()) { sequenceList << assoc.sequence; } else { @@ -358,6 +361,11 @@ QList Entry::autoTypeSequences(const QString& windowTitle) const sequenceList << effectiveAutoTypeSequence(); } + // If any associations were made, include the empty window associations + if (!sequenceList.isEmpty()) { + sequenceList.append(emptyWindowSequences); + } + return sequenceList; } diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 91bd7d0a4..6166c1927 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -125,6 +125,20 @@ void TestAutoType::init() m_entry5->setPassword("example5"); m_entry5->setTitle("some title"); m_entry5->setUrl("http://example.org"); + + m_entry6 = new Entry(); + m_entry6->setGroup(m_group); + m_entry6->setPassword("example6"); + m_entry6->setTitle("empty window test"); + association.window = ""; + association.sequence = "{S:Empty Window}"; + m_entry6->autoTypeAssociations()->add(association); + association.window = "non-matching window"; + association.sequence = "should not match"; + m_entry6->autoTypeAssociations()->add(association); + association.window = "*notepad*"; + association.sequence = "{USERNAME}"; + m_entry6->autoTypeAssociations()->add(association); } void TestAutoType::cleanup() @@ -446,3 +460,13 @@ void TestAutoType::testAutoTypeEffectiveSequences() QCOMPARE(entry6->defaultAutoTypeSequence(), sequenceOrphan); QCOMPARE(entry6->effectiveAutoTypeSequence(), QString()); } + +void TestAutoType::testAutoTypeEmptyWindowAssociation() +{ + auto assoc = m_entry6->autoTypeSequences("Windows Notepad"); + QCOMPARE(assoc.size(), 2); + QVERIFY(assoc.contains("{S:Empty Window}")); + + assoc = m_entry6->autoTypeSequences("Some Other Window"); + QVERIFY(assoc.isEmpty()); +} diff --git a/tests/TestAutoType.h b/tests/TestAutoType.h index 035c0d5c0..de78a425c 100644 --- a/tests/TestAutoType.h +++ b/tests/TestAutoType.h @@ -51,6 +51,7 @@ private slots: void testAutoTypeResults_data(); void testAutoTypeSyntaxChecks(); void testAutoTypeEffectiveSequences(); + void testAutoTypeEmptyWindowAssociation(); private: AutoTypePlatformInterface* m_platform; @@ -64,6 +65,7 @@ private: Entry* m_entry3; Entry* m_entry4; Entry* m_entry5; + Entry* m_entry6; }; #endif // KEEPASSX_TESTAUTOTYPE_H