File indexing completed on 2024-04-28 08:50:59
0001 /* 0002 SPDX-FileCopyrightText: 2002-2003 Tim Jansen <tim@tjansen.de> 0003 SPDX-FileCopyrightText: 2007-2008 Urs Wolfer <uwolfer@kde.org> 0004 SPDX-FileCopyrightText: 2021 RafaĆ Lalik <rafallalik@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #ifndef REMOTEVIEW_H 0010 #define REMOTEVIEW_H 0011 0012 #ifndef QTONLY 0013 #include <KWallet> 0014 #include "krdccore_export.h" 0015 #else 0016 #define KRDCCORE_EXPORT 0017 #endif 0018 0019 #include <QUrl> 0020 #include <QWidget> 0021 0022 class HostPreferences; 0023 0024 /** 0025 * Generic widget that displays a remote framebuffer. 0026 * Implement this if you want to add another backend. 0027 * 0028 * Things to take care of: 0029 * @li The RemoteView is responsible for its size. In 0030 * non-scaling mode, set the fixed size of the widget 0031 * to the remote resolution. In scaling mode, set the 0032 * maximum size to the remote size and minimum size to the 0033 * smallest resolution that your scaler can handle. 0034 * @li if you override mouseMoveEvent() 0035 * you must ignore the QEvent, because the KRDC widget will 0036 * need it for stuff like toolbar auto-hide and bump 0037 * scrolling. If you use x11Event(), make sure that 0038 * MotionNotify events will be forwarded. 0039 * 0040 */ 0041 class KRDCCORE_EXPORT RemoteView : public QWidget 0042 { 0043 Q_OBJECT 0044 0045 public: 0046 0047 enum Quality { 0048 Unknown, 0049 High, 0050 Medium, 0051 Low 0052 }; 0053 Q_ENUM(Quality) 0054 0055 /** 0056 * Describes the state of a local cursor, if there is such a concept in the backend. 0057 * With local cursors, there are two cursors: the cursor on the local machine (client), 0058 * and the cursor on the remote machine (server). Because there is usually some lag, 0059 * some backends show both cursors simultaneously. In the VNC backend the local cursor 0060 * is a dot and the remote cursor is the 'real' cursor, usually an arrow. 0061 */ 0062 0063 enum LocalCursorState { 0064 CursorOn, ///< Always show local cursor based on remote one (or fallback to default). 0065 CursorOff, ///< Never show local cursor, only the remote one. 0066 /// Try to measure the lag and enable the local cursor if the latency is too high. 0067 CursorAuto 0068 }; 0069 Q_ENUM(LocalCursorState) 0070 0071 /** 0072 * State of the connection. The state of the connection is returned 0073 * by @ref RemoteView::status(). 0074 * 0075 * Not every state transition is allowed. You are only allowed to transition 0076 * a state to the following state, with three exceptions: 0077 * @li You can move from every state directly to Disconnected 0078 * @li You can move from every state except Disconnected to 0079 * Disconnecting 0080 * @li You can move from Disconnected to Connecting 0081 * 0082 * @ref RemoteView::setStatus() will follow this rules for you. 0083 * (If you add/remove a state here, you must adapt it) 0084 */ 0085 0086 enum RemoteStatus { 0087 Connecting = 0, 0088 Authenticating = 1, 0089 Preparing = 2, 0090 Connected = 3, 0091 Disconnecting = -1, 0092 Disconnected = -2 0093 }; 0094 Q_ENUM(RemoteStatus) 0095 0096 enum ErrorCode { 0097 None = 0, 0098 Internal, 0099 Connection, 0100 Protocol, 0101 IO, 0102 Name, 0103 NoServer, 0104 ServerBlocked, 0105 Authentication 0106 }; 0107 Q_ENUM(ErrorCode) 0108 0109 ~RemoteView() override; 0110 0111 /** 0112 * Checks whether the backend supports scaling. The 0113 * default implementation returns false. 0114 * @return true if scaling is supported 0115 * @see scaling() 0116 */ 0117 virtual bool supportsScaling() const; 0118 0119 /** 0120 * Checks whether the widget is in scale mode. The 0121 * default implementation always returns false. 0122 * @return true if scaling is activated. Must always be 0123 * false if @ref supportsScaling() returns false 0124 * @see supportsScaling() 0125 */ 0126 virtual bool scaling() const; 0127 0128 /** 0129 * Checks whether the backend supports the concept of local cursors. The 0130 * default implementation returns false. 0131 * @return true if local cursors are supported/known 0132 * @see LocalCursorState 0133 * @see showLocalCursor() 0134 * @see localCursorState() 0135 */ 0136 virtual bool supportsLocalCursor() const; 0137 0138 /** 0139 * Sets the state of the dot cursor, if supported by the backend. 0140 * The default implementation does nothing. 0141 * @param state the new state (CursorOn, CursorOff or 0142 * CursorAuto) 0143 * @see localCursorState() 0144 * @see supportsLocalCursor() 0145 */ 0146 virtual void showLocalCursor(LocalCursorState state); 0147 0148 /** 0149 * Returns the state of the local cursor. The default implementation returns 0150 * always CursorOff. 0151 * @return true if local cursors are supported/known 0152 * @see showLocalCursor() 0153 * @see supportsLocalCursor() 0154 */ 0155 virtual LocalCursorState localCursorState() const; 0156 0157 /** 0158 * Checks whether the backend supports the view only mode. The 0159 * default implementation returns false. 0160 * @return true if view-only mode is supported 0161 * @see LocalCursorState 0162 * @see showLocalCursor() 0163 * @see localCursorState() 0164 */ 0165 virtual bool supportsViewOnly() const; 0166 0167 /** 0168 * Checks whether the view is in view-only mode. This means 0169 * that all input is ignored. 0170 */ 0171 virtual bool viewOnly(); 0172 0173 /** 0174 * Checks whether grabbing all possible keys is enabled. 0175 */ 0176 virtual bool grabAllKeys(); 0177 0178 /** 0179 * Returns the resolution of the remote framebuffer. 0180 * It should return a null @ref QSize when the size 0181 * is not known. 0182 * The backend must also emit a @ref framebufferSizeChanged() 0183 * when the size of the framebuffer becomes available 0184 * for the first time or the size changed. 0185 * @return the remote framebuffer size, a null QSize 0186 * if unknown 0187 */ 0188 virtual QSize framebufferSize(); 0189 0190 /** 0191 * Initiate the disconnection. This doesn't need to happen 0192 * immediately. The call must not block. 0193 * @see isQuitting() 0194 */ 0195 virtual void startQuitting(); 0196 0197 /** 0198 * Checks whether the view is currently quitting. 0199 * @return true if it is quitting 0200 * @see startQuitting() 0201 * @see setStatus() 0202 */ 0203 virtual bool isQuitting(); 0204 0205 /** 0206 * @return the host the view is connected to 0207 */ 0208 virtual QString host(); 0209 0210 /** 0211 * @return the port the view is connected to 0212 */ 0213 virtual int port(); 0214 0215 /** 0216 * Initialize the view (for example by showing configuration 0217 * dialogs to the user) and start connecting. Should not block 0218 * without running the event loop (so displaying a dialog is ok). 0219 * When the view starts connecting the application must call 0220 * @ref setStatus() with the status Connecting. 0221 * @return true if successful (so far), false 0222 * otherwise 0223 * @see connected() 0224 * @see disconnected() 0225 * @see disconnectedError() 0226 * @see statusChanged() 0227 */ 0228 virtual bool start() = 0; 0229 0230 /** 0231 * Called when the configuration is changed. 0232 * The default implementation does nothing. 0233 */ 0234 virtual void updateConfiguration(); 0235 0236 /** 0237 * @return screenshot of the view 0238 */ 0239 virtual QPixmap takeScreenshot(); 0240 0241 #ifndef QTONLY 0242 /** 0243 * Returns the current host preferences of this view. 0244 */ 0245 virtual HostPreferences* hostPreferences() = 0; 0246 #endif 0247 0248 /** 0249 * Returns the current status of the connection. 0250 * @return the status of the connection 0251 * @see setStatus() 0252 */ 0253 RemoteStatus status(); 0254 0255 /** 0256 * @return the current url 0257 */ 0258 QUrl url(); 0259 0260 public Q_SLOTS: 0261 /** 0262 * Called to enable or disable scaling. 0263 * Ignored if @ref supportsScaling() is false. 0264 * The default implementation does nothing. 0265 * @param scale true to enable, false to disable. 0266 * @see supportsScaling() 0267 * @see scaling() 0268 */ 0269 virtual void enableScaling(bool scale); 0270 0271 /** 0272 * Sets scaling factor for the view. If remote view has width R and 0273 * the window has width W, then scaling factor (float, range 0-1) set the 0274 * remote view width A to be: A = (R-W)*factor + W. For factor = 0, A=W, 0275 * so no scalling, for factor=1, A=R. 0276 * 0277 * @param factor scaling factor in the range 0-1 0278 */ 0279 virtual void setScaleFactor(float factor); 0280 0281 /** 0282 * Enables/disables the view-only mode. 0283 * Ignored if @ref supportsScaling() is false. 0284 * The default implementation does nothing. 0285 * @param viewOnly true to enable, false to disable. 0286 * @see supportsScaling() 0287 * @see viewOnly() 0288 */ 0289 virtual void setViewOnly(bool viewOnly); 0290 0291 /** 0292 * Enables/disables grabbing all possible keys. 0293 * @param grabAllKeys true to enable, false to disable. 0294 * Default is false. 0295 * @see grabAllKeys() 0296 */ 0297 virtual void setGrabAllKeys(bool grabAllKeys); 0298 0299 /** 0300 * Called to let the backend know it when 0301 * we switch from/to fullscreen. 0302 * @param on true when switching to fullscreen, 0303 * false when switching from fullscreen. 0304 */ 0305 virtual void switchFullscreen(bool on); 0306 0307 /** 0308 * Sends a QKeyEvent to the remote server. 0309 * @param event the key to send 0310 */ 0311 virtual void keyEvent(QKeyEvent *event); 0312 0313 /** 0314 * Called when the visible place changed so remote 0315 * view can resize itself. 0316 * 0317 * @param w width of the remote view 0318 * @param h height of the remote view 0319 */ 0320 virtual void scaleResize(int w, int h); 0321 0322 Q_SIGNALS: 0323 /** 0324 * Emitted when the size of the remote screen changes. Also 0325 * called when the size is known for the first time. 0326 * @param w the width of the screen 0327 * @param h the height of the screen 0328 */ 0329 void framebufferSizeChanged(int w, int h); 0330 0331 /** 0332 * Emitted when the view connected successfully. 0333 */ 0334 void connected(); 0335 0336 /** 0337 * Emitted when the view disconnected without error. 0338 */ 0339 void disconnected(); 0340 0341 /** 0342 * Emitted when the view disconnected with error. 0343 */ 0344 void disconnectedError(); 0345 0346 /** 0347 * Emitted when the view has a specific error. 0348 */ 0349 void errorMessage(const QString &title, const QString &message); 0350 0351 /** 0352 * Emitted when the status of the view changed. 0353 * @param s the new status 0354 */ 0355 void statusChanged(RemoteView::RemoteStatus s); 0356 0357 /** 0358 * Emitted when the password dialog is shown or hidden. 0359 * @param b true when the dialog is shown, false when it has been hidden 0360 */ 0361 void showingPasswordDialog(bool b); 0362 0363 /** 0364 * Emitted when the mouse on the remote side has been moved. 0365 * @param x the new x coordinate 0366 * @param y the new y coordinate 0367 * @param buttonMask the mask of mouse buttons (bit 0 for first mouse 0368 * button, 1 for second button etc)a 0369 */ 0370 void mouseStateChanged(int x, int y, int buttonMask); 0371 0372 protected: 0373 RemoteView(QWidget *parent = nullptr); 0374 0375 void focusInEvent(QFocusEvent *event) override; 0376 void focusOutEvent(QFocusEvent *event) override; 0377 0378 /** 0379 * The status of the remote view. 0380 */ 0381 RemoteStatus m_status; 0382 0383 /** 0384 * Set the status of the connection. 0385 * Emits a statusChanged() signal. 0386 * Note that the states need to be set in a certain order, 0387 * see @ref RemoteStatus. setStatus() will try to do this 0388 * transition automatically, so if you are in Connecting 0389 * and call setStatus(Preparing), setStatus() will 0390 * emit a Authenticating and then Preparing. 0391 * If you transition backwards, it will emit a 0392 * Disconnected before doing the transition. 0393 * @param s the new status 0394 */ 0395 virtual void setStatus(RemoteStatus s); 0396 0397 QCursor localDefaultCursor() const; 0398 0399 QString m_host; 0400 int m_port; 0401 bool m_viewOnly; 0402 bool m_grabAllKeys; 0403 bool m_scale; 0404 bool m_keyboardIsGrabbed; 0405 QUrl m_url; 0406 qreal m_factor; 0407 0408 #ifndef QTONLY 0409 QString readWalletPassword(bool fromUserNameOnly = false); 0410 void saveWalletPassword(const QString &password, bool fromUserNameOnly = false); 0411 QString readWalletPasswordForKey(const QString &key); 0412 void saveWalletPasswordForKey(const QString &key, const QString &password); 0413 KWallet::Wallet *m_wallet; 0414 #endif 0415 0416 LocalCursorState m_localCursorState; 0417 }; 0418 0419 #endif