From 981b31232335582b3c4973de2365ddefa30e6d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 9 May 2016 14:48:10 +0200 Subject: [PATCH] [Wayland] Make it possible to have internal windows decorated Summary: With this change KWin can create window decorations for internal windows. Thus it's also possible to move internal windows and resize them which is especially important for the debug console. Reviewers: #kwin, #plasma_on_wayland, sebas Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2371 --- autotests/integration/internal_window.cpp | 1 + input.cpp | 9 ++++++- plugins/qpa/window.cpp | 2 ++ pointer_input.cpp | 9 ++++--- shell_client.cpp | 32 +++++++++++++++++++++-- shell_client.h | 1 + workspace.cpp | 5 ++++ 7 files changed, 53 insertions(+), 6 deletions(-) diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp index b027199d85..8092d3059a 100644 --- a/autotests/integration/internal_window.cpp +++ b/autotests/integration/internal_window.cpp @@ -91,6 +91,7 @@ private: HelperWindow::HelperWindow() : QRasterWindow(nullptr) { + setFlags(Qt::FramelessWindowHint); } HelperWindow::~HelperWindow() = default; diff --git a/input.cpp b/input.cpp index 37ab081145..a6de0bd8bb 100644 --- a/input.cpp +++ b/input.cpp @@ -430,6 +430,13 @@ class InternalWindowEventFilter : public InputEventFilter { if (!internal) { return false; } + if (event->buttons() == Qt::NoButton) { + // update pointer window only if no button is pressed + input()->pointer()->update(); + } + if (!internal) { + return false; + } QMouseEvent e(event->type(), event->pos() - internal->position(), event->globalPos(), @@ -1534,7 +1541,7 @@ void InputDeviceHandler::updateInternalWindow(const QPointF &pos) if (!w->isVisible()) { continue; } - if (w->geometry().contains(pos.toPoint())) { + if ((*it)->geometry().contains(pos.toPoint())) { // check input mask const QRegion mask = w->mask().translated(w->geometry().topLeft()); if (!mask.isEmpty() && !mask.contains(pos.toPoint())) { diff --git a/plugins/qpa/window.cpp b/plugins/qpa/window.cpp index e5244c323a..e969577194 100644 --- a/plugins/qpa/window.cpp +++ b/plugins/qpa/window.cpp @@ -25,6 +25,7 @@ along with this program. If not, see . #include #include +#include #include #include @@ -103,6 +104,7 @@ void Window::setGeometry(const QRect &rect) wl_egl_window_resize(m_eglWaylandWindow, geometry().width(), geometry().height(), 0, 0); } #endif + QWindowSystemInterface::handleGeometryChange(window(), geometry()); } void Window::unmap() diff --git a/pointer_input.cpp b/pointer_input.cpp index 3b5df18aee..36f99a18a7 100644 --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -367,11 +367,14 @@ void PointerInputRedirection::update() if (!m_internalWindow) { updateDecoration(t, m_pos); } else { - // TODO: send hover leave to decoration + updateDecoration(waylandServer()->findClient(m_internalWindow), m_pos); if (m_decoration) { - m_decoration->client()->leaveEvent(); + disconnect(m_internalWindowConnection); + m_internalWindowConnection = QMetaObject::Connection(); + QEvent event(QEvent::Leave); + QCoreApplication::sendEvent(m_internalWindow.data(), &event); + m_internalWindow.clear(); } - m_decoration.clear(); } if (m_decoration || m_internalWindow) { t = nullptr; diff --git a/shell_client.cpp b/shell_client.cpp index 9e4a0a5920..a6c43a14a6 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -178,6 +178,7 @@ void ShellClient::init() if (m_internalWindow) { updateInternalWindowGeometry(); setOnAllDesktops(true); + updateDecoration(true); } else { doSetGeometry(QRect(QPoint(0, 0), m_clientSize)); setDesktop(VirtualDesktopManager::self()->current()); @@ -484,6 +485,13 @@ void ShellClient::doSetGeometry(const QRect &rect) if (!m_unmapped) { addWorkspaceRepaint(visibleRect()); } + if (m_internalWindow) { + const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()), + geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); + if (m_internalWindow->geometry() != windowRect) { + m_internalWindow->setGeometry(windowRect); + } + } triggerDecorationRepaint(); if (hasStrut()) { workspace()->updateClientArea(); @@ -526,6 +534,9 @@ void ShellClient::closeWindow() if (m_qtExtendedSurface && isCloseable()) { m_qtExtendedSurface->close(); } + if (m_internalWindow) { + m_internalWindow->hide(); + } } AbstractClient *ShellClient::findModal(bool allow_itself) @@ -542,6 +553,9 @@ bool ShellClient::isCloseable() const if (m_xdgShellSurface) { return true; } + if (m_internal) { + return true; + } return m_qtExtendedSurface ? true : false; } @@ -557,6 +571,9 @@ bool ShellClient::isFullScreen() const bool ShellClient::isMaximizable() const { + if (m_internal) { + return false; + } return true; } @@ -694,7 +711,7 @@ MaximizeMode ShellClient::maximizeMode() const bool ShellClient::noBorder() const { if (isInternal()) { - return true; + return m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); } if (m_serverDecoration) { if (m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { @@ -791,6 +808,9 @@ bool ShellClient::userCanSetNoBorder() const if (m_serverDecoration && m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { return !isFullScreen() && !isShade() && !tabGroup(); } + if (m_internal) { + return !m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); + } return false; } @@ -852,6 +872,7 @@ void ShellClient::findInternalWindow() continue; } m_internalWindow = w; + m_internalWindowFlags = m_internalWindow->flags(); connect(m_internalWindow, &QWindow::xChanged, this, &ShellClient::updateInternalWindowGeometry); connect(m_internalWindow, &QWindow::yChanged, this, &ShellClient::updateInternalWindowGeometry); connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; }); @@ -871,7 +892,8 @@ void ShellClient::updateInternalWindowGeometry() if (!m_internalWindow) { return; } - doSetGeometry(m_internalWindow->geometry()); + doSetGeometry(QRect(m_internalWindow->geometry().topLeft() - QPoint(borderLeft(), borderTop()), + m_internalWindow->geometry().size() + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); } bool ShellClient::isInternal() const @@ -907,6 +929,9 @@ void ShellClient::requestGeometry(const QRect &rect) m_xdgShellSurface->configure(xdgSurfaceStates(), size); } m_blockedRequestGeometry = QRect(); + if (m_internal) { + m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); + } } void ShellClient::clientFullScreenChanged(bool fullScreen) @@ -950,6 +975,9 @@ void ShellClient::resizeWithChecks(int w, int h, ForceGeometry_t force) if (m_xdgShellSurface) { m_xdgShellSurface->configure(xdgSurfaceStates(), QSize(w, h)); } + if (m_internal) { + m_internalWindow->setGeometry(QRect(pos() + QPoint(borderLeft(), borderTop()), QSize(w, h) - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); + } } void ShellClient::unmap() diff --git a/shell_client.h b/shell_client.h index 4f32b0347b..cabda7c2f2 100644 --- a/shell_client.h +++ b/shell_client.h @@ -170,6 +170,7 @@ private: bool m_closing = false; quint32 m_windowId = 0; QWindow *m_internalWindow = nullptr; + Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags(); bool m_unmapped = true; MaximizeMode m_maximizeMode = MaximizeRestore; QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize diff --git a/workspace.cpp b/workspace.cpp index a7f3961c6f..42c15c678f 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -1640,6 +1640,11 @@ AbstractClient *Workspace::findAbstractClient(std::functioninternalClients(), func)) { + return ret; + } + } return nullptr; }