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.
This commit is contained in:
Jonathan White 2021-02-28 09:28:27 -05:00
parent 57af7c131d
commit bc08913c61
2 changed files with 18 additions and 7 deletions

View File

@ -30,6 +30,8 @@ AutoTypePlatformX11::AutoTypePlatformX11()
m_atomString = XInternAtom(m_dpy, "STRING", True); m_atomString = XInternAtom(m_dpy, "STRING", True);
m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True); m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", 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" m_classBlacklist << "desktop_window"
<< "gnome-panel"; // Gnome << "gnome-panel"; // Gnome
@ -262,23 +264,31 @@ QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
bool AutoTypePlatformX11::isTopLevelWindow(Window window) bool AutoTypePlatformX11::isTopLevelWindow(Window window)
{ {
bool result = false;
Atom type = None; Atom type = None;
int format; int format;
unsigned long nitems; unsigned long nitems;
unsigned long after; 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( int retVal = XGetWindowProperty(
m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data); m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format, &nitems, &after, &data);
bool result = false;
if (retVal == 0 && data) { if (retVal == 0 && data) {
if (type == m_atomWmState && format == 32 && nitems > 0) { if (type == m_atomWmState && format == 32 && nitems > 0) {
qint32 state = static_cast<qint32>(*data); result = (static_cast<quint32>(*data) != WithdrawnState);
result = (state != WithdrawnState);
} }
XFree(data); 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; return result;

View File

@ -68,7 +68,6 @@ private:
void updateKeymap(); void updateKeymap();
bool isRemapKeycodeValid(); bool isRemapKeycodeValid();
int AddKeysym(KeySym keysym); int AddKeysym(KeySym keysym);
void AddModifier(KeySym keysym);
void SendKeyEvent(unsigned keycode, bool press); void SendKeyEvent(unsigned keycode, bool press);
void SendModifiers(unsigned int mask, bool press); void SendModifiers(unsigned int mask, bool press);
int GetKeycode(KeySym keysym, unsigned int* mask); int GetKeycode(KeySym keysym, unsigned int* mask);
@ -84,6 +83,8 @@ private:
Atom m_atomString; Atom m_atomString;
Atom m_atomUtf8String; Atom m_atomUtf8String;
Atom m_atomNetActiveWindow; Atom m_atomNetActiveWindow;
Atom m_atomTransientFor;
Atom m_atomWindow;
QSet<QString> m_classBlacklist; QSet<QString> m_classBlacklist;
XkbDescPtr m_xkb; XkbDescPtr m_xkb;