From e0b2be7cb7fa3a6546670600d550d8206196e235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=8D=9A=E6=96=87?= Date: Mon, 22 May 2017 17:17:29 +0800 Subject: [PATCH] add preview widget Change-Id: Ifd6b9b63cae9c3773a1ea7b1146d27bd60154bd9 --- frame/item/appitem.cpp | 2 - frame/item/components/_previewcontainer.cpp | 12 ++- frame/item/components/appsnapshot.cpp | 95 ++++++++++++++++++++- frame/item/components/appsnapshot.h | 18 +++- 4 files changed, 117 insertions(+), 10 deletions(-) diff --git a/frame/item/appitem.cpp b/frame/item/appitem.cpp index 9d8bc977d..e2f5f0a9b 100644 --- a/frame/item/appitem.cpp +++ b/frame/item/appitem.cpp @@ -518,7 +518,5 @@ void AppItem::showPreview() m_appPreviewTips->setWindowInfos(m_titles); m_appPreviewTips->updateLayoutDirection(DockPosition); - qApp->processEvents(); - showPopupWindow(m_appPreviewTips, true); } diff --git a/frame/item/components/_previewcontainer.cpp b/frame/item/components/_previewcontainer.cpp index 932a2bec2..da458db07 100644 --- a/frame/item/components/_previewcontainer.cpp +++ b/frame/item/components/_previewcontainer.cpp @@ -2,6 +2,7 @@ #define FIXED_WIDTH 200 #define FIXED_HEIGHT 130 +#define SPACING 5 _PreviewContainer::_PreviewContainer(QWidget *parent) : QWidget(parent), @@ -9,7 +10,7 @@ _PreviewContainer::_PreviewContainer(QWidget *parent) m_wmHelper(DWindowManagerHelper::instance()) { m_windowListLayout = new QVBoxLayout; - m_windowListLayout->setSpacing(0); + m_windowListLayout->setSpacing(SPACING); m_windowListLayout->setMargin(0); setLayout(m_windowListLayout); @@ -53,19 +54,22 @@ void _PreviewContainer::adjustSize() const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight; const int count = m_snapshots.size(); + if (!count) + return; + if (horizontal) { setFixedHeight(FIXED_HEIGHT); - setFixedWidth(FIXED_WIDTH * count); + setFixedWidth(FIXED_WIDTH * count + SPACING * (count - 1)); } else { setFixedWidth(FIXED_WIDTH); - setFixedHeight(FIXED_HEIGHT * count); + setFixedHeight(FIXED_HEIGHT * count + SPACING * (count - 1)); } } void _PreviewContainer::appendSnapWidget(const WId wid) { - AppSnapshot *snap = new AppSnapshot; + AppSnapshot *snap = new AppSnapshot(wid); m_windowListLayout->addWidget(snap); diff --git a/frame/item/components/appsnapshot.cpp b/frame/item/components/appsnapshot.cpp index aa59cab22..f48ff88de 100644 --- a/frame/item/components/appsnapshot.cpp +++ b/frame/item/components/appsnapshot.cpp @@ -1,7 +1,96 @@ #include "appsnapshot.h" -AppSnapshot::AppSnapshot(QWidget *parent) - : QWidget(parent) -{ +#include +#include +#include +#include +#include +#include + +AppSnapshot::AppSnapshot(const WId wid, QWidget *parent) + : QWidget(parent), + + m_wid(wid), + + m_fetchSnapshotTimer(new QTimer(this)) +{ + m_fetchSnapshotTimer->setSingleShot(true); + m_fetchSnapshotTimer->setInterval(10); + + connect(m_fetchSnapshotTimer, &QTimer::timeout, this, &AppSnapshot::fetchSnapshot, Qt::QueuedConnection); +} + +void AppSnapshot::fetchSnapshot() +{ + if (!isVisible()) + return; + + const auto display = QX11Info::display(); + + XWindowAttributes attrs; + XGetWindowAttributes(display, m_wid, &attrs); + XImage *ximage = XGetImage(display, m_wid, 0, 0, attrs.width, attrs.height, AllPlanes, ZPixmap); + const QImage qimage((const uchar*)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32); + Q_ASSERT(!qimage.isNull()); + + const Atom gtk_frame_extents = XInternAtom(display, "_GTK_FRAME_EXTENTS", true); + Atom actual_type_return; + int actual_format_return; + unsigned long n_items_return; + unsigned long bytes_after_return; + unsigned char *prop_to_return; + + const auto r = XGetWindowProperty(display, m_wid, gtk_frame_extents, 0, 4, false, XA_CARDINAL, + &actual_type_return, &actual_format_return, &n_items_return, &bytes_after_return, &prop_to_return); + if (!r && prop_to_return && n_items_return == 4 && actual_format_return == 32) + { + const unsigned long *extents = reinterpret_cast(prop_to_return); + const int left = extents[0]; + const int right = extents[1]; + const int top = extents[2]; + const int bottom = extents[3]; + const int width = qimage.width(); + const int height = qimage.height(); + + m_snapshot = qimage.copy(left, top, width - left - right, height - top - bottom); + } else { + m_snapshot = qimage; + } + + const QSize s = size(); + m_snapshot = m_snapshot.scaled(s.width(), s.height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + m_snapshot = m_snapshot.copy((m_snapshot.width() - s.width()) / 2, (m_snapshot.height() - s.height()) / 2, s.width(), s.height()); + XDestroyImage(ximage); + XFree(prop_to_return); + + update(); +} + +void AppSnapshot::paintEvent(QPaintEvent *e) +{ + QWidget::paintEvent(e); + + QPainter painter(this); + + if (m_snapshot.isNull()) + return; + + const QRect r = rect(); + + // draw image +// const QRect ir = m_snapshot.rect(); +// const QPoint offset = r.center() - ir.center(); + +// painter.fillRect(offset.x(), offset.y(), ir.width(), ir.height(), Qt::white); +// painter.drawImage(offset.x(), offset.y(), m_snapshot); + painter.fillRect(r, Qt::white); + painter.drawImage(r, m_snapshot); +} + +void AppSnapshot::resizeEvent(QResizeEvent *e) +{ + QWidget::resizeEvent(e); + + m_fetchSnapshotTimer->start(); } diff --git a/frame/item/components/appsnapshot.h b/frame/item/components/appsnapshot.h index 6039f7e56..ce75628c0 100644 --- a/frame/item/components/appsnapshot.h +++ b/frame/item/components/appsnapshot.h @@ -2,13 +2,29 @@ #define APPSNAPSHOT_H #include +#include +#include class AppSnapshot : public QWidget { Q_OBJECT public: - explicit AppSnapshot(QWidget *parent = 0); + explicit AppSnapshot(const WId wid, QWidget *parent = 0); + +private slots: + void fetchSnapshot(); + +private: + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + +private: + const WId m_wid; + + QImage m_snapshot; + + QTimer *m_fetchSnapshotTimer; }; #endif // APPSNAPSHOT_H