Initial import of support for new KDecoration2 based decorations
NOTE: this is not working completely yet, lots of code is still ifdefed other parts are still broken. The main difference for the new decoration API is that it is neither QWidget nor QWindow based. It's just a QObject which processes input events and has a paint method to render the decoration. This means all the workarounds for the QWidget interception are removed. Also the paint redirector is removed. Instead each compositor has now its own renderer which can be optimized for the specific case. E.g. the OpenGL compositor renders to a scratch image which gets copied into the combined texture, the XRender compositor copies into the XPixmaps. Input events are also changed. The events are composed into QMouseEvents and passed through the decoration, which might accept them. If they are not accpted we assume that it's a press on the decoration area allowing us to resize/move the window. Input events are not completely working yet, e.g. wheel events are not yet processed and double click on deco is not yet working. Overall KDecoration2 is way more stateful and KWin core needs more adjustments for it. E.g. borders are allowed to be disabled at any time.
This commit is contained in:
parent
2c78ff8bfd
commit
0030eb7f84
37 changed files with 1502 additions and 2144 deletions
|
@ -97,6 +97,8 @@ set_package_properties(KF5DocTools PROPERTIES
|
||||||
)
|
)
|
||||||
add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation")
|
add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation")
|
||||||
|
|
||||||
|
find_package(KDecoration2 CONFIG REQUIRED)
|
||||||
|
|
||||||
if(${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")
|
if(${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")
|
||||||
find_package(OpenGL)
|
find_package(OpenGL)
|
||||||
set_package_properties(OpenGL PROPERTIES DESCRIPTION "The OpenGL libraries"
|
set_package_properties(OpenGL PROPERTIES DESCRIPTION "The OpenGL libraries"
|
||||||
|
@ -313,7 +315,6 @@ set(kwin_KDEINIT_SRCS
|
||||||
main.cpp
|
main.cpp
|
||||||
options.cpp
|
options.cpp
|
||||||
outline.cpp
|
outline.cpp
|
||||||
decorations.cpp
|
|
||||||
events.cpp
|
events.cpp
|
||||||
killwindow.cpp
|
killwindow.cpp
|
||||||
geometrytip.cpp
|
geometrytip.cpp
|
||||||
|
@ -321,7 +322,6 @@ set(kwin_KDEINIT_SRCS
|
||||||
shadow.cpp
|
shadow.cpp
|
||||||
sm.cpp
|
sm.cpp
|
||||||
group.cpp
|
group.cpp
|
||||||
bridge.cpp
|
|
||||||
manage.cpp
|
manage.cpp
|
||||||
overlaywindow.cpp
|
overlaywindow.cpp
|
||||||
activation.cpp
|
activation.cpp
|
||||||
|
@ -342,7 +342,6 @@ set(kwin_KDEINIT_SRCS
|
||||||
effects.cpp
|
effects.cpp
|
||||||
effectloader.cpp
|
effectloader.cpp
|
||||||
compositingprefs.cpp
|
compositingprefs.cpp
|
||||||
paintredirector.cpp
|
|
||||||
virtualdesktops.cpp
|
virtualdesktops.cpp
|
||||||
xcbutils.cpp
|
xcbutils.cpp
|
||||||
scripting/scripting.cpp
|
scripting/scripting.cpp
|
||||||
|
@ -354,6 +353,10 @@ set(kwin_KDEINIT_SRCS
|
||||||
scripting/scripting_model.cpp
|
scripting/scripting_model.cpp
|
||||||
scripting/dbuscall.cpp
|
scripting/dbuscall.cpp
|
||||||
scripting/screenedgeitem.cpp
|
scripting/screenedgeitem.cpp
|
||||||
|
decorations/decoratedclient.cpp
|
||||||
|
decorations/decorationbridge.cpp
|
||||||
|
decorations/settings.cpp
|
||||||
|
decorations/decorationrenderer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(KWIN_BUILD_TABBOX)
|
if(KWIN_BUILD_TABBOX)
|
||||||
|
@ -445,6 +448,8 @@ set(kwin_KDE_LIBS
|
||||||
KF5::Service
|
KF5::Service
|
||||||
KF5::Plasma
|
KF5::Plasma
|
||||||
KF5::WindowSystem
|
KF5::WindowSystem
|
||||||
|
KDecoration2::KDecoration
|
||||||
|
KDecoration2::KDecoration2Private
|
||||||
)
|
)
|
||||||
|
|
||||||
set(kwin_XLIB_LIBS
|
set(kwin_XLIB_LIBS
|
||||||
|
|
380
bridge.cpp
380
bridge.cpp
|
@ -1,380 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#include "bridge.h"
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
#include "cursor.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
#include <kconfiggroup.h>
|
|
||||||
#include "composite.h"
|
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "virtualdesktops.h"
|
|
||||||
#include "workspace.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
Bridge::Bridge(Client* cl)
|
|
||||||
: c(cl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BRIDGE_HELPER( rettype, prototype, args1, args2, cst ) \
|
|
||||||
rettype Bridge::prototype ( args1 ) cst \
|
|
||||||
{ \
|
|
||||||
return c->prototype( args2 ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BRIDGE_HELPER(bool, isCloseable, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isMaximizable, , , const)
|
|
||||||
BRIDGE_HELPER(Bridge::MaximizeMode, maximizeMode, , , const)
|
|
||||||
BRIDGE_HELPER(Bridge::QuickTileMode, quickTileMode, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isMinimizable, , , const)
|
|
||||||
BRIDGE_HELPER(bool, providesContextHelp, , , const)
|
|
||||||
BRIDGE_HELPER(int, desktop, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isModal, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isShadeable, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isShade, , , const)
|
|
||||||
BRIDGE_HELPER(bool, keepAbove, , , const)
|
|
||||||
BRIDGE_HELPER(bool, keepBelow, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isMovable, , , const)
|
|
||||||
BRIDGE_HELPER(bool, isResizable, , , const)
|
|
||||||
BRIDGE_HELPER(void, processMousePressEvent, QMouseEvent* e, e,)
|
|
||||||
BRIDGE_HELPER(QRect, geometry, , , const)
|
|
||||||
BRIDGE_HELPER(void, closeWindow, , ,)
|
|
||||||
BRIDGE_HELPER(void, maximize, MaximizeMode m, m,)
|
|
||||||
BRIDGE_HELPER(void, minimize, , ,)
|
|
||||||
BRIDGE_HELPER(void, showContextHelp, , ,)
|
|
||||||
BRIDGE_HELPER(void, setDesktop, int desktop, desktop,)
|
|
||||||
BRIDGE_HELPER(QPalette, palette, , , const)
|
|
||||||
|
|
||||||
bool Bridge::isActive() const
|
|
||||||
{
|
|
||||||
return c->isActive() || (c->tabGroup() && c->tabGroup()->isActive());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::setKeepAbove(bool set)
|
|
||||||
{
|
|
||||||
if (c->keepAbove() != set)
|
|
||||||
workspace()->performWindowOperation(c, KeepAboveOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::setKeepBelow(bool set)
|
|
||||||
{
|
|
||||||
if (c->keepBelow() != set)
|
|
||||||
workspace()->performWindowOperation(c, KeepBelowOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
NET::WindowType Bridge::windowType(unsigned long supported_types) const
|
|
||||||
{
|
|
||||||
return c->windowType(false, supported_types);
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon Bridge::icon() const
|
|
||||||
{
|
|
||||||
return c->icon();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bridge::isSetShade() const
|
|
||||||
{
|
|
||||||
return c->shadeMode() != ShadeNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::showWindowMenu(const QPoint &p)
|
|
||||||
{
|
|
||||||
workspace()->showWindowMenu(QRect(p,p), c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::showWindowMenu(const QPoint &p, long id)
|
|
||||||
{
|
|
||||||
Client *cc = clientForId(id);
|
|
||||||
if (!cc)
|
|
||||||
cc = c;
|
|
||||||
workspace()->showWindowMenu(QRect(p,p), cc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::showWindowMenu(const QRect &p)
|
|
||||||
{
|
|
||||||
workspace()->showWindowMenu(p, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::showApplicationMenu(const QPoint &p)
|
|
||||||
{
|
|
||||||
#ifdef KWIN_BUILD_KAPPMENU
|
|
||||||
c->showApplicationMenu(p);
|
|
||||||
#else
|
|
||||||
Q_UNUSED(p)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bridge::menuAvailable() const
|
|
||||||
{
|
|
||||||
#ifdef KWIN_BUILD_KAPPMENU
|
|
||||||
return c->menuAvailable();
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::performWindowOperation(WindowOperation op)
|
|
||||||
{
|
|
||||||
workspace()->performWindowOperation(c, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::setMask(const QRegion& r, int mode)
|
|
||||||
{
|
|
||||||
c->setMask(r, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bridge::isPreview() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect Bridge::iconGeometry() const
|
|
||||||
{
|
|
||||||
NETRect r = c->info->iconGeometry();
|
|
||||||
return QRect(r.pos.x, r.pos.y, r.size.width, r.size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
WId Bridge::windowId() const
|
|
||||||
{
|
|
||||||
return c->window();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::titlebarDblClickOperation()
|
|
||||||
{
|
|
||||||
workspace()->performWindowOperation(c, options->operationTitlebarDblClick());
|
|
||||||
c->dontMoveResize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::titlebarMouseWheelOperation(int delta)
|
|
||||||
{
|
|
||||||
c->performMouseCommand(options->operationTitlebarMouseWheel(delta), Cursor::pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::setShade(bool set)
|
|
||||||
{
|
|
||||||
c->setShade(set ? ShadeNormal : ShadeNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bridge::currentDesktop() const
|
|
||||||
{
|
|
||||||
return VirtualDesktopManager::self()->current();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::WindowFlags Bridge::initialWFlags() const
|
|
||||||
{
|
|
||||||
return Qt::WindowDoesNotAcceptFocus;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRegion Bridge::unobscuredRegion(const QRegion& r) const
|
|
||||||
{
|
|
||||||
QRegion reg(r);
|
|
||||||
const ToplevelList stacking_order = workspace()->stackingOrder();
|
|
||||||
int pos = stacking_order.indexOf(c);
|
|
||||||
++pos;
|
|
||||||
for (; pos < stacking_order.count(); ++pos) {
|
|
||||||
Client *client = qobject_cast<Client*>(stacking_order[pos]);
|
|
||||||
if (!client) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!client->isShown(true))
|
|
||||||
continue; // these don't obscure the window
|
|
||||||
if (c->isOnAllDesktops()) {
|
|
||||||
if (!client->isOnCurrentDesktop())
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
if (!client->isOnDesktop(c->desktop()))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* the clients all have their mask-regions in local coords
|
|
||||||
so we have to translate them to a shared coord system
|
|
||||||
we choose ours */
|
|
||||||
int dx = client->x() - c->x();
|
|
||||||
int dy = client->y() - c->y();
|
|
||||||
QRegion creg = client->mask();
|
|
||||||
creg.translate(dx, dy);
|
|
||||||
reg -= creg;
|
|
||||||
if (reg.isEmpty()) {
|
|
||||||
// early out, we are completely obscured
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::grabXServer(bool grab)
|
|
||||||
{
|
|
||||||
if (grab)
|
|
||||||
KWin::grabXServer();
|
|
||||||
else
|
|
||||||
KWin::ungrabXServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Bridge::compositingActive() const
|
|
||||||
{
|
|
||||||
return Compositor::compositing();
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect Bridge::transparentRect() const
|
|
||||||
{
|
|
||||||
return c->transparentRect().translated(-c->decorationRect().topLeft());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::update(const QRegion ®ion)
|
|
||||||
{
|
|
||||||
if (c->paintRedirector) {
|
|
||||||
c->paintRedirector->addRepaint(region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//BEGIN TABBING
|
|
||||||
|
|
||||||
Client *Bridge::clientForId(long id) const
|
|
||||||
{
|
|
||||||
Client* client = reinterpret_cast<Client*>(id);
|
|
||||||
if (!workspace()->hasClient(client)) {
|
|
||||||
qWarning() << "****** ARBITRARY CODE EXECUTION ATTEMPT DETECTED ******" << id;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bridge::tabCount() const
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
return c->tabGroup()->count();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long Bridge::tabId(int idx) const
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
return tabIdOf(c->tabGroup()->clients().at(idx));
|
|
||||||
return tabIdOf(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon Bridge::icon(int idx) const
|
|
||||||
{
|
|
||||||
if (c->tabGroup()) {
|
|
||||||
return c->tabGroup()->clients().at(idx)->icon();
|
|
||||||
}
|
|
||||||
return icon();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Bridge::caption() const
|
|
||||||
{
|
|
||||||
return c->caption(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Bridge::caption(int idx) const
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
return c->tabGroup()->clients().at(idx)->caption(true, true);
|
|
||||||
return c->caption(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
long Bridge::currentTabId() const
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
return tabIdOf(c->tabGroup()->current());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::setCurrentTab(long id)
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
c->tabGroup()->setCurrent(clientForId(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::tab_A_before_B(long A, long B)
|
|
||||||
{
|
|
||||||
if (!B) {
|
|
||||||
if (c->tabGroup()) {
|
|
||||||
if (Client *a = clientForId(A))
|
|
||||||
a->untab();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Client *a = clientForId(A))
|
|
||||||
if (Client *b = clientForId(B))
|
|
||||||
if (a != b)
|
|
||||||
a->tabBefore(b, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::tab_A_behind_B(long A, long B)
|
|
||||||
{
|
|
||||||
if (!B) {
|
|
||||||
if (c->tabGroup()) {
|
|
||||||
if (Client *a = clientForId(A))
|
|
||||||
a->untab();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Client *a = clientForId(A))
|
|
||||||
if (Client *b = clientForId(B))
|
|
||||||
if (a != b)
|
|
||||||
a->tabBehind(b, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Bridge::untab(long id, const QRect& newGeom)
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
if (Client* client = clientForId(id))
|
|
||||||
if (client->untab(newGeom)) {
|
|
||||||
if (options->focusPolicyIsReasonable())
|
|
||||||
workspace()->takeActivity(client, Workspace::ActivityFocus | Workspace::ActivityRaise);
|
|
||||||
workspace()->raiseClient(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::closeTab(long id)
|
|
||||||
{
|
|
||||||
if (Client* client = clientForId(id))
|
|
||||||
client->closeWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bridge::closeTabGroup()
|
|
||||||
{
|
|
||||||
if (c->tabGroup())
|
|
||||||
c->tabGroup()->closeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
//END TABBING
|
|
||||||
|
|
||||||
bool Bridge::isOnAllDesktopsAvailable() const
|
|
||||||
{
|
|
||||||
return VirtualDesktopManager::self()->count() > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
KDecoration::WindowOperation Bridge::buttonToWindowOperation(Qt::MouseButtons button)
|
|
||||||
{
|
|
||||||
return c->mouseButtonToWindowOperation(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
113
bridge.h
113
bridge.h
|
@ -1,113 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#ifndef KWIN_BRIDGE_H
|
|
||||||
#define KWIN_BRIDGE_H
|
|
||||||
|
|
||||||
#include <kdecorationbridge.h>
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
class Client;
|
|
||||||
|
|
||||||
class Bridge : public KDecorationBridge
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Bridge(Client* cl);
|
|
||||||
virtual bool isActive() const override;
|
|
||||||
virtual bool isCloseable() const override;
|
|
||||||
virtual bool isMaximizable() const override;
|
|
||||||
virtual MaximizeMode maximizeMode() const override;
|
|
||||||
virtual QuickTileMode quickTileMode() const override;
|
|
||||||
virtual bool isMinimizable() const override;
|
|
||||||
virtual bool providesContextHelp() const override;
|
|
||||||
virtual int desktop() const override;
|
|
||||||
bool isOnAllDesktopsAvailable() const override;
|
|
||||||
virtual bool isModal() const override;
|
|
||||||
virtual bool isShadeable() const override;
|
|
||||||
virtual bool isShade() const override;
|
|
||||||
virtual bool isSetShade() const override;
|
|
||||||
virtual bool keepAbove() const override;
|
|
||||||
virtual bool keepBelow() const override;
|
|
||||||
virtual bool isMovable() const override;
|
|
||||||
virtual bool isResizable() const override;
|
|
||||||
virtual NET::WindowType windowType(unsigned long supported_types) const override;
|
|
||||||
virtual QIcon icon() const override;
|
|
||||||
virtual QString caption() const override;
|
|
||||||
virtual void processMousePressEvent(QMouseEvent*) override;
|
|
||||||
virtual void showWindowMenu(const QPoint &) override;
|
|
||||||
virtual void showWindowMenu(const QRect &) override;
|
|
||||||
virtual void showApplicationMenu(const QPoint &) override;
|
|
||||||
virtual bool menuAvailable() const override;
|
|
||||||
virtual void performWindowOperation(WindowOperation) override;
|
|
||||||
virtual void setMask(const QRegion&, int) override;
|
|
||||||
virtual bool isPreview() const override;
|
|
||||||
virtual QRect geometry() const override;
|
|
||||||
virtual QRect iconGeometry() const override;
|
|
||||||
virtual QRegion unobscuredRegion(const QRegion& r) const override;
|
|
||||||
virtual WId windowId() const override;
|
|
||||||
virtual void closeWindow() override;
|
|
||||||
virtual void maximize(MaximizeMode mode) override;
|
|
||||||
virtual void minimize() override;
|
|
||||||
virtual void showContextHelp() override;
|
|
||||||
virtual void setDesktop(int desktop) override;
|
|
||||||
virtual void titlebarDblClickOperation() override;
|
|
||||||
virtual void titlebarMouseWheelOperation(int delta) override;
|
|
||||||
virtual void setShade(bool set) override;
|
|
||||||
virtual void setKeepAbove(bool) override;
|
|
||||||
virtual void setKeepBelow(bool) override;
|
|
||||||
virtual int currentDesktop() const override;
|
|
||||||
virtual Qt::WindowFlags initialWFlags() const override;
|
|
||||||
virtual void grabXServer(bool grab) override;
|
|
||||||
|
|
||||||
virtual bool compositingActive() const override;
|
|
||||||
virtual QRect transparentRect() const override;
|
|
||||||
|
|
||||||
virtual void update(const QRegion ®ion) override;
|
|
||||||
virtual QPalette palette() const override;
|
|
||||||
|
|
||||||
// Window tabbing
|
|
||||||
virtual QString caption(int idx) const override;
|
|
||||||
virtual void closeTab(long id) override;
|
|
||||||
virtual void closeTabGroup() override;
|
|
||||||
virtual long currentTabId() const override;
|
|
||||||
virtual QIcon icon(int idx) const override;
|
|
||||||
virtual void setCurrentTab(long id) override;
|
|
||||||
virtual void showWindowMenu(const QPoint &, long id) override;
|
|
||||||
virtual void tab_A_before_B(long A, long B) override;
|
|
||||||
virtual void tab_A_behind_B(long A, long B) override;
|
|
||||||
virtual int tabCount() const override;
|
|
||||||
virtual long tabId(int idx) const override;
|
|
||||||
virtual void untab(long id, const QRect& newGeom) override;
|
|
||||||
|
|
||||||
virtual WindowOperation buttonToWindowOperation(Qt::MouseButtons button) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Client *clientForId(long id) const;
|
|
||||||
static inline long tabIdOf(Client *c) {
|
|
||||||
return reinterpret_cast<long>(c);
|
|
||||||
}
|
|
||||||
Client* c;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#endif
|
|
285
client.cpp
285
client.cpp
|
@ -28,21 +28,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "appmenu.h"
|
#include "appmenu.h"
|
||||||
#endif
|
#endif
|
||||||
#include "atoms.h"
|
#include "atoms.h"
|
||||||
#include "bridge.h"
|
|
||||||
#include "client_machine.h"
|
#include "client_machine.h"
|
||||||
#include "composite.h"
|
#include "composite.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "focuschain.h"
|
#include "focuschain.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "shadow.h"
|
#include "shadow.h"
|
||||||
#ifdef KWIN_BUILD_TABBOX
|
#ifdef KWIN_BUILD_TABBOX
|
||||||
#include "tabbox.h"
|
#include "tabbox.h"
|
||||||
#endif
|
#endif
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "screenedge.h"
|
#include "screenedge.h"
|
||||||
|
#include "decorations/decorationbridge.h"
|
||||||
|
#include "decorations/decoratedclient.h"
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
#include <KDecoration2/DecoratedClient>
|
||||||
// KDE
|
// KDE
|
||||||
#include <KWindowSystem>
|
#include <KWindowSystem>
|
||||||
#include <KColorScheme>
|
#include <KColorScheme>
|
||||||
|
@ -181,8 +182,7 @@ Client::Client()
|
||||||
, m_client()
|
, m_client()
|
||||||
, m_wrapper()
|
, m_wrapper()
|
||||||
, m_frame()
|
, m_frame()
|
||||||
, decoration(NULL)
|
, m_decoration(nullptr)
|
||||||
, bridge(new Bridge(this))
|
|
||||||
, m_activityUpdatesBlocked(false)
|
, m_activityUpdatesBlocked(false)
|
||||||
, m_blockedActivityUpdatesRequireTransients(false)
|
, m_blockedActivityUpdatesRequireTransients(false)
|
||||||
, m_moveResizeGrabWindow()
|
, m_moveResizeGrabWindow()
|
||||||
|
@ -211,16 +211,7 @@ Client::Client()
|
||||||
, block_geometry_updates(0)
|
, block_geometry_updates(0)
|
||||||
, pending_geometry_update(PendingGeometryNone)
|
, pending_geometry_update(PendingGeometryNone)
|
||||||
, shade_geometry_change(false)
|
, shade_geometry_change(false)
|
||||||
, border_left(0)
|
|
||||||
, border_right(0)
|
|
||||||
, border_top(0)
|
|
||||||
, border_bottom(0)
|
|
||||||
, padding_left(0)
|
|
||||||
, padding_right(0)
|
|
||||||
, padding_top(0)
|
|
||||||
, padding_bottom(0)
|
|
||||||
, sm_stacking_order(-1)
|
, sm_stacking_order(-1)
|
||||||
, paintRedirector(0)
|
|
||||||
, m_firstInTabBox(false)
|
, m_firstInTabBox(false)
|
||||||
, electricMaximizing(false)
|
, electricMaximizing(false)
|
||||||
, activitiesDefined(false)
|
, activitiesDefined(false)
|
||||||
|
@ -306,12 +297,6 @@ Client::Client()
|
||||||
connect(clientMachine(), &ClientMachine::localhostChanged, this, &Client::updateCaption);
|
connect(clientMachine(), &ClientMachine::localhostChanged, this, &Client::updateCaption);
|
||||||
connect(options, &Options::condensedTitleChanged, this, &Client::updateCaption);
|
connect(options, &Options::condensedTitleChanged, this, &Client::updateCaption);
|
||||||
|
|
||||||
m_connections << connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, [this]() {
|
|
||||||
if (decoration) {
|
|
||||||
decoration->onAllDesktopsAvailableChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// SELI TODO: Initialize xsizehints??
|
// SELI TODO: Initialize xsizehints??
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,10 +316,9 @@ Client::~Client()
|
||||||
assert(m_client == XCB_WINDOW_NONE);
|
assert(m_client == XCB_WINDOW_NONE);
|
||||||
assert(m_wrapper == XCB_WINDOW_NONE);
|
assert(m_wrapper == XCB_WINDOW_NONE);
|
||||||
//assert( frameId() == None );
|
//assert( frameId() == None );
|
||||||
assert(decoration == NULL);
|
Q_ASSERT(m_decoration == nullptr);
|
||||||
assert(block_geometry_updates == 0);
|
assert(block_geometry_updates == 0);
|
||||||
assert(!check_active_modal);
|
assert(!check_active_modal);
|
||||||
delete bridge;
|
|
||||||
for (auto it = m_connections.constBegin(); it != m_connections.constEnd(); ++it) {
|
for (auto it = m_connections.constBegin(); it != m_connections.constEnd(); ++it) {
|
||||||
disconnect(*it);
|
disconnect(*it);
|
||||||
}
|
}
|
||||||
|
@ -461,6 +445,7 @@ void Client::updateInputWindow()
|
||||||
|
|
||||||
QRegion region;
|
QRegion region;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (!noBorder()) {
|
if (!noBorder()) {
|
||||||
// This function is implemented as a slot to avoid breaking binary
|
// This function is implemented as a slot to avoid breaking binary
|
||||||
// compatibility
|
// compatibility
|
||||||
|
@ -468,6 +453,7 @@ void Client::updateInputWindow()
|
||||||
Q_RETURN_ARG(QRegion, region),
|
Q_RETURN_ARG(QRegion, region),
|
||||||
Q_ARG(KDecorationDefines::Region, KDecorationDefines::ExtendedBorderRegion));
|
Q_ARG(KDecorationDefines::Region, KDecorationDefines::ExtendedBorderRegion));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (region.isEmpty()) {
|
if (region.isEmpty()) {
|
||||||
m_decoInputExtent.reset();
|
m_decoInputExtent.reset();
|
||||||
|
@ -507,7 +493,7 @@ void Client::updateInputWindow()
|
||||||
void Client::updateDecoration(bool check_workspace_pos, bool force)
|
void Client::updateDecoration(bool check_workspace_pos, bool force)
|
||||||
{
|
{
|
||||||
if (!force &&
|
if (!force &&
|
||||||
((decoration == NULL && noBorder()) || (decoration != NULL && !noBorder())))
|
((m_decoration == NULL && noBorder()) || (m_decoration != NULL && !noBorder())))
|
||||||
return;
|
return;
|
||||||
QRect oldgeom = geometry();
|
QRect oldgeom = geometry();
|
||||||
blockGeometryUpdates(true);
|
blockGeometryUpdates(true);
|
||||||
|
@ -521,55 +507,19 @@ void Client::updateDecoration(bool check_workspace_pos, bool force)
|
||||||
checkWorkspacePosition(oldgeom);
|
checkWorkspacePosition(oldgeom);
|
||||||
updateInputWindow();
|
updateInputWindow();
|
||||||
blockGeometryUpdates(false);
|
blockGeometryUpdates(false);
|
||||||
if (!noBorder())
|
|
||||||
decoration->show();
|
|
||||||
updateFrameExtents();
|
updateFrameExtents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::createDecoration(const QRect& oldgeom)
|
void Client::createDecoration(const QRect& oldgeom)
|
||||||
{
|
{
|
||||||
setMask(QRegion()); // Reset shape mask
|
m_decoration = Decoration::DecorationBridge::self()->createDecoration(this);
|
||||||
if (decorationPlugin()->isDisabled()) {
|
if (m_decoration) {
|
||||||
decoration = NULL;
|
m_decoration->update();
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
decoration = decorationPlugin()->createDecoration(bridge);
|
|
||||||
}
|
}
|
||||||
connect(this, &Client::iconChanged, decoration, &KDecoration::iconChanged);
|
|
||||||
connect(this, &Client::shadeChanged, decoration, &KDecoration::shadeChanged);
|
|
||||||
connect(this, &Client::desktopChanged, decoration, &KDecoration::desktopChanged);
|
|
||||||
connect(this, &Client::captionChanged, decoration, &KDecoration::captionChanged);
|
|
||||||
connect(this, &Client::activeChanged, decoration, &KDecoration::activeChanged);
|
|
||||||
auto signalMaximizeChanged = static_cast<void (Client::*)(Client*, KDecorationDefines::MaximizeMode)>(&Client::clientMaximizedStateChanged);
|
|
||||||
connect(this, signalMaximizeChanged, decoration, &KDecoration::maximizeChanged);
|
|
||||||
auto slotKeepAbove = static_cast<void(KDecoration::*)(bool)>(&KDecoration::keepAboveChanged);
|
|
||||||
connect(this, &Client::keepAboveChanged, decoration, slotKeepAbove);
|
|
||||||
auto slotKeepBelow = static_cast<void(KDecoration::*)(bool)>(&KDecoration::keepBelowChanged);
|
|
||||||
connect(this, &Client::keepBelowChanged, decoration, slotKeepBelow);
|
|
||||||
#ifdef KWIN_BUILD_KAPPMENU
|
|
||||||
connect(this, SIGNAL(showRequest()), decoration, SIGNAL(showRequest()));
|
|
||||||
connect(this, SIGNAL(appMenuAvailable()), decoration, SIGNAL(appMenuAvailable()));
|
|
||||||
connect(this, SIGNAL(appMenuUnavailable()), decoration, SIGNAL(appMenuUnavailable()));
|
|
||||||
connect(this, SIGNAL(menuHidden()), decoration, SIGNAL(menuHidden()));
|
|
||||||
#endif
|
|
||||||
// TODO: Check decoration's minimum size?
|
|
||||||
decoration->init();
|
|
||||||
if (decoration->widget()) {
|
|
||||||
decoration->widget()->installEventFilter(this);
|
|
||||||
decoration->window()->setParent(m_frameWrapper.data());
|
|
||||||
} else if (decoration->window()) {
|
|
||||||
decoration->window()->installEventFilter(this);
|
|
||||||
xcb_reparent_window(connection(), decoration->window()->winId(), frameId(), 0, 0);
|
|
||||||
}
|
|
||||||
decoration->window()->lower();
|
|
||||||
decoration->borders(border_left, border_right, border_top, border_bottom);
|
|
||||||
padding_left = padding_right = padding_top = padding_bottom = 0;
|
|
||||||
decoration->padding(padding_left, padding_right, padding_top, padding_bottom);
|
|
||||||
Xcb::moveWindow(decoration->window()->winId(), -padding_left, -padding_top);
|
|
||||||
move(calculateGravitation(false));
|
move(calculateGravitation(false));
|
||||||
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
||||||
if (Compositor::compositing()) {
|
if (Compositor::compositing()) {
|
||||||
paintRedirector = PaintRedirector::create(this, decoration);
|
|
||||||
discardWindowPixmap();
|
discardWindowPixmap();
|
||||||
}
|
}
|
||||||
emit geometryShapeChanged(this, oldgeom);
|
emit geometryShapeChanged(this, oldgeom);
|
||||||
|
@ -578,13 +528,10 @@ void Client::createDecoration(const QRect& oldgeom)
|
||||||
void Client::destroyDecoration()
|
void Client::destroyDecoration()
|
||||||
{
|
{
|
||||||
QRect oldgeom = geometry();
|
QRect oldgeom = geometry();
|
||||||
if (decoration != NULL) {
|
if (m_decoration) {
|
||||||
delete decoration;
|
delete m_decoration;
|
||||||
decoration = NULL;
|
m_decoration = nullptr;
|
||||||
paintRedirector = NULL;
|
|
||||||
QPoint grav = calculateGravitation(true);
|
QPoint grav = calculateGravitation(true);
|
||||||
border_left = border_right = border_top = border_bottom = 0;
|
|
||||||
setMask(QRegion()); // Reset shape mask
|
|
||||||
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
||||||
move(grav);
|
move(grav);
|
||||||
if (compositing())
|
if (compositing())
|
||||||
|
@ -598,6 +545,7 @@ void Client::destroyDecoration()
|
||||||
|
|
||||||
bool Client::checkBorderSizes(bool also_resize)
|
bool Client::checkBorderSizes(bool also_resize)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (decoration == NULL)
|
if (decoration == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -630,25 +578,28 @@ bool Client::checkBorderSizes(bool also_resize)
|
||||||
QRect oldgeom = geometry();
|
QRect oldgeom = geometry();
|
||||||
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
|
||||||
checkWorkspacePosition(oldgeom);
|
checkWorkspacePosition(oldgeom);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::triggerDecorationRepaint()
|
void Client::triggerDecorationRepaint()
|
||||||
{
|
{
|
||||||
if (decoration && decoration->widget())
|
if (m_decoration) {
|
||||||
decoration->widget()->update();
|
m_decoration->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom, Client::CoordinateMode mode) const
|
void Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom, Client::CoordinateMode mode) const
|
||||||
{
|
{
|
||||||
QRect r = decoration->rect();
|
if (!m_decoration) {
|
||||||
if (mode == WindowRelative)
|
return;
|
||||||
r.translate(-padding_left, -padding_top);
|
}
|
||||||
|
QRect r = m_decoration->rect();
|
||||||
|
|
||||||
NETStrut strut = info->frameOverlap();
|
NETStrut strut = info->frameOverlap();
|
||||||
|
|
||||||
// Ignore the overlap strut when compositing is disabled
|
// Ignore the overlap strut when compositing is disabled
|
||||||
if (!compositing() || !decorationPlugin()->supportsFrameOverlap())
|
if (!compositing())
|
||||||
strut.left = strut.top = strut.right = strut.bottom = 0;
|
strut.left = strut.top = strut.right = strut.bottom = 0;
|
||||||
else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && strut.bottom == -1) {
|
else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && strut.bottom == -1) {
|
||||||
top = QRect(r.x(), r.y(), r.width(), r.height() / 3);
|
top = QRect(r.x(), r.y(), r.width(), r.height() / 3);
|
||||||
|
@ -658,20 +609,13 @@ void Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
top = QRect(r.x(), r.y(), r.width(), padding_top + border_top + strut.top);
|
top = QRect(r.x(), r.y(), r.width(), borderTop() + strut.top);
|
||||||
bottom = QRect(r.x(), r.y() + r.height() - padding_bottom - border_bottom - strut.bottom,
|
bottom = QRect(r.x(), r.y() + r.height() - borderBottom() - strut.bottom,
|
||||||
r.width(), padding_bottom + border_bottom + strut.bottom);
|
r.width(), borderBottom() + strut.bottom);
|
||||||
left = QRect(r.x(), r.y() + top.height(),
|
left = QRect(r.x(), r.y() + top.height(),
|
||||||
padding_left + border_left + strut.left, r.height() - top.height() - bottom.height());
|
borderLeft() + strut.left, r.height() - top.height() - bottom.height());
|
||||||
right = QRect(r.x() + r.width() - padding_right - border_right - strut.right, r.y() + top.height(),
|
right = QRect(r.x() + r.width() - borderRight() - strut.right, r.y() + top.height(),
|
||||||
padding_right + border_right + strut.right, r.height() - top.height() - bottom.height());
|
borderRight() + strut.right, r.height() - top.height() - bottom.height());
|
||||||
}
|
|
||||||
|
|
||||||
QRegion Client::decorationPendingRegion() const
|
|
||||||
{
|
|
||||||
if (!paintRedirector)
|
|
||||||
return QRegion();
|
|
||||||
return paintRedirector->scheduledRepaintRegion().translated(x() - padding_left, y() - padding_top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect Client::transparentRect() const
|
QRect Client::transparentRect() const
|
||||||
|
@ -681,7 +625,7 @@ QRect Client::transparentRect() const
|
||||||
|
|
||||||
NETStrut strut = info->frameOverlap();
|
NETStrut strut = info->frameOverlap();
|
||||||
// Ignore the strut when compositing is disabled or the decoration doesn't support it
|
// Ignore the strut when compositing is disabled or the decoration doesn't support it
|
||||||
if (!compositing() || !decorationPlugin()->supportsFrameOverlap())
|
if (!compositing())
|
||||||
strut.left = strut.top = strut.right = strut.bottom = 0;
|
strut.left = strut.top = strut.right = strut.bottom = 0;
|
||||||
else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && strut.bottom == -1)
|
else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && strut.bottom == -1)
|
||||||
return QRect();
|
return QRect();
|
||||||
|
@ -733,10 +677,10 @@ void Client::detectNoBorder()
|
||||||
void Client::updateFrameExtents()
|
void Client::updateFrameExtents()
|
||||||
{
|
{
|
||||||
NETStrut strut;
|
NETStrut strut;
|
||||||
strut.left = border_left;
|
strut.left = borderLeft();
|
||||||
strut.right = border_right;
|
strut.right = borderRight();
|
||||||
strut.top = border_top;
|
strut.top = borderTop();
|
||||||
strut.bottom = border_bottom;
|
strut.bottom = borderBottom();
|
||||||
info->setFrameExtents(strut);
|
info->setFrameExtents(strut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,32 +700,16 @@ void Client::detectGtkFrameExtents()
|
||||||
*/
|
*/
|
||||||
void Client::resizeDecoration(const QSize& s)
|
void Client::resizeDecoration(const QSize& s)
|
||||||
{
|
{
|
||||||
if (decoration == NULL)
|
if (m_decoration) {
|
||||||
return;
|
m_decoration->update();
|
||||||
QSize newSize = s + QSize(padding_left + padding_right, padding_top + padding_bottom);
|
updateInputWindow();
|
||||||
QSize oldSize = decoration->window()->size();
|
|
||||||
decoration->resize(newSize);
|
|
||||||
if (oldSize == newSize) {
|
|
||||||
QResizeEvent e(newSize, oldSize);
|
|
||||||
QObject *receiver = nullptr;
|
|
||||||
if (decoration->widget()) {
|
|
||||||
receiver = decoration->widget();
|
|
||||||
} else {
|
|
||||||
receiver = decoration->window();
|
|
||||||
}
|
|
||||||
QApplication::sendEvent(receiver, &e);
|
|
||||||
} else if (paintRedirector) { // oldSize != newSize
|
|
||||||
paintRedirector->resizePixmaps();
|
|
||||||
} else {
|
|
||||||
triggerDecorationRepaint();
|
|
||||||
}
|
}
|
||||||
Xcb::moveWindow(decoration->window()->winId(), -padding_left, -padding_top);
|
|
||||||
updateInputWindow();
|
updateInputWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::noBorder() const
|
bool Client::noBorder() const
|
||||||
{
|
{
|
||||||
return decorationPlugin()->isDisabled() || noborder || isFullScreen();
|
return noborder || isFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::userCanSetNoBorder() const
|
bool Client::userCanSetNoBorder() const
|
||||||
|
@ -870,59 +798,6 @@ void Client::updateInputShape()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::setMask(const QRegion& reg, int mode)
|
|
||||||
{
|
|
||||||
QRegion r = reg.translated(-padding_left, -padding_right) & QRect(0, 0, width(), height());
|
|
||||||
if (_mask == r)
|
|
||||||
return;
|
|
||||||
_mask = r;
|
|
||||||
xcb_connection_t *c = connection();
|
|
||||||
xcb_window_t shape_window = frameId();
|
|
||||||
if (shape()) {
|
|
||||||
// The same way of applying a shape without strange intermediate states like above
|
|
||||||
if (!shape_helper_window.isValid())
|
|
||||||
shape_helper_window.create(QRect(0, 0, 1, 1));
|
|
||||||
shape_window = shape_helper_window;
|
|
||||||
}
|
|
||||||
if (_mask.isEmpty()) {
|
|
||||||
xcb_shape_mask(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, shape_window, 0, 0, XCB_PIXMAP_NONE);
|
|
||||||
} else {
|
|
||||||
const QVector< QRect > rects = _mask.rects();
|
|
||||||
QVector< xcb_rectangle_t > xrects(rects.count());
|
|
||||||
for (int i = 0; i < rects.count(); ++i) {
|
|
||||||
const QRect &rect = rects.at(i);
|
|
||||||
xcb_rectangle_t xrect;
|
|
||||||
xrect.x = rect.x();
|
|
||||||
xrect.y = rect.y();
|
|
||||||
xrect.width = rect.width();
|
|
||||||
xrect.height = rect.height();
|
|
||||||
xrects[i] = xrect;
|
|
||||||
}
|
|
||||||
xcb_shape_rectangles(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, mode, shape_window,
|
|
||||||
0, 0, xrects.count(), xrects.constData());
|
|
||||||
}
|
|
||||||
if (shape()) {
|
|
||||||
// The rest of the applying using a temporary window
|
|
||||||
xcb_rectangle_t rec = { 0, 0, static_cast<uint16_t>(clientSize().width()),
|
|
||||||
static_cast<uint16_t>(clientSize().height()) };
|
|
||||||
xcb_shape_rectangles(c, XCB_SHAPE_SO_SUBTRACT, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
|
|
||||||
shape_helper_window, clientPos().x(), clientPos().y(), 1, &rec);
|
|
||||||
xcb_shape_combine(c, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING,
|
|
||||||
shape_helper_window, clientPos().x(), clientPos().y(), window());
|
|
||||||
xcb_shape_combine(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING,
|
|
||||||
frameId(), 0, 0, shape_helper_window);
|
|
||||||
}
|
|
||||||
emit geometryShapeChanged(this, geometry());
|
|
||||||
updateShape();
|
|
||||||
}
|
|
||||||
|
|
||||||
QRegion Client::mask() const
|
|
||||||
{
|
|
||||||
if (_mask.isEmpty())
|
|
||||||
return QRegion(0, 0, width(), height());
|
|
||||||
return _mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::hideClient(bool hide)
|
void Client::hideClient(bool hide)
|
||||||
{
|
{
|
||||||
if (hidden == hide)
|
if (hidden == hide)
|
||||||
|
@ -1066,8 +941,10 @@ void Client::setShade(ShadeMode mode)
|
||||||
|
|
||||||
// Decorations may turn off some borders when shaded
|
// Decorations may turn off some borders when shaded
|
||||||
// this has to happen _before_ the tab alignment since it will restrict the minimum geometry
|
// this has to happen _before_ the tab alignment since it will restrict the minimum geometry
|
||||||
|
#if 0
|
||||||
if (decoration)
|
if (decoration)
|
||||||
decoration->borders(border_left, border_right, border_top, border_bottom);
|
decoration->borders(border_left, border_right, border_top, border_bottom);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Update states of all other windows in this group
|
// Update states of all other windows in this group
|
||||||
if (tabGroup())
|
if (tabGroup())
|
||||||
|
@ -1079,7 +956,7 @@ void Client::setShade(ShadeMode mode)
|
||||||
return; // No real change in shaded state
|
return; // No real change in shaded state
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(decoration != NULL); // noborder windows can't be shaded
|
assert(m_decoration != NULL); // noborder windows can't be shaded
|
||||||
GeometryUpdatesBlocker blocker(this);
|
GeometryUpdatesBlocker blocker(this);
|
||||||
|
|
||||||
// TODO: All this unmapping, resizing etc. feels too much duplicated from elsewhere
|
// TODO: All this unmapping, resizing etc. feels too much duplicated from elsewhere
|
||||||
|
@ -1089,7 +966,7 @@ void Client::setShade(ShadeMode mode)
|
||||||
// Shade
|
// Shade
|
||||||
shade_geometry_change = true;
|
shade_geometry_change = true;
|
||||||
QSize s(sizeForClientSize(QSize(clientSize())));
|
QSize s(sizeForClientSize(QSize(clientSize())));
|
||||||
s.setHeight(border_top + border_bottom);
|
s.setHeight(borderTop() + borderBottom());
|
||||||
m_wrapper.selectInput(ClientWinMask); // Avoid getting UnmapNotify
|
m_wrapper.selectInput(ClientWinMask); // Avoid getting UnmapNotify
|
||||||
m_wrapper.unmap();
|
m_wrapper.unmap();
|
||||||
m_client.unmap();
|
m_client.unmap();
|
||||||
|
@ -1314,8 +1191,6 @@ void Client::map()
|
||||||
// for use in effects, but now we want to have access to the new pixmap
|
// for use in effects, but now we want to have access to the new pixmap
|
||||||
if (compositing())
|
if (compositing())
|
||||||
discardWindowPixmap();
|
discardWindowPixmap();
|
||||||
if (decoration != NULL)
|
|
||||||
decoration->show(); // Not really necessary, but let it know the state
|
|
||||||
m_frame.map();
|
m_frame.map();
|
||||||
if (!isShade()) {
|
if (!isShade()) {
|
||||||
m_wrapper.map();
|
m_wrapper.map();
|
||||||
|
@ -1343,8 +1218,6 @@ void Client::unmap()
|
||||||
m_client.unmap();
|
m_client.unmap();
|
||||||
m_decoInputExtent.unmap();
|
m_decoInputExtent.unmap();
|
||||||
m_wrapper.selectInput(ClientWinMask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
|
m_wrapper.selectInput(ClientWinMask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
|
||||||
if (decoration != NULL)
|
|
||||||
decoration->hide(); // Not really necessary, but let it know the state
|
|
||||||
exportMappingState(IconicState);
|
exportMappingState(IconicState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2093,8 +1966,10 @@ void Client::getMotifHints()
|
||||||
motif_may_close = mclose; // Motif apps like to crash when they set this hint and WM closes them anyway
|
motif_may_close = mclose; // Motif apps like to crash when they set this hint and WM closes them anyway
|
||||||
if (isManaged())
|
if (isManaged())
|
||||||
updateDecoration(true); // Check if noborder state has changed
|
updateDecoration(true); // Check if noborder state has changed
|
||||||
|
#if 0
|
||||||
if (decoration && closabilityChanged)
|
if (decoration && closabilityChanged)
|
||||||
emit decoration->decorationButtonsChanged();
|
emit decoration->decorationButtonsChanged();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::getIcons()
|
void Client::getIcons()
|
||||||
|
@ -2302,8 +2177,6 @@ void Client::updateCursor()
|
||||||
if (c == m_cursor)
|
if (c == m_cursor)
|
||||||
return;
|
return;
|
||||||
m_cursor = c;
|
m_cursor = c;
|
||||||
if (decoration != NULL)
|
|
||||||
decoration->window()->setCursor(m_cursor);
|
|
||||||
xcb_cursor_t nativeCursor = Cursor::x11Cursor(m_cursor);
|
xcb_cursor_t nativeCursor = Cursor::x11Cursor(m_cursor);
|
||||||
m_frame.defineCursor(nativeCursor);
|
m_frame.defineCursor(nativeCursor);
|
||||||
if (m_decoInputExtent.isValid())
|
if (m_decoInputExtent.isValid())
|
||||||
|
@ -2326,8 +2199,29 @@ void Client::setBlockingCompositing(bool block)
|
||||||
|
|
||||||
Client::Position Client::mousePosition(const QPoint& p) const
|
Client::Position Client::mousePosition(const QPoint& p) const
|
||||||
{
|
{
|
||||||
if (decoration != NULL)
|
Q_UNUSED(p)
|
||||||
return decoration->mousePosition(p);
|
if (m_decoration) {
|
||||||
|
switch (m_decoration->windowFrameSection()) {
|
||||||
|
case Qt::BottomLeftSection:
|
||||||
|
return KDecorationDefines::PositionBottomLeft;
|
||||||
|
case Qt::BottomRightSection:
|
||||||
|
return KDecorationDefines::PositionBottomRight;
|
||||||
|
case Qt::BottomSection:
|
||||||
|
return KDecorationDefines::PositionBottom;
|
||||||
|
case Qt::LeftSection:
|
||||||
|
return KDecorationDefines::PositionLeft;
|
||||||
|
case Qt::RightSection:
|
||||||
|
return KDecorationDefines::PositionRight;
|
||||||
|
case Qt::TopSection:
|
||||||
|
return KDecorationDefines::PositionTop;
|
||||||
|
case Qt::TopLeftSection:
|
||||||
|
return KDecorationDefines::PositionTopLeft;
|
||||||
|
case Qt::TopRightSection:
|
||||||
|
return KDecorationDefines::PositionTopRight;
|
||||||
|
default:
|
||||||
|
return KDecorationDefines::PositionCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
return PositionCenter;
|
return PositionCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2360,8 +2254,10 @@ void Client::updateAllowedActions(bool force)
|
||||||
|
|
||||||
// ONLY if relevant features have changed (and the window didn't just get/loose moveresize for maximization state changes)
|
// ONLY if relevant features have changed (and the window didn't just get/loose moveresize for maximization state changes)
|
||||||
const NET::Actions relevant = ~(NET::ActionMove|NET::ActionResize);
|
const NET::Actions relevant = ~(NET::ActionMove|NET::ActionResize);
|
||||||
|
#if 0
|
||||||
if (decoration && (allowed_actions & relevant) != (old_allowed_actions & relevant))
|
if (decoration && (allowed_actions & relevant) != (old_allowed_actions & relevant))
|
||||||
emit decoration->decorationButtonsChanged();
|
emit decoration->decorationButtonsChanged();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::autoRaise()
|
void Client::autoRaise()
|
||||||
|
@ -2433,21 +2329,13 @@ void Client::setSessionInteract(bool needed)
|
||||||
|
|
||||||
QRect Client::decorationRect() const
|
QRect Client::decorationRect() const
|
||||||
{
|
{
|
||||||
if (decoration) {
|
return QRect(0, 0, width(), height());
|
||||||
return decoration->rect().translated(-padding_left, -padding_top);
|
|
||||||
} else {
|
|
||||||
return QRect(0, 0, width(), height());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KDecorationDefines::Position Client::titlebarPosition() const
|
KDecorationDefines::Position Client::titlebarPosition() const
|
||||||
{
|
{
|
||||||
Position titlePos = PositionCenter; // PositionTop is returned by the default implementation
|
// TODO: still needed, remove?
|
||||||
// this will hint errors in the metaobject usage ;-)
|
return PositionTop;
|
||||||
if (decoration)
|
|
||||||
QMetaObject::invokeMethod(decoration, "titlebarPosition", Qt::DirectConnection,
|
|
||||||
Q_RETURN_ARG(KDecorationDefines::Position, titlePos));
|
|
||||||
return titlePos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::updateFirstInTabBox()
|
void Client::updateFirstInTabBox()
|
||||||
|
@ -2518,6 +2406,7 @@ NET::WindowType Client::windowType(bool direct, int supportedTypes) const
|
||||||
|
|
||||||
bool Client::decorationHasAlpha() const
|
bool Client::decorationHasAlpha() const
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (!decoration || !decorationPlugin()->hasAlpha()) {
|
if (!decoration || !decorationPlugin()->hasAlpha()) {
|
||||||
// either no decoration or decoration has alpha disabled
|
// either no decoration or decoration has alpha disabled
|
||||||
return false;
|
return false;
|
||||||
|
@ -2528,6 +2417,8 @@ bool Client::decorationHasAlpha() const
|
||||||
// decoration has alpha enabled and does not support alpha announcement
|
// decoration has alpha enabled and does not support alpha announcement
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::cancelFocusOutTimer()
|
void Client::cancelFocusOutTimer()
|
||||||
|
@ -2616,6 +2507,26 @@ void Client::sendKeybordKeyEvent(uint32_t key, InputRedirection::KeyboardKeyStat
|
||||||
xcb_test_fake_input(connection(), type, key + 8, XCB_TIME_CURRENT_TIME, frameId(), 0, 0, 0);
|
xcb_test_fake_input(connection(), type, key + 8, XCB_TIME_CURRENT_TIME, frameId(), 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BORDER(which) \
|
||||||
|
int Client::border##which() const \
|
||||||
|
{ \
|
||||||
|
return m_decoration ? m_decoration->border##which() : 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
BORDER(Bottom)
|
||||||
|
BORDER(Left)
|
||||||
|
BORDER(Right)
|
||||||
|
BORDER(Top)
|
||||||
|
#undef BORDER
|
||||||
|
|
||||||
|
Decoration::DecoratedClientImpl *Client::decoratedClient()
|
||||||
|
{
|
||||||
|
if (!m_decoration) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return static_cast<Decoration::DecoratedClientImpl*>(m_decoration->client()->handle());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#include "client.moc"
|
#include "client.moc"
|
||||||
|
|
62
client.h
62
client.h
|
@ -44,6 +44,11 @@ class KStartupInfoId;
|
||||||
|
|
||||||
struct xcb_sync_alarm_notify_event_t;
|
struct xcb_sync_alarm_notify_event_t;
|
||||||
|
|
||||||
|
namespace KDecoration2
|
||||||
|
{
|
||||||
|
class Decoration;
|
||||||
|
}
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
namespace TabBox
|
namespace TabBox
|
||||||
|
@ -52,8 +57,10 @@ namespace TabBox
|
||||||
class TabBoxClientImpl;
|
class TabBoxClientImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bridge;
|
namespace Decoration
|
||||||
class PaintRedirector;
|
{
|
||||||
|
class DecoratedClientImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -286,7 +293,6 @@ class Client
|
||||||
public:
|
public:
|
||||||
explicit Client();
|
explicit Client();
|
||||||
xcb_window_t wrapperId() const;
|
xcb_window_t wrapperId() const;
|
||||||
xcb_window_t decorationId() const;
|
|
||||||
xcb_window_t inputId() const { return m_decoInputExtent; }
|
xcb_window_t inputId() const { return m_decoInputExtent; }
|
||||||
virtual xcb_window_t frameId() const override;
|
virtual xcb_window_t frameId() const override;
|
||||||
|
|
||||||
|
@ -329,7 +335,6 @@ public:
|
||||||
QPoint inputPos() const { return input_offset; } // Inside of geometry()
|
QPoint inputPos() const { return input_offset; } // Inside of geometry()
|
||||||
|
|
||||||
bool windowEvent(xcb_generic_event_t *e);
|
bool windowEvent(xcb_generic_event_t *e);
|
||||||
virtual bool eventFilter(QObject* o, QEvent* e);
|
|
||||||
void syncEvent(xcb_sync_alarm_notify_event_t* e);
|
void syncEvent(xcb_sync_alarm_notify_event_t* e);
|
||||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
|
||||||
|
|
||||||
|
@ -438,9 +443,6 @@ public:
|
||||||
}
|
}
|
||||||
void demandAttention(bool set = true);
|
void demandAttention(bool set = true);
|
||||||
|
|
||||||
void setMask(const QRegion& r, int mode = XCB_CLIP_ORDERING_UNSORTED);
|
|
||||||
QRegion mask() const;
|
|
||||||
|
|
||||||
void updateDecoration(bool check_workspace_pos, bool force = false);
|
void updateDecoration(bool check_workspace_pos, bool force = false);
|
||||||
bool checkBorderSizes(bool also_resize);
|
bool checkBorderSizes(bool also_resize);
|
||||||
void triggerDecorationRepaint();
|
void triggerDecorationRepaint();
|
||||||
|
@ -589,29 +591,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decorations <-> Effects
|
// Decorations <-> Effects
|
||||||
PaintRedirector *decorationPaintRedirector() {
|
KDecoration2::Decoration *decoration() {
|
||||||
return paintRedirector;
|
return m_decoration;
|
||||||
}
|
}
|
||||||
|
const KDecoration2::Decoration *decoration() const {
|
||||||
int paddingLeft() const {
|
return m_decoration;
|
||||||
return padding_left;
|
|
||||||
}
|
|
||||||
int paddingRight() const {
|
|
||||||
return padding_right;
|
|
||||||
}
|
|
||||||
int paddingTop() const {
|
|
||||||
return padding_top;
|
|
||||||
}
|
|
||||||
int paddingBottom() const {
|
|
||||||
return padding_bottom;
|
|
||||||
}
|
}
|
||||||
|
Decoration::DecoratedClientImpl *decoratedClient();
|
||||||
|
|
||||||
QRect decorationRect() const;
|
QRect decorationRect() const;
|
||||||
|
|
||||||
QRect transparentRect() const;
|
QRect transparentRect() const;
|
||||||
|
|
||||||
QRegion decorationPendingRegion() const;
|
|
||||||
|
|
||||||
bool decorationHasAlpha() const;
|
bool decorationHasAlpha() const;
|
||||||
bool isClientSideDecorated() const;
|
bool isClientSideDecorated() const;
|
||||||
|
|
||||||
|
@ -683,10 +674,6 @@ private Q_SLOTS:
|
||||||
void shadeHover();
|
void shadeHover();
|
||||||
void shadeUnhover();
|
void shadeUnhover();
|
||||||
|
|
||||||
private:
|
|
||||||
friend class Bridge; // FRAME
|
|
||||||
virtual void processMousePressEvent(QMouseEvent* e);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Use Workspace::createClient()
|
// Use Workspace::createClient()
|
||||||
virtual ~Client(); ///< Use destroyClient() or releaseWindow()
|
virtual ~Client(); ///< Use destroyClient() or releaseWindow()
|
||||||
|
@ -789,6 +776,10 @@ Q_SIGNALS:
|
||||||
void clientSideDecoratedChanged();
|
void clientSideDecoratedChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int borderLeft() const;
|
||||||
|
int borderRight() const;
|
||||||
|
int borderTop() const;
|
||||||
|
int borderBottom() const;
|
||||||
void exportMappingState(int s); // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1
|
void exportMappingState(int s); // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1
|
||||||
bool isManaged() const; ///< Returns false if this client is not yet managed
|
bool isManaged() const; ///< Returns false if this client is not yet managed
|
||||||
void updateAllowedActions(bool force = false);
|
void updateAllowedActions(bool force = false);
|
||||||
|
@ -869,8 +860,7 @@ private:
|
||||||
Xcb::Window m_frame;
|
Xcb::Window m_frame;
|
||||||
// wrapper around m_frame to use as a parent for the decoration
|
// wrapper around m_frame to use as a parent for the decoration
|
||||||
QScopedPointer<QWindow> m_frameWrapper;
|
QScopedPointer<QWindow> m_frameWrapper;
|
||||||
KDecoration* decoration;
|
KDecoration2::Decoration *m_decoration;
|
||||||
Bridge* bridge;
|
|
||||||
int desk;
|
int desk;
|
||||||
QStringList activityList;
|
QStringList activityList;
|
||||||
int m_activityUpdatesBlocked;
|
int m_activityUpdatesBlocked;
|
||||||
|
@ -991,15 +981,11 @@ private:
|
||||||
QTimer *timeout, *failsafeTimeout;
|
QTimer *timeout, *failsafeTimeout;
|
||||||
bool isPending;
|
bool isPending;
|
||||||
} syncRequest;
|
} syncRequest;
|
||||||
int border_left, border_right, border_top, border_bottom;
|
|
||||||
int padding_left, padding_right, padding_top, padding_bottom;
|
|
||||||
QRegion _mask;
|
|
||||||
static bool check_active_modal; ///< \see Client::checkActiveModal()
|
static bool check_active_modal; ///< \see Client::checkActiveModal()
|
||||||
QKeySequence _shortcut;
|
QKeySequence _shortcut;
|
||||||
int sm_stacking_order;
|
int sm_stacking_order;
|
||||||
friend struct ResetupRulesProcedure;
|
friend struct ResetupRulesProcedure;
|
||||||
friend class GeometryUpdatesBlocker;
|
friend class GeometryUpdatesBlocker;
|
||||||
PaintRedirector* paintRedirector;
|
|
||||||
QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
|
QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
|
||||||
bool m_firstInTabBox;
|
bool m_firstInTabBox;
|
||||||
|
|
||||||
|
@ -1050,14 +1036,6 @@ inline xcb_window_t Client::wrapperId() const
|
||||||
return m_wrapper;
|
return m_wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline xcb_window_t Client::decorationId() const
|
|
||||||
{
|
|
||||||
if (decoration) {
|
|
||||||
return decoration->window()->winId();
|
|
||||||
}
|
|
||||||
return XCB_WINDOW_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Client::isClientSideDecorated() const
|
inline bool Client::isClientSideDecorated() const
|
||||||
{
|
{
|
||||||
return m_clientSideDecorated;
|
return m_clientSideDecorated;
|
||||||
|
@ -1223,7 +1201,7 @@ inline bool Client::isManaged() const
|
||||||
|
|
||||||
inline QPoint Client::clientPos() const
|
inline QPoint Client::clientPos() const
|
||||||
{
|
{
|
||||||
return QPoint(border_left, border_top);
|
return QPoint(borderLeft(), borderTop());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QSize Client::clientSize() const
|
inline QSize Client::clientSize() const
|
||||||
|
|
|
@ -1106,10 +1106,6 @@ bool Client::setupCompositing()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
updateVisibility(); // for internalKeep()
|
updateVisibility(); // for internalKeep()
|
||||||
if (isManaged()) {
|
|
||||||
// only create the decoration when a client is managed
|
|
||||||
updateDecoration(true, true);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1118,8 +1114,7 @@ void Client::finishCompositing(ReleaseReason releaseReason)
|
||||||
Toplevel::finishCompositing(releaseReason);
|
Toplevel::finishCompositing(releaseReason);
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
if (!deleting) {
|
if (!deleting) {
|
||||||
// only recreate the decoration if we are not shutting down completely
|
triggerDecorationRepaint();
|
||||||
updateDecoration(true, true);
|
|
||||||
}
|
}
|
||||||
// for safety in case KWin is just resizing the window
|
// for safety in case KWin is just resizing the window
|
||||||
s_haveResizeEffect = false;
|
s_haveResizeEffect = false;
|
||||||
|
|
183
decorations.cpp
183
decorations.cpp
|
@ -1,183 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 1999, 2000 Daniel M. Duley <mosfet@kde.org>
|
|
||||||
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#include "decorations.h"
|
|
||||||
#include "config-kwin.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "workspace.h"
|
|
||||||
#include <kdecorationfactory.h>
|
|
||||||
|
|
||||||
#include <KLocalizedString>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <QPixmap>
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
KWIN_SINGLETON_FACTORY(DecorationPlugin)
|
|
||||||
|
|
||||||
DecorationPlugin::DecorationPlugin(QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, KDecorationPlugins(KSharedConfig::openConfig())
|
|
||||||
, m_disabled(false)
|
|
||||||
{
|
|
||||||
defaultPlugin = QStringLiteral("Oxygen");
|
|
||||||
#ifdef KWIN_BUILD_DECORATIONS
|
|
||||||
loadPlugin(QString()); // load the plugin specified in cfg file
|
|
||||||
connect(factory(), &KDecorationFactory::recreateDecorations, this, &DecorationPlugin::recreateDecorations);
|
|
||||||
connect(this, &DecorationPlugin::compositingToggled, options, &KDecorationOptions::compositingChanged);
|
|
||||||
#else
|
|
||||||
setDisabled(true);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
DecorationPlugin::~DecorationPlugin()
|
|
||||||
{
|
|
||||||
s_self = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DecorationPlugin::error(const QString &error_msg)
|
|
||||||
{
|
|
||||||
qWarning("%s", QString(i18n("KWin: ") + error_msg).toLocal8Bit().data());
|
|
||||||
|
|
||||||
setDisabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::provides(Requirement)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DecorationPlugin::setDisabled(bool disabled)
|
|
||||||
{
|
|
||||||
m_disabled = disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::isDisabled() const
|
|
||||||
{
|
|
||||||
return m_disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::hasShadows() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityProvidesShadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::hasAlpha() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityUsesAlphaChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::supportsAnnounceAlpha() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityAnnounceAlphaChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::supportsTabbing() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityTabbing);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::supportsFrameOverlap() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityExtendIntoClientArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecorationPlugin::supportsBlurBehind() const
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return factory()->supports(AbilityUsesBlurBehind);
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::Corner DecorationPlugin::closeButtonCorner()
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return Qt::TopRightCorner;
|
|
||||||
}
|
|
||||||
return factory()->closeButtonCorner();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DecorationPlugin::supportInformation()
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return QStringLiteral("Decoration Plugin disabled\n");
|
|
||||||
}
|
|
||||||
QString support;
|
|
||||||
support.append(QStringLiteral("Current Plugin: "));
|
|
||||||
support.append(currentPlugin());
|
|
||||||
support.append(QStringLiteral("\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Shadows: "));
|
|
||||||
support.append(hasShadows() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Alpha: "));
|
|
||||||
support.append(hasAlpha() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Announces Alpha: "));
|
|
||||||
support.append(supportsAnnounceAlpha() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Tabbing: "));
|
|
||||||
support.append(supportsTabbing() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Frame Overlap: "));
|
|
||||||
support.append(supportsFrameOverlap() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
|
|
||||||
support.append(QStringLiteral("Blur Behind: "));
|
|
||||||
support.append(supportsBlurBehind() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
|
|
||||||
// TODO: Qt5 - read support information from Factory
|
|
||||||
return support;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DecorationPlugin::recreateDecorations()
|
|
||||||
{
|
|
||||||
if (m_disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Decorations need to be recreated
|
|
||||||
workspace()->forEachClient([](Client *c) {
|
|
||||||
c->updateDecoration(true, true);
|
|
||||||
});
|
|
||||||
// If the new decoration doesn't supports tabs then ungroup clients
|
|
||||||
if (!supportsTabbing()) {
|
|
||||||
workspace()->forEachClient([](Client *c) {
|
|
||||||
c->untab();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
|
@ -1,72 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 1999, 2000 Daniel M. Duley <mosfet@kde.org>
|
|
||||||
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#ifndef KWIN_PLUGINS_H
|
|
||||||
#define KWIN_PLUGINS_H
|
|
||||||
|
|
||||||
#include <kdecoration_plugins_p.h>
|
|
||||||
#include <kwinglobals.h>
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
class DecorationPlugin
|
|
||||||
: public QObject, public KDecorationPlugins
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
virtual ~DecorationPlugin();
|
|
||||||
virtual bool provides(Requirement);
|
|
||||||
/**
|
|
||||||
* @returns @c true if there is no decoration plugin.
|
|
||||||
**/
|
|
||||||
bool isDisabled() const;
|
|
||||||
|
|
||||||
bool hasShadows() const;
|
|
||||||
bool hasAlpha() const;
|
|
||||||
bool supportsAnnounceAlpha() const;
|
|
||||||
bool supportsTabbing() const;
|
|
||||||
bool supportsFrameOverlap() const;
|
|
||||||
bool supportsBlurBehind() const;
|
|
||||||
Qt::Corner closeButtonCorner();
|
|
||||||
|
|
||||||
QString supportInformation();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void compositingToggled();
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void recreateDecorations();
|
|
||||||
protected:
|
|
||||||
virtual void error(const QString& error_msg);
|
|
||||||
private:
|
|
||||||
void setDisabled(bool noDecoration);
|
|
||||||
bool m_disabled;
|
|
||||||
KWIN_SINGLETON(DecorationPlugin)
|
|
||||||
};
|
|
||||||
|
|
||||||
inline DecorationPlugin *decorationPlugin() {
|
|
||||||
return DecorationPlugin::self();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#endif
|
|
201
decorations/decoratedclient.cpp
Normal file
201
decorations/decoratedclient.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "decoratedclient.h"
|
||||||
|
#include "decorationrenderer.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "composite.h"
|
||||||
|
#include "cursor.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "scene.h"
|
||||||
|
#include "workspace.h"
|
||||||
|
|
||||||
|
#include <KDecoration2/DecoratedClient>
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
DecoratedClientImpl::DecoratedClientImpl(Client *client, KDecoration2::DecoratedClient *decoratedClient, KDecoration2::Decoration *decoration)
|
||||||
|
: QObject()
|
||||||
|
, DecoratedClientPrivate(decoratedClient, decoration)
|
||||||
|
, m_client(client)
|
||||||
|
, m_renderer(nullptr)
|
||||||
|
{
|
||||||
|
createRenderer();
|
||||||
|
connect(client, &Client::activeChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
emit decoratedClient->activeChanged(client->isActive());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::geometryChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
emit decoratedClient->widthChanged(client->clientSize().width());
|
||||||
|
emit decoratedClient->heightChanged(client->clientSize().height());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::desktopChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
emit decoratedClient->onAllDesktopsChanged(client->isOnAllDesktops());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::captionChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
emit decoratedClient->captionChanged(client->caption());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::iconChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
emit decoratedClient->iconChanged(client->icon());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::shadeChanged, this,
|
||||||
|
[decoratedClient, client]() {
|
||||||
|
// TODO: geometry is wrong
|
||||||
|
emit decoratedClient->shadedChanged(client->isShade());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(client, &Client::keepAboveChanged, decoratedClient, &KDecoration2::DecoratedClient::keepAboveChanged);
|
||||||
|
connect(client, &Client::keepBelowChanged, decoratedClient, &KDecoration2::DecoratedClient::keepBelowChanged);
|
||||||
|
// closeable, etc.
|
||||||
|
connect(Compositor::self(), &Compositor::compositingToggled, this,
|
||||||
|
[this, decoration]() {
|
||||||
|
delete m_renderer;
|
||||||
|
m_renderer = nullptr;
|
||||||
|
createRenderer();
|
||||||
|
decoration->update();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DecoratedClientImpl::~DecoratedClientImpl() = default;
|
||||||
|
|
||||||
|
#define DELEGATE(type, name) \
|
||||||
|
type DecoratedClientImpl::name() const \
|
||||||
|
{ \
|
||||||
|
return m_client->name(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DELEGATE(QString, caption)
|
||||||
|
DELEGATE(bool, isActive)
|
||||||
|
DELEGATE(bool, isCloseable)
|
||||||
|
DELEGATE(bool, isMaximizable)
|
||||||
|
DELEGATE(bool, isMinimizable)
|
||||||
|
DELEGATE(bool, isModal)
|
||||||
|
DELEGATE(bool, isMovable)
|
||||||
|
DELEGATE(bool, isResizable)
|
||||||
|
DELEGATE(bool, isShadeable)
|
||||||
|
DELEGATE(bool, providesContextHelp)
|
||||||
|
DELEGATE(int, desktop)
|
||||||
|
DELEGATE(bool, isOnAllDesktops)
|
||||||
|
DELEGATE(QPalette, palette)
|
||||||
|
DELEGATE(QIcon, icon)
|
||||||
|
|
||||||
|
#undef DELEGATE
|
||||||
|
|
||||||
|
#define DELEGATE(type, name, clientName) \
|
||||||
|
type DecoratedClientImpl::name() const \
|
||||||
|
{ \
|
||||||
|
return m_client->clientName(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DELEGATE(bool, isKeepAbove, keepAbove)
|
||||||
|
DELEGATE(bool, isKeepBelow, keepBelow)
|
||||||
|
DELEGATE(bool, isShaded, isShade)
|
||||||
|
DELEGATE(WId, windowId, window)
|
||||||
|
DELEGATE(WId, decorationId, frameId)
|
||||||
|
|
||||||
|
#undef DELEGATE
|
||||||
|
|
||||||
|
#define DELEGATE(name, op) \
|
||||||
|
void DecoratedClientImpl::name() \
|
||||||
|
{ \
|
||||||
|
Workspace::self()->performWindowOperation(m_client, KDecorationDefines::op); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DELEGATE(requestToggleShade, ShadeOp)
|
||||||
|
DELEGATE(requestToggleOnAllDesktops, OnAllDesktopsOp)
|
||||||
|
DELEGATE(requestToggleKeepAbove, KeepAboveOp)
|
||||||
|
DELEGATE(requestToggleKeepBelow, KeepBelowOp)
|
||||||
|
|
||||||
|
#undef DELEGATE
|
||||||
|
|
||||||
|
#define DELEGATE(name, clientName) \
|
||||||
|
void DecoratedClientImpl::name() \
|
||||||
|
{ \
|
||||||
|
m_client->clientName(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DELEGATE(requestContextHelp, showContextHelp)
|
||||||
|
DELEGATE(requestMinimize, minimize)
|
||||||
|
DELEGATE(requestClose, closeWindow)
|
||||||
|
|
||||||
|
#undef DELEGATE
|
||||||
|
|
||||||
|
void DecoratedClientImpl::requestShowWindowMenu()
|
||||||
|
{
|
||||||
|
// TODO: add rect to requestShowWindowMenu
|
||||||
|
Workspace::self()->showWindowMenu(QRect(Cursor::pos(), Cursor::pos()), m_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecoratedClientImpl::requestMaximize(Qt::MouseButtons buttons)
|
||||||
|
{
|
||||||
|
Workspace::self()->performWindowOperation(m_client, options->operationMaxButtonClick(buttons));
|
||||||
|
}
|
||||||
|
|
||||||
|
int DecoratedClientImpl::width() const
|
||||||
|
{
|
||||||
|
return m_client->clientSize().width();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DecoratedClientImpl::height() const
|
||||||
|
{
|
||||||
|
return m_client->clientSize().height();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecoratedClientImpl::isMaximizedVertically() const
|
||||||
|
{
|
||||||
|
return m_client->maximizeMode() & KDecorationDefines::MaximizeVertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecoratedClientImpl::isMaximized() const
|
||||||
|
{
|
||||||
|
return isMaximizedHorizontally() && isMaximizedVertically();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecoratedClientImpl::isMaximizedHorizontally() const
|
||||||
|
{
|
||||||
|
return m_client->maximizeMode() & KDecorationDefines::MaximizeHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecoratedClientImpl::createRenderer()
|
||||||
|
{
|
||||||
|
if (Compositor::self()->hasScene()) {
|
||||||
|
m_renderer = Compositor::self()->scene()->createDecorationRenderer(this);
|
||||||
|
} else {
|
||||||
|
m_renderer = new X11Renderer(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
97
decorations/decoratedclient.h
Normal file
97
decorations/decoratedclient.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef KWIN_DECORATED_CLIENT_H
|
||||||
|
#define KWIN_DECORATED_CLIENT_H
|
||||||
|
|
||||||
|
#include <KDecoration2/Private/DecoratedClientPrivate>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
|
||||||
|
class DecoratedClientImpl : public QObject, public KDecoration2::DecoratedClientPrivate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DecoratedClientImpl(Client *client, KDecoration2::DecoratedClient *decoratedClient, KDecoration2::Decoration *decoration);
|
||||||
|
virtual ~DecoratedClientImpl();
|
||||||
|
QString caption() const override;
|
||||||
|
WId decorationId() const override;
|
||||||
|
int desktop() const override;
|
||||||
|
int height() const override;
|
||||||
|
QIcon icon() const override;
|
||||||
|
bool isActive() const override;
|
||||||
|
bool isCloseable() const override;
|
||||||
|
bool isKeepAbove() const override;
|
||||||
|
bool isKeepBelow() const override;
|
||||||
|
bool isMaximizable() const override;
|
||||||
|
bool isMaximized() const override;
|
||||||
|
bool isMaximizedHorizontally() const override;
|
||||||
|
bool isMaximizedVertically() const override;
|
||||||
|
bool isMinimizable() const override;
|
||||||
|
bool isModal() const override;
|
||||||
|
bool isMovable() const override;
|
||||||
|
bool isOnAllDesktops() const override;
|
||||||
|
bool isResizable() const override;
|
||||||
|
bool isShadeable() const override;
|
||||||
|
bool isShaded() const override;
|
||||||
|
QPalette palette() const override;
|
||||||
|
bool providesContextHelp() const override;
|
||||||
|
int width() const override;
|
||||||
|
WId windowId() const override;
|
||||||
|
|
||||||
|
void requestClose() override;
|
||||||
|
void requestContextHelp() override;
|
||||||
|
void requestMaximize(Qt::MouseButtons buttons) override;
|
||||||
|
void requestMinimize() override;
|
||||||
|
void requestShowWindowMenu() override;
|
||||||
|
void requestToggleKeepAbove() override;
|
||||||
|
void requestToggleKeepBelow() override;
|
||||||
|
void requestToggleOnAllDesktops() override;
|
||||||
|
void requestToggleShade() override;
|
||||||
|
|
||||||
|
Client *client() {
|
||||||
|
return m_client;
|
||||||
|
}
|
||||||
|
Renderer *renderer() {
|
||||||
|
return m_renderer;
|
||||||
|
}
|
||||||
|
KDecoration2::DecoratedClient *decoratedClient() {
|
||||||
|
return KDecoration2::DecoratedClientPrivate::client();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createRenderer();
|
||||||
|
Client *m_client;
|
||||||
|
Renderer *m_renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
113
decorations/decorationbridge.cpp
Normal file
113
decorations/decorationbridge.cpp
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "decorationbridge.h"
|
||||||
|
#include "decoratedclient.h"
|
||||||
|
#include "decorationrenderer.h"
|
||||||
|
#include "settings.h"
|
||||||
|
// KWin core
|
||||||
|
#include "client.h"
|
||||||
|
#include "composite.h"
|
||||||
|
#include "scene.h"
|
||||||
|
|
||||||
|
// KDecoration
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
#include <KDecoration2/DecoratedClient>
|
||||||
|
#include <KDecoration2/DecorationSettings>
|
||||||
|
|
||||||
|
// Frameworks
|
||||||
|
#include <KPluginTrader>
|
||||||
|
#include <KPluginLoader>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2");
|
||||||
|
|
||||||
|
DecorationBridge::DecorationBridge(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, KDecoration2::DecorationBridge()
|
||||||
|
, m_factory(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DecorationBridge::~DecorationBridge() = default;
|
||||||
|
|
||||||
|
DecorationBridge *DecorationBridge::self()
|
||||||
|
{
|
||||||
|
return static_cast<KWin::Decoration::DecorationBridge*>(KDecoration2::DecorationBridge::self());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecorationBridge::init()
|
||||||
|
{
|
||||||
|
KDecoration2::DecorationSettings::self(this);
|
||||||
|
|
||||||
|
// TODO: configurable plugin
|
||||||
|
const auto offers = KPluginTrader::self()->query(s_pluginName,
|
||||||
|
s_pluginName,
|
||||||
|
QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(QStringLiteral("org.kde.breeze")));
|
||||||
|
if (offers.isEmpty()) {
|
||||||
|
qWarning() << "Could not locate decoration plugin";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << "Trying to load decoration plugin: " << offers.first().libraryPath();
|
||||||
|
KPluginLoader loader(offers.first().libraryPath());
|
||||||
|
KPluginFactory *factory = loader.factory();
|
||||||
|
if (!factory) {
|
||||||
|
qWarning() << "Error loading plugin:" << loader.errorString();
|
||||||
|
} else {
|
||||||
|
m_factory = factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KDecoration2::DecoratedClientPrivate *DecorationBridge::createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration)
|
||||||
|
{
|
||||||
|
return new DecoratedClientImpl(static_cast<Client*>(decoration->parent()), client, decoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
KDecoration2::DecorationSettingsPrivate *DecorationBridge::settings(KDecoration2::DecorationSettings *parent)
|
||||||
|
{
|
||||||
|
return new SettingsImpl(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecorationBridge::update(KDecoration2::Decoration *decoration, const QRect &geometry)
|
||||||
|
{
|
||||||
|
// TODO: remove check once all compositors implement it
|
||||||
|
if (Renderer *renderer = static_cast<DecoratedClientImpl*>(decoration->client()->handle())->renderer()) {
|
||||||
|
renderer->schedule(geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KDecoration2::Decoration *DecorationBridge::createDecoration(Client *client)
|
||||||
|
{
|
||||||
|
if (!m_factory) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return m_factory->create<KDecoration2::Decoration>(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Decoration
|
||||||
|
} // KWin
|
58
decorations/decorationbridge.h
Normal file
58
decorations/decorationbridge.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef KWIN_DECORATION_BRIDGE_H
|
||||||
|
#define KWIN_DECORATION_BRIDGE_H
|
||||||
|
|
||||||
|
#include <KDecoration2/Private/DecorationBridge>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class KPluginFactory;
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
class DecorationBridge : public QObject, public KDecoration2::DecorationBridge
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DecorationBridge(QObject *parent);
|
||||||
|
virtual ~DecorationBridge();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
KDecoration2::Decoration *createDecoration(Client *client);
|
||||||
|
|
||||||
|
KDecoration2::DecoratedClientPrivate *createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) override;
|
||||||
|
KDecoration2::DecorationSettingsPrivate *settings(KDecoration2::DecorationSettings *parent) override;
|
||||||
|
void update(KDecoration2::Decoration *decoration, const QRect &geometry) override;
|
||||||
|
|
||||||
|
static DecorationBridge *self();
|
||||||
|
private:
|
||||||
|
KPluginFactory *m_factory;
|
||||||
|
};
|
||||||
|
} // Decoration
|
||||||
|
} // KWin
|
||||||
|
|
||||||
|
#endif
|
134
decorations/decorationrenderer.cpp
Normal file
134
decorations/decorationrenderer.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "decorationrenderer.h"
|
||||||
|
#include "decoratedclient.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
#include <kwinglobals.h>
|
||||||
|
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
#include <KDecoration2/DecoratedClient>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
Renderer::Renderer(DecoratedClientImpl *client)
|
||||||
|
: QObject(client)
|
||||||
|
, m_client(client)
|
||||||
|
, m_imageSizesDirty(true)
|
||||||
|
{
|
||||||
|
auto markImageSizesDirty = [this]{ m_imageSizesDirty = true; };
|
||||||
|
connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, this, markImageSizesDirty);
|
||||||
|
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::widthChanged, this, markImageSizesDirty);
|
||||||
|
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::heightChanged, this, markImageSizesDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::~Renderer() = default;
|
||||||
|
|
||||||
|
void Renderer::schedule(const QRect &rect)
|
||||||
|
{
|
||||||
|
m_scheduled = m_scheduled.united(rect);
|
||||||
|
emit renderScheduled(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegion Renderer::getScheduled()
|
||||||
|
{
|
||||||
|
QRegion region = m_scheduled;
|
||||||
|
m_scheduled = QRegion();
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage Renderer::renderToImage(const QRect &geo)
|
||||||
|
{
|
||||||
|
QImage image(geo.width(), geo.height(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
image.fill(Qt::transparent);
|
||||||
|
QPainter p(&image);
|
||||||
|
p.setRenderHint(QPainter::Antialiasing);
|
||||||
|
p.setWindow(geo);
|
||||||
|
p.setClipRect(geo);
|
||||||
|
client()->decoration()->paint(&p);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
X11Renderer::X11Renderer(DecoratedClientImpl *client)
|
||||||
|
: Renderer(client)
|
||||||
|
, m_scheduleTimer(new QTimer(this))
|
||||||
|
, m_gc(XCB_NONE)
|
||||||
|
{
|
||||||
|
// delay any rendering to end of event cycle to catch multiple updates per cycle
|
||||||
|
m_scheduleTimer->setSingleShot(true);
|
||||||
|
m_scheduleTimer->setInterval(0);
|
||||||
|
connect(m_scheduleTimer, &QTimer::timeout, this, &X11Renderer::render);
|
||||||
|
connect(this, &Renderer::renderScheduled, m_scheduleTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
|
||||||
|
}
|
||||||
|
|
||||||
|
X11Renderer::~X11Renderer()
|
||||||
|
{
|
||||||
|
if (m_gc != XCB_NONE) {
|
||||||
|
xcb_free_gc(connection(), m_gc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11Renderer::render()
|
||||||
|
{
|
||||||
|
const QRegion scheduled = getScheduled();
|
||||||
|
if (scheduled.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_connection_t *c = connection();
|
||||||
|
if (m_gc == XCB_NONE) {
|
||||||
|
m_gc = xcb_generate_id(c);
|
||||||
|
xcb_create_gc(c, m_gc, client()->client()->frameId(), 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect left, top, right, bottom;
|
||||||
|
client()->client()->layoutDecorationRects(left, top, right, bottom, Client::DecorationRelative);
|
||||||
|
|
||||||
|
const QRect geometry = scheduled.boundingRect();
|
||||||
|
left = left.intersected(geometry);
|
||||||
|
top = top.intersected(geometry);
|
||||||
|
right = right.intersected(geometry);
|
||||||
|
bottom = bottom.intersected(geometry);
|
||||||
|
|
||||||
|
auto renderPart = [this, c](const QRect &geo) {
|
||||||
|
if (geo.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QImage image = renderToImage(geo);
|
||||||
|
xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, client()->client()->frameId(), m_gc,
|
||||||
|
image.width(), image.height(), geo.x(), geo.y(), 0, 24, image.byteCount(), image.constBits());
|
||||||
|
};
|
||||||
|
renderPart(left);
|
||||||
|
renderPart(top);
|
||||||
|
renderPart(right);
|
||||||
|
renderPart(bottom);
|
||||||
|
|
||||||
|
xcb_flush(c);
|
||||||
|
resetImageSizesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
94
decorations/decorationrenderer.h
Normal file
94
decorations/decorationrenderer.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef KWIN_DECORATION_RENDERER_H
|
||||||
|
#define KWIN_DECORATION_RENDERER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QRegion>
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
class DecoratedClientImpl;
|
||||||
|
|
||||||
|
class Renderer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual ~Renderer();
|
||||||
|
|
||||||
|
void schedule(const QRect &rect);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void renderScheduled(const QRect &geo);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit Renderer(DecoratedClientImpl *client);
|
||||||
|
/**
|
||||||
|
* @returns the scheduled paint region and resets
|
||||||
|
**/
|
||||||
|
QRegion getScheduled();
|
||||||
|
|
||||||
|
virtual void render() = 0;
|
||||||
|
|
||||||
|
DecoratedClientImpl *client() {
|
||||||
|
return m_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool areImageSizesDirty() const {
|
||||||
|
return m_imageSizesDirty;
|
||||||
|
}
|
||||||
|
void resetImageSizesDirty() {
|
||||||
|
m_imageSizesDirty = false;
|
||||||
|
}
|
||||||
|
QImage renderToImage(const QRect &geo);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DecoratedClientImpl *m_client;
|
||||||
|
QRegion m_scheduled;
|
||||||
|
bool m_imageSizesDirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
class X11Renderer : public Renderer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit X11Renderer(DecoratedClientImpl *client);
|
||||||
|
virtual ~X11Renderer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void render() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer *m_scheduleTimer;
|
||||||
|
xcb_gcontext_t m_gc;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
77
decorations/settings.cpp
Normal file
77
decorations/settings.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "settings.h"
|
||||||
|
// KWin
|
||||||
|
#include "composite.h"
|
||||||
|
#include "virtualdesktops.h"
|
||||||
|
|
||||||
|
#include <KDecoration2/DecorationSettings>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
SettingsImpl::SettingsImpl(KDecoration2::DecorationSettings *parent)
|
||||||
|
: QObject()
|
||||||
|
, DecorationSettingsPrivate(parent)
|
||||||
|
{
|
||||||
|
connect(Compositor::self(), &Compositor::compositingToggled,
|
||||||
|
parent, &KDecoration2::DecorationSettings::alphaChannelSupportedChanged);
|
||||||
|
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, this,
|
||||||
|
[parent](uint previous, uint current) {
|
||||||
|
if (previous != 1 && current != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit parent->onAllDesktopsAvailableChanged(current > 1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsImpl::~SettingsImpl() = default;
|
||||||
|
|
||||||
|
bool SettingsImpl::isAlphaChannelSupported() const
|
||||||
|
{
|
||||||
|
return Compositor::self()->compositing();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsImpl::isOnAllDesktopsAvailable() const
|
||||||
|
{
|
||||||
|
return VirtualDesktopManager::self()->count() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< KDecoration2::DecorationButtonType > SettingsImpl::decorationButtonsLeft() const
|
||||||
|
{
|
||||||
|
return QList<KDecoration2::DecorationButtonType >({
|
||||||
|
KDecoration2::DecorationButtonType::Menu,
|
||||||
|
KDecoration2::DecorationButtonType::OnAllDesktops
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< KDecoration2::DecorationButtonType > SettingsImpl::decorationButtonsRight() const
|
||||||
|
{
|
||||||
|
return QList<KDecoration2::DecorationButtonType >({
|
||||||
|
KDecoration2::DecorationButtonType::Minimize,
|
||||||
|
KDecoration2::DecorationButtonType::Maximize,
|
||||||
|
KDecoration2::DecorationButtonType::Close
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
46
decorations/settings.h
Normal file
46
decorations/settings.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#ifndef KWIN_DECORATION_SETTINGS_H
|
||||||
|
#define KWIN_DECORATION_SETTINGS_H
|
||||||
|
|
||||||
|
#include <KDecoration2/Private/DecorationSettingsPrivate>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
|
||||||
|
class SettingsImpl : public QObject, public KDecoration2::DecorationSettingsPrivate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SettingsImpl(KDecoration2::DecorationSettings *parent);
|
||||||
|
virtual ~SettingsImpl();
|
||||||
|
bool isAlphaChannelSupported() const override;
|
||||||
|
bool isOnAllDesktopsAvailable() const override;
|
||||||
|
QList< KDecoration2::DecorationButtonType > decorationButtonsLeft() const override;
|
||||||
|
QList< KDecoration2::DecorationButtonType > decorationButtonsRight() const override;
|
||||||
|
};
|
||||||
|
} // Decoration
|
||||||
|
} // KWin
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,7 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "netinfo.h"
|
#include "netinfo.h"
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "shadow.h"
|
#include "shadow.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -43,7 +42,6 @@ Deleted::Deleted()
|
||||||
, m_layer(UnknownLayer)
|
, m_layer(UnknownLayer)
|
||||||
, m_minimized(false)
|
, m_minimized(false)
|
||||||
, m_modal(false)
|
, m_modal(false)
|
||||||
, m_paintRedirector(NULL)
|
|
||||||
, m_wasClient(false)
|
, m_wasClient(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -88,21 +86,18 @@ void Deleted::copyToDeleted(Toplevel* c)
|
||||||
if (client) {
|
if (client) {
|
||||||
m_wasClient = true;
|
m_wasClient = true;
|
||||||
no_border = client->noBorder();
|
no_border = client->noBorder();
|
||||||
|
#if 0
|
||||||
padding_left = client->paddingLeft();
|
padding_left = client->paddingLeft();
|
||||||
padding_right = client->paddingRight();
|
padding_right = client->paddingRight();
|
||||||
padding_bottom = client->paddingBottom();
|
padding_bottom = client->paddingBottom();
|
||||||
padding_top = client->paddingTop();
|
padding_top = client->paddingTop();
|
||||||
|
#endif
|
||||||
if (!no_border) {
|
if (!no_border) {
|
||||||
client->layoutDecorationRects(decoration_left,
|
client->layoutDecorationRects(decoration_left,
|
||||||
decoration_top,
|
decoration_top,
|
||||||
decoration_right,
|
decoration_right,
|
||||||
decoration_bottom,
|
decoration_bottom,
|
||||||
Client::WindowRelative);
|
Client::WindowRelative);
|
||||||
if (PaintRedirector *redirector = client->decorationPaintRedirector()) {
|
|
||||||
redirector->ensurePixmapsPainted();
|
|
||||||
redirector->reparent(this);
|
|
||||||
m_paintRedirector = redirector;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_minimized = client->isMinimized();
|
m_minimized = client->isMinimized();
|
||||||
m_modal = client->isModal();
|
m_modal = client->isModal();
|
||||||
|
|
|
@ -25,7 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
class PaintRedirector;
|
|
||||||
|
|
||||||
class Deleted
|
class Deleted
|
||||||
: public Toplevel
|
: public Toplevel
|
||||||
|
@ -64,9 +63,6 @@ public:
|
||||||
return m_mainClients;
|
return m_mainClients;
|
||||||
}
|
}
|
||||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
|
||||||
PaintRedirector *decorationPaintRedirector() {
|
|
||||||
return m_paintRedirector;
|
|
||||||
}
|
|
||||||
bool wasClient() const {
|
bool wasClient() const {
|
||||||
return m_wasClient;
|
return m_wasClient;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +93,6 @@ private:
|
||||||
bool m_minimized;
|
bool m_minimized;
|
||||||
bool m_modal;
|
bool m_modal;
|
||||||
ClientList m_mainClients;
|
ClientList m_mainClients;
|
||||||
PaintRedirector *m_paintRedirector;
|
|
||||||
bool m_wasClient;
|
bool m_wasClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#ifdef KWIN_BUILD_ACTIVITIES
|
#ifdef KWIN_BUILD_ACTIVITIES
|
||||||
#include "activities.h"
|
#include "activities.h"
|
||||||
#endif
|
#endif
|
||||||
#include "decorations.h"
|
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
|
@ -492,17 +491,17 @@ void EffectsHandlerImpl::buildQuads(EffectWindow* w, WindowQuadList& quadList)
|
||||||
|
|
||||||
bool EffectsHandlerImpl::hasDecorationShadows() const
|
bool EffectsHandlerImpl::hasDecorationShadows() const
|
||||||
{
|
{
|
||||||
return decorationPlugin()->hasShadows();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectsHandlerImpl::decorationsHaveAlpha() const
|
bool EffectsHandlerImpl::decorationsHaveAlpha() const
|
||||||
{
|
{
|
||||||
return decorationPlugin()->hasAlpha();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectsHandlerImpl::decorationSupportsBlurBehind() const
|
bool EffectsHandlerImpl::decorationSupportsBlurBehind() const
|
||||||
{
|
{
|
||||||
return decorationPlugin()->supportsBlurBehind();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start another painting pass
|
// start another painting pass
|
||||||
|
@ -1441,7 +1440,7 @@ QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt)
|
||||||
{
|
{
|
||||||
switch (kwopt) {
|
switch (kwopt) {
|
||||||
case CloseButtonCorner:
|
case CloseButtonCorner:
|
||||||
return decorationPlugin()->closeButtonCorner();
|
return Qt::TopRightCorner;
|
||||||
#ifdef KWIN_BUILD_SCREENEDGES
|
#ifdef KWIN_BUILD_SCREENEDGES
|
||||||
case SwitchDesktopOnScreenEdge:
|
case SwitchDesktopOnScreenEdge:
|
||||||
return ScreenEdges::self()->isDesktopSwitching();
|
return ScreenEdges::self()->isDesktopSwitching();
|
||||||
|
|
162
events.cpp
162
events.cpp
|
@ -27,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "focuschain.h"
|
#include "focuschain.h"
|
||||||
#include "netinfo.h"
|
#include "netinfo.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
|
@ -47,6 +46,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "screens.h"
|
#include "screens.h"
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
|
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QWhatsThis>
|
#include <QWhatsThis>
|
||||||
|
@ -312,25 +313,8 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (movingClient) {
|
if (movingClient) {
|
||||||
if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE) {
|
if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE || eventType == XCB_MOTION_NOTIFY) {
|
||||||
Client *c = movingClient;
|
|
||||||
if (movingClient->moveResizeGrabWindow() == reinterpret_cast<xcb_button_press_event_t*>(e)->event && movingClient->windowEvent(e)) {
|
if (movingClient->moveResizeGrabWindow() == reinterpret_cast<xcb_button_press_event_t*>(e)->event && movingClient->windowEvent(e)) {
|
||||||
// we need to pass the button release event to the decoration, otherwise Qt still thinks the button is pressed.
|
|
||||||
if (eventType == XCB_BUTTON_RELEASE && c->decorationId() != XCB_WINDOW_NONE) {
|
|
||||||
// the event is for the moveResizeGrabWindow and Qt doesn't forward that to the decoration
|
|
||||||
// so we need to send the event to the decoration ourselves
|
|
||||||
// TODO check whether m_moveResizeWindow can be offscreen and XAllowEvents be sufficient here
|
|
||||||
xcb_button_release_event_t event = *(reinterpret_cast<xcb_button_release_event_t*>(e));
|
|
||||||
event.event = c->decorationId();
|
|
||||||
event.child = XCB_WINDOW_NONE;
|
|
||||||
event.event_x = event.root_x - c->x() + c->paddingLeft();
|
|
||||||
event.event_y = event.root_y - c->y() + c->paddingTop();
|
|
||||||
xcb_send_event(connection(), false, c->decorationId(), XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast<const char*>(&event));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (eventType == XCB_MOTION_NOTIFY) {
|
|
||||||
if (movingClient->moveResizeGrabWindow() == reinterpret_cast<xcb_motion_notify_event_t*>(e)->event && movingClient->windowEvent(e)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,6 +670,14 @@ bool Client::windowEvent(xcb_generic_event_t *e)
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
clientMessageEvent(reinterpret_cast<xcb_client_message_event_t*>(e));
|
clientMessageEvent(reinterpret_cast<xcb_client_message_event_t*>(e));
|
||||||
break;
|
break;
|
||||||
|
case XCB_EXPOSE: {
|
||||||
|
xcb_expose_event_t *event = reinterpret_cast<xcb_expose_event_t*>(e);
|
||||||
|
if (event->window == frameId() && !Compositor::self()->isActive()) {
|
||||||
|
// TODO: only repaint required areas
|
||||||
|
triggerDecorationRepaint();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if (eventType == Xcb::Extensions::self()->shapeNotifyEvent() && reinterpret_cast<xcb_shape_notify_event_t*>(e)->affected_window == window()) {
|
if (eventType == Xcb::Extensions::self()->shapeNotifyEvent() && reinterpret_cast<xcb_shape_notify_event_t*>(e)->affected_window == window()) {
|
||||||
detectShape(window()); // workaround for #19644
|
detectShape(window()); // workaround for #19644
|
||||||
|
@ -1036,65 +1028,6 @@ void Client::updateMouseGrab()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Qt propagates mouse events up the widget hierachy, which means events
|
|
||||||
// for the decoration window cannot be (easily) intercepted as X11 events
|
|
||||||
bool Client::eventFilter(QObject* o, QEvent* e)
|
|
||||||
{
|
|
||||||
if (decoration == NULL
|
|
||||||
|| (o != decoration->widget() && o != decoration->window()))
|
|
||||||
return false;
|
|
||||||
if (e->type() == QEvent::MouseButtonPress && decoration->widget()) {
|
|
||||||
QMouseEvent* ev = static_cast< QMouseEvent* >(e);
|
|
||||||
return buttonPressEvent(decorationId(), qtToX11Button(ev->button()), qtToX11State(ev->buttons(), ev->modifiers()),
|
|
||||||
ev->x(), ev->y(), ev->globalX(), ev->globalY());
|
|
||||||
}
|
|
||||||
if (e->type() == QEvent::MouseButtonRelease) {
|
|
||||||
QMouseEvent* ev = static_cast< QMouseEvent* >(e);
|
|
||||||
return buttonReleaseEvent(decorationId(), qtToX11Button(ev->button()), qtToX11State(ev->buttons(), ev->modifiers()),
|
|
||||||
ev->x(), ev->y(), ev->globalX(), ev->globalY());
|
|
||||||
}
|
|
||||||
if (e->type() == QEvent::MouseMove) { // FRAME i fake z enter/leave?
|
|
||||||
QMouseEvent* ev = static_cast< QMouseEvent* >(e);
|
|
||||||
return motionNotifyEvent(decorationId(), qtToX11State(ev->buttons(), ev->modifiers()),
|
|
||||||
ev->x(), ev->y(), ev->globalX(), ev->globalY());
|
|
||||||
}
|
|
||||||
if (e->type() == QEvent::Wheel) {
|
|
||||||
QWheelEvent* ev = static_cast< QWheelEvent* >(e);
|
|
||||||
bool r = buttonPressEvent(decorationId(), ev->delta() > 0 ? Button4 : Button5, qtToX11State(ev->buttons(), ev->modifiers()),
|
|
||||||
ev->x(), ev->y(), ev->globalX(), ev->globalY());
|
|
||||||
r = r || buttonReleaseEvent(decorationId(), ev->delta() > 0 ? Button4 : Button5, qtToX11State(ev->buttons(), ev->modifiers()),
|
|
||||||
ev->x(), ev->y(), ev->globalX(), ev->globalY());
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
if (e->type() == QEvent::Resize && decoration->widget()) {
|
|
||||||
QResizeEvent* ev = static_cast< QResizeEvent* >(e);
|
|
||||||
// Filter out resize events that inform about size different than frame size.
|
|
||||||
// This will ensure that decoration->width() etc. and decoration->widget()->width() will be in sync.
|
|
||||||
// These events only seem to be delayed events from initial resizing before show() was called
|
|
||||||
// on the decoration widget.
|
|
||||||
if (ev->size() != (size() + QSize(padding_left + padding_right, padding_top + padding_bottom)))
|
|
||||||
return true;
|
|
||||||
// HACK: Avoid decoration redraw delays. On resize Qt sets WA_WStateConfigPending
|
|
||||||
// which delays all painting until a matching ConfigureNotify event comes.
|
|
||||||
// But this process itself is the window manager, so it's not needed
|
|
||||||
// to wait for that event, the geometry is known.
|
|
||||||
// Note that if Qt in the future changes how this flag is handled and what it
|
|
||||||
// triggers then this may potentionally break things. See mainly QETWidget::translateConfigEvent().
|
|
||||||
decoration->widget()->setAttribute(Qt::WA_WState_ConfigPending, false);
|
|
||||||
decoration->widget()->update();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (e->type() == QEvent::ZOrderChange) {
|
|
||||||
// when the user actions menu is closed by clicking on the window decoration (which is not unlikely)
|
|
||||||
// Qt will raise the decoration window and thus the decoration window is above the actual Client
|
|
||||||
// see QWidgetWindow::handleMouseEvent (qtbase/src/widgets/kernel/qwidgetwindow.cpp)
|
|
||||||
// when this happens also a ZOrderChange event is sent, we intercept all of them and make sure that
|
|
||||||
// the window is lowest in stack again.
|
|
||||||
Xcb::lowerWindow(decorationId());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool modKeyDown(int state) {
|
static bool modKeyDown(int state) {
|
||||||
const uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ?
|
const uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ?
|
||||||
KKeyServer::modXMeta() : KKeyServer::modXAlt();
|
KKeyServer::modXMeta() : KKeyServer::modXAlt();
|
||||||
|
@ -1111,7 +1044,7 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w == wrapperId() || w == frameId() || w == decorationId() || w == inputId()) {
|
if (w == wrapperId() || w == frameId() || w == inputId()) {
|
||||||
// FRAME neco s tohohle by se melo zpracovat, nez to dostane dekorace
|
// FRAME neco s tohohle by se melo zpracovat, nez to dostane dekorace
|
||||||
updateUserTime(time);
|
updateUserTime(time);
|
||||||
workspace()->setWasUserInteraction();
|
workspace()->setWasUserInteraction();
|
||||||
|
@ -1189,16 +1122,22 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (w == inputId()) {
|
if (w == inputId()) {
|
||||||
x = x_root - geometry().x() + padding_left;
|
x = x_root - geometry().x();
|
||||||
y = y_root - geometry().y() + padding_top;
|
y = y_root - geometry().y();
|
||||||
// New API processes core events FIRST and only passes unused ones to the decoration
|
// New API processes core events FIRST and only passes unused ones to the decoration
|
||||||
return processDecorationButtonPress(button, state, x, y, x_root, y_root, true);
|
return processDecorationButtonPress(button, state, x, y, x_root, y_root, true);
|
||||||
}
|
}
|
||||||
if (w == decorationId()) {
|
if (w == frameId() && m_decoration) {
|
||||||
return false;
|
qDebug() << "Button press on frame";
|
||||||
|
QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y), QPointF(x_root, y_root),
|
||||||
|
x11ToQtMouseButton(button), x11ToQtMouseButtons(state), x11ToQtKeyboardModifiers(state));
|
||||||
|
event.setAccepted(false);
|
||||||
|
QCoreApplication::sendEvent(m_decoration, &event);
|
||||||
|
if (!event.isAccepted()) {
|
||||||
|
processDecorationButtonPress(button, state, x, y, x_root, y_root);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (w == frameId())
|
|
||||||
processDecorationButtonPress(button, state, x, y, x_root, y_root);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,7 +1164,7 @@ bool Client::processDecorationButtonPress(int button, int /*state*/, int x, int
|
||||||
&& com != Options::MouseDragTab) {
|
&& com != Options::MouseDragTab) {
|
||||||
mode = mousePosition(QPoint(x, y));
|
mode = mousePosition(QPoint(x, y));
|
||||||
buttonDown = true;
|
buttonDown = true;
|
||||||
moveOffset = QPoint(x - padding_left, y - padding_top);
|
moveOffset = QPoint(x/* - padding_left*/, y/* - padding_top*/);
|
||||||
invertedMoveOffset = rect().bottomRight() - moveOffset;
|
invertedMoveOffset = rect().bottomRight() - moveOffset;
|
||||||
unrestrictedMoveResize = false;
|
unrestrictedMoveResize = false;
|
||||||
startDelayedMoveResize();
|
startDelayedMoveResize();
|
||||||
|
@ -1246,40 +1185,19 @@ bool Client::processDecorationButtonPress(int button, int /*state*/, int x, int
|
||||||
com == Options::MouseNothing);
|
com == Options::MouseNothing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from decoration
|
|
||||||
void Client::processMousePressEvent(QMouseEvent* e)
|
|
||||||
{
|
|
||||||
if (e->type() != QEvent::MouseButtonPress) {
|
|
||||||
qWarning() << "processMousePressEvent()" ;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int button;
|
|
||||||
switch(e->button()) {
|
|
||||||
case Qt::LeftButton:
|
|
||||||
button = XCB_BUTTON_INDEX_1;
|
|
||||||
break;
|
|
||||||
case Qt::MidButton:
|
|
||||||
button = XCB_BUTTON_INDEX_2;
|
|
||||||
break;
|
|
||||||
case Qt::RightButton:
|
|
||||||
button = XCB_BUTTON_INDEX_3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
processDecorationButtonPress(button, e->buttons(), e->x(), e->y(), e->globalX(), e->globalY());
|
|
||||||
}
|
|
||||||
|
|
||||||
// return value matters only when filtering events before decoration gets them
|
// return value matters only when filtering events before decoration gets them
|
||||||
bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root)
|
bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root)
|
||||||
{
|
{
|
||||||
if (w == decorationId() && !buttonDown)
|
if (w == frameId() && m_decoration) {
|
||||||
return false;
|
qDebug() << "Button release on frame";
|
||||||
|
QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x, y), QPointF(x_root, y_root), x11ToQtMouseButton(button), x11ToQtMouseButtons(state), x11ToQtKeyboardModifiers(state));
|
||||||
|
QCoreApplication::sendEvent(m_decoration, &event);
|
||||||
|
}
|
||||||
if (w == wrapperId()) {
|
if (w == wrapperId()) {
|
||||||
xcb_allow_events(connection(), XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); //xTime());
|
xcb_allow_events(connection(), XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); //xTime());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (w != frameId() && w != decorationId() && w != inputId() && w != moveResizeGrabWindow())
|
if (w != frameId() && w != inputId() && w != moveResizeGrabWindow())
|
||||||
return true;
|
return true;
|
||||||
x = this->x(); // translate from grab window to local coords
|
x = this->x(); // translate from grab window to local coords
|
||||||
y = this->y();
|
y = this->y();
|
||||||
|
@ -1299,10 +1217,9 @@ bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, in
|
||||||
if (moveResizeMode) {
|
if (moveResizeMode) {
|
||||||
finishMoveResize(false);
|
finishMoveResize(false);
|
||||||
// mouse position is still relative to old Client position, adjust it
|
// mouse position is still relative to old Client position, adjust it
|
||||||
QPoint mousepos(x_root - x + padding_left, y_root - y + padding_top);
|
QPoint mousepos(x_root - x, y_root - y);
|
||||||
mode = mousePosition(mousepos);
|
mode = mousePosition(mousepos);
|
||||||
} else if (decorationPlugin()->supportsTabbing())
|
}
|
||||||
return false;
|
|
||||||
updateCursor();
|
updateCursor();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1342,15 +1259,18 @@ void Client::checkQuickTilingMaximizationZones(int xroot, int yroot)
|
||||||
// return value matters only when filtering events before decoration gets them
|
// return value matters only when filtering events before decoration gets them
|
||||||
bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root)
|
bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root)
|
||||||
{
|
{
|
||||||
if (w != frameId() && w != decorationId() && w != inputId() && w != moveResizeGrabWindow())
|
if (w == frameId() && m_decoration) {
|
||||||
|
// TODO Mouse move event dependent on state
|
||||||
|
QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y));
|
||||||
|
QCoreApplication::instance()->sendEvent(m_decoration, &event);
|
||||||
|
}
|
||||||
|
if (w != frameId() && w != inputId() && w != moveResizeGrabWindow())
|
||||||
return true; // care only about the whole frame
|
return true; // care only about the whole frame
|
||||||
if (!buttonDown) {
|
if (!buttonDown) {
|
||||||
QPoint mousePos(x, y);
|
QPoint mousePos(x, y);
|
||||||
if (w == frameId())
|
|
||||||
mousePos += QPoint(padding_left, padding_top);
|
|
||||||
if (w == inputId()) {
|
if (w == inputId()) {
|
||||||
int x = x_root - geometry().x() + padding_left;
|
int x = x_root - geometry().x();// + padding_left;
|
||||||
int y = y_root - geometry().y() + padding_top;
|
int y = y_root - geometry().y();// + padding_top;
|
||||||
mousePos = QPoint(x, y);
|
mousePos = QPoint(x, y);
|
||||||
}
|
}
|
||||||
Position newmode = modKeyDown(state) ? PositionCenter : mousePosition(mousePos);
|
Position newmode = modKeyDown(state) ? PositionCenter : mousePosition(mousePos);
|
||||||
|
|
102
geometry.cpp
102
geometry.cpp
|
@ -48,6 +48,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "outline.h"
|
#include "outline.h"
|
||||||
|
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
#include <KDecoration2/DecoratedClient>
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1239,8 +1242,8 @@ void Client::checkOffscreenPosition(QRect* geom, const QRect& screenArea)
|
||||||
QSize Client::adjustedSize(const QSize& frame, Sizemode mode) const
|
QSize Client::adjustedSize(const QSize& frame, Sizemode mode) const
|
||||||
{
|
{
|
||||||
// first, get the window size for the given frame size s
|
// first, get the window size for the given frame size s
|
||||||
QSize wsize(frame.width() - (border_left + border_right),
|
QSize wsize(frame.width() - (borderLeft() + borderRight()),
|
||||||
frame.height() - (border_top + border_bottom));
|
frame.height() - (borderTop() + borderBottom()));
|
||||||
if (wsize.isEmpty())
|
if (wsize.isEmpty())
|
||||||
wsize = QSize(1, 1);
|
wsize = QSize(1, 1);
|
||||||
|
|
||||||
|
@ -1276,9 +1279,9 @@ QSize Client::sizeForClientSize(const QSize& wsize, Sizemode mode, bool noframe)
|
||||||
// even if they're not set in flags - see getWmNormalHints()
|
// even if they're not set in flags - see getWmNormalHints()
|
||||||
QSize min_size = tabGroup() ? tabGroup()->minSize() : minSize();
|
QSize min_size = tabGroup() ? tabGroup()->minSize() : minSize();
|
||||||
QSize max_size = tabGroup() ? tabGroup()->maxSize() : maxSize();
|
QSize max_size = tabGroup() ? tabGroup()->maxSize() : maxSize();
|
||||||
if (decoration != NULL) {
|
if (m_decoration != NULL) {
|
||||||
QSize decominsize = decoration->minimumSize();
|
QSize decominsize(0, 0);
|
||||||
QSize border_size(border_left + border_right, border_top + border_bottom);
|
QSize border_size(borderLeft() + borderRight(), borderTop() + borderBottom());
|
||||||
if (border_size.width() > decominsize.width()) // just in case
|
if (border_size.width() > decominsize.width()) // just in case
|
||||||
decominsize.setWidth(border_size.width());
|
decominsize.setWidth(border_size.width());
|
||||||
if (border_size.height() > decominsize.height())
|
if (border_size.height() > decominsize.height())
|
||||||
|
@ -1424,8 +1427,8 @@ QSize Client::sizeForClientSize(const QSize& wsize, Sizemode mode, bool noframe)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noframe) {
|
if (!noframe) {
|
||||||
w += border_left + border_right;
|
w += borderLeft() + borderRight();
|
||||||
h += border_top + border_bottom;
|
h += borderTop() + borderBottom();
|
||||||
}
|
}
|
||||||
return rules()->checkSize(QSize(w, h));
|
return rules()->checkSize(QSize(w, h));
|
||||||
}
|
}
|
||||||
|
@ -1556,19 +1559,19 @@ const QPoint Client::calculateGravitation(bool invert, int gravity) const
|
||||||
switch(gravity) {
|
switch(gravity) {
|
||||||
case NorthWestGravity: // move down right
|
case NorthWestGravity: // move down right
|
||||||
default:
|
default:
|
||||||
dx = border_left;
|
dx = borderLeft();
|
||||||
dy = border_top;
|
dy = borderTop();
|
||||||
break;
|
break;
|
||||||
case NorthGravity: // move right
|
case NorthGravity: // move right
|
||||||
dx = 0;
|
dx = 0;
|
||||||
dy = border_top;
|
dy = borderTop();
|
||||||
break;
|
break;
|
||||||
case NorthEastGravity: // move down left
|
case NorthEastGravity: // move down left
|
||||||
dx = -border_right;
|
dx = -borderRight();
|
||||||
dy = border_top;
|
dy = borderTop();
|
||||||
break;
|
break;
|
||||||
case WestGravity: // move right
|
case WestGravity: // move right
|
||||||
dx = border_left;
|
dx = borderLeft();
|
||||||
dy = 0;
|
dy = 0;
|
||||||
break;
|
break;
|
||||||
case CenterGravity:
|
case CenterGravity:
|
||||||
|
@ -1578,30 +1581,30 @@ const QPoint Client::calculateGravitation(bool invert, int gravity) const
|
||||||
dy = 0;
|
dy = 0;
|
||||||
break;
|
break;
|
||||||
case EastGravity: // move left
|
case EastGravity: // move left
|
||||||
dx = -border_right;
|
dx = -borderRight();
|
||||||
dy = 0;
|
dy = 0;
|
||||||
break;
|
break;
|
||||||
case SouthWestGravity: // move up right
|
case SouthWestGravity: // move up right
|
||||||
dx = border_left ;
|
dx = borderLeft() ;
|
||||||
dy = -border_bottom;
|
dy = -borderBottom();
|
||||||
break;
|
break;
|
||||||
case SouthGravity: // move up
|
case SouthGravity: // move up
|
||||||
dx = 0;
|
dx = 0;
|
||||||
dy = -border_bottom;
|
dy = -borderBottom();
|
||||||
break;
|
break;
|
||||||
case SouthEastGravity: // move up left
|
case SouthEastGravity: // move up left
|
||||||
dx = -border_right;
|
dx = -borderRight();
|
||||||
dy = -border_bottom;
|
dy = -borderBottom();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (gravity != CenterGravity) {
|
if (gravity != CenterGravity) {
|
||||||
// translate from client movement to frame movement
|
// translate from client movement to frame movement
|
||||||
dx -= border_left;
|
dx -= borderLeft();
|
||||||
dy -= border_top;
|
dy -= borderTop();
|
||||||
} else {
|
} else {
|
||||||
// center of the frame will be at the same position client center without frame would be
|
// center of the frame will be at the same position client center without frame would be
|
||||||
dx = - (border_left + border_right) / 2;
|
dx = - (borderLeft() + borderRight()) / 2;
|
||||||
dy = - (border_top + border_bottom) / 2;
|
dy = - (borderTop() + borderBottom()) / 2;
|
||||||
}
|
}
|
||||||
if (!invert)
|
if (!invert)
|
||||||
return QPoint(x() + dx, y() + dy);
|
return QPoint(x() + dx, y() + dy);
|
||||||
|
@ -1740,7 +1743,7 @@ void Client::resizeWithChecks(int w, int h, ForceGeometry_t force)
|
||||||
{
|
{
|
||||||
assert(!shade_geometry_change);
|
assert(!shade_geometry_change);
|
||||||
if (isShade()) {
|
if (isShade()) {
|
||||||
if (h == border_top + border_bottom) {
|
if (h == borderTop() + borderBottom()) {
|
||||||
qWarning() << "Shaded geometry passed for size:" ;
|
qWarning() << "Shaded geometry passed for size:" ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1892,14 +1895,14 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
|
||||||
if (shade_geometry_change)
|
if (shade_geometry_change)
|
||||||
; // nothing
|
; // nothing
|
||||||
else if (isShade()) {
|
else if (isShade()) {
|
||||||
if (h == border_top + border_bottom) {
|
if (h == borderTop() + borderBottom()) {
|
||||||
qDebug() << "Shaded geometry passed for size:";
|
qDebug() << "Shaded geometry passed for size:";
|
||||||
} else {
|
} else {
|
||||||
client_size = QSize(w - border_left - border_right, h - border_top - border_bottom);
|
client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
|
||||||
h = border_top + border_bottom;
|
h = borderTop() + borderBottom();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client_size = QSize(w - border_left - border_right, h - border_top - border_bottom);
|
client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
|
||||||
}
|
}
|
||||||
QRect g(x, y, w, h);
|
QRect g(x, y, w, h);
|
||||||
if (block_geometry_updates == 0 && g != rules()->checkGeometry(g)) {
|
if (block_geometry_updates == 0 && g != rules()->checkGeometry(g)) {
|
||||||
|
@ -1980,14 +1983,14 @@ void Client::plainResize(int w, int h, ForceGeometry_t force)
|
||||||
if (shade_geometry_change)
|
if (shade_geometry_change)
|
||||||
; // nothing
|
; // nothing
|
||||||
else if (isShade()) {
|
else if (isShade()) {
|
||||||
if (h == border_top + border_bottom) {
|
if (h == borderTop() + borderBottom()) {
|
||||||
qDebug() << "Shaded geometry passed for size:";
|
qDebug() << "Shaded geometry passed for size:";
|
||||||
} else {
|
} else {
|
||||||
client_size = QSize(w - border_left - border_right, h - border_top - border_bottom);
|
client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
|
||||||
h = border_top + border_bottom;
|
h = borderTop() + borderBottom();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client_size = QSize(w - border_left - border_right, h - border_top - border_bottom);
|
client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
|
||||||
}
|
}
|
||||||
QSize s(w, h);
|
QSize s(w, h);
|
||||||
if (block_geometry_updates == 0 && s != rules()->checkSize(s)) {
|
if (block_geometry_updates == 0 && s != rules()->checkSize(s)) {
|
||||||
|
@ -2208,6 +2211,19 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
|
||||||
changeMaximize(false, false, false); // restore
|
changeMaximize(false, false, false); // restore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call into decoration update borders
|
||||||
|
if (m_decoration) {
|
||||||
|
if ((max_mode & KDecorationDefines::MaximizeVertical) != (old_mode & KDecorationDefines::MaximizeVertical)) {
|
||||||
|
emit m_decoration->client()->maximizedVerticallyChanged(max_mode & KDecorationDefines::MaximizeVertical);
|
||||||
|
}
|
||||||
|
if ((max_mode & KDecorationDefines::MaximizeHorizontal) != (old_mode & KDecorationDefines::MaximizeHorizontal)) {
|
||||||
|
emit m_decoration->client()->maximizedHorizontallyChanged(max_mode & KDecorationDefines::MaximizeHorizontal);
|
||||||
|
}
|
||||||
|
if ((max_mode == KDecorationDefines::MaximizeFull) != (old_mode == KDecorationDefines::MaximizeFull)) {
|
||||||
|
emit m_decoration->client()->maximizedChanged(max_mode & KDecorationDefines::MaximizeFull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// save sizes for restoring, if maximalizing
|
// save sizes for restoring, if maximalizing
|
||||||
QSize sz;
|
QSize sz;
|
||||||
if (isShade())
|
if (isShade())
|
||||||
|
@ -2234,7 +2250,7 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
|
||||||
changeMaximizeRecursion = false;
|
changeMaximizeRecursion = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
|
const ForceGeometry_t geom_mode = m_decoration ? ForceGeometrySet : NormalGeometrySet;
|
||||||
|
|
||||||
// Conditional quick tiling exit points
|
// Conditional quick tiling exit points
|
||||||
if (quick_tile_mode != QuickTileNone) {
|
if (quick_tile_mode != QuickTileNone) {
|
||||||
|
@ -2692,12 +2708,12 @@ void Client::checkUnrestrictedMoveResize()
|
||||||
int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
|
int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
|
||||||
// restricted move/resize - keep at least part of the titlebar always visible
|
// restricted move/resize - keep at least part of the titlebar always visible
|
||||||
// how much must remain visible when moved away in that direction
|
// how much must remain visible when moved away in that direction
|
||||||
left_marge = qMin(100 + border_right, moveResizeGeom.width());
|
left_marge = qMin(100 + borderRight(), moveResizeGeom.width());
|
||||||
right_marge = qMin(100 + border_left, moveResizeGeom.width());
|
right_marge = qMin(100 + borderLeft(), moveResizeGeom.width());
|
||||||
// width/height change with opaque resizing, use the initial ones
|
// width/height change with opaque resizing, use the initial ones
|
||||||
titlebar_marge = initialMoveResizeGeom.height();
|
titlebar_marge = initialMoveResizeGeom.height();
|
||||||
top_marge = border_bottom;
|
top_marge = borderBottom();
|
||||||
bottom_marge = border_top;
|
bottom_marge = borderTop();
|
||||||
if (isResize()) {
|
if (isResize()) {
|
||||||
if (moveResizeGeom.bottom() < desktopArea.top() + top_marge)
|
if (moveResizeGeom.bottom() < desktopArea.top() + top_marge)
|
||||||
unrestrictedMoveResize = true;
|
unrestrictedMoveResize = true;
|
||||||
|
@ -2760,7 +2776,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!moveResizeMode) {
|
if (!moveResizeMode) {
|
||||||
QPoint p(QPoint(x - padding_left, y - padding_top) - moveOffset);
|
QPoint p(QPoint(x/* - padding_left*/, y/* - padding_top*/) - moveOffset);
|
||||||
if (p.manhattanLength() >= QApplication::startDragDistance()) {
|
if (p.manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
if (!startMoveResize()) {
|
if (!startMoveResize()) {
|
||||||
buttonDown = false;
|
buttonDown = false;
|
||||||
|
@ -2787,7 +2803,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root)
|
||||||
|
|
||||||
// When doing a restricted move we must always keep 100px of the titlebar
|
// When doing a restricted move we must always keep 100px of the titlebar
|
||||||
// visible to allow the user to be able to move it again.
|
// visible to allow the user to be able to move it again.
|
||||||
const int frameTop = border_top;
|
const int frameTop = borderTop();
|
||||||
int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * moveResizeGeom.height());
|
int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * moveResizeGeom.height());
|
||||||
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
@ -3033,7 +3049,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root)
|
||||||
syncRequest.isPending = true; // limit the resizes to 30Hz to take pointless load from X11
|
syncRequest.isPending = true; // limit the resizes to 30Hz to take pointless load from X11
|
||||||
syncRequest.timeout->start(33); // and the client, the mouse is still moved at full speed
|
syncRequest.timeout->start(33); // and the client, the mouse is still moved at full speed
|
||||||
} // and no human can control faster resizes anyway
|
} // and no human can control faster resizes anyway
|
||||||
m_client.setGeometry(0, 0, moveResizeGeom.width() - (border_left + border_right), moveResizeGeom.height() - (border_top + border_bottom));
|
m_client.setGeometry(0, 0, moveResizeGeom.width() - (borderLeft() + borderRight()), moveResizeGeom.height() - (borderTop() + borderBottom()));
|
||||||
} else
|
} else
|
||||||
performMoveResize();
|
performMoveResize();
|
||||||
|
|
||||||
|
@ -3156,7 +3172,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
||||||
if (mode != QuickTileNone) {
|
if (mode != QuickTileNone) {
|
||||||
quick_tile_mode = mode;
|
quick_tile_mode = mode;
|
||||||
// decorations may turn off some borders when tiled
|
// decorations may turn off some borders when tiled
|
||||||
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
|
const ForceGeometry_t geom_mode = m_decoration ? ForceGeometrySet : NormalGeometrySet;
|
||||||
quick_tile_mode = QuickTileNone; // Temporary, so the maximize code doesn't get all confused
|
quick_tile_mode = QuickTileNone; // Temporary, so the maximize code doesn't get all confused
|
||||||
setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : Cursor::pos(), desktop()), geom_mode);
|
setGeometry(electricBorderMaximizeGeometry(keyboard ? geometry().center() : Cursor::pos(), desktop()), geom_mode);
|
||||||
}
|
}
|
||||||
|
@ -3220,7 +3236,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
||||||
if (mode != QuickTileNone) {
|
if (mode != QuickTileNone) {
|
||||||
quick_tile_mode = mode;
|
quick_tile_mode = mode;
|
||||||
// decorations may turn off some borders when tiled
|
// decorations may turn off some borders when tiled
|
||||||
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
|
const ForceGeometry_t geom_mode = m_decoration ? ForceGeometrySet : NormalGeometrySet;
|
||||||
// Temporary, so the maximize code doesn't get all confused
|
// Temporary, so the maximize code doesn't get all confused
|
||||||
quick_tile_mode = QuickTileNone;
|
quick_tile_mode = QuickTileNone;
|
||||||
setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()), geom_mode);
|
setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()), geom_mode);
|
||||||
|
@ -3238,7 +3254,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
||||||
if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement
|
if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement
|
||||||
geom_restore = geometry();
|
geom_restore = geometry();
|
||||||
// decorations may turn off some borders when tiled
|
// decorations may turn off some borders when tiled
|
||||||
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
|
const ForceGeometry_t geom_mode = m_decoration ? ForceGeometrySet : NormalGeometrySet;
|
||||||
setGeometry(geom_restore, geom_mode);
|
setGeometry(geom_restore, geom_mode);
|
||||||
checkWorkspacePosition(); // Just in case it's a different screen
|
checkWorkspacePosition(); // Just in case it's a different screen
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "activities.h"
|
#include "activities.h"
|
||||||
#endif
|
#endif
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include <QX11Info>
|
#include <QX11Info>
|
||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
@ -321,7 +320,7 @@ bool Client::manage(xcb_window_t w, bool isMapped)
|
||||||
// Create client group if the window will have a decoration
|
// Create client group if the window will have a decoration
|
||||||
bool dontKeepInArea = false;
|
bool dontKeepInArea = false;
|
||||||
setTabGroup(NULL);
|
setTabGroup(NULL);
|
||||||
if (!noBorder() && DecorationPlugin::self()->supportsTabbing()) {
|
if (!noBorder() && false) {
|
||||||
const bool autogrouping = rules()->checkAutogrouping(options->isAutogroupSimilarWindows());
|
const bool autogrouping = rules()->checkAutogrouping(options->isAutogroupSimilarWindows());
|
||||||
const bool autogroupInFg = rules()->checkAutogroupInForeground(options->isAutogroupInForeground());
|
const bool autogroupInFg = rules()->checkAutogroupInForeground(options->isAutogroupInForeground());
|
||||||
// Automatically add to previous groups on session restore
|
// Automatically add to previous groups on session restore
|
||||||
|
@ -678,7 +677,7 @@ void Client::embedClient(xcb_window_t w, xcb_visualid_t visualid, xcb_colormap_t
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
|
||||||
|
|
||||||
const uint32_t frame_event_mask = common_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
const uint32_t frame_event_mask = common_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_VISIBILITY_CHANGE;
|
||||||
const uint32_t wrapper_event_mask = common_event_mask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
const uint32_t wrapper_event_mask = common_event_mask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||||
|
|
||||||
const uint32_t client_event_mask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE |
|
const uint32_t client_event_mask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE |
|
||||||
|
|
|
@ -25,7 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <kdecorationfactory.h>
|
#include <kdecorationfactory.h>
|
||||||
// kwin
|
// kwin
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "virtualdesktops.h"
|
#include "virtualdesktops.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
// Qt
|
// Qt
|
||||||
|
@ -121,10 +120,6 @@ RootInfo *RootInfo::create()
|
||||||
NET::ActionChangeDesktop |
|
NET::ActionChangeDesktop |
|
||||||
NET::ActionClose;
|
NET::ActionClose;
|
||||||
|
|
||||||
DecorationPlugin *deco = DecorationPlugin::self();
|
|
||||||
if (!deco->isDisabled() && deco->factory()->supports(KDecorationDefines::AbilityExtendIntoClientArea))
|
|
||||||
properties2 |= NET::WM2FrameOverlap;
|
|
||||||
|
|
||||||
s_self = new RootInfo(supportWindow, "KWin", properties, types, states, properties2, actions, screen_number);
|
s_self = new RootInfo(supportWindow, "KWin", properties, types, states, properties2, actions, screen_number);
|
||||||
return s_self;
|
return s_self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,561 +0,0 @@
|
||||||
/*****************************************************************
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2009 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
******************************************************************/
|
|
||||||
|
|
||||||
#include "paintredirector.h"
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
#include "deleted.h"
|
|
||||||
#include "effects.h"
|
|
||||||
#include <kwinglplatform.h>
|
|
||||||
#include <kwinglutils.h>
|
|
||||||
#include <kwinxrenderutils.h>
|
|
||||||
#include <QPaintEngine>
|
|
||||||
#include <qevent.h>
|
|
||||||
#include <qpainter.h>
|
|
||||||
#include <qmath.h>
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
PaintRedirector *PaintRedirector::create(Client *c, KDecoration *deco)
|
|
||||||
{
|
|
||||||
if (effects->isOpenGLCompositing()) {
|
|
||||||
return new OpenGLPaintRedirector(c, deco);
|
|
||||||
} else if (effects->compositingType() == XRenderCompositing) {
|
|
||||||
return new RasterXRenderPaintRedirector(c, deco);
|
|
||||||
} else if (effects->compositingType() == QPainterCompositing) {
|
|
||||||
return new QImagePaintRedirector(c, deco);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PaintRedirector::PaintRedirector(Client *c, KDecoration *deco)
|
|
||||||
: QObject(deco)
|
|
||||||
, widget(deco->widget())
|
|
||||||
, recursionCheck(false)
|
|
||||||
, m_client(c)
|
|
||||||
, m_decoration(deco)
|
|
||||||
, m_requiresRepaint(false)
|
|
||||||
{
|
|
||||||
added(deco->widget());
|
|
||||||
}
|
|
||||||
|
|
||||||
PaintRedirector::~PaintRedirector()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::reparent(Deleted *d)
|
|
||||||
{
|
|
||||||
setParent(d);
|
|
||||||
widget = NULL;
|
|
||||||
m_client = NULL;
|
|
||||||
m_decoration = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int align(int value, int align)
|
|
||||||
{
|
|
||||||
return (value + align - 1) & ~(align - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::performPendingPaint()
|
|
||||||
{
|
|
||||||
if (!widget && !m_decoration->window()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//qDebug() << "### performing paint, pending:" << pending.boundingRect();
|
|
||||||
const QSize size = pending.boundingRect().size();
|
|
||||||
QPaintDevice *scratch = this->scratch();
|
|
||||||
if (scratch->width() < size.width() || scratch->height() < size.height()) {
|
|
||||||
int w = align(size.width(), 128);
|
|
||||||
int h = align(size.height(), 128);
|
|
||||||
scratch = recreateScratch(QSize(qMax(scratch->width(), w), qMax(scratch->height(), h)));
|
|
||||||
}
|
|
||||||
fillScratch(Qt::transparent);
|
|
||||||
recursionCheck = true;
|
|
||||||
m_decoration->render(scratch, pending.boundingRect());
|
|
||||||
recursionCheck = false;
|
|
||||||
cleanupTimer.start(2000, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PaintRedirector::isToolTip(QWidget *object) const
|
|
||||||
{
|
|
||||||
// ### We need a more reliable way of doing this
|
|
||||||
return object->windowFlags() & Qt::ToolTip;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PaintRedirector::eventFilter(QObject* o, QEvent* e)
|
|
||||||
{
|
|
||||||
if (!widget || !m_client) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch(e->type()) {
|
|
||||||
case QEvent::ChildAdded: {
|
|
||||||
QChildEvent* c = static_cast< QChildEvent* >(e);
|
|
||||||
if (c->child()->isWidgetType() && !isToolTip(static_cast< QWidget* >(c->child())))
|
|
||||||
added(static_cast< QWidget* >(c->child()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::ChildRemoved: {
|
|
||||||
QChildEvent* c = static_cast< QChildEvent* >(e);
|
|
||||||
if (c->child()->isWidgetType())
|
|
||||||
removed(static_cast< QWidget* >(c->child()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::Paint: {
|
|
||||||
if (!recursionCheck) {
|
|
||||||
QPaintEvent* pe = static_cast< QPaintEvent* >(e);
|
|
||||||
QWidget* w = static_cast< QWidget* >(o);
|
|
||||||
pending |= pe->region().translated(w->mapTo(widget, QPoint(0, 0)));
|
|
||||||
scheduled = pending;
|
|
||||||
|
|
||||||
// schedule repaint
|
|
||||||
const int paddingLeft = m_client->paddingLeft();
|
|
||||||
const int paddingTop = m_client->paddingTop();
|
|
||||||
const bool needsTranslate = (paddingLeft != 0 || paddingTop != 0);
|
|
||||||
m_client->addRepaint(needsTranslate ? pending.translated(-paddingLeft, -paddingTop) : pending);
|
|
||||||
m_requiresRepaint = true;
|
|
||||||
return true; // filter out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::addRepaint(const QRegion ®ion)
|
|
||||||
{
|
|
||||||
pending |= region;
|
|
||||||
scheduled = pending;
|
|
||||||
|
|
||||||
// schedule repaint
|
|
||||||
const int paddingLeft = m_client->paddingLeft();
|
|
||||||
const int paddingTop = m_client->paddingTop();
|
|
||||||
const bool needsTranslate = (paddingLeft != 0 || paddingTop != 0);
|
|
||||||
m_client->addRepaint(needsTranslate ? pending.translated(-paddingLeft, -paddingTop) : pending);
|
|
||||||
m_requiresRepaint = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRegion PaintRedirector::pendingRegion() const
|
|
||||||
{
|
|
||||||
return pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRegion PaintRedirector::scheduledRepaintRegion()
|
|
||||||
{
|
|
||||||
QRegion tempRegion = scheduled;
|
|
||||||
scheduled = QRegion();
|
|
||||||
return tempRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::added(QWidget* w)
|
|
||||||
{
|
|
||||||
if (!w) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
w->installEventFilter(this);
|
|
||||||
foreach (QObject * o, w->children()) {
|
|
||||||
if (o->isWidgetType() && !isToolTip(static_cast< QWidget* >(o)))
|
|
||||||
added(static_cast< QWidget* >(o));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::removed(QWidget* w)
|
|
||||||
{
|
|
||||||
foreach (QObject * o, w->children()) {
|
|
||||||
if (o->isWidgetType())
|
|
||||||
removed(static_cast< QWidget* >(o));
|
|
||||||
}
|
|
||||||
w->installEventFilter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::timerEvent(QTimerEvent* event)
|
|
||||||
{
|
|
||||||
if (event->timerId() == cleanupTimer.timerId()) {
|
|
||||||
cleanupTimer.stop();
|
|
||||||
discardScratch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::ensurePixmapsPainted()
|
|
||||||
{
|
|
||||||
if (pending.isEmpty() || !m_client)
|
|
||||||
return;
|
|
||||||
|
|
||||||
performPendingPaint();
|
|
||||||
|
|
||||||
QRect rects[PixmapCount];
|
|
||||||
m_client->layoutDecorationRects(rects[LeftPixmap], rects[TopPixmap], rects[RightPixmap], rects[BottomPixmap], Client::DecorationRelative);
|
|
||||||
|
|
||||||
updatePixmaps(rects, pending);
|
|
||||||
|
|
||||||
pending = QRegion();
|
|
||||||
scheduled = QRegion();
|
|
||||||
|
|
||||||
xcb_flush(connection());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::updatePixmaps(const QRect *rects, const QRegion ®ion)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < PixmapCount; ++i) {
|
|
||||||
if (!rects[i].isValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const QRect bounding = region.boundingRect();
|
|
||||||
const QRegion reg = region & rects[i];
|
|
||||||
|
|
||||||
if (reg.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
paint(DecorationPixmap(i), rects[i], bounding, reg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::preparePaint(const QPixmap &pending)
|
|
||||||
{
|
|
||||||
Q_UNUSED(pending)
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::resizePixmaps()
|
|
||||||
{
|
|
||||||
QRect rects[PixmapCount];
|
|
||||||
m_client->layoutDecorationRects(rects[LeftPixmap], rects[TopPixmap], rects[RightPixmap], rects[BottomPixmap], Client::DecorationRelative);
|
|
||||||
|
|
||||||
resizePixmaps(rects);
|
|
||||||
|
|
||||||
// repaint
|
|
||||||
if (widget) {
|
|
||||||
widget->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::resizePixmaps(const QRect *rects)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < PixmapCount; ++i) {
|
|
||||||
resize(DecorationPixmap(i), rects[i].size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture *PaintRedirector::texture(PaintRedirector::DecorationPixmap border) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(border)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_render_picture_t PaintRedirector::picture(PaintRedirector::DecorationPixmap border) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(border)
|
|
||||||
return XCB_RENDER_PICTURE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QImage *PaintRedirector::image(PaintRedirector::DecorationPixmap border) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(border)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::resize(DecorationPixmap border, const QSize &size)
|
|
||||||
{
|
|
||||||
Q_UNUSED(border)
|
|
||||||
Q_UNUSED(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintRedirector::paint(DecorationPixmap border, const QRect& r, const QRect &b, const QRegion ®)
|
|
||||||
{
|
|
||||||
Q_UNUSED(border)
|
|
||||||
Q_UNUSED(r)
|
|
||||||
Q_UNUSED(b)
|
|
||||||
Q_UNUSED(reg)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ImageBasedPaintRedirector::ImageBasedPaintRedirector(Client *c, KDecoration *deco)
|
|
||||||
: PaintRedirector(c, deco)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageBasedPaintRedirector::~ImageBasedPaintRedirector()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QPaintDevice *ImageBasedPaintRedirector::recreateScratch(const QSize &size)
|
|
||||||
{
|
|
||||||
m_scratchImage = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
return &m_scratchImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPaintDevice *ImageBasedPaintRedirector::scratch()
|
|
||||||
{
|
|
||||||
return &m_scratchImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageBasedPaintRedirector::fillScratch(Qt::GlobalColor color)
|
|
||||||
{
|
|
||||||
m_scratchImage.fill(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageBasedPaintRedirector::discardScratch()
|
|
||||||
{
|
|
||||||
m_scratchImage = QImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
OpenGLPaintRedirector::OpenGLPaintRedirector(Client *c, KDecoration *deco)
|
|
||||||
: ImageBasedPaintRedirector(c, deco),
|
|
||||||
m_texture(nullptr)
|
|
||||||
{
|
|
||||||
PaintRedirector::resizePixmaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenGLPaintRedirector::~OpenGLPaintRedirector()
|
|
||||||
{
|
|
||||||
delete m_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLPaintRedirector::resizePixmaps(const QRect *rects)
|
|
||||||
{
|
|
||||||
QSize size;
|
|
||||||
|
|
||||||
size.rwidth() = qMax(qMax(rects[TopPixmap].width(), rects[BottomPixmap].width()),
|
|
||||||
qMax(rects[LeftPixmap].height(), rects[RightPixmap].height()));
|
|
||||||
size.rheight() = rects[TopPixmap].height() + rects[BottomPixmap].height() +
|
|
||||||
rects[LeftPixmap].width() + rects[RightPixmap].width() + 3;
|
|
||||||
|
|
||||||
size.rwidth() = align(size.width(), 128);
|
|
||||||
|
|
||||||
effects->makeOpenGLContextCurrent();
|
|
||||||
if (!GLTexture::NPOTTextureSupported()) {
|
|
||||||
size.rwidth() = nearestPowerOfTwo(size.width());
|
|
||||||
size.rheight() = nearestPowerOfTwo(size.height());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_texture && m_texture->size() == size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete m_texture;
|
|
||||||
m_texture = 0;
|
|
||||||
|
|
||||||
if (!size.isEmpty()) {
|
|
||||||
m_texture = new GLTexture(size.width(), size.height());
|
|
||||||
m_texture->setYInverted(true);
|
|
||||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
|
||||||
m_texture->clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotates the given source rect 90° counter-clockwise,
|
|
||||||
// and flips it vertically
|
|
||||||
static QImage rotate(const QImage &srcImage, const QRect &srcRect)
|
|
||||||
{
|
|
||||||
QImage image(srcRect.height(), srcRect.width(), srcImage.format());
|
|
||||||
|
|
||||||
const uint32_t *src = reinterpret_cast<const uint32_t *>(srcImage.bits());
|
|
||||||
uint32_t *dst = reinterpret_cast<uint32_t *>(image.bits());
|
|
||||||
|
|
||||||
for (int x = 0; x < image.width(); x++) {
|
|
||||||
const uint32_t *s = src + (srcRect.y() + x) * srcImage.width() + srcRect.x();
|
|
||||||
uint32_t *d = dst + x;
|
|
||||||
|
|
||||||
for (int y = 0; y < image.height(); y++) {
|
|
||||||
*d = s[y];
|
|
||||||
d += image.width();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLPaintRedirector::updatePixmaps(const QRect *rects, const QRegion ®ion)
|
|
||||||
{
|
|
||||||
const QImage &image = scratchImage();
|
|
||||||
const QRect bounding = region.boundingRect();
|
|
||||||
|
|
||||||
if (!m_texture)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Top, Right, Bottom, Left
|
|
||||||
Qt::Orientation orientations[4] = { Qt::Horizontal, Qt::Vertical, Qt::Horizontal, Qt::Vertical };
|
|
||||||
|
|
||||||
const int topHeight = rects[TopPixmap].height();
|
|
||||||
const int bottomHeight = rects[BottomPixmap].height();
|
|
||||||
const int leftWidth = rects[RightPixmap].width();
|
|
||||||
|
|
||||||
const QPoint offsets[4] = {
|
|
||||||
QPoint(0, 0), // Top
|
|
||||||
QPoint(0, topHeight + bottomHeight + leftWidth + 3), // Right
|
|
||||||
QPoint(0, topHeight + 1), // Bottom
|
|
||||||
QPoint(0, topHeight + bottomHeight + 2) // Left
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
const QRect dirty = (region & rects[i]).boundingRect();
|
|
||||||
if (dirty.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const QPoint dst = dirty.topLeft() - rects[i].topLeft() + offsets[i];
|
|
||||||
const QRect src(dirty.topLeft() - bounding.topLeft(), dirty.size());
|
|
||||||
|
|
||||||
if (orientations[i] == Qt::Horizontal) {
|
|
||||||
m_texture->update(image, dst, src);
|
|
||||||
} else {
|
|
||||||
// We have to rotate the src image
|
|
||||||
const QImage im = rotate(image, src);
|
|
||||||
m_texture->update(im, dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RasterXRenderPaintRedirector::RasterXRenderPaintRedirector(Client *c, KDecoration *deco)
|
|
||||||
: ImageBasedPaintRedirector(c, deco)
|
|
||||||
, m_gc(0)
|
|
||||||
{
|
|
||||||
for (int i=0; i<PixmapCount; ++i) {
|
|
||||||
m_pixmaps[i] = XCB_PIXMAP_NONE;
|
|
||||||
m_pictures[i] = NULL;
|
|
||||||
}
|
|
||||||
resizePixmaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
RasterXRenderPaintRedirector::~RasterXRenderPaintRedirector()
|
|
||||||
{
|
|
||||||
for (int i=0; i<PixmapCount; ++i) {
|
|
||||||
if (m_pixmaps[i] != XCB_PIXMAP_NONE) {
|
|
||||||
xcb_free_pixmap(connection(), m_pixmaps[i]);
|
|
||||||
}
|
|
||||||
delete m_pictures[i];
|
|
||||||
}
|
|
||||||
if (m_gc != 0) {
|
|
||||||
xcb_free_gc(connection(), m_gc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_render_picture_t RasterXRenderPaintRedirector::picture(PaintRedirector::DecorationPixmap border) const
|
|
||||||
{
|
|
||||||
XRenderPicture *picture = m_pictures[border];
|
|
||||||
if (!picture) {
|
|
||||||
return XCB_RENDER_PICTURE_NONE;
|
|
||||||
}
|
|
||||||
return *picture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterXRenderPaintRedirector::resize(PaintRedirector::DecorationPixmap border, const QSize &size)
|
|
||||||
{
|
|
||||||
if (m_sizes[border] != size) {
|
|
||||||
m_sizes[border] = size;
|
|
||||||
if (m_pixmaps[border] != XCB_PIXMAP_NONE) {
|
|
||||||
xcb_free_pixmap(connection(), m_pixmaps[border]);
|
|
||||||
}
|
|
||||||
delete m_pictures[border];
|
|
||||||
if (!size.isEmpty()) {
|
|
||||||
m_pixmaps[border] = xcb_generate_id(connection());
|
|
||||||
xcb_create_pixmap(connection(), 32, m_pixmaps[border], rootWindow(), size.width(), size.height());
|
|
||||||
m_pictures[border] = new XRenderPicture(m_pixmaps[border], 32);
|
|
||||||
} else {
|
|
||||||
m_pixmaps[border] = XCB_PIXMAP_NONE;
|
|
||||||
m_pictures[border] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!m_pictures[border]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// fill transparent
|
|
||||||
xcb_rectangle_t rect = {0, 0, uint16_t(size.width()), uint16_t(size.height())};
|
|
||||||
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, *m_pictures[border], preMultiply(Qt::transparent), 1, &rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterXRenderPaintRedirector::preparePaint(const QPixmap &pending)
|
|
||||||
{
|
|
||||||
m_tempImage = pending.toImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterXRenderPaintRedirector::paint(PaintRedirector::DecorationPixmap border, const QRect &r, const QRect &b, const QRegion ®)
|
|
||||||
{
|
|
||||||
// clip the sub area
|
|
||||||
const QRect bounding = reg.boundingRect();
|
|
||||||
const QPoint offset = bounding.topLeft() - r.topLeft();
|
|
||||||
if (m_gc == 0) {
|
|
||||||
m_gc = xcb_generate_id(connection());
|
|
||||||
xcb_create_gc(connection(), m_gc, m_pixmaps[border], 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QImage img(scratchImage().copy(QRect(bounding.topLeft() - b.topLeft(), bounding.size())));
|
|
||||||
xcb_put_image(connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, m_pixmaps[border], m_gc,
|
|
||||||
img.width(), img.height(), offset.x(), offset.y(), 0, 32, img.byteCount(), img.constBits());
|
|
||||||
}
|
|
||||||
|
|
||||||
QImagePaintRedirector::QImagePaintRedirector(Client *c, KDecoration *deco)
|
|
||||||
: ImageBasedPaintRedirector(c, deco)
|
|
||||||
{
|
|
||||||
resizePixmaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
QImagePaintRedirector::~QImagePaintRedirector()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QImagePaintRedirector::paint(PaintRedirector::DecorationPixmap border, const QRect &r, const QRect &b, const QRegion ®)
|
|
||||||
{
|
|
||||||
// clip the sub area
|
|
||||||
const QRect bounding = reg.boundingRect();
|
|
||||||
const QPoint offset = bounding.topLeft() - r.topLeft();
|
|
||||||
|
|
||||||
QPainter painter(&m_images[border]);
|
|
||||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
|
||||||
painter.drawImage(offset, scratchImage(), QRect(bounding.topLeft() - b.topLeft(), bounding.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QImagePaintRedirector::resize(PaintRedirector::DecorationPixmap border, const QSize &size)
|
|
||||||
{
|
|
||||||
m_images[border] = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
m_images[border].fill(Qt::transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QImage *QImagePaintRedirector::image(PaintRedirector::DecorationPixmap border) const
|
|
||||||
{
|
|
||||||
return &m_images[border];
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#include "paintredirector.moc"
|
|
|
@ -1,290 +0,0 @@
|
||||||
/*****************************************************************
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2009 Lubos Lunak <l.lunak@kde.org>
|
|
||||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
******************************************************************/
|
|
||||||
|
|
||||||
#ifndef PAINTREDIRECTOR_H
|
|
||||||
#define PAINTREDIRECTOR_H
|
|
||||||
|
|
||||||
#include <qregion.h>
|
|
||||||
#include <qtimer.h>
|
|
||||||
#include <qwidget.h>
|
|
||||||
#include <qbasictimer.h>
|
|
||||||
// xcb
|
|
||||||
#include <xcb/render.h>
|
|
||||||
|
|
||||||
class KDecoration;
|
|
||||||
|
|
||||||
namespace KWin
|
|
||||||
{
|
|
||||||
|
|
||||||
// forward declarations
|
|
||||||
class Client;
|
|
||||||
class Deleted;
|
|
||||||
class XRenderPicture;
|
|
||||||
class GLTexture;
|
|
||||||
|
|
||||||
// This class redirects all painting of a given widget (including its children)
|
|
||||||
// into a paint device (QPixmap).
|
|
||||||
class PaintRedirector
|
|
||||||
: public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
enum DecorationPixmap {
|
|
||||||
TopPixmap,
|
|
||||||
RightPixmap,
|
|
||||||
BottomPixmap,
|
|
||||||
LeftPixmap,
|
|
||||||
PixmapCount
|
|
||||||
};
|
|
||||||
virtual ~PaintRedirector();
|
|
||||||
virtual bool eventFilter(QObject* o, QEvent* e);
|
|
||||||
QRegion pendingRegion() const;
|
|
||||||
QRegion scheduledRepaintRegion();
|
|
||||||
|
|
||||||
void markAsRepainted() {
|
|
||||||
m_requiresRepaint = false;
|
|
||||||
}
|
|
||||||
bool requiresRepaint() const {
|
|
||||||
return m_requiresRepaint;
|
|
||||||
}
|
|
||||||
void resizePixmaps();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T topDecoPixmap() const;
|
|
||||||
template <typename T>
|
|
||||||
T leftDecoPixmap() const;
|
|
||||||
template <typename T>
|
|
||||||
T bottomDecoPixmap() const;
|
|
||||||
template <typename T>
|
|
||||||
T rightDecoPixmap() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by Deleted::copyToDeleted() to move the PaintRedirector to the Deleted.
|
|
||||||
* The actual redirecting ends as the decoration gets destroyed after the Deleted
|
|
||||||
* is created.
|
|
||||||
**/
|
|
||||||
void reparent(Deleted *d);
|
|
||||||
static PaintRedirector *create(Client *c, KDecoration *deco);
|
|
||||||
|
|
||||||
void addRepaint(const QRegion ®ion);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void ensurePixmapsPainted();
|
|
||||||
protected:
|
|
||||||
PaintRedirector(Client *c, KDecoration *deco);
|
|
||||||
virtual xcb_render_picture_t picture(DecorationPixmap border) const;
|
|
||||||
virtual GLTexture *texture(DecorationPixmap border) const;
|
|
||||||
virtual const QImage *image(DecorationPixmap border) const;
|
|
||||||
virtual void resizePixmaps(const QRect *rects);
|
|
||||||
virtual void resize(DecorationPixmap border, const QSize &size);
|
|
||||||
virtual void preparePaint(const QPixmap &pending);
|
|
||||||
virtual void updatePixmaps(const QRect *rects, const QRegion ®ion);
|
|
||||||
virtual void paint(DecorationPixmap border, const QRect& r, const QRect &b, const QRegion ®);
|
|
||||||
virtual QPaintDevice *scratch() = 0;
|
|
||||||
virtual QPaintDevice *recreateScratch(const QSize &size) = 0;
|
|
||||||
virtual void fillScratch(Qt::GlobalColor color) = 0;
|
|
||||||
virtual void discardScratch() = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void added(QWidget* widget);
|
|
||||||
void removed(QWidget* widget);
|
|
||||||
bool isToolTip(QWidget* widget) const;
|
|
||||||
void timerEvent(QTimerEvent* event);
|
|
||||||
|
|
||||||
void performPendingPaint();
|
|
||||||
void repaintPixmap(DecorationPixmap border, const QRect& r, QRegion reg);
|
|
||||||
QWidget* widget;
|
|
||||||
QRegion pending;
|
|
||||||
QRegion scheduled;
|
|
||||||
bool recursionCheck;
|
|
||||||
QBasicTimer cleanupTimer;
|
|
||||||
|
|
||||||
Client *m_client;
|
|
||||||
KDecoration *m_decoration;
|
|
||||||
bool m_requiresRepaint;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImageBasedPaintRedirector : public PaintRedirector
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
virtual ~ImageBasedPaintRedirector();
|
|
||||||
protected:
|
|
||||||
ImageBasedPaintRedirector(Client *c, KDecoration *deco);
|
|
||||||
virtual QPaintDevice *recreateScratch(const QSize &size);
|
|
||||||
virtual QPaintDevice *scratch();
|
|
||||||
virtual void fillScratch(Qt::GlobalColor color);
|
|
||||||
virtual void discardScratch();
|
|
||||||
const QImage &scratchImage() const;
|
|
||||||
private:
|
|
||||||
QImage m_scratchImage;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OpenGLPaintRedirector : public ImageBasedPaintRedirector
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
OpenGLPaintRedirector(Client *c, KDecoration *deco);
|
|
||||||
virtual ~OpenGLPaintRedirector();
|
|
||||||
|
|
||||||
GLTexture *decorationTexture() const { return m_texture; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void resizePixmaps(const QRect *rects);
|
|
||||||
virtual void updatePixmaps(const QRect *rects, const QRegion ®ion);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLTexture *m_texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RasterXRenderPaintRedirector : public ImageBasedPaintRedirector
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
RasterXRenderPaintRedirector(Client *c, KDecoration *deco);
|
|
||||||
virtual ~RasterXRenderPaintRedirector();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual xcb_render_picture_t picture(DecorationPixmap border) const;
|
|
||||||
virtual void resize(DecorationPixmap border, const QSize &size);
|
|
||||||
virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, const QRegion ®);
|
|
||||||
virtual void preparePaint(const QPixmap &pending);
|
|
||||||
private:
|
|
||||||
QSize m_sizes[PixmapCount];
|
|
||||||
xcb_pixmap_t m_pixmaps[PixmapCount];
|
|
||||||
xcb_gcontext_t m_gc;
|
|
||||||
XRenderPicture* m_pictures[PixmapCount];
|
|
||||||
QImage m_tempImage;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QImagePaintRedirector : public ImageBasedPaintRedirector
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QImagePaintRedirector(Client *c, KDecoration *deco);
|
|
||||||
virtual ~QImagePaintRedirector();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void resize(DecorationPixmap border, const QSize &size) override;
|
|
||||||
virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, const QRegion ®) override;
|
|
||||||
virtual const QImage* image(DecorationPixmap border) const override;
|
|
||||||
private:
|
|
||||||
QImage m_images[PixmapCount];
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
GLTexture *PaintRedirector::bottomDecoPixmap() const
|
|
||||||
{
|
|
||||||
return texture(BottomPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
GLTexture *PaintRedirector::leftDecoPixmap() const
|
|
||||||
{
|
|
||||||
return texture(LeftPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
GLTexture *PaintRedirector::rightDecoPixmap() const
|
|
||||||
{
|
|
||||||
return texture(RightPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
GLTexture *PaintRedirector::topDecoPixmap() const
|
|
||||||
{
|
|
||||||
return texture(TopPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
xcb_render_picture_t PaintRedirector::bottomDecoPixmap() const
|
|
||||||
{
|
|
||||||
return picture(BottomPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
xcb_render_picture_t PaintRedirector::leftDecoPixmap() const
|
|
||||||
{
|
|
||||||
return picture(LeftPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
xcb_render_picture_t PaintRedirector::rightDecoPixmap() const
|
|
||||||
{
|
|
||||||
return picture(RightPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
xcb_render_picture_t PaintRedirector::topDecoPixmap() const
|
|
||||||
{
|
|
||||||
return picture(TopPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
const QImage *PaintRedirector::bottomDecoPixmap() const
|
|
||||||
{
|
|
||||||
return image(BottomPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
const QImage *PaintRedirector::leftDecoPixmap() const
|
|
||||||
{
|
|
||||||
return image(LeftPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
const QImage *PaintRedirector::rightDecoPixmap() const
|
|
||||||
{
|
|
||||||
return image(RightPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline
|
|
||||||
const QImage *PaintRedirector::topDecoPixmap() const
|
|
||||||
{
|
|
||||||
return image(TopPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
const QImage &ImageBasedPaintRedirector::scratchImage() const
|
|
||||||
{
|
|
||||||
return m_scratchImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -72,7 +72,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
|
@ -264,7 +263,6 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
|
||||||
w->resetPaintingEnabled();
|
w->resetPaintingEnabled();
|
||||||
data.paint = region;
|
data.paint = region;
|
||||||
data.paint |= topw->repaints();
|
data.paint |= topw->repaints();
|
||||||
data.paint |= topw->decorationPendingRegion();
|
|
||||||
|
|
||||||
// Reset the repaint_region.
|
// Reset the repaint_region.
|
||||||
// This has to be done here because many effects schedule a repaint for
|
// This has to be done here because many effects schedule a repaint for
|
||||||
|
@ -703,8 +701,7 @@ void Scene::Window::discardShape()
|
||||||
const QRegion &Scene::Window::shape() const
|
const QRegion &Scene::Window::shape() const
|
||||||
{
|
{
|
||||||
if (!shape_valid) {
|
if (!shape_valid) {
|
||||||
Client* c = dynamic_cast< Client* >(toplevel);
|
if (toplevel->shape()) {
|
||||||
if (toplevel->shape() || (c != NULL && !c->mask().isEmpty())) {
|
|
||||||
auto cookie = xcb_shape_get_rectangles_unchecked(connection(), toplevel->frameId(), XCB_SHAPE_SK_BOUNDING);
|
auto cookie = xcb_shape_get_rectangles_unchecked(connection(), toplevel->frameId(), XCB_SHAPE_SK_BOUNDING);
|
||||||
ScopedCPointer<xcb_shape_get_rectangles_reply_t> reply(xcb_shape_get_rectangles_reply(connection(), cookie, nullptr));
|
ScopedCPointer<xcb_shape_get_rectangles_reply_t> reply(xcb_shape_get_rectangles_reply(connection(), cookie, nullptr));
|
||||||
if (!reply.isNull()) {
|
if (!reply.isNull()) {
|
||||||
|
@ -809,7 +806,7 @@ WindowQuadList Scene::Window::buildQuads(bool force) const
|
||||||
Client *client = dynamic_cast<Client*>(toplevel);
|
Client *client = dynamic_cast<Client*>(toplevel);
|
||||||
QRegion contents = clientShape();
|
QRegion contents = clientShape();
|
||||||
QRegion center = toplevel->transparentRect();
|
QRegion center = toplevel->transparentRect();
|
||||||
QRegion decoration = (client && decorationPlugin()->hasAlpha() ?
|
QRegion decoration = (client && true ?
|
||||||
QRegion(client->decorationRect()) : shape()) - center;
|
QRegion(client->decorationRect()) : shape()) - center;
|
||||||
ret = makeQuads(WindowQuadContents, contents);
|
ret = makeQuads(WindowQuadContents, contents);
|
||||||
|
|
||||||
|
|
8
scene.h
8
scene.h
|
@ -30,6 +30,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace Decoration
|
||||||
|
{
|
||||||
|
class DecoratedClientImpl;
|
||||||
|
class Renderer;
|
||||||
|
}
|
||||||
|
|
||||||
class AbstractThumbnailItem;
|
class AbstractThumbnailItem;
|
||||||
class Workspace;
|
class Workspace;
|
||||||
class Deleted;
|
class Deleted;
|
||||||
|
@ -134,6 +140,8 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool isLastFrameRendered() const = 0;
|
virtual bool isLastFrameRendered() const = 0;
|
||||||
|
|
||||||
|
virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *) = 0;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
// a window has been destroyed
|
// a window has been destroyed
|
||||||
void windowDeleted(KWin::Deleted*);
|
void windowDeleted(KWin::Deleted*);
|
||||||
|
|
151
scene_opengl.cpp
151
scene_opengl.cpp
|
@ -44,9 +44,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "lanczosfilter.h"
|
#include "lanczosfilter.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "screens.h"
|
#include "screens.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
|
#include "decorations/decoratedclient.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -569,6 +569,11 @@ Shadow *SceneOpenGL::createShadow(Toplevel *toplevel)
|
||||||
return new SceneOpenGLShadow(toplevel);
|
return new SceneOpenGLShadow(toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Decoration::Renderer *SceneOpenGL::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||||
|
{
|
||||||
|
return new SceneOpenGLDecorationRenderer(impl);
|
||||||
|
}
|
||||||
|
|
||||||
//****************************************
|
//****************************************
|
||||||
// SceneOpenGL2
|
// SceneOpenGL2
|
||||||
//****************************************
|
//****************************************
|
||||||
|
@ -963,39 +968,23 @@ void SceneOpenGL::Window::endRenderWindow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenGLPaintRedirector *SceneOpenGL::Window::paintRedirector() const
|
|
||||||
{
|
|
||||||
if (toplevel->isClient()) {
|
|
||||||
Client *client = static_cast<Client *>(toplevel);
|
|
||||||
if (client->noBorder())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return static_cast<OpenGLPaintRedirector *>(client->decorationPaintRedirector());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toplevel->isDeleted()) {
|
|
||||||
Deleted *deleted = static_cast<Deleted *>(toplevel);
|
|
||||||
if (deleted->noBorder())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return static_cast<OpenGLPaintRedirector *>(deleted->decorationPaintRedirector());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture *SceneOpenGL::Window::getDecorationTexture() const
|
GLTexture *SceneOpenGL::Window::getDecorationTexture() const
|
||||||
{
|
{
|
||||||
OpenGLPaintRedirector *redirector = paintRedirector();
|
// TODO: deleted
|
||||||
if (!redirector)
|
if (toplevel->isClient()) {
|
||||||
return 0;
|
Client *client = static_cast<Client *>(toplevel);
|
||||||
|
if (client->noBorder()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
redirector->ensurePixmapsPainted();
|
if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) {
|
||||||
GLTexture *texture = redirector->decorationTexture();
|
if (SceneOpenGLDecorationRenderer *renderer = static_cast<SceneOpenGLDecorationRenderer*>(impl->renderer())) {
|
||||||
redirector->markAsRepainted();
|
renderer->render();
|
||||||
|
return renderer->texture();
|
||||||
return texture;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneOpenGL::Window::paintDecorations(const WindowPaintData &data, const QRegion ®ion)
|
void SceneOpenGL::Window::paintDecorations(const WindowPaintData &data, const QRegion ®ion)
|
||||||
|
@ -2009,4 +1998,104 @@ char SwapProfiler::end()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SceneOpenGLDecorationRenderer::SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||||
|
: Renderer(client)
|
||||||
|
, m_texture()
|
||||||
|
{
|
||||||
|
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (Client::*)(const QRect&)>(&Client::addRepaint));
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneOpenGLDecorationRenderer::~SceneOpenGLDecorationRenderer() = default;
|
||||||
|
|
||||||
|
// Rotates the given source rect 90° counter-clockwise,
|
||||||
|
// and flips it vertically
|
||||||
|
static QImage rotate(const QImage &srcImage, const QRect &srcRect)
|
||||||
|
{
|
||||||
|
QImage image(srcRect.height(), srcRect.width(), srcImage.format());
|
||||||
|
|
||||||
|
const uint32_t *src = reinterpret_cast<const uint32_t *>(srcImage.bits());
|
||||||
|
uint32_t *dst = reinterpret_cast<uint32_t *>(image.bits());
|
||||||
|
|
||||||
|
for (int x = 0; x < image.width(); x++) {
|
||||||
|
const uint32_t *s = src + (srcRect.y() + x) * srcImage.width() + srcRect.x();
|
||||||
|
uint32_t *d = dst + x;
|
||||||
|
|
||||||
|
for (int y = 0; y < image.height(); y++) {
|
||||||
|
*d = s[y];
|
||||||
|
d += image.width();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneOpenGLDecorationRenderer::render()
|
||||||
|
{
|
||||||
|
const QRegion scheduled = getScheduled();
|
||||||
|
if (scheduled.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (areImageSizesDirty()) {
|
||||||
|
resizeTexture();
|
||||||
|
resetImageSizesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect left, top, right, bottom;
|
||||||
|
client()->client()->layoutDecorationRects(left, top, right, bottom, Client::DecorationRelative);
|
||||||
|
|
||||||
|
const QRect geometry = scheduled.boundingRect();
|
||||||
|
|
||||||
|
auto renderPart = [this](const QRect &geo, const QRect &partRect, const QPoint &offset, bool rotated = false) {
|
||||||
|
if (geo.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QImage image = renderToImage(geo);
|
||||||
|
if (rotated) {
|
||||||
|
// TODO: get this done directly when rendering to the image
|
||||||
|
image = rotate(image, QRect(geo.topLeft() - partRect.topLeft(), geo.size()));
|
||||||
|
}
|
||||||
|
m_texture->update(image, geo.topLeft() - partRect.topLeft() + offset);
|
||||||
|
};
|
||||||
|
renderPart(left.intersected(geometry), left, QPoint(0, top.height() + bottom.height() + 2), true);
|
||||||
|
renderPart(top.intersected(geometry), top, QPoint(0, 0));
|
||||||
|
renderPart(right.intersected(geometry), right, QPoint(0, top.height() + bottom.height() + left.width() + 3), true);
|
||||||
|
renderPart(bottom.intersected(geometry), bottom, QPoint(0, top.height() + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int align(int value, int align)
|
||||||
|
{
|
||||||
|
return (value + align - 1) & ~(align - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneOpenGLDecorationRenderer::resizeTexture()
|
||||||
|
{
|
||||||
|
QRect left, top, right, bottom;
|
||||||
|
client()->client()->layoutDecorationRects(left, top, right, bottom, Client::DecorationRelative);
|
||||||
|
QSize size;
|
||||||
|
|
||||||
|
size.rwidth() = qMax(qMax(top.width(), bottom.width()),
|
||||||
|
qMax(left.height(), right.height()));
|
||||||
|
size.rheight() = top.height() + bottom.height() +
|
||||||
|
left.width() + right.width() + 3;
|
||||||
|
|
||||||
|
size.rwidth() = align(size.width(), 128);
|
||||||
|
|
||||||
|
if (!GLTexture::NPOTTextureSupported()) {
|
||||||
|
size.rwidth() = nearestPowerOfTwo(size.width());
|
||||||
|
size.rheight() = nearestPowerOfTwo(size.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_texture && m_texture->size() == size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!size.isEmpty()) {
|
||||||
|
m_texture.reset(new GLTexture(size.width(), size.height()));
|
||||||
|
m_texture->setYInverted(true);
|
||||||
|
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||||
|
m_texture->clear();
|
||||||
|
} else {
|
||||||
|
m_texture.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -28,12 +28,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "kwinglutils.h"
|
#include "kwinglutils.h"
|
||||||
#include "kwingltexture_p.h"
|
#include "kwingltexture_p.h"
|
||||||
|
|
||||||
|
#include "decorations/decorationrenderer.h"
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
class ColorCorrection;
|
class ColorCorrection;
|
||||||
class LanczosFilter;
|
class LanczosFilter;
|
||||||
class OpenGLBackend;
|
class OpenGLBackend;
|
||||||
class OpenGLPaintRedirector;
|
|
||||||
|
|
||||||
class SceneOpenGL
|
class SceneOpenGL
|
||||||
: public Scene
|
: public Scene
|
||||||
|
@ -58,6 +59,7 @@ public:
|
||||||
virtual bool makeOpenGLContextCurrent() override;
|
virtual bool makeOpenGLContextCurrent() override;
|
||||||
virtual void doneOpenGLContextCurrent() override;
|
virtual void doneOpenGLContextCurrent() override;
|
||||||
virtual bool isLastFrameRendered() const override;
|
virtual bool isLastFrameRendered() const override;
|
||||||
|
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||||
|
|
||||||
void idle();
|
void idle();
|
||||||
|
|
||||||
|
@ -238,9 +240,6 @@ protected:
|
||||||
protected:
|
protected:
|
||||||
SceneOpenGL *m_scene;
|
SceneOpenGL *m_scene;
|
||||||
bool m_hardwareClipping;
|
bool m_hardwareClipping;
|
||||||
|
|
||||||
private:
|
|
||||||
OpenGLPaintRedirector *paintRedirector() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneOpenGL2Window : public SceneOpenGL::Window
|
class SceneOpenGL2Window : public SceneOpenGL::Window
|
||||||
|
@ -617,6 +616,31 @@ private:
|
||||||
QElapsedTimer m_renderTimer;
|
QElapsedTimer m_renderTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SceneOpenGLDecorationRenderer : public Decoration::Renderer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class DecorationPart : int {
|
||||||
|
Left,
|
||||||
|
Top,
|
||||||
|
Right,
|
||||||
|
Bottom,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||||
|
virtual ~SceneOpenGLDecorationRenderer();
|
||||||
|
|
||||||
|
void render() override;
|
||||||
|
|
||||||
|
GLTexture *texture() {
|
||||||
|
return m_texture.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizeTexture();
|
||||||
|
QScopedPointer<GLTexture> m_texture;
|
||||||
|
};
|
||||||
|
|
||||||
inline bool SceneOpenGL::hasPendingFlush() const
|
inline bool SceneOpenGL::hasPendingFlush() const
|
||||||
{
|
{
|
||||||
return m_backend->hasPendingFlush();
|
return m_backend->hasPendingFlush();
|
||||||
|
|
|
@ -24,16 +24,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "toplevel.h"
|
#include "toplevel.h"
|
||||||
#if HAVE_WAYLAND
|
#if HAVE_WAYLAND
|
||||||
#include "wayland_backend.h"
|
#include "wayland_backend.h"
|
||||||
#endif
|
#endif
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
|
#include "decorations/decoratedclient.h"
|
||||||
// Qt
|
// Qt
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <KDecoration2/Decoration>
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
@ -442,33 +443,31 @@ void SceneQPainter::Window::renderWindowDecorations(QPainter *painter)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool noBorder = true;
|
bool noBorder = true;
|
||||||
PaintRedirector *redirector = NULL;
|
SceneQPainterDecorationRenderer *renderer = nullptr;
|
||||||
QRect dtr, dlr, drr, dbr;
|
QRect dtr, dlr, drr, dbr;
|
||||||
if (client && !client->noBorder()) {
|
if (client && !client->noBorder()) {
|
||||||
redirector = client->decorationPaintRedirector();
|
if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) {
|
||||||
|
if (SceneQPainterDecorationRenderer *r = static_cast<SceneQPainterDecorationRenderer *>(impl->renderer())) {
|
||||||
|
renderer = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative);
|
client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative);
|
||||||
noBorder = false;
|
noBorder = false;
|
||||||
} else if (deleted && !deleted->noBorder()) {
|
} else if (deleted && !deleted->noBorder()) {
|
||||||
noBorder = false;
|
noBorder = false;
|
||||||
redirector = deleted->decorationPaintRedirector();
|
// TODO: renderer
|
||||||
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||||
}
|
}
|
||||||
if (noBorder || !redirector) {
|
if (noBorder || !renderer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
redirector->ensurePixmapsPainted();
|
renderer->render();
|
||||||
const QImage *left = redirector->leftDecoPixmap<const QImage *>();
|
|
||||||
const QImage *top = redirector->topDecoPixmap<const QImage *>();
|
|
||||||
const QImage *right = redirector->rightDecoPixmap<const QImage *>();
|
|
||||||
const QImage *bottom = redirector->bottomDecoPixmap<const QImage *>();
|
|
||||||
|
|
||||||
painter->drawImage(dtr, *top);
|
painter->drawImage(dtr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Top));
|
||||||
painter->drawImage(dlr, *left);
|
painter->drawImage(dlr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Left));
|
||||||
painter->drawImage(drr, *right);
|
painter->drawImage(drr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Right));
|
||||||
painter->drawImage(dbr, *bottom);
|
painter->drawImage(dbr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Bottom));
|
||||||
|
|
||||||
redirector->markAsRepainted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowPixmap *SceneQPainter::Window::createWindowPixmap()
|
WindowPixmap *SceneQPainter::Window::createWindowPixmap()
|
||||||
|
@ -476,6 +475,11 @@ WindowPixmap *SceneQPainter::Window::createWindowPixmap()
|
||||||
return new QPainterWindowPixmap(this);
|
return new QPainterWindowPixmap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Decoration::Renderer *SceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||||
|
{
|
||||||
|
return new SceneQPainterDecorationRenderer(impl);
|
||||||
|
}
|
||||||
|
|
||||||
//****************************************
|
//****************************************
|
||||||
// QPainterWindowPixmap
|
// QPainterWindowPixmap
|
||||||
//****************************************
|
//****************************************
|
||||||
|
@ -615,4 +619,77 @@ bool SceneQPainterShadow::prepareBackend()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//****************************************
|
||||||
|
// QPainterDecorationRenderer
|
||||||
|
//****************************************
|
||||||
|
SceneQPainterDecorationRenderer::SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||||
|
: Renderer(client)
|
||||||
|
{
|
||||||
|
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (Client::*)(const QRect&)>(&Client::addRepaint));
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneQPainterDecorationRenderer::~SceneQPainterDecorationRenderer() = default;
|
||||||
|
|
||||||
|
QImage SceneQPainterDecorationRenderer::image(SceneQPainterDecorationRenderer::DecorationPart part) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(part != DecorationPart::Count);
|
||||||
|
return m_images[int(part)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneQPainterDecorationRenderer::render()
|
||||||
|
{
|
||||||
|
const QRegion scheduled = getScheduled();
|
||||||
|
if (scheduled.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (areImageSizesDirty()) {
|
||||||
|
resizeImages();
|
||||||
|
resetImageSizesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QRect top(QPoint(0, 0), m_images[int(DecorationPart::Top)].size());
|
||||||
|
const QRect left(QPoint(0, top.height()), m_images[int(DecorationPart::Left)].size());
|
||||||
|
const QRect right(QPoint(top.width() - m_images[int(DecorationPart::Right)].size().width(), top.height()), m_images[int(DecorationPart::Right)].size());
|
||||||
|
const QRect bottom(QPoint(0, left.y() + left.height()), m_images[int(DecorationPart::Bottom)].size());
|
||||||
|
|
||||||
|
const QRect geometry = scheduled.boundingRect();
|
||||||
|
auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) {
|
||||||
|
if (rect.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QPainter painter(&m_images[index]);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
painter.setWindow(partRect);
|
||||||
|
painter.setClipRect(rect);
|
||||||
|
painter.save();
|
||||||
|
// clear existing part
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
painter.fillRect(rect, Qt::red);
|
||||||
|
painter.restore();
|
||||||
|
client()->decoration()->paint(&painter);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderPart(left.intersected(geometry), left, int(DecorationPart::Left));
|
||||||
|
renderPart(top.intersected(geometry), top, int(DecorationPart::Top));
|
||||||
|
renderPart(right.intersected(geometry), right, int(DecorationPart::Right));
|
||||||
|
renderPart(bottom.intersected(geometry), bottom, int(DecorationPart::Bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneQPainterDecorationRenderer::resizeImages()
|
||||||
|
{
|
||||||
|
QRect left, top, right, bottom;
|
||||||
|
client()->client()->layoutDecorationRects(left, top, right, bottom, Client::DecorationRelative);
|
||||||
|
|
||||||
|
auto checkAndCreate = [this](int index, const QSize &size) {
|
||||||
|
if (m_images[index].size() != size) {
|
||||||
|
m_images[index] = QImage(size, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
m_images[index].fill(Qt::transparent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAndCreate(int(DecorationPart::Left), left.size());
|
||||||
|
checkAndCreate(int(DecorationPart::Right), right.size());
|
||||||
|
checkAndCreate(int(DecorationPart::Top), top.size());
|
||||||
|
checkAndCreate(int(DecorationPart::Bottom), bottom.size());
|
||||||
|
}
|
||||||
|
|
||||||
} // KWin
|
} // KWin
|
||||||
|
|
|
@ -23,6 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "shadow.h"
|
#include "shadow.h"
|
||||||
|
|
||||||
|
#include "decorations/decorationrenderer.h"
|
||||||
|
|
||||||
namespace KWin {
|
namespace KWin {
|
||||||
|
|
||||||
namespace Xcb {
|
namespace Xcb {
|
||||||
|
@ -143,6 +145,7 @@ public:
|
||||||
virtual bool initFailed() const override;
|
virtual bool initFailed() const override;
|
||||||
virtual EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
virtual EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
||||||
virtual Shadow *createShadow(Toplevel *toplevel) override;
|
virtual Shadow *createShadow(Toplevel *toplevel) override;
|
||||||
|
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||||
|
|
||||||
QPainter *painter();
|
QPainter *painter();
|
||||||
|
|
||||||
|
@ -227,6 +230,29 @@ protected:
|
||||||
virtual bool prepareBackend() override;
|
virtual bool prepareBackend() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SceneQPainterDecorationRenderer : public Decoration::Renderer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class DecorationPart : int {
|
||||||
|
Left,
|
||||||
|
Top,
|
||||||
|
Right,
|
||||||
|
Bottom,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
explicit SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||||
|
virtual ~SceneQPainterDecorationRenderer();
|
||||||
|
|
||||||
|
void render() override;
|
||||||
|
|
||||||
|
QImage image(DecorationPart part) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizeImages();
|
||||||
|
QImage m_images[int(DecorationPart::Count)];
|
||||||
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
bool SceneQPainter::usesOverlayWindow() const
|
bool SceneQPainter::usesOverlayWindow() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,18 +26,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "toplevel.h"
|
#include "toplevel.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "composite.h"
|
#include "composite.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
#include "paintredirector.h"
|
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
#include "kwinxrenderutils.h"
|
#include "kwinxrenderutils.h"
|
||||||
#if HAVE_WAYLAND
|
#if HAVE_WAYLAND
|
||||||
#include "wayland_backend.h"
|
#include "wayland_backend.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "decorations/decoratedclient.h"
|
||||||
|
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
|
|
||||||
|
@ -466,6 +465,11 @@ Shadow *SceneXrender::createShadow(Toplevel *toplevel)
|
||||||
return new SceneXRenderShadow(toplevel);
|
return new SceneXRenderShadow(toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Decoration::Renderer *SceneXrender::createDecorationRenderer(Decoration::DecoratedClientImpl* client)
|
||||||
|
{
|
||||||
|
return new SceneXRenderDecorationRenderer(client);
|
||||||
|
}
|
||||||
|
|
||||||
//****************************************
|
//****************************************
|
||||||
// SceneXrender::Window
|
// SceneXrender::Window
|
||||||
//****************************************
|
//****************************************
|
||||||
|
@ -611,7 +615,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
||||||
Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
|
Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
|
||||||
const QRect decorationRect = toplevel->decorationRect();
|
const QRect decorationRect = toplevel->decorationRect();
|
||||||
if (((client && !client->noBorder()) || (deleted && !deleted->noBorder())) &&
|
if (((client && !client->noBorder()) || (deleted && !deleted->noBorder())) &&
|
||||||
decorationPlugin()->hasAlpha()) {
|
true) {
|
||||||
// decorated client
|
// decorated client
|
||||||
transformed_shape = decorationRect;
|
transformed_shape = decorationRect;
|
||||||
if (toplevel->shape()) {
|
if (toplevel->shape()) {
|
||||||
|
@ -717,32 +721,30 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
|
||||||
xcb_render_picture_t top = XCB_RENDER_PICTURE_NONE;
|
xcb_render_picture_t top = XCB_RENDER_PICTURE_NONE;
|
||||||
xcb_render_picture_t right = XCB_RENDER_PICTURE_NONE;
|
xcb_render_picture_t right = XCB_RENDER_PICTURE_NONE;
|
||||||
xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE;
|
xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE;
|
||||||
PaintRedirector *redirector = NULL;
|
|
||||||
QRect dtr, dlr, drr, dbr;
|
QRect dtr, dlr, drr, dbr;
|
||||||
if (client || deleted) {
|
SceneXRenderDecorationRenderer *renderer = nullptr;
|
||||||
|
// TODO: deleted
|
||||||
|
if (client) {
|
||||||
if (client && !client->noBorder()) {
|
if (client && !client->noBorder()) {
|
||||||
redirector = client->decorationPaintRedirector();
|
if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) {
|
||||||
|
renderer = static_cast<SceneXRenderDecorationRenderer*>(impl->renderer());
|
||||||
|
}
|
||||||
noBorder = client->noBorder();
|
noBorder = client->noBorder();
|
||||||
client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative);
|
client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative);
|
||||||
}
|
}
|
||||||
if (deleted && !deleted->noBorder()) {
|
}
|
||||||
noBorder = deleted->noBorder();
|
if (renderer) {
|
||||||
redirector = deleted->decorationPaintRedirector();
|
renderer->render();
|
||||||
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
left = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Left);
|
||||||
}
|
top = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Top);
|
||||||
if (redirector) {
|
right = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Right);
|
||||||
redirector->ensurePixmapsPainted();
|
bottom = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Bottom);
|
||||||
left = redirector->leftDecoPixmap<xcb_render_picture_t>();
|
}
|
||||||
top = redirector->topDecoPixmap<xcb_render_picture_t>();
|
if (!noBorder) {
|
||||||
right = redirector->rightDecoPixmap<xcb_render_picture_t>();
|
MAP_RECT_TO_TARGET(dtr);
|
||||||
bottom = redirector->bottomDecoPixmap<xcb_render_picture_t>();
|
MAP_RECT_TO_TARGET(dlr);
|
||||||
}
|
MAP_RECT_TO_TARGET(drr);
|
||||||
if (!noBorder) {
|
MAP_RECT_TO_TARGET(dbr);
|
||||||
MAP_RECT_TO_TARGET(dtr);
|
|
||||||
MAP_RECT_TO_TARGET(dlr);
|
|
||||||
MAP_RECT_TO_TARGET(drr);
|
|
||||||
MAP_RECT_TO_TARGET(dbr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//END deco preparations
|
//END deco preparations
|
||||||
|
|
||||||
|
@ -860,9 +862,6 @@ xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, m_xrenderShadow->pic
|
||||||
renderDeco(right, drr);
|
renderDeco(right, drr);
|
||||||
renderDeco(bottom, dbr);
|
renderDeco(bottom, dbr);
|
||||||
}
|
}
|
||||||
if (redirector) {
|
|
||||||
redirector->markAsRepainted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.brightness() != 1.0) {
|
if (data.brightness() != 1.0) {
|
||||||
|
@ -1307,6 +1306,115 @@ xcb_render_picture_t SceneXRenderShadow::picture(Shadow::ShadowElements element)
|
||||||
return *m_pictures[element];
|
return *m_pictures[element];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SceneXRenderDecorationRenderer::SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||||
|
: Renderer(client)
|
||||||
|
, m_gc(XCB_NONE)
|
||||||
|
{
|
||||||
|
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (Client::*)(const QRect&)>(&Client::addRepaint));
|
||||||
|
for (int i = 0; i < int(DecorationPart::Count); ++i) {
|
||||||
|
m_pixmaps[i] = XCB_PIXMAP_NONE;
|
||||||
|
m_pictures[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneXRenderDecorationRenderer::~SceneXRenderDecorationRenderer()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < int(DecorationPart::Count); ++i) {
|
||||||
|
if (m_pixmaps[i] != XCB_PIXMAP_NONE) {
|
||||||
|
xcb_free_pixmap(connection(), m_pixmaps[i]);
|
||||||
|
}
|
||||||
|
delete m_pictures[i];
|
||||||
|
}
|
||||||
|
if (m_gc != 0) {
|
||||||
|
xcb_free_gc(connection(), m_gc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneXRenderDecorationRenderer::render()
|
||||||
|
{
|
||||||
|
const QRegion scheduled = getScheduled();
|
||||||
|
if (scheduled.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (areImageSizesDirty()) {
|
||||||
|
resizePixmaps();
|
||||||
|
resetImageSizesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QRect top(QPoint(0, 0), m_sizes[int(DecorationPart::Top)]);
|
||||||
|
const QRect left(QPoint(0, top.height()), m_sizes[int(DecorationPart::Left)]);
|
||||||
|
const QRect right(QPoint(top.width() - m_sizes[int(DecorationPart::Right)].width(), top.height()), m_sizes[int(DecorationPart::Right)]);
|
||||||
|
const QRect bottom(QPoint(0, left.y() + left.height()), m_sizes[int(DecorationPart::Bottom)]);
|
||||||
|
|
||||||
|
xcb_connection_t *c = connection();
|
||||||
|
if (m_gc == 0) {
|
||||||
|
m_gc = xcb_generate_id(connection());
|
||||||
|
xcb_create_gc(c, m_gc, m_pixmaps[int(DecorationPart::Top)], 0, nullptr);
|
||||||
|
}
|
||||||
|
auto renderPart = [this, c](const QRect &geo, const QPoint &offset, int index) {
|
||||||
|
if (geo.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QImage image = renderToImage(geo);
|
||||||
|
xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, m_pixmaps[index], m_gc,
|
||||||
|
image.width(), image.height(), geo.x() - offset.x(), geo.y() - offset.y(), 0, 32,
|
||||||
|
image.byteCount(), image.constBits());
|
||||||
|
};
|
||||||
|
const QRect geometry = scheduled.boundingRect();
|
||||||
|
renderPart(left.intersected(geometry), left.topLeft(), int(DecorationPart::Left));
|
||||||
|
renderPart(top.intersected(geometry), top.topLeft(), int(DecorationPart::Top));
|
||||||
|
renderPart(right.intersected(geometry), right.topLeft(), int(DecorationPart::Right));
|
||||||
|
renderPart(bottom.intersected(geometry), bottom.topLeft(), int(DecorationPart::Bottom));
|
||||||
|
xcb_flush(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneXRenderDecorationRenderer::resizePixmaps()
|
||||||
|
{
|
||||||
|
QRect left, top, right, bottom;
|
||||||
|
client()->client()->layoutDecorationRects(left, top, right, bottom, Client::DecorationRelative);
|
||||||
|
|
||||||
|
xcb_connection_t *c = connection();
|
||||||
|
auto checkAndCreate = [this, c](int border, const QRect &rect) {
|
||||||
|
const QSize size = rect.size();
|
||||||
|
if (m_sizes[border] != size) {
|
||||||
|
m_sizes[border] = size;
|
||||||
|
if (m_pixmaps[border] != XCB_PIXMAP_NONE) {
|
||||||
|
xcb_free_pixmap(c, m_pixmaps[border]);
|
||||||
|
}
|
||||||
|
delete m_pictures[border];
|
||||||
|
if (!size.isEmpty()) {
|
||||||
|
m_pixmaps[border] = xcb_generate_id(connection());
|
||||||
|
xcb_create_pixmap(connection(), 32, m_pixmaps[border], rootWindow(), size.width(), size.height());
|
||||||
|
m_pictures[border] = new XRenderPicture(m_pixmaps[border], 32);
|
||||||
|
} else {
|
||||||
|
m_pixmaps[border] = XCB_PIXMAP_NONE;
|
||||||
|
m_pictures[border] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_pictures[border]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// fill transparent
|
||||||
|
xcb_rectangle_t r = {0, 0, uint16_t(size.width()), uint16_t(size.height())};
|
||||||
|
xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, *m_pictures[border], preMultiply(Qt::transparent), 1, &r);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkAndCreate(int(DecorationPart::Left), left);
|
||||||
|
checkAndCreate(int(DecorationPart::Top), top);
|
||||||
|
checkAndCreate(int(DecorationPart::Right), right);
|
||||||
|
checkAndCreate(int(DecorationPart::Bottom), bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_render_picture_t SceneXRenderDecorationRenderer::picture(SceneXRenderDecorationRenderer::DecorationPart part) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(part != DecorationPart::Count);
|
||||||
|
XRenderPicture *picture = m_pictures[int(part)];
|
||||||
|
if (!picture) {
|
||||||
|
return XCB_RENDER_PICTURE_NONE;
|
||||||
|
}
|
||||||
|
return *picture;
|
||||||
|
}
|
||||||
|
|
||||||
#undef DOUBLE_TO_FIXED
|
#undef DOUBLE_TO_FIXED
|
||||||
#undef FIXED_TO_DOUBLE
|
#undef FIXED_TO_DOUBLE
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "shadow.h"
|
#include "shadow.h"
|
||||||
|
#include "decorations/decorationrenderer.h"
|
||||||
|
|
||||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||||
|
|
||||||
|
@ -196,6 +197,7 @@ public:
|
||||||
virtual bool isLastFrameRendered() const {
|
virtual bool isLastFrameRendered() const {
|
||||||
return m_backend->isLastFrameRendered();
|
return m_backend->isLastFrameRendered();
|
||||||
}
|
}
|
||||||
|
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||||
|
|
||||||
static SceneXrender *createScene();
|
static SceneXrender *createScene();
|
||||||
protected:
|
protected:
|
||||||
|
@ -337,6 +339,32 @@ private:
|
||||||
XRenderPicture* m_pictures[ShadowElementsCount];
|
XRenderPicture* m_pictures[ShadowElementsCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SceneXRenderDecorationRenderer : public Decoration::Renderer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class DecorationPart : int {
|
||||||
|
Left,
|
||||||
|
Top,
|
||||||
|
Right,
|
||||||
|
Bottom,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
explicit SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||||
|
virtual ~SceneXRenderDecorationRenderer();
|
||||||
|
|
||||||
|
void render() override;
|
||||||
|
|
||||||
|
xcb_render_picture_t picture(DecorationPart part) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizePixmaps();
|
||||||
|
QSize m_sizes[int(DecorationPart::Count)];
|
||||||
|
xcb_pixmap_t m_pixmaps[int(DecorationPart::Count)];
|
||||||
|
xcb_gcontext_t m_gc;
|
||||||
|
XRenderPicture* m_pictures[int(DecorationPart::Count)];
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "tabgroup.h"
|
#include "tabgroup.h"
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
|
|
||||||
|
@ -63,7 +62,7 @@ bool TabGroup::add(Client* c, Client *other, bool after, bool becomeVisible)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!c->tabGroup());
|
Q_ASSERT(!c->tabGroup());
|
||||||
|
|
||||||
if (!decorationPlugin()->supportsTabbing() || contains(c) || !contains(other))
|
if (contains(c) || !contains(other))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Tabbed windows MUST have a decoration
|
// Tabbed windows MUST have a decoration
|
||||||
|
|
|
@ -205,7 +205,6 @@ public:
|
||||||
virtual QRect visibleRect() const; // the area the window occupies on the screen
|
virtual QRect visibleRect() const; // the area the window occupies on the screen
|
||||||
virtual QRect decorationRect() const; // rect including the decoration shadows
|
virtual QRect decorationRect() const; // rect including the decoration shadows
|
||||||
virtual QRect transparentRect() const = 0;
|
virtual QRect transparentRect() const = 0;
|
||||||
virtual QRegion decorationPendingRegion() const; // decoration region that needs to be repainted
|
|
||||||
virtual bool isClient() const;
|
virtual bool isClient() const;
|
||||||
virtual bool isDeleted() const;
|
virtual bool isDeleted() const;
|
||||||
|
|
||||||
|
@ -511,11 +510,6 @@ inline QRect Toplevel::rect() const
|
||||||
return QRect(0, 0, width(), height());
|
return QRect(0, 0, width(), height());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QRegion Toplevel::decorationPendingRegion() const
|
|
||||||
{
|
|
||||||
return QRegion();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Toplevel::readyForPainting() const
|
inline bool Toplevel::readyForPainting() const
|
||||||
{
|
{
|
||||||
return ready_for_painting;
|
return ready_for_painting;
|
||||||
|
|
|
@ -34,7 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "useractions.h"
|
#include "useractions.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
|
@ -337,7 +336,7 @@ void UserActionsMenu::init()
|
||||||
m_menu->addSeparator();
|
m_menu->addSeparator();
|
||||||
|
|
||||||
// Actions for window tabbing
|
// Actions for window tabbing
|
||||||
if (decorationPlugin()->supportsTabbing()) {
|
if (false) {
|
||||||
m_removeFromTabGroup = m_menu->addAction(i18n("&Untab"));
|
m_removeFromTabGroup = m_menu->addAction(i18n("&Untab"));
|
||||||
setShortcut(m_removeFromTabGroup, QStringLiteral("Untab"));
|
setShortcut(m_removeFromTabGroup, QStringLiteral("Untab"));
|
||||||
m_removeFromTabGroup->setData(Options::RemoveTabFromGroupOp);
|
m_removeFromTabGroup->setData(Options::RemoveTabFromGroupOp);
|
||||||
|
@ -409,7 +408,7 @@ void UserActionsMenu::menuAboutToShow()
|
||||||
m_minimizeOperation->setEnabled(m_client.data()->isMinimizable());
|
m_minimizeOperation->setEnabled(m_client.data()->isMinimizable());
|
||||||
m_closeOperation->setEnabled(m_client.data()->isCloseable());
|
m_closeOperation->setEnabled(m_client.data()->isCloseable());
|
||||||
|
|
||||||
if (decorationPlugin()->supportsTabbing()) {
|
if (false) {
|
||||||
initTabbingPopups();
|
initTabbingPopups();
|
||||||
m_addTabsMenu->setPalette(m_client.data()->palette());
|
m_addTabsMenu->setPalette(m_client.data()->palette());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -36,7 +36,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "composite.h"
|
#include "composite.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "dbusinterface.h"
|
#include "dbusinterface.h"
|
||||||
#include "decorations.h"
|
|
||||||
#include "deleted.h"
|
#include "deleted.h"
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "focuschain.h"
|
#include "focuschain.h"
|
||||||
|
@ -63,6 +62,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#endif
|
#endif
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "decorations/decorationbridge.h"
|
||||||
// KDE
|
// KDE
|
||||||
#include <KConfig>
|
#include <KConfig>
|
||||||
#include <KConfigGroup>
|
#include <KConfigGroup>
|
||||||
|
@ -171,7 +171,6 @@ Workspace::Workspace(bool restore)
|
||||||
|
|
||||||
options->loadConfig();
|
options->loadConfig();
|
||||||
options->loadCompositingConfig(false);
|
options->loadCompositingConfig(false);
|
||||||
DecorationPlugin::create(this);
|
|
||||||
ColorMapper *colormaps = new ColorMapper(this);
|
ColorMapper *colormaps = new ColorMapper(this);
|
||||||
connect(this, SIGNAL(clientActivated(KWin::Client*)), colormaps, SLOT(update()));
|
connect(this, SIGNAL(clientActivated(KWin::Client*)), colormaps, SLOT(update()));
|
||||||
|
|
||||||
|
@ -213,7 +212,9 @@ Workspace::Workspace(bool restore)
|
||||||
XRenderUtils::init(connection(), rootWindow());
|
XRenderUtils::init(connection(), rootWindow());
|
||||||
m_compositor = Compositor::create(this);
|
m_compositor = Compositor::create(this);
|
||||||
connect(this, SIGNAL(currentDesktopChanged(int,KWin::Client*)), m_compositor, SLOT(addRepaintFull()));
|
connect(this, SIGNAL(currentDesktopChanged(int,KWin::Client*)), m_compositor, SLOT(addRepaintFull()));
|
||||||
connect(m_compositor, &Compositor::compositingToggled, decorationPlugin(), &DecorationPlugin::compositingToggled);
|
|
||||||
|
new Decoration::DecorationBridge(this);
|
||||||
|
Decoration::DecorationBridge::self()->init();
|
||||||
|
|
||||||
new DBusInterface(this);
|
new DBusInterface(this);
|
||||||
|
|
||||||
|
@ -784,18 +785,6 @@ void Workspace::slotReconfigure()
|
||||||
m_userActionsMenu->discard();
|
m_userActionsMenu->discard();
|
||||||
updateToolWindows(true);
|
updateToolWindows(true);
|
||||||
|
|
||||||
DecorationPlugin *deco = DecorationPlugin::self();
|
|
||||||
if (!deco->isDisabled() && deco->reset()) {
|
|
||||||
deco->recreateDecorations();
|
|
||||||
deco->destroyPreviousPlugin();
|
|
||||||
connect(deco->factory(), &KDecorationFactory::recreateDecorations, deco, &DecorationPlugin::recreateDecorations);
|
|
||||||
} else {
|
|
||||||
foreach (Client * c, clients) {
|
|
||||||
c->checkBorderSizes(true);
|
|
||||||
c->triggerDecorationRepaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RuleBook::self()->load();
|
RuleBook::self()->load();
|
||||||
for (ClientList::Iterator it = clients.begin();
|
for (ClientList::Iterator it = clients.begin();
|
||||||
it != clients.end();
|
it != clients.end();
|
||||||
|
@ -816,12 +805,6 @@ void Workspace::slotReconfigure()
|
||||||
(*it)->checkNoBorder();
|
(*it)->checkNoBorder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deco->isDisabled()) {
|
|
||||||
rootInfo()->setSupported(NET::WM2FrameOverlap, deco->factory()->supports(AbilityExtendIntoClientArea));
|
|
||||||
} else {
|
|
||||||
rootInfo()->setSupported(NET::WM2FrameOverlap, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1412,9 +1395,6 @@ QString Workspace::supportInformation() const
|
||||||
.arg(geo.width())
|
.arg(geo.width())
|
||||||
.arg(geo.height()));
|
.arg(geo.height()));
|
||||||
}
|
}
|
||||||
support.append(QStringLiteral("\nDecoration\n"));
|
|
||||||
support.append(QStringLiteral( "==========\n"));
|
|
||||||
support.append(decorationPlugin()->supportInformation());
|
|
||||||
support.append(QStringLiteral("\nCompositing\n"));
|
support.append(QStringLiteral("\nCompositing\n"));
|
||||||
support.append(QStringLiteral( "===========\n"));
|
support.append(QStringLiteral( "===========\n"));
|
||||||
if (effects) {
|
if (effects) {
|
||||||
|
|
Loading…
Reference in a new issue