Split Outline in a composited and non-composited part

The non-composited part handles the showWithX case with the four small
windows. The composited part shows a translucent QWidget with the
FrameSvg as done by the selection effect frame.

Outline connects to the Compositor toggled signal to switch the mode if
compositing gets suspended/resumed. This works fine also in the case that
the switch happens while the outline is shown. To support this Outline
is now a QObject and created with Workspace as a parent.

Given that the Outline handles both cases by itself, the outline effect
is no longer needed and is dropped together with all the hooks into the
effect system.
This commit is contained in:
Martin Gräßlin 2013-04-24 09:50:04 +02:00
parent 83e3f18014
commit 1a3bc3f60c
11 changed files with 185 additions and 326 deletions

View file

@ -1616,16 +1616,6 @@ QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt)
} }
} }
void EffectsHandlerImpl::slotShowOutline(const QRect& geometry)
{
emit showOutline(geometry);
}
void EffectsHandlerImpl::slotHideOutline()
{
emit hideOutline();
}
QString EffectsHandlerImpl::supportInformation(const QString &name) const QString EffectsHandlerImpl::supportInformation(const QString &name) const
{ {
if (!isEffectLoaded(name)) { if (!isEffectLoaded(name)) {

View file

@ -202,8 +202,6 @@ public Q_SLOTS:
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to); void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
void slotTabAdded(EffectWindow* from, EffectWindow* to); void slotTabAdded(EffectWindow* from, EffectWindow* to);
void slotTabRemoved(EffectWindow* c, EffectWindow* newActiveWindow); void slotTabRemoved(EffectWindow* c, EffectWindow* newActiveWindow);
void slotShowOutline(const QRect &geometry);
void slotHideOutline();
// slots for D-Bus interface // slots for D-Bus interface
Q_SCRIPTABLE void reconfigureEffect(const QString& name); Q_SCRIPTABLE void reconfigureEffect(const QString& name);

View file

@ -111,7 +111,6 @@ endif()
# Common effects # Common effects
include( dialogparent/CMakeLists.txt ) include( dialogparent/CMakeLists.txt )
include( outline/CMakeLists.txt )
include( presentwindows/CMakeLists.txt ) include( presentwindows/CMakeLists.txt )
include( screenedge/CMakeLists.txt ) include( screenedge/CMakeLists.txt )
include( slidingpopups/CMakeLists.txt ) include( slidingpopups/CMakeLists.txt )

View file

@ -1,12 +0,0 @@
#######################################
# Effect
# Source files
set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
outline/outline.cpp
)
# .desktop files
install( FILES
outline/outline.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/kwin )

View file

@ -1,86 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 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 "outline.h"
namespace KWin
{
KWIN_EFFECT(outline, OutlineEffect)
OutlineEffect::OutlineEffect()
: Effect()
, m_active(false)
, m_outline(NULL)
{
connect(effects, SIGNAL(showOutline(QRect)), SLOT(slotShowOutline(QRect)));
connect(effects, SIGNAL(hideOutline()), SLOT(slotHideOutline()));
}
OutlineEffect::~OutlineEffect()
{
delete m_outline;
}
void OutlineEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
{
effects->paintScreen(mask, region, data);
if (m_active) {
m_outline->render();
}
}
bool OutlineEffect::provides(Feature feature)
{
if (feature == Outline) {
return true;
} else {
return false;
}
}
void OutlineEffect::slotHideOutline()
{
m_active = false;
effects->addRepaint(m_geometry);
}
void OutlineEffect::slotShowOutline(const QRect& geometry)
{
if (m_active) {
effects->addRepaint(m_geometry);
}
m_active = true;
m_geometry = geometry;
if (!m_outline) {
m_outline = effects->effectFrame(EffectFrameNone);
}
m_outline->setGeometry(geometry);
m_outline->setSelection(geometry);
effects->addRepaint(geometry);
}
bool OutlineEffect::isActive() const
{
return m_active;
}
} // namespace

View file

@ -1,114 +0,0 @@
[Desktop Entry]
Name=Outline
Name[bs]=Kontura
Name[ca]=Contorn
Name[ca@valencia]=Contorn
Name[cs]=Obrys
Name[da]=Omrids
Name[de]=Umriss
Name[el]=Περίγραμμα
Name[es]=Contorno
Name[et]=Kontuur
Name[eu]=Zirriborroa
Name[fa]=طرح کلی
Name[fi]=Ääriviiva
Name[fr]=Esquisse
Name[gl]=Contorno
Name[he]=מתאר
Name[hr]=Kontura
Name[hu]=Körvonal
Name[ia]=Profilo
Name[is]=Útlína
Name[it]=Bordo
Name[kk]=Айнала сызық
Name[km]=
Name[ko]=
Name[lt]=Apibrėžti
Name[lv]=Kontūra
Name[mr]=
Name[nb]=Omriss
Name[nds]=Ümreet
Name[nl]=Omlijning
Name[pa]=
Name[pl]=Zarys
Name[pt]=Contorno
Name[pt_BR]=Contorno
Name[ro]=Contur
Name[ru]=Контур окна
Name[sk]=Obrys
Name[sl]=Obris
Name[sr]=Контура
Name[sr@ijekavian]=Контура
Name[sr@ijekavianlatin]=Kontura
Name[sr@latin]=Kontura
Name[sv]=Kontur
Name[tr]=Anahat
Name[ug]=ئىزنا
Name[uk]=Контур
Name[wa]=Cotoû
Name[x-test]=xxOutlinexx
Name[zh_CN]=
Name[zh_TW]=
Icon=preferences-system-windows-effect-outline
Comment=Helper effect to render an outline
Comment[bs]=Pomoćni efekt za crtanje konture
Comment[ca]=Efecte auxiliar per dibuixar un contorn
Comment[ca@valencia]=Efecte auxiliar per dibuixar un contorn
Comment[cs]=Pomocný efekt pro vykreslení obrysu
Comment[da]=Hjælpeeffekt til at rendere et omrids
Comment[de]=Hilfseffekt, der einen Umriss zeichnet.
Comment[el]=Εφέ αποτύπωσης ενός περιγράμματος
Comment[es]=Efecto de ayuda para representar un contorno
Comment[et]=Abiefekt kontuuri renderdamiseks
Comment[eu]=Zirriborro bat errendatzeko efektu laguntzailea
Comment[fi]=Piirtää ikkunoiden ääriviivat
Comment[fr]=Effet d'assistance permettant de dessiner dans un style esquissé
Comment[gl]=Efecto auxiliar para debuxar un contorno
Comment[he]=אפקט שמצייר מתאר
Comment[hr]=Pomoćni efekt za iscrtavanje konture
Comment[hu]=Segédeffektus körvonal rajzolásához
Comment[ia]=Effecto de adjuta pro render un profilo
Comment[is]=Myndgerir útlínu
Comment[it]=Effetto per creare un bordo
Comment[kk]=Айнала сызық салу көмек эффекті
Comment[km]=
Comment[ko]=
Comment[lt]=Pagalbos efektas vaizduoti kontūrą
Comment[lv]=Palīgefekts kontūras zīmēšanai
Comment[mr]= ि
Comment[nb]=Hjelper-effekt for å tegne et omriss
Comment[nds]=Hölper för't Opstellen vun en Ümreet
Comment[nl]=Effect van hulp bij weergeven van omlijning
Comment[pl]=Efekt pomocniczy przy renderowania zarysu
Comment[pt]=Efeito auxiliar para desenhar um contorno
Comment[pt_BR]=Efeito auxiliar para desenhar um contorno
Comment[ro]=Efect ajutător pentru desenarea unui contur
Comment[ru]=Вспомогательный эффект для отрисовки контуров окон
Comment[sk]=Pomocný efekt na vykreslenie obrysu
Comment[sl]=Pomožni učinek, ki izrisuje obris
Comment[sr]=Помоћни ефекат за исцртавање контуре
Comment[sr@ijekavian]=Помоћни ефекат за исцртавање контуре
Comment[sr@ijekavianlatin]=Pomoćni efekat za iscrtavanje konture
Comment[sr@latin]=Pomoćni efekat za iscrtavanje konture
Comment[sv]=Hjälpeffekt för att återge en kontur
Comment[tr]=Anahattı render etmek için yardımcı efekt
Comment[ug]=ئىزناسىنى سىزىدىغان ياردەمچىنىڭ ئۈنۈمى
Comment[uk]=Допоміжний ефект показу контуру
Comment[vi]=Hiu ng tr giúp đ hin th vin ca s
Comment[wa]=Efet aidant pol rindou d' on cotoû
Comment[x-test]=xxHelper effect to render an outlinexx
Comment[zh_CN]=
Comment[zh_TW]=
Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Martin Gräßlin
X-KDE-PluginInfo-Email=mgraesslin@kde.org
X-KDE-PluginInfo-Name=kwin4_effect_outline
X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Category=Window Management
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-Library=kwin4_effect_builtins
X-KDE-Ordering=90

View file

@ -1,52 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 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_OUTLINE_H
#define KWIN_OUTLINE_H
#include <kwineffects.h>
namespace KWin
{
class OutlineEffect : public Effect
{
Q_OBJECT
public:
OutlineEffect();
virtual ~OutlineEffect();
virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data);
virtual bool provides(Feature feature);
virtual bool isActive() const;
public Q_SLOTS:
void slotShowOutline(const QRect &geometry);
void slotHideOutline();
private:
QRect m_geometry;
bool m_active;
EffectFrame *m_outline;
};
} // namespace
#endif // KWIN_OUTLINE_H

View file

@ -1135,22 +1135,6 @@ Q_SIGNALS:
* @since 4.7 * @since 4.7
*/ */
void propertyNotify(KWin::EffectWindow* w, long atom); void propertyNotify(KWin::EffectWindow* w, long atom);
/**
* Requests to show an outline. An effect providing to show an outline should
* connect to the signal and render an outline.
* The outline should be shown till the signal is emitted again with a new
* geometry or the @link hideOutline signal is emitted.
* @param outline The geometry of the outline to render.
* @see hideOutline
* @since 4.7
**/
void showOutline(const QRect& outline);
/**
* Signal emitted when the outline should no longer be shown.
* @see showOutline
* @since 4.7
**/
void hideOutline();
/** /**
* Signal emitted after the screen geometry changed (e.g. add of a monitor). * Signal emitted after the screen geometry changed (e.g. add of a monitor).

View file

@ -21,18 +21,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// own // own
#include "outline.h" #include "outline.h"
// KWin // KWin
#include "effects.h" #include "composite.h"
// KWin libs // KWin libs
#include <kwinxrenderutils.h> #include <kwinxrenderutils.h>
// Plasma
#include <Plasma/FrameSvg>
// Qt
#include <QPainter>
// xcb // xcb
#include <xcb/render.h> #include <xcb/render.h>
namespace KWin { namespace KWin {
Outline::Outline() Outline::Outline(QObject *parent)
: m_initialized(false) : QObject(parent)
, m_active(false) , m_active(false)
{ {
connect(Compositor::self(), SIGNAL(compositingToggled(bool)), SLOT(compositingChanged()));
} }
Outline::~Outline() Outline::~Outline()
@ -42,11 +47,14 @@ Outline::~Outline()
void Outline::show() void Outline::show()
{ {
m_active = true; m_active = true;
if (effects && static_cast<EffectsHandlerImpl*>(effects)->provides(Effect::Outline)) { if (m_visual.isNull()) {
static_cast<EffectsHandlerImpl*>(effects)->slotShowOutline(m_outlineGeometry); createHelper();
return; // done by effect
} }
showWithX(); if (m_visual.isNull()) {
// something went wrong
return;
}
m_visual->show();
} }
void Outline::hide() void Outline::hide()
@ -55,11 +63,10 @@ void Outline::hide()
return; return;
} }
m_active = false; m_active = false;
if (effects && static_cast<EffectsHandlerImpl*>(effects)->provides(Effect::Outline)) { if (m_visual.isNull()) {
static_cast<EffectsHandlerImpl*>(effects)->slotHideOutline(); return;
return; // done by effect
} }
forEachWindow(&Xcb::Window::unmap); m_visual->hide();
} }
void Outline::show(const QRect& outlineGeometry) void Outline::show(const QRect& outlineGeometry)
@ -73,7 +80,85 @@ void Outline::setGeometry(const QRect& outlineGeometry)
m_outlineGeometry = outlineGeometry; m_outlineGeometry = outlineGeometry;
} }
void Outline::showWithX() void Outline::createHelper()
{
if (!m_visual.isNull()) {
return;
}
if (Compositor::compositing()) {
m_visual.reset(new CompositedOutlineVisual(this));
} else {
m_visual.reset(new NonCompositedOutlineVisual(this));
}
}
void Outline::compositingChanged()
{
m_visual.reset();
if (m_active) {
show();
}
}
OutlineVisual::OutlineVisual(Outline *outline)
: m_outline(outline)
{
}
OutlineVisual::~OutlineVisual()
{
}
CompositedOutlineVisual::CompositedOutlineVisual(Outline *outline)
: QWidget(NULL, Qt::X11BypassWindowManagerHint)
, OutlineVisual(outline)
, m_background(new Plasma::FrameSvg(this))
{
setAttribute(Qt::WA_TranslucentBackground);
QPalette pal = palette();
pal.setColor(backgroundRole(), Qt::transparent);
setPalette(pal);
m_background->setImagePath("widgets/viewitem");
m_background->setElementPrefix("hover");
m_background->setCacheAllRenderedFrames(true);
m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
}
CompositedOutlineVisual::~CompositedOutlineVisual()
{
}
void CompositedOutlineVisual::hide()
{
QWidget::hide();
}
void CompositedOutlineVisual::show()
{
const QRect &outlineGeometry = outline()->geometry();
m_background->resizeFrame(outlineGeometry.size());
setGeometry(outlineGeometry);
QWidget::show();
}
void CompositedOutlineVisual::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
m_background->paintFrame(&painter);
}
NonCompositedOutlineVisual::NonCompositedOutlineVisual(Outline *outline)
: OutlineVisual(outline)
, m_initialized(false)
{
}
NonCompositedOutlineVisual::~NonCompositedOutlineVisual()
{
}
void NonCompositedOutlineVisual::show()
{ {
if (!m_initialized) { if (!m_initialized) {
const QRect geo(0, 0, 1, 1); const QRect geo(0, 0, 1, 1);
@ -88,15 +173,16 @@ void Outline::showWithX()
const int defaultDepth = Xcb::defaultDepth(); const int defaultDepth = Xcb::defaultDepth();
// left/right parts are between top/bottom, they don't reach as far as the corners const QRect &outlineGeometry = outline()->geometry();
// left/right parts are between top/bottom, they don't reach as far as the corners
const uint16_t verticalWidth = 5; const uint16_t verticalWidth = 5;
const uint16_t verticalHeight = m_outlineGeometry.height() - 10; const uint16_t verticalHeight = outlineGeometry.height() - 10;
const uint16_t horizontalWidth = m_outlineGeometry.width(); const uint16_t horizontalWidth = outlineGeometry.width();
const uint horizontalHeight = 5; const uint horizontalHeight = 5;
m_leftOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y() + 5, verticalWidth, verticalHeight); m_leftOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + 5, verticalWidth, verticalHeight);
m_rightOutline.setGeometry(m_outlineGeometry.x() + m_outlineGeometry.width() - 5, m_outlineGeometry.y() + 5, verticalWidth, verticalHeight); m_rightOutline.setGeometry(outlineGeometry.x() + outlineGeometry.width() - 5, outlineGeometry.y() + 5, verticalWidth, verticalHeight);
m_topOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y(), horizontalWidth, horizontalHeight); m_topOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y(), horizontalWidth, horizontalHeight);
m_bottomOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y() + m_outlineGeometry.height() - 5, horizontalWidth, horizontalHeight); m_bottomOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + outlineGeometry.height() - 5, horizontalWidth, horizontalHeight);
const xcb_render_color_t white = {0xffff, 0xffff, 0xffff, 0xffff}; const xcb_render_color_t white = {0xffff, 0xffff, 0xffff, 0xffff};
QColor qGray(Qt::gray); QColor qGray(Qt::gray);
@ -151,7 +237,7 @@ void Outline::showWithX()
} }
{ {
xcb_pixmap_t xpix = xcb_generate_id(connection()); xcb_pixmap_t xpix = xcb_generate_id(connection());
xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), m_outlineGeometry.width(), 5); xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), outlineGeometry.width(), 5);
XRenderPicture pic(xpix, defaultDepth); XRenderPicture pic(xpix, defaultDepth);
xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight}; xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight};
@ -176,4 +262,9 @@ void Outline::showWithX()
forEachWindow(&Xcb::Window::map); forEachWindow(&Xcb::Window::map);
} }
void NonCompositedOutlineVisual::hide()
{
forEachWindow(&Xcb::Window::unmap);
}
} // namespace } // namespace

View file

@ -23,7 +23,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "xcbutils.h" #include "xcbutils.h"
#include <QRect> #include <QRect>
namespace Plasma {
class FrameSvg;
}
namespace KWin { namespace KWin {
class OutlineVisual;
/** /**
* @short This class is used to show the outline of a given geometry. * @short This class is used to show the outline of a given geometry.
@ -36,9 +41,10 @@ namespace KWin {
* @author Arthur Arlt * @author Arthur Arlt
* @since 4.7 * @since 4.7
*/ */
class Outline { class Outline : public QObject {
Q_OBJECT
public: public:
Outline(); Outline(QObject *parent);
~Outline(); ~Outline();
/** /**
@ -71,29 +77,85 @@ public:
*/ */
void hide(); void hide();
const QRect &geometry() const;
private Q_SLOTS:
void compositingChanged();
private: private:
void createHelper();
QScopedPointer<OutlineVisual> m_visual;
QRect m_outlineGeometry;
bool m_active;
};
/** class OutlineVisual
* Show the window outline using the X implementation {
*/ public:
void showWithX(); OutlineVisual(Outline *outline);
virtual ~OutlineVisual();
virtual void show() = 0;
virtual void hide() = 0;
protected:
Outline *outline();
const Outline *outline() const;
private:
Outline *m_outline;
};
class CompositedOutlineVisual : public QWidget, public OutlineVisual
{
public:
CompositedOutlineVisual(Outline *outline);
virtual ~CompositedOutlineVisual();
virtual void show();
virtual void hide();
protected:
virtual void paintEvent(QPaintEvent *);
private:
Plasma::FrameSvg *m_background;
};
class NonCompositedOutlineVisual : public OutlineVisual
{
public:
NonCompositedOutlineVisual(Outline *outline);
virtual ~NonCompositedOutlineVisual();
virtual void show();
virtual void hide();
private:
// TODO: variadic template arguments for adding method arguments // TODO: variadic template arguments for adding method arguments
template <typename T> template <typename T>
void forEachWindow(T method); void forEachWindow(T method);
bool m_initialized;
Xcb::Window m_topOutline; Xcb::Window m_topOutline;
Xcb::Window m_rightOutline; Xcb::Window m_rightOutline;
Xcb::Window m_bottomOutline; Xcb::Window m_bottomOutline;
Xcb::Window m_leftOutline; Xcb::Window m_leftOutline;
QRect m_outlineGeometry;
bool m_initialized;
bool m_active;
}; };
inline
const QRect &Outline::geometry() const
{
return m_outlineGeometry;
}
inline
Outline *OutlineVisual::outline()
{
return m_outline;
}
inline
const Outline *OutlineVisual::outline() const
{
return m_outline;
}
template <typename T> template <typename T>
inline inline
void Outline::forEachWindow(T method) void NonCompositedOutlineVisual::forEachWindow(T method)
{ {
(m_topOutline.*method)(); (m_topOutline.*method)();
(m_rightOutline.*method)(); (m_rightOutline.*method)();

View file

@ -231,7 +231,7 @@ Workspace::Workspace(bool restore)
client_keys = new KActionCollection(this); client_keys = new KActionCollection(this);
m_outline = new Outline(); m_outline = new Outline(this);
initShortcuts(); initShortcuts();
@ -523,7 +523,6 @@ Workspace::~Workspace()
} }
for (UnmanagedList::iterator it = unmanaged.begin(), end = unmanaged.end(); it != end; ++it) for (UnmanagedList::iterator it = unmanaged.begin(), end = unmanaged.end(); it != end; ++it)
(*it)->release(true); (*it)->release(true);
delete m_outline;
XDeleteProperty(display(), rootWindow(), atoms->kwin_running); XDeleteProperty(display(), rootWindow(), atoms->kwin_running);
writeWindowRules(); writeWindowRules();