|
|
|
/*
|
|
|
|
krdpview.h, implementation of the KRdpView class
|
|
|
|
Copyright (C) 2002 Arend van Beelen jr.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or (at
|
|
|
|
your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
|
|
For any questions, comments or whatever, you may mail me at: arend@auton.nl
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kwallet.h>
|
|
|
|
#include <kpassdlg.h>
|
|
|
|
|
|
|
|
#include <tqvbox.h>
|
|
|
|
#include <qxembed.h>
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
|
|
|
|
#undef Bool
|
|
|
|
|
|
|
|
#include "krdpview.h"
|
|
|
|
#include "rdphostpref.h"
|
|
|
|
#include "rdpprefs.h"
|
|
|
|
|
|
|
|
bool launch_Fullscreen_rdp = false;
|
|
|
|
bool rdpAppDataConfigured = false;
|
|
|
|
extern KWallet::Wallet *wallet;
|
|
|
|
|
|
|
|
static KRdpView *krdpview;
|
|
|
|
|
|
|
|
RdpContainer::RdpContainer(TQWidget *parent, const char *name, WFlags f) :
|
|
|
|
QXEmbed(parent, name, f),
|
|
|
|
m_viewOnly(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RdpContainer::~RdpContainer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void RdpContainer::windowChanged(WId window)
|
|
|
|
{
|
|
|
|
if(window == 0)
|
|
|
|
{
|
|
|
|
emit embeddedWindowDestroyed();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
emit newEmbeddedWindow(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RdpContainer::x11Event(XEvent *e)
|
|
|
|
{
|
|
|
|
// FIXME: mouse events still get through in view-only
|
|
|
|
if(m_viewOnly && (e->type == KeyPress || e->type == KeyRelease || e->type == ButtonPress ||
|
|
|
|
e->type == ButtonRelease || e->type == MotionNotify || e->type == FocusIn ||
|
|
|
|
e->type == FocusOut || e->type == EnterNotify || e->type == LeaveNotify))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QXEmbed::x11Event(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// constructor
|
|
|
|
KRdpView::KRdpView(TQWidget *parent, const char *name,
|
|
|
|
const TQString &host, int port,
|
|
|
|
const TQString &user, const TQString &password,
|
|
|
|
int flags, const TQString &domain,
|
|
|
|
const TQString &shell, const TQString &directory) :
|
|
|
|
KRemoteView(parent, name, Qt::WResizeNoErase | Qt::WRepaintNoErase | Qt::WStaticContents),
|
|
|
|
m_name(name),
|
|
|
|
m_host(host),
|
|
|
|
m_port(port),
|
|
|
|
m_user(user),
|
|
|
|
m_password(password),
|
|
|
|
m_flags(flags),
|
|
|
|
m_domain(domain),
|
|
|
|
m_shell(shell),
|
|
|
|
m_directory(directory),
|
|
|
|
m_quitFlag(false),
|
|
|
|
m_process(NULL)
|
|
|
|
{
|
|
|
|
krdpview = this;
|
|
|
|
setFixedSize(16, 16);
|
|
|
|
if(m_port == 0)
|
|
|
|
{
|
|
|
|
m_port = TCP_PORT_RDP;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_container = new RdpContainer(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// destructor
|
|
|
|
KRdpView::~KRdpView()
|
|
|
|
{
|
|
|
|
startQuitting();
|
|
|
|
delete m_container;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the size of the framebuffer
|
|
|
|
TQSize KRdpView::framebufferSize()
|
|
|
|
{
|
|
|
|
return m_container->sizeHint();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the suggested size
|
|
|
|
TQSize KRdpView::sizeHint()
|
|
|
|
{
|
|
|
|
return maximumSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
// start closing the connection
|
|
|
|
void KRdpView::startQuitting()
|
|
|
|
{
|
|
|
|
m_quitFlag = true;
|
|
|
|
if(m_process != NULL)
|
|
|
|
{
|
|
|
|
m_container->sendDelete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// are we currently closing the connection?
|
|
|
|
bool KRdpView::isQuitting()
|
|
|
|
{
|
|
|
|
return m_quitFlag;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the host we're connected to
|
|
|
|
TQString KRdpView::host()
|
|
|
|
{
|
|
|
|
return m_host;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the port number we're connected on
|
|
|
|
int KRdpView::port()
|
|
|
|
{
|
|
|
|
return m_port;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KRdpView::editPreferences( HostPrefPtr host )
|
|
|
|
{
|
|
|
|
SmartPtr<RdpHostPref> hp( host );
|
|
|
|
|
|
|
|
int wv = hp->width();
|
|
|
|
int hv = hp->height();
|
|
|
|
int cd = hp->colorDepth();
|
|
|
|
TQString kl = hp->layout();
|
|
|
|
bool kwallet = hp->useKWallet();
|
|
|
|
|
|
|
|
// show preferences dialog
|
|
|
|
KDialogBase *dlg = new KDialogBase( 0L, "dlg", true,
|
|
|
|
i18n( "RDP Host Preferences for %1" ).arg( host->host() ),
|
|
|
|
KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true );
|
|
|
|
|
|
|
|
TQVBox *vbox = dlg->makeVBoxMainWidget();
|
|
|
|
RdpPrefs *prefs = new RdpPrefs( vbox );
|
|
|
|
TQWidget *spacer = new TQWidget( vbox );
|
|
|
|
vbox->setStretchFactor( spacer, 10 );
|
|
|
|
|
|
|
|
prefs->setRdpWidth( wv );
|
|
|
|
prefs->setRdpHeight( hv );
|
|
|
|
prefs->setResolution();
|
|
|
|
prefs->setColorDepth(cd);
|
|
|
|
prefs->setKbLayout( keymap2int( kl ) );
|
|
|
|
prefs->setShowPrefs( true );
|
|
|
|
prefs->setUseKWallet(kwallet);
|
|
|
|
|
|
|
|
if ( dlg->exec() == TQDialog::Rejected )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
wv = prefs->rdpWidth();
|
|
|
|
hv = prefs->rdpHeight();
|
|
|
|
|
|
|
|
kl = int2keymap( prefs->kbLayout() );
|
|
|
|
hp->setAskOnConnect( prefs->showPrefs() );
|
|
|
|
hp->setWidth(wv);
|
|
|
|
hp->setHeight(hv);
|
|
|
|
hp->setColorDepth( prefs->colorDepth() );
|
|
|
|
hp->setLayout(kl);
|
|
|
|
hp->setUseKWallet(prefs->useKWallet());
|
|
|
|
|
|
|
|
delete dlg;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// open a connection
|
|
|
|
bool KRdpView::start()
|
|
|
|
{
|
|
|
|
SmartPtr<RdpHostPref> hp, rdpDefaults;
|
|
|
|
bool useKWallet = false;
|
|
|
|
|
|
|
|
TQWidget *desktop = TQApplication::desktop();
|
|
|
|
|
|
|
|
if(!rdpAppDataConfigured)
|
|
|
|
{
|
|
|
|
HostPreferences *hps = HostPreferences::instance();
|
|
|
|
hp = SmartPtr<RdpHostPref>(hps->createHostPref(m_host,
|
|
|
|
RdpHostPref::RdpType));
|
|
|
|
if(hp->askOnConnect())
|
|
|
|
{
|
|
|
|
if( !editPreferences( hp ))
|
|
|
|
return false;
|
|
|
|
hps->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
useKWallet = hp->useKWallet();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_container->show();
|
|
|
|
|
|
|
|
m_process = new KProcess(m_container);
|
|
|
|
*m_process << "rdesktop";
|
|
|
|
// Check for fullscreen mode
|
|
|
|
if ((hp->width() == 0) && (hp->height() == 0)) {
|
|
|
|
launch_Fullscreen_rdp = true;
|
|
|
|
*m_process << "-g" << (TQString::number(desktop->width()) + "x" + TQString::number((desktop->height()-2)));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((hp->height() > (desktop->height()-2)) && (hp->height() <= (desktop->height()))) {
|
|
|
|
*m_process << "-g" << (TQString::number(hp->width()) + "x" + TQString::number(desktop->height()-2));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*m_process << "-g" << (TQString::number(hp->width()) + "x" + TQString::number(hp->height()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*m_process << "-k" << hp->layout();
|
|
|
|
if(!m_user.isEmpty()) { *m_process << "-u" << m_user; }
|
|
|
|
|
|
|
|
if(m_password.isEmpty() && useKWallet ) {
|
|
|
|
TQString krdc_folder = "KRDC-RDP";
|
|
|
|
|
|
|
|
// Bugfix: Check if wallet has been closed by an outside source
|
|
|
|
if ( wallet && !wallet->isOpen() ) {
|
|
|
|
delete wallet; wallet=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do we need to open the wallet?
|
|
|
|
if ( !wallet ) {
|
|
|
|
TQString walletName = KWallet::Wallet::NetworkWallet();
|
|
|
|
wallet = KWallet::Wallet::openWallet(walletName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wallet && wallet->isOpen()) {
|
|
|
|
bool walletOK = wallet->hasFolder(krdc_folder);
|
|
|
|
if (walletOK == false) {
|
|
|
|
walletOK = wallet->createFolder(krdc_folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (walletOK == true) {
|
|
|
|
wallet->setFolder(krdc_folder);
|
|
|
|
if ( wallet->hasEntry(m_host) ) {
|
|
|
|
wallet->readPassword(m_host, m_password);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_password.isEmpty() ) {
|
|
|
|
//There must not be an existing entry. Let's make one.
|
|
|
|
TQCString newPassword;
|
|
|
|
if (KPasswordDialog::getPassword(newPassword, i18n("Please enter the password.")) == KPasswordDialog::Accepted) {
|
|
|
|
m_password = newPassword;
|
|
|
|
wallet->writePassword(m_host, m_password);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!m_password.isEmpty()) {
|
|
|
|
*m_process << "-p" << m_password;
|
|
|
|
}
|
|
|
|
|
|
|
|
*m_process << "-X" << ("0x" + TQString::number(m_container->winId(), 16));
|
|
|
|
*m_process << "-a" << TQString::number(hp->colorDepth());
|
|
|
|
*m_process << (m_host + ":" + TQString::number(m_port));
|
|
|
|
connect(m_process, TQT_SIGNAL(processExited(KProcess *)), TQT_SLOT(processDied(KProcess *)));
|
|
|
|
connect(m_process, TQT_SIGNAL(receivedStderr(KProcess *, char *, int)), TQT_SLOT(receivedStderr(KProcess *, char *, int)));
|
|
|
|
connect(m_container, TQT_SIGNAL(embeddedWindowDestroyed()), TQT_SLOT(connectionClosed()));
|
|
|
|
connect(m_container, TQT_SIGNAL(newEmbeddedWindow(WId)), TQT_SLOT(connectionOpened(WId)));
|
|
|
|
qDebug("Color depth: %d", hp->colorDepth());
|
|
|
|
if(!m_process->start(KProcess::NotifyOnExit, KProcess::Stderr))
|
|
|
|
{
|
|
|
|
KMessageBox::error(0, i18n("Could not start rdesktop; make sure rdesktop is properly installed."),
|
|
|
|
i18n("rdesktop Failure"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
setStatus(REMOTE_VIEW_CONNECTING);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::switchFullscreen(bool on)
|
|
|
|
{
|
|
|
|
if(on == true)
|
|
|
|
{
|
|
|
|
m_container->grabKeyboard();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// captures pressed keys
|
|
|
|
void KRdpView::pressKey(XEvent *e)
|
|
|
|
{
|
|
|
|
m_container->x11Event(e);
|
|
|
|
m_container->grabKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KRdpView::viewOnly()
|
|
|
|
{
|
|
|
|
return m_container->m_viewOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KRdpView::startFullscreen()
|
|
|
|
{
|
|
|
|
return launch_Fullscreen_rdp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::setViewOnly(bool s)
|
|
|
|
{
|
|
|
|
m_container->m_viewOnly = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::connectionOpened(WId /*window*/)
|
|
|
|
{
|
|
|
|
TQSize size = m_container->sizeHint();
|
|
|
|
|
|
|
|
setStatus(REMOTE_VIEW_CONNECTED);
|
|
|
|
setFixedSize(size);
|
|
|
|
m_container->setFixedSize(size);
|
|
|
|
emit changeSize(size.width(), size.height());
|
|
|
|
emit connected();
|
|
|
|
setFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::connectionClosed()
|
|
|
|
{
|
|
|
|
emit disconnected();
|
|
|
|
setStatus(REMOTE_VIEW_DISCONNECTED);
|
|
|
|
m_quitFlag = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::processDied(KProcess */*proc*/)
|
|
|
|
{
|
|
|
|
if(m_status == REMOTE_VIEW_CONNECTING)
|
|
|
|
{
|
|
|
|
setStatus(REMOTE_VIEW_DISCONNECTED);
|
|
|
|
if(m_clientVersion.isEmpty())
|
|
|
|
{
|
|
|
|
KMessageBox::error(0, i18n("Connection attempt to host failed."),
|
|
|
|
i18n("Connection Failure"));
|
|
|
|
}
|
|
|
|
emit disconnectedError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KRdpView::receivedStderr(KProcess */*proc*/, char *buffer, int /*buflen*/)
|
|
|
|
{
|
|
|
|
TQString output(buffer);
|
|
|
|
TQString line;
|
|
|
|
int i = 0;
|
|
|
|
while(!(line = output.section('\n', i, i)).isEmpty())
|
|
|
|
{
|
|
|
|
if(line.startsWith("Version "))
|
|
|
|
{
|
|
|
|
m_clientVersion = line.section(' ', 1, 1);
|
|
|
|
m_clientVersion = m_clientVersion.left(m_clientVersion.length() - 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "krdpview.moc"
|