2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "toplevel.h"
|
|
|
|
|
2020-08-20 17:34:15 +00:00
|
|
|
#include "abstract_client.h"
|
2013-04-04 14:14:12 +00:00
|
|
|
#ifdef KWIN_BUILD_ACTIVITIES
|
|
|
|
#include "activities.h"
|
|
|
|
#endif
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "atoms.h"
|
2013-01-07 07:07:27 +00:00
|
|
|
#include "client_machine.h"
|
2019-06-22 10:00:56 +00:00
|
|
|
#include "composite.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "effects.h"
|
2013-04-03 10:19:27 +00:00
|
|
|
#include "screens.h"
|
2011-03-27 10:33:07 +00:00
|
|
|
#include "shadow.h"
|
2019-06-22 10:00:56 +00:00
|
|
|
#include "workspace.h"
|
2012-12-21 14:11:31 +00:00
|
|
|
#include "xcbutils.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
#include <KWaylandServer/surface_interface.h>
|
2015-02-24 09:54:28 +00:00
|
|
|
|
2013-09-02 11:14:39 +00:00
|
|
|
#include <QDebug>
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2013-05-08 11:39:06 +00:00
|
|
|
Toplevel::Toplevel()
|
2014-04-25 10:06:39 +00:00
|
|
|
: m_visual(XCB_NONE)
|
2015-06-01 14:25:21 +00:00
|
|
|
, bit_depth(24)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, info(nullptr)
|
2019-09-15 14:59:40 +00:00
|
|
|
, ready_for_painting(false)
|
2012-11-15 06:48:08 +00:00
|
|
|
, m_isDamaged(false)
|
2018-11-18 19:13:55 +00:00
|
|
|
, m_internalId(QUuid::createUuid())
|
2013-09-10 05:09:44 +00:00
|
|
|
, m_client()
|
2019-09-06 14:30:26 +00:00
|
|
|
, damage_handle(XCB_NONE)
|
2011-01-30 14:34:42 +00:00
|
|
|
, is_shape(false)
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
, effect_window(nullptr)
|
2013-01-07 07:07:27 +00:00
|
|
|
, m_clientMachine(new ClientMachine(this))
|
2019-09-06 14:30:26 +00:00
|
|
|
, m_wmClientLeader(XCB_WINDOW_NONE)
|
2012-03-28 18:29:33 +00:00
|
|
|
, m_damageReplyPending(false)
|
2013-03-26 06:45:08 +00:00
|
|
|
, m_screen(0)
|
2014-01-24 11:34:16 +00:00
|
|
|
, m_skipCloseAnimation(false)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-08-23 11:42:59 +00:00
|
|
|
connect(this, SIGNAL(damaged(KWin::Toplevel*,QRect)), SIGNAL(needsRepaint()));
|
2013-04-03 10:19:27 +00:00
|
|
|
connect(screens(), SIGNAL(changed()), SLOT(checkScreen()));
|
2013-05-10 20:03:59 +00:00
|
|
|
connect(screens(), SIGNAL(countChanged(int,int)), SLOT(checkScreen()));
|
2013-03-26 06:45:08 +00:00
|
|
|
setupCheckScreenConnection();
|
2020-07-14 11:34:25 +00:00
|
|
|
connect(this, &Toplevel::bufferGeometryChanged, this, &Toplevel::inputTransformationChanged);
|
2020-02-05 09:28:50 +00:00
|
|
|
|
|
|
|
// Only for compatibility reasons, drop in the next major release.
|
|
|
|
connect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::geometryChanged);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
Toplevel::~Toplevel()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2019-09-06 14:30:26 +00:00
|
|
|
Q_ASSERT(damage_handle == XCB_NONE);
|
2007-04-29 17:35:43 +00:00
|
|
|
delete info;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-20 17:34:15 +00:00
|
|
|
QDebug operator<<(QDebug debug, const Toplevel *toplevel)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-08-20 17:34:15 +00:00
|
|
|
QDebugStateSaver saver(debug);
|
|
|
|
debug.nospace();
|
|
|
|
if (toplevel) {
|
|
|
|
debug << toplevel->metaObject()->className() << '(' << static_cast<const void *>(toplevel);
|
|
|
|
debug << ", windowId=0x" << Qt::hex << toplevel->windowId() << Qt::dec;
|
|
|
|
if (const KWaylandServer::SurfaceInterface *surface = toplevel->surface()) {
|
|
|
|
debug << ", surface=" << surface;
|
|
|
|
}
|
|
|
|
const AbstractClient *client = qobject_cast<const AbstractClient *>(toplevel);
|
|
|
|
if (client) {
|
|
|
|
if (!client->isPopupWindow()) {
|
|
|
|
debug << ", caption=" << client->caption();
|
|
|
|
}
|
|
|
|
if (client->transientFor()) {
|
|
|
|
debug << ", transientFor=" << client->transientFor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (debug.verbosity() > 2) {
|
|
|
|
debug << ", frameGeometry=" << toplevel->frameGeometry();
|
|
|
|
debug << ", resourceName=" << toplevel->resourceName();
|
|
|
|
debug << ", resourceClass=" << toplevel->resourceClass();
|
|
|
|
}
|
|
|
|
debug << ')';
|
|
|
|
} else {
|
|
|
|
debug << "Toplevel(0x0)";
|
|
|
|
}
|
|
|
|
return debug;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-09-06 14:30:26 +00:00
|
|
|
void Toplevel::detectShape(xcb_window_t id)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-01-15 10:03:15 +00:00
|
|
|
const bool wasShape = is_shape;
|
2012-12-21 14:11:31 +00:00
|
|
|
is_shape = Xcb::Extensions::self()->hasShape(id);
|
2012-01-15 10:03:15 +00:00
|
|
|
if (wasShape != is_shape) {
|
|
|
|
emit shapedChanged();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
// used only by Deleted::copy()
|
2011-01-30 14:34:42 +00:00
|
|
|
void Toplevel::copyToDeleted(Toplevel* c)
|
|
|
|
{
|
2018-11-18 19:13:55 +00:00
|
|
|
m_internalId = c->internalId();
|
2019-12-04 13:18:34 +00:00
|
|
|
m_frameGeometry = c->m_frameGeometry;
|
2020-06-01 10:43:49 +00:00
|
|
|
m_clientGeometry = c->m_clientGeometry;
|
2014-04-25 10:06:39 +00:00
|
|
|
m_visual = c->m_visual;
|
2007-04-29 17:35:43 +00:00
|
|
|
bit_depth = c->bit_depth;
|
|
|
|
info = c->info;
|
2013-09-10 05:09:44 +00:00
|
|
|
m_client.reset(c->m_client, false);
|
2007-06-25 08:51:44 +00:00
|
|
|
ready_for_painting = c->ready_for_painting;
|
2019-09-06 14:30:26 +00:00
|
|
|
damage_handle = XCB_NONE;
|
2007-04-29 17:35:43 +00:00
|
|
|
damage_region = c->damage_region;
|
|
|
|
repaints_region = c->repaints_region;
|
2019-02-06 14:09:25 +00:00
|
|
|
layer_repaints_region = c->layer_repaints_region;
|
2007-04-29 17:35:43 +00:00
|
|
|
is_shape = c->is_shape;
|
|
|
|
effect_window = c->effect_window;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
if (effect_window != nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
effect_window->setWindow(this);
|
2007-04-29 17:35:43 +00:00
|
|
|
resource_name = c->resourceName();
|
|
|
|
resource_class = c->resourceClass();
|
2013-01-07 07:07:27 +00:00
|
|
|
m_clientMachine = c->m_clientMachine;
|
|
|
|
m_clientMachine->setParent(this);
|
2019-09-06 14:30:26 +00:00
|
|
|
m_wmClientLeader = c->wmClientLeader();
|
2011-10-22 09:02:49 +00:00
|
|
|
opaque_region = c->opaqueRegion();
|
2013-03-26 06:45:08 +00:00
|
|
|
m_screen = c->m_screen;
|
2014-01-24 11:34:16 +00:00
|
|
|
m_skipCloseAnimation = c->m_skipCloseAnimation;
|
2015-08-18 12:40:26 +00:00
|
|
|
m_internalFBO = c->m_internalFBO;
|
2019-09-29 10:31:08 +00:00
|
|
|
m_internalImage = c->m_internalImage;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
// before being deleted, remove references to everything that's now
|
|
|
|
// owner by Deleted
|
|
|
|
void Toplevel::disownDataPassedToDeleted()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
info = nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2009-06-11 20:12:11 +00:00
|
|
|
QRect Toplevel::visibleRect() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2019-09-30 08:30:04 +00:00
|
|
|
// There's no strict order between frame geometry and buffer geometry.
|
|
|
|
QRect rect = frameGeometry() | bufferGeometry();
|
|
|
|
|
2019-09-29 11:15:18 +00:00
|
|
|
if (shadow() && !shadow()->shadowRegion().isEmpty()) {
|
2019-09-30 08:30:04 +00:00
|
|
|
rect |= shadow()->shadowRegion().boundingRect().translated(pos());
|
2011-03-27 10:33:07 +00:00
|
|
|
}
|
2019-09-30 08:30:04 +00:00
|
|
|
|
|
|
|
return rect;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-06-11 20:12:11 +00:00
|
|
|
|
2015-01-15 13:33:28 +00:00
|
|
|
Xcb::Property Toplevel::fetchWmClientLeader() const
|
|
|
|
{
|
|
|
|
return Xcb::Property(false, window(), atoms->wm_client_leader, XCB_ATOM_WINDOW, 0, 10000);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::readWmClientLeader(Xcb::Property &prop)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2019-09-06 14:30:26 +00:00
|
|
|
m_wmClientLeader = prop.value<xcb_window_t>(window());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2015-01-15 13:33:28 +00:00
|
|
|
void Toplevel::getWmClientLeader()
|
|
|
|
{
|
|
|
|
auto prop = fetchWmClientLeader();
|
|
|
|
readWmClientLeader(prop);
|
|
|
|
}
|
|
|
|
|
2019-02-02 18:17:44 +00:00
|
|
|
/**
|
|
|
|
* Returns sessionId for this client,
|
|
|
|
* taken either from its window or from the leader window.
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2012-04-12 19:52:44 +00:00
|
|
|
QByteArray Toplevel::sessionId() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-04-15 08:09:25 +00:00
|
|
|
QByteArray result = Xcb::StringProperty(window(), atoms->sm_client_id);
|
2019-09-06 14:30:26 +00:00
|
|
|
if (result.isEmpty() && m_wmClientLeader && m_wmClientLeader != window()) {
|
|
|
|
result = Xcb::StringProperty(m_wmClientLeader, atoms->sm_client_id);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
return result;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-02-02 18:17:44 +00:00
|
|
|
/**
|
|
|
|
* Returns command property for this client,
|
|
|
|
* taken either from its window or from the leader window.
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2016-06-23 17:40:40 +00:00
|
|
|
QByteArray Toplevel::wmCommand()
|
|
|
|
{
|
|
|
|
QByteArray result = Xcb::StringProperty(window(), XCB_ATOM_WM_COMMAND);
|
2019-09-06 14:30:26 +00:00
|
|
|
if (result.isEmpty() && m_wmClientLeader && m_wmClientLeader != window()) {
|
|
|
|
result = Xcb::StringProperty(m_wmClientLeader, XCB_ATOM_WM_COMMAND);
|
|
|
|
}
|
2016-06-23 17:40:40 +00:00
|
|
|
result.replace(0, ' ');
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
void Toplevel::getWmClientMachine()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-01-07 07:07:27 +00:00
|
|
|
m_clientMachine->resolve(window(), wmClientLeader());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-02-02 18:17:44 +00:00
|
|
|
/**
|
|
|
|
* Returns client machine for this client,
|
|
|
|
* taken either from its window or from the leader window.
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2011-01-30 14:34:42 +00:00
|
|
|
QByteArray Toplevel::wmClientMachine(bool use_localhost) const
|
|
|
|
{
|
2013-01-07 07:07:27 +00:00
|
|
|
if (!m_clientMachine) {
|
|
|
|
// this should never happen
|
|
|
|
return QByteArray();
|
|
|
|
}
|
|
|
|
if (use_localhost && m_clientMachine->isLocal()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
// special name for the local machine (localhost)
|
2013-01-07 07:07:27 +00:00
|
|
|
return ClientMachine::localhost();
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2013-01-07 07:07:27 +00:00
|
|
|
return m_clientMachine->hostName();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-02-02 18:17:44 +00:00
|
|
|
/**
|
|
|
|
* Returns client leader window for this client.
|
|
|
|
* Returns the client window itself if no leader window is defined.
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2019-09-06 14:30:26 +00:00
|
|
|
xcb_window_t Toplevel::wmClientLeader() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2019-09-06 14:30:26 +00:00
|
|
|
if (m_wmClientLeader != XCB_WINDOW_NONE) {
|
|
|
|
return m_wmClientLeader;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
return window();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void Toplevel::getResourceClass()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-20 07:37:36 +00:00
|
|
|
setResourceClass(QByteArray(info->windowClassName()).toLower(), QByteArray(info->windowClassClass()).toLower());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::setResourceClass(const QByteArray &name, const QByteArray &className)
|
|
|
|
{
|
|
|
|
resource_name = name;
|
|
|
|
resource_class = className;
|
2014-04-11 06:06:26 +00:00
|
|
|
emit windowClassChanged();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-12-03 10:14:43 +00:00
|
|
|
bool Toplevel::resourceMatch(const Toplevel *c1, const Toplevel *c2)
|
|
|
|
{
|
|
|
|
return c1->resourceClass() == c2->resourceClass();
|
|
|
|
}
|
|
|
|
|
2007-09-03 15:00:43 +00:00
|
|
|
double Toplevel::opacity() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return 1.0;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
if (info->opacity() == 0xffffffff)
|
2007-04-29 17:35:43 +00:00
|
|
|
return 1.0;
|
|
|
|
return info->opacity() * 1.0 / 0xffffffff;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void Toplevel::setOpacity(double new_opacity)
|
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-09-03 15:00:43 +00:00
|
|
|
double old_opacity = opacity();
|
2011-01-30 14:34:42 +00:00
|
|
|
new_opacity = qBound(0.0, new_opacity, 1.0);
|
|
|
|
if (old_opacity == new_opacity)
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
info->setOpacity(static_cast< unsigned long >(new_opacity * 0xffffffff));
|
|
|
|
if (compositing()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
addRepaintFull();
|
2011-03-06 09:30:23 +00:00
|
|
|
emit opacityChanged(this, old_opacity);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-06-22 10:00:56 +00:00
|
|
|
bool Toplevel::setupCompositing()
|
|
|
|
{
|
|
|
|
if (!compositing())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (damage_handle != XCB_NONE)
|
|
|
|
return false;
|
|
|
|
|
2019-12-02 17:36:13 +00:00
|
|
|
if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) {
|
2019-06-22 10:00:56 +00:00
|
|
|
damage_handle = xcb_generate_id(connection());
|
2019-12-02 17:36:13 +00:00
|
|
|
xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2019-12-02 17:36:13 +00:00
|
|
|
damage_region = QRegion(0, 0, width(), height());
|
2019-06-22 10:00:56 +00:00
|
|
|
effect_window = new EffectWindowImpl(this);
|
|
|
|
|
|
|
|
Compositor::self()->scene()->addToplevel(this);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::finishCompositing(ReleaseReason releaseReason)
|
|
|
|
{
|
|
|
|
if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE)
|
|
|
|
return;
|
|
|
|
if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data
|
|
|
|
discardWindowPixmap();
|
|
|
|
delete effect_window;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (damage_handle != XCB_NONE &&
|
|
|
|
releaseReason != ReleaseReason::Destroyed) {
|
|
|
|
xcb_damage_destroy(connection(), damage_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
damage_handle = XCB_NONE;
|
|
|
|
damage_region = QRegion();
|
|
|
|
repaints_region = QRegion();
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
effect_window = nullptr;
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::discardWindowPixmap()
|
|
|
|
{
|
|
|
|
addDamageFull();
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
if (effectWindow() != nullptr && effectWindow()->sceneWindow() != nullptr)
|
[x11] Fix visual artifacts during interactive resize
Summary:
When a window is being interactively resized, its contents may jump. The
reason why that happens is because KWin renders partially resized client
window. Composite extension spec says that a window will get a new pixmap
each time it is resized or mapped. This applies to the frame window, but
not to the client window itself. If the client window is resized,
off-screen storage for the frame window won't be reallocated. Therefore,
KWin may render partially resized client window if the client doesn't
attempt to be in sync with our rendering loop. Currently, the only way
to do that is to use extended frame counters, which are not supported by
KWin.
So, in order to fix visual artifacts during interactive resize, we need
somehow forcefully re-allocate off-screen storage for the frame window.
Unfortunately, Composite extension doesn't provide any request to do
that, so the only option we have is to resize the frame window.
BUG: 415839
FIXED-IN: 5.18.0
Reviewers: #kwin
Subscribers: davidedmundson, ngraham, alexde, fredrik, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D26914
2020-02-03 11:29:43 +00:00
|
|
|
effectWindow()->sceneWindow()->discardPixmap();
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::damageNotifyEvent()
|
|
|
|
{
|
|
|
|
m_isDamaged = true;
|
|
|
|
|
|
|
|
// Note: The rect is supposed to specify the damage extents,
|
|
|
|
// but we don't know it at this point. No one who connects
|
|
|
|
// to this signal uses the rect however.
|
|
|
|
emit damaged(this, QRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Toplevel::compositing() const
|
|
|
|
{
|
|
|
|
if (!Workspace::self()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Workspace::self()->compositing();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Toplevel::resetAndFetchDamage()
|
|
|
|
{
|
|
|
|
if (!m_isDamaged)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (damage_handle == XCB_NONE) {
|
|
|
|
m_isDamaged = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_connection_t *conn = connection();
|
|
|
|
|
|
|
|
// Create a new region and copy the damage region to it,
|
|
|
|
// resetting the damaged state.
|
|
|
|
xcb_xfixes_region_t region = xcb_generate_id(conn);
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
xcb_xfixes_create_region(conn, region, 0, nullptr);
|
2019-06-22 10:00:56 +00:00
|
|
|
xcb_damage_subtract(conn, damage_handle, 0, region);
|
|
|
|
|
|
|
|
// Send a fetch-region request and destroy the region
|
|
|
|
m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region);
|
|
|
|
xcb_xfixes_destroy_region(conn, region);
|
|
|
|
|
|
|
|
m_isDamaged = false;
|
|
|
|
m_damageReplyPending = true;
|
|
|
|
|
|
|
|
return m_damageReplyPending;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::getDamageRegionReply()
|
|
|
|
{
|
|
|
|
if (!m_damageReplyPending)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_damageReplyPending = false;
|
|
|
|
|
|
|
|
// Get the fetch-region reply
|
|
|
|
xcb_xfixes_fetch_region_reply_t *reply =
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, nullptr);
|
2019-06-22 10:00:56 +00:00
|
|
|
|
|
|
|
if (!reply)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Convert the reply to a QRegion
|
|
|
|
int count = xcb_xfixes_fetch_region_rectangles_length(reply);
|
|
|
|
QRegion region;
|
|
|
|
|
|
|
|
if (count > 1 && count < 16) {
|
|
|
|
xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply);
|
|
|
|
|
|
|
|
QVector<QRect> qrects;
|
|
|
|
qrects.reserve(count);
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
|
|
|
|
|
|
|
|
region.setRects(qrects.constData(), count);
|
|
|
|
} else
|
|
|
|
region += QRect(reply->extents.x, reply->extents.y,
|
|
|
|
reply->extents.width, reply->extents.height);
|
|
|
|
|
[x11] Add support for _GTK_FRAME_EXTENTS
Summary:
KDE is known for having a strong view on the client-side decorations vs
server-side decorations issue. The main argument raised against CSD is
that desktop will look less consistent when clients start drawing window
decorations by themselves, which is somewhat true. It all ties to how
well each toolkit is integrated with the desktop environment.
KDE doesn't control the desktop market on Linux. Another big "player"
is GNOME. Both KDE and GNOME have very polarized views on in which
direction desktop should move forward. The KDE community is pushing more
toward server-side decorations while the GNOME community is pushing
more toward client-side decorations. Both communities have developed
great applications and it's not rare to see a GNOME application being
used in KDE Plasma. The only problem is that these different views are
not left behind the curtain and our users pay the price. Resizing GTK
clients in Plasma became practically impossible due to resize borders
having small hit area.
When a client draws its window decoration, it's more likely that it also
draws the drop-shadow around the decoration. The compositor must know
the extents of the shadow so things like snapping and so on work as
expected. And here lies the problem... While the xdg-shell protocol has
a way to specify such things, the NetWM spec doesn't have anything like
that. There's _GTK_FRAME_EXTENTS in the wild, however the problem with
it is that it's a proprietary atom, which is specific only to GTK apps.
Due to that, _GTK_FRAME_EXTENTS wasn't implemented because implementing
anything like that would require major changes in how we think about
geometry.
Recent xdg-shell window geometry patches adjusted geometry abstractions
in kwin to such a degree that it's very easy to add support for client
side decorated clients on X11. We just have to make sure that the
X11Client class provides correct buffer geometry and frame geometry when
the gtk frame extents are set.
Even though the X11 code is feature frozen, I still think it's worth
to have _GTK_FRAME_EXTENTS support in kwin because it will fix the resize
issues. Also, because KWin/Wayland is unfortunately far from becoming
default, it will help us with testing some implementation bits of the
window geometry from xdg-shell.
BUG: 390550
FIXED-IN: 5.18.0
Test Plan:
Things like quick tiling, maximizing, tiling scripts and so on work as
expected with GTK clients.
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: cblack, trmdi, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24660
2019-10-08 08:46:59 +00:00
|
|
|
const QRect bufferRect = bufferGeometry();
|
|
|
|
const QRect frameRect = frameGeometry();
|
|
|
|
|
2019-06-22 10:00:56 +00:00
|
|
|
damage_region += region;
|
[x11] Add support for _GTK_FRAME_EXTENTS
Summary:
KDE is known for having a strong view on the client-side decorations vs
server-side decorations issue. The main argument raised against CSD is
that desktop will look less consistent when clients start drawing window
decorations by themselves, which is somewhat true. It all ties to how
well each toolkit is integrated with the desktop environment.
KDE doesn't control the desktop market on Linux. Another big "player"
is GNOME. Both KDE and GNOME have very polarized views on in which
direction desktop should move forward. The KDE community is pushing more
toward server-side decorations while the GNOME community is pushing
more toward client-side decorations. Both communities have developed
great applications and it's not rare to see a GNOME application being
used in KDE Plasma. The only problem is that these different views are
not left behind the curtain and our users pay the price. Resizing GTK
clients in Plasma became practically impossible due to resize borders
having small hit area.
When a client draws its window decoration, it's more likely that it also
draws the drop-shadow around the decoration. The compositor must know
the extents of the shadow so things like snapping and so on work as
expected. And here lies the problem... While the xdg-shell protocol has
a way to specify such things, the NetWM spec doesn't have anything like
that. There's _GTK_FRAME_EXTENTS in the wild, however the problem with
it is that it's a proprietary atom, which is specific only to GTK apps.
Due to that, _GTK_FRAME_EXTENTS wasn't implemented because implementing
anything like that would require major changes in how we think about
geometry.
Recent xdg-shell window geometry patches adjusted geometry abstractions
in kwin to such a degree that it's very easy to add support for client
side decorated clients on X11. We just have to make sure that the
X11Client class provides correct buffer geometry and frame geometry when
the gtk frame extents are set.
Even though the X11 code is feature frozen, I still think it's worth
to have _GTK_FRAME_EXTENTS support in kwin because it will fix the resize
issues. Also, because KWin/Wayland is unfortunately far from becoming
default, it will help us with testing some implementation bits of the
window geometry from xdg-shell.
BUG: 390550
FIXED-IN: 5.18.0
Test Plan:
Things like quick tiling, maximizing, tiling scripts and so on work as
expected with GTK clients.
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: cblack, trmdi, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24660
2019-10-08 08:46:59 +00:00
|
|
|
repaints_region += region.translated(bufferRect.topLeft() - frameRect.topLeft());
|
2019-06-22 10:00:56 +00:00
|
|
|
|
|
|
|
free(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addDamageFull()
|
|
|
|
{
|
|
|
|
if (!compositing())
|
|
|
|
return;
|
|
|
|
|
2019-09-30 09:28:07 +00:00
|
|
|
const QRect bufferRect = bufferGeometry();
|
|
|
|
const QRect frameRect = frameGeometry();
|
2019-06-22 10:00:56 +00:00
|
|
|
|
2019-09-30 09:28:07 +00:00
|
|
|
const int offsetX = bufferRect.x() - frameRect.x();
|
|
|
|
const int offsetY = bufferRect.y() - frameRect.y();
|
|
|
|
|
|
|
|
const QRect damagedRect = QRect(0, 0, bufferRect.width(), bufferRect.height());
|
|
|
|
|
|
|
|
damage_region = damagedRect;
|
|
|
|
repaints_region |= damagedRect.translated(offsetX, offsetY);
|
|
|
|
|
|
|
|
emit damaged(this, damagedRect);
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::resetDamage()
|
|
|
|
{
|
|
|
|
damage_region = QRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addRepaint(const QRect& r)
|
|
|
|
{
|
|
|
|
if (!compositing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
repaints_region += r;
|
|
|
|
emit needsRepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
QRect r(x, y, w, h);
|
|
|
|
addRepaint(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addRepaint(const QRegion& r)
|
|
|
|
{
|
|
|
|
if (!compositing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
repaints_region += r;
|
|
|
|
emit needsRepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addLayerRepaint(const QRect& r)
|
|
|
|
{
|
|
|
|
if (!compositing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
layer_repaints_region += r;
|
|
|
|
emit needsRepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addLayerRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
QRect r(x, y, w, h);
|
|
|
|
addLayerRepaint(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addLayerRepaint(const QRegion& r)
|
|
|
|
{
|
|
|
|
if (!compositing())
|
|
|
|
return;
|
|
|
|
layer_repaints_region += r;
|
|
|
|
emit needsRepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addRepaintFull()
|
|
|
|
{
|
|
|
|
repaints_region = visibleRect().translated(-pos());
|
|
|
|
emit needsRepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::resetRepaints()
|
|
|
|
{
|
|
|
|
repaints_region = QRegion();
|
|
|
|
layer_repaints_region = QRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
addWorkspaceRepaint(QRect(x, y, w, h));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addWorkspaceRepaint(const QRect& r2)
|
|
|
|
{
|
|
|
|
if (!compositing())
|
|
|
|
return;
|
|
|
|
Compositor::self()->addRepaint(r2);
|
|
|
|
}
|
|
|
|
|
2012-01-24 16:00:40 +00:00
|
|
|
void Toplevel::setReadyForPainting()
|
|
|
|
{
|
|
|
|
if (!ready_for_painting) {
|
|
|
|
ready_for_painting = true;
|
|
|
|
if (compositing()) {
|
|
|
|
addRepaintFull();
|
|
|
|
emit windowShown(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-23 14:41:27 +00:00
|
|
|
void Toplevel::deleteEffectWindow()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-05-23 14:41:27 +00:00
|
|
|
delete effect_window;
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
effect_window = nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-05-23 14:41:27 +00:00
|
|
|
|
2013-03-26 06:45:08 +00:00
|
|
|
void Toplevel::checkScreen()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-03 10:19:27 +00:00
|
|
|
if (screens()->count() == 1) {
|
2013-03-26 06:45:08 +00:00
|
|
|
if (m_screen != 0) {
|
|
|
|
m_screen = 0;
|
|
|
|
emit screenChanged();
|
|
|
|
}
|
2017-11-01 17:54:21 +00:00
|
|
|
} else {
|
2019-09-27 10:01:10 +00:00
|
|
|
const int s = screens()->number(frameGeometry().center());
|
2017-11-01 17:54:21 +00:00
|
|
|
if (s != m_screen) {
|
|
|
|
m_screen = s;
|
|
|
|
emit screenChanged();
|
|
|
|
}
|
2008-06-09 16:09:56 +00:00
|
|
|
}
|
2017-11-01 17:54:21 +00:00
|
|
|
qreal newScale = screens()->scale(m_screen);
|
|
|
|
if (newScale != m_screenScale) {
|
|
|
|
m_screenScale = newScale;
|
|
|
|
emit screenScaleChanged();
|
2013-03-26 06:45:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::setupCheckScreenConnection()
|
|
|
|
{
|
2020-02-05 09:28:50 +00:00
|
|
|
connect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkScreen);
|
2013-03-26 06:45:08 +00:00
|
|
|
checkScreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::removeCheckScreenConnection()
|
|
|
|
{
|
2020-02-05 09:28:50 +00:00
|
|
|
disconnect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkScreen);
|
2013-03-26 06:45:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Toplevel::screen() const
|
|
|
|
{
|
|
|
|
return m_screen;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-09 16:09:56 +00:00
|
|
|
|
2017-11-01 17:54:21 +00:00
|
|
|
qreal Toplevel::screenScale() const
|
|
|
|
{
|
|
|
|
return m_screenScale;
|
|
|
|
}
|
|
|
|
|
2019-08-26 07:44:04 +00:00
|
|
|
qreal Toplevel::bufferScale() const
|
|
|
|
{
|
2020-06-19 07:20:57 +00:00
|
|
|
return surface() ? surface()->bufferScale() : 1;
|
2019-08-26 07:44:04 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool Toplevel::isOnScreen(int screen) const
|
|
|
|
{
|
2019-09-27 10:01:10 +00:00
|
|
|
return screens()->geometry(screen).intersects(frameGeometry());
|
2013-04-03 10:19:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Toplevel::isOnActiveScreen() const
|
|
|
|
{
|
|
|
|
return isOnScreen(screens()->current());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-09 16:09:56 +00:00
|
|
|
|
2019-09-29 11:26:04 +00:00
|
|
|
void Toplevel::updateShadow()
|
2011-03-27 10:33:07 +00:00
|
|
|
{
|
2011-07-02 19:39:01 +00:00
|
|
|
QRect dirtyRect; // old & new shadow region
|
2012-03-24 21:42:29 +00:00
|
|
|
const QRect oldVisibleRect = visibleRect();
|
2019-09-29 11:15:18 +00:00
|
|
|
if (shadow()) {
|
2011-07-02 19:39:01 +00:00
|
|
|
dirtyRect = shadow()->shadowRegion().boundingRect();
|
2018-12-06 12:54:27 +00:00
|
|
|
if (!effectWindow()->sceneWindow()->shadow()->updateShadow()) {
|
|
|
|
effectWindow()->sceneWindow()->updateShadow(nullptr);
|
|
|
|
}
|
|
|
|
emit shadowChanged();
|
2011-03-27 10:33:07 +00:00
|
|
|
} else {
|
2011-04-03 09:31:33 +00:00
|
|
|
Shadow::createShadow(this);
|
2011-07-02 19:39:01 +00:00
|
|
|
}
|
2019-09-29 11:15:18 +00:00
|
|
|
if (shadow())
|
2011-07-02 19:39:01 +00:00
|
|
|
dirtyRect |= shadow()->shadowRegion().boundingRect();
|
2012-03-24 21:42:29 +00:00
|
|
|
if (oldVisibleRect != visibleRect())
|
|
|
|
emit paddingChanged(this, oldVisibleRect);
|
2011-07-02 19:39:01 +00:00
|
|
|
if (dirtyRect.isValid()) {
|
|
|
|
dirtyRect.translate(pos());
|
2012-03-16 17:53:19 +00:00
|
|
|
addLayerRepaint(dirtyRect);
|
2011-03-27 10:33:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-03 09:31:33 +00:00
|
|
|
Shadow *Toplevel::shadow()
|
2011-03-27 10:33:07 +00:00
|
|
|
{
|
2011-04-03 09:31:33 +00:00
|
|
|
if (effectWindow() && effectWindow()->sceneWindow()) {
|
|
|
|
return effectWindow()->sceneWindow()->shadow();
|
|
|
|
} else {
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
return nullptr;
|
2011-04-03 09:31:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const Shadow *Toplevel::shadow() const
|
|
|
|
{
|
|
|
|
if (effectWindow() && effectWindow()->sceneWindow()) {
|
|
|
|
return effectWindow()->sceneWindow()->shadow();
|
|
|
|
} else {
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
return nullptr;
|
2011-04-03 09:31:33 +00:00
|
|
|
}
|
2011-03-27 10:33:07 +00:00
|
|
|
}
|
2008-06-09 16:09:56 +00:00
|
|
|
|
2014-07-24 06:55:57 +00:00
|
|
|
bool Toplevel::wantsShadowToBeRendered() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-10-22 09:02:49 +00:00
|
|
|
void Toplevel::getWmOpaqueRegion()
|
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-22 14:46:12 +00:00
|
|
|
const auto rects = info->opaqueRegion();
|
2011-10-22 09:02:49 +00:00
|
|
|
QRegion new_opaque_region;
|
2015-01-22 14:46:12 +00:00
|
|
|
for (const auto &r : rects) {
|
|
|
|
new_opaque_region += QRect(r.pos.x, r.pos.y, r.size.width, r.size.height);
|
|
|
|
}
|
2011-10-22 09:02:49 +00:00
|
|
|
|
|
|
|
opaque_region = new_opaque_region;
|
|
|
|
}
|
|
|
|
|
2012-01-15 09:51:09 +00:00
|
|
|
bool Toplevel::isClient() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Toplevel::isDeleted() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-04-04 14:14:12 +00:00
|
|
|
bool Toplevel::isOnCurrentActivity() const
|
|
|
|
{
|
|
|
|
#ifdef KWIN_BUILD_ACTIVITIES
|
2015-07-07 09:48:42 +00:00
|
|
|
if (!Activities::self()) {
|
|
|
|
return true;
|
|
|
|
}
|
2013-04-04 14:14:12 +00:00
|
|
|
return isOnActivity(Activities::self()->current());
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-04-24 08:46:34 +00:00
|
|
|
void Toplevel::elevate(bool elevate)
|
|
|
|
{
|
|
|
|
if (!effectWindow()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
effectWindow()->elevate(elevate);
|
2013-07-02 10:45:55 +00:00
|
|
|
addWorkspaceRepaint(visibleRect());
|
2013-04-24 08:46:34 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 09:18:57 +00:00
|
|
|
pid_t Toplevel::pid() const
|
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return -1;
|
|
|
|
}
|
2013-04-26 09:18:57 +00:00
|
|
|
return info->pid();
|
|
|
|
}
|
|
|
|
|
2013-09-10 06:13:33 +00:00
|
|
|
xcb_window_t Toplevel::frameId() const
|
|
|
|
{
|
|
|
|
return m_client;
|
|
|
|
}
|
|
|
|
|
2015-01-15 14:19:04 +00:00
|
|
|
Xcb::Property Toplevel::fetchSkipCloseAnimation() const
|
|
|
|
{
|
|
|
|
return Xcb::Property(false, window(), atoms->kde_skip_close_animation, XCB_ATOM_CARDINAL, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::readSkipCloseAnimation(Xcb::Property &property)
|
2014-01-24 11:34:16 +00:00
|
|
|
{
|
2014-04-15 08:09:25 +00:00
|
|
|
setSkipCloseAnimation(property.toBool());
|
2014-01-24 11:34:16 +00:00
|
|
|
}
|
|
|
|
|
2015-01-15 14:19:04 +00:00
|
|
|
void Toplevel::getSkipCloseAnimation()
|
|
|
|
{
|
|
|
|
Xcb::Property property = fetchSkipCloseAnimation();
|
|
|
|
readSkipCloseAnimation(property);
|
|
|
|
}
|
|
|
|
|
2014-01-24 11:34:16 +00:00
|
|
|
bool Toplevel::skipsCloseAnimation() const
|
|
|
|
{
|
|
|
|
return m_skipCloseAnimation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::setSkipCloseAnimation(bool set)
|
|
|
|
{
|
|
|
|
if (set == m_skipCloseAnimation) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_skipCloseAnimation = set;
|
|
|
|
emit skipCloseAnimationChanged();
|
|
|
|
}
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
void Toplevel::setSurface(KWaylandServer::SurfaceInterface *surface)
|
2015-02-24 09:54:28 +00:00
|
|
|
{
|
|
|
|
if (m_surface == surface) {
|
|
|
|
return;
|
|
|
|
}
|
2020-04-29 15:18:41 +00:00
|
|
|
using namespace KWaylandServer;
|
2015-02-24 09:54:28 +00:00
|
|
|
if (m_surface) {
|
|
|
|
disconnect(m_surface, &SurfaceInterface::damaged, this, &Toplevel::addDamage);
|
2016-08-26 06:32:03 +00:00
|
|
|
disconnect(m_surface, &SurfaceInterface::sizeChanged, this, &Toplevel::discardWindowPixmap);
|
2015-02-24 09:54:28 +00:00
|
|
|
}
|
|
|
|
m_surface = surface;
|
|
|
|
connect(m_surface, &SurfaceInterface::damaged, this, &Toplevel::addDamage);
|
2016-08-26 06:32:03 +00:00
|
|
|
connect(m_surface, &SurfaceInterface::sizeChanged, this, &Toplevel::discardWindowPixmap);
|
2016-03-21 15:24:59 +00:00
|
|
|
connect(m_surface, &SurfaceInterface::subSurfaceTreeChanged, this,
|
|
|
|
[this] {
|
|
|
|
// TODO improve to only update actual visual area
|
|
|
|
if (ready_for_painting) {
|
|
|
|
addDamageFull();
|
|
|
|
m_isDamaged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2015-06-01 14:51:27 +00:00
|
|
|
connect(m_surface, &SurfaceInterface::destroyed, this,
|
|
|
|
[this] {
|
|
|
|
m_surface = nullptr;
|
|
|
|
}
|
|
|
|
);
|
2016-06-26 13:57:38 +00:00
|
|
|
emit surfaceChanged();
|
2015-02-24 09:54:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addDamage(const QRegion &damage)
|
|
|
|
{
|
|
|
|
m_isDamaged = true;
|
|
|
|
damage_region += damage;
|
2019-07-09 20:08:47 +00:00
|
|
|
for (const QRect &r : damage) {
|
2015-02-24 09:54:28 +00:00
|
|
|
emit damaged(this, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-04 07:53:51 +00:00
|
|
|
QByteArray Toplevel::windowRole() const
|
|
|
|
{
|
2020-03-17 14:51:21 +00:00
|
|
|
if (!info) {
|
|
|
|
return {};
|
|
|
|
}
|
2015-03-04 07:53:51 +00:00
|
|
|
return QByteArray(info->windowRole());
|
|
|
|
}
|
|
|
|
|
2015-06-01 14:25:21 +00:00
|
|
|
void Toplevel::setDepth(int depth)
|
|
|
|
{
|
|
|
|
if (bit_depth == depth) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const bool oldAlpha = hasAlpha();
|
|
|
|
bit_depth = depth;
|
|
|
|
if (oldAlpha != hasAlpha()) {
|
|
|
|
emit hasAlphaChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-18 21:19:13 +00:00
|
|
|
QRegion Toplevel::inputShape() const
|
|
|
|
{
|
|
|
|
if (m_surface) {
|
|
|
|
return m_surface->input();
|
2015-08-10 14:31:45 +00:00
|
|
|
} else {
|
|
|
|
// TODO: maybe also for X11?
|
|
|
|
return QRegion();
|
|
|
|
}
|
2015-06-18 21:19:13 +00:00
|
|
|
}
|
|
|
|
|
2015-12-07 13:25:08 +00:00
|
|
|
QMatrix4x4 Toplevel::inputTransformation() const
|
|
|
|
{
|
|
|
|
QMatrix4x4 m;
|
|
|
|
m.translate(-x(), -y());
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2016-05-02 15:47:39 +00:00
|
|
|
quint32 Toplevel::windowId() const
|
|
|
|
{
|
|
|
|
return window();
|
|
|
|
}
|
|
|
|
|
2016-09-15 09:44:32 +00:00
|
|
|
QRect Toplevel::inputGeometry() const
|
|
|
|
{
|
2019-09-27 10:01:10 +00:00
|
|
|
return frameGeometry();
|
2016-09-15 09:44:32 +00:00
|
|
|
}
|
|
|
|
|
2018-12-23 07:56:15 +00:00
|
|
|
bool Toplevel::isLocalhost() const
|
|
|
|
{
|
|
|
|
if (!m_clientMachine) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return m_clientMachine->isLocal();
|
|
|
|
}
|
|
|
|
|
2019-12-02 17:36:13 +00:00
|
|
|
QMargins Toplevel::bufferMargins() const
|
|
|
|
{
|
|
|
|
return QMargins();
|
|
|
|
}
|
|
|
|
|
2019-09-27 10:33:42 +00:00
|
|
|
QMargins Toplevel::frameMargins() const
|
|
|
|
{
|
|
|
|
return QMargins();
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
} // namespace
|
|
|
|
|