2
// libavg - Media Playback Engine.
3
// Copyright (C) 2003-2008 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 "LibMTDevEventSource.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>
43
#include <mtdev-mapping.h>
50
LibMTDevEventSource::LibMTDevEventSource()
56
LibMTDevEventSource::~LibMTDevEventSource()
59
mtdev_close(m_pMTDevice);
64
void LibMTDevEventSource::start()
66
string sDevice("/dev/input/event3");
67
getEnv("AVG_LINUX_MULTITOUCH_DEVICE", sDevice);
68
m_DeviceFD = ::open(sDevice.c_str(), O_RDONLY | O_NONBLOCK);
69
if (m_DeviceFD == -1) {
70
throw Exception(AVG_ERR_MT_INIT,
71
string("Linux multitouch event source: Could not open device file '")+
72
sDevice+"'. "+strerror(errno)+".");
74
m_pMTDevice = new mtdev;
75
int err = mtdev_open(m_pMTDevice, m_DeviceFD);
77
throw Exception(AVG_ERR_MT_INIT,
78
string("Linux multitouch event source: Could not open mtdev '")+
79
sDevice+"'. "+strerror(errno)+".");
81
input_absinfo* pAbsInfo;
82
pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_X]);
83
m_Dimensions.tl.x = pAbsInfo->minimum;
84
m_Dimensions.br.x = pAbsInfo->maximum;
85
pAbsInfo = &(m_pMTDevice->caps.abs[MTDEV_POSITION_Y]);
86
m_Dimensions.tl.y = pAbsInfo->minimum;
87
m_Dimensions.br.y = pAbsInfo->maximum;
89
MultitouchEventSource::start();
90
AVG_TRACE(Logger::CONFIG, "Linux MTDev Multitouch event source created.");
93
std::vector<EventPtr> LibMTDevEventSource::pollEvents()
95
struct input_event events[64];
96
int numEvents = mtdev_get(m_pMTDevice, m_DeviceFD, events, 64);
99
cerr << "---- read ----" << endl;
102
static int curSlot = 0;
105
for (int i = 0; i < numEvents; ++i) {
106
input_event event = events[i];
107
if (event.type == EV_ABS && event.code == ABS_MT_SLOT) {
108
// cerr << ">> slot " << event.value << endl;
109
curSlot = event.value;
112
switch (event.code) {
113
case ABS_MT_TRACKING_ID:
114
// cerr << ">> ABS_MT_TRACKING_ID: " << event.value << endl;
115
pTouch = &(m_Slots[curSlot]);
116
if (event.value == -1) {
117
TouchStatusPtr pTouchStatus = getTouchStatus(pTouch->id);
118
// cerr << "up " << pTouch->id << endl;
120
// cerr << " --> remove" << endl;
121
TouchEventPtr pOldEvent = pTouchStatus->getLastEvent();
122
TouchEventPtr pUpEvent =
123
boost::dynamic_pointer_cast<TouchEvent>(
124
pOldEvent->cloneAs(Event::CURSORUP));
125
pTouchStatus->updateEvent(pUpEvent);
129
pTouch->id = event.value;
132
case ABS_MT_POSITION_X:
133
// cerr << ">> ABS_MT_POSITION_X: " << event.value << endl;
134
pTouch = &(m_Slots[curSlot]);
135
pTouch->pos.x = event.value;
137
case ABS_MT_POSITION_Y:
138
// cerr << ">> ABS_MT_POSITION_Y: " << event.value << endl;
139
pTouch = &(m_Slots[curSlot]);
140
pTouch->pos.y = event.value;
145
// cerr << ">> new id: " << curSlot << endl;
146
changedIDs.insert(curSlot);
149
for (set<int>::iterator it = changedIDs.begin(); it != changedIDs.end(); ++it) {
150
map<int, TouchData>::iterator it2 = m_Slots.find(*it);
151
if (it2 != m_Slots.end()) {
152
const TouchData& touch = it2->second;
153
// cerr << "slot: " << *it << ", id: " << touch.id << ", pos: " << touch.pos
155
// AVG_ASSERT(touch.pos.x != 0);
156
if (touch.id != -1) {
157
TouchStatusPtr pTouchStatus = getTouchStatus(touch.id);
159
// cerr << "down" << endl;
162
TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSORDOWN,
164
addTouchStatus((long)touch.id, pEvent);
166
// cerr << "move" << endl;
168
TouchEventPtr pEvent = createEvent(0, Event::CURSORMOTION, touch.pos);
169
pTouchStatus->updateEvent(pEvent);
174
return MultitouchEventSource::pollEvents();
177
TouchEventPtr LibMTDevEventSource::createEvent(int id, Event::Type type, IntPoint pos)
179
DPoint size = getWindowSize();
180
DPoint normPos = DPoint(double(pos.x-m_Dimensions.tl.x)/m_Dimensions.width(),
181
double(pos.y-m_Dimensions.tl.y)/m_Dimensions.height());
182
IntPoint screenPos(int(normPos.x*size.x+0.5), int(normPos.y*size.y+0.5));
183
return TouchEventPtr(new TouchEvent(id, type, screenPos, Event::TOUCH, DPoint(0,0),
184
0, 20, 1, DPoint(5,0), DPoint(0,5)));