update:event改为message更恰当

This commit is contained in:
Barry 2019-06-19 16:13:58 +08:00
commit b92199dea3
28 changed files with 560 additions and 733 deletions

View file

@ -1,136 +0,0 @@
#include <QDebug>
#include "controlevent.h"
#include "bufferutil.h"
ControlEvent::ControlEvent(ControlEventType controlEventType)
: QScrcpyEvent(Control)
{
m_data.type = controlEventType;
}
ControlEvent::~ControlEvent()
{
if (CET_SET_CLIPBOARD == m_data.type
&& Q_NULLPTR != m_data.setClipboardEvent.text) {
delete m_data.setClipboardEvent.text;
m_data.setClipboardEvent.text = Q_NULLPTR;
} else if (CET_TEXT == m_data.type
&& Q_NULLPTR != m_data.textEvent.text){
delete m_data.textEvent.text;
m_data.textEvent.text = Q_NULLPTR;
}
}
void ControlEvent::setKeycodeEventData(AndroidKeyeventAction action, AndroidKeycode keycode, AndroidMetastate metastate)
{
m_data.keycodeEvent.action = action;
m_data.keycodeEvent.keycode = keycode;
m_data.keycodeEvent.metastate = metastate;
}
void ControlEvent::setTextEventData(QString& text)
{
// write length (2 byte) + string (non nul-terminated)
if (CONTROL_EVENT_TEXT_MAX_LENGTH < text.length()) {
// injecting a text takes time, so limit the text length
text = text.left(CONTROL_EVENT_TEXT_MAX_LENGTH);
}
QByteArray tmp = text.toUtf8();
m_data.textEvent.text = new char[tmp.length() + 1];
memcpy(m_data.textEvent.text, tmp.data(), tmp.length());
m_data.textEvent.text[tmp.length()] = '\0';
}
void ControlEvent::setMouseEventData(AndroidMotioneventAction action, AndroidMotioneventButtons buttons, QRect position)
{
m_data.mouseEvent.action = action;
m_data.mouseEvent.buttons = buttons;
m_data.mouseEvent.position = position;
}
void ControlEvent::setTouchEventData(quint32 id, AndroidMotioneventAction action, QRect position)
{
m_data.touchEvent.action = action;
m_data.touchEvent.id = id;
m_data.touchEvent.position = position;
}
void ControlEvent::setScrollEventData(QRect position, qint32 hScroll, qint32 vScroll)
{
m_data.scrollEvent.position = position;
m_data.scrollEvent.hScroll = hScroll;
m_data.scrollEvent.vScroll = vScroll;
}
void ControlEvent::setSetClipboardEventData(QString &text)
{
if (text.isEmpty()) {
return;
}
if (CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH < text.length()) {
text = text.left(CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH);
}
QByteArray tmp = text.toUtf8();
m_data.setClipboardEvent.text = new char[tmp.length() + 1];
memcpy(m_data.setClipboardEvent.text, tmp.data(), tmp.length());
m_data.setClipboardEvent.text[tmp.length()] = '\0';
}
void ControlEvent::writePosition(QBuffer &buffer, const QRect& value)
{
BufferUtil::write16(buffer, value.left());
BufferUtil::write16(buffer, value.top());
BufferUtil::write16(buffer, value.width());
BufferUtil::write16(buffer, value.height());
}
QByteArray ControlEvent::serializeData()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QBuffer::WriteOnly);
buffer.putChar(m_data.type);
switch (m_data.type) {
case CET_KEYCODE:
buffer.putChar(m_data.keycodeEvent.action);
BufferUtil::write32(buffer, m_data.keycodeEvent.keycode);
BufferUtil::write32(buffer, m_data.keycodeEvent.metastate);
break;
case CET_TEXT:
BufferUtil::write16(buffer, strlen(m_data.textEvent.text));
buffer.write(m_data.textEvent.text, strlen(m_data.textEvent.text));
break;
case CET_MOUSE:
buffer.putChar(m_data.mouseEvent.action);
BufferUtil::write32(buffer, m_data.mouseEvent.buttons);
writePosition(buffer, m_data.mouseEvent.position);
break;
case CET_TOUCH:
buffer.putChar(m_data.touchEvent.id);
buffer.putChar(m_data.touchEvent.action);
writePosition(buffer, m_data.touchEvent.position);
break;
case CET_SCROLL:
writePosition(buffer, m_data.scrollEvent.position);
BufferUtil::write32(buffer, m_data.scrollEvent.hScroll);
BufferUtil::write32(buffer, m_data.scrollEvent.vScroll);
break;
case CET_SET_CLIPBOARD:
BufferUtil::write16(buffer, strlen(m_data.setClipboardEvent.text));
buffer.write(m_data.setClipboardEvent.text, strlen(m_data.setClipboardEvent.text));
break;
case CET_BACK_OR_SCREEN_ON:
case CET_EXPAND_NOTIFICATION_PANEL:
case CET_COLLAPSE_NOTIFICATION_PANEL:
case CET_GET_CLIPBOARD:
break;
default:
qDebug() << "Unknown event type:" << m_data.type;
break;
}
buffer.close();
return byteArray;
}

View file

@ -1,90 +0,0 @@
#ifndef CONTROLEVENT_H
#define CONTROLEVENT_H
#include <QRect>
#include <QString>
#include <QBuffer>
#include "qscrcpyevent.h"
#include "input.h"
#include "keycodes.h"
#define CONTROL_EVENT_TEXT_MAX_LENGTH 300
#define CONTROL_EVENT_CLIPBOARD_TEXT_MAX_LENGTH 4093
// ControlEvent
class ControlEvent : public QScrcpyEvent
{
public:
enum ControlEventType {
CET_NULL = -1,
CET_KEYCODE = 0,
CET_TEXT,
CET_MOUSE,
CET_SCROLL,
CET_BACK_OR_SCREEN_ON,
CET_EXPAND_NOTIFICATION_PANEL,
CET_COLLAPSE_NOTIFICATION_PANEL,
CET_GET_CLIPBOARD,
CET_SET_CLIPBOARD,
CET_TOUCH,
};
ControlEvent(ControlEventType controlEventType);
virtual ~ControlEvent();
void setKeycodeEventData(AndroidKeyeventAction action, AndroidKeycode keycode, AndroidMetastate metastate);
void setTextEventData(QString& text);
void setMouseEventData(AndroidMotioneventAction action, AndroidMotioneventButtons buttons, QRect position);
// id 代表一个触摸点最多支持10个触摸点[0,9]
// action 只能是AMOTION_EVENT_ACTION_DOWNAMOTION_EVENT_ACTION_UPAMOTION_EVENT_ACTION_MOVE
// position action动作对应的位置
void setTouchEventData(quint32 id, AndroidMotioneventAction action, QRect position);
void setScrollEventData(QRect position, qint32 hScroll, qint32 vScroll);
void setSetClipboardEventData(QString& text);
QByteArray serializeData();
private:
void writePosition(QBuffer& buffer, const QRect& value);
private:
struct ControlEventData {
ControlEventType type = CET_NULL;
union {
struct {
AndroidKeyeventAction action;
AndroidKeycode keycode;
AndroidMetastate metastate;
} keycodeEvent;
struct {
char* text = Q_NULLPTR;
} textEvent;
struct {
AndroidMotioneventAction action;
AndroidMotioneventButtons buttons;
QRect position;
} mouseEvent;
struct {
quint32 id;
AndroidMotioneventAction action;
QRect position;
} touchEvent;
struct {
QRect position;
qint32 hScroll;
qint32 vScroll;
} scrollEvent;
struct {
char *text = Q_NULLPTR;
} setClipboardEvent;
};
ControlEventData(){}
~ControlEventData(){}
};
ControlEventData m_data;
};
#endif // CONTROLEVENT_H

View file

@ -2,7 +2,7 @@
#include "controller.h" #include "controller.h"
#include "videosocket.h" #include "videosocket.h"
#include "controlevent.h" #include "controlmsg.h"
#include "receiver.h" #include "receiver.h"
Controller::Controller(QObject* parent) : QObject(parent) Controller::Controller(QObject* parent) : QObject(parent)
@ -29,26 +29,26 @@ QTcpSocket *Controller::getControlSocket()
return m_controlSocket; return m_controlSocket;
} }
void Controller::postControlEvent(ControlEvent *controlEvent) void Controller::postControlMsg(ControlMsg *controlMsg)
{ {
if (controlEvent) { if (controlMsg) {
QCoreApplication::postEvent(this, controlEvent); QCoreApplication::postEvent(this, controlMsg);
} }
} }
void Controller::test(QRect rc) void Controller::test(QRect rc)
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_MOUSE); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_MOUSE);
controlEvent->setMouseEventData(AMOTION_EVENT_ACTION_DOWN, AMOTION_EVENT_BUTTON_PRIMARY, rc); controlMsg->setInjectMouseMsgData(AMOTION_EVENT_ACTION_DOWN, AMOTION_EVENT_BUTTON_PRIMARY, rc);
postControlEvent(controlEvent); postControlMsg(controlMsg);
} }
bool Controller::event(QEvent *event) bool Controller::event(QEvent *event)
{ {
if (event && event->type() == ControlEvent::Control) { if (event && event->type() == ControlMsg::Control) {
ControlEvent* controlEvent = dynamic_cast<ControlEvent*>(event); ControlMsg* controlMsg = dynamic_cast<ControlMsg*>(event);
if (controlEvent) { if (controlMsg) {
sendControl(controlEvent->serializeData()); sendControl(controlMsg->serializeData());
} }
return true; return true;
} }

View file

@ -5,7 +5,7 @@
#include <QPointer> #include <QPointer>
class QTcpSocket; class QTcpSocket;
class ControlEvent; class ControlMsg;
class Receiver; class Receiver;
class Controller : public QObject class Controller : public QObject
{ {
@ -16,7 +16,7 @@ public:
void setControlSocket(QTcpSocket* controlSocket); void setControlSocket(QTcpSocket* controlSocket);
QTcpSocket* getControlSocket(); QTcpSocket* getControlSocket();
void postControlEvent(ControlEvent* controlEvent); void postControlMsg(ControlMsg* controlMsg);
void test(QRect rc); void test(QRect rc);
protected: protected:

View file

@ -0,0 +1,136 @@
#include <QDebug>
#include "controlmsg.h"
#include "bufferutil.h"
ControlMsg::ControlMsg(ControlMsgType controlMsgType)
: QScrcpyEvent(Control)
{
m_data.type = controlMsgType;
}
ControlMsg::~ControlMsg()
{
if (CMT_SET_CLIPBOARD == m_data.type
&& Q_NULLPTR != m_data.setClipboardMsg.text) {
delete m_data.setClipboardMsg.text;
m_data.setClipboardMsg.text = Q_NULLPTR;
} else if (CMT_INJECT_TEXT == m_data.type
&& Q_NULLPTR != m_data.injectTextMsg.text){
delete m_data.injectTextMsg.text;
m_data.injectTextMsg.text = Q_NULLPTR;
}
}
void ControlMsg::setInjectKeycodeMsgData(AndroidKeyeventAction action, AndroidKeycode keycode, AndroidMetastate metastate)
{
m_data.injectKeycodeMsg.action = action;
m_data.injectKeycodeMsg.keycode = keycode;
m_data.injectKeycodeMsg.metastate = metastate;
}
void ControlMsg::setInjectTextMsgData(QString& text)
{
// write length (2 byte) + string (non nul-terminated)
if (CONTROL_MSG_TEXT_MAX_LENGTH < text.length()) {
// injecting a text takes time, so limit the text length
text = text.left(CONTROL_MSG_TEXT_MAX_LENGTH);
}
QByteArray tmp = text.toUtf8();
m_data.injectTextMsg.text = new char[tmp.length() + 1];
memcpy(m_data.injectTextMsg.text, tmp.data(), tmp.length());
m_data.injectTextMsg.text[tmp.length()] = '\0';
}
void ControlMsg::setInjectMouseMsgData(AndroidMotioneventAction action, AndroidMotioneventButtons buttons, QRect position)
{
m_data.injectMouseMsg.action = action;
m_data.injectMouseMsg.buttons = buttons;
m_data.injectMouseMsg.position = position;
}
void ControlMsg::setInjectTouchMsgData(quint32 id, AndroidMotioneventAction action, QRect position)
{
m_data.injectTouchMsg.action = action;
m_data.injectTouchMsg.id = id;
m_data.injectTouchMsg.position = position;
}
void ControlMsg::setInjectScrollMsgData(QRect position, qint32 hScroll, qint32 vScroll)
{
m_data.injectScrollMsg.position = position;
m_data.injectScrollMsg.hScroll = hScroll;
m_data.injectScrollMsg.vScroll = vScroll;
}
void ControlMsg::setSetClipboardMsgData(QString &text)
{
if (text.isEmpty()) {
return;
}
if (CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH < text.length()) {
text = text.left(CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH);
}
QByteArray tmp = text.toUtf8();
m_data.setClipboardMsg.text = new char[tmp.length() + 1];
memcpy(m_data.setClipboardMsg.text, tmp.data(), tmp.length());
m_data.setClipboardMsg.text[tmp.length()] = '\0';
}
void ControlMsg::writePosition(QBuffer &buffer, const QRect& value)
{
BufferUtil::write16(buffer, value.left());
BufferUtil::write16(buffer, value.top());
BufferUtil::write16(buffer, value.width());
BufferUtil::write16(buffer, value.height());
}
QByteArray ControlMsg::serializeData()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QBuffer::WriteOnly);
buffer.putChar(m_data.type);
switch (m_data.type) {
case CMT_INJECT_KEYCODE:
buffer.putChar(m_data.injectKeycodeMsg.action);
BufferUtil::write32(buffer, m_data.injectKeycodeMsg.keycode);
BufferUtil::write32(buffer, m_data.injectKeycodeMsg.metastate);
break;
case CMT_INJECT_TEXT:
BufferUtil::write16(buffer, strlen(m_data.injectTextMsg.text));
buffer.write(m_data.injectTextMsg.text, strlen(m_data.injectTextMsg.text));
break;
case CMT_INJECT_MOUSE:
buffer.putChar(m_data.injectMouseMsg.action);
BufferUtil::write32(buffer, m_data.injectMouseMsg.buttons);
writePosition(buffer, m_data.injectMouseMsg.position);
break;
case CMT_INJECT_TOUCH:
buffer.putChar(m_data.injectTouchMsg.id);
buffer.putChar(m_data.injectTouchMsg.action);
writePosition(buffer, m_data.injectTouchMsg.position);
break;
case CMT_INJECT_SCROLL:
writePosition(buffer, m_data.injectScrollMsg.position);
BufferUtil::write32(buffer, m_data.injectScrollMsg.hScroll);
BufferUtil::write32(buffer, m_data.injectScrollMsg.vScroll);
break;
case CMT_SET_CLIPBOARD:
BufferUtil::write16(buffer, strlen(m_data.setClipboardMsg.text));
buffer.write(m_data.setClipboardMsg.text, strlen(m_data.setClipboardMsg.text));
break;
case CMT_BACK_OR_SCREEN_ON:
case CMT_EXPAND_NOTIFICATION_PANEL:
case CMT_COLLAPSE_NOTIFICATION_PANEL:
case CMT_GET_CLIPBOARD:
break;
default:
qDebug() << "Unknown event type:" << m_data.type;
break;
}
buffer.close();
return byteArray;
}

View file

@ -0,0 +1,90 @@
#ifndef CONTROLMSG_H
#define CONTROLMSG_H
#include <QRect>
#include <QString>
#include <QBuffer>
#include "qscrcpyevent.h"
#include "input.h"
#include "keycodes.h"
#define CONTROL_MSG_TEXT_MAX_LENGTH 300
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH 4093
// ControlMsg
class ControlMsg : public QScrcpyEvent
{
public:
enum ControlMsgType {
CMT_NULL = -1,
CMT_INJECT_KEYCODE = 0,
CMT_INJECT_TEXT,
CMT_INJECT_MOUSE,
CMT_INJECT_SCROLL,
CMT_BACK_OR_SCREEN_ON,
CMT_EXPAND_NOTIFICATION_PANEL,
CMT_COLLAPSE_NOTIFICATION_PANEL,
CMT_GET_CLIPBOARD,
CMT_SET_CLIPBOARD,
CMT_INJECT_TOUCH,
};
ControlMsg(ControlMsgType controlMsgType);
virtual ~ControlMsg();
void setInjectKeycodeMsgData(AndroidKeyeventAction action, AndroidKeycode keycode, AndroidMetastate metastate);
void setInjectTextMsgData(QString& text);
void setInjectMouseMsgData(AndroidMotioneventAction action, AndroidMotioneventButtons buttons, QRect position);
// id 代表一个触摸点最多支持10个触摸点[0,9]
// action 只能是AMOTION_EVENT_ACTION_DOWNAMOTION_EVENT_ACTION_UPAMOTION_EVENT_ACTION_MOVE
// position action动作对应的位置
void setInjectTouchMsgData(quint32 id, AndroidMotioneventAction action, QRect position);
void setInjectScrollMsgData(QRect position, qint32 hScroll, qint32 vScroll);
void setSetClipboardMsgData(QString& text);
QByteArray serializeData();
private:
void writePosition(QBuffer& buffer, const QRect& value);
private:
struct ControlMsgData {
ControlMsgType type = CMT_NULL;
union {
struct {
AndroidKeyeventAction action;
AndroidKeycode keycode;
AndroidMetastate metastate;
} injectKeycodeMsg;
struct {
char* text = Q_NULLPTR;
} injectTextMsg;
struct {
AndroidMotioneventAction action;
AndroidMotioneventButtons buttons;
QRect position;
} injectMouseMsg;
struct {
quint32 id;
AndroidMotioneventAction action;
QRect position;
} injectTouchMsg;
struct {
QRect position;
qint32 hScroll;
qint32 vScroll;
} injectScrollMsg;
struct {
char *text = Q_NULLPTR;
} setClipboardMsg;
};
ControlMsgData(){}
~ControlMsgData(){}
};
ControlMsgData m_data;
};
#endif // CONTROLMSG_H

View file

@ -1,69 +0,0 @@
#include <QDebug>
#include "deviceevent.h"
#include "bufferutil.h"
DeviceEvent::DeviceEvent(QObject *parent) : QObject(parent)
{
}
DeviceEvent::~DeviceEvent()
{
if (DET_GET_CLIPBOARD == m_data.type
&& Q_NULLPTR != m_data.clipboardEvent.text) {
delete m_data.clipboardEvent.text;
m_data.clipboardEvent.text = Q_NULLPTR;
}
}
DeviceEvent::DeviceEventType DeviceEvent::type()
{
return m_data.type;
}
void DeviceEvent::getClipboardEventData(QString& text)
{
text = QString::fromUtf8(m_data.clipboardEvent.text);
}
qint32 DeviceEvent::deserialize(QByteArray& byteArray)
{
QBuffer buf(&byteArray);
buf.open(QBuffer::ReadOnly);
qint64 len = buf.size();
char c = 0;
qint32 ret = 0;
if (len < 3) {
// at least type + empty string length
return 0; // not available
}
buf.getChar(&c);
m_data.type = (DeviceEventType)c;
switch (m_data.type) {
case DET_GET_CLIPBOARD: {
quint16 clipboardLen = BufferUtil::read16(buf);
if (clipboardLen > len - 3) {
ret = 0; // not available
break;
}
QByteArray text = buf.readAll();
m_data.clipboardEvent.text = new char[text.length() + 1];
memcpy(m_data.clipboardEvent.text, text.data(), text.length());
m_data.clipboardEvent.text[text.length()] = '\0';
ret = 3 + clipboardLen;
break;
}
default:
qWarning("Unsupported device event type: %d", (int) m_data.type);
ret = -1; // error, we cannot recover
}
buf.close();
return ret;
}

View file

@ -1,42 +0,0 @@
#ifndef DEVICEEVENT_H
#define DEVICEEVENT_H
#include <QBuffer>
#define DEVICE_EVENT_QUEUE_SIZE 64
#define DEVICE_EVENT_TEXT_MAX_LENGTH 4093
#define DEVICE_EVENT_SERIALIZED_MAX_SIZE (3 + DEVICE_EVENT_TEXT_MAX_LENGTH)
class DeviceEvent : public QObject
{
Q_OBJECT
public:
enum DeviceEventType {
DET_NULL = -1,
// 和服务端对应
DET_GET_CLIPBOARD = 0,
};
explicit DeviceEvent(QObject *parent = nullptr);
virtual ~DeviceEvent();
DeviceEvent::DeviceEventType type();
void getClipboardEventData(QString& text);
qint32 deserialize(QByteArray& byteArray);
private:
struct DeviceEventData {
DeviceEventType type = DET_NULL;
union {
struct {
char* text = Q_NULLPTR;
} clipboardEvent;
};
DeviceEventData(){}
~DeviceEventData(){}
};
DeviceEventData m_data;
};
#endif // DEVICEEVENT_H

View file

@ -0,0 +1,69 @@
#include <QDebug>
#include "devicemsg.h"
#include "bufferutil.h"
DeviceMsg::DeviceMsg(QObject *parent) : QObject(parent)
{
}
DeviceMsg::~DeviceMsg()
{
if (DMT_GET_CLIPBOARD == m_data.type
&& Q_NULLPTR != m_data.clipboardMsg.text) {
delete m_data.clipboardMsg.text;
m_data.clipboardMsg.text = Q_NULLPTR;
}
}
DeviceMsg::DeviceMsgType DeviceMsg::type()
{
return m_data.type;
}
void DeviceMsg::getClipboardMsgData(QString& text)
{
text = QString::fromUtf8(m_data.clipboardMsg.text);
}
qint32 DeviceMsg::deserialize(QByteArray& byteArray)
{
QBuffer buf(&byteArray);
buf.open(QBuffer::ReadOnly);
qint64 len = buf.size();
char c = 0;
qint32 ret = 0;
if (len < 3) {
// at least type + empty string length
return 0; // not available
}
buf.getChar(&c);
m_data.type = (DeviceMsgType)c;
switch (m_data.type) {
case DMT_GET_CLIPBOARD: {
quint16 clipboardLen = BufferUtil::read16(buf);
if (clipboardLen > len - 3) {
ret = 0; // not available
break;
}
QByteArray text = buf.readAll();
m_data.clipboardMsg.text = new char[text.length() + 1];
memcpy(m_data.clipboardMsg.text, text.data(), text.length());
m_data.clipboardMsg.text[text.length()] = '\0';
ret = 3 + clipboardLen;
break;
}
default:
qWarning("Unsupported device msg type: %d", (int) m_data.type);
ret = -1; // error, we cannot recover
}
buf.close();
return ret;
}

View file

@ -0,0 +1,42 @@
#ifndef DEVICEMSG_H
#define DEVICEMSG_H
#include <QBuffer>
#define DEVICE_MSG_QUEUE_SIZE 64
#define DEVICE_MSG_TEXT_MAX_LENGTH 4093
#define DEVICE_MSG_SERIALIZED_MAX_SIZE (3 + DEVICE_MSG_TEXT_MAX_LENGTH)
class DeviceMsg : public QObject
{
Q_OBJECT
public:
enum DeviceMsgType {
DMT_NULL = -1,
// 和服务端对应
DMT_GET_CLIPBOARD = 0,
};
explicit DeviceMsg(QObject *parent = nullptr);
virtual ~DeviceMsg();
DeviceMsg::DeviceMsgType type();
void getClipboardMsgData(QString& text);
qint32 deserialize(QByteArray& byteArray);
private:
struct DeviceMsgData {
DeviceMsgType type = DMT_NULL;
union {
struct {
char* text = Q_NULLPTR;
} clipboardMsg;
};
DeviceMsgData(){}
~DeviceMsgData(){}
};
DeviceMsgData m_data;
};
#endif // DEVICEMSG_H

View file

@ -1,18 +1,18 @@
HEADERS += \ HEADERS += \
$$PWD/controlevent.h \
$$PWD/controller.h \ $$PWD/controller.h \
$$PWD/inputconvertbase.h \ $$PWD/inputconvertbase.h \
$$PWD/inputconvertgame.h \ $$PWD/inputconvertgame.h \
$$PWD/inputconvertnormal.h \ $$PWD/inputconvertnormal.h \
$$PWD/deviceevent.h \ $$PWD/receiver.h \
$$PWD/receiver.h $$PWD/controlmsg.h \
$$PWD/devicemsg.h
SOURCES += \ SOURCES += \
$$PWD/controlevent.cpp \
$$PWD/controller.cpp \ $$PWD/controller.cpp \
$$PWD/inputconvertbase.cpp \ $$PWD/inputconvertbase.cpp \
$$PWD/inputconvertgame.cpp \ $$PWD/inputconvertgame.cpp \
$$PWD/inputconvertnormal.cpp \ $$PWD/inputconvertnormal.cpp \
$$PWD/deviceevent.cpp \ $$PWD/receiver.cpp \
$$PWD/receiver.cpp $$PWD/controlmsg.cpp \
$$PWD/devicemsg.cpp

View file

@ -15,10 +15,10 @@ void InputConvertBase::setControlSocket(QTcpSocket *controlSocket)
m_controller.setControlSocket(controlSocket); m_controller.setControlSocket(controlSocket);
} }
void InputConvertBase::sendControlEvent(ControlEvent *event) void InputConvertBase::sendControlMsg(ControlMsg *msg)
{ {
if (event) { if (msg) {
m_controller.postControlEvent(event); m_controller.postControlMsg(msg);
} }
} }

View file

@ -5,7 +5,7 @@
#include <QWheelEvent> #include <QWheelEvent>
#include <QKeyEvent> #include <QKeyEvent>
#include "controlevent.h" #include "controlmsg.h"
#include "controller.h" #include "controller.h"
class InputConvertBase class InputConvertBase
@ -21,7 +21,7 @@ public:
virtual void keyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize) = 0; virtual void keyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize) = 0;
void setControlSocket(QTcpSocket* controlSocket); void setControlSocket(QTcpSocket* controlSocket);
void sendControlEvent(ControlEvent* event); void sendControlMsg(ControlMsg* msg);
private: private:
Controller m_controller; Controller m_controller;

View file

@ -111,12 +111,12 @@ void InputConvertGame::sendTouchEvent(int id, QPointF pos, AndroidMotioneventAct
if (0 > id || MULTI_TOUCH_MAX_NUM-1 < id) { if (0 > id || MULTI_TOUCH_MAX_NUM-1 < id) {
return; return;
} }
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_TOUCH); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_TOUCH);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setTouchEventData(id, action, QRect(calcFrameAbsolutePos(pos).toPoint(), m_frameSize)); controlMsg->setInjectTouchMsgData(id, action, QRect(calcFrameAbsolutePos(pos).toPoint(), m_frameSize));
sendControlEvent(controlEvent); sendControlMsg(controlMsg);
} }
QPointF InputConvertGame::calcFrameAbsolutePos(QPointF relativePos) QPointF InputConvertGame::calcFrameAbsolutePos(QPointF relativePos)

View file

@ -39,12 +39,12 @@ void InputConvertNormal::mouseEvent(const QMouseEvent* from, const QSize& frameS
pos.setY(pos.y() * frameSize.height() / showSize.height()); pos.setY(pos.y() * frameSize.height() / showSize.height());
// set data // set data
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_MOUSE); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_MOUSE);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setMouseEventData(action, convertMouseButtons(from->buttons()), QRect(pos.toPoint(), frameSize)); controlMsg->setInjectMouseMsgData(action, convertMouseButtons(from->buttons()), QRect(pos.toPoint(), frameSize));
sendControlEvent(controlEvent); sendControlMsg(controlMsg);
} }
void InputConvertNormal::wheelEvent(const QWheelEvent *from, const QSize& frameSize, const QSize& showSize) void InputConvertNormal::wheelEvent(const QWheelEvent *from, const QSize& frameSize, const QSize& showSize)
@ -72,12 +72,12 @@ void InputConvertNormal::wheelEvent(const QWheelEvent *from, const QSize& frameS
pos.setY(pos.y() * frameSize.height() / showSize.height()); pos.setY(pos.y() * frameSize.height() / showSize.height());
// set data // set data
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_SCROLL); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_SCROLL);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setScrollEventData(QRect(pos.toPoint(), frameSize), hScroll, vScroll); controlMsg->setInjectScrollMsgData(QRect(pos.toPoint(), frameSize), hScroll, vScroll);
sendControlEvent(controlEvent); sendControlMsg(controlMsg);
} }
void InputConvertNormal::keyEvent(const QKeyEvent *from, const QSize& frameSize, const QSize& showSize) void InputConvertNormal::keyEvent(const QKeyEvent *from, const QSize& frameSize, const QSize& showSize)
@ -108,12 +108,12 @@ void InputConvertNormal::keyEvent(const QKeyEvent *from, const QSize& frameSize,
} }
// set data // set data
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_KEYCODE); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_KEYCODE);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setKeycodeEventData(action, keyCode, convertMetastate(from->modifiers())); controlMsg->setInjectKeycodeMsgData(action, keyCode, convertMetastate(from->modifiers()));
sendControlEvent(controlEvent); sendControlMsg(controlMsg);
} }
AndroidMotioneventButtons InputConvertNormal::convertMouseButtons(Qt::MouseButtons buttonState) AndroidMotioneventButtons InputConvertNormal::convertMouseButtons(Qt::MouseButtons buttonState)

View file

@ -4,7 +4,7 @@
#include "receiver.h" #include "receiver.h"
#include "controller.h" #include "controller.h"
#include "deviceevent.h" #include "devicemsg.h"
Receiver::Receiver(Controller* controller) : QObject(controller) Receiver::Receiver(Controller* controller) : QObject(controller)
{ {
@ -26,24 +26,24 @@ void Receiver::onReadyRead()
while (controlSocket->bytesAvailable()) { while (controlSocket->bytesAvailable()) {
QByteArray byteArray = controlSocket->peek(controlSocket->bytesAvailable()); QByteArray byteArray = controlSocket->peek(controlSocket->bytesAvailable());
DeviceEvent deviceEvent; DeviceMsg deviceMsg;
qint32 consume = deviceEvent.deserialize(byteArray); qint32 consume = deviceMsg.deserialize(byteArray);
if (0 >= consume) { if (0 >= consume) {
break; break;
} }
controlSocket->read(consume); controlSocket->read(consume);
processEvent(&deviceEvent); processMsg(&deviceMsg);
} }
} }
void Receiver::processEvent(DeviceEvent *deviceEvent) void Receiver::processMsg(DeviceMsg *deviceMsg)
{ {
switch (deviceEvent->type()) { switch (deviceMsg->type()) {
case DeviceEvent::DET_GET_CLIPBOARD: case DeviceMsg::DMT_GET_CLIPBOARD:
{ {
QClipboard *board = QApplication::clipboard(); QClipboard *board = QApplication::clipboard();
QString text; QString text;
deviceEvent->getClipboardEventData(text); deviceMsg->getClipboardMsgData(text);
board->setText(text); board->setText(text);
break; break;
} }

View file

@ -4,7 +4,7 @@
#include <QPointer> #include <QPointer>
class Controller; class Controller;
class DeviceEvent; class DeviceMsg;
class Receiver : public QObject class Receiver : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -16,7 +16,7 @@ public slots:
void onReadyRead(); void onReadyRead();
protected: protected:
void processEvent(DeviceEvent *deviceEvent); void processMsg(DeviceMsg *deviceMsg);
private: private:
QPointer<Controller> m_controller; QPointer<Controller> m_controller;

View file

@ -20,7 +20,7 @@
#include "ui_videoform.h" #include "ui_videoform.h"
#include "iconhelper.h" #include "iconhelper.h"
#include "toolform.h" #include "toolform.h"
#include "controlevent.h" #include "controlmsg.h"
#include "mousetap/mousetap.h" #include "mousetap/mousetap.h"
VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) : VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) :
@ -341,50 +341,50 @@ void VideoForm::postVolumeDown()
void VideoForm::postTurnOn() void VideoForm::postTurnOn()
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_BACK_OR_SCREEN_ON); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::expandNotificationPanel() void VideoForm::expandNotificationPanel()
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_EXPAND_NOTIFICATION_PANEL); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_EXPAND_NOTIFICATION_PANEL);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::collapseNotificationPanel() void VideoForm::collapseNotificationPanel()
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_COLLAPSE_NOTIFICATION_PANEL); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_COLLAPSE_NOTIFICATION_PANEL);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::requestDeviceClipboard() void VideoForm::requestDeviceClipboard()
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_GET_CLIPBOARD); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_GET_CLIPBOARD);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::setDeviceClipboard() void VideoForm::setDeviceClipboard()
{ {
QClipboard *board = QApplication::clipboard(); QClipboard *board = QApplication::clipboard();
QString text = board->text(); QString text = board->text();
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_SET_CLIPBOARD); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_SET_CLIPBOARD);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setSetClipboardEventData(text); controlMsg->setSetClipboardMsgData(text);
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::clipboardPaste() void VideoForm::clipboardPaste()
@ -396,12 +396,12 @@ void VideoForm::clipboardPaste()
void VideoForm::postTextInput(QString& text) void VideoForm::postTextInput(QString& text)
{ {
ControlEvent* controlEvent = new ControlEvent(ControlEvent::CET_TEXT); ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_TEXT);
if (!controlEvent) { if (!controlMsg) {
return; return;
} }
controlEvent->setTextEventData(text); controlMsg->setInjectTextMsgData(text);
m_inputConvert.sendControlEvent(controlEvent); m_inputConvert.sendControlMsg(controlMsg);
} }
void VideoForm::staysOnTop(bool top) void VideoForm::staysOnTop(bool top)
@ -426,19 +426,19 @@ void VideoForm::postGoHome()
void VideoForm::postKeyCodeClick(AndroidKeycode keycode) void VideoForm::postKeyCodeClick(AndroidKeycode keycode)
{ {
ControlEvent* controlEventDown = new ControlEvent(ControlEvent::CET_KEYCODE); ControlMsg* controlEventDown = new ControlMsg(ControlMsg::CMT_INJECT_KEYCODE);
if (!controlEventDown) { if (!controlEventDown) {
return; return;
} }
controlEventDown->setKeycodeEventData(AKEY_EVENT_ACTION_DOWN, keycode, AMETA_NONE); controlEventDown->setInjectKeycodeMsgData(AKEY_EVENT_ACTION_DOWN, keycode, AMETA_NONE);
m_inputConvert.sendControlEvent(controlEventDown); m_inputConvert.sendControlMsg(controlEventDown);
ControlEvent* controlEventUp = new ControlEvent(ControlEvent::CET_KEYCODE); ControlMsg* controlEventUp = new ControlMsg(ControlMsg::CMT_INJECT_KEYCODE);
if (!controlEventUp) { if (!controlEventUp) {
return; return;
} }
controlEventUp->setKeycodeEventData(AKEY_EVENT_ACTION_UP, keycode, AMETA_NONE); controlEventUp->setInjectKeycodeMsgData(AKEY_EVENT_ACTION_UP, keycode, AMETA_NONE);
m_inputConvert.sendControlEvent(controlEventUp); m_inputConvert.sendControlMsg(controlEventUp);
} }
void VideoForm::mousePressEvent(QMouseEvent *event) void VideoForm::mousePressEvent(QMouseEvent *event)

View file

@ -1,21 +1,21 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
/** /**
* Union of all supported event types, identified by their {@code type}. * Union of all supported msg types, identified by their {@code type}.
*/ */
public final class ControlEvent { public final class ControlMessage {
public static final int TYPE_KEYCODE = 0; public static final int TYPE_INJECT_KEYCODE = 0;
public static final int TYPE_TEXT = 1; public static final int TYPE_INJECT_TEXT = 1;
public static final int TYPE_MOUSE = 2; public static final int TYPE_INJECT_MOUSE = 2;
public static final int TYPE_SCROLL = 3; public static final int TYPE_INJECT_SCROLL = 3;
public static final int TYPE_BACK_OR_SCREEN_ON = 4; public static final int TYPE_BACK_OR_SCREEN_ON = 4;
public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5; public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5;
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6; public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6;
public static final int TYPE_GET_CLIPBOARD = 7; public static final int TYPE_GET_CLIPBOARD = 7;
public static final int TYPE_SET_CLIPBOARD = 8; public static final int TYPE_SET_CLIPBOARD = 8;
public static final int TYPE_TOUCH = 9; public static final int TYPE_INJECT_TOUCH = 9;
private int type; private int type;
@ -29,61 +29,61 @@ public final class ControlEvent {
private int hScroll; private int hScroll;
private int vScroll; private int vScroll;
private ControlEvent() { private ControlMessage() {
} }
public static ControlEvent createKeycodeControlEvent(int action, int keycode, int metaState) { public static ControlMessage createInjectKeycode(int action, int keycode, int metaState) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_KEYCODE; event.type = TYPE_INJECT_KEYCODE;
event.action = action; event.action = action;
event.keycode = keycode; event.keycode = keycode;
event.metaState = metaState; event.metaState = metaState;
return event; return event;
} }
public static ControlEvent createTextControlEvent(String text) { public static ControlMessage createInjectText(String text) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_TEXT; event.type = TYPE_INJECT_TEXT;
event.text = text; event.text = text;
return event; return event;
} }
public static ControlEvent createMotionControlEvent(int action, int buttons, Position position) { public static ControlMessage createInjectMotion(int action, int buttons, Position position) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_MOUSE; event.type = TYPE_INJECT_MOUSE;
event.action = action; event.action = action;
event.buttons = buttons; event.buttons = buttons;
event.position = position; event.position = position;
return event; return event;
} }
public static ControlEvent createMotionTouchEvent(int id, int action, Position position) { public static ControlMessage createInjectMotionTouch(int id, int action, Position position) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_TOUCH; event.type = TYPE_INJECT_TOUCH;
event.action = action; event.action = action;
event.id = id; event.id = id;
event.position = position; event.position = position;
return event; return event;
} }
public static ControlEvent createScrollControlEvent(Position position, int hScroll, int vScroll) { public static ControlMessage createInjectScroll(Position position, int hScroll, int vScroll) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_SCROLL; event.type = TYPE_INJECT_SCROLL;
event.position = position; event.position = position;
event.hScroll = hScroll; event.hScroll = hScroll;
event.vScroll = vScroll; event.vScroll = vScroll;
return event; return event;
} }
public static ControlEvent createSetClipboardControlEvent(String text) { public static ControlMessage createSetClipboard(String text) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = TYPE_SET_CLIPBOARD; event.type = TYPE_SET_CLIPBOARD;
event.text = text; event.text = text;
return event; return event;
} }
public static ControlEvent createSimpleControlEvent(int type) { public static ControlMessage createEmpty(int type) {
ControlEvent event = new ControlEvent(); ControlMessage event = new ControlMessage();
event.type = type; event.type = type;
return event; return event;
} }

View file

@ -6,12 +6,12 @@ import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class ControlEventReader { public class ControlMessageReader {
private static final int KEYCODE_PAYLOAD_LENGTH = 9; private static final int INJECT_KEYCODE_PAYLOAD_LENGTH = 9;
private static final int MOUSE_PAYLOAD_LENGTH = 13; private static final int INJECT_MOUSE_PAYLOAD_LENGTH = 13;
private static final int TOUCH_PAYLOAD_LENGTH = 10; private static final int INJECT_SCROLL_PAYLOAD_LENGTH = 16;
private static final int SCROLL_PAYLOAD_LENGTH = 16; private static final int INJECT_TOUCH_PAYLOAD_LENGTH = 10;
public static final int TEXT_MAX_LENGTH = 300; public static final int TEXT_MAX_LENGTH = 300;
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093; public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
@ -21,7 +21,7 @@ public class ControlEventReader {
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer); private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
private final byte[] textBuffer = new byte[CLIPBOARD_TEXT_MAX_LENGTH]; private final byte[] textBuffer = new byte[CLIPBOARD_TEXT_MAX_LENGTH];
public ControlEventReader() { public ControlMessageReader() {
// invariant: the buffer is always in "get" mode // invariant: the buffer is always in "get" mode
buffer.limit(0); buffer.limit(0);
} }
@ -38,43 +38,43 @@ public class ControlEventReader {
int head = buffer.position(); int head = buffer.position();
int r = input.read(rawBuffer, head, rawBuffer.length - head); int r = input.read(rawBuffer, head, rawBuffer.length - head);
if (r == -1) { if (r == -1) {
throw new EOFException("Event controller socket closed"); throw new EOFException("Controller socket closed");
} }
buffer.position(head + r); buffer.position(head + r);
buffer.flip(); buffer.flip();
} }
public ControlEvent next() { public ControlMessage next() {
if (!buffer.hasRemaining()) { if (!buffer.hasRemaining()) {
return null; return null;
} }
int savedPosition = buffer.position(); int savedPosition = buffer.position();
int type = buffer.get(); int type = buffer.get();
ControlEvent controlEvent; ControlMessage controlEvent;
switch (type) { switch (type) {
case ControlEvent.TYPE_KEYCODE: case ControlMessage.TYPE_INJECT_KEYCODE:
controlEvent = parseKeycodeControlEvent(); controlEvent = parseInjectKeycode();
break; break;
case ControlEvent.TYPE_TEXT: case ControlMessage.TYPE_INJECT_TEXT:
controlEvent = parseTextControlEvent(); controlEvent = parseInjectText();
break; break;
case ControlEvent.TYPE_MOUSE: case ControlMessage.TYPE_INJECT_MOUSE:
controlEvent = parseMouseControlEvent(); controlEvent = parseInjectMouse();
break; break;
case ControlEvent.TYPE_TOUCH: case ControlMessage.TYPE_INJECT_TOUCH:
controlEvent = parseMouseTouchEvent(); controlEvent = parseInjectMouseTouch();
break; break;
case ControlEvent.TYPE_SCROLL: case ControlMessage.TYPE_INJECT_SCROLL:
controlEvent = parseScrollControlEvent(); controlEvent = parseInjectScroll();
break; break;
case ControlEvent.TYPE_SET_CLIPBOARD: case ControlMessage.TYPE_SET_CLIPBOARD:
controlEvent = parseSetClipboardEvent(); controlEvent = parseSetClipboard();
break; break;
case ControlEvent.TYPE_BACK_OR_SCREEN_ON: case ControlMessage.TYPE_BACK_OR_SCREEN_ON:
case ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL: case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
case ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL: case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
case ControlEvent.TYPE_GET_CLIPBOARD: case ControlMessage.TYPE_GET_CLIPBOARD:
controlEvent = ControlEvent.createSimpleControlEvent(type); controlEvent = ControlMessage.createEmpty(type);
break; break;
default: default:
Ln.w("Unknown event type: " + type); Ln.w("Unknown event type: " + type);
@ -89,14 +89,14 @@ public class ControlEventReader {
return controlEvent; return controlEvent;
} }
private ControlEvent parseKeycodeControlEvent() { private ControlMessage parseInjectKeycode() {
if (buffer.remaining() < KEYCODE_PAYLOAD_LENGTH) { if (buffer.remaining() < INJECT_KEYCODE_PAYLOAD_LENGTH) {
return null; return null;
} }
int action = toUnsigned(buffer.get()); int action = toUnsigned(buffer.get());
int keycode = buffer.getInt(); int keycode = buffer.getInt();
int metaState = buffer.getInt(); int metaState = buffer.getInt();
return ControlEvent.createKeycodeControlEvent(action, keycode, metaState); return ControlMessage.createInjectKeycode(action, keycode, metaState);
} }
private String parseString() { private String parseString() {
@ -111,50 +111,50 @@ public class ControlEventReader {
return new String(textBuffer, 0, len, StandardCharsets.UTF_8); return new String(textBuffer, 0, len, StandardCharsets.UTF_8);
} }
private ControlEvent parseTextControlEvent() { private ControlMessage parseInjectText() {
String text = parseString(); String text = parseString();
if (text == null) { if (text == null) {
return null; return null;
} }
return ControlEvent.createTextControlEvent(text); return ControlMessage.createInjectText(text);
} }
private ControlEvent parseMouseControlEvent() { private ControlMessage parseInjectMouse() {
if (buffer.remaining() < MOUSE_PAYLOAD_LENGTH) { if (buffer.remaining() < INJECT_MOUSE_PAYLOAD_LENGTH) {
return null; return null;
} }
int action = toUnsigned(buffer.get()); int action = toUnsigned(buffer.get());
int buttons = buffer.getInt(); int buttons = buffer.getInt();
Position position = readPosition(buffer); Position position = readPosition(buffer);
return ControlEvent.createMotionControlEvent(action, buttons, position); return ControlMessage.createInjectMotion(action, buttons, position);
} }
private ControlEvent parseMouseTouchEvent() { private ControlMessage parseInjectMouseTouch() {
if (buffer.remaining() < TOUCH_PAYLOAD_LENGTH) { if (buffer.remaining() < INJECT_TOUCH_PAYLOAD_LENGTH) {
return null; return null;
} }
int id = toUnsigned(buffer.get()); int id = toUnsigned(buffer.get());
int action = toUnsigned(buffer.get()); int action = toUnsigned(buffer.get());
Position position = readPosition(buffer); Position position = readPosition(buffer);
return ControlEvent.createMotionTouchEvent(id, action, position); return ControlMessage.createInjectMotionTouch(id, action, position);
} }
private ControlEvent parseScrollControlEvent() { private ControlMessage parseInjectScroll() {
if (buffer.remaining() < SCROLL_PAYLOAD_LENGTH) { if (buffer.remaining() < INJECT_SCROLL_PAYLOAD_LENGTH) {
return null; return null;
} }
Position position = readPosition(buffer); Position position = readPosition(buffer);
int hScroll = buffer.getInt(); int hScroll = buffer.getInt();
int vScroll = buffer.getInt(); int vScroll = buffer.getInt();
return ControlEvent.createScrollControlEvent(position, hScroll, vScroll); return ControlMessage.createInjectScroll(position, hScroll, vScroll);
} }
private ControlEvent parseSetClipboardEvent() { private ControlMessage parseSetClipboard() {
String text = parseString(); String text = parseString();
if (text == null) { if (text == null) {
return null; return null;
} }
return ControlEvent.createSetClipboardControlEvent(text); return ControlMessage.createSetClipboard(text);
} }
private static Position readPosition(ByteBuffer buffer) { private static Position readPosition(ByteBuffer buffer) {

View file

@ -13,11 +13,11 @@ import android.view.MotionEvent;
import java.io.IOException; import java.io.IOException;
import java.util.Vector; import java.util.Vector;
public class EventController { public class Controller {
private final Device device; private final Device device;
private final DesktopConnection connection; private final DesktopConnection connection;
private final EventSender sender; private final DeviceMessageSender sender;
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
@ -25,10 +25,10 @@ public class EventController {
private Vector<MotionEvent.PointerProperties> pointerProperties = new Vector<MotionEvent.PointerProperties>(); private Vector<MotionEvent.PointerProperties> pointerProperties = new Vector<MotionEvent.PointerProperties>();
private Vector<MotionEvent.PointerCoords> pointerCoords = new Vector<MotionEvent.PointerCoords>(); private Vector<MotionEvent.PointerCoords> pointerCoords = new Vector<MotionEvent.PointerCoords>();
public EventController(Device device, DesktopConnection connection) { public Controller(Device device, DesktopConnection connection) {
this.device = device; this.device = device;
this.connection = connection; this.connection = connection;
sender = new EventSender(connection); sender = new DeviceMessageSender(connection);
} }
private int getPointer(int id) { private int getPointer(int id) {
@ -98,7 +98,7 @@ public class EventController {
} }
} }
public EventSender getSender() { public DeviceMessageSender getSender() {
return sender; return sender;
} }
@ -112,38 +112,38 @@ public class EventController {
} }
private void handleEvent() throws IOException { private void handleEvent() throws IOException {
ControlEvent controlEvent = connection.receiveControlEvent(); ControlMessage msg = connection.receiveControlMessage();
switch (controlEvent.getType()) { switch (msg.getType()) {
case ControlEvent.TYPE_KEYCODE: case ControlMessage.TYPE_INJECT_KEYCODE:
injectKeycode(controlEvent.getAction(), controlEvent.getKeycode(), controlEvent.getMetaState()); injectKeycode(msg.getAction(), msg.getKeycode(), msg.getMetaState());
break; break;
case ControlEvent.TYPE_TEXT: case ControlMessage.TYPE_INJECT_TEXT:
injectText(controlEvent.getText()); injectText(msg.getText());
break; break;
case ControlEvent.TYPE_MOUSE: case ControlMessage.TYPE_INJECT_MOUSE:
injectMouse(controlEvent.getAction(), controlEvent.getButtons(), controlEvent.getPosition()); injectMouse(msg.getAction(), msg.getButtons(), msg.getPosition());
break; break;
case ControlEvent.TYPE_TOUCH: case ControlMessage.TYPE_INJECT_TOUCH:
injectTouch(controlEvent.getId(), controlEvent.getAction(), controlEvent.getPosition()); injectTouch(msg.getId(), msg.getAction(), msg.getPosition());
break; break;
case ControlEvent.TYPE_SCROLL: case ControlMessage.TYPE_INJECT_SCROLL:
injectScroll(controlEvent.getPosition(), controlEvent.getHScroll(), controlEvent.getVScroll()); injectScroll(msg.getPosition(), msg.getHScroll(), msg.getVScroll());
break; break;
case ControlEvent.TYPE_BACK_OR_SCREEN_ON: case ControlMessage.TYPE_BACK_OR_SCREEN_ON:
pressBackOrTurnScreenOn(); pressBackOrTurnScreenOn();
break; break;
case ControlEvent.TYPE_EXPAND_NOTIFICATION_PANEL: case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
device.expandNotificationPanel(); device.expandNotificationPanel();
break; break;
case ControlEvent.TYPE_COLLAPSE_NOTIFICATION_PANEL: case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
device.collapsePanels(); device.collapsePanels();
break; break;
case ControlEvent.TYPE_GET_CLIPBOARD: case ControlMessage.TYPE_GET_CLIPBOARD:
String clipboardText = device.getClipboardText(); String clipboardText = device.getClipboardText();
sender.pushClipboardText(clipboardText); sender.pushClipboardText(clipboardText);
break; break;
case ControlEvent.TYPE_SET_CLIPBOARD: case ControlMessage.TYPE_SET_CLIPBOARD:
device.setClipboardText(controlEvent.getText()); device.setClipboardText(msg.getText());
break; break;
default: default:
// do nothing // do nothing

View file

@ -25,8 +25,8 @@ public final class DesktopConnection implements Closeable {
private final OutputStream controlOutputStream; private final OutputStream controlOutputStream;
private final ControlEventReader reader = new ControlEventReader(); private final ControlMessageReader reader = new ControlMessageReader();
private final DeviceEventWriter writer = new DeviceEventWriter(); private final DeviceMessageWriter writer = new DeviceMessageWriter();
private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException { private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException {
this.videoSocket = videoSocket; this.videoSocket = videoSocket;
@ -105,16 +105,16 @@ public final class DesktopConnection implements Closeable {
return videoFd; return videoFd;
} }
public ControlEvent receiveControlEvent() throws IOException { public ControlMessage receiveControlMessage() throws IOException {
ControlEvent event = reader.next(); ControlMessage msg = reader.next();
while (event == null) { while (msg == null) {
reader.readFrom(controlInputStream); reader.readFrom(controlInputStream);
event = reader.next(); msg = reader.next();
} }
return event; return msg;
} }
public void sendDeviceEvent(DeviceEvent event) throws IOException { public void sendDeviceMessage(DeviceMessage msg) throws IOException {
writer.writeTo(event, controlOutputStream); writer.writeTo(msg, controlOutputStream);
} }
} }

View file

@ -1,27 +0,0 @@
package com.genymobile.scrcpy;
public final class DeviceEvent {
public static final int TYPE_GET_CLIPBOARD = 0;
private int type;
private String text;
private DeviceEvent() {
}
public static DeviceEvent createGetClipboardEvent(String text) {
DeviceEvent event = new DeviceEvent();
event.type = TYPE_GET_CLIPBOARD;
event.text = text;
return event;
}
public int getType() {
return type;
}
public String getText() {
return text;
}
}

View file

@ -0,0 +1,27 @@
package com.genymobile.scrcpy;
public final class DeviceMessage {
public static final int TYPE_CLIPBOARD = 0;
private int type;
private String text;
private DeviceMessage() {
}
public static DeviceMessage createClipboard(String text) {
DeviceMessage event = new DeviceMessage();
event.type = TYPE_CLIPBOARD;
event.text = text;
return event;
}
public int getType() {
return type;
}
public String getText() {
return text;
}
}

View file

@ -2,13 +2,13 @@ package com.genymobile.scrcpy;
import java.io.IOException; import java.io.IOException;
public final class EventSender { public final class DeviceMessageSender {
private final DesktopConnection connection; private final DesktopConnection connection;
private String clipboardText; private String clipboardText;
public EventSender(DesktopConnection connection) { public DeviceMessageSender(DesktopConnection connection) {
this.connection = connection; this.connection = connection;
} }
@ -27,8 +27,8 @@ public final class EventSender {
text = clipboardText; text = clipboardText;
clipboardText = null; clipboardText = null;
} }
DeviceEvent event = DeviceEvent.createGetClipboardEvent(text); DeviceMessage msg = DeviceMessage.createClipboard(text);
connection.sendDeviceEvent(event); connection.sendDeviceMessage(msg);
} }
} }
} }

View file

@ -5,7 +5,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class DeviceEventWriter { public class DeviceMessageWriter {
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093; public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093;
private static final int MAX_EVENT_SIZE = CLIPBOARD_TEXT_MAX_LENGTH + 3; private static final int MAX_EVENT_SIZE = CLIPBOARD_TEXT_MAX_LENGTH + 3;
@ -14,12 +14,12 @@ public class DeviceEventWriter {
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer); private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
@SuppressWarnings("checkstyle:MagicNumber") @SuppressWarnings("checkstyle:MagicNumber")
public void writeTo(DeviceEvent event, OutputStream output) throws IOException { public void writeTo(DeviceMessage msg, OutputStream output) throws IOException {
buffer.clear(); buffer.clear();
buffer.put((byte) DeviceEvent.TYPE_GET_CLIPBOARD); buffer.put((byte) DeviceMessage.TYPE_CLIPBOARD);
switch (event.getType()) { switch (msg.getType()) {
case DeviceEvent.TYPE_GET_CLIPBOARD: case DeviceMessage.TYPE_CLIPBOARD:
String text = event.getText(); String text = msg.getText();
byte[] raw = text.getBytes(StandardCharsets.UTF_8); byte[] raw = text.getBytes(StandardCharsets.UTF_8);
int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH); int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH);
buffer.putShort((short) len); buffer.putShort((short) len);
@ -27,7 +27,7 @@ public class DeviceEventWriter {
output.write(rawBuffer, 0, buffer.position()); output.write(rawBuffer, 0, buffer.position());
break; break;
default: default:
Ln.w("Unknown device event: " + event.getType()); Ln.w("Unknown device msg: " + msg.getType());
break; break;
} }
} }

View file

@ -20,11 +20,11 @@ public final class Server {
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) { try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate()); ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate());
EventController controller = new EventController(device, connection); Controller controller = new Controller(device, connection);
// asynchronous // asynchronous
startEventController(controller); startController(controller);
startEventSender(controller.getSender()); startDeviceMessageSender(controller.getSender());
try { try {
// synchronous // synchronous
@ -36,7 +36,7 @@ public final class Server {
} }
} }
private static void startEventController(final EventController controller) { private static void startController(final Controller controller) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -44,13 +44,13 @@ public final class Server {
controller.control(); controller.control();
} catch (IOException e) { } catch (IOException e) {
// this is expected on close // this is expected on close
Ln.d("Event controller stopped"); Ln.d("Controller stopped");
} }
} }
}).start(); }).start();
} }
private static void startEventSender(final EventSender sender) { private static void startDeviceMessageSender(final DeviceMessageSender sender) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -58,7 +58,7 @@ public final class Server {
sender.loop(); sender.loop();
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
// this is expected on close // this is expected on close
Ln.d("Event sender stopped"); Ln.d("Devide message sender stopped");
} }
} }
}).start(); }).start();

View file

@ -1,173 +0,0 @@
package com.genymobile.scrcpy;
import android.view.KeyEvent;
import android.view.MotionEvent;
import org.junit.Assert;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class ControlEventReaderTest {
@Test
public void testParseKeycodeEvent() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(KeyEvent.ACTION_UP);
dos.writeInt(KeyEvent.KEYCODE_ENTER);
dos.writeInt(KeyEvent.META_CTRL_ON);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
}
@Test
public void testParseTextEvent() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_TEXT);
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
dos.writeShort(text.length);
dos.write(text);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
Assert.assertEquals("testé", event.getText());
}
@Test
public void testParseLongTextEvent() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_TEXT);
byte[] text = new byte[ControlEventReader.TEXT_MAX_LENGTH];
Arrays.fill(text, (byte) 'a');
dos.writeShort(text.length);
dos.write(text);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
Assert.assertEquals(new String(text, StandardCharsets.US_ASCII), event.getText());
}
@Test
public void testParseMouseEvent() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(MotionEvent.ACTION_DOWN);
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
dos.writeInt(KeyEvent.META_CTRL_ON);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
}
@Test
public void testMultiEvents() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(KeyEvent.ACTION_UP);
dos.writeInt(KeyEvent.KEYCODE_ENTER);
dos.writeInt(KeyEvent.META_CTRL_ON);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(MotionEvent.ACTION_DOWN);
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
dos.writeInt(KeyEvent.META_CTRL_ON);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
}
@Test
public void testPartialEvents() throws IOException {
ControlEventReader reader = new ControlEventReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(KeyEvent.ACTION_UP);
dos.writeInt(KeyEvent.KEYCODE_ENTER);
dos.writeInt(KeyEvent.META_CTRL_ON);
dos.writeByte(ControlEvent.TYPE_KEYCODE);
dos.writeByte(MotionEvent.ACTION_DOWN);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlEvent event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
event = reader.next();
Assert.assertNull(event); // the event is not complete
bos.reset();
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
dos.writeInt(KeyEvent.META_CTRL_ON);
packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
// the event is now complete
event = reader.next();
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
}
}