/***************************************************************************
                          krdc.cpp  -  main window
                             -------------------
    begin                : Tue May 13 23:07:42 CET 2002
    copyright            : (C) 2002-2003 by Tim Jansen
                           (C) 2003 Nadeem Hasan <nhasan@kde.org>
    email                : tim@tjansen.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "krdc.h"
#include "maindialog.h"
#include "hostpreferences.h"

#include <tdeapplication.h>
#include <tdeconfig.h>
#include <kdebug.h>
#include <kcombobox.h>
#include <kurl.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdetoolbar.h>
#include <tdetoolbarbutton.h>
#include <tdepopupmenu.h>
#include <tdemessagebox.h>
#include <twin.h>
#include <tdestartupinfo.h>
#include <tqclipboard.h>

#include <tqdockarea.h>
#include <tqlabel.h>
#include <tqwhatsthis.h>
#include <tqtooltip.h>

#define BUMP_SCROLL_CONSTANT (200)

const int VIEW_ONLY_ID = 10;
const int SHOW_LOCAL_CURSOR_ID = 20;

const int FS_AUTOHIDE_ID = 1;
const int FS_FULLSCREEN_ID = 2;
const int FS_SCALE_ID = 3;
const int FS_HOSTLABEL_ID = 4;
const int FS_ADVANCED_ID = 5;
const int FS_ICONIFY_ID = 6;
const int FS_CLOSE_ID = 7;
const int FS_PASTE_ID = 8;

const int KRDC::TOOLBAR_AUTOHIDE_TIMEOUT = 1000;
const int KRDC::TOOLBAR_FPS_1000 = 10000;
const int KRDC::TOOLBAR_SPEED_DOWN = 34;
const int KRDC::TOOLBAR_SPEED_UP = 20;

TQScrollView2::TQScrollView2(TQWidget *w, const char *name) :
	TQScrollView(w, name) {
	setMouseTracking(true);
        viewport()->setMouseTracking(true);
        horizontalScrollBar()->setMouseTracking(true);
        verticalScrollBar()->setMouseTracking(true);
}

void TQScrollView2::mouseMoveEvent( TQMouseEvent *e )
{
         e->ignore();
}


TQString KRDC::m_lastHost = "";

KRDC::KRDC(WindowMode wm, const TQString &host,
	   Quality q, const TQString &encodings,
	   const TQString &password,
	   bool scale,
	   bool localCursor,
	   TQSize initialWindowSize) :
  TQWidget(0, 0, TQt::WStyle_ContextHelp),
  m_layout(0),
  m_scrollView(0),
  m_view(0),
  m_fsToolbar(0),
  m_toolbar(0),
  m_dockArea(0),
  m_popup(0),
  m_ftAutoHide(false),
  m_showProgress(false),
  m_host(host),
  m_protocol(PROTOCOL_AUTO),
  m_quality(q),
  m_encodings(encodings),
  m_password(password),
  m_isFullscreen(wm),
  m_oldResolution(),
  m_fullscreenMinimized(false),
  m_windowScaling(scale),
  m_localCursor(localCursor),
  m_initialWindowSize(initialWindowSize)
{
	connect(&m_autoHideTimer, TQ_SIGNAL(timeout()), TQ_SLOT(hideFullscreenToolbarNow()));
	connect(&m_bumpScrollTimer, TQ_SIGNAL(timeout()), TQ_SLOT(bumpScroll()));

	m_pindown = UserIcon("pindown");
	m_pinup   = UserIcon("pinup");

	m_keyCaptureDialog = new KeyCaptureDialog(0, 0);

	setMouseTracking(true);

	TDEStartupInfo::appStarted();
}

bool KRDC::start()
{
	TQString userName, password;
	TQString serverHost;
	int serverPort = 5900;
	int ret_status;

	if (!m_host.isNull() &&
	    (m_host != "vnc:/") &&
	    (m_host != "rdp:/")) {
		if (m_host.startsWith("vnc:/"))
			m_protocol = PROTOCOL_VNC;
		if (m_host.startsWith("rdp:/"))
			m_protocol = PROTOCOL_RDP;
		if (!parseHost(m_host, m_protocol, serverHost, serverPort,
			       userName, password)) {
			KMessageBox::error(0,
			   i18n("The entered host does not have the required form."),
			   i18n("Malformed URL or Host"));
			emit disconnectedError();
			return true;
		}
	} else {

		MainDialog mainDlg(this, "MainDialog");
		mainDlg.setRemoteHost(m_lastHost);

		if (mainDlg.exec() == TQDialog::Rejected) {
			return false;
		}

		TQString m_host = mainDlg.remoteHost();
		m_lastHost = m_host;
		if (m_host.startsWith("vnc:/"))
			m_protocol = PROTOCOL_VNC;
		if (m_host.startsWith("rdp:/"))
			m_protocol = PROTOCOL_RDP;
		if (!parseHost(m_host, m_protocol, serverHost, serverPort,
			       userName, password)) {
			KMessageBox::error(0,
					i18n("The entered host does not have the required form."),
					i18n("Malformed URL or Host"));
			emit disconnectedError();
			return true;
		}
	}

	setCaption(i18n("%1 - Remote Desktop Connection").arg(serverHost));

	m_scrollView = new TQScrollView2(this, "remote scrollview");
	m_scrollView->setFrameStyle(TQFrame::NoFrame);
	m_scrollView->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding,
					TQSizePolicy::Expanding));

	switch(m_protocol)
	{
		case PROTOCOL_AUTO:
			// fall through

		case PROTOCOL_VNC:
			m_view = new KVncView(this, 0, serverHost, serverPort,
			                      m_password.isNull() ? password : m_password,
			                      m_quality,
			                      m_localCursor ? DOT_CURSOR_ON : DOT_CURSOR_AUTO,
			                      m_encodings);
			break;

		case PROTOCOL_RDP:
			m_view = new KRdpView(this, 0, serverHost, serverPort,
			                      userName, m_password.isNull() ? password : m_password);
			break;
	}

	m_view->setViewOnly(kapp->config()->readBoolEntry("viewOnly", false));

	m_scrollView->addChild(m_view);
	TQWhatsThis::add(m_view, i18n("Here you can see the remote desktop. If the other side allows you to control it, you can also move the mouse, click or enter keystrokes. If the content does not fit your screen, click on the toolbar's full screen button or scale button. To end the connection, just close the window."));

	connect(m_view, TQ_SIGNAL(changeSize(int,int)), TQ_SLOT(setSize(int,int)));
	connect(m_view, TQ_SIGNAL(connected()), TQ_SLOT(show()));
	connect(m_view, TQ_SIGNAL(disconnected()), TQ_SIGNAL(disconnected()));
	// note that the disconnectedError() will be disconnected when kremoteview
	// is completely initialized
	connect(m_view, TQ_SIGNAL(disconnectedError()), TQ_SIGNAL(disconnectedError()));
	connect(m_view, TQ_SIGNAL(statusChanged(RemoteViewStatus)),
		TQ_SLOT(changeProgress(RemoteViewStatus)));
	connect(m_view, TQ_SIGNAL(showingPasswordDialog(bool)),
		TQ_SLOT(showingPasswordDialog(bool)));
	connect(m_keyCaptureDialog, TQ_SIGNAL(keyPressed(XEvent*)),
		m_view, TQ_SLOT(pressKey(XEvent*)));

	ret_status = m_view->start();

	return ret_status;
}

void KRDC::changeProgress(RemoteViewStatus s) {
	if (!m_progressDialog) {
		m_progressDialog = new KProgressDialog(0, 0, TQString(),
				   "1234567890", false);
		m_progressDialog->showCancelButton(true);
		m_progressDialog->setMinimumDuration(0x7fffffff);//disable effectively
		m_progress = m_progressDialog->progressBar();
		m_progress->setTextEnabled(false);
		m_progress->setTotalSteps(3);
		connect(m_progressDialog, TQ_SIGNAL(cancelClicked()),
			TQ_SIGNAL(disconnectedError()));
	}

	if (s == REMOTE_VIEW_CONNECTING) {
		m_progress->setValue(0);
		m_progressDialog->setLabel(i18n("Establishing connection..."));
		m_progressDialog->setAllowCancel(false);
		showProgressDialog();
	}
	else if (s == REMOTE_VIEW_AUTHENTICATING) {
		m_progress->setValue(1);
		m_progressDialog->setLabel(i18n("Authenticating..."));
		m_progressDialog->setAllowCancel(true);
	}
	else if (s == REMOTE_VIEW_PREPARING) {
		m_progress->setValue(2);
		m_progressDialog->setLabel(i18n("Preparing desktop..."));
	}
	else if ((s == REMOTE_VIEW_CONNECTED) ||
		 (s == REMOTE_VIEW_DISCONNECTED)) {
		m_progress->setValue(3);
		hideProgressDialog();
		if (s == REMOTE_VIEW_CONNECTED) {
			TQObject::disconnect(m_view, TQ_SIGNAL(disconnectedError()),
					    this, TQ_SIGNAL(disconnectedError()));
			connect(m_view, TQ_SIGNAL(disconnectedError()),
				TQ_SIGNAL(disconnected()));
			if (m_view->startFullscreen()) {
				// m_view instance is asking to start in fullscreen mode
				enableFullscreen(true);
			}
		}
		else if (m_isFullscreen == WINDOW_MODE_FULLSCREEN)
			switchToNormal(m_view->scaling());
	}
}

void KRDC::showingPasswordDialog(bool b) {
	if (!m_progressDialog)
		return;
	if (b)
		hideProgressDialog();
	else
		showProgressDialog();
}

void KRDC::showProgressDialog() {
	m_showProgress = true;
	TQTimer::singleShot(400, this, TQ_SLOT(showProgressTimeout()));
}

void KRDC::hideProgressDialog() {
	m_showProgress = false;
	m_progressDialog->hide();
}

void KRDC::showProgressTimeout() {
	if (!m_showProgress)
		return;

	m_progressDialog->setMinimumSize(300, 50);
	m_progressDialog->show();
}

void KRDC::quit() {
	m_view->releaseKeyboard();
	hide();
	vidmodeNormalSwitch(tqt_xdisplay(), m_oldResolution);
	if (m_view)
		m_view->startQuitting();
	emit disconnected();
}

bool KRDC::parseHost(TQString &str, Protocol &prot, TQString &serverHost, int &serverPort,
		     TQString &userName, TQString &password) {
	TQString s = str;
	userName = TQString();
	password = TQString();

	if (prot == PROTOCOL_AUTO) {
		if(s.startsWith("smb:/")>0) {  //we know it's more likely to be windows..
			s = "rdp:/" + s.section("smb:/", 1);
			prot = PROTOCOL_RDP;
		} else if(s.contains("://") > 0) {
			s = s.section("://",1);
		} else if(s.contains(":/") > 0) {
			s = s.section(":/", 1);
		}
	}
	if (prot == PROTOCOL_AUTO || prot == PROTOCOL_VNC) {
		if (s.startsWith(":"))
			s = "localhost" + s;
		if (!s.startsWith("vnc:/"))
			s = "vnc://" + s;
		else if (!s.startsWith("vnc://")) // TODO: fix this in KURL!
			s.insert(4, '/');
	}
	if (prot == PROTOCOL_RDP) {
		if (!s.startsWith("rdp:/"))
			s = "rdp://" + s;
		else if (!s.startsWith("rdp://")) // TODO: fix this in KURL!
			s.insert(4, '/');
	}

	KURL url(s);
	if (!url.isValid())
		return false;
	serverHost = url.host();
	if (serverHost.isEmpty())
		serverHost = "localhost";
	serverPort = url.port();
	if ((prot == PROTOCOL_AUTO || prot == PROTOCOL_VNC) && serverPort < 100)
		serverPort += 5900;
	if (url.hasUser())
		userName = url.user();
	if (url.hasPass())
		password = url.pass();

	if (url.port()) {
		if (url.hasUser())
			str = TQString("%1@%2:%3").arg(userName).arg(serverHost).arg(url.port());
		else
			str = TQString("%1:%2").arg(serverHost).arg(url.port());
	}
	else {
		if (url.hasUser())
			str = TQString("%1@%2").arg(userName).arg(serverHost);
		else
			str = TQString("%1").arg(serverHost);
	}
	return true;
}

KRDC::~KRDC()
{
	// kill explicitly to avoid xlib calls by the threads after closing the window!
	if (m_view)
		delete m_view;
}

void KRDC::enableFullscreen(bool on)
{
	if (on) {
		if (m_isFullscreen != WINDOW_MODE_FULLSCREEN)
			switchToFullscreen(m_view->scaling());
	}
	else {
		if (m_isFullscreen != WINDOW_MODE_NORMAL)
			switchToNormal(m_view->scaling() || m_windowScaling);
	}
	m_view->switchFullscreen(on);
}

void KRDC::paste()
{
	TQClipboard *cb = TQApplication::clipboard();
	TQString text = cb->text(TQClipboard::Clipboard);
	m_view->sendString(text);
}

TQSize KRDC::sizeHint()
{
	if ((m_isFullscreen != WINDOW_MODE_FULLSCREEN) && m_toolbar) {
		int dockHint = m_dockArea->sizeHint().height();
		dockHint = dockHint < 1 ? 1 : dockHint; // fix wrong size hint
		return TQSize(m_view->framebufferSize().width(),
			  dockHint + m_view->framebufferSize().height());
	}
	else
		return m_view->framebufferSize();
}

TQPopupMenu *KRDC::createPopupMenu(TQWidget *parent) const {
	TDEPopupMenu *pu = new TDEPopupMenu(parent);
	pu->insertItem(i18n("View Only"), this, TQ_SLOT(viewOnlyToggled()), 0, VIEW_ONLY_ID);
	pu->setCheckable(true);
	pu->setItemChecked(VIEW_ONLY_ID, m_view->viewOnly());
	if (m_view->supportsLocalCursor()) {
		pu->insertItem(i18n("Always Show Local Cursor"), this,
			TQ_SLOT(showLocalCursorToggled()), 0,
			SHOW_LOCAL_CURSOR_ID);
		pu->setCheckable(true);
		pu->setItemChecked(SHOW_LOCAL_CURSOR_ID,
			m_view->dotCursorState() == DOT_CURSOR_ON);
	}
	return pu;
}

void KRDC::switchToFullscreen(bool scaling)
{
	int x, y;

	bool fromFullscreen = (m_isFullscreen == WINDOW_MODE_FULLSCREEN);

	TQDesktopWidget* desktopWidget = TQApplication::desktop();
	//int activeXineramaScreen = desktopWidget->screenNumber(this);
	int activeXineramaScreen = desktopWidget->screenNumber(TQCursor::pos());
	if (activeXineramaScreen < 0) {
		activeXineramaScreen = 0;
	}
	TQRect desktopScreenGeometry = desktopWidget->screenGeometry(activeXineramaScreen);
	TQSize ds = desktopScreenGeometry.size();

	TQSize fbs = m_view->framebufferSize();
	bool scalingPossible = m_view->supportsScaling() &&
	  ((fbs.width() >= ds.width()) || (fbs.height() >= ds.height()));

	if (!fromFullscreen) {
		hide();
		m_oldResolution = vidmodeFullscreenSwitch(tqt_xdisplay(),
							  m_desktopWidget.screenNumber(this),
							  fbs.width(),
							  fbs.height(),
							  x, y);
		if (m_oldResolution.valid) {
			m_fullscreenResolution = TQSize(x, y);
		}
		else {
			m_fullscreenResolution = ds;
		}
		m_isFullscreen = WINDOW_MODE_FULLSCREEN;
		if (!scalingPossible) {
			m_windowScaling = m_view->scaling();
		}
	}

	if (m_toolbar) {
		m_toolbar->hide();
		m_toolbar->deleteLater();
		m_toolbar = 0;
		m_dockArea->hide();
		m_dockArea->deleteLater();
		m_dockArea = 0;
	}
	if (m_popup) {
		m_popup->deleteLater();
		m_popup = 0;
	}
	if (m_fsToolbar) {
		m_fsToolbar->hide();
		m_fsToolbar->deleteLater();
		m_fsToolbar = 0;
	}

	if (m_layout)
		delete m_layout;
	m_layout = new TQVBoxLayout(this);
	m_layout->addWidget(m_scrollView);

	if (scalingPossible) {
		m_view->enableScaling(scaling);
		if (scaling)
			m_view->resize(ds);
		else
			m_view->resize(fbs);
		repositionView(true);
	}
	else {
		m_view->enableScaling(false);
	}

	m_fsToolbar = new KFullscreenPanel(this, "fstoolbar", m_fullscreenResolution);
	connect(m_fsToolbar, TQ_SIGNAL(mouseEnter()), TQ_SLOT(showFullscreenToolbar()));
	connect(m_fsToolbar, TQ_SIGNAL(mouseLeave()), TQ_SLOT(hideFullscreenToolbarDelayed()));

	TDEToolBar *t = new TDEToolBar(m_fsToolbar);
	m_fsToolbarWidget = t;
	t->setIconSize(16);

	TQIconSet pinIconSet;
	pinIconSet.setPixmap(m_pinup, TQIconSet::Automatic, TQIconSet::Normal, TQIconSet::On);
	pinIconSet.setPixmap(m_pindown, TQIconSet::Automatic, TQIconSet::Normal, TQIconSet::Off);
	t->insertButton("pinup", FS_AUTOHIDE_ID);
	TDEToolBarButton *pinButton = t->getButton(FS_AUTOHIDE_ID);
	pinButton->setIconSet(pinIconSet);
	TQToolTip::add(pinButton, i18n("Autohide on/off"));
	t->setToggle(FS_AUTOHIDE_ID);
	t->addConnection(FS_AUTOHIDE_ID, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(setFsToolbarAutoHide(bool)));

	t->insertButton("view-restore", FS_FULLSCREEN_ID);
	TDEToolBarButton *fullscreenButton = t->getButton(FS_FULLSCREEN_ID);
	TQToolTip::add(fullscreenButton, i18n("Fullscreen"));
	t->setToggle(FS_FULLSCREEN_ID);
	t->setButton(FS_FULLSCREEN_ID, true);
	t->addConnection(FS_FULLSCREEN_ID, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableFullscreen(bool)));

	if(m_view->supportsSendString())
	{
		t->insertButton("edit-paste", FS_PASTE_ID);
		TDEToolBarButton *pasteButton = t->getButton(FS_PASTE_ID);
		TQToolTip::add(pasteButton, i18n("Sends clipboard text to the remote system as key presses"));
		t->addConnection(FS_PASTE_ID, TQ_SIGNAL(clicked()), this, TQ_SLOT(paste()));
	}

	m_popup = createPopupMenu(t);
	t->insertButton("configure", FS_ADVANCED_ID, m_popup, true, i18n("Advanced options"));
	TDEToolBarButton *advancedButton = t->getButton(FS_ADVANCED_ID);
	TQToolTip::add(advancedButton, i18n("Advanced options"));

	TQLabel *hostLabel = new TQLabel(t);
	hostLabel->setName("tde toolbar widget");
	hostLabel->setAlignment(TQt::AlignCenter);
	hostLabel->setText("   "+m_host+"   ");
	t->insertWidget(FS_HOSTLABEL_ID, 150, hostLabel);
	t->setItemAutoSized(FS_HOSTLABEL_ID, true);

	if (scalingPossible) {
		t->insertButton("zoom-fit-best", FS_SCALE_ID);
		TDEToolBarButton *scaleButton = t->getButton(FS_SCALE_ID);
		TQToolTip::add(scaleButton, i18n("Scale view"));
		t->setToggle(FS_SCALE_ID);
		t->setButton(FS_SCALE_ID, scaling);
		t->addConnection(FS_SCALE_ID, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(switchToFullscreen(bool)));
	}

	t->insertButton("iconify", FS_ICONIFY_ID);
	TDEToolBarButton *iconifyButton = t->getButton(FS_ICONIFY_ID);
	TQToolTip::add(iconifyButton, i18n("Minimize"));
	t->addConnection(FS_ICONIFY_ID, TQ_SIGNAL(clicked()), this, TQ_SLOT(iconify()));

	t->insertButton("close", FS_CLOSE_ID);
	TDEToolBarButton *closeButton = t->getButton(FS_CLOSE_ID);
	TQToolTip::add(closeButton, i18n("Close"));
	t->addConnection(FS_CLOSE_ID, TQ_SIGNAL(clicked()), this, TQ_SLOT(quit()));

	m_fsToolbar->setChild(t);

	repositionView(true);

	setMaximumSize(m_fullscreenResolution.width(),
		       m_fullscreenResolution.height());
	setGeometry(desktopScreenGeometry.x(), desktopScreenGeometry.y(), m_fullscreenResolution.width(),
		    m_fullscreenResolution.height());

	KWin::setState(winId(), NET::StaysOnTop);

	if (m_ftAutoHide == false) {
		showFullscreenToolbar();
	}
	else {
		t->setButton(FS_AUTOHIDE_ID, true);
	}

	if (!fromFullscreen) {
		if (m_oldResolution.valid)
			grabInput(tqt_xdisplay(), winId());
		m_view->grabKeyboard();
	}

	showFullScreen();

	m_view->switchFullscreen( true );
}

void KRDC::switchToNormal(bool scaling)
{
	bool fromFullscreen = (m_isFullscreen == WINDOW_MODE_FULLSCREEN);
	bool scalingChanged = (scaling != m_view->scaling());
	m_windowScaling = false; // delete remembered scaling value
	if (fromFullscreen) {
		KWin::clearState(winId(), NET::StaysOnTop);
		hide();
	}
	m_isFullscreen = WINDOW_MODE_NORMAL;
	m_view->enableScaling(scaling);

	m_view->releaseKeyboard();
	if (m_oldResolution.valid) {
		ungrabInput(tqt_xdisplay());
		vidmodeNormalSwitch(tqt_xdisplay(), m_oldResolution);
		m_oldResolution = Resolution();
	}

	if (m_fsToolbar) {
		m_fsToolbar->hide();
		m_fsToolbar->deleteLater();
		m_fsToolbar = 0;
	}

	if (!m_toolbar) {
		m_dockArea = new TQDockArea(TQt::Horizontal, TQDockArea::Normal, this);
		m_dockArea->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding,
					TQSizePolicy::Fixed));
		TDEToolBar *t = new TDEToolBar(m_dockArea);
		m_toolbar = t;
		t->setIconText(TDEToolBar::IconTextRight);
		connect(t, TQ_SIGNAL(placeChanged(TQDockWindow::Place)), TQ_SLOT(toolbarChanged()));
		t->insertButton("view-fullscreen", 0, true, i18n("Fullscreen"));
		TDEToolBarButton *fullscreenButton = t->getButton(0);
		TQToolTip::add(fullscreenButton, i18n("Fullscreen"));
		TQWhatsThis::add(fullscreenButton, i18n("Switches to full screen. If the remote desktop has a different screen resolution, Remote Desktop Connection will automatically switch to the nearest resolution."));
		t->setToggle(0);
		t->setButton(0, false);
		t->addConnection(0, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(enableFullscreen(bool)));

		if (m_view->supportsScaling()) {
			t->insertButton("zoom-fit-best", 1, true, i18n("Scale"));
			TDEToolBarButton *scaleButton = t->getButton(1);
			TQToolTip::add(scaleButton, i18n("Scale view"));
			TQWhatsThis::add(scaleButton, i18n("This option scales the remote screen to fit your window size."));
			t->setToggle(1);
			t->setButton(1, scaling);
			t->addConnection(1, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(switchToNormal(bool)));
		}

		t->insertButton("key_enter", 2, true, i18n("Special Keys"));
		TDEToolBarButton *skButton = t->getButton(2);
		TQToolTip::add(skButton, i18n("Enter special keys."));
		TQWhatsThis::add(skButton, i18n("This option allows you to send special key combinations like Ctrl-Alt-Del to the remote host."));
		t->addConnection(2, TQ_SIGNAL(clicked()), m_keyCaptureDialog, TQ_SLOT(execute()));

		if (m_popup) {
			m_popup->deleteLater();
			m_popup = 0;
		}

		if(m_view->supportsSendString())
		{
			t->insertButton("edit-paste", 4, true, i18n("Paste"));
			TDEToolBarButton *pasteButton = t->getButton(4);
			TQToolTip::add(pasteButton, i18n("Sends clipboard text to the remote system as key presses"));
			t->addConnection(4, TQ_SIGNAL(clicked()), this, TQ_SLOT(paste()));
		}

		m_popup = createPopupMenu(t);
		t->insertButton("configure", 3, m_popup, true, i18n("Advanced"));
		TDEToolBarButton *advancedButton = t->getButton(3);
		TQToolTip::add(advancedButton, i18n("Advanced options"));

		if (m_layout)
			delete m_layout;
		m_layout = new TQVBoxLayout(this);
		m_layout->addWidget(m_dockArea);
		m_layout->addWidget(m_scrollView);
		m_layout->setGeometry(TQRect(0, 0, m_scrollView->width(),
		                            m_dockArea->height() + m_scrollView->height()));
	}

	if (scaling) {
		m_scrollView->installEventFilter(this);
		m_view->resize(m_scrollView->size());
	}
	else {
		m_scrollView->removeEventFilter(this);
		m_view->resize(m_view->framebufferSize());
	}

	setMaximumSize(sizeHint());

	repositionView(false);


	if (!fromFullscreen) {
		if (m_initialWindowSize.isValid()) {
			resize(m_initialWindowSize);
			m_initialWindowSize = TQSize();
		}
		else if (!scalingChanged)
			resize(sizeHint());
		show();
		if (scalingChanged)
			m_view->update();
	}
	else
		showNormal();
}

void KRDC::viewOnlyToggled() {
	bool s = !m_view->viewOnly();
	m_popup->setItemChecked(VIEW_ONLY_ID, s);
	m_view->setViewOnly(s);
}

void KRDC::showLocalCursorToggled() {
	bool s = (m_view->dotCursorState() != DOT_CURSOR_ON);
	m_popup->setItemChecked(SHOW_LOCAL_CURSOR_ID, s);
	m_view->showDotCursor(s ? DOT_CURSOR_ON : DOT_CURSOR_AUTO);
}

void KRDC::iconify()
{
	KWin::clearState(winId(), NET::StaysOnTop);

	m_view->releaseKeyboard();
	if (m_oldResolution.valid)
		ungrabInput(tqt_xdisplay());

	vidmodeNormalSwitch(tqt_xdisplay(), m_oldResolution);
	m_oldResolution = Resolution();
	showNormal();
	showMinimized();
	m_fullscreenMinimized = true;
}

void KRDC::toolbarChanged() {
	setMaximumSize(sizeHint());

	// resize window when toolbar is docked and it was maximized
	TQSize fs = m_view->framebufferSize();
	TQSize cs = size();
	TQSize cs1(cs.width(), cs.height()-1); // adjusted for TQDockArea.height()==1
	if ((fs == cs) || (fs == cs1))
		resize(sizeHint());
}


bool KRDC::event(TQEvent *e) {
	/* used to change resolution when fullscreen was minimized */
        if ((!m_fullscreenMinimized) || (e->type() != TQEvent::WindowActivate))
		return TQWidget::event(e);

	m_fullscreenMinimized = false;
	int x, y;
	m_oldResolution = vidmodeFullscreenSwitch(tqt_xdisplay(),
						  m_desktopWidget.screenNumber(this),
						  m_view->width(),
						  m_view->height(),
						  x, y);
	if (m_oldResolution.valid) {
		m_fullscreenResolution = TQSize(x, y);
	}
	else {
		m_fullscreenResolution = TQApplication::desktop()->size();
	}

	showFullScreen();
	setGeometry(0, 0, m_fullscreenResolution.width(),
		    m_fullscreenResolution.height());
	if (m_oldResolution.valid)
		grabInput(tqt_xdisplay(), winId());
	m_view->switchFullscreen( true );
	KWin::setState(winId(), NET::StaysOnTop);

	return TQWidget::event(e);
}

bool KRDC::eventFilter(TQObject *watched, TQEvent *e) {
	/* used to get events from TQScrollView  on resize  for scale mode*/
	if (watched != m_scrollView)
		return false;
	if (e->type() != TQEvent::Resize)
		return false;

	TQResizeEvent *re = (TQResizeEvent*) e;
	m_view->resize(re->size());
	return false;
}

void KRDC::setSize(int w, int h)
{
	int dw, dh;

	TQWidget *desktop = TQApplication::desktop();
	dw = desktop->width();
	dh = desktop->height();

	switch (m_isFullscreen) {
	case WINDOW_MODE_AUTO:
		if ((w > dw) || (h > dh))
			switchToFullscreen(m_windowScaling);
		else
			switchToNormal(m_windowScaling);
		break;
	case WINDOW_MODE_NORMAL:
		switchToNormal(m_windowScaling);
		break;
	case WINDOW_MODE_FULLSCREEN:
		switchToFullscreen(m_windowScaling);
 	        break;
	}
}

void KRDC::repositionView(bool fullscreen) {
	int ox = 0;
	int oy = 0;

	if (!m_scrollView)
		return;

	TQSize s = m_view->size();

	if (fullscreen) {
		TQSize d = m_fullscreenResolution;
		bool margin = false;
		if (d.width() > s.width())
			ox = (d.width() - s.width()) / 2;
		else if (d.width() < s.width())
			margin = true;

		if (d.height() > s.height())
			oy = (d.height() - s.height()) / 2;
		else if (d.height() < s.height())
			margin = true;

		if (margin)
			m_layout->setMargin(1);
	}

	m_scrollView->moveChild(m_view, ox, oy);
}

void KRDC::toggleFsToolbarAutoHide() {
	setFsToolbarAutoHide(!m_ftAutoHide);
}

void KRDC::setFsToolbarAutoHide(bool on) {

	if (on == m_ftAutoHide)
		return;
	if (m_isFullscreen != WINDOW_MODE_FULLSCREEN)
		return;

	m_ftAutoHide = on;
	if (!on)
		showFullscreenToolbar();
}

void KRDC::hideFullscreenToolbarNow() {
	if (m_fsToolbar && m_ftAutoHide)
		m_fsToolbar->startHide();
}

void KRDC::bumpScroll() {
	int x = TQCursor::pos().x();
	int y = TQCursor::pos().y();
	TQSize s = m_view->size();
	TQSize d = m_fullscreenResolution;

	if (d.width() < s.width()) {
		if (x == 0)
			m_scrollView->scrollBy(-BUMP_SCROLL_CONSTANT, 0);
		else if (x == d.width()-1)
			m_scrollView->scrollBy(BUMP_SCROLL_CONSTANT, 0);
	}
	if (d.height() < s.height()) {
		if (y == 0)
			m_scrollView->scrollBy(0, -BUMP_SCROLL_CONSTANT);
		else if (y == d.height()-1)
			m_scrollView->scrollBy(0, BUMP_SCROLL_CONSTANT);
	}

	m_bumpScrollTimer.start(333, true);
}

void KRDC::showFullscreenToolbar() {
	m_fsToolbar->startShow();
	m_autoHideTimer.stop();
}

void KRDC::hideFullscreenToolbarDelayed() {
	if (!m_autoHideTimer.isActive())
		m_autoHideTimer.start(TOOLBAR_AUTOHIDE_TIMEOUT, true);
}

void KRDC::mouseMoveEvent(TQMouseEvent *e) {
	if (m_isFullscreen != WINDOW_MODE_FULLSCREEN)
		return;

	int x = e->x();
	int y = e->y();

	/* Bump Scrolling */

	TQSize s = m_view->size();
	TQSize d = m_fullscreenResolution;
	if ((d.width() < s.width()) || d.height() < s.height()) {
 		if ((x == 0) || (x >= d.width()-1) ||
		    (y == 0) || (y >= d.height()-1))
			bumpScroll();
		else
			m_bumpScrollTimer.stop();
	}

	/* Toolbar autohide */

	if (!m_ftAutoHide)
		return;

	int dw = d.width();
	int w = m_fsToolbar->width();
	int x1 = (dw - w)/4;
	int x2 = dw - x1;

	if (((y <= 0) && (x >= x1) && (x <= x2)))
		showFullscreenToolbar();
	else
		hideFullscreenToolbarDelayed();
	e->accept();
}

void KRDC::setLastHost(const TQString &lastHost) {
	m_lastHost = lastHost;
}

#include "krdc.moc"
