summaryrefslogtreecommitdiffstats
path: root/krdc/vnc/pointerlatencyometer.h
blob: 559536b224bfb0d414f2d3feac92ad4380e821de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/***************************************************************************
                  pointerlatencyometer.h  - measuring pointer latency
                             -------------------
    begin                : Wed Jun 30 12:04:44 CET 2002
    copyright            : (C) 2002-2003 by Tim Jansen
    email                : [email protected]
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qdatetime.h>
#include <kdebug.h>

struct PointerState {
	int x, y;
	QTime timestamp;
};

class PointerLatencyOMeter {
private:
	enum { stateCapacity = 30, maximumLatency = 1000 };
	PointerState states[stateCapacity];
	int firstState, stateNum;
	float last3Latency, last20Latency;

public:
	PointerLatencyOMeter() :
		firstState(0),
		stateNum(0),
		last3Latency(125),
		last20Latency(25) {
	}
	
	// registers a client pointer state
	void registerPointerState(int x, int y) {
		if (stateNum == stateCapacity)
			stateNum--;
		if (firstState == 0)
			firstState = stateCapacity-1;
		else
			firstState--;
		states[firstState].x = x;
		states[firstState].y = y;
		states[firstState].timestamp.start();
		stateNum++;
	}

	/* Returns true if pointer should be visible */
	bool registerLatency(int msecs) {
		last3Latency = ((last3Latency * 2.0) + msecs) / 3.0;
		last20Latency = ((last20Latency * 19.0) + msecs) / 20.0;

		if (msecs >= maximumLatency) 
			return true;
		if (last3Latency > (1000/4))
			return true;
		return last20Latency > (1000/12);
	}

	// Called with server-side coordinates.
	// Returns true if pointer should be visible
	bool handlePointerEvent(int x, int y) {
		for (int i = stateNum-1; i >= 0; i--) {
			int idx = (i+firstState) % stateCapacity;
			if ((states[idx].x != x) ||
			    (states[idx].y != y)) 
				continue;
			
			stateNum = i;
			int l = states[idx].timestamp.elapsed();
			return registerLatency((l > maximumLatency) ? maximumLatency : l);
		}
		return true;
	}

};