Skip to content

Commit

Permalink
Keep track of the focusing order of top-level windows
Browse files Browse the repository at this point in the history
Required to trigger actions from external applications, e.g. "insert
text into the front-most (source) window"
  • Loading branch information
stloeffler committed Oct 29, 2023
1 parent 5e75479 commit 12d45f8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
78 changes: 78 additions & 0 deletions src/TWApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,32 @@ void TWApp::init()

scriptManager = new TWScriptManager;

connect(this, &QGuiApplication::focusObjectChanged, this, [=](QObject * focusObj) {
QWidget * widget = qobject_cast<QWidget*>(focusObj);
if (!widget) {
return;
}
// Get the corresponding top level widget
while (widget && widget->parentWidget()) {
widget = widget->parentWidget();
}
if (!m_focusStack.empty() && m_focusStack.top() == widget) {
return;
}
// Remove all empty pointers (to widgets that were destroyed already)
// and all mentions of the current widget
// NB: Using one indexed loop instead of two removeAll invocations (the
// latter was only introduced in Qt 5.4) to only traverse the stack once
for (decltype(m_focusStack)::size_type i = 0; i < m_focusStack.size(); ) {
if (!m_focusStack[i] || m_focusStack[i] == widget) {
m_focusStack.remove(i);
continue;
}
++i;
}
m_focusStack.push(widget);
});

#if defined(Q_OS_DARWIN)
setQuitOnLastWindowClosed(false);
setAttribute(Qt::AA_DontShowIconsInMenus);
Expand Down Expand Up @@ -1211,6 +1237,58 @@ QStringList TWApp::getTranslationList()
return translationList;
}

QWidget * TWApp::topWindow() const
{
if (m_focusStack.empty()) {
return nullptr;
}
return m_focusStack.top().data();
}

QWidget *TWApp::topTeXWindow() const
{
// NB: using iterators is safer, in case QStack::size_type is turned into an
// unsigned type at some point
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
for (decltype(m_focusStack)::size_type i = m_focusStack.size() - 1; i >= 0; --i) {
auto * win = qobject_cast<TeXDocumentWindow *>(m_focusStack[i]);
if (win) {
return win;
}
}
#else
for (auto it = m_focusStack.crbegin(); it != m_focusStack.crend(); ++it) {
auto * win = qobject_cast<TeXDocumentWindow *>(it->data());
if (win) {
return win;
}
}
#endif
return nullptr;
}

QWidget *TWApp::topPDFWindow() const
{
// NB: using iterators is safer, in case QStack::size_type is turned into an
// unsigned type at some point
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
for (decltype(m_focusStack)::size_type i = m_focusStack.size() - 1; i >= 0; --i) {
auto * win = qobject_cast<PDFDocumentWindow *>(m_focusStack[i]);
if (win) {
return win;
}
}
#else
for (auto it = m_focusStack.crbegin(); it != m_focusStack.crend(); ++it) {
auto * win = qobject_cast<PDFDocumentWindow *>(it->data());
if (win) {
return win;
}
}
#endif
return nullptr;
}

void TWApp::applyTranslation(const QString& locale)
{
foreach (QTranslator* t, translators) {
Expand Down
7 changes: 7 additions & 0 deletions src/TWApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <QMenuBar>
#endif
#include <QSettings>
#include <QStack>
#include <QString>
#include <QTextCodec>
#include <QVariant>
Expand Down Expand Up @@ -113,6 +114,10 @@ class TWApp : public QApplication

TWScriptManager* getScriptManager() { return scriptManager; }

QWidget * topWindow() const;
QWidget * topTeXWindow() const;
QWidget * topPDFWindow() const;

#if defined(Q_OS_WIN)
static QString GetWindowsVersionString();
static unsigned int GetWindowsVersion();
Expand Down Expand Up @@ -275,6 +280,8 @@ private slots:

static TWApp *theAppInstance;
Tw::InterProcessCommunicator m_IPC;

QStack<QPointer<QWidget>> m_focusStack;
};

inline TWApp *TWApp::instance()
Expand Down

0 comments on commit 12d45f8

Please sign in to comment.