mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-07-29 12:18:39 +00:00
update:event改为message更恰当
This commit is contained in:
parent
e010199752
commit
b92199dea3
28 changed files with 560 additions and 733 deletions
|
@ -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;
|
|
||||||
}
|
|
|
@ -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_DOWN,AMOTION_EVENT_ACTION_UP,AMOTION_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
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
136
QtScrcpy/inputcontrol/controlmsg.cpp
Normal file
136
QtScrcpy/inputcontrol/controlmsg.cpp
Normal 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;
|
||||||
|
}
|
90
QtScrcpy/inputcontrol/controlmsg.h
Normal file
90
QtScrcpy/inputcontrol/controlmsg.h
Normal 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_DOWN,AMOTION_EVENT_ACTION_UP,AMOTION_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
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
69
QtScrcpy/inputcontrol/devicemsg.cpp
Normal file
69
QtScrcpy/inputcontrol/devicemsg.cpp
Normal 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;
|
||||||
|
}
|
42
QtScrcpy/inputcontrol/devicemsg.h
Normal file
42
QtScrcpy/inputcontrol/devicemsg.h
Normal 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
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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) {
|
|
@ -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
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue