2015-03-04 08:21:10 +00:00
|
|
|
/********************************************************************
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
|
|
|
#include "shell_client.h"
|
2015-05-27 08:16:46 +00:00
|
|
|
#include "composite.h"
|
2015-03-04 08:21:10 +00:00
|
|
|
#include "deleted.h"
|
2015-05-27 08:16:46 +00:00
|
|
|
#include "screens.h"
|
2015-03-04 08:21:10 +00:00
|
|
|
#include "wayland_server.h"
|
2015-05-27 08:16:46 +00:00
|
|
|
#include "workspace.h"
|
2015-03-16 08:14:04 +00:00
|
|
|
#include "virtualdesktops.h"
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2015-05-18 12:51:40 +00:00
|
|
|
#include <KWayland/Client/surface.h>
|
2015-03-04 08:21:10 +00:00
|
|
|
#include <KWayland/Server/shell_interface.h>
|
|
|
|
#include <KWayland/Server/surface_interface.h>
|
|
|
|
#include <KWayland/Server/buffer_interface.h>
|
|
|
|
|
2015-05-18 12:51:40 +00:00
|
|
|
#include <QWindow>
|
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
using namespace KWayland::Server;
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
ShellClient::ShellClient(ShellSurfaceInterface *surface)
|
2015-03-16 08:14:04 +00:00
|
|
|
: AbstractClient()
|
2015-03-04 08:21:10 +00:00
|
|
|
, m_shellSurface(surface)
|
|
|
|
{
|
|
|
|
setSurface(surface->surface());
|
2015-05-18 12:51:40 +00:00
|
|
|
findInternalWindow();
|
|
|
|
createWindowId();
|
2015-03-04 08:21:10 +00:00
|
|
|
setupCompositing();
|
|
|
|
if (surface->surface()->buffer()) {
|
|
|
|
setReadyForPainting();
|
|
|
|
m_clientSize = surface->surface()->buffer()->size();
|
|
|
|
} else {
|
|
|
|
ready_for_painting = false;
|
|
|
|
}
|
2015-05-18 12:51:40 +00:00
|
|
|
if (m_internalWindow) {
|
2015-05-20 06:27:48 +00:00
|
|
|
updateInternalWindowGeometry();
|
2015-05-18 12:51:40 +00:00
|
|
|
} else {
|
|
|
|
setGeometry(QRect(QPoint(0, 0), m_clientSize));
|
|
|
|
}
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2015-03-16 08:14:04 +00:00
|
|
|
setDesktop(VirtualDesktopManager::self()->current());
|
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
connect(surface->surface(), &SurfaceInterface::sizeChanged, this,
|
|
|
|
[this] {
|
|
|
|
m_clientSize = m_shellSurface->surface()->buffer()->size();
|
2015-05-18 12:50:10 +00:00
|
|
|
setGeometry(QRect(geom.topLeft(), m_clientSize));
|
2015-05-21 11:30:55 +00:00
|
|
|
discardWindowPixmap();
|
2015-03-04 08:21:10 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(surface, &ShellSurfaceInterface::destroyed, this, &ShellClient::destroyClient);
|
|
|
|
connect(surface->surface(), &SurfaceInterface::unmapped, this, &ShellClient::destroyClient);
|
2015-05-20 12:40:32 +00:00
|
|
|
connect(surface, &ShellSurfaceInterface::titleChanged, this, &ShellClient::captionChanged);
|
2015-03-04 08:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ShellClient::~ShellClient() = default;
|
|
|
|
|
|
|
|
void ShellClient::destroyClient()
|
|
|
|
{
|
2015-04-30 11:48:59 +00:00
|
|
|
m_closing = true;
|
2015-03-04 08:21:10 +00:00
|
|
|
Deleted *del = Deleted::create(this);
|
|
|
|
emit windowClosed(this, del);
|
|
|
|
waylandServer()->removeClient(this);
|
|
|
|
|
|
|
|
del->unrefWindow();
|
|
|
|
m_shellSurface = nullptr;
|
|
|
|
deleteClient(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::deleteClient(ShellClient *c)
|
|
|
|
{
|
|
|
|
delete c;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList ShellClient::activities() const
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPoint ShellClient::clientPos() const
|
|
|
|
{
|
|
|
|
return QPoint(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize ShellClient::clientSize() const
|
|
|
|
{
|
|
|
|
// TODO: connect for changes
|
|
|
|
return m_clientSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::debug(QDebug &stream) const
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
Q_UNUSED(stream)
|
|
|
|
}
|
|
|
|
|
|
|
|
Layer ShellClient::layer() const
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
return KWin::NormalLayer;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::shouldUnredirect() const
|
|
|
|
{
|
|
|
|
// TODO: unredirect for fullscreen
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRect ShellClient::transparentRect() const
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
return QRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
NET::WindowType ShellClient::windowType(bool direct, int supported_types) const
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
Q_UNUSED(direct)
|
|
|
|
Q_UNUSED(supported_types)
|
|
|
|
return NET::Normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ShellClient::opacity() const
|
|
|
|
{
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
2015-03-16 08:13:19 +00:00
|
|
|
void ShellClient::setOpacity(double opacity)
|
|
|
|
{
|
|
|
|
Q_UNUSED(opacity)
|
|
|
|
}
|
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
void ShellClient::addDamage(const QRegion &damage)
|
|
|
|
{
|
|
|
|
setReadyForPainting();
|
|
|
|
if (m_shellSurface->surface()->buffer()->size().isValid()) {
|
|
|
|
m_clientSize = m_shellSurface->surface()->buffer()->size();
|
2015-05-18 12:50:10 +00:00
|
|
|
setGeometry(QRect(geom.topLeft(), m_clientSize));
|
2015-03-04 08:21:10 +00:00
|
|
|
}
|
|
|
|
Toplevel::addDamage(damage);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setGeometry(const QRect &rect)
|
|
|
|
{
|
|
|
|
if (geom == rect) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const QRect old = geom;
|
|
|
|
geom = rect;
|
|
|
|
emit geometryChanged();
|
|
|
|
emit geometryShapeChanged(this, old);
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray ShellClient::windowRole() const
|
|
|
|
{
|
|
|
|
return QByteArray();
|
|
|
|
}
|
|
|
|
|
2015-03-16 08:14:04 +00:00
|
|
|
bool ShellClient::belongsToSameApplication(const AbstractClient *other, bool active_hack) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(active_hack)
|
|
|
|
if (auto s = other->surface()) {
|
|
|
|
return s->client() == surface()->client();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::blockActivityUpdates(bool b)
|
|
|
|
{
|
|
|
|
Q_UNUSED(b)
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ShellClient::caption(bool full, bool stripped) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(full)
|
|
|
|
Q_UNUSED(stripped)
|
2015-05-20 12:40:32 +00:00
|
|
|
return m_shellSurface->title();
|
2015-03-16 08:14:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::checkWorkspacePosition(QRect oldGeometry, int oldDesktop)
|
|
|
|
{
|
|
|
|
Q_UNUSED(oldGeometry)
|
|
|
|
Q_UNUSED(oldDesktop)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::closeWindow()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractClient *ShellClient::findModal(bool allow_itself)
|
|
|
|
{
|
|
|
|
Q_UNUSED(allow_itself)
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isCloseable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-21 13:59:27 +00:00
|
|
|
bool ShellClient::isFullScreenable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-16 08:14:04 +00:00
|
|
|
bool ShellClient::isFullScreen() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isMaximizable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isMinimizable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isMovable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isMovableAcrossScreens() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isResizable() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::isShown(bool shaded_is_shown) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(shaded_is_shown)
|
2015-04-30 11:48:59 +00:00
|
|
|
return !m_closing;
|
2015-03-16 08:14:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::maximize(MaximizeMode)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MaximizeMode ShellClient::maximizeMode() const
|
|
|
|
{
|
|
|
|
return KWin::MaximizeRestore;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::noBorder() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::performMouseCommand(Options::MouseCommand cmd, const QPoint &globalPos)
|
|
|
|
{
|
|
|
|
Q_UNUSED(cmd)
|
|
|
|
Q_UNUSED(globalPos)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const WindowRules *ShellClient::rules() const
|
|
|
|
{
|
|
|
|
static WindowRules s_rules;
|
|
|
|
return &s_rules;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::sendToScreen(int screen)
|
|
|
|
{
|
|
|
|
Q_UNUSED(screen)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setFullScreen(bool set, bool user)
|
|
|
|
{
|
|
|
|
Q_UNUSED(set)
|
|
|
|
Q_UNUSED(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setNoBorder(bool set)
|
|
|
|
{
|
|
|
|
Q_UNUSED(set)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setOnAllActivities(bool set)
|
|
|
|
{
|
|
|
|
Q_UNUSED(set)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setQuickTileMode(AbstractClient::QuickTileMode mode, bool keyboard)
|
|
|
|
{
|
|
|
|
Q_UNUSED(mode)
|
|
|
|
Q_UNUSED(keyboard)
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::setShortcut(const QString &cut)
|
|
|
|
{
|
|
|
|
Q_UNUSED(cut)
|
|
|
|
}
|
|
|
|
|
|
|
|
const QKeySequence &ShellClient::shortcut() const
|
|
|
|
{
|
|
|
|
static QKeySequence seq;
|
|
|
|
return seq;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::takeFocus()
|
|
|
|
{
|
|
|
|
setActive(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::updateWindowRules(Rules::Types selection)
|
|
|
|
{
|
|
|
|
Q_UNUSED(selection)
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::userCanSetFullScreen() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::userCanSetNoBorder() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShellClient::wantsInput() const
|
|
|
|
{
|
2015-05-21 08:39:10 +00:00
|
|
|
if (isInternal()) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-03-16 08:14:04 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-18 12:51:40 +00:00
|
|
|
void ShellClient::createWindowId()
|
|
|
|
{
|
|
|
|
if (m_internalWindow) {
|
|
|
|
m_windowId = m_internalWindow->winId();
|
2015-05-21 07:59:45 +00:00
|
|
|
} else {
|
|
|
|
m_windowId = waylandServer()->createWindowId(m_shellSurface->surface());
|
2015-05-18 12:51:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShellClient::findInternalWindow()
|
|
|
|
{
|
|
|
|
if (m_shellSurface->client() != waylandServer()->qtConnection()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const QWindowList windows = kwinApp()->topLevelWindows();
|
|
|
|
for (QWindow *w: windows) {
|
|
|
|
QScopedPointer<KWayland::Client::Surface> s(KWayland::Client::Surface::fromWindow(w));
|
|
|
|
if (!s) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (s->id() != surface()->id()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_internalWindow = w;
|
2015-05-20 06:27:48 +00:00
|
|
|
connect(m_internalWindow, &QWindow::xChanged, this, &ShellClient::updateInternalWindowGeometry);
|
2015-05-20 06:57:51 +00:00
|
|
|
connect(m_internalWindow, &QWindow::yChanged, this, &ShellClient::updateInternalWindowGeometry);
|
2015-05-18 12:51:40 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 06:27:48 +00:00
|
|
|
void ShellClient::updateInternalWindowGeometry()
|
|
|
|
{
|
|
|
|
if (!m_internalWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setGeometry(m_internalWindow->geometry());
|
|
|
|
}
|
|
|
|
|
2015-05-21 08:31:19 +00:00
|
|
|
bool ShellClient::isInternal() const
|
|
|
|
{
|
|
|
|
return m_shellSurface->client() == waylandServer()->internalConnection() ||
|
|
|
|
m_shellSurface->client() == waylandServer()->qtConnection();
|
|
|
|
}
|
|
|
|
|
2015-05-21 08:46:12 +00:00
|
|
|
xcb_window_t ShellClient::window() const
|
|
|
|
{
|
|
|
|
return windowId();
|
|
|
|
}
|
|
|
|
|
2015-05-27 08:16:46 +00:00
|
|
|
void ShellClient::move(int x, int y, ForceGeometry_t force)
|
|
|
|
{
|
|
|
|
QPoint p(x, y);
|
|
|
|
if (force == NormalGeometrySet && geom.topLeft() == p) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const QRect oldGeom = visibleRect();
|
|
|
|
geom.moveTopLeft(p);
|
|
|
|
updateWindowRules(Rules::Position);
|
|
|
|
screens()->setCurrent(this);
|
|
|
|
workspace()->updateStackingOrder();
|
|
|
|
if (Compositor::isCreated()) {
|
|
|
|
// TODO: is this really needed here?
|
|
|
|
Compositor::self()->checkUnredirect();
|
|
|
|
}
|
|
|
|
|
|
|
|
addLayerRepaint(oldGeom);
|
|
|
|
addLayerRepaint(visibleRect());
|
|
|
|
emit geometryChanged();
|
|
|
|
}
|
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
}
|