Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ set(CONNECTION_SOURCES
if(enable-wayland)
list(APPEND CONNECTION_SOURCES
connection/waylandinputmethodconnection.cpp
connection/waylandinputmethodconnection.h)
connection/waylandinputmethodconnection.h
connection/waylandinputmethodtransport.h
connection/dbuswaylandinputcontextconnection.cpp
connection/dbuswaylandinputcontextconnection.h)

ecm_add_qtwayland_client_protocol(CONNECTION_SOURCES PROTOCOL ${WAYLANDPROTOCOLS_PATH}/unstable/input-method/input-method-unstable-v1.xml BASENAME input-method-unstable-v1)

Expand Down
43 changes: 43 additions & 0 deletions connection/connectionfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
#include "minputcontextconnection.h"
#include "dbusinputcontextconnection.h"

#include <QDebug>
#include <QGuiApplication>

#ifdef HAVE_WAYLAND
#include "waylandinputmethodconnection.h"
#include "dbuswaylandinputcontextconnection.h"
#endif

namespace Maliit {
Expand All @@ -43,6 +47,45 @@ MInputContextConnection *createWestonIMProtocolConnection()
{
return new WaylandInputMethodConnection;
}

MInputContextConnection *createDBusAndWaylandConnectionWithDynamicAddress()
{
QSharedPointer<Maliit::Server::DBus::Address> address(new Maliit::Server::DBus::DynamicAddress);
return new DBusWaylandInputContextConnection(address);
}

MInputContextConnection *createDBusAndWaylandConnectionWithFixedAddress(const QString &fixedAddress, bool allowAnonymous)
{
Q_UNUSED(allowAnonymous);
QSharedPointer<Maliit::Server::DBus::Address> address(new Maliit::Server::DBus::FixedAddress(fixedAddress));
return new DBusWaylandInputContextConnection(address);
}
#endif

ConnectionMode connectionModeFromEnvironment()
{
#ifdef HAVE_WAYLAND
const bool onWayland = QGuiApplication::platformName().startsWith("wayland");
const QByteArray mode = qgetenv("MALIIT_CONNECTION");

if (mode == "dbus") {
return ConnectionMode::DBus;
} else if (mode == "wayland" || mode == "both") {
if (!onWayland) {
qWarning() << "MALIIT_CONNECTION=" << mode << "needs a Wayland platform, using D-Bus only";
return ConnectionMode::DBus;
}
return mode == "both" ? ConnectionMode::DBusAndWayland : ConnectionMode::Wayland;
} else if (!mode.isEmpty()) {
qWarning() << "Unknown MALIIT_CONNECTION value" << mode << ", expected dbus, wayland or both";
}

const QByteArray forceDbus = qgetenv("MALIIT_FORCE_DBUS_CONNECTION");
if (onWayland && (forceDbus.isEmpty() || forceDbus == "0")) {
return ConnectionMode::Wayland;
}
#endif
return ConnectionMode::DBus;
}

} // namespace Maliit
16 changes: 16 additions & 0 deletions connection/connectionfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,24 @@ MInputContextConnection *createInputContextConnectionWithFixedAddress(const QStr

#ifdef HAVE_WAYLAND
MInputContextConnection *createWestonIMProtocolConnection();
MInputContextConnection *createDBusAndWaylandConnectionWithDynamicAddress();
MInputContextConnection *createDBusAndWaylandConnectionWithFixedAddress(const QString &fixedAddress, bool allowAnonymous);
#endif

enum class ConnectionMode {
DBus,
Wayland,
DBusAndWayland
};

/*! Picks the input context connection from the environment.
*
* MALIIT_CONNECTION=dbus|wayland|both selects the connection explicitly.
* Without it, MALIIT_FORCE_DBUS_CONNECTION keeps its old meaning. Wayland
* connections are only used when running on a Wayland Qt platform.
*/
ConnectionMode connectionModeFromEnvironment();

} // namespace Maliit

#endif // MALIIT_DBUS_CONNECTIONFACTORY_H
140 changes: 140 additions & 0 deletions connection/dbuswaylandinputcontextconnection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* * This file is part of Maliit framework *
*
* This library is free software; you can redistribute it and/or
* modify it 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.
*/

#include "dbuswaylandinputcontextconnection.h"
#include "waylandinputmethodtransport.h"

#include <QKeyEvent>

namespace {

// TODO: Deduplicate it. Same values as in minputcontextconnection.cpp.
const char * const SurroundingTextAttribute = "surroundingText";
const char * const CursorPositionAttribute = "cursorPosition";

} // unnamed namespace

DBusWaylandInputContextConnection::DBusWaylandInputContextConnection(const QSharedPointer<Maliit::Server::DBus::Address> &address)
: DBusInputContextConnection(address)
, m_transport(new Maliit::Wayland::InputMethodTransport(this))
{
}

DBusWaylandInputContextConnection::~DBusWaylandInputContextConnection()
{
}

bool DBusWaylandInputContextConnection::waylandClientActive() const
{
return activeConnection == Maliit::Wayland::ConnectionId;
}

void DBusWaylandInputContextConnection::sendPreeditString(const QString &string,
const QList<Maliit::PreeditTextFormat> &preeditFormats,
int replacementStart,
int replacementLength,
int cursorPos)
{
if (!waylandClientActive()) {
DBusInputContextConnection::sendPreeditString(string, preeditFormats,
replacementStart, replacementLength,
cursorPos);
return;
}

if (!m_transport->context())
return;

MInputContextConnection::sendPreeditString(string, preeditFormats,
replacementStart, replacementLength,
cursorPos);

m_transport->sendPreeditString(string, preeditFormats, replacementStart, replacementLength, cursorPos,
widgetState().value(CursorPositionAttribute).toInt());
}

void DBusWaylandInputContextConnection::sendCommitString(const QString &string,
int replaceStart,
int replaceLength,
int cursorPos)
{
if (!waylandClientActive()) {
DBusInputContextConnection::sendCommitString(string, replaceStart, replaceLength, cursorPos);
return;
}

if (!m_transport->context())
return;

MInputContextConnection::sendCommitString(string, replaceStart, replaceLength, cursorPos);

m_transport->sendCommitString(string, replaceStart, replaceLength, cursorPos,
widgetState().value(CursorPositionAttribute).toInt());
}

void DBusWaylandInputContextConnection::sendKeyEvent(const QKeyEvent &keyEvent,
Maliit::EventRequestType requestType)
{
if (!waylandClientActive()) {
DBusInputContextConnection::sendKeyEvent(keyEvent, requestType);
return;
}

if (!m_transport->context())
return;

Maliit::Wayland::InputMethodTransport::Key key;
if (!Maliit::Wayland::InputMethodTransport::keyFromQKeyEvent(keyEvent, &key))
return;

MInputContextConnection::sendKeyEvent(keyEvent, requestType);

m_transport->sendKey(key, keyEvent.timestamp());
}

void DBusWaylandInputContextConnection::setSelection(int start, int length)
{
if (!waylandClientActive()) {
DBusInputContextConnection::setSelection(start, length);
return;
}

m_transport->setSelection(start, length,
widgetState().value(SurroundingTextAttribute).toString());
}

QString DBusWaylandInputContextConnection::selection(bool &valid)
{
if (!waylandClientActive())
return DBusInputContextConnection::selection(valid);

return m_transport->selection(valid);
}

void DBusWaylandInputContextConnection::setLanguage(const QString &language)
{
// Always let the D-Bus side record the language: it is sent to the next
// D-Bus client that becomes active.
DBusInputContextConnection::setLanguage(language);

if (waylandClientActive())
m_transport->setLanguage(language);
}

void DBusWaylandInputContextConnection::sendActivationLostEvent()
{
if (!waylandClientActive()) {
DBusInputContextConnection::sendActivationLostEvent();
return;
}

// Another client takes over while the Wayland client may still be
// focused: don't leave a half-typed word behind as preedit.
m_transport->sendPreeditString(QString(), QList<Maliit::PreeditTextFormat>(), 0, 0, 0, 0);
}
64 changes: 64 additions & 0 deletions connection/dbuswaylandinputcontextconnection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* * This file is part of Maliit framework *
*
* This library is free software; you can redistribute it and/or
* modify it 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.
*/

#ifndef DBUSWAYLANDINPUTCONTEXTCONNECTION_H
#define DBUSWAYLANDINPUTCONTEXTCONNECTION_H

#include "dbusinputcontextconnection.h"

#include <QScopedPointer>

namespace Maliit {
namespace Wayland {
class InputMethodTransport;
}
}

/*! \internal
* \ingroup maliitserver
* \brief Serves D-Bus input contexts and a zwp_input_method_v1 client at once.
*
* Both kinds of clients share one activeConnection, so the base class decides
* which one is active; outbound calls are routed to the active client only.
*/
class DBusWaylandInputContextConnection : public DBusInputContextConnection
{
Q_OBJECT
Q_DISABLE_COPY(DBusWaylandInputContextConnection)

public:
explicit DBusWaylandInputContextConnection(const QSharedPointer<Maliit::Server::DBus::Address> &address);
virtual ~DBusWaylandInputContextConnection();

//! \reimp
virtual void sendPreeditString(const QString &string,
const QList<Maliit::PreeditTextFormat> &preeditFormats,
int replacementStart = 0,
int replacementLength = 0,
int cursorPos = -1);
virtual void sendCommitString(const QString &string,
int replaceStart = 0,
int replaceLength = 0,
int cursorPos = -1);
virtual void sendKeyEvent(const QKeyEvent &keyEvent,
Maliit::EventRequestType requestType);
virtual void setSelection(int start, int length);
virtual QString selection(bool &valid);
virtual void setLanguage(const QString &language);
virtual void sendActivationLostEvent();
//! \reimp_end

private:
bool waylandClientActive() const;

const QScopedPointer<Maliit::Wayland::InputMethodTransport> m_transport;
};
//! \internal_end

#endif // DBUSWAYLANDINPUTCONTEXTCONNECTION_H
Loading