[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
This commit is contained in:
Martin Gräßlin 2016-05-09 14:48:10 +02:00
parent 18397c1028
commit 981b312323
7 changed files with 53 additions and 6 deletions

View file

@ -91,6 +91,7 @@ private:
HelperWindow::HelperWindow() HelperWindow::HelperWindow()
: QRasterWindow(nullptr) : QRasterWindow(nullptr)
{ {
setFlags(Qt::FramelessWindowHint);
} }
HelperWindow::~HelperWindow() = default; HelperWindow::~HelperWindow() = default;

View file

@ -430,6 +430,13 @@ class InternalWindowEventFilter : public InputEventFilter {
if (!internal) { if (!internal) {
return false; 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(), QMouseEvent e(event->type(),
event->pos() - internal->position(), event->pos() - internal->position(),
event->globalPos(), event->globalPos(),
@ -1534,7 +1541,7 @@ void InputDeviceHandler::updateInternalWindow(const QPointF &pos)
if (!w->isVisible()) { if (!w->isVisible()) {
continue; continue;
} }
if (w->geometry().contains(pos.toPoint())) { if ((*it)->geometry().contains(pos.toPoint())) {
// check input mask // check input mask
const QRegion mask = w->mask().translated(w->geometry().topLeft()); const QRegion mask = w->mask().translated(w->geometry().topLeft());
if (!mask.isEmpty() && !mask.contains(pos.toPoint())) { if (!mask.isEmpty() && !mask.contains(pos.toPoint())) {

View file

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <logging.h> #include <logging.h>
#include <QOpenGLFramebufferObject> #include <QOpenGLFramebufferObject>
#include <qpa/qwindowsysteminterface.h>
#include <KWayland/Client/buffer.h> #include <KWayland/Client/buffer.h>
#include <KWayland/Client/connection_thread.h> #include <KWayland/Client/connection_thread.h>
@ -103,6 +104,7 @@ void Window::setGeometry(const QRect &rect)
wl_egl_window_resize(m_eglWaylandWindow, geometry().width(), geometry().height(), 0, 0); wl_egl_window_resize(m_eglWaylandWindow, geometry().width(), geometry().height(), 0, 0);
} }
#endif #endif
QWindowSystemInterface::handleGeometryChange(window(), geometry());
} }
void Window::unmap() void Window::unmap()

View file

@ -367,11 +367,14 @@ void PointerInputRedirection::update()
if (!m_internalWindow) { if (!m_internalWindow) {
updateDecoration(t, m_pos); updateDecoration(t, m_pos);
} else { } else {
// TODO: send hover leave to decoration updateDecoration(waylandServer()->findClient(m_internalWindow), m_pos);
if (m_decoration) { 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) { if (m_decoration || m_internalWindow) {
t = nullptr; t = nullptr;

View file

@ -178,6 +178,7 @@ void ShellClient::init()
if (m_internalWindow) { if (m_internalWindow) {
updateInternalWindowGeometry(); updateInternalWindowGeometry();
setOnAllDesktops(true); setOnAllDesktops(true);
updateDecoration(true);
} else { } else {
doSetGeometry(QRect(QPoint(0, 0), m_clientSize)); doSetGeometry(QRect(QPoint(0, 0), m_clientSize));
setDesktop(VirtualDesktopManager::self()->current()); setDesktop(VirtualDesktopManager::self()->current());
@ -484,6 +485,13 @@ void ShellClient::doSetGeometry(const QRect &rect)
if (!m_unmapped) { if (!m_unmapped) {
addWorkspaceRepaint(visibleRect()); 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(); triggerDecorationRepaint();
if (hasStrut()) { if (hasStrut()) {
workspace()->updateClientArea(); workspace()->updateClientArea();
@ -526,6 +534,9 @@ void ShellClient::closeWindow()
if (m_qtExtendedSurface && isCloseable()) { if (m_qtExtendedSurface && isCloseable()) {
m_qtExtendedSurface->close(); m_qtExtendedSurface->close();
} }
if (m_internalWindow) {
m_internalWindow->hide();
}
} }
AbstractClient *ShellClient::findModal(bool allow_itself) AbstractClient *ShellClient::findModal(bool allow_itself)
@ -542,6 +553,9 @@ bool ShellClient::isCloseable() const
if (m_xdgShellSurface) { if (m_xdgShellSurface) {
return true; return true;
} }
if (m_internal) {
return true;
}
return m_qtExtendedSurface ? true : false; return m_qtExtendedSurface ? true : false;
} }
@ -557,6 +571,9 @@ bool ShellClient::isFullScreen() const
bool ShellClient::isMaximizable() const bool ShellClient::isMaximizable() const
{ {
if (m_internal) {
return false;
}
return true; return true;
} }
@ -694,7 +711,7 @@ MaximizeMode ShellClient::maximizeMode() const
bool ShellClient::noBorder() const bool ShellClient::noBorder() const
{ {
if (isInternal()) { if (isInternal()) {
return true; return m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup);
} }
if (m_serverDecoration) { if (m_serverDecoration) {
if (m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { if (m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) {
@ -791,6 +808,9 @@ bool ShellClient::userCanSetNoBorder() const
if (m_serverDecoration && m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { if (m_serverDecoration && m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) {
return !isFullScreen() && !isShade() && !tabGroup(); return !isFullScreen() && !isShade() && !tabGroup();
} }
if (m_internal) {
return !m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup);
}
return false; return false;
} }
@ -852,6 +872,7 @@ void ShellClient::findInternalWindow()
continue; continue;
} }
m_internalWindow = w; m_internalWindow = w;
m_internalWindowFlags = m_internalWindow->flags();
connect(m_internalWindow, &QWindow::xChanged, this, &ShellClient::updateInternalWindowGeometry); connect(m_internalWindow, &QWindow::xChanged, this, &ShellClient::updateInternalWindowGeometry);
connect(m_internalWindow, &QWindow::yChanged, this, &ShellClient::updateInternalWindowGeometry); connect(m_internalWindow, &QWindow::yChanged, this, &ShellClient::updateInternalWindowGeometry);
connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; }); connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; });
@ -871,7 +892,8 @@ void ShellClient::updateInternalWindowGeometry()
if (!m_internalWindow) { if (!m_internalWindow) {
return; 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 bool ShellClient::isInternal() const
@ -907,6 +929,9 @@ void ShellClient::requestGeometry(const QRect &rect)
m_xdgShellSurface->configure(xdgSurfaceStates(), size); m_xdgShellSurface->configure(xdgSurfaceStates(), size);
} }
m_blockedRequestGeometry = QRect(); 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) void ShellClient::clientFullScreenChanged(bool fullScreen)
@ -950,6 +975,9 @@ void ShellClient::resizeWithChecks(int w, int h, ForceGeometry_t force)
if (m_xdgShellSurface) { if (m_xdgShellSurface) {
m_xdgShellSurface->configure(xdgSurfaceStates(), QSize(w, h)); 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() void ShellClient::unmap()

View file

@ -170,6 +170,7 @@ private:
bool m_closing = false; bool m_closing = false;
quint32 m_windowId = 0; quint32 m_windowId = 0;
QWindow *m_internalWindow = nullptr; QWindow *m_internalWindow = nullptr;
Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags();
bool m_unmapped = true; bool m_unmapped = true;
MaximizeMode m_maximizeMode = MaximizeRestore; MaximizeMode m_maximizeMode = MaximizeRestore;
QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize

View file

@ -1640,6 +1640,11 @@ AbstractClient *Workspace::findAbstractClient(std::function<bool (const Abstract
if (Client *ret = Toplevel::findInList(desktops, func)) { if (Client *ret = Toplevel::findInList(desktops, func)) {
return ret; return ret;
} }
if (waylandServer()) {
if (AbstractClient *ret = Toplevel::findInList(waylandServer()->internalClients(), func)) {
return ret;
}
}
return nullptr; return nullptr;
} }