add preview widget

Change-Id: Ifd6b9b63cae9c3773a1ea7b1146d27bd60154bd9
This commit is contained in:
石博文 2017-05-22 17:17:29 +08:00
parent 0f1e3db89f
commit e0b2be7cb7
Notes: Deepin Code Review 2017-05-22 17:20:56 +08:00
Verified+1: Anonymous Coward #1000004
Code-Review+2: 石博文 <sbw@sbw.so>
Submitted-by: 石博文 <sbw@sbw.so>
Submitted-at: Mon, 22 May 2017 17:20:54 +0800
Reviewed-on: https://cr.deepin.io/23326
Project: dde/dde-dock
Branch: refs/heads/master
4 changed files with 117 additions and 10 deletions

View File

@ -518,7 +518,5 @@ void AppItem::showPreview()
m_appPreviewTips->setWindowInfos(m_titles); m_appPreviewTips->setWindowInfos(m_titles);
m_appPreviewTips->updateLayoutDirection(DockPosition); m_appPreviewTips->updateLayoutDirection(DockPosition);
qApp->processEvents();
showPopupWindow(m_appPreviewTips, true); showPopupWindow(m_appPreviewTips, true);
} }

View File

@ -2,6 +2,7 @@
#define FIXED_WIDTH 200 #define FIXED_WIDTH 200
#define FIXED_HEIGHT 130 #define FIXED_HEIGHT 130
#define SPACING 5
_PreviewContainer::_PreviewContainer(QWidget *parent) _PreviewContainer::_PreviewContainer(QWidget *parent)
: QWidget(parent), : QWidget(parent),
@ -9,7 +10,7 @@ _PreviewContainer::_PreviewContainer(QWidget *parent)
m_wmHelper(DWindowManagerHelper::instance()) m_wmHelper(DWindowManagerHelper::instance())
{ {
m_windowListLayout = new QVBoxLayout; m_windowListLayout = new QVBoxLayout;
m_windowListLayout->setSpacing(0); m_windowListLayout->setSpacing(SPACING);
m_windowListLayout->setMargin(0); m_windowListLayout->setMargin(0);
setLayout(m_windowListLayout); setLayout(m_windowListLayout);
@ -53,19 +54,22 @@ void _PreviewContainer::adjustSize()
const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight; const bool horizontal = m_windowListLayout->direction() == QBoxLayout::LeftToRight;
const int count = m_snapshots.size(); const int count = m_snapshots.size();
if (!count)
return;
if (horizontal) if (horizontal)
{ {
setFixedHeight(FIXED_HEIGHT); setFixedHeight(FIXED_HEIGHT);
setFixedWidth(FIXED_WIDTH * count); setFixedWidth(FIXED_WIDTH * count + SPACING * (count - 1));
} else { } else {
setFixedWidth(FIXED_WIDTH); setFixedWidth(FIXED_WIDTH);
setFixedHeight(FIXED_HEIGHT * count); setFixedHeight(FIXED_HEIGHT * count + SPACING * (count - 1));
} }
} }
void _PreviewContainer::appendSnapWidget(const WId wid) void _PreviewContainer::appendSnapWidget(const WId wid)
{ {
AppSnapshot *snap = new AppSnapshot; AppSnapshot *snap = new AppSnapshot(wid);
m_windowListLayout->addWidget(snap); m_windowListLayout->addWidget(snap);

View File

@ -1,7 +1,96 @@
#include "appsnapshot.h" #include "appsnapshot.h"
AppSnapshot::AppSnapshot(QWidget *parent) #include <X11/Xlib.h>
: QWidget(parent) #include <X11/X.h>
{ #include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <QX11Info>
#include <QPainter>
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<const unsigned long *>(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();
} }

View File

@ -2,13 +2,29 @@
#define APPSNAPSHOT_H #define APPSNAPSHOT_H
#include <QWidget> #include <QWidget>
#include <QDebug>
#include <QTimer>
class AppSnapshot : public QWidget class AppSnapshot : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: 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 #endif // APPSNAPSHOT_H