From 0c57c7a67bec2b817450e1e6f5880339eb755621 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 28 Feb 2021 09:28:27 -0500 Subject: [PATCH] Auto-Type: Allow selection of modal dialogs on X11 * Fix #5958 - Modal dialogs do not have WM_STATE set even though they are a valid top-level window with a valid name. In this case, we need to poll for WM_TRANSIENT_FOR which returns the top level window the dialog is a child of. --- src/autotype/xcb/AutoTypeXCB.cpp | 22 ++++++++++++++++------ src/autotype/xcb/AutoTypeXCB.h | 3 ++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp index d2d757b4e..2f320f73b 100644 --- a/src/autotype/xcb/AutoTypeXCB.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -39,6 +39,8 @@ AutoTypePlatformX11::AutoTypePlatformX11() m_atomString = XInternAtom(m_dpy, "STRING", True); m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True); m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True); + m_atomTransientFor = XInternAtom(m_dpy, "WM_TRANSIENT_FOR", True); + m_atomWindow = XInternAtom(m_dpy, "WINDOW", True); m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome @@ -373,23 +375,31 @@ QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window) bool AutoTypePlatformX11::isTopLevelWindow(Window window) { + bool result = false; + Atom type = None; int format; unsigned long nitems; unsigned long after; - unsigned char* data = Q_NULLPTR; + unsigned char* data = nullptr; + + // Check if the window has WM_STATE atom and it is not Withdrawn int retVal = XGetWindowProperty( m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data); - bool result = false; - if (retVal == 0 && data) { if (type == m_atomWmState && format == 32 && nitems > 0) { - qint32 state = static_cast(*data); - result = (state != WithdrawnState); + result = (static_cast(*data) != WithdrawnState); } - XFree(data); + } else { + // See if this is a transient window without WM_STATE + retVal = XGetWindowProperty( + m_dpy, window, m_atomTransientFor, 0, 1, False, m_atomWindow, &type, &format, &nitems, &after, &data); + if (retVal == 0 && data) { + result = true; + XFree(data); + } } return result; diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h index 221d2ba7b..327359d3c 100644 --- a/src/autotype/xcb/AutoTypeXCB.h +++ b/src/autotype/xcb/AutoTypeXCB.h @@ -77,7 +77,6 @@ private: void updateKeymap(); bool isRemapKeycodeValid(); int AddKeysym(KeySym keysym); - void AddModifier(KeySym keysym); void SendKeyEvent(unsigned keycode, bool press); void SendModifiers(unsigned int mask, bool press); int GetKeycode(KeySym keysym, unsigned int* mask); @@ -93,6 +92,8 @@ private: Atom m_atomString; Atom m_atomUtf8String; Atom m_atomNetActiveWindow; + Atom m_atomTransientFor; + Atom m_atomWindow; QSet m_classBlacklist; Qt::Key m_currentGlobalKey; Qt::KeyboardModifiers m_currentGlobalModifiers;