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