Skip to content

Instantly share code, notes, and snippets.

@oKcerG

oKcerG/windowhole.cpp Secret

Created Aug 6, 2018
Embed
What would you like to do?
#include "windowhole.h"
#include <QAbstractVideoSurface>
#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QQuickItem>
#include <QScreen>
#include <QTimer>
#include <QVideoSurfaceFormat>
WindowHole::WindowHole(QObject* parent)
: QObject(parent)
, m_desktopWidget(qApp->desktop())
, m_timer(new QTimer(this))
, m_primaryScreen(qApp->primaryScreen())
{
m_timer->setInterval(8);
connect(m_timer, &QTimer::timeout, this, &WindowHole::presentFrame);
}
QAbstractVideoSurface* WindowHole::videoSurface() const
{
return m_videoSurface;
}
void WindowHole::setVideoSurface(QAbstractVideoSurface* videoSurface)
{
qDebug() << "setVideoSurface" << videoSurface << parent();
if (m_videoSurface == videoSurface)
return;
m_videoSurface = videoSurface;
emit videoSurfaceChanged();
if (m_completed)
startSurface();
}
void WindowHole::classBegin()
{
}
void WindowHole::componentComplete()
{
m_parentItem = qobject_cast<QQuickItem*>(parent());
connect(m_parentItem, &QQuickItem::widthChanged, this, &WindowHole::parentSizeChanged);
connect(m_parentItem, &QQuickItem::heightChanged, this, &WindowHole::parentSizeChanged);
}
void WindowHole::parentSizeChanged()
{
m_completed = true;
if (!m_parentItem->width() == 0)
startSurface();
}
QPixmap WindowHole::grabDesktopPixmap()
{
QPointF mappedPos = m_parentItem->mapToGlobal({ 0, 0 });
QRect sourceRect = QRectF(mappedPos, QSizeF{ m_parentItem->width(), m_parentItem->height() }).toRect();
return m_primaryScreen->grabWindow(0, sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
}
void WindowHole::startSurface()
{
if (!m_videoSurface) {
m_timer->stop();
return;
}
QImage image = grabDesktopPixmap().toImage();
auto pixelFormat = QVideoFrame::pixelFormatFromImageFormat(image.format());
pixelFormat = QVideoFrame::Format_ARGB32;
QVideoSurfaceFormat format(QSizeF{ m_parentItem->width(), m_parentItem->height() }.toSize(), pixelFormat, QAbstractVideoBuffer::NoHandle);
m_videoSurface->start(format);
m_timer->start();
}
void WindowHole::presentFrame()
{
QImage image = grabDesktopPixmap().toImage();
image = image.convertToFormat(QImage::Format_ARGB32);
QVideoFrame videoFrame(image);
m_videoSurface->present(videoFrame);
}
#ifndef WINDOWHOLE_H
#define WINDOWHOLE_H
#include <QObject>
#include <QQmlParserStatus>
class QDesktopWidget;
class QQuickItem;
class QAbstractVideoSurface;
class QTimer;
class QScreen;
class WindowHole : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface NOTIFY videoSurfaceChanged)
Q_INTERFACES(QQmlParserStatus)
public:
WindowHole(QObject* parent = nullptr);
QAbstractVideoSurface* videoSurface() const;
void setVideoSurface(QAbstractVideoSurface* videoSurface);
void classBegin() override;
void componentComplete() override;
signals:
void videoSurfaceChanged();
private:
void parentSizeChanged();
QPixmap grabDesktopPixmap();
void startSurface();
void presentFrame();
QAbstractVideoSurface* m_videoSurface = nullptr;
QDesktopWidget* m_desktopWidget = nullptr;
QQuickItem* m_parentItem = nullptr;
QTimer* m_timer;
QScreen* m_primaryScreen;
bool m_completed = false;
};
#endif // WINDOWHOLE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment