1 /****************************************************************************
3 ** Copyright (C) 2007 Urs Wolfer <uwolfer @ kde.org>
5 ** This file is part of KDE.
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; see the file COPYING. If not, write to
19 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ** Boston, MA 02110-1301, USA.
22 ****************************************************************************/
27 #include <KMessageBox>
28 #include <KPasswordDialog>
31 #include <QApplication>
34 #include <QMouseEvent>
36 VncView::VncView(QWidget
*parent
, const KUrl
&url
)
42 m_firstPasswordTry(true),
43 m_dontSendClipboard(false)
49 connect(&vncThread
, SIGNAL(imageUpdated(int, int, int, int)), this, SLOT(updateImage(int, int, int, int)), Qt::BlockingQueuedConnection
);
50 connect(&vncThread
, SIGNAL(gotCut(const QString
&)), this, SLOT(setCut(const QString
&)), Qt::BlockingQueuedConnection
);
51 connect(&vncThread
, SIGNAL(passwordRequest()), this, SLOT(requestPassword()), Qt::BlockingQueuedConnection
);
52 connect(&vncThread
, SIGNAL(outputErrorMessage(QString
)), this, SLOT(outputErrorMessage(QString
)));
54 m_clipboard
= QApplication::clipboard();
55 connect(m_clipboard
, SIGNAL(selectionChanged()), this, SLOT(clipboardSelectionChanged()));
56 connect(m_clipboard
, SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
64 bool VncView::eventFilter(QObject
*obj
, QEvent
*event
)
67 setCursor(Qt::ArrowCursor
);
69 if (event
->type() == QEvent::KeyPress
||
70 event
->type() == QEvent::KeyRelease
||
71 event
->type() == QEvent::MouseButtonDblClick
||
72 event
->type() == QEvent::MouseButtonPress
||
73 event
->type() == QEvent::MouseButtonRelease
||
74 event
->type() == QEvent::Wheel
||
75 event
->type() == QEvent::MouseMove
)
79 setCursor(m_dotCursorState
== CursorOn
? localDotCursor() : Qt::BlankCursor
);
81 return RemoteView::eventFilter(obj
, event
);
84 QSize
VncView::framebufferSize()
89 QSize
VncView::sizeHint() const
94 QSize
VncView::minimumSizeHint() const
99 void VncView::startQuitting()
101 kDebug(5011) << "about to quit";
103 bool connected
= status() == RemoteView::Connected
;
105 setStatus(Disconnecting
);
117 setStatus(Disconnected
);
120 bool VncView::isQuitting()
125 bool VncView::start()
127 m_hostPreferences
= new VncHostPreferences(m_url
.prettyUrl(KUrl::RemoveTrailingSlash
), false, this);
129 vncThread
.setHost(m_host
);
130 vncThread
.setPort(m_port
);
131 vncThread
.setQuality(m_hostPreferences
->quality());
133 setStatus(Connecting
);
139 bool VncView::supportsLocalCursor() const
144 void VncView::requestPassword()
146 kDebug(5011) << "request password";
148 setStatus(Authenticating
);
150 if (m_hostPreferences
->walletSupport()) {
151 QString walletPassword
= readWalletPassword();
153 if (!walletPassword
.isNull()) {
154 vncThread
.setPassword(walletPassword
);
159 if (!m_url
.password().isNull()) {
160 vncThread
.setPassword(m_url
.password());
164 KPasswordDialog
dialog(this);
165 dialog
.setPixmap(KIcon("dialog-password").pixmap(48));
166 dialog
.setPrompt(m_firstPasswordTry
? i18n("Access to the system requires a password.")
167 : i18n("Authentication failed. Please try again."));
168 if (dialog
.exec() == KPasswordDialog::Accepted
) {
169 m_firstPasswordTry
= false;
170 vncThread
.setPassword(dialog
.password());
174 void VncView::outputErrorMessage(const QString
&message
)
176 kDebug(5011) << message
;
180 KMessageBox::error(this, message
, i18n("VNC failure"));
183 void VncView::updateImage(int x
, int y
, int w
, int h
)
185 // kDebug(5011) << "got update";
193 setAttribute(Qt::WA_StaticContents
);
194 setAttribute(Qt::WA_OpaquePaintEvent
);
195 installEventFilter(this);
197 setCursor(m_dotCursorState
== CursorOn
? localDotCursor() : Qt::BlankCursor
);
199 setMouseTracking(true); // get mouse events even when there is no mousebutton pressed
200 setFocusPolicy(Qt::WheelFocus
);
201 QImage frame
= vncThread
.image();
202 setFixedSize(frame
.width(), frame
.height());
203 setStatus(Connected
);
204 emit
changeSize(frame
.width(), frame
.height());
208 if (m_hostPreferences
->walletSupport()) {
209 saveWalletPassword(vncThread
.password());
218 void VncView::setCut(const QString
&text
)
220 m_dontSendClipboard
= true;
221 m_clipboard
->setText(text
, QClipboard::Clipboard
);
222 m_clipboard
->setText(text
, QClipboard::Selection
);
223 m_dontSendClipboard
= false;
226 void VncView::paintEvent(QPaintEvent
*event
)
228 // kDebug(5011) << "paint event: x: " << m_x << ", y: " << m_y << ", w: " << m_w << ", h: " << m_h;
232 QPainter
painter(this);
236 // kDebug(5011) << "normal repaint";
237 painter
.drawImage(QRect(m_x
, m_y
, m_w
, m_h
), vncThread
.image(m_x
, m_y
, m_w
, m_h
));
239 // kDebug(5011) << "resize repaint";
240 QImage frame
= vncThread
.image();
241 painter
.drawImage(frame
.rect(), frame
);
244 QWidget::paintEvent(event
);
247 void VncView::focusOutEvent(QFocusEvent
*event
)
249 // kDebug(5011) << "focusOutEvent";
251 if (event
->reason() == Qt::TabFocusReason
) {
252 // kDebug(5011) << "event->reason() == Qt::TabFocusReason";
254 setFocus(); // get focus back and send tab key event to remote desktop
255 keyEvent(new QKeyEvent(QEvent::KeyPress
, Qt::Key_Tab
, Qt::NoModifier
));
256 keyEvent(new QKeyEvent(QEvent::KeyRelease
, Qt::Key_Tab
, Qt::NoModifier
));
262 void VncView::mouseMoveEvent(QMouseEvent
*event
)
264 // kDebug(5011) << "mouse move";
271 void VncView::mousePressEvent(QMouseEvent
*event
)
273 // kDebug(5011) << "mouse press";
280 void VncView::mouseDoubleClickEvent(QMouseEvent
*event
)
282 // kDebug(5011) << "mouse double click";
289 void VncView::mouseReleaseEvent(QMouseEvent
*event
)
291 // kDebug(5011) << "mouse release";
298 void VncView::mouseEvent(QMouseEvent
*e
)
300 if (e
->type() != QEvent::MouseMove
) {
301 if ((e
->type() == QEvent::MouseButtonPress
) ||
302 (e
->type() == QEvent::MouseButtonDblClick
)) {
303 if (e
->button() & Qt::LeftButton
)
304 m_buttonMask
|= 0x01;
305 if (e
->button() & Qt::MidButton
)
306 m_buttonMask
|= 0x02;
307 if (e
->button() & Qt::RightButton
)
308 m_buttonMask
|= 0x04;
309 } else if (e
->type() == QEvent::MouseButtonRelease
) {
310 if (e
->button() & Qt::LeftButton
)
311 m_buttonMask
&= 0xfe;
312 if (e
->button() & Qt::MidButton
)
313 m_buttonMask
&= 0xfd;
314 if (e
->button() & Qt::RightButton
)
315 m_buttonMask
&= 0xfb;
319 vncThread
.mouseEvent(e
->x(), e
->y(), m_buttonMask
);
322 void VncView::wheelEvent(QWheelEvent
*event
)
325 if (event
->delta() < 0)
333 vncThread
.mouseEvent(x
, y
, eb
| m_buttonMask
);
334 vncThread
.mouseEvent(x
, y
, m_buttonMask
);
338 void VncView::keyEvent(QKeyEvent
*e
)
342 case Qt::Key_Backspace
: k
= XK_BackSpace
; break;
343 case Qt::Key_Tab
: k
= XK_Tab
; break;
344 case Qt::Key_Clear
: k
= XK_Clear
; break;
345 case Qt::Key_Return
: k
= XK_Return
; break;
346 case Qt::Key_Pause
: k
= XK_Pause
; break;
347 case Qt::Key_Escape
: k
= XK_Escape
; break;
348 case Qt::Key_Space
: k
= XK_space
; break;
349 case Qt::Key_Delete
: k
= XK_Delete
; break;
350 case Qt::Key_Enter
: k
= XK_KP_Enter
; break;
351 case Qt::Key_Equal
: k
= XK_KP_Equal
; break;
352 case Qt::Key_Up
: k
= XK_Up
; break;
353 case Qt::Key_Down
: k
= XK_Down
; break;
354 case Qt::Key_Right
: k
= XK_Right
; break;
355 case Qt::Key_Left
: k
= XK_Left
; break;
356 case Qt::Key_Insert
: k
= XK_Insert
; break;
357 case Qt::Key_Home
: k
= XK_Home
; break;
358 case Qt::Key_End
: k
= XK_End
; break;
359 case Qt::Key_PageUp
: k
= XK_Page_Up
; break;
360 case Qt::Key_PageDown
: k
= XK_Page_Down
; break;
361 case Qt::Key_F1
: k
= XK_F1
; break;
362 case Qt::Key_F2
: k
= XK_F2
; break;
363 case Qt::Key_F3
: k
= XK_F3
; break;
364 case Qt::Key_F4
: k
= XK_F4
; break;
365 case Qt::Key_F5
: k
= XK_F5
; break;
366 case Qt::Key_F6
: k
= XK_F6
; break;
367 case Qt::Key_F7
: k
= XK_F7
; break;
368 case Qt::Key_F8
: k
= XK_F8
; break;
369 case Qt::Key_F9
: k
= XK_F9
; break;
370 case Qt::Key_F10
: k
= XK_F10
; break;
371 case Qt::Key_F11
: k
= XK_F11
; break;
372 case Qt::Key_F12
: k
= XK_F12
; break;
373 case Qt::Key_F13
: k
= XK_F13
; break;
374 case Qt::Key_F14
: k
= XK_F14
; break;
375 case Qt::Key_F15
: k
= XK_F15
; break;
376 case Qt::Key_NumLock
: k
= XK_Num_Lock
; break;
377 case Qt::Key_CapsLock
: k
= XK_Caps_Lock
; break;
378 case Qt::Key_ScrollLock
: k
= XK_Scroll_Lock
; break;
379 case Qt::Key_Shift
: k
= XK_Shift_L
; break;
380 case Qt::Key_Control
: k
= XK_Control_L
; break;
381 case Qt::Key_AltGr
: k
= XK_Alt_R
; break;
382 case Qt::Key_Alt
: k
= XK_Alt_L
; break;
383 case Qt::Key_Meta
: k
= XK_Meta_L
; break;
384 case Qt::Key_Mode_switch
: k
= XK_Mode_switch
; break;
385 case Qt::Key_Help
: k
= XK_Help
; break;
386 case Qt::Key_Print
: k
= XK_Print
; break;
387 case Qt::Key_SysReq
: k
= XK_Sys_Req
; break;
392 if (e
->key() < 0x100)
393 k
= QChar(e
->text().at(0)).unicode(); //respect upper- / lowercase
395 rfbClientLog("Unknown keysym: %d\n", e
->key());
398 if (k
< 26) // workaround for modified keys by pressing CTRL
401 vncThread
.keyEvent(k
, (e
->type() == QEvent::KeyPress
) ? true : false);
404 void VncView::keyPressEvent(QKeyEvent
*event
)
406 // kDebug(5011) << "key press" << event->key();
413 void VncView::keyReleaseEvent(QKeyEvent
*event
)
415 // kDebug(5011) << "key release" << event->key();
422 void VncView::clipboardSelectionChanged()
426 if (m_status
!= Connected
)
429 if (m_clipboard
->ownsSelection() || m_dontSendClipboard
)
432 QString text
= m_clipboard
->text(QClipboard::Selection
);
434 vncThread
.clientCut(text
);
437 void VncView::clipboardDataChanged()
441 if (m_status
!= Connected
)
444 if (m_clipboard
->ownsClipboard() || m_dontSendClipboard
)
447 QString text
= m_clipboard
->text(QClipboard::Clipboard
);
449 vncThread
.clientCut(text
);
452 #include "vncview.moc"