Skip to content

Commit

Permalink
Made modal dialogs stay in front of dropdown window on Wayland (#1202)
Browse files Browse the repository at this point in the history
That's done for any child dialog of the main window. It can't be done (consistently) for another dialog that may be called by a child dialog — especially, it's impossible for LXQt file dialog.

Closes #1133

NOTE: The main issue should be fixed by Wayland implementations. I made this patch only because I found a relatively simple and centralized workaround.
  • Loading branch information
tsujan authored Dec 2, 2024
1 parent ff15273 commit 0e6bea2
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,16 +892,51 @@ bool MainWindow::event(QEvent *event)
{
if (m_dropMode &&
!Properties::Instance()->dropKeepOpen &&
qApp->activeWindow() == nullptr
)
hide();
qApp->activeWindow() == nullptr)
{
// On Wayland and with a modal dialog, the dropdown window can be activated by
// clicking inside it and then deactivated by clicking on another window (see below).
if (!m_layerWindow || m_layerWindow->layer() == LayerShellQt::Window::Layer::LayerOverlay)
{
hide();
}
}
}
// A workaround for the modal dialogs of the dropdown window on Wayland.
else if (event->type() == QEvent::WindowBlocked && m_layerWindow && m_dropMode)
{
if (auto dialog = qobject_cast<QDialog*>(qApp->activeModalWidget()))
{
dialog->winId();
if (QWindow *win = dialog->windowHandle())
{
if (LayerShellQt::Window *layershell = LayerShellQt::Window::get(win))
{
layershell->setLayer(LayerShellQt::Window::Layer::LayerOverlay);
layershell->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand);
LayerShellQt::Window::Anchors anchors = {LayerShellQt::Window::AnchorTop};
layershell->setAnchors(anchors);
layershell->setScreenConfiguration(LayerShellQt::Window::ScreenConfiguration::ScreenFromCompositor);
// For preventing the dialog from going behind the dropdown window if
// the latter is clicked, the window is set on the top layer temporarily.
// It will be set on the overlay layer again when the dialog exits.
m_layerWindow->setLayer(LayerShellQt::Window::Layer::LayerTop);
}
}
}
}
else if (event->type() == QEvent::WindowUnblocked && m_layerWindow && m_dropMode)
{
// Restore the overlay layer.
m_layerWindow->setLayer(LayerShellQt::Window::Layer::LayerOverlay);
}

return QMainWindow::event(event);
}

void MainWindow::showEvent(QShowEvent* event)
{
if (m_dropMode && m_layerWindow)
if (m_layerWindow && m_dropMode)
{
const QRect desktop = windowHandle()->screen()->availableGeometry();
int hMargin = desktop.width() * (100 - Properties::Instance()->dropWidth) / 200;
Expand Down

0 comments on commit 0e6bea2

Please sign in to comment.