QNX: Override QPlatformScreen::grabWindow

The grabWindow API basically should return a screenshot at the window
location. On QNX only the SCREEN_DISPLAY_MANAGER_CONTEXT can read from
the screen which will require root privileges.
At least this will fix some QWidget auto tests that rely on this API.

Change-Id: I350233173d3aecd376f48af9f650606a5cce6205
Reviewed-by: Fabian Bumberger <fbumberger@rim.com>
bb10
Bernd Weimer 2014-06-18 11:23:05 +02:00
parent d49f7168ab
commit d8103d0e62
2 changed files with 101 additions and 2 deletions

View File

@ -209,6 +209,103 @@ QQnxScreen::~QQnxScreen()
delete m_cursor;
}
QPixmap QQnxScreen::grabWindow(WId window, int x, int y, int width, int height) const
{
QQnxWindow *qnxWin = findWindow(reinterpret_cast<screen_window_t>(window));
if (!qnxWin) {
qWarning("grabWindow: unknown window");
return QPixmap();
}
QRect bound = qnxWin->geometry();
if (width < 0)
width = bound.width();
if (height < 0)
height = bound.height();
bound &= QRect(x + bound.x(), y + bound.y(), width, height);
if (bound.width() <= 0 || bound.height() <= 0) {
qWarning("grabWindow: size is null");
return QPixmap();
}
// Create new context, only SCREEN_DISPLAY_MANAGER_CONTEXT can read from screen
screen_context_t context;
if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
if (errno == EPERM)
qWarning("grabWindow: root privileges required");
else
qWarning("grabWindow: cannot create context");
return QPixmap();
}
// Find corresponding display in SCREEN_DISPLAY_MANAGER_CONTEXT
int count = 0;
screen_display_t display = 0;
screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
if (count > 0) {
const size_t idLen = 30;
char matchId[idLen];
char id[idLen];
bool found = false;
screen_display_t *displays = static_cast<screen_display_t*>
(calloc(count, sizeof(screen_display_t)));
screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, idLen, matchId);
while (count && !found) {
--count;
screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
found = !strncmp(id, matchId, idLen);
}
if (found)
display = displays[count];
free(displays);
}
// Create screen and Qt pixmap
screen_pixmap_t pixmap;
QPixmap result;
if (display && !screen_create_pixmap(&pixmap, context)) {
screen_buffer_t buffer;
void *pointer;
int stride;
const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
int val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_USAGE, &val);
val = SCREEN_FORMAT_RGBA8888;
screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_FORMAT, &val);
int err = screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
err = err || screen_create_pixmap_buffer(pixmap);
err = err || screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
reinterpret_cast<void**>(&buffer));
err = err || screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, &pointer);
err = err || screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
err = err || screen_read_display(display, buffer, 1, rect, 0);
if (!err) {
const QImage img(static_cast<unsigned char*>(pointer),
bound.width(), bound.height(), stride, QImage::Format_ARGB32);
result = QPixmap::fromImage(img);
} else {
qWarning("grabWindow: capture error");
}
screen_destroy_pixmap(pixmap);
} else {
qWarning("grabWindow: display/pixmap error ");
}
screen_destroy_context(context);
return result;
}
static int defaultDepth()
{
qScreenDebug() << Q_FUNC_INFO;
@ -463,7 +560,7 @@ void QQnxScreen::resizeWindows(const QRect &previousScreenGeometry)
}
}
QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle)
QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle) const
{
Q_FOREACH (QQnxWindow *window, m_childWindows) {
QQnxWindow * const result = window->findWindow(windowHandle);

View File

@ -62,6 +62,8 @@ public:
QQnxScreen(screen_context_t context, screen_display_t display, bool primaryScreen);
~QQnxScreen();
QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
QRect geometry() const { return m_currentGeometry; }
QRect availableGeometry() const;
int depth() const;
@ -86,7 +88,7 @@ public:
screen_context_t nativeContext() const { return m_screenContext; }
const char *windowGroupName() const { return m_rootWindow ? m_rootWindow->groupName().constData() : 0; }
QQnxWindow *findWindow(screen_window_t windowHandle);
QQnxWindow *findWindow(screen_window_t windowHandle) const;
/* Window hierarchy management */
void addWindow(QQnxWindow *child);