mirror of
https://invent.kde.org/network/falkon.git
synced 2024-09-22 18:22:10 +02:00
171 lines
4.7 KiB
C++
171 lines
4.7 KiB
C++
|
/*
|
||
|
* This file is part of the mouse gesture package.
|
||
|
* Copyright (C) 2006 Johan Thelin <e8johan@gmail.com>
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or
|
||
|
* without modification, are permitted provided that the
|
||
|
* following conditions are met:
|
||
|
*
|
||
|
* - Redistributions of source code must retain the above
|
||
|
* copyright notice, this list of conditions and the
|
||
|
* following disclaimer.
|
||
|
* - Redistributions in binary form must reproduce the
|
||
|
* above copyright notice, this list of conditions and
|
||
|
* the following disclaimer in the documentation and/or
|
||
|
* other materials provided with the distribution.
|
||
|
* - The names of its contributors may be used to endorse
|
||
|
* or promote products derived from this software without
|
||
|
* specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||
|
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "adv_recognizer.h"
|
||
|
#include <algorithm>
|
||
|
|
||
|
using namespace Gesture;
|
||
|
|
||
|
RealTimeMouseGestureRecognizer::RealTimeMouseGestureRecognizer(int minimumMovement, double minimumMatch, bool allowDiagonals)
|
||
|
: minimumMatch(minimumMatch), allowDiagonals(allowDiagonals)
|
||
|
{
|
||
|
minimumMovement2 = minimumMovement * minimumMovement;
|
||
|
|
||
|
directions.resize(64);
|
||
|
lastX = 0;
|
||
|
lastY = 0;
|
||
|
lastDirection = NoMatch;
|
||
|
}
|
||
|
|
||
|
RealTimeMouseGestureRecognizer::~RealTimeMouseGestureRecognizer()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
const Direction dirsD[8] = {
|
||
|
Down,
|
||
|
Up,
|
||
|
Right,
|
||
|
Left,
|
||
|
DownRight,
|
||
|
DownLeft,
|
||
|
UpLeft,
|
||
|
UpRight
|
||
|
};
|
||
|
|
||
|
void RealTimeMouseGestureRecognizer::addPoint(int x, int y)
|
||
|
{
|
||
|
int dx, dy;
|
||
|
|
||
|
dx = x - lastX;
|
||
|
dy = y - lastY;
|
||
|
|
||
|
if (dx * dx + dy * dy < minimumMovement2) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Direction direction;
|
||
|
|
||
|
const int _directions[8][2] = {
|
||
|
{0, 15}, //down 0
|
||
|
{0, -15}, //up 1
|
||
|
{15, 0}, //right 2
|
||
|
{ -15, 0}, //left 3
|
||
|
{10, 10}, //down right 4
|
||
|
{ -10, 10}, //down left 5
|
||
|
{ -10, -10}, //up left 6
|
||
|
{10, -10}//up right 7
|
||
|
};
|
||
|
int maxValue = 0;
|
||
|
int maxIndex = -1;
|
||
|
|
||
|
for (int i = 0; i < (allowDiagonals ? 8 : 4); i++) {
|
||
|
int value = dx * _directions[i][0] + dy * _directions[i][1];
|
||
|
if (value > maxValue) {
|
||
|
maxValue = value;
|
||
|
maxIndex = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
direction = dirsD[maxIndex];
|
||
|
|
||
|
if (direction != lastDirection) {
|
||
|
directions.push_back(direction);
|
||
|
recognizeGesture();
|
||
|
}
|
||
|
|
||
|
|
||
|
lastX = x;
|
||
|
lastY = y;
|
||
|
lastDirection = direction;
|
||
|
}
|
||
|
|
||
|
struct DirectionSort {
|
||
|
bool operator()(GestureDefinition a, GestureDefinition b) {
|
||
|
return a.directions.size() > b.directions.size();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void RealTimeMouseGestureRecognizer::addGestureDefinition(const GestureDefinition &gesture)
|
||
|
{
|
||
|
gestures.push_back(gesture);
|
||
|
std::sort(gestures.begin(), gestures.end(), DirectionSort());
|
||
|
}
|
||
|
|
||
|
void RealTimeMouseGestureRecognizer::clearGestureDefinitions()
|
||
|
{
|
||
|
gestures.clear();
|
||
|
}
|
||
|
|
||
|
void RealTimeMouseGestureRecognizer::recognizeGesture()
|
||
|
{
|
||
|
int first = gestures.size();
|
||
|
|
||
|
for (GestureList::const_iterator gi = gestures.begin(); gi != gestures.end(); ++gi) {
|
||
|
int readIndex = directions.getReadPointer();
|
||
|
bool match = true;
|
||
|
|
||
|
try {
|
||
|
for (DirectionList::const_iterator di = gi->directions.begin(); di != gi->directions.end() && match; ++di) {
|
||
|
Direction d = directions.pop();
|
||
|
if (*di != d) {
|
||
|
match = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (match) {
|
||
|
if (gi->callbackClass) {
|
||
|
gi->callbackClass->callback();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
else {
|
||
|
first--;
|
||
|
directions.setReadPointerTo(readIndex);
|
||
|
}
|
||
|
}
|
||
|
catch (const std::exception &e) {
|
||
|
directions.setReadPointerTo(readIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (first == 0) {
|
||
|
directions.pop();
|
||
|
}
|
||
|
}
|