Skip to content

Commit

Permalink
qt5: add clipboard support
Browse files Browse the repository at this point in the history
If a Qt application shall use the clipboard, this must be configured as:

<config clipboard="yes">

Fixes #1749
  • Loading branch information
cproc authored and chelmuth committed Nov 9, 2015
1 parent 97bbc8f commit f6863e3
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 4 deletions.
1 change: 1 addition & 0 deletions repos/libports/lib/mk/qt5_qpa_nitpicker.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ SRC_CC = qgenericunixeventdispatcher.cpp \
qeglconvenience.cpp

SRC_CC += main.cpp \
qgenodeclipboard.cpp \
qnitpickerglcontext.cpp \
qnitpickerintegration.cpp \
qnitpickerplatformwindow.cpp \
Expand Down
4 changes: 4 additions & 0 deletions repos/libports/run/qt5_common.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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" />

Expand Down Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -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 */
Original file line number Diff line number Diff line change
@@ -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_ */
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

/* Qt includes */
#include <QtGui/private/qguiapplication_p.h>
#include "qgenodeclipboard.h"
#include "qnitpickerglcontext.h"
#include "qnitpickerintegration.h"
#include "qnitpickerplatformwindow.h"
Expand Down Expand Up @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
32 changes: 29 additions & 3 deletions repos/ports/run/arora.run
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -39,26 +39,51 @@ 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>
<tar name="qt5_fs_arora.tar"/>
</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>}

Expand All @@ -71,6 +96,7 @@ install_config $config
append boot_modules [qt5_boot_modules feature]

append boot_modules {
clipboard
loader
tar_rom
nit_fb
Expand Down

0 comments on commit f6863e3

Please sign in to comment.