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>
|
|
|
|
SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@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 "effects.h"
|
|
|
|
|
2021-03-01 09:45:52 +00:00
|
|
|
#include "abstract_output.h"
|
2012-08-30 06:20:26 +00:00
|
|
|
#include "effectsadaptor.h"
|
2014-03-25 12:43:56 +00:00
|
|
|
#include "effectloader.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 "deleted.h"
|
2019-09-24 08:48:08 +00:00
|
|
|
#include "x11client.h"
|
2013-02-19 10:25:46 +00:00
|
|
|
#include "cursor.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "group.h"
|
2019-08-26 07:44:04 +00:00
|
|
|
#include "internal_client.h"
|
2016-12-23 16:39:12 +00:00
|
|
|
#include "osd.h"
|
2016-02-23 11:29:05 +00:00
|
|
|
#include "pointer_input.h"
|
2008-01-02 15:37:46 +00:00
|
|
|
#include "unmanaged.h"
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2011-03-06 11:15:16 +00:00
|
|
|
#include "tabbox.h"
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2013-01-21 08:04:06 +00:00
|
|
|
#include "screenedge.h"
|
2012-01-29 16:32:56 +00:00
|
|
|
#include "scripting/scriptedeffect.h"
|
2013-04-03 10:19:27 +00:00
|
|
|
#include "screens.h"
|
2016-08-15 06:16:33 +00:00
|
|
|
#include "screenlockerwatcher.h"
|
2012-11-16 07:23:47 +00:00
|
|
|
#include "virtualdesktops.h"
|
2017-09-16 17:25:33 +00:00
|
|
|
#include "window_property_notify_x11_filter.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
#include "workspace.h"
|
|
|
|
#include "kwinglutils.h"
|
[libkwineffects] Introduce API to easily show a QtQuick scene in an effect
Summary:
EffectQuickView/Scene is a convenient class to render a QtQuick
scenegraph into an effect.
Current methods (such as present windows) involve creating an underlying
platform window which is expensive, causes a headache to filter out
again in the rest of the code, and only works as an overlay.
The new class exposes things more natively to an effect where we don't
mess with real windows, we can perform the painting anywhere in the view
and we don't have issues with hiding/closing.
QtQuick has both software and hardware accelerated modes, and kwin also
has 3 render backends. Every combination is supported.
* When used in OpenGL mode for both, we render into an FBO export the
texture ID then it's up to the effect to render that into a scene.
* When using software QtQuick rendering we blit into an image, upload
that into a KWinGLTexture which serves as an abstraction layer and
render that into the scene.
* When using GL for QtQuick and XRender/QPainter in kwin everything is
rendered into the internal FBO, blit and exported as an image.
* When using software rendering for both an image gets passed directly.
Mouse and keyboard events can be forwarded, only if the effect
intercepts them.
The class is meant to be generic enough that we can remove all the
QtQuick code from Aurorae.
The intention is also to replace EffectFrameImpl using this backend and
we can kill all of the EffectFrame code throughout the scenes.
The close button in present windows will also be ported to this,
simplifiying that code base.
Classes that handle the rendering and handling QML are intentionally
split so that in the future we can have a declarative effects API create
overlays from within the same context. Similar to how one can
instantiate windows from a typical QML scene.
Notes:
I don't like how I pass the kwin GL context from the backends into the
effect, but I need something that works with the library separation. It
also currently has wayland problem if I create a QOpenGLContext before
the QPA is set up with a scene - but I don't have anything better?
I know for the EffectFrame we need an API to push things through the
effects stack to handle blur/invert etc. Will deal with that when we
port the EffectFrame.
Test Plan: Used in an effect
Reviewers: #kwin, zzag
Reviewed By: #kwin, zzag
Subscribers: zzag, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24215
2019-09-27 15:06:37 +00:00
|
|
|
#include "kwineffectquickview.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-09-02 11:14:39 +00:00
|
|
|
#include <QDebug>
|
2021-06-02 08:45:50 +00:00
|
|
|
#include <QMouseEvent>
|
|
|
|
#include <QWheelEvent>
|
2014-03-25 12:43:56 +00:00
|
|
|
|
2011-02-17 18:35:08 +00:00
|
|
|
#include <Plasma/Theme>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-08-21 19:50:23 +00:00
|
|
|
#include "composite.h"
|
2012-12-20 13:03:02 +00:00
|
|
|
#include "xcbutils.h"
|
2016-04-07 07:24:17 +00:00
|
|
|
#include "platform.h"
|
2020-02-17 18:39:17 +00:00
|
|
|
#include "waylandclient.h"
|
2015-03-20 13:41:03 +00:00
|
|
|
#include "wayland_server.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2014-07-22 12:47:08 +00:00
|
|
|
#include "decorations/decorationbridge.h"
|
2014-07-22 14:08:08 +00:00
|
|
|
#include <KDecoration2/DecorationSettings>
|
2014-07-22 12:47:08 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
2010-02-01 07:44:27 +00:00
|
|
|
//---------------------
|
|
|
|
// Static
|
|
|
|
|
2013-09-11 06:38:10 +00:00
|
|
|
static QByteArray readWindowProperty(xcb_window_t win, xcb_atom_t atom, xcb_atom_t type, int format)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-05-02 15:47:39 +00:00
|
|
|
if (win == XCB_WINDOW_NONE) {
|
|
|
|
return QByteArray();
|
|
|
|
}
|
2013-09-11 06:38:10 +00:00
|
|
|
uint32_t len = 32768;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (;;) {
|
2014-04-15 08:09:25 +00:00
|
|
|
Xcb::Property prop(false, win, atom, XCB_ATOM_ANY, 0, len);
|
2013-09-11 06:38:10 +00:00
|
|
|
if (prop.isNull()) {
|
|
|
|
// get property failed
|
2010-02-01 07:44:27 +00:00
|
|
|
return QByteArray();
|
2013-09-11 06:38:10 +00:00
|
|
|
}
|
|
|
|
if (prop->bytes_after > 0) {
|
|
|
|
len *= 2;
|
|
|
|
continue;
|
|
|
|
}
|
2014-04-15 08:09:25 +00:00
|
|
|
return prop.toByteArray(format, type);
|
2010-02-01 07:44:27 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-02-01 07:44:27 +00:00
|
|
|
|
2020-12-10 08:54:14 +00:00
|
|
|
static void deleteWindowProperty(xcb_window_t win, long int atom)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-05-02 15:47:39 +00:00
|
|
|
if (win == XCB_WINDOW_NONE) {
|
|
|
|
return;
|
|
|
|
}
|
2017-09-02 08:04:15 +00:00
|
|
|
xcb_delete_property(kwinApp()->x11Connection(), win, atom);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-02-01 07:44:27 +00:00
|
|
|
|
2017-08-23 09:41:26 +00:00
|
|
|
static xcb_atom_t registerSupportProperty(const QByteArray &propertyName)
|
|
|
|
{
|
|
|
|
auto c = kwinApp()->x11Connection();
|
|
|
|
if (!c) {
|
|
|
|
return XCB_ATOM_NONE;
|
|
|
|
}
|
|
|
|
// get the atom for the propertyName
|
|
|
|
ScopedCPointer<xcb_intern_atom_reply_t> atomReply(xcb_intern_atom_reply(c,
|
|
|
|
xcb_intern_atom_unchecked(c, false, propertyName.size(), propertyName.constData()),
|
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
|
|
|
nullptr));
|
2017-08-23 09:41:26 +00:00
|
|
|
if (atomReply.isNull()) {
|
|
|
|
return XCB_ATOM_NONE;
|
|
|
|
}
|
|
|
|
// announce property on root window
|
|
|
|
unsigned char dummy = 0;
|
|
|
|
xcb_change_property(c, XCB_PROP_MODE_REPLACE, kwinApp()->x11RootWindow(), atomReply->atom, atomReply->atom, 8, 1, &dummy);
|
|
|
|
// TODO: add to _NET_SUPPORTED
|
|
|
|
return atomReply->atom;
|
|
|
|
}
|
|
|
|
|
2010-02-01 07:44:27 +00:00
|
|
|
//---------------------
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-08-23 16:04:36 +00:00
|
|
|
EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
2012-08-16 19:19:54 +00:00
|
|
|
: EffectsHandler(scene->compositingType())
|
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
|
|
|
, keyboard_grab_effect(nullptr)
|
|
|
|
, fullscreen_effect(nullptr)
|
2012-08-23 16:04:36 +00:00
|
|
|
, m_compositor(compositor)
|
2012-08-16 19:19:54 +00:00
|
|
|
, m_scene(scene)
|
2012-03-29 18:12:34 +00:00
|
|
|
, m_desktopRendering(false)
|
|
|
|
, m_currentRenderedDesktop(0)
|
2014-01-24 14:42:40 +00:00
|
|
|
, m_effectLoader(new EffectLoader(this))
|
2015-02-07 16:12:53 +00:00
|
|
|
, m_trackingCursorChanges(0)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-08-30 13:50:31 +00:00
|
|
|
qRegisterMetaType<QVector<KWin::EffectWindow*>>();
|
2014-03-25 12:43:56 +00:00
|
|
|
connect(m_effectLoader, &AbstractEffectLoader::effectLoaded, this,
|
|
|
|
[this](Effect *effect, const QString &name) {
|
|
|
|
effect_order.insert(effect->requestedEffectChainPosition(), EffectPair(name, effect));
|
|
|
|
loaded_effects << EffectPair(name, effect);
|
|
|
|
effectsChanged();
|
|
|
|
}
|
|
|
|
);
|
2016-01-29 10:24:18 +00:00
|
|
|
m_effectLoader->setConfig(kwinApp()->config());
|
2012-08-30 06:20:26 +00:00
|
|
|
new EffectsAdaptor(this);
|
|
|
|
QDBusConnection dbus = QDBusConnection::sessionBus();
|
2013-07-23 05:02:52 +00:00
|
|
|
dbus.registerObject(QStringLiteral("/Effects"), this);
|
2011-11-27 17:36:59 +00:00
|
|
|
|
2011-02-25 19:41:10 +00:00
|
|
|
Workspace *ws = Workspace::self();
|
2012-11-16 07:23:47 +00:00
|
|
|
VirtualDesktopManager *vds = VirtualDesktopManager::self();
|
2015-03-28 23:12:21 +00:00
|
|
|
connect(ws, &Workspace::showingDesktopChanged,
|
|
|
|
this, &EffectsHandlerImpl::showingDesktopChanged);
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(ws, &Workspace::currentDesktopChanged, this,
|
2015-03-06 11:38:07 +00:00
|
|
|
[this](int old, AbstractClient *c) {
|
2014-03-26 08:13:35 +00:00
|
|
|
const int newDesktop = VirtualDesktopManager::self()->current();
|
|
|
|
if (old != 0 && newDesktop != old) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT desktopChanged(old, newDesktop, c ? c->effectWindow() : nullptr);
|
2014-03-26 08:13:35 +00:00
|
|
|
// TODO: remove in 4.10
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT desktopChanged(old, newDesktop);
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(ws, &Workspace::desktopPresenceChanged, this,
|
2015-03-13 10:48:08 +00:00
|
|
|
[this](AbstractClient *c, int old) {
|
2014-03-26 08:13:35 +00:00
|
|
|
if (!c->effectWindow()) {
|
|
|
|
return;
|
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT desktopPresenceChanged(c->effectWindow(), old, c->desktop());
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(ws, &Workspace::clientAdded, this,
|
2020-05-11 17:34:36 +00:00
|
|
|
[this](AbstractClient *c) {
|
2014-03-26 08:13:35 +00:00
|
|
|
if (c->readyForPainting())
|
|
|
|
slotClientShown(c);
|
|
|
|
else
|
|
|
|
connect(c, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotClientShown);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(ws, &Workspace::unmanagedAdded, this,
|
|
|
|
[this](Unmanaged *u) {
|
|
|
|
// it's never initially ready but has synthetic 50ms delay
|
|
|
|
connect(u, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotUnmanagedShown);
|
|
|
|
}
|
|
|
|
);
|
2019-08-26 07:44:04 +00:00
|
|
|
connect(ws, &Workspace::internalClientAdded, this,
|
|
|
|
[this](InternalClient *client) {
|
2020-05-08 07:07:20 +00:00
|
|
|
setupClientConnections(client);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowAdded(client->effectWindow());
|
2019-08-26 07:44:04 +00:00
|
|
|
}
|
|
|
|
);
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(ws, &Workspace::clientActivated, this,
|
2015-03-06 12:58:24 +00:00
|
|
|
[this](KWin::AbstractClient *c) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowActivated(c ? c->effectWindow() : nullptr);
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(ws, &Workspace::deletedRemoved, this,
|
|
|
|
[this](KWin::Deleted *d) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowDeleted(d->effectWindow());
|
2014-03-26 08:13:35 +00:00
|
|
|
elevated_windows.removeAll(d->effectWindow());
|
|
|
|
}
|
|
|
|
);
|
2019-11-01 17:14:55 +00:00
|
|
|
connect(ws->sessionManager(), &SessionManager::stateChanged, this,
|
|
|
|
&KWin::EffectsHandler::sessionStateChanged);
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(vds, &VirtualDesktopManager::countChanged, this, &EffectsHandler::numberDesktopsChanged);
|
2020-04-02 16:18:01 +00:00
|
|
|
connect(Cursors::self()->mouse(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged);
|
2021-03-01 09:45:52 +00:00
|
|
|
connect(Screens::self(), &Screens::countChanged, this, &EffectsHandler::numberScreensChanged);
|
|
|
|
connect(Screens::self(), &Screens::sizeChanged, this, &EffectsHandler::virtualScreenSizeChanged);
|
|
|
|
connect(Screens::self(), &Screens::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged);
|
2013-04-04 14:14:12 +00:00
|
|
|
#ifdef KWIN_BUILD_ACTIVITIES
|
2015-07-07 09:48:42 +00:00
|
|
|
if (Activities *activities = Activities::self()) {
|
|
|
|
connect(activities, &Activities::added, this, &EffectsHandler::activityAdded);
|
|
|
|
connect(activities, &Activities::removed, this, &EffectsHandler::activityRemoved);
|
|
|
|
connect(activities, &Activities::currentChanged, this, &EffectsHandler::currentActivityChanged);
|
|
|
|
}
|
2013-04-04 14:14:12 +00:00
|
|
|
#endif
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(ws, &Workspace::stackingOrderChanged, this, &EffectsHandler::stackingOrderChanged);
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox *tabBox = TabBox::TabBox::self();
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(tabBox, &TabBox::TabBox::tabBoxAdded, this, &EffectsHandler::tabBoxAdded);
|
|
|
|
connect(tabBox, &TabBox::TabBox::tabBoxUpdated, this, &EffectsHandler::tabBoxUpdated);
|
|
|
|
connect(tabBox, &TabBox::TabBox::tabBoxClosed, this, &EffectsHandler::tabBoxClosed);
|
|
|
|
connect(tabBox, &TabBox::TabBox::tabBoxKeyEvent, this, &EffectsHandler::tabBoxKeyEvent);
|
2013-01-26 10:50:14 +00:00
|
|
|
#endif
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(ScreenEdges::self(), &ScreenEdges::approaching, this, &EffectsHandler::screenEdgeApproaching);
|
2016-08-15 06:37:24 +00:00
|
|
|
connect(ScreenLockerWatcher::self(), &ScreenLockerWatcher::locked, this, &EffectsHandler::screenLockingChanged);
|
2019-06-23 15:59:44 +00:00
|
|
|
connect(ScreenLockerWatcher::self(), &ScreenLockerWatcher::aboutToLock, this, &EffectsHandler::screenAboutToLock);
|
2017-08-23 09:41:26 +00:00
|
|
|
|
|
|
|
connect(kwinApp(), &Application::x11ConnectionChanged, this,
|
|
|
|
[this] {
|
|
|
|
registered_atoms.clear();
|
|
|
|
for (auto it = m_propertiesForEffects.keyBegin(); it != m_propertiesForEffects.keyEnd(); it++) {
|
|
|
|
const auto atom = registerSupportProperty(*it);
|
|
|
|
if (atom == XCB_ATOM_NONE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_compositor->keepSupportProperty(atom);
|
|
|
|
m_managedProperties.insert(*it, atom);
|
|
|
|
registerPropertyType(atom, true);
|
|
|
|
}
|
2017-09-16 17:25:33 +00:00
|
|
|
if (kwinApp()->x11Connection()) {
|
|
|
|
m_x11WindowPropertyNotify = std::make_unique<WindowPropertyNotifyX11Filter>(this);
|
|
|
|
} else {
|
|
|
|
m_x11WindowPropertyNotify.reset();
|
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT xcbConnectionChanged();
|
2017-08-23 09:41:26 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-09-16 17:25:33 +00:00
|
|
|
if (kwinApp()->x11Connection()) {
|
|
|
|
m_x11WindowPropertyNotify = std::make_unique<WindowPropertyNotifyX11Filter>(this);
|
|
|
|
}
|
|
|
|
|
2011-02-27 08:25:45 +00:00
|
|
|
// connect all clients
|
2020-10-01 11:33:31 +00:00
|
|
|
for (AbstractClient *client : ws->allClientList()) {
|
|
|
|
if (client->readyForPainting()) {
|
|
|
|
setupClientConnections(client);
|
|
|
|
} else {
|
|
|
|
connect(client, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotClientShown);
|
|
|
|
}
|
2011-02-27 08:25:45 +00:00
|
|
|
}
|
2013-09-24 12:31:35 +00:00
|
|
|
for (Unmanaged *u : ws->unmanagedList()) {
|
2011-03-06 10:13:11 +00:00
|
|
|
setupUnmanagedConnections(u);
|
2011-02-27 08:25:45 +00:00
|
|
|
}
|
2019-08-26 07:44:04 +00:00
|
|
|
for (InternalClient *client : ws->internalClients()) {
|
2020-05-08 07:07:20 +00:00
|
|
|
setupClientConnections(client);
|
2019-08-26 07:44:04 +00:00
|
|
|
}
|
2020-10-01 11:33:31 +00:00
|
|
|
|
2021-03-01 09:45:52 +00:00
|
|
|
connect(kwinApp()->platform(), &Platform::outputEnabled, this, &EffectsHandlerImpl::slotOutputEnabled);
|
|
|
|
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &EffectsHandlerImpl::slotOutputDisabled);
|
|
|
|
|
|
|
|
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
|
|
|
|
for (AbstractOutput *output : outputs) {
|
|
|
|
slotOutputEnabled(output);
|
|
|
|
}
|
|
|
|
|
2007-05-28 11:23:00 +00:00
|
|
|
reconfigure();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
EffectsHandlerImpl::~EffectsHandlerImpl()
|
2015-11-12 10:29:56 +00:00
|
|
|
{
|
|
|
|
unloadAllEffects();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::unloadAllEffects()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-05-13 16:41:39 +00:00
|
|
|
for (const EffectPair &pair : qAsConst(loaded_effects)) {
|
2018-12-19 14:44:06 +00:00
|
|
|
destroyEffect(pair.second);
|
2013-11-13 09:03:58 +00:00
|
|
|
}
|
2018-12-01 16:33:52 +00:00
|
|
|
|
|
|
|
effect_order.clear();
|
2015-11-16 13:06:23 +00:00
|
|
|
m_effectLoader->clear();
|
2018-12-01 16:33:52 +00:00
|
|
|
|
|
|
|
effectsChanged();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-05-08 07:07:20 +00:00
|
|
|
void EffectsHandlerImpl::setupClientConnections(AbstractClient* c)
|
2011-03-06 10:13:11 +00:00
|
|
|
{
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::windowClosed, this, &EffectsHandlerImpl::slotWindowClosed);
|
|
|
|
connect(c, static_cast<void (AbstractClient::*)(KWin::AbstractClient*, MaximizeMode)>(&AbstractClient::clientMaximizedStateChanged),
|
2014-03-26 08:13:35 +00:00
|
|
|
this, &EffectsHandlerImpl::slotClientMaximized);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::clientStartUserMovedResized, this,
|
2015-10-22 13:47:02 +00:00
|
|
|
[this](AbstractClient *c) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowStartUserMovedResized(c->effectWindow());
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::clientStepUserMovedResized, this,
|
2015-10-22 13:47:02 +00:00
|
|
|
[this](AbstractClient *c, const QRect &geometry) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowStepUserMovedResized(c->effectWindow(), geometry);
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::clientFinishUserMovedResized, this,
|
2015-10-22 13:47:02 +00:00
|
|
|
[this](AbstractClient *c) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowFinishUserMovedResized(c->effectWindow());
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::opacityChanged, this, &EffectsHandlerImpl::slotOpacityChanged);
|
|
|
|
connect(c, &AbstractClient::clientMinimized, this,
|
2015-03-13 13:45:21 +00:00
|
|
|
[this](AbstractClient *c, bool animate) {
|
2014-03-26 08:13:35 +00:00
|
|
|
// TODO: notify effects even if it should not animate?
|
|
|
|
if (animate) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowMinimized(c->effectWindow());
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::clientUnminimized, this,
|
2015-03-13 13:45:21 +00:00
|
|
|
[this](AbstractClient* c, bool animate) {
|
2014-03-26 08:13:35 +00:00
|
|
|
// TODO: notify effects even if it should not animate?
|
|
|
|
if (animate) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowUnminimized(c->effectWindow());
|
2014-03-26 08:13:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::modalChanged, this, &EffectsHandlerImpl::slotClientModalityChanged);
|
|
|
|
connect(c, &AbstractClient::geometryShapeChanged, this, &EffectsHandlerImpl::slotGeometryShapeChanged);
|
2020-02-11 17:03:23 +00:00
|
|
|
connect(c, &AbstractClient::frameGeometryChanged, this, &EffectsHandlerImpl::slotFrameGeometryChanged);
|
2015-10-26 09:43:36 +00:00
|
|
|
connect(c, &AbstractClient::damaged, this, &EffectsHandlerImpl::slotWindowDamaged);
|
2017-04-05 09:16:23 +00:00
|
|
|
connect(c, &AbstractClient::unresponsiveChanged, this,
|
|
|
|
[this, c](bool unresponsive) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowUnresponsiveChanged(c->effectWindow(), unresponsive);
|
2017-04-05 09:16:23 +00:00
|
|
|
}
|
|
|
|
);
|
2016-07-04 13:37:30 +00:00
|
|
|
connect(c, &AbstractClient::windowShown, this,
|
|
|
|
[this](Toplevel *c) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowShown(c->effectWindow());
|
2016-07-04 13:37:30 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(c, &AbstractClient::windowHidden, this,
|
|
|
|
[this](Toplevel *c) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowHidden(c->effectWindow());
|
2016-07-04 13:37:30 +00:00
|
|
|
}
|
|
|
|
);
|
2018-10-17 11:05:11 +00:00
|
|
|
connect(c, &AbstractClient::keepAboveChanged, this,
|
|
|
|
[this, c](bool above) {
|
|
|
|
Q_UNUSED(above)
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowKeepAboveChanged(c->effectWindow());
|
2018-10-17 11:05:11 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(c, &AbstractClient::keepBelowChanged, this,
|
|
|
|
[this, c](bool below) {
|
|
|
|
Q_UNUSED(below)
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowKeepBelowChanged(c->effectWindow());
|
2018-10-17 11:05:11 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
connect(c, &AbstractClient::fullScreenChanged, this,
|
|
|
|
[this, c]() {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowFullScreenChanged(c->effectWindow());
|
2018-10-17 11:05:11 +00:00
|
|
|
}
|
|
|
|
);
|
2021-02-05 13:05:13 +00:00
|
|
|
connect(c, &AbstractClient::visibleGeometryChanged, this, [this, c]() {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowExpandedGeometryChanged(c->effectWindow());
|
2021-02-05 13:05:13 +00:00
|
|
|
});
|
2015-10-26 09:43:36 +00:00
|
|
|
}
|
|
|
|
|
2011-03-06 10:13:11 +00:00
|
|
|
void EffectsHandlerImpl::setupUnmanagedConnections(Unmanaged* u)
|
|
|
|
{
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(u, &Unmanaged::windowClosed, this, &EffectsHandlerImpl::slotWindowClosed);
|
|
|
|
connect(u, &Unmanaged::opacityChanged, this, &EffectsHandlerImpl::slotOpacityChanged);
|
|
|
|
connect(u, &Unmanaged::geometryShapeChanged, this, &EffectsHandlerImpl::slotGeometryShapeChanged);
|
2020-02-11 17:03:23 +00:00
|
|
|
connect(u, &Unmanaged::frameGeometryChanged, this, &EffectsHandlerImpl::slotFrameGeometryChanged);
|
2014-03-26 08:13:35 +00:00
|
|
|
connect(u, &Unmanaged::damaged, this, &EffectsHandlerImpl::slotWindowDamaged);
|
2021-02-05 13:05:13 +00:00
|
|
|
connect(u, &Unmanaged::visibleGeometryChanged, this, [this, u]() {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowExpandedGeometryChanged(u->effectWindow());
|
2021-02-05 13:05:13 +00:00
|
|
|
});
|
2011-03-06 10:13:11 +00:00
|
|
|
}
|
|
|
|
|
2007-05-28 11:23:00 +00:00
|
|
|
void EffectsHandlerImpl::reconfigure()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-03-25 12:43:56 +00:00
|
|
|
m_effectLoader->queryAndLoadAll();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-05-28 11:23:00 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
// the idea is that effects call this function again which calls the next one
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
void EffectsHandlerImpl::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) {
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
(*m_currentPaintScreenIterator++)->prePaintScreen(data, presentTime);
|
2011-08-27 09:21:31 +00:00
|
|
|
--m_currentPaintScreenIterator;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
// no special final code
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void EffectsHandlerImpl::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentPaintScreenIterator++)->paintScreen(mask, region, data);
|
|
|
|
--m_currentPaintScreenIterator;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else
|
2012-08-16 19:19:54 +00:00
|
|
|
m_scene->finalPaintScreen(mask, region, data);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-03-29 18:12:34 +00:00
|
|
|
void EffectsHandlerImpl::paintDesktop(int desktop, int mask, QRegion region, ScreenPaintData &data)
|
|
|
|
{
|
|
|
|
if (desktop < 1 || desktop > numberOfDesktops()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_currentRenderedDesktop = desktop;
|
|
|
|
m_desktopRendering = true;
|
|
|
|
// save the paint screen iterator
|
2013-07-19 09:34:01 +00:00
|
|
|
EffectsIterator savedIterator = m_currentPaintScreenIterator;
|
|
|
|
m_currentPaintScreenIterator = m_activeEffects.constBegin();
|
2012-03-29 18:12:34 +00:00
|
|
|
effects->paintScreen(mask, region, data);
|
|
|
|
// restore the saved iterator
|
|
|
|
m_currentPaintScreenIterator = savedIterator;
|
|
|
|
m_desktopRendering = false;
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
void EffectsHandlerImpl::postPaintScreen()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentPaintScreenIterator++)->postPaintScreen();
|
|
|
|
--m_currentPaintScreenIterator;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
// no special final code
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
void EffectsHandlerImpl::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) {
|
Provide expected presentation time to effects
Effects are given the interval between two consecutive frames. The main
flaw of this approach is that if the Compositor transitions from the idle
state to "active" state, i.e. when there is something to repaint,
effects may see a very large interval between the last painted frame and
the current. In order to address this issue, the Scene invalidates the
timer that is used to measure time between consecutive frames before the
Compositor is about to become idle.
While this works perfectly fine with Xinerama-style rendering, with per
screen rendering, determining whether the compositor is about to idle is
rather a tedious task mostly because a single output can't be used for
the test.
Furthermore, since the Compositor schedules pointless repaints just to
ensure that it's idle, it might take several attempts to figure out
whether the scene timer must be invalidated if you use (true) per screen
rendering.
Ideally, all effects should use a timeline helper that is aware of the
underlying render loop and its timings. However, this option is off the
table because it will involve a lot of work to implement it.
Alternative and much simpler option is to pass the expected presentation
time to effects rather than time between consecutive frames. This means
that effects are responsible for determining how much animation timelines
have to be advanced. Typically, an effect would have to store the
presentation timestamp provided in either prePaint{Screen,Window} and
use it in the subsequent prePaint{Screen,Window} call to estimate the
amount of time passed between the next and the last frames.
Unfortunately, this is an API incompatible change. However, it shouldn't
take a lot of work to port third-party binary effects, which don't use the
AnimationEffect class, to the new API. On the bright side, we no longer
need to be concerned about the Compositor getting idle.
We do still try to determine whether the Compositor is about to idle,
primarily, because the OpenGL render backend swaps buffers on present,
but that will change with the ongoing compositing timing rework.
2020-11-20 15:44:04 +00:00
|
|
|
(*m_currentPaintWindowIterator++)->prePaintWindow(w, data, presentTime);
|
2011-08-27 09:21:31 +00:00
|
|
|
--m_currentPaintWindowIterator;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
// no special final code
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void EffectsHandlerImpl::paintWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentPaintWindowIterator++)->paintWindow(w, mask, region, data);
|
|
|
|
--m_currentPaintWindowIterator;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else
|
2012-08-16 19:19:54 +00:00
|
|
|
m_scene->finalPaintWindow(static_cast<EffectWindowImpl*>(w), mask, region, data);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void EffectsHandlerImpl::paintEffectFrame(EffectFrame* frame, const QRegion ®ion, double opacity, double frameOpacity)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintEffectFrameIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentPaintEffectFrameIterator++)->paintEffectFrame(frame, region, opacity, frameOpacity);
|
|
|
|
--m_currentPaintEffectFrameIterator;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
const EffectFrameImpl* frameImpl = static_cast<const EffectFrameImpl*>(frame);
|
|
|
|
frameImpl->finalRender(region, opacity, frameOpacity);
|
2010-07-24 16:29:16 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-24 16:29:16 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::postPaintWindow(EffectWindow* w)
|
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentPaintWindowIterator++)->postPaintWindow(w);
|
|
|
|
--m_currentPaintWindowIterator;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
// no special final code
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-03-23 01:06:46 +00:00
|
|
|
Effect *EffectsHandlerImpl::provides(Effect::Feature ef)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < loaded_effects.size(); ++i)
|
|
|
|
if (loaded_effects.at(i).second->provides(ef))
|
2012-03-23 01:06:46 +00:00
|
|
|
return loaded_effects.at(i).second;
|
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-01-30 14:34:42 +00:00
|
|
|
}
|
2010-04-25 18:40:04 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void EffectsHandlerImpl::drawWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
if (m_currentDrawWindowIterator != m_activeEffects.constEnd()) {
|
2011-08-27 09:21:31 +00:00
|
|
|
(*m_currentDrawWindowIterator++)->drawWindow(w, mask, region, data);
|
|
|
|
--m_currentDrawWindowIterator;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else
|
2012-08-16 19:19:54 +00:00
|
|
|
m_scene->finalDrawWindow(static_cast<EffectWindowImpl*>(w), mask, region, data);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-10-17 10:30:43 +00:00
|
|
|
bool EffectsHandlerImpl::hasDecorationShadows() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-07-22 11:11:19 +00:00
|
|
|
return false;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-10-17 10:30:43 +00:00
|
|
|
|
2010-03-05 18:21:14 +00:00
|
|
|
bool EffectsHandlerImpl::decorationsHaveAlpha() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-07-22 11:11:19 +00:00
|
|
|
return true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-05 18:21:14 +00:00
|
|
|
|
2010-11-10 18:33:07 +00:00
|
|
|
bool EffectsHandlerImpl::decorationSupportsBlurBehind() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-07-22 12:47:08 +00:00
|
|
|
return Decoration::DecorationBridge::self()->needsBlur();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-11-10 18:33:07 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
// start another painting pass
|
|
|
|
void EffectsHandlerImpl::startPaint()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-08-27 09:21:31 +00:00
|
|
|
m_activeEffects.clear();
|
2013-07-19 09:46:42 +00:00
|
|
|
m_activeEffects.reserve(loaded_effects.count());
|
2013-07-19 09:34:01 +00:00
|
|
|
for(QVector< KWin::EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
2011-08-27 09:21:31 +00:00
|
|
|
if (it->second->isActive()) {
|
|
|
|
m_activeEffects << it->second;
|
|
|
|
}
|
|
|
|
}
|
2013-07-19 09:34:01 +00:00
|
|
|
m_currentDrawWindowIterator = m_activeEffects.constBegin();
|
|
|
|
m_currentPaintWindowIterator = m_activeEffects.constBegin();
|
|
|
|
m_currentPaintScreenIterator = m_activeEffects.constBegin();
|
|
|
|
m_currentPaintEffectFrameIterator = m_activeEffects.constBegin();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2015-06-07 01:17:34 +00:00
|
|
|
void EffectsHandlerImpl::slotClientMaximized(KWin::AbstractClient *c, MaximizeMode maxMode)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-13 08:48:51 +00:00
|
|
|
bool horizontal = false;
|
|
|
|
bool vertical = false;
|
|
|
|
switch (maxMode) {
|
2014-12-02 12:49:08 +00:00
|
|
|
case MaximizeHorizontal:
|
2011-03-13 08:48:51 +00:00
|
|
|
horizontal = true;
|
|
|
|
break;
|
2014-12-02 12:49:08 +00:00
|
|
|
case MaximizeVertical:
|
2011-03-13 08:48:51 +00:00
|
|
|
vertical = true;
|
|
|
|
break;
|
2014-12-02 12:49:08 +00:00
|
|
|
case MaximizeFull:
|
2011-03-13 08:48:51 +00:00
|
|
|
horizontal = true;
|
|
|
|
vertical = true;
|
|
|
|
break;
|
2014-12-02 12:49:08 +00:00
|
|
|
case MaximizeRestore: // fall through
|
2011-03-13 08:48:51 +00:00
|
|
|
default:
|
|
|
|
// default - nothing to do
|
|
|
|
break;
|
|
|
|
}
|
2013-05-07 07:46:40 +00:00
|
|
|
if (EffectWindowImpl *w = c->effectWindow()) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowMaximizedStateChanged(w, horizontal, vertical);
|
2013-05-07 07:46:40 +00:00
|
|
|
}
|
2011-02-28 20:03:13 +00:00
|
|
|
}
|
|
|
|
|
2011-03-06 09:30:23 +00:00
|
|
|
void EffectsHandlerImpl::slotOpacityChanged(Toplevel *t, qreal oldOpacity)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-15 17:34:12 +00:00
|
|
|
if (t->opacity() == oldOpacity || !t->effectWindow()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-03-06 09:30:23 +00:00
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowOpacityChanged(t->effectWindow(), oldOpacity, (qreal)t->opacity());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2012-01-12 06:42:55 +00:00
|
|
|
void EffectsHandlerImpl::slotClientShown(KWin::Toplevel *t)
|
2012-01-24 16:00:40 +00:00
|
|
|
{
|
2020-05-11 17:34:36 +00:00
|
|
|
Q_ASSERT(qobject_cast<AbstractClient *>(t));
|
|
|
|
AbstractClient *c = static_cast<AbstractClient *>(t);
|
2016-08-03 14:12:23 +00:00
|
|
|
disconnect(c, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotClientShown);
|
2012-01-12 06:42:55 +00:00
|
|
|
setupClientConnections(c);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowAdded(c->effectWindow());
|
2012-01-24 16:00:40 +00:00
|
|
|
}
|
|
|
|
|
2013-06-28 12:23:22 +00:00
|
|
|
void EffectsHandlerImpl::slotUnmanagedShown(KWin::Toplevel *t)
|
|
|
|
{ // regardless, unmanaged windows are -yet?- not synced anyway
|
2018-12-08 12:04:20 +00:00
|
|
|
Q_ASSERT(qobject_cast<Unmanaged *>(t));
|
2013-06-28 12:23:22 +00:00
|
|
|
Unmanaged *u = static_cast<Unmanaged*>(t);
|
|
|
|
setupUnmanagedConnections(u);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowAdded(u->effectWindow());
|
2013-06-28 12:23:22 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 15:27:15 +00:00
|
|
|
void EffectsHandlerImpl::slotWindowClosed(KWin::Toplevel *c, KWin::Deleted *d)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-12-29 16:02:09 +00:00
|
|
|
c->disconnect(this);
|
2015-11-09 15:27:15 +00:00
|
|
|
if (d) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowClosed(c->effectWindow());
|
2015-11-09 15:27:15 +00:00
|
|
|
}
|
2011-02-27 08:25:45 +00:00
|
|
|
}
|
|
|
|
|
2013-06-19 14:26:55 +00:00
|
|
|
void EffectsHandlerImpl::slotClientModalityChanged()
|
|
|
|
{
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowModalityChanged(static_cast<X11Client *>(sender())->effectWindow());
|
2013-06-19 14:26:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-12 06:42:55 +00:00
|
|
|
void EffectsHandlerImpl::slotCurrentTabAboutToChange(EffectWindow *from, EffectWindow *to)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT currentTabAboutToChange(from, to);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 03:24:04 +00:00
|
|
|
|
2012-01-12 06:42:55 +00:00
|
|
|
void EffectsHandlerImpl::slotTabAdded(EffectWindow* w, EffectWindow* to)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT tabAdded(w, to);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 03:24:04 +00:00
|
|
|
|
2012-01-12 06:42:55 +00:00
|
|
|
void EffectsHandlerImpl::slotTabRemoved(EffectWindow *w, EffectWindow* leaderOfFormerGroup)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT tabRemoved(w, leaderOfFormerGroup);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-11-15 03:24:04 +00:00
|
|
|
|
2020-09-22 00:13:11 +00:00
|
|
|
void EffectsHandlerImpl::slotWindowDamaged(Toplevel* t, const QRegion& r)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-05-19 15:28:15 +00:00
|
|
|
if (!t->effectWindow()) {
|
|
|
|
// can happen during tear down of window
|
|
|
|
return;
|
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowDamaged(t->effectWindow(), r);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-06-19 20:07:19 +00:00
|
|
|
void EffectsHandlerImpl::slotGeometryShapeChanged(Toplevel* t, const QRect& old)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-03-12 11:34:59 +00:00
|
|
|
// during late cleanup effectWindow() may be already NULL
|
|
|
|
// in some functions that may still call this
|
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 (t == nullptr || t->effectWindow() == nullptr)
|
2011-03-12 11:34:59 +00:00
|
|
|
return;
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowGeometryShapeChanged(t->effectWindow(), old);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-02-11 17:03:23 +00:00
|
|
|
void EffectsHandlerImpl::slotFrameGeometryChanged(Toplevel *toplevel, const QRect &oldGeometry)
|
|
|
|
{
|
|
|
|
// effectWindow() might be nullptr during tear down of the client.
|
|
|
|
if (toplevel->effectWindow()) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT windowFrameGeometryChanged(toplevel->effectWindow(), oldGeometry);
|
2020-02-11 17:03:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::setActiveFullScreenEffect(Effect* e)
|
|
|
|
{
|
2018-06-23 19:41:26 +00:00
|
|
|
if (fullscreen_effect == e) {
|
|
|
|
return;
|
|
|
|
}
|
2018-10-03 00:11:59 +00:00
|
|
|
const bool activeChanged = (e == nullptr || fullscreen_effect == nullptr);
|
2007-11-01 17:47:41 +00:00
|
|
|
fullscreen_effect = e;
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT activeFullScreenEffectChanged();
|
2018-10-03 00:11:59 +00:00
|
|
|
if (activeChanged) {
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT hasActiveFullScreenEffectChanged();
|
2018-10-03 00:11:59 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-01 17:47:41 +00:00
|
|
|
|
|
|
|
Effect* EffectsHandlerImpl::activeFullScreenEffect() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-11-01 17:47:41 +00:00
|
|
|
return fullscreen_effect;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-01 17:47:41 +00:00
|
|
|
|
2018-10-03 00:11:59 +00:00
|
|
|
bool EffectsHandlerImpl::hasActiveFullScreenEffect() const
|
|
|
|
{
|
|
|
|
return fullscreen_effect;
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
bool EffectsHandlerImpl::grabKeyboard(Effect* effect)
|
|
|
|
{
|
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 (keyboard_grab_effect != nullptr)
|
2007-04-29 17:35:43 +00:00
|
|
|
return false;
|
2017-09-23 18:21:26 +00:00
|
|
|
if (!doGrabKeyboard()) {
|
|
|
|
return false;
|
2013-07-02 09:44:18 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
keyboard_grab_effect = effect;
|
|
|
|
return true;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-09-23 18:21:26 +00:00
|
|
|
bool EffectsHandlerImpl::doGrabKeyboard()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
void EffectsHandlerImpl::ungrabKeyboard()
|
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
|
|
|
Q_ASSERT(keyboard_grab_effect != nullptr);
|
2017-09-23 18:21:26 +00:00
|
|
|
doUngrabKeyboard();
|
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
|
|
|
keyboard_grab_effect = nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-09-23 18:21:26 +00:00
|
|
|
void EffectsHandlerImpl::doUngrabKeyboard()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::grabbedKeyboardEvent(QKeyEvent* e)
|
|
|
|
{
|
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 (keyboard_grab_effect != nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
keyboard_grab_effect->grabbedKeyboardEvent(e);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-24 14:51:04 +00:00
|
|
|
void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape shape)
|
|
|
|
{
|
|
|
|
if (m_grabbedMouseEffects.contains(effect)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_grabbedMouseEffects.append(effect);
|
|
|
|
if (m_grabbedMouseEffects.size() != 1) {
|
|
|
|
return;
|
|
|
|
}
|
2017-09-23 18:21:26 +00:00
|
|
|
doStartMouseInterception(shape);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::doStartMouseInterception(Qt::CursorShape shape)
|
|
|
|
{
|
|
|
|
input()->pointer()->setEffectsOverrideCursor(shape);
|
2013-04-24 14:51:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::stopMouseInterception(Effect *effect)
|
|
|
|
{
|
|
|
|
if (!m_grabbedMouseEffects.contains(effect)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_grabbedMouseEffects.removeAll(effect);
|
|
|
|
if (m_grabbedMouseEffects.isEmpty()) {
|
2017-09-23 18:21:26 +00:00
|
|
|
doStopMouseInterception();
|
2013-04-24 14:51:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-23 18:21:26 +00:00
|
|
|
void EffectsHandlerImpl::doStopMouseInterception()
|
|
|
|
{
|
|
|
|
input()->pointer()->removeEffectsOverrideCursor();
|
|
|
|
}
|
|
|
|
|
2016-02-23 11:29:05 +00:00
|
|
|
bool EffectsHandlerImpl::isMouseInterception() const
|
|
|
|
{
|
|
|
|
return m_grabbedMouseEffects.count() > 0;
|
|
|
|
}
|
|
|
|
|
2016-08-15 13:44:10 +00:00
|
|
|
|
2019-08-11 19:57:45 +00:00
|
|
|
bool EffectsHandlerImpl::touchDown(qint32 id, const QPointF &pos, quint32 time)
|
2016-08-15 13:44:10 +00:00
|
|
|
{
|
|
|
|
// TODO: reverse call order?
|
|
|
|
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
|
|
|
if (it->second->touchDown(id, pos, time)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-08-11 19:57:45 +00:00
|
|
|
bool EffectsHandlerImpl::touchMotion(qint32 id, const QPointF &pos, quint32 time)
|
2016-08-15 13:44:10 +00:00
|
|
|
{
|
|
|
|
// TODO: reverse call order?
|
|
|
|
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
|
|
|
if (it->second->touchMotion(id, pos, time)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-08-11 19:57:45 +00:00
|
|
|
bool EffectsHandlerImpl::touchUp(qint32 id, quint32 time)
|
2016-08-15 13:44:10 +00:00
|
|
|
{
|
|
|
|
// TODO: reverse call order?
|
|
|
|
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
|
|
|
if (it->second->touchUp(id, time)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-07-10 10:26:50 +00:00
|
|
|
void EffectsHandlerImpl::registerGlobalShortcut(const QKeySequence &shortcut, QAction *action)
|
|
|
|
{
|
|
|
|
input()->registerShortcut(shortcut, action);
|
|
|
|
}
|
|
|
|
|
2013-07-14 20:58:30 +00:00
|
|
|
void EffectsHandlerImpl::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action)
|
|
|
|
{
|
|
|
|
input()->registerPointerShortcut(modifiers, pointerButtons, action);
|
|
|
|
}
|
|
|
|
|
2013-07-15 10:04:13 +00:00
|
|
|
void EffectsHandlerImpl::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action)
|
|
|
|
{
|
|
|
|
input()->registerAxisShortcut(modifiers, axis, action);
|
|
|
|
}
|
|
|
|
|
2017-03-18 10:00:30 +00:00
|
|
|
void EffectsHandlerImpl::registerTouchpadSwipeShortcut(SwipeDirection direction, QAction *action)
|
|
|
|
{
|
|
|
|
input()->registerTouchpadSwipeShortcut(direction, action);
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void* EffectsHandlerImpl::getProxy(QString name)
|
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
for (QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it)
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((*it).first == name)
|
2009-02-06 10:15:06 +00:00
|
|
|
return (*it).second->proxy();
|
|
|
|
|
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-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-06 10:15:06 +00:00
|
|
|
|
2009-02-01 15:16:52 +00:00
|
|
|
void EffectsHandlerImpl::startMousePolling()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-04-02 16:18:01 +00:00
|
|
|
if (Cursors::self()->mouse())
|
|
|
|
Cursors::self()->mouse()->startMousePolling();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-01 15:16:52 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::stopMousePolling()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-04-02 16:18:01 +00:00
|
|
|
if (Cursors::self()->mouse())
|
|
|
|
Cursors::self()->mouse()->stopMousePolling();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-01 15:16:52 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
bool EffectsHandlerImpl::hasKeyboardGrab() const
|
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
|
|
|
return keyboard_grab_effect != nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-11-26 15:15:46 +00:00
|
|
|
void EffectsHandlerImpl::desktopResized(const QSize &size)
|
|
|
|
{
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT screenGeometryChanged(size);
|
2011-11-26 15:15:46 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::registerPropertyType(long atom, bool reg)
|
|
|
|
{
|
|
|
|
if (reg)
|
2008-01-02 15:21:33 +00:00
|
|
|
++registered_atoms[ atom ]; // initialized to 0 if not present yet
|
2011-01-30 14:34:42 +00:00
|
|
|
else {
|
|
|
|
if (--registered_atoms[ atom ] == 0)
|
|
|
|
registered_atoms.remove(atom);
|
2008-01-02 15:21:33 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-01-02 15:21:33 +00:00
|
|
|
|
2012-12-13 23:09:47 +00:00
|
|
|
xcb_atom_t EffectsHandlerImpl::announceSupportProperty(const QByteArray &propertyName, Effect *effect)
|
|
|
|
{
|
|
|
|
PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName);
|
|
|
|
if (it != m_propertiesForEffects.end()) {
|
|
|
|
// property has already been registered for an effect
|
|
|
|
// just append Effect and return the atom stored in m_managedProperties
|
|
|
|
if (!it.value().contains(effect)) {
|
|
|
|
it.value().append(effect);
|
|
|
|
}
|
2017-08-23 09:41:26 +00:00
|
|
|
return m_managedProperties.value(propertyName, XCB_ATOM_NONE);
|
2012-12-13 23:09:47 +00:00
|
|
|
}
|
|
|
|
m_propertiesForEffects.insert(propertyName, QList<Effect*>() << effect);
|
2017-08-23 09:41:26 +00:00
|
|
|
const auto atom = registerSupportProperty(propertyName);
|
|
|
|
if (atom == XCB_ATOM_NONE) {
|
|
|
|
return atom;
|
|
|
|
}
|
|
|
|
m_compositor->keepSupportProperty(atom);
|
|
|
|
m_managedProperties.insert(propertyName, atom);
|
|
|
|
registerPropertyType(atom, true);
|
|
|
|
return atom;
|
2012-12-13 23:09:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::removeSupportProperty(const QByteArray &propertyName, Effect *effect)
|
|
|
|
{
|
|
|
|
PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName);
|
|
|
|
if (it == m_propertiesForEffects.end()) {
|
|
|
|
// property is not registered - nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!it.value().contains(effect)) {
|
|
|
|
// property is not registered for given effect - nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
it.value().removeAll(effect);
|
|
|
|
if (!it.value().isEmpty()) {
|
|
|
|
// property still registered for another effect - nothing further to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const xcb_atom_t atom = m_managedProperties.take(propertyName);
|
|
|
|
registerPropertyType(atom, false);
|
|
|
|
m_propertiesForEffects.remove(propertyName);
|
2013-04-26 22:00:23 +00:00
|
|
|
m_compositor->removeSupportProperty(atom); // delayed removal
|
2012-12-13 23:09:47 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QByteArray EffectsHandlerImpl::readRootProperty(long atom, long type, int format) const
|
|
|
|
{
|
2017-09-02 08:04:15 +00:00
|
|
|
if (!kwinApp()->x11Connection()) {
|
|
|
|
return QByteArray();
|
|
|
|
}
|
|
|
|
return readWindowProperty(kwinApp()->x11RootWindow(), atom, type, format);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-02-01 07:44:27 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::activateWindow(EffectWindow* c)
|
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
if (auto cl = qobject_cast<AbstractClient *>(static_cast<EffectWindowImpl *>(c)->window())) {
|
2011-01-30 14:34:42 +00:00
|
|
|
Workspace::self()->activateClient(cl, true);
|
2018-12-08 12:04:20 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
EffectWindow* EffectsHandlerImpl::activeWindow() const
|
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
|
|
|
return Workspace::self()->activeClient() ? Workspace::self()->activeClient()->effectWindow() : nullptr;
|
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 EffectsHandlerImpl::moveWindow(EffectWindow* w, const QPoint& pos, bool snap, double snapAdjust)
|
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
auto cl = qobject_cast<AbstractClient *>(static_cast<EffectWindowImpl *>(w)->window());
|
2009-10-05 04:06:20 +00:00
|
|
|
if (!cl || !cl->isMovable())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (snap)
|
|
|
|
cl->move(Workspace::self()->adjustClientPosition(cl, pos, true, snapAdjust));
|
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
cl->move(pos);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::windowToDesktop(EffectWindow* w, int desktop)
|
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
auto cl = qobject_cast<AbstractClient *>(static_cast<EffectWindowImpl *>(w)->window());
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
if (cl && !cl->isDesktop() && !cl->isDock()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
Workspace::self()->sendClientToDesktop(cl, desktop, true);
|
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2018-11-13 16:18:46 +00:00
|
|
|
void EffectsHandlerImpl::windowToDesktops(EffectWindow *w, const QVector<uint> &desktopIds)
|
|
|
|
{
|
|
|
|
AbstractClient* cl = qobject_cast< AbstractClient* >(static_cast<EffectWindowImpl*>(w)->window());
|
|
|
|
if (!cl || cl->isDesktop() || cl->isDock()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QVector<VirtualDesktop*> desktops;
|
|
|
|
desktops.reserve(desktopIds.count());
|
|
|
|
for (uint x11Id: desktopIds) {
|
|
|
|
if (x11Id > VirtualDesktopManager::self()->count()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
VirtualDesktop *d = VirtualDesktopManager::self()->desktopForX11Id(x11Id);
|
|
|
|
Q_ASSERT(d);
|
|
|
|
if (desktops.contains(d)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
desktops << d;
|
|
|
|
}
|
|
|
|
cl->setDesktops(desktops);
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::windowToScreen(EffectWindow* w, int screen)
|
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
auto cl = qobject_cast<AbstractClient *>(static_cast<EffectWindowImpl *>(w)->window());
|
2011-06-24 10:19:47 +00:00
|
|
|
if (cl && !cl->isDesktop() && !cl->isDock())
|
2011-01-30 14:34:42 +00:00
|
|
|
Workspace::self()->sendClientToScreen(cl, screen);
|
|
|
|
}
|
2009-11-19 08:34:28 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::setShowingDesktop(bool showing)
|
|
|
|
{
|
|
|
|
Workspace::self()->setShowingDesktop(showing);
|
|
|
|
}
|
2009-06-28 17:17:29 +00:00
|
|
|
|
2011-04-24 12:20:47 +00:00
|
|
|
QString EffectsHandlerImpl::currentActivity() const
|
|
|
|
{
|
2013-04-04 14:14:12 +00:00
|
|
|
#ifdef KWIN_BUILD_ACTIVITIES
|
2015-07-07 09:48:42 +00:00
|
|
|
if (!Activities::self()) {
|
|
|
|
return QString();
|
|
|
|
}
|
2013-04-04 14:14:12 +00:00
|
|
|
return Activities::self()->current();
|
|
|
|
#else
|
|
|
|
return QString();
|
|
|
|
#endif
|
2011-04-24 12:20:47 +00:00
|
|
|
}
|
2009-06-28 17:17:29 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
int EffectsHandlerImpl::currentDesktop() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return VirtualDesktopManager::self()->current();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
int EffectsHandlerImpl::numberOfDesktops() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return VirtualDesktopManager::self()->count();
|
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 EffectsHandlerImpl::setCurrentDesktop(int desktop)
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
VirtualDesktopManager::self()->setCurrent(desktop);
|
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 EffectsHandlerImpl::setNumberOfDesktops(int desktops)
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
VirtualDesktopManager::self()->setCount(desktops);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-28 09:04:14 +00:00
|
|
|
|
2009-02-14 14:49:46 +00:00
|
|
|
QSize EffectsHandlerImpl::desktopGridSize() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return VirtualDesktopManager::self()->grid().size();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2009-02-14 14:49:46 +00:00
|
|
|
int EffectsHandlerImpl::desktopGridWidth() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return desktopGridSize().width();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2009-02-14 14:49:46 +00:00
|
|
|
int EffectsHandlerImpl::desktopGridHeight() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return desktopGridSize().height();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2009-02-14 14:49:46 +00:00
|
|
|
int EffectsHandlerImpl::workspaceWidth() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return desktopGridWidth() * Screens::self()->size().width();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
|
|
|
int EffectsHandlerImpl::workspaceHeight() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return desktopGridHeight() * Screens::self()->size().height();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::desktopAtCoords(QPoint coords) const
|
|
|
|
{
|
2016-11-10 13:02:14 +00:00
|
|
|
if (auto vd = VirtualDesktopManager::self()->grid().at(coords)) {
|
|
|
|
return vd->x11DesktopNumber();
|
|
|
|
}
|
|
|
|
return 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QPoint EffectsHandlerImpl::desktopGridCoords(int id) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return VirtualDesktopManager::self()->grid().gridCoords(id);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QPoint EffectsHandlerImpl::desktopCoords(int id) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
QPoint coords = VirtualDesktopManager::self()->grid().gridCoords(id);
|
|
|
|
if (coords.x() == -1)
|
|
|
|
return QPoint(-1, -1);
|
2021-03-01 09:45:52 +00:00
|
|
|
const QSize displaySize = Screens::self()->size();
|
2016-06-08 10:46:02 +00:00
|
|
|
return QPoint(coords.x() * displaySize.width(), coords.y() * displaySize.height());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::desktopAbove(int desktop, bool wrap) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return getDesktop<DesktopAbove>(desktop, wrap);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 16:17:08 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::desktopToRight(int desktop, bool wrap) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return getDesktop<DesktopRight>(desktop, wrap);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 16:17:08 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::desktopBelow(int desktop, bool wrap) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return getDesktop<DesktopBelow>(desktop, wrap);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 16:17:08 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::desktopToLeft(int desktop, bool wrap) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return getDesktop<DesktopLeft>(desktop, wrap);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QString EffectsHandlerImpl::desktopName(int desktop) const
|
|
|
|
{
|
2012-11-16 07:23:47 +00:00
|
|
|
return VirtualDesktopManager::self()->name(desktop);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-02-14 14:49:46 +00:00
|
|
|
|
|
|
|
bool EffectsHandlerImpl::optionRollOverDesktops() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-02-20 09:25:13 +00:00
|
|
|
return options->isRollOverDesktops();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 16:17:08 +00:00
|
|
|
|
2008-08-30 07:25:54 +00:00
|
|
|
double EffectsHandlerImpl::animationTimeFactor() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-08-30 07:25:54 +00:00
|
|
|
return options->animationTimeFactor();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-08-30 07:25:54 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectWindow* EffectsHandlerImpl::findWindow(WId id) const
|
|
|
|
{
|
2019-09-24 08:48:08 +00:00
|
|
|
if (X11Client *w = Workspace::self()->findClient(Predicate::WindowMatch, id))
|
2008-01-02 15:37:46 +00:00
|
|
|
return w->effectWindow();
|
2014-03-20 06:52:18 +00:00
|
|
|
if (Unmanaged* w = Workspace::self()->findUnmanaged(id))
|
2008-01-02 15:37:46 +00:00
|
|
|
return w->effectWindow();
|
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-01-30 14:34:42 +00:00
|
|
|
}
|
2008-01-02 15:37:46 +00:00
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
EffectWindow* EffectsHandlerImpl::findWindow(KWaylandServer::SurfaceInterface *surf) const
|
2015-09-14 14:39:39 +00:00
|
|
|
{
|
|
|
|
if (waylandServer()) {
|
2020-03-04 07:55:26 +00:00
|
|
|
if (AbstractClient *w = waylandServer()->findClient(surf)) {
|
2015-09-14 14:39:39 +00:00
|
|
|
return w->effectWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-13 16:50:32 +00:00
|
|
|
EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const
|
|
|
|
{
|
2019-08-26 07:44:04 +00:00
|
|
|
if (Toplevel *toplevel = workspace()->findInternal(w)) {
|
|
|
|
return toplevel->effectWindow();
|
2019-01-13 16:50:32 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-20 13:04:13 +00:00
|
|
|
EffectWindow *EffectsHandlerImpl::findWindow(const QUuid &id) const
|
|
|
|
{
|
|
|
|
if (const auto client = workspace()->findAbstractClient([&id] (const AbstractClient *c) { return c->internalId() == id; })) {
|
|
|
|
return client->effectWindow();
|
|
|
|
}
|
|
|
|
if (const auto unmanaged = workspace()->findUnmanaged([&id] (const Unmanaged *c) { return c->internalId() == id; })) {
|
|
|
|
return unmanaged->effectWindow();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2015-09-14 14:39:39 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowList EffectsHandlerImpl::stackingOrder() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
|
|
|
QList<Toplevel *> list = Workspace::self()->xStackingOrder();
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowList ret;
|
2013-09-24 12:31:35 +00:00
|
|
|
for (Toplevel *t : list) {
|
2013-07-02 10:45:01 +00:00
|
|
|
if (EffectWindow *w = effectWindow(t))
|
|
|
|
ret.append(w);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
return ret;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2015-03-28 23:13:41 +00:00
|
|
|
void EffectsHandlerImpl::setElevatedWindow(KWin::EffectWindow* w, bool set)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
elevated_windows.removeAll(w);
|
|
|
|
if (set)
|
|
|
|
elevated_windows.append(w);
|
|
|
|
}
|
2007-05-24 14:41:56 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
void EffectsHandlerImpl::setTabBoxWindow(EffectWindow* w)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2018-12-08 12:04:20 +00:00
|
|
|
if (auto c = qobject_cast<AbstractClient *>(static_cast<EffectWindowImpl *>(w)->window())) {
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox::self()->setCurrentClient(c);
|
2011-06-30 11:02:30 +00:00
|
|
|
}
|
2011-07-07 16:31:18 +00:00
|
|
|
#else
|
|
|
|
Q_UNUSED(w)
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::setTabBoxDesktop(int desktop)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox::self()->setCurrentDesktop(desktop);
|
2011-07-07 16:31:18 +00:00
|
|
|
#else
|
|
|
|
Q_UNUSED(desktop)
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
EffectWindowList EffectsHandlerImpl::currentTabBoxWindowList() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2015-03-05 12:59:18 +00:00
|
|
|
const auto clients = TabBox::TabBox::self()->currentClientList();
|
2018-07-01 07:45:39 +00:00
|
|
|
EffectWindowList ret;
|
|
|
|
ret.reserve(clients.size());
|
|
|
|
std::transform(std::cbegin(clients), std::cend(clients),
|
|
|
|
std::back_inserter(ret),
|
|
|
|
[](auto client) { return client->effectWindow(); });
|
2007-04-29 17:35:43 +00:00
|
|
|
return ret;
|
2011-06-30 11:02:30 +00:00
|
|
|
#else
|
2011-07-06 15:42:07 +00:00
|
|
|
return EffectWindowList();
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::refTabBox()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox::self()->reference();
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::unrefTabBox()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox::self()->unreference();
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::closeTabBox()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
TabBox::TabBox::self()->close();
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QList< int > EffectsHandlerImpl::currentTabBoxDesktopList() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
return TabBox::TabBox::self()->currentDesktopList();
|
2019-08-10 10:27:19 +00:00
|
|
|
#else
|
2011-06-25 16:05:07 +00:00
|
|
|
return QList< int >();
|
2019-08-10 10:27:19 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
int EffectsHandlerImpl::currentTabBoxDesktop() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2013-04-04 07:41:18 +00:00
|
|
|
return TabBox::TabBox::self()->currentDesktop();
|
2019-08-10 10:27:19 +00:00
|
|
|
#else
|
2011-06-25 16:05:07 +00:00
|
|
|
return -1;
|
2019-08-10 10:27:19 +00:00
|
|
|
#endif
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
EffectWindow* EffectsHandlerImpl::currentTabBoxWindow() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2011-06-30 11:02:30 +00:00
|
|
|
#ifdef KWIN_BUILD_TABBOX
|
2015-03-05 12:59:18 +00:00
|
|
|
if (auto c = TabBox::TabBox::self()->currentClient())
|
2007-04-29 17:35:43 +00:00
|
|
|
return c->effectWindow();
|
2011-06-30 11:02:30 +00:00
|
|
|
#endif
|
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-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectsHandlerImpl::addRepaintFull()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaintFull();
|
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 EffectsHandlerImpl::addRepaint(const QRect& r)
|
|
|
|
{
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaint(r);
|
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 EffectsHandlerImpl::addRepaint(const QRegion& r)
|
|
|
|
{
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaint(r);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-19 14:16:21 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::addRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaint(x, y, w, h);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2007-11-20 18:58:30 +00:00
|
|
|
int EffectsHandlerImpl::activeScreen() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return Screens::self()->current();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 18:58:30 +00:00
|
|
|
|
2008-06-09 16:09:56 +00:00
|
|
|
int EffectsHandlerImpl::numScreens() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return Screens::self()->count();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-09 16:09:56 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
int EffectsHandlerImpl::screenNumber(const QPoint& pos) const
|
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return Screens::self()->number(pos);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-19 14:16:21 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, int screen, int desktop) const
|
|
|
|
{
|
|
|
|
return Workspace::self()->clientArea(opt, screen, desktop);
|
|
|
|
}
|
2007-11-20 18:58:30 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const EffectWindow* c) const
|
|
|
|
{
|
2007-11-20 18:58:30 +00:00
|
|
|
const Toplevel* t = static_cast< const EffectWindowImpl* >(c)->window();
|
2018-12-08 12:04:20 +00:00
|
|
|
if (const auto *cl = qobject_cast<const AbstractClient *>(t)) {
|
2011-01-30 14:34:42 +00:00
|
|
|
return Workspace::self()->clientArea(opt, cl);
|
2018-12-08 12:04:20 +00:00
|
|
|
} else {
|
2019-09-27 10:01:10 +00:00
|
|
|
return Workspace::self()->clientArea(opt, t->frameGeometry().center(), VirtualDesktopManager::self()->current());
|
2018-12-08 12:04:20 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-11-20 18:58:30 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint& p, int desktop) const
|
|
|
|
{
|
|
|
|
return Workspace::self()->clientArea(opt, p, desktop);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2014-02-27 08:55:45 +00:00
|
|
|
QRect EffectsHandlerImpl::virtualScreenGeometry() const
|
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return Screens::self()->geometry();
|
2014-02-27 08:55:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QSize EffectsHandlerImpl::virtualScreenSize() const
|
|
|
|
{
|
2021-03-01 09:45:52 +00:00
|
|
|
return Screens::self()->size();
|
2014-02-27 08:55:45 +00:00
|
|
|
}
|
|
|
|
|
2013-04-24 14:51:04 +00:00
|
|
|
void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2017-09-23 18:21:26 +00:00
|
|
|
input()->pointer()->setEffectsOverrideCursor(shape);
|
2013-02-19 17:35:23 +00:00
|
|
|
}
|
|
|
|
|
2013-06-26 09:40:30 +00:00
|
|
|
bool EffectsHandlerImpl::checkInputWindowEvent(QMouseEvent *e)
|
|
|
|
{
|
|
|
|
if (m_grabbedMouseEffects.isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_FOREACH (Effect *effect, m_grabbedMouseEffects) {
|
2013-06-26 09:40:30 +00:00
|
|
|
effect->windowInputMouseEvent(e);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-03-04 13:14:44 +00:00
|
|
|
bool EffectsHandlerImpl::checkInputWindowEvent(QWheelEvent *e)
|
|
|
|
{
|
|
|
|
if (m_grabbedMouseEffects.isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_FOREACH (Effect *effect, m_grabbedMouseEffects) {
|
2016-03-04 13:14:44 +00:00
|
|
|
effect->windowInputMouseEvent(e);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-02-07 16:12:53 +00:00
|
|
|
void EffectsHandlerImpl::connectNotify(const QMetaMethod &signal)
|
|
|
|
{
|
|
|
|
if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) {
|
|
|
|
if (!m_trackingCursorChanges) {
|
2020-04-02 16:18:01 +00:00
|
|
|
connect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged);
|
|
|
|
Cursors::self()->mouse()->startCursorTracking();
|
2015-02-07 16:12:53 +00:00
|
|
|
}
|
|
|
|
++m_trackingCursorChanges;
|
|
|
|
}
|
|
|
|
EffectsHandler::connectNotify(signal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::disconnectNotify(const QMetaMethod &signal)
|
|
|
|
{
|
|
|
|
if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) {
|
|
|
|
Q_ASSERT(m_trackingCursorChanges > 0);
|
|
|
|
if (!--m_trackingCursorChanges) {
|
2020-04-02 16:18:01 +00:00
|
|
|
Cursors::self()->mouse()->stopCursorTracking();
|
|
|
|
disconnect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged);
|
2015-02-07 16:12:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
EffectsHandler::disconnectNotify(signal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
void EffectsHandlerImpl::checkInputWindowStacking()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-04-24 14:51:04 +00:00
|
|
|
if (m_grabbedMouseEffects.isEmpty()) {
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2012-07-16 19:57:11 +00:00
|
|
|
}
|
2017-09-23 18:21:26 +00:00
|
|
|
doCheckInputWindowStacking();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::doCheckInputWindowStacking()
|
|
|
|
{
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
QPoint EffectsHandlerImpl::cursorPos() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2020-04-02 16:18:01 +00:00
|
|
|
return Cursors::self()->mouse()->pos();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-01-22 11:47:06 +00:00
|
|
|
void EffectsHandlerImpl::reserveElectricBorder(ElectricBorder border, Effect *effect)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-01-25 09:15:00 +00:00
|
|
|
ScreenEdges::self()->reserve(border, effect, "borderActivated");
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-01-22 11:47:06 +00:00
|
|
|
void EffectsHandlerImpl::unreserveElectricBorder(ElectricBorder border, Effect *effect)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-01-25 09:15:00 +00:00
|
|
|
ScreenEdges::self()->unreserve(border, effect);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2017-03-31 05:41:21 +00:00
|
|
|
void EffectsHandlerImpl::registerTouchBorder(ElectricBorder border, QAction *action)
|
|
|
|
{
|
|
|
|
ScreenEdges::self()->reserveTouch(border, action);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::unregisterTouchBorder(ElectricBorder border, QAction *action)
|
|
|
|
{
|
|
|
|
ScreenEdges::self()->unreserveTouch(border, action);
|
|
|
|
}
|
|
|
|
|
2013-06-21 12:14:48 +00:00
|
|
|
QPainter *EffectsHandlerImpl::scenePainter()
|
|
|
|
{
|
2017-08-09 04:56:23 +00:00
|
|
|
return m_scene->scenePainter();
|
2013-06-21 12:14:48 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::toggleEffect(const QString& name)
|
|
|
|
{
|
|
|
|
if (isEffectLoaded(name))
|
|
|
|
unloadEffect(name);
|
2007-05-29 11:42:47 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
loadEffect(name);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-06-10 09:32:46 +00:00
|
|
|
QStringList EffectsHandlerImpl::loadedEffects() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-06-10 09:32:46 +00:00
|
|
|
QStringList listModules;
|
2018-07-09 10:53:39 +00:00
|
|
|
listModules.reserve(loaded_effects.count());
|
|
|
|
std::transform(loaded_effects.constBegin(), loaded_effects.constEnd(),
|
|
|
|
std::back_inserter(listModules),
|
|
|
|
[](const EffectPair &pair) { return pair.first; });
|
2011-01-30 14:34:42 +00:00
|
|
|
return listModules;
|
|
|
|
}
|
2008-06-02 19:52:02 +00:00
|
|
|
|
2008-06-10 09:32:46 +00:00
|
|
|
QStringList EffectsHandlerImpl::listOfEffects() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2014-03-25 12:43:56 +00:00
|
|
|
return m_effectLoader->listOfKnownEffects();
|
2014-03-09 08:12:09 +00:00
|
|
|
}
|
|
|
|
|
2014-03-25 12:43:56 +00:00
|
|
|
bool EffectsHandlerImpl::loadEffect(const QString& name)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
makeOpenGLContextCurrent();
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaintFull();
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2014-03-25 12:43:56 +00:00
|
|
|
return m_effectLoader->loadEffect(name);
|
2012-01-29 16:32:56 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectsHandlerImpl::unloadEffect(const QString& name)
|
|
|
|
{
|
2018-12-19 14:44:06 +00:00
|
|
|
auto it = std::find_if(effect_order.begin(), effect_order.end(),
|
|
|
|
[name](EffectPair &pair) {
|
|
|
|
return pair.first == name;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
if (it == effect_order.end()) {
|
|
|
|
qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Effect not loaded :" << name;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Unloading Effect :" << name;
|
|
|
|
destroyEffect((*it).second);
|
|
|
|
effect_order.erase(it);
|
|
|
|
effectsChanged();
|
|
|
|
|
2012-08-23 16:04:36 +00:00
|
|
|
m_compositor->addRepaintFull();
|
2018-12-19 14:44:06 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
|
2018-12-19 14:44:06 +00:00
|
|
|
void EffectsHandlerImpl::destroyEffect(Effect *effect)
|
|
|
|
{
|
|
|
|
makeOpenGLContextCurrent();
|
|
|
|
|
|
|
|
if (fullscreen_effect == effect) {
|
|
|
|
setActiveFullScreenEffect(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyboard_grab_effect == effect) {
|
|
|
|
ungrabKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
stopMouseInterception(effect);
|
|
|
|
|
|
|
|
const QList<QByteArray> properties = m_propertiesForEffects.keys();
|
|
|
|
for (const QByteArray &property : properties) {
|
|
|
|
removeSupportProperty(property, effect);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 14:44:06 +00:00
|
|
|
delete effect;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::reconfigureEffect(const QString& name)
|
|
|
|
{
|
2013-07-19 09:34:01 +00:00
|
|
|
for (QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it)
|
2011-01-30 14:34:42 +00:00
|
|
|
if ((*it).first == name) {
|
2016-01-29 10:24:18 +00:00
|
|
|
kwinApp()->config()->reparseConfiguration();
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
makeOpenGLContextCurrent();
|
2011-01-30 14:34:42 +00:00
|
|
|
(*it).second->reconfigure(Effect::ReconfigureAll);
|
2008-10-02 09:27:32 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-29 11:42:47 +00:00
|
|
|
|
2012-08-11 09:24:37 +00:00
|
|
|
bool EffectsHandlerImpl::isEffectLoaded(const QString& name) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-07-02 07:26:58 +00:00
|
|
|
auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(),
|
|
|
|
[&name](const EffectPair &pair) { return pair.first == name; });
|
|
|
|
return it != loaded_effects.constEnd();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-05-29 11:42:47 +00:00
|
|
|
|
2014-03-09 08:12:09 +00:00
|
|
|
bool EffectsHandlerImpl::isEffectSupported(const QString &name)
|
|
|
|
{
|
2018-07-02 07:26:58 +00:00
|
|
|
// If the effect is loaded, it is obviously supported.
|
|
|
|
if (isEffectLoaded(name)) {
|
2014-03-09 08:12:09 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// next checks might require a context
|
|
|
|
makeOpenGLContextCurrent();
|
|
|
|
m_compositor->addRepaintFull();
|
|
|
|
|
2014-03-25 12:43:56 +00:00
|
|
|
return m_effectLoader->isEffectSupported(name);
|
2014-03-09 08:12:09 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-09 10:53:39 +00:00
|
|
|
QList<bool> EffectsHandlerImpl::areEffectsSupported(const QStringList &names)
|
2014-03-09 08:12:09 +00:00
|
|
|
{
|
2018-07-09 10:53:39 +00:00
|
|
|
QList<bool> retList;
|
|
|
|
retList.reserve(names.count());
|
|
|
|
std::transform(names.constBegin(), names.constEnd(),
|
|
|
|
std::back_inserter(retList),
|
|
|
|
[this](const QString &name) {
|
|
|
|
return isEffectSupported(name);
|
|
|
|
});
|
2014-03-09 08:12:09 +00:00
|
|
|
return retList;
|
|
|
|
}
|
|
|
|
|
2011-11-26 15:15:46 +00:00
|
|
|
void EffectsHandlerImpl::reloadEffect(Effect *effect)
|
|
|
|
{
|
|
|
|
QString effectName;
|
2013-07-19 09:34:01 +00:00
|
|
|
for (QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
2011-11-26 15:15:46 +00:00
|
|
|
if ((*it).second == effect) {
|
|
|
|
effectName = (*it).first;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!effectName.isNull()) {
|
|
|
|
unloadEffect(effectName);
|
2014-03-25 12:43:56 +00:00
|
|
|
m_effectLoader->loadEffect(effectName);
|
2011-11-26 15:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-06 12:38:41 +00:00
|
|
|
void EffectsHandlerImpl::effectsChanged()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-07-06 12:38:41 +00:00
|
|
|
loaded_effects.clear();
|
2013-05-03 21:12:53 +00:00
|
|
|
m_activeEffects.clear(); // it's possible to have a reconfigure and a quad rebuild between two paint cycles - bug #308201
|
2018-07-09 12:36:27 +00:00
|
|
|
|
|
|
|
loaded_effects.reserve(effect_order.count());
|
|
|
|
std::copy(effect_order.constBegin(), effect_order.constEnd(),
|
|
|
|
std::back_inserter(loaded_effects));
|
|
|
|
|
2013-07-19 09:46:42 +00:00
|
|
|
m_activeEffects.reserve(loaded_effects.count());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-07-06 12:38:41 +00:00
|
|
|
|
2011-12-29 22:33:45 +00:00
|
|
|
QStringList EffectsHandlerImpl::activeEffects() const
|
|
|
|
{
|
|
|
|
QStringList ret;
|
|
|
|
for(QVector< KWin::EffectPair >::const_iterator it = loaded_effects.constBegin(),
|
|
|
|
end = loaded_effects.constEnd(); it != end; ++it) {
|
|
|
|
if (it->second->isActive()) {
|
|
|
|
ret << it->first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-02-02 13:26:43 +00:00
|
|
|
bool EffectsHandlerImpl::blocksDirectScanout() const
|
|
|
|
{
|
|
|
|
for(QVector< KWin::EffectPair >::const_iterator it = loaded_effects.constBegin(),
|
|
|
|
end = loaded_effects.constEnd(); it != end; ++it) {
|
|
|
|
if (it->second->isActive() && it->second->blocksDirectScanout()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
KWaylandServer::Display *EffectsHandlerImpl::waylandDisplay() const
|
2015-08-31 13:47:01 +00:00
|
|
|
{
|
|
|
|
if (waylandServer()) {
|
|
|
|
return waylandServer()->display();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectFrame* EffectsHandlerImpl::effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const
|
|
|
|
{
|
|
|
|
return new EffectFrameImpl(style, staticSize, position, alignment);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-04-25 15:04:04 +00:00
|
|
|
|
|
|
|
QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt)
|
|
|
|
{
|
2011-08-09 21:53:46 +00:00
|
|
|
switch (kwopt) {
|
|
|
|
case CloseButtonCorner:
|
2014-07-22 14:08:08 +00:00
|
|
|
// TODO: this could become per window and be derived from the actual position in the deco
|
2014-10-29 15:11:20 +00:00
|
|
|
return Decoration::DecorationBridge::self()->settings()->decorationButtonsLeft().contains(KDecoration2::DecorationButtonType::Close) ? Qt::TopLeftCorner : Qt::TopRightCorner;
|
2013-01-30 12:36:37 +00:00
|
|
|
case SwitchDesktopOnScreenEdge:
|
|
|
|
return ScreenEdges::self()->isDesktopSwitching();
|
|
|
|
case SwitchDesktopOnScreenEdgeMovingWindows:
|
|
|
|
return ScreenEdges::self()->isDesktopSwitchingMovingClients();
|
2013-02-22 11:37:12 +00:00
|
|
|
default:
|
|
|
|
return QVariant(); // an invalid one
|
2011-04-25 15:04:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-11 09:24:37 +00:00
|
|
|
QString EffectsHandlerImpl::supportInformation(const QString &name) const
|
|
|
|
{
|
2018-07-02 08:10:04 +00:00
|
|
|
auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(),
|
|
|
|
[name](const EffectPair &pair) { return pair.first == name; });
|
|
|
|
if (it == loaded_effects.constEnd()) {
|
2012-08-11 09:24:37 +00:00
|
|
|
return QString();
|
|
|
|
}
|
2018-07-02 08:10:04 +00:00
|
|
|
|
|
|
|
QString support((*it).first + QLatin1String(":\n"));
|
|
|
|
const QMetaObject *metaOptions = (*it).second->metaObject();
|
|
|
|
for (int i=0; i<metaOptions->propertyCount(); ++i) {
|
|
|
|
const QMetaProperty property = metaOptions->property(i);
|
|
|
|
if (qstrcmp(property.name(), "objectName") == 0) {
|
|
|
|
continue;
|
2012-08-11 09:24:37 +00:00
|
|
|
}
|
2018-07-02 08:10:04 +00:00
|
|
|
support += QString::fromUtf8(property.name()) + QLatin1String(": ") + (*it).second->property(property.name()).toString() + QLatin1Char('\n');
|
2012-08-11 09:24:37 +00:00
|
|
|
}
|
2018-07-02 08:10:04 +00:00
|
|
|
|
|
|
|
return support;
|
2012-08-11 09:24:37 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 21:35:19 +00:00
|
|
|
|
2013-01-30 12:07:59 +00:00
|
|
|
bool EffectsHandlerImpl::isScreenLocked() const
|
|
|
|
{
|
2016-08-15 06:37:24 +00:00
|
|
|
return ScreenLockerWatcher::self()->isLocked();
|
2013-01-30 12:07:59 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 21:35:19 +00:00
|
|
|
QString EffectsHandlerImpl::debug(const QString& name, const QString& parameter) const
|
|
|
|
{
|
2014-04-04 09:49:31 +00:00
|
|
|
QString internalName = name.toLower();;
|
2012-10-27 21:35:19 +00:00
|
|
|
for (QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
|
|
|
if ((*it).first == internalName) {
|
|
|
|
return it->second->debug(parameter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
2013-11-22 14:05:36 +00:00
|
|
|
bool EffectsHandlerImpl::makeOpenGLContextCurrent()
|
|
|
|
{
|
|
|
|
return m_scene->makeOpenGLContextCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::doneOpenGLContextCurrent()
|
|
|
|
{
|
|
|
|
m_scene->doneOpenGLContextCurrent();
|
|
|
|
}
|
|
|
|
|
2016-08-10 07:24:53 +00:00
|
|
|
bool EffectsHandlerImpl::animationsSupported() const
|
|
|
|
{
|
|
|
|
static const QByteArray forceEnvVar = qgetenv("KWIN_EFFECTS_FORCE_ANIMATIONS");
|
|
|
|
if (!forceEnvVar.isEmpty()) {
|
|
|
|
static const int forceValue = forceEnvVar.toInt();
|
|
|
|
return forceValue == 1;
|
|
|
|
}
|
|
|
|
return m_scene->animationsSupported();
|
|
|
|
}
|
|
|
|
|
2016-08-30 13:50:31 +00:00
|
|
|
void EffectsHandlerImpl::highlightWindows(const QVector<EffectWindow *> &windows)
|
|
|
|
{
|
|
|
|
Effect *e = provides(Effect::HighlightWindows);
|
|
|
|
if (!e) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
e->perform(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)});
|
|
|
|
}
|
|
|
|
|
2016-10-17 14:12:21 +00:00
|
|
|
PlatformCursorImage EffectsHandlerImpl::cursorImage() const
|
|
|
|
{
|
|
|
|
return kwinApp()->platform()->cursorImage();
|
|
|
|
}
|
|
|
|
|
2016-10-20 08:25:37 +00:00
|
|
|
void EffectsHandlerImpl::hideCursor()
|
|
|
|
{
|
|
|
|
kwinApp()->platform()->hideCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::showCursor()
|
|
|
|
{
|
|
|
|
kwinApp()->platform()->showCursor();
|
|
|
|
}
|
|
|
|
|
2016-11-15 14:40:30 +00:00
|
|
|
void EffectsHandlerImpl::startInteractiveWindowSelection(std::function<void(KWin::EffectWindow*)> callback)
|
|
|
|
{
|
|
|
|
kwinApp()->platform()->startInteractiveWindowSelection(
|
|
|
|
[callback] (KWin::Toplevel *t) {
|
|
|
|
if (t && t->effectWindow()) {
|
|
|
|
callback(t->effectWindow());
|
|
|
|
} else {
|
|
|
|
callback(nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-11-23 14:53:17 +00:00
|
|
|
void EffectsHandlerImpl::startInteractivePositionSelection(std::function<void(const QPoint&)> callback)
|
|
|
|
{
|
|
|
|
kwinApp()->platform()->startInteractivePositionSelection(callback);
|
|
|
|
}
|
|
|
|
|
2016-12-23 16:39:12 +00:00
|
|
|
void EffectsHandlerImpl::showOnScreenMessage(const QString &message, const QString &iconName)
|
|
|
|
{
|
|
|
|
OSD::show(message, iconName);
|
|
|
|
}
|
|
|
|
|
2017-01-11 19:14:36 +00:00
|
|
|
void EffectsHandlerImpl::hideOnScreenMessage(OnScreenMessageHideFlags flags)
|
2016-12-23 16:39:12 +00:00
|
|
|
{
|
2017-01-11 19:14:36 +00:00
|
|
|
OSD::HideFlags osdFlags;
|
|
|
|
if (flags.testFlag(OnScreenMessageHideFlag::SkipsCloseAnimation)) {
|
|
|
|
osdFlags |= OSD::HideFlag::SkipCloseAnimation;
|
|
|
|
}
|
|
|
|
OSD::hide(osdFlags);
|
2016-12-23 16:39:12 +00:00
|
|
|
}
|
|
|
|
|
2016-12-02 19:27:43 +00:00
|
|
|
KSharedConfigPtr EffectsHandlerImpl::config() const
|
|
|
|
{
|
|
|
|
return kwinApp()->config();
|
|
|
|
}
|
|
|
|
|
2017-04-19 15:00:02 +00:00
|
|
|
KSharedConfigPtr EffectsHandlerImpl::inputConfig() const
|
|
|
|
{
|
2020-07-13 01:56:45 +00:00
|
|
|
return InputConfig::self()->inputConfig();
|
2017-04-19 15:00:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-01 16:23:37 +00:00
|
|
|
Effect *EffectsHandlerImpl::findEffect(const QString &name) const
|
|
|
|
{
|
|
|
|
auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(),
|
|
|
|
[name] (const EffectPair &pair) {
|
|
|
|
return pair.first == name;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
if (it == loaded_effects.constEnd()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return (*it).second;
|
|
|
|
}
|
|
|
|
|
[libkwineffects] Introduce API to easily show a QtQuick scene in an effect
Summary:
EffectQuickView/Scene is a convenient class to render a QtQuick
scenegraph into an effect.
Current methods (such as present windows) involve creating an underlying
platform window which is expensive, causes a headache to filter out
again in the rest of the code, and only works as an overlay.
The new class exposes things more natively to an effect where we don't
mess with real windows, we can perform the painting anywhere in the view
and we don't have issues with hiding/closing.
QtQuick has both software and hardware accelerated modes, and kwin also
has 3 render backends. Every combination is supported.
* When used in OpenGL mode for both, we render into an FBO export the
texture ID then it's up to the effect to render that into a scene.
* When using software QtQuick rendering we blit into an image, upload
that into a KWinGLTexture which serves as an abstraction layer and
render that into the scene.
* When using GL for QtQuick and XRender/QPainter in kwin everything is
rendered into the internal FBO, blit and exported as an image.
* When using software rendering for both an image gets passed directly.
Mouse and keyboard events can be forwarded, only if the effect
intercepts them.
The class is meant to be generic enough that we can remove all the
QtQuick code from Aurorae.
The intention is also to replace EffectFrameImpl using this backend and
we can kill all of the EffectFrame code throughout the scenes.
The close button in present windows will also be ported to this,
simplifiying that code base.
Classes that handle the rendering and handling QML are intentionally
split so that in the future we can have a declarative effects API create
overlays from within the same context. Similar to how one can
instantiate windows from a typical QML scene.
Notes:
I don't like how I pass the kwin GL context from the backends into the
effect, but I need something that works with the library separation. It
also currently has wayland problem if I create a QOpenGLContext before
the QPA is set up with a scene - but I don't have anything better?
I know for the EffectFrame we need an API to push things through the
effects stack to handle blur/invert etc. Will deal with that when we
port the EffectFrame.
Test Plan: Used in an effect
Reviewers: #kwin, zzag
Reviewed By: #kwin, zzag
Subscribers: zzag, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24215
2019-09-27 15:06:37 +00:00
|
|
|
void EffectsHandlerImpl::renderEffectQuickView(EffectQuickView *w) const
|
|
|
|
{
|
|
|
|
if (!w->isVisible()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
scene()->paintEffectQuickView(w);
|
|
|
|
}
|
|
|
|
|
2019-11-01 17:14:55 +00:00
|
|
|
SessionState EffectsHandlerImpl::sessionState() const
|
|
|
|
{
|
|
|
|
return Workspace::self()->sessionManager()->state();
|
|
|
|
}
|
|
|
|
|
2021-03-01 09:45:52 +00:00
|
|
|
QList<EffectScreen *> EffectsHandlerImpl::screens() const
|
|
|
|
{
|
|
|
|
return m_effectScreens;
|
|
|
|
}
|
|
|
|
|
|
|
|
EffectScreen *EffectsHandlerImpl::screenAt(const QPoint &point) const
|
|
|
|
{
|
|
|
|
return m_effectScreens.value(screenNumber(point));
|
|
|
|
}
|
|
|
|
|
|
|
|
EffectScreen *EffectsHandlerImpl::findScreen(const QString &name) const
|
|
|
|
{
|
|
|
|
for (EffectScreen *screen : qAsConst(m_effectScreens)) {
|
|
|
|
if (screen->name() == name) {
|
|
|
|
return screen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
EffectScreen *EffectsHandlerImpl::findScreen(int screenId) const
|
|
|
|
{
|
|
|
|
return m_effectScreens.value(screenId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::slotOutputEnabled(AbstractOutput *output)
|
|
|
|
{
|
|
|
|
EffectScreen *screen = new EffectScreenImpl(output, this);
|
|
|
|
m_effectScreens.append(screen);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT screenAdded(screen);
|
2021-03-01 09:45:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void EffectsHandlerImpl::slotOutputDisabled(AbstractOutput *output)
|
|
|
|
{
|
|
|
|
auto it = std::find_if(m_effectScreens.begin(), m_effectScreens.end(), [&output](EffectScreen *screen) {
|
|
|
|
return static_cast<EffectScreenImpl *>(screen)->platformOutput() == output;
|
|
|
|
});
|
|
|
|
if (it != m_effectScreens.end()) {
|
|
|
|
EffectScreen *screen = *it;
|
|
|
|
m_effectScreens.erase(it);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT screenRemoved(screen);
|
2021-03-01 09:45:52 +00:00
|
|
|
delete screen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//****************************************
|
|
|
|
// EffectScreenImpl
|
|
|
|
//****************************************
|
|
|
|
|
|
|
|
EffectScreenImpl::EffectScreenImpl(AbstractOutput *output, QObject *parent)
|
|
|
|
: EffectScreen(parent)
|
|
|
|
, m_platformOutput(output)
|
|
|
|
{
|
2021-07-09 00:28:53 +00:00
|
|
|
connect(output, &AbstractOutput::wakeUp, this, &EffectScreen::wakeUp);
|
|
|
|
connect(output, &AbstractOutput::aboutToTurnOff, this, &EffectScreen::aboutToTurnOff);
|
2021-07-23 07:37:18 +00:00
|
|
|
connect(output, &AbstractOutput::scaleChanged, this, &EffectScreen::devicePixelRatioChanged);
|
|
|
|
connect(output, &AbstractOutput::geometryChanged, this, &EffectScreen::geometryChanged);
|
2021-03-01 09:45:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AbstractOutput *EffectScreenImpl::platformOutput() const
|
|
|
|
{
|
|
|
|
return m_platformOutput;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString EffectScreenImpl::name() const
|
|
|
|
{
|
|
|
|
return m_platformOutput->name();
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal EffectScreenImpl::devicePixelRatio() const
|
|
|
|
{
|
|
|
|
return m_platformOutput->scale();
|
|
|
|
}
|
|
|
|
|
|
|
|
QRect EffectScreenImpl::geometry() const
|
|
|
|
{
|
|
|
|
return m_platformOutput->geometry();
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
//****************************************
|
|
|
|
// EffectWindowImpl
|
|
|
|
//****************************************
|
|
|
|
|
2011-12-29 09:31:37 +00:00
|
|
|
EffectWindowImpl::EffectWindowImpl(Toplevel *toplevel)
|
|
|
|
: EffectWindow(toplevel)
|
|
|
|
, toplevel(toplevel)
|
2018-11-30 09:58:45 +00:00
|
|
|
, sw(nullptr)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-11-30 09:58:45 +00:00
|
|
|
// Deleted windows are not managed. So, when windowClosed signal is
|
|
|
|
// emitted, effects can't distinguish managed windows from unmanaged
|
|
|
|
// windows(e.g. combo box popups, popup menus, etc). Save value of the
|
|
|
|
// managed property during construction of EffectWindow. At that time,
|
2019-08-30 21:36:58 +00:00
|
|
|
// parent can be Client, XdgShellClient, or Unmanaged. So, later on, when
|
2018-11-30 09:58:45 +00:00
|
|
|
// an instance of Deleted becomes parent of the EffectWindow, effects
|
|
|
|
// can still figure out whether it is/was a managed window.
|
|
|
|
managed = toplevel->isClient();
|
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
waylandClient = qobject_cast<KWin::WaylandClient *>(toplevel) != nullptr;
|
2020-01-10 10:05:29 +00:00
|
|
|
x11Client = qobject_cast<KWin::X11Client *>(toplevel) != nullptr ||
|
|
|
|
qobject_cast<KWin::Unmanaged *>(toplevel) != nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
EffectWindowImpl::~EffectWindowImpl()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
QVariant cachedTextureVariant = data(LanczosCacheRole);
|
|
|
|
if (cachedTextureVariant.isValid()) {
|
2010-11-01 10:46:11 +00:00
|
|
|
GLTexture *cachedTexture = static_cast< GLTexture*>(cachedTextureVariant.value<void*>());
|
|
|
|
delete cachedTexture;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
bool EffectWindowImpl::isPaintingEnabled()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
return sceneWindow()->isPaintingEnabled();
|
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 EffectWindowImpl::enablePainting(int reason)
|
|
|
|
{
|
|
|
|
sceneWindow()->enablePainting(reason);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectWindowImpl::disablePainting(int reason)
|
|
|
|
{
|
|
|
|
sceneWindow()->disablePainting(reason);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-01-07 16:29:00 +00:00
|
|
|
void EffectWindowImpl::addRepaint(const QRect &r)
|
|
|
|
{
|
|
|
|
toplevel->addRepaint(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::addRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
toplevel->addRepaint(x, y, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::addRepaintFull()
|
|
|
|
{
|
|
|
|
toplevel->addRepaintFull();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::addLayerRepaint(const QRect &r)
|
|
|
|
{
|
|
|
|
toplevel->addLayerRepaint(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::addLayerRepaint(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
toplevel->addLayerRepaint(x, y, w, h);
|
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
const EffectWindowGroup* EffectWindowImpl::group() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2019-09-24 08:48:08 +00:00
|
|
|
if (auto c = qobject_cast<X11Client *>(toplevel)) {
|
2007-04-29 17:35:43 +00:00
|
|
|
return c->group()->effectGroup();
|
2018-12-08 12:04:20 +00:00
|
|
|
}
|
2018-11-30 09:58:45 +00:00
|
|
|
return nullptr; // TODO
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectWindowImpl::refWindow()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
if (auto d = qobject_cast<Deleted *>(toplevel)) {
|
2007-04-29 17:35:43 +00:00
|
|
|
return d->refWindow();
|
2018-12-08 12:04:20 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
abort(); // TODO
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void EffectWindowImpl::unrefWindow()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
if (auto d = qobject_cast<Deleted *>(toplevel)) {
|
2013-05-31 17:15:51 +00:00
|
|
|
return d->unrefWindow(); // delays deletion in case
|
2018-12-08 12:04:20 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
abort(); // TODO
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2018-11-30 09:58:45 +00:00
|
|
|
#define TOPLEVEL_HELPER( rettype, prototype, toplevelPrototype) \
|
|
|
|
rettype EffectWindowImpl::prototype ( ) const \
|
|
|
|
{ \
|
|
|
|
return toplevel->toplevelPrototype(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
TOPLEVEL_HELPER(double, opacity, opacity)
|
|
|
|
TOPLEVEL_HELPER(bool, hasAlpha, hasAlpha)
|
|
|
|
TOPLEVEL_HELPER(int, x, x)
|
|
|
|
TOPLEVEL_HELPER(int, y, y)
|
|
|
|
TOPLEVEL_HELPER(int, width, width)
|
|
|
|
TOPLEVEL_HELPER(int, height, height)
|
|
|
|
TOPLEVEL_HELPER(QPoint, pos, pos)
|
|
|
|
TOPLEVEL_HELPER(QSize, size, size)
|
|
|
|
TOPLEVEL_HELPER(int, screen, screen)
|
2019-09-27 10:01:10 +00:00
|
|
|
TOPLEVEL_HELPER(QRect, geometry, frameGeometry)
|
2019-09-28 15:09:12 +00:00
|
|
|
TOPLEVEL_HELPER(QRect, frameGeometry, frameGeometry)
|
|
|
|
TOPLEVEL_HELPER(QRect, bufferGeometry, bufferGeometry)
|
2021-05-28 08:05:28 +00:00
|
|
|
TOPLEVEL_HELPER(QRect, clientGeometry, clientGeometry)
|
2021-02-05 12:46:22 +00:00
|
|
|
TOPLEVEL_HELPER(QRect, expandedGeometry, visibleGeometry)
|
2018-11-30 09:58:45 +00:00
|
|
|
TOPLEVEL_HELPER(QRect, rect, rect)
|
|
|
|
TOPLEVEL_HELPER(int, desktop, desktop)
|
|
|
|
TOPLEVEL_HELPER(bool, isDesktop, isDesktop)
|
|
|
|
TOPLEVEL_HELPER(bool, isDock, isDock)
|
|
|
|
TOPLEVEL_HELPER(bool, isToolbar, isToolbar)
|
|
|
|
TOPLEVEL_HELPER(bool, isMenu, isMenu)
|
|
|
|
TOPLEVEL_HELPER(bool, isNormalWindow, isNormalWindow)
|
|
|
|
TOPLEVEL_HELPER(bool, isDialog, isDialog)
|
|
|
|
TOPLEVEL_HELPER(bool, isSplash, isSplash)
|
|
|
|
TOPLEVEL_HELPER(bool, isUtility, isUtility)
|
|
|
|
TOPLEVEL_HELPER(bool, isDropdownMenu, isDropdownMenu)
|
|
|
|
TOPLEVEL_HELPER(bool, isPopupMenu, isPopupMenu)
|
|
|
|
TOPLEVEL_HELPER(bool, isTooltip, isTooltip)
|
|
|
|
TOPLEVEL_HELPER(bool, isNotification, isNotification)
|
2019-05-02 08:29:38 +00:00
|
|
|
TOPLEVEL_HELPER(bool, isCriticalNotification, isCriticalNotification)
|
2018-11-30 09:58:45 +00:00
|
|
|
TOPLEVEL_HELPER(bool, isOnScreenDisplay, isOnScreenDisplay)
|
|
|
|
TOPLEVEL_HELPER(bool, isComboBox, isComboBox)
|
|
|
|
TOPLEVEL_HELPER(bool, isDNDIcon, isDNDIcon)
|
|
|
|
TOPLEVEL_HELPER(bool, isDeleted, isDeleted)
|
|
|
|
TOPLEVEL_HELPER(QString, windowRole, windowRole)
|
|
|
|
TOPLEVEL_HELPER(QStringList, activities, activities)
|
|
|
|
TOPLEVEL_HELPER(bool, skipsCloseAnimation, skipsCloseAnimation)
|
2020-04-29 15:18:41 +00:00
|
|
|
TOPLEVEL_HELPER(KWaylandServer::SurfaceInterface *, surface, surface)
|
2018-11-30 09:58:45 +00:00
|
|
|
TOPLEVEL_HELPER(bool, isPopupWindow, isPopupWindow)
|
2019-03-19 14:01:29 +00:00
|
|
|
TOPLEVEL_HELPER(bool, isOutline, isOutline)
|
2021-05-12 18:56:16 +00:00
|
|
|
TOPLEVEL_HELPER(bool, isLockScreen, isLockScreen)
|
2019-09-26 12:54:33 +00:00
|
|
|
TOPLEVEL_HELPER(pid_t, pid, pid)
|
2020-11-01 14:25:15 +00:00
|
|
|
TOPLEVEL_HELPER(qlonglong, windowId, window)
|
2018-11-30 09:58:45 +00:00
|
|
|
|
|
|
|
#undef TOPLEVEL_HELPER
|
|
|
|
|
|
|
|
#define CLIENT_HELPER_WITH_DELETED( rettype, prototype, propertyname, defaultValue ) \
|
|
|
|
rettype EffectWindowImpl::prototype ( ) const \
|
|
|
|
{ \
|
|
|
|
auto client = qobject_cast<AbstractClient *>(toplevel); \
|
|
|
|
if (client) { \
|
|
|
|
return client->propertyname(); \
|
|
|
|
} \
|
|
|
|
auto deleted = qobject_cast<Deleted *>(toplevel); \
|
|
|
|
if (deleted) { \
|
|
|
|
return deleted->propertyname(); \
|
|
|
|
} \
|
|
|
|
return defaultValue; \
|
|
|
|
}
|
|
|
|
|
|
|
|
CLIENT_HELPER_WITH_DELETED(bool, isMinimized, isMinimized, false)
|
|
|
|
CLIENT_HELPER_WITH_DELETED(bool, isModal, isModal, false)
|
|
|
|
CLIENT_HELPER_WITH_DELETED(bool, isFullScreen, isFullScreen, false)
|
|
|
|
CLIENT_HELPER_WITH_DELETED(bool, keepAbove, keepAbove, false)
|
|
|
|
CLIENT_HELPER_WITH_DELETED(bool, keepBelow, keepBelow, false)
|
|
|
|
CLIENT_HELPER_WITH_DELETED(QString, caption, caption, QString());
|
|
|
|
CLIENT_HELPER_WITH_DELETED(QVector<uint>, desktops, x11DesktopIds, QVector<uint>());
|
|
|
|
|
|
|
|
#undef CLIENT_HELPER_WITH_DELETED
|
|
|
|
|
2019-09-14 08:58:12 +00:00
|
|
|
// legacy from tab groups, can be removed when no effects use this any more.
|
|
|
|
bool EffectWindowImpl::isCurrentTab() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-11-30 09:58:45 +00:00
|
|
|
QString EffectWindowImpl::windowClass() const
|
|
|
|
{
|
|
|
|
return toplevel->resourceName() + QLatin1Char(' ') + toplevel->resourceClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
QRect EffectWindowImpl::contentsRect() const
|
|
|
|
{
|
|
|
|
return QRect(toplevel->clientPos(), toplevel->clientSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
NET::WindowType EffectWindowImpl::windowType() const
|
|
|
|
{
|
|
|
|
return toplevel->windowType();
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CLIENT_HELPER( rettype, prototype, propertyname, defaultValue ) \
|
|
|
|
rettype EffectWindowImpl::prototype ( ) const \
|
|
|
|
{ \
|
|
|
|
auto client = qobject_cast<AbstractClient *>(toplevel); \
|
|
|
|
if (client) { \
|
|
|
|
return client->propertyname(); \
|
|
|
|
} \
|
|
|
|
return defaultValue; \
|
|
|
|
}
|
|
|
|
|
|
|
|
CLIENT_HELPER(bool, isMovable, isMovable, false)
|
|
|
|
CLIENT_HELPER(bool, isMovableAcrossScreens, isMovableAcrossScreens, false)
|
2021-04-30 18:06:58 +00:00
|
|
|
CLIENT_HELPER(bool, isUserMove, isInteractiveMove, false)
|
|
|
|
CLIENT_HELPER(bool, isUserResize, isInteractiveResize, false)
|
2018-11-30 09:58:45 +00:00
|
|
|
CLIENT_HELPER(QRect, iconGeometry, iconGeometry, QRect())
|
|
|
|
CLIENT_HELPER(bool, isSpecialWindow, isSpecialWindow, true)
|
|
|
|
CLIENT_HELPER(bool, acceptsFocus, wantsInput, true) // We don't actually know...
|
|
|
|
CLIENT_HELPER(QIcon, icon, icon, QIcon())
|
|
|
|
CLIENT_HELPER(bool, isSkipSwitcher, skipSwitcher, false)
|
|
|
|
CLIENT_HELPER(bool, decorationHasAlpha, decorationHasAlpha, false)
|
|
|
|
CLIENT_HELPER(bool, isUnresponsive, unresponsive, false)
|
|
|
|
|
|
|
|
#undef CLIENT_HELPER
|
|
|
|
|
|
|
|
QSize EffectWindowImpl::basicUnit() const
|
|
|
|
{
|
2019-09-24 08:48:08 +00:00
|
|
|
if (auto client = qobject_cast<X11Client *>(toplevel)){
|
2018-11-30 09:58:45 +00:00
|
|
|
return client->basicUnit();
|
|
|
|
}
|
|
|
|
return QSize(1,1);
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectWindowImpl::setWindow(Toplevel* w)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
toplevel = w;
|
2011-12-29 09:31:37 +00:00
|
|
|
setParent(w);
|
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 EffectWindowImpl::setSceneWindow(Scene::Window* w)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
sw = w;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2010-03-12 16:33:01 +00:00
|
|
|
QRect EffectWindowImpl::decorationInnerRect() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2021-08-12 11:56:39 +00:00
|
|
|
return toplevel->rect() - toplevel->frameMargins();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-03-12 16:33:01 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QByteArray EffectWindowImpl::readProperty(long atom, long type, int format) const
|
|
|
|
{
|
2017-09-02 08:04:15 +00:00
|
|
|
if (!kwinApp()->x11Connection()) {
|
|
|
|
return QByteArray();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
return readWindowProperty(window()->window(), atom, type, format);
|
|
|
|
}
|
2008-01-02 15:21:33 +00:00
|
|
|
|
2009-06-27 10:21:49 +00:00
|
|
|
void EffectWindowImpl::deleteProperty(long int atom) const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2017-09-02 08:04:15 +00:00
|
|
|
if (kwinApp()->x11Connection()) {
|
|
|
|
deleteWindowProperty(window()->window(), atom);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2009-06-27 10:21:49 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindow* EffectWindowImpl::findModal()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-12-08 12:04:20 +00:00
|
|
|
auto client = qobject_cast<AbstractClient *>(toplevel);
|
|
|
|
if (!client) {
|
|
|
|
return nullptr;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2018-12-08 12:04:20 +00:00
|
|
|
|
|
|
|
AbstractClient *modal = client->findModal();
|
|
|
|
if (modal) {
|
|
|
|
return modal->effectWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 10:25:28 +00:00
|
|
|
EffectWindow* EffectWindowImpl::transientFor()
|
|
|
|
{
|
|
|
|
auto client = qobject_cast<AbstractClient *>(toplevel);
|
|
|
|
if (!client) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractClient *transientFor = client->transientFor();
|
|
|
|
if (transientFor) {
|
|
|
|
return transientFor->effectWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-13 16:50:32 +00:00
|
|
|
QWindow *EffectWindowImpl::internalWindow() const
|
|
|
|
{
|
2019-08-26 07:44:04 +00:00
|
|
|
auto client = qobject_cast<InternalClient *>(toplevel);
|
2019-01-13 16:50:32 +00:00
|
|
|
if (!client) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return client->internalWindow();
|
|
|
|
}
|
|
|
|
|
2013-06-03 13:08:05 +00:00
|
|
|
template <typename T>
|
2018-12-08 11:47:22 +00:00
|
|
|
EffectWindowList getMainWindows(T *c)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2015-09-11 13:55:23 +00:00
|
|
|
const auto mainclients = c->mainClients();
|
2018-07-01 07:45:39 +00:00
|
|
|
EffectWindowList ret;
|
|
|
|
ret.reserve(mainclients.size());
|
|
|
|
std::transform(std::cbegin(mainclients), std::cend(mainclients),
|
|
|
|
std::back_inserter(ret),
|
|
|
|
[](auto client) { return client->effectWindow(); });
|
2013-06-03 13:08:05 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
EffectWindowList EffectWindowImpl::mainWindows() const
|
|
|
|
{
|
2018-12-08 11:47:22 +00:00
|
|
|
if (auto client = qobject_cast<AbstractClient *>(toplevel)) {
|
|
|
|
return getMainWindows(client);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2018-12-08 11:47:22 +00:00
|
|
|
if (auto deleted = qobject_cast<Deleted *>(toplevel)) {
|
|
|
|
return getMainWindows(deleted);
|
|
|
|
}
|
|
|
|
return {};
|
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 EffectWindowImpl::setData(int role, const QVariant &data)
|
|
|
|
{
|
|
|
|
if (!data.isNull())
|
2010-01-03 17:50:38 +00:00
|
|
|
dataMap[ role ] = data;
|
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
dataMap.remove(role);
|
2021-06-08 07:02:14 +00:00
|
|
|
Q_EMIT effects->windowDataChanged(this, role);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-01-03 17:50:38 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
QVariant EffectWindowImpl::data(int role) const
|
|
|
|
{
|
2018-07-01 07:30:30 +00:00
|
|
|
return dataMap.value(role);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-01-03 17:50:38 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectWindow* effectWindow(Toplevel* w)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowImpl* ret = w->effectWindow();
|
|
|
|
return ret;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectWindow* effectWindow(Scene::Window* w)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowImpl* ret = w->window()->effectWindow();
|
2011-01-30 14:34:42 +00:00
|
|
|
ret->setSceneWindow(w);
|
2007-04-29 17:35:43 +00:00
|
|
|
return ret;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-04-24 08:46:34 +00:00
|
|
|
void EffectWindowImpl::elevate(bool elevate)
|
|
|
|
{
|
|
|
|
effects->setElevatedWindow(this, elevate);
|
|
|
|
}
|
|
|
|
|
2019-01-07 16:29:00 +00:00
|
|
|
void EffectWindowImpl::minimize()
|
|
|
|
{
|
|
|
|
if (auto client = qobject_cast<AbstractClient *>(toplevel)) {
|
|
|
|
client->minimize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::unminimize()
|
|
|
|
{
|
|
|
|
if (auto client = qobject_cast<AbstractClient *>(toplevel)) {
|
|
|
|
client->unminimize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::closeWindow()
|
|
|
|
{
|
|
|
|
if (auto client = qobject_cast<AbstractClient *>(toplevel)) {
|
|
|
|
client->closeWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-13 06:17:28 +00:00
|
|
|
void EffectWindowImpl::referencePreviousWindowPixmap()
|
|
|
|
{
|
|
|
|
if (sw) {
|
|
|
|
sw->referencePreviousPixmap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectWindowImpl::unreferencePreviousWindowPixmap()
|
|
|
|
{
|
|
|
|
if (sw) {
|
|
|
|
sw->unreferencePreviousPixmap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-30 09:58:45 +00:00
|
|
|
bool EffectWindowImpl::isManaged() const
|
|
|
|
{
|
|
|
|
return managed;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EffectWindowImpl::isWaylandClient() const
|
|
|
|
{
|
|
|
|
return waylandClient;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EffectWindowImpl::isX11Client() const
|
|
|
|
{
|
|
|
|
return x11Client;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
//****************************************
|
|
|
|
// EffectWindowGroupImpl
|
|
|
|
//****************************************
|
|
|
|
|
2008-06-02 19:52:02 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowList EffectWindowGroupImpl::members() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2018-07-01 07:45:39 +00:00
|
|
|
const auto memberList = group->members();
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindowList ret;
|
2018-07-01 07:45:39 +00:00
|
|
|
ret.reserve(memberList.size());
|
|
|
|
std::transform(std::cbegin(memberList), std::cend(memberList),
|
|
|
|
std::back_inserter(ret),
|
|
|
|
[](auto toplevel) { return toplevel->effectWindow(); });
|
2007-04-29 17:35:43 +00:00
|
|
|
return ret;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2010-07-18 16:32:37 +00:00
|
|
|
//****************************************
|
|
|
|
// EffectFrameImpl
|
|
|
|
//****************************************
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectFrameImpl::EffectFrameImpl(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment)
|
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
|
|
|
: QObject(nullptr)
|
2010-07-18 16:32:37 +00:00
|
|
|
, EffectFrame()
|
2011-01-30 14:34:42 +00:00
|
|
|
, m_style(style)
|
|
|
|
, m_static(staticSize)
|
|
|
|
, m_point(position)
|
|
|
|
, m_alignment(alignment)
|
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
|
|
|
, m_shader(nullptr)
|
2013-07-22 14:10:47 +00:00
|
|
|
, m_theme(new Plasma::Theme(this))
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (m_style == EffectFrameStyled) {
|
2013-07-23 05:02:52 +00:00
|
|
|
m_frame.setImagePath(QStringLiteral("widgets/background"));
|
2011-01-30 14:34:42 +00:00
|
|
|
m_frame.setCacheAllRenderedFrames(true);
|
2020-09-23 18:39:59 +00:00
|
|
|
connect(m_theme, &Plasma::Theme::themeChanged, this, &EffectFrameImpl::plasmaThemeChanged);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2013-07-23 05:02:52 +00:00
|
|
|
m_selection.setImagePath(QStringLiteral("widgets/viewitem"));
|
|
|
|
m_selection.setElementPrefix(QStringLiteral("hover"));
|
2011-04-28 11:41:11 +00:00
|
|
|
m_selection.setCacheAllRenderedFrames(true);
|
|
|
|
m_selection.setEnabledBorders(Plasma::FrameSvg::AllBorders);
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2013-06-24 06:49:24 +00:00
|
|
|
m_sceneFrame = Compositor::self()->scene()->createEffectFrame(this);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
EffectFrameImpl::~EffectFrameImpl()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
delete m_sceneFrame;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
const QFont& EffectFrameImpl::font() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_font;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setFont(const QFont& font)
|
|
|
|
{
|
|
|
|
if (m_font == font) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
m_font = font;
|
|
|
|
QRect oldGeom = m_geometry;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!m_text.isEmpty()) {
|
2010-07-18 16:32:37 +00:00
|
|
|
autoResize();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (oldGeom == m_geometry) {
|
|
|
|
// Wasn't updated in autoResize()
|
2010-07-18 16:32:37 +00:00
|
|
|
m_sceneFrame->freeTextFrame();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
void EffectFrameImpl::free()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
m_sceneFrame->free();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
const QRect& EffectFrameImpl::geometry() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_geometry;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setGeometry(const QRect& geometry, bool force)
|
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
QRect oldGeom = m_geometry;
|
|
|
|
m_geometry = geometry;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (m_geometry == oldGeom && !force) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
effects->addRepaint(oldGeom);
|
|
|
|
effects->addRepaint(m_geometry);
|
|
|
|
if (m_geometry.size() == oldGeom.size() && !force) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
if (m_style == EffectFrameStyled) {
|
2010-07-18 16:32:37 +00:00
|
|
|
qreal left, top, right, bottom;
|
2011-01-30 14:34:42 +00:00
|
|
|
m_frame.getMargins(left, top, right, bottom); // m_geometry is the inner geometry
|
|
|
|
m_frame.resizeFrame(m_geometry.adjusted(-left, -top, right, bottom).size());
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
free();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2013-12-06 13:41:23 +00:00
|
|
|
const QIcon& EffectFrameImpl::icon() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_icon;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2013-12-06 13:41:23 +00:00
|
|
|
void EffectFrameImpl::setIcon(const QIcon& icon)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
m_icon = icon;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (isCrossFade()) {
|
2010-08-07 14:08:34 +00:00
|
|
|
m_sceneFrame->crossFadeIcon();
|
2010-07-18 16:32:37 +00:00
|
|
|
}
|
2013-12-06 13:41:23 +00:00
|
|
|
if (m_iconSize.isEmpty() && !m_icon.availableSizes().isEmpty()) { // Set a size if we don't already have one
|
2021-05-13 16:38:42 +00:00
|
|
|
setIconSize(m_icon.availableSizes().constFirst());
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
m_sceneFrame->freeIconFrame();
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
const QSize& EffectFrameImpl::iconSize() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_iconSize;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setIconSize(const QSize& size)
|
|
|
|
{
|
|
|
|
if (m_iconSize == size) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
m_iconSize = size;
|
|
|
|
autoResize();
|
2010-07-20 21:11:03 +00:00
|
|
|
m_sceneFrame->freeIconFrame();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
void EffectFrameImpl::plasmaThemeChanged()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
free();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void EffectFrameImpl::render(const QRegion ®ion, double opacity, double frameOpacity)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (m_geometry.isEmpty()) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return; // Nothing to display
|
2010-07-24 16:29:16 +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
|
|
|
m_shader = nullptr;
|
2015-12-03 08:50:40 +00:00
|
|
|
setScreenProjectionMatrix(static_cast<EffectsHandlerImpl*>(effects)->scene()->screenProjectionMatrix());
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->paintEffectFrame(this, region, opacity, frameOpacity);
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::finalRender(QRegion region, double opacity, double frameOpacity) const
|
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
m_sceneFrame->render(region, opacity, frameOpacity);
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
Qt::Alignment EffectFrameImpl::alignment() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_alignment;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2010-12-04 10:01:57 +00:00
|
|
|
|
|
|
|
void
|
2011-01-30 14:34:42 +00:00
|
|
|
EffectFrameImpl::align(QRect &geometry)
|
2010-12-04 10:01:57 +00:00
|
|
|
{
|
2011-01-30 14:34:42 +00:00
|
|
|
if (m_alignment & Qt::AlignLeft)
|
|
|
|
geometry.moveLeft(m_point.x());
|
|
|
|
else if (m_alignment & Qt::AlignRight)
|
|
|
|
geometry.moveLeft(m_point.x() - geometry.width());
|
2010-12-04 10:01:57 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
geometry.moveLeft(m_point.x() - geometry.width() / 2);
|
|
|
|
if (m_alignment & Qt::AlignTop)
|
|
|
|
geometry.moveTop(m_point.y());
|
|
|
|
else if (m_alignment & Qt::AlignBottom)
|
|
|
|
geometry.moveTop(m_point.y() - geometry.height());
|
2010-12-04 10:01:57 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
geometry.moveTop(m_point.y() - geometry.height() / 2);
|
2010-12-04 10:01:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setAlignment(Qt::Alignment alignment)
|
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
m_alignment = alignment;
|
2011-01-30 14:34:42 +00:00
|
|
|
align(m_geometry);
|
|
|
|
setGeometry(m_geometry);
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setPosition(const QPoint& point)
|
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
m_point = point;
|
2010-12-04 10:01:57 +00:00
|
|
|
QRect geometry = m_geometry; // this is important, setGeometry need call repaint for old & new geometry
|
2011-01-30 14:34:42 +00:00
|
|
|
align(geometry);
|
|
|
|
setGeometry(geometry);
|
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
|
|
|
const QString& EffectFrameImpl::text() const
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2010-07-18 16:32:37 +00:00
|
|
|
return m_text;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setText(const QString& text)
|
|
|
|
{
|
|
|
|
if (m_text == text) {
|
2010-07-18 16:32:37 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
if (isCrossFade()) {
|
2010-08-07 14:08:34 +00:00
|
|
|
m_sceneFrame->crossFadeText();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
m_text = text;
|
|
|
|
QRect oldGeom = m_geometry;
|
|
|
|
autoResize();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (oldGeom == m_geometry) {
|
|
|
|
// Wasn't updated in autoResize()
|
2010-07-18 16:32:37 +00:00
|
|
|
m_sceneFrame->freeTextFrame();
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-18 16:32:37 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void EffectFrameImpl::setSelection(const QRect& selection)
|
|
|
|
{
|
|
|
|
if (selection == m_selectionGeometry) {
|
2010-07-26 20:00:04 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-26 20:00:04 +00:00
|
|
|
m_selectionGeometry = selection;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (m_selectionGeometry.size() != m_selection.frameSize().toSize()) {
|
|
|
|
m_selection.resizeFrame(m_selectionGeometry.size());
|
|
|
|
}
|
2010-07-26 20:00:04 +00:00
|
|
|
// TODO; optimize to only recreate when resizing
|
|
|
|
m_sceneFrame->freeSelection();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2010-07-26 20:00:04 +00:00
|
|
|
|
2010-07-18 16:32:37 +00:00
|
|
|
void EffectFrameImpl::autoResize()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (m_static)
|
2010-07-18 16:32:37 +00:00
|
|
|
return; // Not automatically resizing
|
|
|
|
|
|
|
|
QRect geometry;
|
|
|
|
// Set size
|
2011-01-30 14:34:42 +00:00
|
|
|
if (!m_text.isEmpty()) {
|
|
|
|
QFontMetrics metrics(m_font);
|
|
|
|
geometry.setSize(metrics.size(0, m_text));
|
|
|
|
}
|
|
|
|
if (!m_icon.isNull() && !m_iconSize.isEmpty()) {
|
|
|
|
geometry.setLeft(-m_iconSize.width());
|
|
|
|
if (m_iconSize.height() > geometry.height())
|
|
|
|
geometry.setHeight(m_iconSize.height());
|
2010-07-18 16:32:37 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
align(geometry);
|
|
|
|
setGeometry(geometry);
|
|
|
|
}
|
|
|
|
|
2011-02-17 18:35:08 +00:00
|
|
|
QColor EffectFrameImpl::styledTextColor()
|
|
|
|
{
|
2013-07-22 14:10:47 +00:00
|
|
|
return m_theme->color(Plasma::Theme::TextColor);
|
2011-02-17 18:35:08 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
} // namespace
|