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