summaryrefslogtreecommitdiffstats
path: root/src/client/vnc/vncthread.h
blob: 17e991db8d8878cc4cc434266240f0f18432ccf5 (plain) (blame)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
 # Freiburg
 #
 # This program is free software distributed under the GPL version 2.
 # See http://openslx.org/COPYING
 #
 # If you have any feedback please consult http://openslx.org/feedback and
 # send your suggestions, praise, or complaints to feedback@openslx.org
 #
 # General information about OpenSLX can be found at http://openslx.org/
 */

#ifndef VNCCLIENTTHREAD_H_
#define VNCCLIENTTHREAD_H_

#include <QtCore>
#include <QImage>
#include <QThread>

class QPainter;

extern "C"
{
#include <rfb/rfbclient.h>
}

/**
 * Event classes. Not my code. Might be useful to implement remote assistance via VNC later.
 * Code might come from the KDE VNC client.
 */
class SomeEvent
{
public:
	virtual ~SomeEvent(){}
	virtual void fire(rfbClient*) = 0;
};

class KeyEvent : public SomeEvent
{
public:
	KeyEvent(int key, int pressed) :
		_key(key), _pressed(pressed)
	{
	}

	void fire(rfbClient*);

private:
	int _key;
	int _pressed;
};

class PointerEvent : public SomeEvent
{
public:
	PointerEvent(int x, int y, int buttonMask) :
		_x(x), _y(y), _buttonMask(buttonMask)
	{
	}

	void fire(rfbClient*);

private:
	int _x;
	int _y;
	int _buttonMask;
};

/**
 * VncThread - communicate with VNC server, scale image if necessary.
 *
 * As this class is derived from QThread and overrides the run() method,
 * it does not have an event-loop. Do NOT try to add any slots to it.
 * It will NOT be able to receive signals. Emitting signals is fine though.
 */
class VncThread : public QThread
{
Q_OBJECT

private:
	rfbClient *_client;
	quint8 *_frameBuffer;

	QString _host;
	int _port;
	QString _passwd;
	int _quality;
	QQueue<SomeEvent*> _eventQueue;

	QPainter *_painter;
	QImage _img;
	QImage _imgScaled;
	QSize _clientSize;
	QSize _localSize;
	QMutex _mutex;

	QSize _newLocalSize;
	volatile bool _hasNewLocalSize;

	int _srcStepX, _srcStepY, _dstStepX, _dstStepY;

	bool _connected;
	volatile bool _run;

	void calcScaling();

	// Callbacks for rfb lib. make them class members so the callbacks can access private members of the class.
	static void updateImage(rfbClient *client, int x, int y, int w, int h);
	static char* passwdHandler(rfbClient *client);
	static rfbBool frameBufferHandler(rfbClient *client);

public:
	VncThread(QString host, int port, QString passwd, int quality);
	// Do NOT delete this class directly. use VncThread::destroy() instead!
	~VncThread();

	const QImage& getImage() const { if (_srcStepX > 1 || _srcStepY > 1) return _imgScaled; return _img; }
	const QSize& getSourceSize() const { return _clientSize; }
	const QString getDesktopName() const;
	void processImageUpdate(const int x, const int y, const int w, const int h);
	void mouseEvent(int x, int y, int buttonMask);
	void keyEvent(int key, bool pressed);
	const bool isConnected() const { return _connected; }
	void stop() { _run = false; }
	void setTargetSize(const QSize size);
	void run();

	int const static HIGH = 0;
	int const static MEDIUM = 1;
	int const static LOW = 2;

signals:
	void imageUpdated(const int x, const int y, const int w, const int h);
	void projectionStarted();
	void projectionStopped();

};

#endif /* VNCCLIENTTHREAD_H_ */