From 69b109b5b939eb40a45ae8c11c18c5f5a4266c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 8 Aug 2013 11:39:39 +0200 Subject: [PATCH] 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. --- CMakeLists.txt | 1 + scene.cpp | 98 +++++-------------- scene.h | 9 -- scripting/scripting.cpp | 6 +- .../present_windows/contents/ui/main.qml | 2 + .../clients/thumbnails/contents/ui/main.qml | 2 + .../desktops/previews/contents/ui/main.qml | 1 + thumbnailitem.cpp | 50 ++++------ thumbnailitem.h | 33 ++++--- 9 files changed, 77 insertions(+), 125 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27f4e66005..40523fd14a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,7 @@ set(kwin_OWN_LIBS set(kwin_QT_LIBS ${Qt5Declarative_LIBRARIES} + ${Qt5Quick_LIBRARIES} ${Qt5X11Extras_LIBRARIES} ) diff --git a/scene.cpp b/scene.cpp index 6ed85dc1ec..78657157c7 100644 --- a/scene.cpp +++ b/scene.cpp @@ -70,8 +70,7 @@ along with this program. If not, see . #include -#include -#include +#include #include #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()) { + 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(effectWindow(w)); @@ -410,18 +429,11 @@ void Scene::paintWindowThumbnails(Scene::Window *w, QRegion region, qreal opacit } thumbData.setXScale(size.width() / static_cast(visualThumbRect.width())); thumbData.setYScale(size.height() / static_cast(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 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 ®ion, ScreenPaintData &data) { static_cast(effects)->paintDesktop(desktop, mask, region, data); diff --git a/scene.h b/scene.h index 462a604d9e..93ba06c793 100644 --- a/scene.h +++ b/scene.h @@ -27,8 +27,6 @@ along with this program. If not, see . #include -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 diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp index 5a561aaaa3..3ab223ff15 100644 --- a/scripting/scripting.cpp +++ b/scripting/scripting.cpp @@ -26,7 +26,9 @@ along with this program. If not, see . #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 . #include #include #include +#include #include #include +#include #include #include #include @@ -552,9 +556,9 @@ void KWin::DeclarativeScript::run() kdeclarative.initialize(); kdeclarative.setupBindings(); installScriptFunctions(kdeclarative.scriptEngine()); -#endif qmlRegisterType("org.kde.kwin", 0, 1, "DesktopThumbnailItem"); qmlRegisterType("org.kde.kwin", 0, 1, "ThumbnailItem"); +#endif qmlRegisterType(); qmlRegisterType("org.kde.kwin", 0, 1, "ClientModel"); qmlRegisterType("org.kde.kwin", 0, 1, "ClientModelByScreen"); diff --git a/tabbox/qml/clients/present_windows/contents/ui/main.qml b/tabbox/qml/clients/present_windows/contents/ui/main.qml index 889fc900de..17531d8c43 100644 --- a/tabbox/qml/clients/present_windows/contents/ui/main.qml +++ b/tabbox/qml/clients/present_windows/contents/ui/main.qml @@ -88,6 +88,8 @@ Item { KWin.ThumbnailItem { id: thumbnailItem wId: windowId + clip: true + clipTo: thumbnailListView anchors { top: parent.top left: parent.left diff --git a/tabbox/qml/clients/thumbnails/contents/ui/main.qml b/tabbox/qml/clients/thumbnails/contents/ui/main.qml index 9cef0b44be..dda3b00009 100644 --- a/tabbox/qml/clients/thumbnails/contents/ui/main.qml +++ b/tabbox/qml/clients/thumbnails/contents/ui/main.qml @@ -98,6 +98,8 @@ Item { property variant data: model id: thumbnailItem wId: windowId + clip: true + clipTo: thumbnailListView anchors { fill: parent leftMargin: hoverItem.margins.left diff --git a/tabbox/qml/desktops/previews/contents/ui/main.qml b/tabbox/qml/desktops/previews/contents/ui/main.qml index 65f76314e4..38a02dd1e8 100644 --- a/tabbox/qml/desktops/previews/contents/ui/main.qml +++ b/tabbox/qml/desktops/previews/contents/ui/main.qml @@ -100,6 +100,7 @@ Item { id: thumbnailItem property variant data: model clip: true + clipTo: listView desktop: model.desktop anchors { fill: parent diff --git a/thumbnailitem.cpp b/thumbnailitem.cpp index bf7e6e1913..0048998638 100644 --- a/thumbnailitem.cpp +++ b/thumbnailitem.cpp @@ -26,24 +26,22 @@ along with this program. If not, see . #include "workspace.h" #include "composite.h" // Qt -#include -#include -#include +#include +#include // KDE #include namespace KWin { -AbstractThumbnailItem::AbstractThumbnailItem(QDeclarativeItem *parent) - : QDeclarativeItem(parent) - , m_clip(true) +AbstractThumbnailItem::AbstractThumbnailItem(QQuickItem *parent) + : QQuickPaintedItem(parent) , m_parent(QWeakPointer()) , 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(effects->findWindow(variant.value()))) { + if (auto *w = static_cast(effects->findWindow(qw->winId()))) { m_parent = QWeakPointer(w); - m_parentWindow = variant.value(); + 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(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 diff --git a/thumbnailitem.h b/thumbnailitem.h index 89fd48d715..5592d7a0ed 100644 --- a/thumbnailitem.h +++ b/thumbnailitem.h @@ -21,8 +21,9 @@ along with this program. If not, see . #ifndef KWIN_THUMBNAILITEM_H #define KWIN_THUMBNAILITEM_H +#include #include -#include +#include 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 m_parent; qulonglong m_parentWindow; qreal m_brightness; qreal m_saturation; + QPointer 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 {