qt5: add clipboard support

If a Qt application shall use the clipboard, this must be configured as:

<config clipboard="yes">

Fixes #1749
This commit is contained in:
Christian Prochaska 2015-10-28 16:14:12 +01:00 committed by Christian Helmuth
parent 97bbc8f965
commit f6863e3f4b
7 changed files with 244 additions and 4 deletions

View File

@ -10,6 +10,7 @@ SRC_CC = qgenericunixeventdispatcher.cpp \
qeglconvenience.cpp
SRC_CC += main.cpp \
qgenodeclipboard.cpp \
qnitpickerglcontext.cpp \
qnitpickerintegration.cpp \
qnitpickerplatformwindow.cpp \

View File

@ -67,9 +67,12 @@ proc qt5_start_nodes { feature_arg } {
<service name="Input"> <child name="ps2_drv" /> </service>
}
append start_nodes {
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent /> <any-child /> </any-service>
</route>
<config>
<report focus="yes"/>
<domain name="pointer" layer="1" label="no" content="client" origin="pointer" />
<domain name="default" layer="2" label="no" content="client" focus="click" hover="always" />
@ -101,6 +104,7 @@ proc qt5_start_nodes { feature_arg } {
<policy label="decorator -> pointer" report="wm -> pointer"/>
<policy label="layouter -> hover" report="decorator -> hover"/>
<policy label="wm -> focus" report="layouter -> focus"/>
<policy label="clipboard -> focus" report="nitpicker -> focus"/>
</rom>
</config>
</start>

View File

@ -0,0 +1,140 @@
/*
* \brief QGenodeClipboard
* \author Christian Prochaska
* \date 2015-09-18
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include "qgenodeclipboard.h"
#ifndef QT_NO_CLIPBOARD
/* Genode includes */
#include <os/config.h>
#include <util/xml_node.h>
/* Qt includes */
#include <QMimeData>
QT_BEGIN_NAMESPACE
static constexpr bool verbose = false;
QGenodeClipboard::QGenodeClipboard(Genode::Signal_receiver &sig_rcv)
: _clipboard_signal_dispatcher(sig_rcv, *this, &QGenodeClipboard::_handle_clipboard)
{
try {
if (Genode::config()->xml_node().attribute("clipboard").has_value("yes")) {
try {
_clipboard_ds = new (Genode::env()->heap())
Genode::Attached_rom_dataspace("clipboard");
_clipboard_ds->sigh(_clipboard_signal_dispatcher);
_clipboard_ds->update();
} catch (...) { }
try {
_clipboard_reporter = new (Genode::env()->heap())
Genode::Reporter("clipboard");
_clipboard_reporter->enabled(true);
} catch (...) { }
}
} catch (...) { }
}
QGenodeClipboard::~QGenodeClipboard()
{
free(_decoded_clipboard_content);
destroy(Genode::env()->heap(), _clipboard_ds);
destroy(Genode::env()->heap(), _clipboard_reporter);
}
void QGenodeClipboard::_handle_clipboard(unsigned int)
{
emitChanged(QClipboard::Clipboard);
}
QMimeData *QGenodeClipboard::mimeData(QClipboard::Mode mode)
{
if (!_clipboard_ds)
return 0;
_clipboard_ds->update();
if (!_clipboard_ds->is_valid()) {
if (verbose)
PERR("invalid clipboard dataspace");
return 0;
}
char *xml_data = _clipboard_ds->local_addr<char>();
try {
Genode::Xml_node node(xml_data);
if (!node.has_type("clipboard")) {
PERR("invalid clipboard xml syntax");
return 0;
}
free(_decoded_clipboard_content);
_decoded_clipboard_content = (char*)malloc(node.content_size());
if (!_decoded_clipboard_content) {
PERR("could not allocate buffer for decoded clipboard content");
return 0;
}
_mimedata->setText(QString::fromUtf8(_decoded_clipboard_content,
node.decoded_content(_decoded_clipboard_content,
node.content_size())));
} catch (Genode::Xml_node::Invalid_syntax) {
PERR("invalid clipboard xml syntax");
return 0;
}
return _mimedata;
}
void QGenodeClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
if (!data || !data->hasText() || !supportsMode(mode))
return;
QString text = data->text();
QByteArray utf8text = text.toUtf8();
if (!_clipboard_reporter)
return;
try {
Genode::Reporter::Xml_generator xml(*_clipboard_reporter, [&] () {
xml.append_sanitized(utf8text.constData(), utf8text.size()); });
} catch (...) {
PERR("could not write clipboard data");
}
}
QT_END_NAMESPACE
#endif /* QT_NO_CLIPBOARD */

View File

@ -0,0 +1,57 @@
/*
* \brief QGenodeClipboard
* \author Christian Prochaska
* \date 2015-09-18
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _QGENODECLIPBOARD_H_
#define _QGENODECLIPBOARD_H_
#include <QtCore/qglobal.h>
#ifndef QT_NO_CLIPBOARD
/* Genode includes */
#include <os/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <qoost/qmember.h>
/* Qt includes */
#include <qpa/qplatformclipboard.h>
QT_BEGIN_NAMESPACE
class QGenodeClipboard : public QPlatformClipboard
{
private:
Genode::Attached_rom_dataspace *_clipboard_ds = nullptr;
Genode::Signal_dispatcher<QGenodeClipboard> _clipboard_signal_dispatcher;
Genode::Reporter *_clipboard_reporter = nullptr;
char *_decoded_clipboard_content = nullptr;
QMember<QMimeData> _mimedata;
void _handle_clipboard(unsigned int);
public:
QGenodeClipboard(Genode::Signal_receiver &sig_rcv);
~QGenodeClipboard();
QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
};
QT_END_NAMESPACE
#endif /* QT_NO_CLIPBOARD */
#endif /* _QGENODECLIPBOARD_H_ */

View File

@ -13,6 +13,7 @@
/* Qt includes */
#include <QtGui/private/qguiapplication_p.h>
#include "qgenodeclipboard.h"
#include "qnitpickerglcontext.h"
#include "qnitpickerintegration.h"
#include "qnitpickerplatformwindow.h"
@ -87,10 +88,18 @@ QPlatformFontDatabase *QNitpickerIntegration::fontDatabase() const
}
#ifndef QT_NO_CLIPBOARD
QPlatformClipboard *QNitpickerIntegration::clipboard() const
{
static QGenodeClipboard cb(_signal_receiver());
return &cb;
}
#endif
QPlatformOpenGLContext *QNitpickerIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
return new QNitpickerGLContext(context);
}
QT_END_NAMESPACE

View File

@ -54,6 +54,9 @@ class QNitpickerIntegration : public QPlatformIntegration
QPlatformFontDatabase *fontDatabase() const override;
#ifndef QT_NO_CLIPBOARD
QPlatformClipboard *clipboard() const override;
#endif
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
};

View File

@ -9,7 +9,7 @@ set feature(Nic) 1
append build_components [qt5_build_components feature]
append build_components {
server/loader server/tar_rom server/nit_fb app/launchpad test/nitpicker
server/clipboard server/loader server/tar_rom server/nit_fb app/launchpad test/nitpicker
app/arora
}
@ -39,19 +39,36 @@ append config [qt5_parent_provides feature]
append config {
</parent-provides>
<default-route>
<any-service> <parent/> <child name="wm"/> <any-child/> </any-service>
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append config [qt5_start_nodes feature]
append config {
<start name="clipboard">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="ROM"/>
<service name="Report"/>
</provides>
<config>
<policy label="arora -> clipboard" domain="default" />
</config>
<route>
<service name="ROM"> <child name="report_rom"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="loader">
<resource name="RAM" quantum="2M"/>
<provides><service name="Loader"/></provides>
</start>
<start name="arora">
<resource name="RAM" quantum="2G"/>
<config>
<config clipboard="yes">
<libc stdout="/dev/log" stderr="/dev/log">
<vfs>
<dir name="dev"> <log/> </dir>
@ -59,6 +76,14 @@ append config {
</vfs>
</libc>
</config>
<route>
<service name="Nitpicker"> <child name="wm"/> </service>
<service name="Report"> <child name="clipboard"/> </service>
<service name="ROM">
<if-arg key="label" value="clipboard"/> <child name="clipboard"/>
</service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
</config>}
@ -71,6 +96,7 @@ install_config $config
append boot_modules [qt5_boot_modules feature]
append boot_modules {
clipboard
loader
tar_rom
nit_fb