Force ActivateWindowDelayed to use xcb_set_input_focus on X11 when activating a parent

There's logic in Qt that uses xcb_set_input_focus to focus parent windows as some X11 window managers ignore such focus requests leaving the parent activated, but without input focus. By the time delayed activation happens, current focus window may no more exist and the logic in Qt won't work. X11BypassWindowManagerHint says Qt it should use xcb_set_input_focus on X11 that asks X11 directly to set input focus to that window.
This commit is contained in:
Ilya Fedin 2022-09-07 00:50:06 +04:00 committed by John Preston
parent 4ec399f169
commit d7c2185f5c

View file

@ -9,9 +9,11 @@
#include "ui/ui_utility.h"
#include "base/call_delayed.h"
#include "base/invoke_queued.h"
#include "base/platform/base_platform_info.h"
#include <QtCore/QPointer>
#include <QtCore/QCoreApplication>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
namespace Ui {
namespace {
@ -40,15 +42,41 @@ void ActivateWindowDelayed(not_null<QWidget*> widget) {
} else if (std::exchange(Window, widget.get())) {
return;
}
const auto focusAncestor = [&] {
const auto focusWindow = QGuiApplication::focusWindow();
if (!focusWindow || !widget->window()) {
return false;
}
const auto handle = widget->window()->windowHandle();
if (!handle) {
return false;
}
return handle->isAncestorOf(focusWindow);
}();
crl::on_main(Window, [=] {
if (const auto widget = base::take(Window)) {
if (const auto window = widget->window()) {
if (!window->isHidden()) {
const auto widget = base::take(Window);
if (!widget) {
return;
}
const auto window = widget->window();
if (!window || window->isHidden()) {
return;
}
const auto guard = [&] {
if (!::Platform::IsX11() || !focusAncestor) {
return gsl::finally(Fn<void()>([] {}));
}
const auto handle = window->windowHandle();
if (!(handle->flags() & Qt::X11BypassWindowManagerHint)) {
handle->setFlag(Qt::X11BypassWindowManagerHint);
return gsl::finally(Fn<void()>([&] {
handle->setFlag(Qt::X11BypassWindowManagerHint, false);
}));
}
return gsl::finally(Fn<void()>([] {}));
}();
window->raise();
window->activateWindow();
}
}
}
});
}