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"
|
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
|
|
|
{
|
2020-09-23 18:39:59 +00:00
|
|
|
connect(screens(), &Screens::changed, this, &Toplevel::checkScreen);
|
|
|
|
connect(screens(), &Screens::countChanged, this, &Toplevel::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);
|
2020-11-04 15:49:10 +00:00
|
|
|
if (toplevel->window()) {
|
|
|
|
debug << ", windowId=0x" << Qt::hex << toplevel->window() << Qt::dec;
|
|
|
|
}
|
2020-08-20 17:34:15 +00:00
|
|
|
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;
|
|
|
|
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();
|
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;
|
|
|
|
|
2020-11-20 09:29:36 +00:00
|
|
|
// The damaged region will be fetched at the next compositing cycle.
|
|
|
|
Compositor::self()->scheduleRepaint();
|
|
|
|
|
2020-09-22 00:13:11 +00:00
|
|
|
// Note: The damage is supposed to specify the damage extents,
|
2019-06-22 10:00:56 +00:00
|
|
|
// but we don't know it at this point. No one who connects
|
|
|
|
// to this signal uses the rect however.
|
2020-09-22 00:13:11 +00:00
|
|
|
emit damaged(this, {});
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
free(reply);
|
2020-11-20 09:29:36 +00:00
|
|
|
|
|
|
|
addDamage(region);
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
2020-09-22 00:13:11 +00:00
|
|
|
const QRect damagedRect(0, 0, bufferRect.width(), bufferRect.height());
|
2019-09-30 09:28:07 +00:00
|
|
|
|
|
|
|
damage_region = damagedRect;
|
2020-10-29 18:25:39 +00:00
|
|
|
addRepaint(damagedRect.translated(offsetX, offsetY));
|
2019-09-30 09:28:07 +00:00
|
|
|
|
2020-09-22 00:13:11 +00:00
|
|
|
emit damaged(this, damage_region);
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::resetDamage()
|
|
|
|
{
|
|
|
|
damage_region = QRegion();
|
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addRepaint(const QRect &rect)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
addRepaint(QRegion(rect));
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addRepaint(int x, int y, int width, int height)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
addRepaint(QRegion(x, y, width, height));
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addRepaint(const QRegion ®ion)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
if (!effectWindow() || !effectWindow()->sceneWindow()) {
|
2019-06-22 10:00:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-11-28 20:26:07 +00:00
|
|
|
effectWindow()->sceneWindow()->addLayerRepaint(region.translated(pos()));
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addLayerRepaint(const QRect &rect)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
addLayerRepaint(QRegion(rect));
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addLayerRepaint(int x, int y, int width, int height)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
addLayerRepaint(QRegion(x, y, width, height));
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:25:39 +00:00
|
|
|
void Toplevel::addLayerRepaint(const QRegion ®ion)
|
2019-06-22 10:00:56 +00:00
|
|
|
{
|
2020-10-29 18:25:39 +00:00
|
|
|
if (!effectWindow() || !effectWindow()->sceneWindow()) {
|
2019-06-22 10:00:56 +00:00
|
|
|
return;
|
2020-10-29 18:25:39 +00:00
|
|
|
}
|
|
|
|
effectWindow()->sceneWindow()->addLayerRepaint(region);
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addRepaintFull()
|
|
|
|
{
|
2021-01-21 07:04:58 +00:00
|
|
|
addLayerRepaint(visibleRect());
|
2019-06-22 10:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-10-29 10:48:10 +00:00
|
|
|
void Toplevel::addWorkspaceRepaint(const QRegion ®ion)
|
|
|
|
{
|
|
|
|
if (compositing()) {
|
|
|
|
Compositor::self()->addRepaint(region);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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();
|
2020-09-24 14:15:57 +00:00
|
|
|
addWorkspaceRepaint(oldVisibleRect);
|
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;
|
2020-11-03 12:30:48 +00:00
|
|
|
m_surfaceId = 0;
|
2015-06-01 14:51:27 +00:00
|
|
|
}
|
|
|
|
);
|
2020-11-03 12:30:48 +00:00
|
|
|
m_surfaceId = surface->id();
|
2016-06-26 13:57:38 +00:00
|
|
|
emit surfaceChanged();
|
2015-02-24 09:54:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Toplevel::addDamage(const QRegion &damage)
|
|
|
|
{
|
2020-11-20 09:29:36 +00:00
|
|
|
const QRect bufferRect = bufferGeometry();
|
|
|
|
const QRect frameRect = frameGeometry();
|
|
|
|
|
2015-02-24 09:54:28 +00:00
|
|
|
m_isDamaged = true;
|
|
|
|
damage_region += damage;
|
2020-11-20 09:29:36 +00:00
|
|
|
addRepaint(damage.translated(bufferRect.topLeft() - frameRect.topLeft()));
|
|
|
|
|
2020-09-22 00:13:11 +00:00
|
|
|
emit damaged(this, damage);
|
2015-02-24 09:54:28 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Adapt to input region changes in kwayland-server
SurfaceInterface::inputIsInfinite() has been dropped. If the surface has
no any input region specified, SurfaceInterface::input() will return a
region that corresponds to the rect of the surface (0, 0, width, height).
While the new design is more robust, for example it's no longer possible
to forget to check SurfaceInterface::inputIsInfinite(), it has shown some
issues in the input stack of kwin.
Currently, acceptsInput() will return false if you attempt to click the
server-side decoration for a surface whose input region is not empty.
Therefore, it's possible for an application to set an input region with
a width and a height of 1. If user doesn't know about KSysGuard or the
possibility of closing apps via the task manager, they won't be able to
close such an application.
Another issue is that if an application has specified an empty input
region on purpose, user will be still able click it. With the new
behavior of SurfaceInterface::input(), this is no longer an issue and it
is handled properly by kwin.
2020-10-17 12:47:25 +00:00
|
|
|
bool Toplevel::hitTest(const QPoint &point) const
|
|
|
|
{
|
|
|
|
if (m_surface && m_surface->isMapped()) {
|
|
|
|
return m_surface->inputSurfaceAt(mapToLocal(point));
|
|
|
|
}
|
|
|
|
return inputGeometry().contains(point);
|
|
|
|
}
|
|
|
|
|
2020-10-17 12:40:51 +00:00
|
|
|
QPoint Toplevel::mapToFrame(const QPoint &point) const
|
|
|
|
{
|
|
|
|
return point - frameGeometry().topLeft();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPoint Toplevel::mapToLocal(const QPoint &point) const
|
|
|
|
{
|
|
|
|
return point - bufferGeometry().topLeft();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPointF Toplevel::mapToLocal(const QPointF &point) const
|
|
|
|
{
|
|
|
|
return point - bufferGeometry().topLeft();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|