Adjust the ThumbnailItems to QtQuick2

AbstractThumbnailItem inherits from QQuickPaintedItem using QPainter to
do the fallback painting of icons.

The scene is adjusted to get the information from QQuickItem instead of
QDeclarativeItem. Clipping got a little bit more complex as the clip
path does not exist any more. To get it right the ThumbnailItem needs to
specify the parent it wants to be clipped to with the clipTo property.
E.g.:
clipTo: listView

The scene uses this clipTo parent item to correctly calculate the clip
region. Also the ThumbnailItem needs to have clipping enabled.

Note: this commit currently breaks TabBox as the qml and view are not
yet adjusted. In scripting the export of the item is disabled, but any
qml script using a ThumbnailItem would obviously also fail.
This commit is contained in:
Martin Gräßlin 2013-08-08 11:39:39 +02:00
parent 08a53e6a11
commit 69b109b5b9
9 changed files with 77 additions and 125 deletions

View file

@ -222,6 +222,7 @@ set(kwin_OWN_LIBS
set(kwin_QT_LIBS
${Qt5Declarative_LIBRARIES}
${Qt5Quick_LIBRARIES}
${Qt5X11Extras_LIBRARIES}
)

View file

@ -70,8 +70,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <X11/extensions/shape.h>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QQuickWindow>
#include <QVector2D>
#include "client.h"
@ -382,6 +381,26 @@ void Scene::paintWindow(Window* w, int mask, QRegion region, WindowQuadList quad
paintDesktopThumbnails(w);
}
static void adjustClipRegion(AbstractThumbnailItem *item, QRegion &clippingRegion)
{
if (item->clip() && item->clipTo()) {
// the x/y positions of the parent item are not correct. The margins are added, though the size seems fine
// that's why we have to get the offset by inspecting the anchors properties
QQuickItem *parentItem = item->clipTo();
QPointF offset;
QVariant anchors = parentItem->property("anchors");
if (anchors.isValid()) {
if (QObject *anchorsObject = anchors.value<QObject*>()) {
offset.setX(anchorsObject->property("leftMargin").toReal());
offset.setY(anchorsObject->property("topMargin").toReal());
}
}
const QRectF rect = parentItem->mapRectToScene(QRectF(parentItem->position() - offset,
QSizeF(parentItem->width(), parentItem->height())));
clippingRegion &= rect.adjusted(0,0,-1,-1).translated(item->window()->position()).toRect();
}
}
void Scene::paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacity, qreal brightness, qreal saturation)
{
EffectWindowImpl *wImpl = static_cast<EffectWindowImpl*>(effectWindow(w));
@ -410,18 +429,11 @@ void Scene::paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacit
}
thumbData.setXScale(size.width() / static_cast<qreal>(visualThumbRect.width()));
thumbData.setYScale(size.height() / static_cast<qreal>(visualThumbRect.height()));
// it can happen in the init/closing phase of the tabbox
// that the corresponding QGraphicsScene is not available
if (item->scene() == 0) {
continue;
}
QGraphicsView* declview = findViewForThumbnailItem(item, w);
if (declview == 0) {
if (!item->window()) {
continue;
}
QPoint viewPos = findOffsetInWindow(declview, w->window()->window());
const QPoint point = viewPos + declview->mapFromScene(item->scenePos());
const QPointF point = item->mapToScene(item->position());
qreal x = point.x() + w->x() + (item->width() - size.width())/2;
qreal y = point.y() + w->y() + (item->height() - size.height()) / 2;
x -= thumb->x();
@ -439,14 +451,7 @@ void Scene::paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacit
}
QRegion clippingRegion = region;
clippingRegion &= QRegion(wImpl->x(), wImpl->y(), wImpl->width(), wImpl->height());
QPainterPath path = item->clipPath();
if (!path.isEmpty()) {
// here we assume that the clippath consists of a single rectangle
const QPolygonF sceneBounds = item->mapToScene(path.boundingRect());
const QRect viewBounds = declview->mapFromScene(sceneBounds).boundingRect();
// shrinking the rect due to rounding errors
clippingRegion &= viewBounds.adjusted(0,0,-1,-1).translated(viewPos + w->pos());
}
adjustClipRegion(item, clippingRegion);
effects->drawWindow(thumb, thumbMask, clippingRegion, thumbData);
}
}
@ -461,16 +466,9 @@ void Scene::paintDesktopThumbnails(Scene::Window *w)
if (!item->isVisible()) {
continue;
}
// it can happen in the init/closing phase of the tabbox
// that the corresponding QGraphicsScene is not available
if (item->scene() == 0) {
if (!item->window()) {
continue;
}
QGraphicsView* declview = findViewForThumbnailItem(item, w);
if (declview == 0) {
continue;
}
QPoint viewPos = findOffsetInWindow(declview, w->window()->window());
s_recursionCheck = w;
ScreenPaintData data;
@ -479,20 +477,13 @@ void Scene::paintDesktopThumbnails(Scene::Window *w)
size.scale(item->width(), item->height(), Qt::KeepAspectRatio);
data *= QVector2D(size.width() / double(displayWidth()),
size.height() / double(displayHeight()));
const QPoint point = viewPos + declview->mapFromScene(item->scenePos());
const QPointF point = item->mapToScene(item->position());
const qreal x = point.x() + w->x() + (item->width() - size.width())/2;
const qreal y = point.y() + w->y() + (item->height() - size.height()) / 2;
const QRect region = QRect(x, y, item->width(), item->height());
QRegion clippingRegion = region;
clippingRegion &= QRegion(wImpl->x(), wImpl->y(), wImpl->width(), wImpl->height());
QPainterPath path = item->clipPath();
if (!path.isEmpty()) {
// here we assume that the clippath consists of a single rectangle
const QPolygonF sceneBounds = item->mapToScene(path.boundingRect());
const QRect viewBounds = declview->mapFromScene(sceneBounds).boundingRect();
// shrinking the rect due to rounding errors
clippingRegion &= viewBounds.adjusted(0,0,-1,-1).translated(viewPos + w->pos());
}
adjustClipRegion(item, clippingRegion);
data += QPointF(x, y);
const int desktopMask = PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
paintDesktop(item->desktop(), desktopMask, clippingRegion, data);
@ -500,41 +491,6 @@ void Scene::paintDesktopThumbnails(Scene::Window *w)
}
}
QGraphicsView *Scene::findViewForThumbnailItem(AbstractThumbnailItem *item, Scene::Window *w)
{
// in principle there could be more than one QGraphicsView per QGraphicsScene,
// although TabBox does not make use of it so far
QList<QGraphicsView*> views = item->scene()->views();
foreach (QGraphicsView* view, views) {
if (view->winId() == w->window()->window()) {
return view;
}
QWidget *parent = view;
while ((parent = parent->parentWidget())) {
// if the graphicsview is not the topmost widget we try to go up to the
// toplevel widget and check whether that is the window we are looking for.
if (parent->winId() == w->window()->window()) {
return view;
}
}
}
return NULL;
}
QPoint Scene::findOffsetInWindow(QWidget *view, xcb_window_t idOfTopmostWindow)
{
if (view->winId() == idOfTopmostWindow) {
return QPoint();
}
QWidget *parent = view;
while ((parent = parent->parentWidget())) {
if (parent->winId() == idOfTopmostWindow) {
return view->mapTo(parent, QPoint());
}
}
return QPoint();
}
void Scene::paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data)
{
static_cast<EffectsHandlerImpl*>(effects)->paintDesktop(desktop, mask, region, data);

View file

@ -27,8 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QElapsedTimer>
class QGraphicsView;
namespace KWin
{
@ -167,13 +165,6 @@ protected:
private:
void paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacity, qreal brightness, qreal saturation);
void paintDesktopThumbnails(Scene::Window *w);
/**
* Helper function to find the GraphicsView the ThumbnailItem @p item is rendered in which
* matches our Window @p w.
* If not found @c NULL is returned.
**/
QGraphicsView *findViewForThumbnailItem(AbstractThumbnailItem *item, Scene::Window *w);
QPoint findOffsetInWindow(QWidget *view, xcb_window_t idOfTopmostWindow);
};
// The base class for windows representations in composite backends

View file

@ -26,7 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace_wrapper.h"
#include "scripting_model.h"
#include "../client.h"
#if KWIN_QT5_PORTING
#include "../thumbnailitem.h"
#endif
#include "../options.h"
#include "../workspace.h"
// KDE
@ -44,8 +46,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QFutureWatcher>
#include <QSettings>
#include <QtConcurrentRun>
#include <QtDeclarative/QDeclarativeComponent>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeItem>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/qdeclarative.h>
#include <QMenu>
@ -552,9 +556,9 @@ void KWin::DeclarativeScript::run()
kdeclarative.initialize();
kdeclarative.setupBindings();
installScriptFunctions(kdeclarative.scriptEngine());
#endif
qmlRegisterType<DesktopThumbnailItem>("org.kde.kwin", 0, 1, "DesktopThumbnailItem");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 0, 1, "ThumbnailItem");
#endif
qmlRegisterType<KWin::ScriptingClientModel::ClientModel>();
qmlRegisterType<KWin::ScriptingClientModel::SimpleClientModel>("org.kde.kwin", 0, 1, "ClientModel");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreen>("org.kde.kwin", 0, 1, "ClientModelByScreen");

View file

@ -88,6 +88,8 @@ Item {
KWin.ThumbnailItem {
id: thumbnailItem
wId: windowId
clip: true
clipTo: thumbnailListView
anchors {
top: parent.top
left: parent.left

View file

@ -98,6 +98,8 @@ Item {
property variant data: model
id: thumbnailItem
wId: windowId
clip: true
clipTo: thumbnailListView
anchors {
fill: parent
leftMargin: hoverItem.margins.left

View file

@ -100,6 +100,7 @@ Item {
id: thumbnailItem
property variant data: model
clip: true
clipTo: listView
desktop: model.desktop
anchors {
fill: parent

View file

@ -26,24 +26,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "workspace.h"
#include "composite.h"
// Qt
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeView>
#include <QPainter>
#include <QQuickWindow>
// KDE
#include <KDE/KDebug>
namespace KWin
{
AbstractThumbnailItem::AbstractThumbnailItem(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
, m_clip(true)
AbstractThumbnailItem::AbstractThumbnailItem(QQuickItem *parent)
: QQuickPaintedItem(parent)
, m_parent(QWeakPointer<EffectWindowImpl>())
, m_parentWindow(0)
, m_brightness(1.0)
, m_saturation(1.0)
, m_clipToItem()
{
setFlags(flags() & ~QGraphicsItem::ItemHasNoContents);
Q_ASSERT(Compositor::isCreated());
connect(Compositor::self(), SIGNAL(compositingToggled(bool)), SLOT(compositingToggled()));
compositingToggled();
@ -90,29 +88,18 @@ void AbstractThumbnailItem::findParentEffectWindow()
return;
}
}
QDeclarativeContext *ctx = QDeclarativeEngine::contextForObject(this);
if (!ctx) {
kDebug(1212) << "No Context";
QQuickWindow *qw = window();
if (!qw) {
kDebug(1212) << "No QQuickWindow assigned yet";
return;
}
const QVariant variant = ctx->engine()->rootContext()->contextProperty(QStringLiteral("viewId"));
if (!variant.isValid()) {
kDebug(1212) << "Required context property 'viewId' not found";
return;
}
if (EffectWindowImpl *w = static_cast<EffectWindowImpl*>(effects->findWindow(variant.value<qulonglong>()))) {
if (auto *w = static_cast<EffectWindowImpl*>(effects->findWindow(qw->winId()))) {
m_parent = QWeakPointer<EffectWindowImpl>(w);
m_parentWindow = variant.value<qulonglong>();
m_parentWindow = qw->winId();
}
}
}
void AbstractThumbnailItem::setClip(bool clip)
{
m_clip = clip;
emit clipChanged(clip);
}
void AbstractThumbnailItem::effectWindowAdded()
{
// the window might be added before the EffectWindow is created
@ -145,8 +132,13 @@ void AbstractThumbnailItem::setSaturation(qreal saturation)
emit saturationChanged();
}
void AbstractThumbnailItem::setClipTo(QQuickItem *clip)
{
m_clipToItem = QPointer<QQuickItem>(clip);
emit clipToChanged();
}
WindowThumbnailItem::WindowThumbnailItem(QDeclarativeItem* parent)
WindowThumbnailItem::WindowThumbnailItem(QQuickItem* parent)
: AbstractThumbnailItem(parent)
, m_wId(0)
, m_client(NULL)
@ -186,15 +178,13 @@ void WindowThumbnailItem::setClient(Client *client)
emit clientChanged();
}
void WindowThumbnailItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
void WindowThumbnailItem::paint(QPainter *painter)
{
if (effects) {
QDeclarativeItem::paint(painter, option, widget);
return;
}
Client *client = Workspace::self()->findClient(WindowMatchPredicate(m_wId));
if (!client) {
QDeclarativeItem::paint(painter, option, widget);
return;
}
QPixmap pixmap = client->icon(boundingRect().size().toSize());
@ -210,7 +200,7 @@ void WindowThumbnailItem::repaint(KWin::EffectWindow *w)
}
}
DesktopThumbnailItem::DesktopThumbnailItem(QDeclarativeItem *parent)
DesktopThumbnailItem::DesktopThumbnailItem(QQuickItem *parent)
: AbstractThumbnailItem(parent)
, m_desktop(0)
{
@ -231,10 +221,10 @@ void DesktopThumbnailItem::setDesktop(int desktop)
emit desktopChanged(m_desktop);
}
void DesktopThumbnailItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
void DesktopThumbnailItem::paint(QPainter *painter)
{
Q_UNUSED(painter)
if (effects) {
QDeclarativeItem::paint(painter, option, widget);
return;
}
// TODO: render icon

View file

@ -21,8 +21,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_THUMBNAILITEM_H
#define KWIN_THUMBNAILITEM_H
#include <QPointer>
#include <QWeakPointer>
#include <QtDeclarative/QDeclarativeItem>
#include <QQuickPaintedItem>
namespace KWin
{
@ -31,37 +32,35 @@ class Client;
class EffectWindow;
class EffectWindowImpl;
class AbstractThumbnailItem : public QDeclarativeItem
class AbstractThumbnailItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(bool clip READ isClip WRITE setClip NOTIFY clipChanged SCRIPTABLE true)
Q_PROPERTY(qulonglong parentWindow READ parentWindow WRITE setParentWindow)
Q_PROPERTY(qreal brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged)
Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation NOTIFY saturationChanged)
Q_PROPERTY(QQuickItem *clipTo READ clipTo WRITE setClipTo NOTIFY clipToChanged)
public:
virtual ~AbstractThumbnailItem();
bool isClip() const {
return m_clip;
}
void setClip(bool clip);
qulonglong parentWindow() const {
return m_parentWindow;
}
void setParentWindow(qulonglong parentWindow);
qreal brightness() const;
qreal saturation() const;
QQuickItem *clipTo() const;
public Q_SLOTS:
void setBrightness(qreal brightness);
void setSaturation(qreal saturation);
void setClipTo(QQuickItem *clip);
Q_SIGNALS:
void clipChanged(bool clipped);
void brightnessChanged();
void saturationChanged();
void clipToChanged();
protected:
explicit AbstractThumbnailItem(QDeclarativeItem *parent = 0);
explicit AbstractThumbnailItem(QQuickItem *parent = 0);
protected Q_SLOTS:
virtual void repaint(KWin::EffectWindow* w) = 0;
@ -73,11 +72,11 @@ private Q_SLOTS:
private:
void findParentEffectWindow();
bool m_clip;
QWeakPointer<EffectWindowImpl> m_parent;
qulonglong m_parentWindow;
qreal m_brightness;
qreal m_saturation;
QPointer<QQuickItem> m_clipToItem;
};
class WindowThumbnailItem : public AbstractThumbnailItem
@ -86,7 +85,7 @@ class WindowThumbnailItem : public AbstractThumbnailItem
Q_PROPERTY(qulonglong wId READ wId WRITE setWId NOTIFY wIdChanged SCRIPTABLE true)
Q_PROPERTY(KWin::Client *client READ client WRITE setClient NOTIFY clientChanged)
public:
explicit WindowThumbnailItem(QDeclarativeItem *parent = 0);
explicit WindowThumbnailItem(QQuickItem *parent = 0);
virtual ~WindowThumbnailItem();
qulonglong wId() const {
@ -95,7 +94,7 @@ public:
void setWId(qulonglong wId);
Client *client() const;
void setClient(Client *client);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void paint(QPainter *painter);
Q_SIGNALS:
void wIdChanged(qulonglong wid);
void clientChanged();
@ -111,14 +110,14 @@ class DesktopThumbnailItem : public AbstractThumbnailItem
Q_OBJECT
Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged)
public:
DesktopThumbnailItem(QDeclarativeItem *parent = 0);
DesktopThumbnailItem(QQuickItem *parent = 0);
virtual ~DesktopThumbnailItem();
int desktop() const {
return m_desktop;
}
void setDesktop(int desktop);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void paint(QPainter *painter);
Q_SIGNALS:
void desktopChanged(int desktop);
protected Q_SLOTS:
@ -139,6 +138,12 @@ qreal AbstractThumbnailItem::saturation() const
return m_saturation;
}
inline
QQuickItem* AbstractThumbnailItem::clipTo() const
{
return m_clipToItem.data();
}
inline
Client *WindowThumbnailItem::client() const
{