2
// libavg - Media Playback Engine.
3
// Copyright (C) 2003-2011 Ulrich von Zadow
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2 of the License, or (at your option) any later version.
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
// Current versions can be found at www.libavg.de
22
#include "LibMTDevInputDevice.h"
24
#include "TouchEvent.h"
27
#include "TouchStatus.h"
29
#include "../base/Logger.h"
30
#include "../base/Point.h"
31
#include "../base/ObjectCounter.h"
32
#include "../base/Exception.h"
33
#include "../base/OSHelper.h"
35
#include <linux/input.h>
37
#include <sys/types.h>
42
#include <mtdev-mapping.h>
49
LibMTDevInputDevice::LibMTDevInputDevice()
55
LibMTDevInputDevice::~LibMTDevInputDevice()
58
mtdev_close(m_pMTDevice);
63
void LibMTDevInputDevice::start()
65
string sDevice("/dev/input/event3");
66
getEnv("AVG_LINUX_MULTITOUCH_DEVICE", sDevice);
67
m_DeviceFD = ::open(sDevice.c_str(), O_RDONLY | O_NONBLOCK);
68
if (m_DeviceFD == -1) {
69
throw Exception(AVG_ERR_MT_INIT,
70
string("Linux multitouch event source: Could not open device file '")+
71
sDevice+"'. "+strerror(errno)+".");
73
m_pMTDevice = new mtdev;
74
int err = mtdev_open(m_pMTDevice, m_DeviceFD);
76
throw Exception(AVG_ERR_MT_INIT,
77
string("Linux multitouch event source: Could not open mtdev '")+
78
sDevice+"'. "+strerror(errno)+".");
80
input_absinfo* pAbsInfo;
81
pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_X]);
82
m_Dimensions.tl.x = pAbsInfo->minimum;
83
m_Dimensions.br.x = pAbsInfo->maximum;
84
pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_Y]);
85
m_Dimensions.tl.y = pAbsInfo->minimum;
86
m_Dimensions.br.y = pAbsInfo->maximum;
88
MultitouchInputDevice::start();
89
AVG_TRACE(Logger::CONFIG, "Linux MTDev Multitouch event source created.");
92
std::vector<EventPtr> LibMTDevInputDevice::pollEvents()
94
struct input_event event;
95
static int curSlot = 0;
98
while (mtdev_get(m_pMTDevice, m_DeviceFD, &event, 1) > 0) {
99
if (event.type == EV_SYN && event.code == SYN_REPORT) {
100
// cerr << ">> SYN_REPORT" << endl;
101
processEvents(changedIDs);
103
} else if (event.type == EV_ABS && event.code == ABS_MT_SLOT) {
104
// cerr << ">> slot " << event.value << endl;
105
curSlot = event.value;
108
switch (event.code) {
109
case ABS_MT_TRACKING_ID:
110
// cerr << ">> ABS_MT_TRACKING_ID: " << event.value << endl;
111
pTouch = &(m_Slots[curSlot]);
112
if (event.value == -1) {
113
TouchStatusPtr pTouchStatus = getTouchStatus(pTouch->id);
114
// cerr << "up " << pTouch->id << endl;
116
// cerr << " --> remove" << endl;
117
TouchEventPtr pOldEvent = pTouchStatus->getLastEvent();
118
TouchEventPtr pUpEvent =
119
boost::dynamic_pointer_cast<TouchEvent>(
120
pOldEvent->cloneAs(Event::CURSORUP));
121
pTouchStatus->pushEvent(pUpEvent);
122
removeTouchStatus(pTouch->id);
126
pTouch->id = event.value;
127
changedIDs.insert(curSlot);
130
case ABS_MT_POSITION_X:
131
// cerr << ">> ABS_MT_POSITION_X: " << event.value << endl;
132
pTouch = &(m_Slots[curSlot]);
133
pTouch->pos.x = event.value;
134
changedIDs.insert(curSlot);
136
case ABS_MT_POSITION_Y:
137
// cerr << ">> ABS_MT_POSITION_Y: " << event.value << endl;
138
pTouch = &(m_Slots[curSlot]);
139
pTouch->pos.y = event.value;
140
changedIDs.insert(curSlot);
148
return MultitouchInputDevice::pollEvents();
151
void LibMTDevInputDevice::processEvents(const set<int>& changedIDs)
153
for (set<int>::iterator it = changedIDs.begin(); it != changedIDs.end(); ++it) {
154
map<int, TouchData>::iterator it2 = m_Slots.find(*it);
155
if (it2 != m_Slots.end()) {
156
const TouchData& touch = it2->second;
157
// cerr << "slot: " << *it << ", id: " << touch.id << ", pos: " << touch.pos
159
// AVG_ASSERT(touch.pos.x != 0);
160
if (touch.id != -1) {
161
TouchStatusPtr pTouchStatus = getTouchStatus(touch.id);
165
TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSORDOWN,
167
// cerr << "down <" << touch.id << "> --> [" << m_LastID << "]" << endl;
168
addTouchStatus((long)touch.id, pEvent);
170
// cerr << "move <" << touch.id << "> --> " << touch.pos << endl;
172
TouchEventPtr pEvent = createEvent(0, Event::CURSORMOTION, touch.pos);
173
pTouchStatus->pushEvent(pEvent);
180
TouchEventPtr LibMTDevInputDevice::createEvent(int id, Event::Type type, IntPoint pos)
182
DPoint size = getWindowSize();
183
DPoint normPos = DPoint(double(pos.x-m_Dimensions.tl.x)/m_Dimensions.width(),
184
double(pos.y-m_Dimensions.tl.y)/m_Dimensions.height());
185
IntPoint screenPos(int(normPos.x*size.x+0.5), int(normPos.y*size.y+0.5));
186
return TouchEventPtr(new TouchEvent(id, type, screenPos, Event::TOUCH));