VBoxConsoleWnd.cpp revision 00bd52bed859dd5801fd87e7006a04cfc4a647ff
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* VBoxConsoleWnd class implementation
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "VBoxConsoleWnd.h"
#include "VBoxConsoleView.h"
#include "VBoxCloseVMDlg.h"
#include "VBoxTakeSnapshotDlg.h"
#include "VBoxDiskImageManagerDlg.h"
#include "VBoxVMFirstRunWzd.h"
#include "VBoxSharedFoldersSettings.h"
#include "VBoxVMInformationDlg.h"
#include "VBoxDownloaderWgt.h"
#include "VBoxGlobal.h"
#include "QIStateIndicator.h"
#include "QIStatusBar.h"
#include "QIHotKeyEdit.h"
/* Qt includes */
#include <QActionGroup>
#include <QDesktopWidget>
#include <QMenuBar>
#include <QFileInfo>
#include <QDir>
#include <QTimer>
#ifdef Q_WS_X11
# include <QX11Info>
#endif
#include <VBox/VBoxGuest.h>
#if defined(Q_WS_X11)
#include <XKeyboard.h>
#endif
#ifdef Q_WS_MAC
#include "VBoxUtils.h"
#include "VBoxIChatTheaterWrapper.h"
/* Qt includes */
#include <QPainter>
#endif
#ifdef VBOX_WITH_DEBUGGER_GUI
#endif
/** class StatusTipEvent
*
* The StatusTipEvent class is an auxiliary QEvent class
* for carrying statusTip text of non-QAction menu item's.
* This event is posted then the menu item is highlighted but
* processed later in VBoxConsoleWnd::event() handler to
* avoid statusBar messaging collisions.
*/
class StatusTipEvent : public QEvent
{
public:
};
#ifdef RT_OS_DARWIN
class Q3Http;
class Q3HttpResponseHeader;
#endif
/** \class VBoxConsoleWnd
*
* The VBoxConsoleWnd class is a VM console window, one of two main VBox
* GUI windows.
*
* This window appears when the user starts the virtual machine. It
* contains the VBoxConsoleView widget that acts as a console of the
* running virtual machine.
*/
/**
* Constructs the VM console window.
*
* @param aSelf pointer to a variable where to store |this| right after
* this object's constructor is called (necessary to avoid
* recursion in VBoxGlobal::consoleWnd())
*/
, mMainMenu (0)
#ifdef VBOX_WITH_DEBUGGER_GUI
#endif
, console (0)
, no_auto_close (false)
, mIsFullscreen (false)
, mIsSeamless (false)
, mIsSeamlessSupported (false)
, mIsGraphicsSupported (false)
, was_max (false)
, console_style (0)
, mIsOpenViewFinished (false)
, mIsFirstTimeStarted (false)
, mIsAutoSaveMedia (true)
#ifdef VBOX_WITH_DEBUGGER_GUI
#endif
#ifdef Q_WS_MAC
#endif
{
if (aSelf)
*aSelf = this;
idle_timer = new QTimer (this);
/* The default application icon (will change to the VM-specific icon in
* openView()). On Win32, it's built-in to the executable. On Mac OS X the
* icon referenced in info.plist is used. */
#endif
/* ensure status bar is created */
setStatusBar (new QIStatusBar (this));
///// Actions ///////////////////////////////////////////////////////////
/* a group for all actions that are enabled only when the VM is running.
* Note that only actions whose enabled state depends exclusively on the
* execution state of the VM are added to this group. */
mRunningActions = new QActionGroup (this);
mRunningActions->setExclusive (false);
/* a group for all actions that are enabled when the VM is running or
* paused. Note that only actions whose enabled state depends exclusively
* on the execution state of the VM are added to this group. */
mRunningOrPausedActions = new QActionGroup (this);
mRunningOrPausedActions->setExclusive (false);
/* VM menu actions */
vmFullscreenAction = new QAction (this);
vmFullscreenAction->setCheckable (true);
vmSeamlessAction = new QAction (this);
vmSeamlessAction->setCheckable (true);
vmAutoresizeGuestAction->setCheckable (true);
vmAutoresizeGuestAction->setEnabled (false);
vmAdjustWindowAction = new QAction (this);
":/adjust_win_size_disabled_16px.png"));
":/hostkey_disabled_16px.png"));
#if defined(Q_WS_X11)
":/hostkey_disabled_16px.png"));
#endif
":/reset_disabled_16px.png"));
vmPauseAction = new QAction (this);
vmPauseAction->setCheckable (true);
vmCloseAction = new QAction (this);
":/take_snapshot_16px.png", ":/take_snapshot_dis_16px.png"));
vmShowInformationDlgAction = new QAction (this);
":/description_16px.png", ":/description_disabled_16px.png"));
vmDisableMouseIntegrAction = new QAction (this);
":/mouse_can_seamless_16px.png", ":/mouse_can_seamless_disabled_16px.png"));
vmDisableMouseIntegrAction->setCheckable (true);
/* Devices menu actions */
devicesUnmountFloppyAction = new QAction (this);
":/fd_unmount_dis_16px.png"));
devicesUnmountDVDAction = new QAction (this);
":/cd_unmount_dis_16px.png"));
":/shared_folder_disabled_16px.png"));
":/vrdp_disabled_16px.png"));
devicesSwitchVrdpAction->setCheckable (true);
":/guesttools_disabled_16px.png"));
#ifdef VBOX_WITH_DEBUGGER_GUI
if (vboxGlobal().isDebuggerEnabled())
{
dbgStatisticsAction = new QAction (this);
dbgCommandLineAction = new QAction (this);
}
else
{
}
#endif
/* Help menu actions */
helpContentsAction = new QAction (this);
helpWebAction = new QAction (this);
helpRegisterAction = new QAction (this);
":/register_disabled_16px.png"));
helpAboutAction = new QAction (this);
helpResetMessagesAction = new QAction (this);
///// Menubar ///////////////////////////////////////////////////////////
/* Machine submenu */
/* dynamic & status line popup menus */
true /* inverted toggle state */);
mVMMenu->addSeparator();
mVMMenu->addSeparator();
#if defined(Q_WS_X11)
#endif
mVMMenu->addSeparator();
mVMMenu->addSeparator();
mVMMenu->addSeparator();
mVMMenu->addSeparator();
/* Devices submenu */
/* dynamic & statusline popup menus */
mDevicesMountDVDMenu = mDevicesMenu->addMenu (VBoxGlobal::iconSet (":/cd_16px.png", ":/cd_disabled_16px.png"), QString::null);
mDevicesMountFloppyMenu = mDevicesMenu->addMenu (VBoxGlobal::iconSet (":/fd_16px.png", ":/fd_disabled_16px.png"), QString::null);
mDevicesNetworkMenu = mDevicesMenu->addMenu (VBoxGlobal::iconSet (":/nw_16px.png", ":/nw_disabled_16px.png"), QString::null);
/* see showIndicatorContextMenu for a description of mDevicesSFMenu */
/* mDevicesSFMenu = mDevicesMenu->addMenu (QString::null); */
/* Currently not needed cause there is no state icon in the statusbar */
/* mDevicesVRDPMenu = new VBoxSwitchMenu (mDevicesMenu, devicesSwitchVrdpAction); */
/* reset the "context menu" flag */
#ifdef VBOX_WITH_DEBUGGER_GUI
/* Debug popup menu */
if (vboxGlobal().isDebuggerEnabled())
{
}
else
#endif
/* Help submenu */
#ifdef VBOX_WITH_REGISTRATION
#endif
///// Status bar ////////////////////////////////////////////////////////
/* i/o devices */
#if 0 // do not show these indicators, information overload
/* vrdp state */
/* auto resize state */
#endif
/* mouse */
mouse_state = new QIStateIndicator (0);
/* host key */
hostkey_hbox = new QWidget();
hostkey_state = new QIStateIndicator (0);
/* add to statusbar */
/////////////////////////////////////////////////////////////////////////
///// Connections ///////////////////////////////////////////////////////
this, SLOT (vmFullscreen (bool)));
this, SLOT (vmSeamless (bool)));
this, SLOT (vmAutoresizeGuest (bool)));
this, SLOT (vmAdjustWindow()));
#if defined(Q_WS_X11)
#endif
connect (vmDisableMouseIntegrAction, SIGNAL(toggled (bool)), this, SLOT(vmDisableMouseIntegr (bool)));
connect (devicesMountFloppyImageAction, SIGNAL(activated()), this, SLOT(devicesMountFloppyImage()));
connect (devicesInstallGuestToolsAction, SIGNAL(activated()), this, SLOT(devicesInstallGuestAdditions()));
connect (statusBar(), SIGNAL(messageChanged (const QString &)), this, SLOT(statusTipChanged (const QString &)));
connect (mDevicesMountFloppyMenu, SIGNAL(triggered(QAction *)), this, SLOT(captureFloppy(QAction *)));
connect (mDevicesNetworkMenu, SIGNAL(triggered(QAction *)), this, SLOT(activateNetworkMenu(QAction *)));
/* Cleanup the status bar tip when a menu with dynamic items is
* hidden. This is necessary for context menus in the first place but also
* for normal menus (because Qt will not do it on pressing ESC if the menu
* is constructed of dynamic items only) */
this, SLOT (clearStatusBar()));
this, SLOT (clearStatusBar()));
this, SLOT (clearStatusBar()));
#if 0
#endif
/* watch global settings changes */
this, SLOT (processGlobalSettingChange (const char *, const char *)));
#ifdef VBOX_WITH_DEBUGGER_GUI
if (dbgStatisticsAction)
this, SLOT (dbgShowStatistics()));
if (dbgCommandLineAction)
this, SLOT (dbgShowCommandLine()));
#endif
#ifdef Q_WS_MAC
# ifdef VBOX_WITH_ICHAT_THEATER
// int setAttr[] = { kHIWindowBitDoesNotShowBadgeInDock, 0 };
// HIWindowChangeAttributes (window, setAttr, NULL);
# endif
/* prepare the dock images */
#endif
}
{
#ifdef Q_WS_MAC
/* release the dock images */
if (dockImgStatePaused)
if (dockImgStateSaving)
if (dockImgBack100x75)
if (dockImgOS)
#endif
}
//
// Public members
/////////////////////////////////////////////////////////////////////////////
/**
* Opens a new console view to interact with a given VM.
* Does nothing if the console view is already opened.
* Used by VBoxGlobal::startMachine(), should not be called directly.
*/
{
if (console)
{
LogFlowFunc (("Already opened\n"));
return false;
}
if (!centralWidget())
{
setCentralWidget (new QWidget (this));
pMainLayout->setSpacing (0);
mShiftingSpacerLeft = new QSpacerItem (0, 0,
QSizePolicy::Fixed);
mShiftingSpacerTop = new QSpacerItem (0, 0,
QSizePolicy::Fixed);
mShiftingSpacerRight = new QSpacerItem (0, 0,
QSizePolicy::Fixed);
mShiftingSpacerBottom = new QSpacerItem (0, 0,
QSizePolicy::Fixed);
}
vmPauseAction->setChecked (false);
centralWidget());
static_cast<QGridLayout*>(centralWidget()->layout())->addWidget(console, 1, 1, Qt::AlignVCenter | Qt::AlignHCenter);
/* Set the VM-specific application icon */
/* Not on Mac OS X. The dock icon is handled below. */
#ifndef Q_WS_MAC
#endif
/* restore the position of the window and some options */
{
int x = 0, y = 0, w = 0, h = 0;
if (ok)
if (ok)
if (ok)
if (ok)
if (ok)
{
normal_pos = QPoint (x, y);
normal_size = QSize (w, h);
move (normal_pos);
}
else
{
normal_pos = QPoint();
normal_size = QSize();
}
/* normalize to the optimal size */
/* maximize if needed */
if (max)
show();
if (str == "on")
vmFullscreenAction->setChecked (true);
vmSeamlessAction->setEnabled (false);
if (str == "on")
vmSeamlessAction->setChecked (true);
if (str != "off")
vmAutoresizeGuestAction->setChecked (true);
if (str == "yes")
mIsFirstTimeStarted = true;
if (str == "no")
mIsAutoSaveMedia = false;
}
/* initialize usb stuff */
{
/* hide usb_menu & usb_separator & usb_status_led */
mDevicesUSBMenu->setVisible (false);
mDevicesUSBMenuSeparator->setVisible (false);
}
else
{
}
/* initialize vrdp stuff */
{
/* hide vrdp_menu_action & vrdp_separator & vrdp_status_icon */
devicesSwitchVrdpAction->setVisible (false);
mDevicesVRDPMenuSeparator->setVisible (false);
#if 0
vrdp_state->setHidden (true);
#endif
}
/* initialize shared folders stuff */
{
/* hide shared folders menu action & sf_separator & sf_status_icon */
devicesSFDialogAction->setVisible (false);
mDevicesSFMenuSeparator->setVisible (false);
}
/* start an idle timer that will update device lighths */
this, SLOT (updateMouseState (int)));
this, SLOT (updateUsbState()));
this, SLOT (updateNetworkAdarptersState()));
this, SLOT (updateSharedFoldersState()));
#ifdef Q_WS_MAC
QImage osImg100x75 = vboxGlobal().vmGuestOSTypeIcon (osTypeId).toImage().scaled (100, 75, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
painter.drawImage (QPoint (osImg.width() - VBoxOverlay.width(), osImg.height() - VBoxOverlay.height()), VBoxOverlay);
if (dockImgOS)
#endif
/* set the correct initial machine_state value */
/*
* The further startup procedure should be done after we leave this method
* and enter the main event loop in main(), because it may result into
* showing various modal dialigs that will process events from within
* this method that in turn can lead to various side effects like this
* window is closed before this mehod returns, etc.
*/
return true;
}
{
/* Process known keys */
}
void VBoxConsoleWnd::finalizeOpenView()
{
/* Notify the console scroll-view about the console-window is opened. */
console->onViewOpened();
if (mIsFirstTimeStarted)
{
/* Remove GUI_FirstRun extra data key from the machine settings
* file after showing the wizard once. */
}
/* start the VM */
/* check for an immediate failure */
{
/* close this window (this will call closeView()) */
close();
LogFlowFunc (("Error starting VM\n"));
return;
}
/* Disable auto closure because we want to have a chance to show the
* error dialog on startup failure */
no_auto_close = true;
/* show the "VM starting / restoring" progress dialog */
if (saved)
this, 0);
else
this);
if (progress.GetResultCode() != 0)
{
/* close this window (this will call closeView()) */
close();
LogFlowFunc (("Error starting VM\n"));
return;
}
no_auto_close = false;
/* Check if we missed a really quick termination after successful
* startup, and process it if we did. */
{
close();
return;
}
#ifdef VBOX_WITH_DEBUGGER_GUI
/* open debugger windows if requested */
if (vboxGlobal().isDebuggerVisibleAtStartup())
{
}
#endif
/* If seamless mode should be enabled then check if it is enabled
* currently and re-enable it if seamless is supported */
if ( vmSeamlessAction->isChecked()
toggleFullscreenMode (true, true);
mIsOpenViewFinished = true;
#endif
}
/**
* Closes the console view opened by openView().
* Does nothing if no console view was opened.
*/
void VBoxConsoleWnd::closeView()
{
if (!console)
{
LogFlow (("Already closed!\n"));
return;
}
idle_timer->stop();
hide();
/* save the position of the window and some options */
{
|| (mIsSeamless && was_max))
}
delete console;
console = 0;
}
/**
* Refreshes the console view by readressing this call to
* VBoxConsoleView::refresh(). Does nothing if the console view doesn't
* exist (i.e., as before openView() or after stopView()).
*/
void VBoxConsoleWnd::refreshView()
{
if ( console ) {
}
}
/**
* This slot is called just after entering the fullscreen/seamless mode,
* when the console was resized to required size.
*/
void VBoxConsoleWnd::onEnterFullscreen()
{
/* It isn't guaranteed that the guest os set the video mode that
* we requested. So after all the resizing stuff set the clipping
* mask and the spacing shifter to the corresponding values. */
#ifdef Q_WS_MAC
if (!mIsSeamless)
{
/* Fade back to the normal gamma */
CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false);
}
#endif
if (mIsSeamless)
this, SLOT(exitSeamless()));
else if (mIsFullscreen)
this, SLOT(exitFullscreen()));
}
/**
* This slot is called just after leaving the fullscreen/seamless mode,
* when the console was resized to previous size.
*/
void VBoxConsoleWnd::onExitFullscreen()
{
#ifdef Q_WS_MAC
if (!mIsSeamless)
{
/* Fade back to the normal gamma */
CGDisplayFade (mFadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false);
}
#endif
vmFullscreenAction->setEnabled (true);
console->setIgnoreMainwndResize (false);
}
/**
* This slot is called if the guest changes resolution while in fullscreen
* mode.
*/
void VBoxConsoleWnd::exitFullscreen()
{
}
/**
* This slot is called if the guest changes resolution while in seamless
* mode.
*/
void VBoxConsoleWnd::exitSeamless()
{
}
{
vmDisableMouseIntegrAction->setEnabled (false);
}
/**
* Shows up and activates the popup version of the main menu.
*
* @param aCenter If @a true, center the popup menu on the screen, otherwise
* show it at the current mouse pointer location.
*/
{
if (aCenter)
{
}
else
{
/* put the menu's bottom right corner to the pointer's hotspot point */
}
}
//
// Protected Members
/////////////////////////////////////////////////////////////////////////////
{
switch (e->type())
{
/* By handling every Resize and Move we keep track of the normal
* (non-minimized and non-maximized) window geometry. Shame on Qt
* that it doesn't provide this geometry in its public APIs. */
{
{
#ifdef VBOX_WITH_DEBUGGER_GUI
#endif
}
break;
}
{
{
normal_pos = pos();
#ifdef VBOX_WITH_DEBUGGER_GUI
#endif
}
break;
}
#ifdef Q_WS_MAC
{
if (mIsSeamless)
{
/* Clear the background */
}
break;
}
#endif
case StatusTipEvent::Type:
{
break;
}
default:
break;
}
return QMainWindow::event (e);
}
{
static const char *kSave = "save";
static const char *kShutdown = "shutdown";
static const char *kPowerOff = "powerOff";
static const char *kDiscardCurState = "discardCurState";
if (!console)
{
e->accept();
LogFlowFunc (("Console already destroyed!"));
return;
}
if (machine_state > KMachineState_Paused &&
{
/*
* The machine is in some temporary state like Saving or Stopping.
* Ignore the close event. When it is Stopping, it will be soon closed
* anyway from updateMachineState(). In all other cases, an appropriate
* progress dialog will be shown within a few seconds.
*/
e->ignore();
}
else
{
/*
* the machine has been already powered off or saved or aborted --
* close the window immediately
*/
e->accept();
}
else
{
/* start with ignore the close event */
e->ignore();
/* Disable auto closure because we want to have a chance to show the
* error dialog on save state / power off failure. */
no_auto_close = true;
bool success = true;
if (!wasPaused)
{
/* Suspend the VM and ignore the close event if failed to do so.
* pause() will show the error message to the user. */
}
if (success)
{
success = false;
VBoxCloseVMDlg dlg (this);
/* make the Discard checkbox invisible if there are no snapshots */
if (machine_state != KMachineState_Stuck)
{
/* read the last user's choice for the given VM */
if (lastAction [0] == kPowerOff)
else if (lastAction [0] == kShutdown)
else if (lastAction [0] == kSave)
else /* the default is ACPI Shutdown */
}
else
{
/* The stuck VM can only be powered off; disable anything
* else and choose PowerOff */
}
bool wasShutdown = false;
{
{
{
/* show the "VM saving" progress dialog */
this, 0);
if (progress.GetResultCode() != 0)
else
success = true;
}
else
}
else
{
/* unpause the VM to let it grab the ACPI shutdown event */
/* prevent the subsequent unpause request */
wasPaused = true;
/* signal ACPI shutdown (if there is no ACPI device, the
* operation will fail) */
if (!wasShutdown)
/* success is always false because we never accept the close
* window action when doing ACPI shutdown */
success = false;
}
else
{
{
/// @todo (dmik) add an option to close the GUI anyway
// and handle it
}
else
{
/*
* set success to true even if we fail to discard the
* current state later -- the console window will be
* closed anyway
*/
success = true;
/* discard the current state if requested */
{
{
/* show the progress dialog */
this);
if (progress.GetResultCode() != 0)
}
else
}
}
}
if (success)
{
/* accept the close action on success */
e->accept();
}
if (success || wasShutdown)
{
/* memorize the last user's choice for the given VM */
lastAction = kSave;
else
AssertFailed();
}
}
}
no_auto_close = false;
{
/*
* the machine has been stopped while showing the Close or the Pause
* failure dialog -- accept the close event immediately
*/
e->accept();
}
else
{
if (!success)
{
/* restore the running state if needed */
}
}
}
if (e->isAccepted())
{
#ifndef VBOX_GUI_SEPARATE_VM_PROCESS
#endif
closeView();
}
}
#if defined(Q_WS_X11)
{
// Qt bug: when the console view grabs the keyboard, FocusIn, FocusOut,
// WindowActivate and WindowDeactivate Qt events are not properly sent
// on top level window (i.e. this) deactivation. The fix is to substiute
// the mode in FocusOut X11 event structure to NotifyNormal to cause
// Qt to process it as desired.
{
{
}
}
return false;
}
#endif
//
// Private members
/////////////////////////////////////////////////////////////////////////////
/**
* Sets the strings of the subwidgets using the current
* language.
*/
void VBoxConsoleWnd::languageChange()
{
#ifdef VBOX_OSE
#else
#endif
/*
* Note: All action shortcuts should be added to the menu text in the
* form of "\tHost+<Key>" where <Key> is the shortcut key according
* to regular QKeySequence rules. No translation of the "Host" word is
* allowed (VBoxConsoleView relies on its spelling). setAccel() must not
* be used.
*/
/* VM actions */
"\tHost+G");
tr ("Automatically resize the guest display when the window is resized "
"(requires Guest Additions)"));
tr ("Adjust window size and position to best fit the guest display"));
tr ("Send the Ctrl-Alt-Del sequence to the virtual machine"));
#if defined(Q_WS_X11)
"\tHost+Backspace");
tr ("Send the Ctrl-Alt-Backspace sequence to the virtual machine"));
#endif
/* vmPauseAction is set up in updateAppearanceOf() */
tr ("Send the ACPI Power Button press event to the virtual machine"));
"\tHost+N");
/* vmDisableMouseIntegrAction is set up in updateAppearanceOf() */
/* Devices actions */
tr ("Unmount the currently mounted floppy media"));
/* mDevicesVRDPMenu->setToolTip (tr ("Remote Desktop (RDP) Server",
tr ("Enable or disable remote desktop (RDP) connections to this machine"));
tr ("Open the dialog to operate on shared folders"));
tr ("Mount the Guest Additions installation image"));
#ifdef VBOX_WITH_DEBUGGER_GUI
/* Debug actions */
if (dbgStatisticsAction)
if (dbgCommandLineAction)
#endif
/* Help actions */
tr ("Open the browser and go to the VirtualBox product web site"));
tr ("Open VirtualBox registration form"));
tr ("Cause all suppressed warnings and messages to be shown again"));
/* Devices menu submenus */
/* main menu & seamless popup menu */
// mVMMenu->setIcon (VBoxGlobal::iconSet (":/machine_16px.png"));
// mDevicesMenu->setIcon (VBoxGlobal::iconSet (":/settings_16px.png"));
#ifdef VBOX_WITH_DEBUGGER_GUI
if (vboxGlobal().isDebuggerEnabled())
{
}
#endif
// mHelpMenu->setIcon (VBoxGlobal::iconSet (":/help_16px.png"));
/* status bar widgets */
#if 0
tr ("Indicates whether the guest display auto-resize function is On "
"(<img src=:/auto_resize_on_16px.png/>) or Off (<img src=:/auto_resize_off_16px.png/>). "
"Note that this function requires Guest Additions to be installed in the guest OS."));
#endif
tr ("Indicates whether the host mouse pointer is captured by the guest OS:<br>"
"<nobr><img src=:/mouse_disabled_16px.png/> pointer is not captured</nobr><br>"
"<nobr><img src=:/mouse_16px.png/> pointer is captured</nobr><br>"
"<nobr><img src=:/mouse_seamless_16px.png/> mouse integration (MI) is On</nobr><br>"
"<nobr><img src=:/mouse_can_seamless_16px.png/> MI is Off, pointer is captured</nobr><br>"
"<nobr><img src=:/mouse_can_seamless_uncaptured_16px.png/> MI is Off, pointer is not captured</nobr><br>"
"Note that the mouse integration feature requires Guest Additions to be installed in the guest OS."));
tr ("Indicates whether the keyboard is captured by the guest OS "
"(<img src=:/hostkey_captured_16px.png/>) or not (<img src=:/hostkey_16px.png/>)."));
tr ("Shows the currently assigned Host key.<br>"
"This key, when pressed alone, toggles the the keyboard and mouse "
"capture state. It can also be used in combination with other keys "
"to quickly perform actions from the main menu."));
}
{
if (!console) return;
{
if (cmachine.GetSnapshotCount() > 0)
{
}
//#ifdef Q_WS_MAC
// SetWindowTitleWithCFString (reinterpret_cast <WindowPtr> (this->winId()), CFSTR("sfds"));
//SetWindowAlternateTitle
//#endif
}
if (element & FloppyStuff)
{
"%1</qt>",
"Floppy tooltip");
switch (state)
{
{
drvName :
break;
}
case KDriveState_ImageMounted:
{
"Floppy tooltip")
break;
}
case KDriveState_NotMounted:
{
"Floppy tooltip");
break;
}
default:
}
}
{
"%1</qt>",
"DVD-ROM tooltip");
switch (state)
{
{
drvName :
break;
}
case KDriveState_ImageMounted:
{
"DVD-ROM tooltip")
break;
}
case KDriveState_NotMounted:
{
"DVD-ROM tooltip");
break;
}
default:
}
}
if (element & HardDiskStuff)
{
"%1</qt>",
"HDD tooltip");
bool hasDisks = false;
{
hasDisks = true;
}
if (!hasDisks)
"HDD tooltip");
}
if (element & NetworkStuff)
{
count++;
/* update tooltip */
"interfaces:</nobr>"
"%1</qt>",
"Network adapters tooltip");
{
if (adapter.GetEnabled())
"Network adapters tooltip")
}
"Network adapters tooltip");
}
{
{
/* update tooltip */
"attached USB devices:</nobr>"
"%1</qt>",
"USB device tooltip");
if (isUSBEnabled)
{
{
}
"USB device tooltip");
}
else
{
mDevicesUSBMenu->setEnabled (false);
"USB device tooltip");
}
}
}
{
{
/* update menu&status icon state */
#if 0
/* compose status icon tooltip */
"is enabled (<img src=:/vrdp_16px.png/>) or not "
"(<img src=:/vrdp_disabled_16px.png/>)."
);
if (vrdpsrv.GetEnabled())
#endif
}
}
if (element & SharedFolderStuff)
{
"%1</qt>",
"Shared folders tooltip");
/// @todo later: add global folders
/* permanent folders */
{
}
/* transient folders */
{
}
{
/* select slashes depending on the OS type */
"<td><nobr>%2</nobr></td>")
else
"<td><nobr>%2</nobr></td></tr>")
}
"Shared folders tooltip");
else
}
if (element & PauseAction)
{
if (!vmPauseAction->isChecked())
{
tr ("Suspend the execution of the virtual machine"));
}
else
{
tr ("Resume the execution of the virtual machine" ) );
}
}
if (element & DisableMouseIntegrAction)
{
if (!vmDisableMouseIntegrAction->isChecked())
{
"\tHost+I");
tr ("Temporarily disable host mouse pointer integration"));
}
else
{
"\tHost+I");
tr ("Enable temporarily disabled host mouse pointer integration"));
}
if (machine_state == KMachineState_Running)
else
vmDisableMouseIntegrAction->setEnabled (false);
}
}
/**
* @return @c true if successfully performed the requested operation and false
* otherwise.
*/
{
if (aSeamless)
{
/* Check if the Guest Video RAM enough for the seamless mode. */
* _1M /* mb to bytes */
* 8; /* to bits */
* guestBpp
* csession.GetMachine().GetMonitorCount() /**< @todo fix assumption that all screens have same resolution */
+ 4096 * 8; /* adapter info */
{
return false;
}
}
AssertReturn (console, false);
if (aOn)
(!aSeamless && !mIsSeamless), false);
if (aOn)
{
/* Take the toggle hot key from the menu item. */
/* Show the info message. */
if (!ok)
return false;
}
#ifdef Q_WS_MAC
if (!aSeamless)
{
/* Fade to black */
CGDisplayFade (mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true);
}
#endif
if (aSeamless)
{
/* Activate the auto-resize feature required for the seamless mode. */
if (!vmAutoresizeGuestAction->isChecked())
vmAutoresizeGuestAction->setChecked (true);
/* Activate the mouse integration feature for the seamless mode. */
if (vmDisableMouseIntegrAction->isChecked())
vmDisableMouseIntegrAction->setChecked (false);
mIsSeamless = aOn;
}
else
{
mIsFullscreen = aOn;
}
if (aOn)
{
/* Temporarily disable the mode-related action to make sure
* user can not leave the mode before he enter it. */
vmFullscreenAction->setEnabled (false);
/* Toggle console to manual resize mode. */
console->setIgnoreMainwndResize (true);
this, SLOT (onEnterFullscreen()));
/* Memorize the maximized state. */
was_max = isMaximized() &&
/* Save the previous scroll-view minimum size before entering
* fullscreen/seamless state to restore this minimum size before
* the exiting fullscreen. Required for correct scroll-view and
* guest display update in SDL mode. */
console->setMinimumSize (0, 0);
/* let the widget take the whole available desktop space */
/* It isn't guaranteed that the guest os set the video mode that
* we requested. So after all the resizing stuff set the clipping
* mask and the spacing shifter to the corresponding values. */
#ifdef Q_WS_WIN32
#endif
/* Hide all but the central widget containing the console view. */
{
/* todo: The list is now recursive. So think about a better way to
* prevent the childrens of the centralWidget to be hidden */
if (w != centralWidget() &&
w != console &&
{
if (!w->isHidden())
{
w->hide();
hidden_children.append (w);
}
}
}
/* Adjust colors and appearance. */
/* Going fullscreen */
#ifdef Q_WS_MAC /* setMask seems to not include the far border pixels. */
// QRect maskRect = dtw->screenGeometry (this);
// maskRect.setRight (maskRect.right() + 1);
// maskRect.setBottom (maskRect.bottom() + 1);
// setMask (maskRect);
if (aSeamless)
{
/* @todo=poetzsch: Currently this isn't necessary. I should
/*
EventTypeSpec wCompositingEvent = { kEventClassWindow, kEventWindowGetRegion };
status = InstallWindowEventHandler ((WindowPtr)winId(), DarwinRegionHandler, GetEventTypeCount (wCompositingEvent), &wCompositingEvent, &mCurrRegion, &mDarwinRegionEventHandlerRef);
AssertCarbonOSStatus (status);
HIViewRef contentView = 0;
status = HIViewFindByID(HIViewGetRoot(windowRef), kHIViewWindowContentID, &contentView);
AssertCarbonOSStatus (status);
EventTypeSpec drawEvent = { kEventClassControl, kEventControlDraw };
status = InstallControlEventHandler (contentView, DarwinRegionHandler, GetEventTypeCount (drawEvent), &drawEvent, &contentView, NULL);
AssertCarbonOSStatus (status);
*/
if (( features & kWindowIsOpaque ) != 0)
{
}
/* For now disable the shadow of the window. This feature cause errors
* if a window in vbox looses focus, is reselected and than moved. */
/** @todo Search for an option to enable this again. A shadow on every
* window has a big coolness factor. */
}
#else
// setMask (dtw->screenGeometry (this));
#endif
qApp->processEvents();
console->toggleFSMode();
}
else
{
/* Temporarily disable the mode-related action to make sure
* user can not enter the mode before he leave it. */
vmFullscreenAction->setEnabled (false);
/* Toggle console to manual resize mode. */
/* Reset the shifting spacer. */
/* Restore the previous scroll-view minimum size before the exiting
* fullscreen. Required for correct scroll-view and guest display
* update in SDL mode. */
#ifdef Q_WS_MAC
if (aSeamless)
{
/* Undo all mac specific installations */
/* See above.
status = RemoveEventHandler (mDarwinRegionEventHandlerRef);
AssertCarbonOSStatus (status);
*/
}
#endif
/* Adjust colors and appearance. */
clearMask();
centralWidget()->setAutoFillBackground (false);
/* Show everything hidden when going fullscreen. */
/* Going normal || maximized */
qApp->processEvents();
console->toggleFSMode();
}
#ifdef Q_WS_MAC /* wasHidden is wrong on the mac it seems. */
/** @todo figure out what is really wrong here... */
if (!wasHidden)
show();
#else
if (wasHidden)
hide();
#endif
return true;
}
#ifdef Q_WS_MAC
{
if (machine_state == KMachineState_Paused)
else if (machine_state == KMachineState_Restoring)
else if (machine_state == KMachineState_Saving)
else
return img;
}
#endif
//
// Private slots
/////////////////////////////////////////////////////////////////////////////
{
#ifdef Q_WS_MAC
if (aSeamless)
if (aOn)
{
/* Save for later restoring */
mNormalGeometry = geometry();
mSavedFlags = windowFlags();
/* Remove the frame from the window */
/* Set it maximized */
}
else
{
/* Restore old values */
setParent (0, mSavedFlags);
}
else
/* Here we are going really fullscreen */
#else
#endif
}
{
#ifndef Q_WS_MAC
if (mIsSeamless)
{
/* It isn't guaranteed that the guest os set the video mode that
* we requested. So after all the resizing stuff set the clipping
* mask and the spacing shifter to the corresponding values. */
/* Set the clipping mask */
/* Set the shifting spacer */
}
#else // !Q_WS_MAC
NOREF (aTargetRect);
#endif // !Q_WS_MAC
}
{
if (!ok)
{
/* on failure, restore the previous button state */
vmFullscreenAction->blockSignals (true);
vmFullscreenAction->blockSignals (false);
}
}
{
{
if (!ok)
{
/* on failure, restore the previous button state */
vmSeamlessAction->blockSignals (true);
vmSeamlessAction->blockSignals (false);
}
}
}
{
if (!console)
return;
/* Currently, we use only "off" and "on" icons. Later,
* we may want to use disabled versions of icons when no guest additions
* are available (to indicate that this function is ineffective). */
#if 0
#endif
}
void VBoxConsoleWnd::vmAdjustWindow()
{
if (console)
{
if (isMaximized())
showNormal();
}
}
void VBoxConsoleWnd::vmTypeCAD()
{
if (console)
{
}
}
void VBoxConsoleWnd::vmTypeCABS()
{
#if defined(Q_WS_X11)
if (console)
{
{
0x1d, // Ctrl down
0x38, // Alt down
0x0E, // Backspace down
0x8E, // Backspace up
0xb8, // Alt up
0x9d // Ctrl up
};
}
#else
/* we have to define this slot anyway because MOC doesn't understand ifdefs */
#endif
}
void VBoxConsoleWnd::vmReset()
{
if (console)
{
if (vboxProblem().confirmVMReset (this))
}
}
{
if (console)
{
}
}
void VBoxConsoleWnd::vmACPIShutdown()
{
if (console)
{
}
}
void VBoxConsoleWnd::vmClose()
{
if (console)
{
close();
}
}
void VBoxConsoleWnd::vmTakeSnapshot()
{
AssertReturn (console, (void) 0);
/* remember the paused state */
if (!wasPaused)
{
/* Suspend the VM and ignore the close event if failed to do so.
* pause() will show the error message to the user. */
return;
}
VBoxTakeSnapshotDlg dlg (this);
/* search for the max available filter index */
int maxSnapShotIndex = 0;
{
/* Check the current snapshot name */
if (pos != -1)
/* Traversing to the next child */
}
{
{
/* show the "Taking Snapshot" progress dialog */
vboxProblem().
if (progress.GetResultCode() != 0)
}
else
}
/* restore the running state if needed */
if (!wasPaused)
}
void VBoxConsoleWnd::vmShowInfoDialog()
{
}
{
if (console)
{
}
}
{
if (!console) return;
{
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
}
void VBoxConsoleWnd::devicesUnmountFloppy()
{
if (!console) return;
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
void VBoxConsoleWnd::devicesMountDVDImage()
{
if (!console) return;
{
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
}
void VBoxConsoleWnd::devicesUnmountDVD()
{
if (!console) return;
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
{
if (!console) return;
/* this method should not be executed if vrdpServer is null */
}
void VBoxConsoleWnd::devicesOpenSFDialog()
{
if (!console) return;
}
{
#if defined (DEBUG_dmik) /* subscribe yourself here if you care for this behavior. */
#else
char szAppPrivPath [RTPATH_MAX];
int rc;
#endif
else
{
/* Check for the already registered required image: */
{
/* compare the name part ignoring the file case*/
return installGuestAdditionsFrom (path);
}
/* Download required image: */
{
.absoluteFilePath (name);
}
}
}
{
{
}
else
{
return;
}
/// @todo (r=dmik) use VBoxProblemReporter::cannotMountMedia...
}
{
/* The global mask shift cause of toolbars and such things. */
/* Restrict the drawing to the available space on the screen.
* (The &operator is better than the previous used -operator,
* because this excludes space around the real screen also.
* This is necessary for the mac.) */
#ifdef Q_WS_WIN
/* Region offset calculation */
/* I think this isn't necessary anymore because the 4 shifting spacer.
* Has to be verified. */
// if (isTopLevel())
// {
// ftop = topData()->ftop;
// fleft = topData()->fleft;
// }
/* Visible region calculation */
/* Invisible region calculation */
/* Set the current visible region and clean the previous */
# if defined(VBOX_GUI_USE_QUARTZ2D)
{
/* If we are using the Quartz2D backend we have to trigger
* an repaint only. All the magic clipping stuff is done
* in the paint engine. */
// HIWindowInvalidateShadow (::darwinToWindowRef (console->viewport()));
// ReshapeCustomWindow (mapToWindowRef (this));
}
else
# endif
{
/* This is necessary to avoid the flicker by an mask update.
* for the hint.
* There *must* be a better solution. */
// /* Save the current region for later processing in the darwin event handler. */
// mCurrRegion = region;
// /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately
// * this command flushes a copy of the backbuffer to the screen after the new
// * mask is set. This leads into a missplaced drawing of the content. Currently
// * no alternative to this and also this is not 100% perfect. */
// repaint();
// qApp->processEvents();
// /* Now force the reshaping of the window. This is definitly necessary. */
// ReshapeCustomWindow (reinterpret_cast <WindowPtr> (winId()));
// HIWindowInvalidateShadow (::darwinToWindowRef (console->viewport()));
}
#else
#endif
}
/**
* Prepares the "Mount Floppy..." menu by populating the existent host
* floppies.
*/
void VBoxConsoleWnd::prepareFloppyMenu()
{
if (!console) return;
{
/** @todo set icon */
drvName :
"Floppy tip"));
action->setEnabled (false);
action->setEnabled (false);
}
/* if shown as a context menu */
{
}
}
/**
* Prepares the "Capture DVD..." menu by populating the existent host
*/
void VBoxConsoleWnd::prepareDVDMenu()
{
if (!console) return;
hostDVDMap.clear();
{
/** @todo set icon */
drvName :
action->setEnabled (false);
action->setEnabled (false);
}
/* if shown as a context menu */
{
}
}
/**
* Prepares the "Network adapter" menu by populating the existent adapters.
*/
void VBoxConsoleWnd::prepareNetworkMenu()
{
{
action->setCheckable (true);
}
}
{
if (sender() == mDevicesNetworkMenu)
{
tr ("Disconnect the cable from the selected virtual network adapter") :
tr ("Connect the cable to the selected virtual network adapter");
}
{
waitForStatusBarChange = true;
}
}
{
waitForStatusBarChange = false;
}
void VBoxConsoleWnd::clearStatusBar()
{
statusBar()->clearMessage();
}
/**
* Captures a floppy device corresponding to a given menu action.
*/
{
if (!console) return;
/* if null then some other item but host drive is selected */
if (d.isNull()) return;
drv.CaptureHostDrive (d);
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
/**
*/
{
if (!console) return;
/* if null then some other item but host drive is selected */
if (d.isNull()) return;
drv.CaptureHostDrive (d);
{
if (mIsAutoSaveMedia)
{
m.SaveSettings();
if (!m.isOk())
}
}
}
/**
* Switch the cable connected/disconnected for the selected network adapter
*/
{
if (adapter.GetEnabled())
}
/**
*/
{
if (!console) return;
/* if null then some other item but a USB device is selected */
return;
{
{
/// @todo (r=dmik) the dialog should be either modeless
// or we have to pause the VM
}
}
else
{
{
/// @todo (r=dmik) the dialog should be either modeless
// or we have to pause the VM
}
}
}
{
{
/* set "this is a context menu" flag */
}
else
{
/* set "this is a context menu" flag */
}
else
{
if (mDevicesUSBMenu->isEnabled())
{
/* set "this is a context menu" flag */
}
}
else
/* if (ind == vrdp_state)
{
mDevicesVRDPMenu->exec (e->globalPos());
}
else */
if (ind == autoresize_state)
{
}
else
if (ind == mouse_state)
{
}
else
{
/* Showing the context menu that always contains a single item is a
* bit stupid; let's better execute this item's action directly. The
* menu itself is kept just in case if we need more than one item in
* the future. */
/* mDevicesSFMenu->exec (e->globalPos()); */
if (devicesSFDialogAction->isEnabled())
}
else
{
if (mDevicesNetworkMenu->isEnabled())
{
/* set "this is a context menu" flag */
}
}
}
void VBoxConsoleWnd::updateDeviceLights()
{
if (console) {
int st;
}
}
}
}
}
}
}
}
{
bool guruMeditation = false;
{
if (state >= KMachineState_Running)
{
switch (state)
{
case KMachineState_Stuck:
{
guruMeditation = true;
break;
}
case KMachineState_Paused:
{
if (!vmPauseAction->isChecked())
vmPauseAction->setChecked (true);
break;
}
case KMachineState_Running:
{
vmPauseAction->setChecked (false);
break;
}
#ifdef Q_WS_X11
case KMachineState_Starting:
{
/* The keyboard handler may wish to do some release logging
on startup. Tell it that the logger is now active. */
break;
}
#endif
default:
break;
}
}
* updateAppearanceOf() */
if (state < KMachineState_Running)
{
/*
* VM has been powered off or saved or aborted, no matter
* internally or externally -- we must *safely* close the console
* window unless auto closure is disabled.
*/
if (!no_auto_close)
tryClose();
}
}
if (guruMeditation)
{
/* Take the screenshot for debugging purposes and save it */
/// @todo for some reason, IDisplay::takeScreenShot() may not work
/// properly on a VM which is Stuck -- investigate it.
if (vboxProblem().remindAboutGuruMeditation (
{
}
}
#ifdef Q_WS_MAC
if (img)
#endif
}
{
{
}
else
{
}
}
bool aActive,
bool aSeamlessSupported,
bool aGraphicsSupported)
{
if ( (mIsSeamlessSupported != aSeamlessSupported)
|| (mIsGraphicsSupported != aGraphicsSupported))
{
/* If seamless mode should be enabled then check if it is enabled
* currently and re-enable it if open-view procedure is finished */
if ( vmSeamlessAction->isChecked()
toggleFullscreenMode (true, true);
}
/* Check the GA version only in case of additions are active */
if (!aActive)
return;
/* Check the Guest Additions version and warn the user about possible
* compatibility issues in case if the installed version is outdated. */
{
}
{
}
else if (version > VMMDEV_VERSION)
{
}
}
{
}
{
}
void VBoxConsoleWnd::updateUsbState()
{
}
{
}
/**
* Helper to safely close the main console window.
*
* This method ensures that close() will not be called if there is some
* modal widget currently being executed, as it can cause uninitialization
* at the point of code where it is not expected at all (example:
* VBoxConsoleView::mouseEvent() calling
* VBoxProblemReporter::confirmInputCapture()). Instead, an attempt to
* close the current modal widget is done and tryClose() is rescheduled for
* later execution using a single-shot zero timer.
*
* In particular, this method is used by updateMachineState() when the VM
* goes offline, which can even happen if we are inside the modal event loop,
* (for example, the VM has been externally powered off or the guest OS
* has initiated a shutdown procedure).
*/
void VBoxConsoleWnd::tryClose()
{
#warning "port me"
/* It seems that Qt4 closes all child widgets if the parent widget get
* closed. So nothing to do here than to call close. */
close();
/* We have this to test on Windows and Mac or maybe I forgot something, so
* we keep this as a reference: */
// LogFlowFunc (("eventLoopLevel=%d\n", qApp->eventLoop()->loopLevel()));
//
// if (qApp->eventLoop()->loopLevel() > 1)
// {
// if (QApplication::activeModalWidget())
// QApplication::activeModalWidget()->close();
// else if (QApplication::activePopupWidget())
// QApplication::activePopupWidget()->close();
// else
// {
/// @todo (r=dmik) in general, the following is not that correct
// because some custom modal event loop may not expect to be
// exited externally (e.g., it might want to set some internal
// flags before calling exitLoop()). The alternative is to do
// nothing but wait keeping to post singleShot timers.
// qApp->eventLoop()->exitLoop();
// }
//
// QTimer::singleShot (0, this, SLOT (tryClose()));
// }
// else
// close();
}
/**
* Called (on non-UI thread!) when a global GUI setting changes.
*/
const char * /*name*/)
{
}
/**
* Called when the Debug->Statistics... menu item is selected.
*/
void VBoxConsoleWnd::dbgShowStatistics()
{
#ifdef VBOX_WITH_DEBUGGER_GUI
if (dbgCreated())
#endif
}
/**
* Called when the Debug->Command Line... menu item is selected.
*/
void VBoxConsoleWnd::dbgShowCommandLine()
{
#ifdef VBOX_WITH_DEBUGGER_GUI
if (dbgCreated())
#endif
}
#ifdef VBOX_WITH_DEBUGGER_GUI
/**
* Ensures that the debugger GUI instance is ready.
*
* @returns true if instance is fine and dandy.
* @returns flase if it's not.
*/
bool VBoxConsoleWnd::dbgCreated()
{
if (dbg_gui)
return true;
if (VBOX_SUCCESS (rc))
{
return true;
}
return false;
}
/**
* Destroys the debugger GUI instacne if it has been created.
*/
void VBoxConsoleWnd::dbgDestroy()
{
if (dbg_gui)
{
}
}
/**
* Tells the debugger GUI that the console window has moved or been resized.
*/
void VBoxConsoleWnd::dbgAdjustRelativePos()
{
if (dbg_gui)
{
}
}
#endif
, mSettings (0)
{
setModal (true);
/* Setup Dialog's options */
setSizeGripEnabled (true);
/* Setup main dialog's layout */
/* Setup settings layout */
/* Setup button's layout */
/* Setup the default push button */
pbOk->setAutoDefault (true);
pbOk->setDefault (true);
}
void VBoxSFDialog::accept()
{
}
{
setMinimumWidth (400);
}