Merge branch 'master' of https://vcs.maemo.org/git/presencevnc
[presencevnc] / src / remoteview.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2002-2003 Tim Jansen <tim@tjansen.de>
4 ** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
5 **
6 ** This file is part of KDE.
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; see the file COPYING. If not, write to
20 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 ** Boston, MA 02110-1301, USA.
22 **
23 ****************************************************************************/
24
25 #ifndef REMOTEVIEW_H
26 #define REMOTEVIEW_H
27
28 #ifdef QTONLY
29 #include <QUrl>
30 #define KUrl QUrl
31 #define KDE_EXPORT
32 #else
33 #include <KUrl>
34 #include <KWallet/Wallet>
35 #endif
36
37 #include <QWidget>
38
39 class HostPreferences;
40
41 /**
42  * Generic widget that displays a remote framebuffer.
43  * Implement this if you want to add another backend.
44  *
45  * Things to take care of:
46  * @li The RemoteView is responsible for its size. In
47  *     non-scaling mode, set the fixed size of the widget
48  *     to the remote resolution. In scaling mode, set the
49  *     maximum size to the remote size and minimum size to the
50  *     smallest resolution that your scaler can handle.
51  * @li if you override mouseMoveEvent()
52  *     you must ignore the QEvent, because the KRDC widget will
53  *     need it for stuff like toolbar auto-hide and bump
54  *     scrolling. If you use x11Event(), make sure that
55  *     MotionNotify events will be forwarded.
56  *
57  */
58 class KDE_EXPORT RemoteView : public QWidget
59 {
60     Q_OBJECT
61
62 public:
63
64     Q_ENUMS(Quality)
65
66     enum Quality {
67         Unknown,
68         High,
69         Medium,
70         Low
71     };
72
73     /**
74     * Describes the state of a local cursor, if there is such a concept in the backend.
75     * With local cursors, there are two cursors: the cursor on the local machine (client),
76     * and the cursor on the remote machine (server). Because there is usually some lag,
77     * some backends show both cursors simultanously. In the VNC backend the local cursor
78     * is a dot and the remote cursor is the 'real' cursor, usually an arrow.
79     */
80
81     Q_ENUMS(DotCursorState)
82
83     enum DotCursorState {
84         CursorOn,  ///< Always show local cursor (and the remote one).
85         CursorOff, ///< Never show local cursor, only the remote one.
86         /// Try to measure the lag and enable the local cursor if the latency is too high.
87         CursorAuto
88     };
89
90     /**
91     * State of the connection. The state of the connection is returned
92     * by @ref RemoteView::status().
93     *
94     * Not every state transition is allowed. You are only allowed to transition
95     * a state to the following state, with three exceptions:
96     * @li You can move from every state directly to Disconnected
97     * @li You can move from every state except Disconnected to
98     *     Disconnecting
99     * @li You can move from Disconnected to Connecting
100     *
101     * @ref RemoteView::setStatus() will follow this rules for you.
102     * (If you add/remove a state here, you must adapt it)
103     */
104
105     Q_ENUMS(RemoteStatus)
106
107     enum RemoteStatus {
108         Connecting     = 0,
109         Authenticating = 1,
110         Preparing      = 2,
111         Connected      = 3,
112         Disconnecting  = -1,
113         Disconnected   = -2
114     };
115
116     Q_ENUMS(ErrorCode)
117
118     enum ErrorCode {
119         None = 0,
120         Internal,
121         Connection,
122         Protocol,
123         IO,
124         Name,
125         NoServer,
126         ServerBlocked,
127         Authentication
128     };
129
130     virtual ~RemoteView();
131
132     /**
133      * Checks whether the backend supports scaling. The
134      * default implementation returns false.
135      * @return true if scaling is supported
136      * @see scaling()
137      */
138     virtual bool supportsScaling() const;
139
140     /**
141      * Checks whether the widget is in scale mode. The
142      * default implementation always returns false.
143      * @return true if scaling is activated. Must always be
144      *         false if @ref supportsScaling() returns false
145      * @see supportsScaling()
146      */
147     virtual bool scaling() const;
148
149     /**
150      * Checks whether the backend supports the concept of local cursors. The
151      * default implementation returns false.
152      * @return true if local cursors are supported/known
153      * @see DotCursorState
154      * @see showDotCursor()
155      * @see dotCursorState()
156      */
157     virtual bool supportsLocalCursor() const;
158
159     /**
160      * Sets the state of the dot cursor, if supported by the backend.
161      * The default implementation does nothing.
162      * @param state the new state (CursorOn, CursorOff or
163      *        CursorAuto)
164      * @see dotCursorState()
165      * @see supportsLocalCursor()
166      */
167     virtual void showDotCursor(DotCursorState state);
168
169     /**
170      * Returns the state of the local cursor. The default implementation returns
171      * always CursorOff.
172      * @return true if local cursors are supported/known
173      * @see showDotCursor()
174      * @see supportsLocalCursor()
175      */
176     virtual DotCursorState dotCursorState() const;
177
178     /**
179      * Checks whether the view is in view-only mode. This means
180      * that all input is ignored.
181      */
182     virtual bool viewOnly();
183
184     /**
185      * Checks whether grabbing all possible keys is enabled.
186      */
187     virtual bool grabAllKeys();
188
189     /**
190      * Returns the resolution of the remote framebuffer.
191      * It should return a null @ref QSize when the size
192      * is not known.
193      * The backend must also emit a @ref framebufferSizeChanged()
194      * when the size of the framebuffer becomes available
195      * for the first time or the size changed.
196      * @return the remote framebuffer size, a null QSize
197      *         if unknown
198      */
199     virtual QSize framebufferSize();
200
201     /**
202      * Initiate the disconnection. This doesn't need to happen
203      * immediately. The call must not block.
204      * @see isQuitting()
205      */
206     virtual void startQuitting();
207
208     /**
209      * Checks whether the view is currently quitting.
210      * @return true if it is quitting
211      * @see startQuitting()
212      * @see setStatus()
213      */
214     virtual bool isQuitting();
215
216     /**
217      * @return the host the view is connected to
218      */
219     virtual QString host();
220
221     /**
222      * @return the port the view is connected to
223      */
224     virtual int port();
225
226     /**
227      * Initialize the view (for example by showing configuration
228      * dialogs to the user) and start connecting. Should not block
229      * without running the event loop (so displaying a dialog is ok).
230      * When the view starts connecting the application must call
231      * @ref setStatus() with the status Connecting.
232      * @return true if successful (so far), false
233      *         otherwise
234      * @see connected()
235      * @see disconnected()
236      * @see disconnectedError()
237      * @see statusChanged()
238      */
239     virtual bool start() = 0;
240
241     /**
242      * Called when the configuration is changed.
243      * The default implementation does nothing.
244      */
245     virtual void updateConfiguration();
246
247 #ifndef QTONLY
248     /**
249      * Returns the current host preferences of this view.
250      */
251     virtual HostPreferences* hostPreferences() = 0;
252 #endif
253
254     /**
255      * Returns the current status of the connection.
256      * @return the status of the connection
257      * @see setStatus()
258      */
259     RemoteStatus status();
260
261     /**
262      * @return the current url
263      */
264     KUrl url();
265
266 public slots:
267     /**
268      * Called to enable or disable scaling.
269      * Ignored if @ref supportsScaling() is false.
270      * The default implementation does nothing.
271      * @param s true to enable, false to disable.
272      * @see supportsScaling()
273      * @see scaling()
274      */
275     virtual void enableScaling(bool scale);
276
277     /**
278      * Enables/disables the view-only mode.
279      * Ignored if @ref supportsScaling() is false.
280      * The default implementation does nothing.
281      * @param viewOnly true to enable, false to disable.
282      * @see supportsScaling()
283      * @see viewOnly()
284      */
285     virtual void setViewOnly(bool viewOnly);
286
287     /**
288      * Enables/disables grabbing all possible keys.
289      * @param grabAllKeys true to enable, false to disable.
290      * Default is false.
291      * @see grabAllKeys()
292      */
293     virtual void setGrabAllKeys(bool grabAllKeys);
294
295     /**
296      * Called to let the backend know it when
297      * we switch from/to fullscreen.
298      * @param on true when switching to fullscreen,
299      *           false when switching from fullscreen.
300      */
301     virtual void switchFullscreen(bool on);
302
303     /**
304      * Sends a QKeyEvent to the remote server.
305      * @param event the key to send
306      */
307     virtual void keyEvent(QKeyEvent *event);
308
309     /**
310      * Called when the visible place changed so remote
311      * view can resize itself.
312      */
313     virtual void scaleResize(int w, int h);
314
315 signals:
316     /**
317      * Emitted when the size of the remote screen changes. Also
318      * called when the size is known for the first time.
319      * @param x the width of the screen
320      * @param y the height of the screen
321      */
322     void framebufferSizeChanged(int w, int h);
323
324     /**
325      * Emitted when the view connected successfully.
326      */
327     void connected();
328
329     /**
330      * Emitted when the view disconnected without error.
331      */
332     void disconnected();
333
334     /**
335      * Emitted when the view disconnected with error.
336      */
337     void disconnectedError();
338
339     /**
340      * Emitted when the view has a specific error.
341      */
342     void errorMessage(const QString &title, const QString &message);
343
344     /**
345      * Emitted when the status of the view changed.
346      * @param s the new status
347         */
348     void statusChanged(RemoteView::RemoteStatus s);
349
350     /**
351      * Emitted when the password dialog is shown or hidden.
352      * @param b true when the dialog is shown, false when it has been hidden
353      */
354     void showingPasswordDialog(bool b);
355
356     /**
357      * Emitted when the mouse on the remote side has been moved.
358      * @param x the new x coordinate
359      * @param y the new y coordinate
360      * @param buttonMask the mask of mouse buttons (bit 0 for first mouse
361      *                   button, 1 for second button etc)a
362      */
363     void mouseStateChanged(int x, int y, int buttonMask);
364
365 protected:
366     RemoteView(QWidget *parent = 0);
367
368     void focusInEvent(QFocusEvent *event);
369     void focusOutEvent(QFocusEvent *event);
370
371     /**
372      * The status of the remote view.
373      */
374     RemoteStatus m_status;
375
376     /**
377      * Set the status of the connection.
378      * Emits a statusChanged() signal.
379      * Note that the states need to be set in a certain order,
380      * see @ref Status. setStatus() will try to do this
381      * transition automatically, so if you are in Connecting
382      * and call setStatus(Preparing), setStatus() will
383      * emit a Authenticating and then Preparing.
384      * If you transition backwards, it will emit a
385      * Disconnected before doing the transition.
386      * @param s the new status
387      */
388     virtual void setStatus(RemoteStatus s);
389
390     QCursor localDotCursor() const;
391
392     QString m_host;
393     int m_port;
394     bool m_viewOnly;
395     bool m_grabAllKeys;
396     bool m_scale;
397     bool m_keyboardIsGrabbed;
398     KUrl m_url;
399
400 #ifndef QTONLY
401     QString readWalletPassword(bool fromUserNameOnly = false);
402     void saveWalletPassword(const QString &password, bool fromUserNameOnly = false);
403     KWallet::Wallet *m_wallet;
404 #endif
405
406     DotCursorState m_dotCursorState;
407 };
408
409 #endif