File indexing completed on 2024-05-05 09:12:57
0001 /* 0002 SPDX-FileCopyrightText: 2002 Arend van Beelen jr. <arend@auton.nl> 0003 SPDX-FileCopyrightText: 2007-2012 Urs Wolfer <uwolfer@kde.org> 0004 SPDX-FileCopyrightText: 2012 AceLan Kao <acelan@acelan.idv.tw> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "rdpview.h" 0010 0011 #include "rdphostpreferences.h" 0012 #include "krdc_debug.h" 0013 0014 #include <KMessageBox> 0015 #include <KPasswordDialog> 0016 #include <KShell> 0017 #include <KWindowSystem> 0018 0019 #include <QScreen> 0020 #include <QWindow> 0021 #include <QDir> 0022 #include <QEvent> 0023 #include <QInputDialog> 0024 #include <QPainter> 0025 #include <QKeyEvent> 0026 #include <QMouseEvent> 0027 0028 #include "rdpsession.h" 0029 0030 RdpView::RdpView(QWidget *parent, 0031 const QUrl &url, 0032 KConfigGroup configGroup, 0033 const QString &user, const QString &password) 0034 : RemoteView(parent), 0035 m_user(user), 0036 m_password(password) 0037 { 0038 m_url = url; 0039 m_host = url.host(); 0040 m_port = url.port(); 0041 0042 if (m_user.isEmpty() && !m_url.userName().isEmpty()) { 0043 m_user = m_url.userName(); 0044 } 0045 0046 if (m_password.isEmpty() && !m_url.password().isEmpty()) { 0047 m_password = m_url.password(); 0048 } 0049 0050 if (m_port <= 0) { 0051 m_port = TCP_PORT_RDP; 0052 } 0053 0054 setMouseTracking(true); 0055 0056 m_hostPreferences = std::make_unique<RdpHostPreferences>(configGroup); 0057 } 0058 0059 RdpView::~RdpView() 0060 { 0061 startQuitting(); 0062 } 0063 0064 QSize RdpView::framebufferSize() 0065 { 0066 if (m_session) { 0067 return m_session->size(); 0068 } 0069 0070 return QSize{}; 0071 } 0072 0073 void RdpView::scaleResize(int w, int h) 0074 { 0075 RemoteView::scaleResize(w, h); 0076 0077 // handle window resizes 0078 resize(sizeHint()); 0079 } 0080 0081 QSize RdpView::sizeHint() const 0082 { 0083 if (!m_session) { 0084 return QSize{}; 0085 } 0086 0087 // when parent is resized and scaling is enabled, resize the view, preserving aspect ratio 0088 if (m_hostPreferences->scaleToSize()) { 0089 return m_session->size().scaled(parentWidget()->size(), Qt::KeepAspectRatio); 0090 } 0091 0092 return m_session->size(); 0093 } 0094 0095 void RdpView::startQuitting() 0096 { 0097 m_quitting = true; 0098 m_session->stop(); 0099 } 0100 0101 bool RdpView::isQuitting() 0102 { 0103 return m_quitting; 0104 } 0105 0106 bool RdpView::start() 0107 { 0108 m_session = std::make_unique<RdpSession>(this); 0109 m_session->setHostPreferences(m_hostPreferences.get()); 0110 m_session->setHost(m_host); 0111 m_session->setPort(m_port); 0112 m_session->setUser(m_user); 0113 m_session->setSize(initialSize()); 0114 0115 if (m_password.isEmpty()) { 0116 m_session->setPassword(readWalletPassword()); 0117 } else { 0118 m_session->setPassword(m_password); 0119 } 0120 0121 connect(m_session.get(), &RdpSession::sizeChanged, this, [this]() { 0122 resize(sizeHint()); 0123 qCDebug(KRDC) << "freerdp resized rdp view" << sizeHint(); 0124 Q_EMIT framebufferSizeChanged(width(), height()); 0125 }); 0126 connect(m_session.get(), &RdpSession::rectangleUpdated, this, &RdpView::onRectangleUpdated); 0127 connect(m_session.get(), &RdpSession::stateChanged, this, [this]() { 0128 switch (m_session->state()) { 0129 case RdpSession::State::Starting: 0130 setStatus(Authenticating); 0131 break; 0132 case RdpSession::State::Connected: 0133 setStatus(Preparing); 0134 break; 0135 case RdpSession::State::Running: 0136 setStatus(Connected); 0137 break; 0138 case RdpSession::State::Closed: 0139 setStatus(Disconnected); 0140 break; 0141 default: 0142 break; 0143 } 0144 }); 0145 connect(m_session.get(), &RdpSession::errorMessage, this, [this](const QString &title, const QString &message) { 0146 KMessageBox::error(this, message, title); 0147 }); 0148 0149 setStatus(RdpView::Connecting); 0150 if (!m_session->start()) { 0151 0152 Q_EMIT disconnected(); 0153 return false; 0154 } 0155 0156 setFocus(); 0157 0158 return true; 0159 } 0160 0161 HostPreferences* RdpView::hostPreferences() 0162 { 0163 return m_hostPreferences.get(); 0164 } 0165 0166 void RdpView::switchFullscreen(bool on) 0167 { 0168 if (on) { 0169 showFullScreen(); 0170 } else { 0171 showNormal(); 0172 } 0173 } 0174 0175 QPixmap RdpView::takeScreenshot() 0176 { 0177 if (!m_session->videoBuffer()->isNull()) { 0178 return QPixmap::fromImage(*m_session->videoBuffer()); 0179 } 0180 return QPixmap{}; 0181 } 0182 0183 bool RdpView::supportsScaling() const 0184 { 0185 return true; 0186 } 0187 0188 bool RdpView::scaling() const 0189 { 0190 return m_hostPreferences->scaleToSize(); 0191 } 0192 0193 void RdpView::enableScaling(bool scale) 0194 { 0195 m_hostPreferences->setScaleToSize(scale); 0196 qCDebug(KRDC) << "Scaling changed" << scale; 0197 resize(sizeHint()); 0198 update(); 0199 } 0200 0201 void RdpView::setScaleFactor(float factor) 0202 { 0203 0204 } 0205 0206 QSize RdpView::initialSize() 0207 { 0208 switch (m_hostPreferences->resolution()) { 0209 case RdpHostPreferences::Resolution::Small: 0210 return QSize{1280, 720}; 0211 case RdpHostPreferences::Resolution::Medium: 0212 return QSize{1600, 900}; 0213 case RdpHostPreferences::Resolution::Large: 0214 return QSize{1920, 1080}; 0215 case RdpHostPreferences::Resolution::MatchWindow: 0216 return parentWidget()->size(); 0217 case RdpHostPreferences::Resolution::MatchScreen: 0218 return window()->windowHandle()->screen()->size(); 0219 case RdpHostPreferences::Resolution::Custom: 0220 return QSize{m_hostPreferences->width(), m_hostPreferences->height()}; 0221 } 0222 0223 return parentWidget()->size(); 0224 } 0225 0226 void RdpView::savePassword(const QString& password) 0227 { 0228 saveWalletPassword(password); 0229 } 0230 0231 void RdpView::paintEvent(QPaintEvent *event) 0232 { 0233 if (m_session->videoBuffer()->isNull()) { 0234 return; 0235 } 0236 0237 QPainter painter; 0238 0239 painter.begin(this); 0240 painter.setClipRect(event->rect()); 0241 0242 auto image = *m_session->videoBuffer(); 0243 0244 if (m_hostPreferences->scaleToSize()) { 0245 painter.drawImage(QPoint{0, 0}, image.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); 0246 } else { 0247 painter.drawImage(QPoint{0, 0}, image); 0248 } 0249 painter.end(); 0250 } 0251 0252 void RdpView::keyPressEvent(QKeyEvent *event) 0253 { 0254 m_session->sendEvent(event, this); 0255 event->accept(); 0256 } 0257 0258 void RdpView::keyReleaseEvent(QKeyEvent *event) 0259 { 0260 m_session->sendEvent(event, this); 0261 event->accept(); 0262 } 0263 0264 void RdpView::mousePressEvent(QMouseEvent *event) 0265 { 0266 if (!hasFocus()) { 0267 setFocus(); 0268 } 0269 0270 m_session->sendEvent(event, this); 0271 event->accept(); 0272 } 0273 0274 void RdpView::mouseDoubleClickEvent(QMouseEvent *event) 0275 { 0276 if (!hasFocus()) { 0277 setFocus(); 0278 } 0279 0280 m_session->sendEvent(event, this); 0281 event->accept(); 0282 } 0283 0284 void RdpView::mouseReleaseEvent(QMouseEvent *event) 0285 { 0286 m_session->sendEvent(event, this); 0287 event->accept(); 0288 } 0289 0290 void RdpView::mouseMoveEvent(QMouseEvent *event) 0291 { 0292 m_session->sendEvent(event, this); 0293 event->accept(); 0294 } 0295 0296 void RdpView::wheelEvent(QWheelEvent* event) 0297 { 0298 m_session->sendEvent(event, this); 0299 event->accept(); 0300 } 0301 0302 void RdpView::onRectangleUpdated(const QRect &rect) 0303 { 0304 m_pendingRectangle = rect; 0305 update(); 0306 }