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 {