2017-05-22 15:11:07 +08:00
|
|
|
#include "appsnapshot.h"
|
2017-05-23 10:52:06 +08:00
|
|
|
#include "_previewcontainer.h"
|
2017-05-22 15:11:07 +08:00
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
|
|
|
|
#include <QX11Info>
|
|
|
|
#include <QPainter>
|
2017-05-24 14:12:50 +08:00
|
|
|
#include <QVBoxLayout>
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
|
|
AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
|
|
|
|
: QWidget(parent),
|
|
|
|
|
2017-05-24 14:12:50 +08:00
|
|
|
m_wid(wid),
|
|
|
|
|
|
|
|
m_title(new QLabel),
|
|
|
|
m_closeBtn(new DImageButton),
|
|
|
|
|
|
|
|
m_wmHelper(DWindowManagerHelper::instance())
|
2017-05-22 17:17:29 +08:00
|
|
|
{
|
2017-05-24 14:12:50 +08:00
|
|
|
m_closeBtn->setFixedSize(24, 24);
|
|
|
|
m_closeBtn->setNormalPic(":/icons/resources/close_round_normal.png");
|
|
|
|
m_closeBtn->setHoverPic(":/icons/resources/close_round_hover.png");
|
|
|
|
m_closeBtn->setPressPic(":/icons/resources/close_round_press.png");
|
|
|
|
m_closeBtn->setVisible(false);
|
|
|
|
|
|
|
|
QHBoxLayout *centralLayout = new QHBoxLayout;
|
|
|
|
centralLayout->addWidget(m_title);
|
|
|
|
centralLayout->addWidget(m_closeBtn);
|
|
|
|
centralLayout->setSpacing(5);
|
|
|
|
centralLayout->setMargin(0);
|
|
|
|
|
|
|
|
setLayout(centralLayout);
|
2017-07-04 14:34:38 +08:00
|
|
|
setAcceptDrops(true);
|
2017-05-24 14:12:50 +08:00
|
|
|
|
|
|
|
connect(m_closeBtn, &DImageButton::clicked, this, &AppSnapshot::closeWindow, Qt::QueuedConnection);
|
|
|
|
connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &AppSnapshot::compositeChanged, Qt::QueuedConnection);
|
|
|
|
|
|
|
|
QTimer::singleShot(1, this, &AppSnapshot::compositeChanged);
|
2017-05-24 11:32:14 +08:00
|
|
|
// QTimer::singleShot(1, this, &AppSnapshot::fetchSnapshot);
|
2017-05-22 17:17:29 +08:00
|
|
|
}
|
|
|
|
|
2017-05-23 15:32:03 +08:00
|
|
|
void AppSnapshot::closeWindow() const
|
|
|
|
{
|
|
|
|
const auto display = QX11Info::display();
|
|
|
|
|
|
|
|
XEvent e;
|
|
|
|
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
|
|
e.xclient.type = ClientMessage;
|
|
|
|
e.xclient.window = m_wid;
|
|
|
|
e.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", true);
|
|
|
|
e.xclient.format = 32;
|
|
|
|
e.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", false);
|
|
|
|
e.xclient.data.l[1] = CurrentTime;
|
|
|
|
|
|
|
|
XSendEvent(display, m_wid, false, NoEventMask, &e);
|
|
|
|
XFlush(display);
|
|
|
|
}
|
|
|
|
|
2017-05-24 14:12:50 +08:00
|
|
|
void AppSnapshot::compositeChanged() const
|
|
|
|
{
|
|
|
|
const bool composite = m_wmHelper->hasComposite();
|
|
|
|
|
|
|
|
m_title->setVisible(!composite);
|
|
|
|
// m_closeBtn->setVisible(!composite);
|
|
|
|
}
|
|
|
|
|
2017-05-24 10:56:43 +08:00
|
|
|
void AppSnapshot::setWindowTitle(const QString &title)
|
|
|
|
{
|
2017-05-24 14:12:50 +08:00
|
|
|
m_title->setText(title);
|
2017-05-24 10:56:43 +08:00
|
|
|
}
|
|
|
|
|
2017-07-04 14:34:38 +08:00
|
|
|
void AppSnapshot::dragEnterEvent(QDragEnterEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::dragEnterEvent(e);
|
|
|
|
|
|
|
|
if (m_wmHelper->hasComposite())
|
|
|
|
emit entered(m_wid);
|
|
|
|
}
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
void AppSnapshot::fetchSnapshot()
|
|
|
|
{
|
2017-05-24 14:12:50 +08:00
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
return;
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
const auto display = QX11Info::display();
|
|
|
|
|
2017-06-09 16:18:15 +08:00
|
|
|
Window unused_window;
|
|
|
|
int unused_int;
|
|
|
|
unsigned unused_uint, w, h;
|
|
|
|
XGetGeometry(display, m_wid, &unused_window, &unused_int, &unused_int, &w, &h, &unused_uint, &unused_uint);
|
|
|
|
XImage *ximage = XGetImage(display, m_wid, 0, 0, w, h, AllPlanes, ZPixmap);
|
|
|
|
if (!ximage)
|
|
|
|
{
|
|
|
|
emit requestCheckWindow();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
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 {
|
2017-05-23 10:52:06 +08:00
|
|
|
m_snapshot = qimage.copy();
|
2017-05-22 17:17:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
XDestroyImage(ximage);
|
|
|
|
XFree(prop_to_return);
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
2017-05-22 17:54:59 +08:00
|
|
|
void AppSnapshot::enterEvent(QEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::enterEvent(e);
|
|
|
|
|
2017-05-24 14:12:50 +08:00
|
|
|
if (!m_wmHelper->hasComposite())
|
|
|
|
m_closeBtn->setVisible(true);
|
|
|
|
else
|
|
|
|
emit entered(m_wid);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppSnapshot::leaveEvent(QEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::leaveEvent(e);
|
|
|
|
|
|
|
|
m_closeBtn->setVisible(false);
|
2017-05-22 17:54:59 +08:00
|
|
|
}
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
void AppSnapshot::paintEvent(QPaintEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::paintEvent(e);
|
|
|
|
|
|
|
|
QPainter painter(this);
|
|
|
|
|
2017-05-25 10:13:38 +08:00
|
|
|
if (!m_wmHelper->hasComposite())
|
2017-05-24 14:12:50 +08:00
|
|
|
{
|
2017-05-25 10:13:38 +08:00
|
|
|
if (underMouse())
|
|
|
|
painter.fillRect(rect(), QColor(255, 255, 255, 255 * .2));
|
2017-05-24 14:12:50 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-22 17:17:29 +08:00
|
|
|
if (m_snapshot.isNull())
|
|
|
|
return;
|
|
|
|
|
2017-05-24 10:56:43 +08:00
|
|
|
const QRect r = rect().marginsRemoved(QMargins(8, 8, 8, 8));
|
2017-05-22 17:17:29 +08:00
|
|
|
|
|
|
|
// draw image
|
2017-05-24 10:56:43 +08:00
|
|
|
const QImage im = m_snapshot.scaled(r.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
2017-05-23 10:52:06 +08:00
|
|
|
const QRect ir = im.rect();
|
|
|
|
const QPoint offset = r.center() - ir.center();
|
|
|
|
painter.drawImage(offset.x(), offset.y(), im);
|
2017-05-22 17:17:29 +08:00
|
|
|
}
|
|
|
|
|
2017-05-22 17:54:59 +08:00
|
|
|
void AppSnapshot::mousePressEvent(QMouseEvent *e)
|
|
|
|
{
|
|
|
|
QWidget::mousePressEvent(e);
|
|
|
|
|
|
|
|
emit clicked(m_wid);
|
|
|
|
}
|