summaryrefslogtreecommitdiffstats
path: root/src/plugins/blackberry/common/windowgrabber.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/blackberry/common/windowgrabber.cpp')
-rw-r--r--src/plugins/blackberry/common/windowgrabber.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/plugins/blackberry/common/windowgrabber.cpp b/src/plugins/blackberry/common/windowgrabber.cpp
new file mode 100644
index 000000000..d02e022aa
--- /dev/null
+++ b/src/plugins/blackberry/common/windowgrabber.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "windowgrabber.h"
+
+#include <QAbstractEventDispatcher>
+#include <QDebug>
+#include <QGuiApplication>
+#include <QImage>
+#include <qpa/qplatformnativeinterface.h>
+
+#include <bps/screen.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+WindowGrabber::WindowGrabber(QObject *parent)
+ : QObject(parent),
+ m_screenBuffer(0),
+ m_active(false),
+ m_screenContextInitialized(false),
+ m_screenPixmapInitialized(false),
+ m_screenPixmapBufferInitialized(false)
+{
+ // grab the window frame with 60 frames per second
+ m_timer.setInterval(1000/60);
+
+ connect(&m_timer, SIGNAL(timeout()), SLOT(grab()));
+
+ QCoreApplication::eventDispatcher()->installNativeEventFilter(this);
+}
+
+WindowGrabber::~WindowGrabber()
+{
+ QCoreApplication::eventDispatcher()->removeNativeEventFilter(this);
+}
+
+void WindowGrabber::setFrameRate(int frameRate)
+{
+ m_timer.setInterval(1000/frameRate);
+}
+
+void WindowGrabber::setWindowId(const QByteArray &windowId)
+{
+ m_windowId = windowId;
+}
+
+void WindowGrabber::start()
+{
+ int result = 0;
+
+ result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
+ if (result != 0) {
+ qWarning() << "WindowGrabber: cannot create screen context:" << strerror(errno);
+ return;
+ } else {
+ m_screenContextInitialized = true;
+ }
+
+ result = screen_create_pixmap(&m_screenPixmap, m_screenContext);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot create pixmap:" << strerror(errno);
+ return;
+ } else {
+ m_screenPixmapInitialized = true;
+ }
+
+ const int usage = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
+ result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_USAGE, &usage);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot set pixmap usage:" << strerror(errno);
+ return;
+ }
+
+ const int format = SCREEN_FORMAT_RGBA8888;
+ result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_FORMAT, &format);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot set pixmap format:" << strerror(errno);
+ return;
+ }
+
+ int size[2] = { 0, 0 };
+ result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, size);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot get window size:" << strerror(errno);
+ return;
+ }
+
+ m_screenBufferWidth = size[0];
+ m_screenBufferHeight = size[1];
+
+ result = screen_set_pixmap_property_iv(m_screenPixmap, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot set pixmap size:" << strerror(errno);
+ return;
+ }
+
+ result = screen_create_pixmap_buffer(m_screenPixmap);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot create pixmap buffer:" << strerror(errno);
+ return;
+ }
+
+ result = screen_get_pixmap_property_pv(m_screenPixmap, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&m_screenPixmapBuffer);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot get pixmap buffer:" << strerror(errno);
+ return;
+ } else {
+ m_screenPixmapBufferInitialized = true;
+ }
+
+ result = screen_get_buffer_property_pv(m_screenPixmapBuffer, SCREEN_PROPERTY_POINTER, (void**)&m_screenBuffer);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot get pixmap buffer pointer:" << strerror(errno);
+ return;
+ }
+
+ result = screen_get_buffer_property_iv(m_screenPixmapBuffer, SCREEN_PROPERTY_STRIDE, &m_screenBufferStride);
+ if (result != 0) {
+ cleanup();
+ qWarning() << "WindowGrabber: cannot get pixmap buffer stride:" << strerror(errno);
+ return;
+ }
+
+ m_timer.start();
+
+ m_active = true;
+}
+
+void WindowGrabber::stop()
+{
+ if (!m_active)
+ return;
+
+ cleanup();
+
+ m_timer.stop();
+
+ m_active = false;
+}
+
+void WindowGrabber::pause()
+{
+ m_timer.stop();
+}
+
+void WindowGrabber::resume()
+{
+ if (!m_active)
+ return;
+
+ m_timer.start();
+}
+
+bool WindowGrabber::nativeEventFilter(const QByteArray&, void *message, long*)
+{
+ bps_event_t * const event = static_cast<bps_event_t *>(message);
+
+ if (event && bps_event_get_domain(event) == screen_get_domain()) {
+ const screen_event_t screen_event = screen_event_get_event(event);
+
+ int eventType;
+ if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
+ qWarning() << "WindowGrabber: Failed to query screen event type";
+ return false;
+ }
+
+ if (eventType != SCREEN_EVENT_CREATE)
+ return false;
+
+ screen_window_t window = 0;
+ if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) {
+ qWarning() << "WindowGrabber: Failed to query window property";
+ return false;
+ }
+
+ const int maxIdStrLength = 128;
+ char idString[maxIdStrLength];
+ if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) {
+ qWarning() << "WindowGrabber: Failed to query window ID string";
+ return false;
+ }
+
+ if (m_windowId == idString) {
+ m_window = window;
+ start();
+ }
+ }
+
+ return false;
+}
+
+QByteArray WindowGrabber::windowGroupId() const
+{
+ QWindow *window = QGuiApplication::allWindows().isEmpty() ? 0 : QGuiApplication::allWindows().first();
+ if (!window)
+ return QByteArray();
+
+ QPlatformNativeInterface * const nativeInterface = QGuiApplication::platformNativeInterface();
+ if (!nativeInterface) {
+ qWarning() << "WindowGrabber: Unable to get platform native interface";
+ return QByteArray();
+ }
+
+ const char * const groupIdData = static_cast<const char *>(
+ nativeInterface->nativeResourceForWindow("windowGroup", window));
+ if (!groupIdData) {
+ qWarning() << "WindowGrabber: Unable to find window group for window" << window;
+ return QByteArray();
+ }
+
+ return QByteArray(groupIdData);
+}
+
+void WindowGrabber::grab()
+{
+ const int result = screen_read_window(m_window, m_screenPixmapBuffer, 0, 0, 0);
+ if (result != 0)
+ return;
+
+ const QImage frame((unsigned char*)m_screenBuffer, m_screenBufferWidth, m_screenBufferHeight,
+ m_screenBufferStride, QImage::Format_ARGB32);
+
+ emit frameGrabbed(frame);
+}
+
+void WindowGrabber::cleanup()
+{
+ if (m_screenPixmapBufferInitialized) {
+ screen_destroy_buffer(m_screenPixmapBuffer);
+ m_screenPixmapBufferInitialized = false;
+ }
+
+ if (m_screenPixmapInitialized) {
+ screen_destroy_pixmap(m_screenPixmap);
+ m_screenPixmapInitialized = false;
+ }
+
+ if (m_screenContextInitialized) {
+ screen_destroy_context(m_screenContext);
+ m_screenContextInitialized = false;
+ }
+}
+
+QT_END_NAMESPACE