VirtualBox

Changeset 26691 in vbox


Ignore:
Timestamp:
Feb 23, 2010 3:32:44 AM (15 years ago)
Author:
vboxsync
Message:

FE/Qt4: New running VM core: Just a cumulative update.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
16 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r26655 r26691  
    375375ifdef VBOX_WITH_NEW_RUNTIME_CORE
    376376VirtualBox_QT_MOCHDRS += \
     377        src/runtime/UISession.h \
    377378        src/runtime/UIActionsPool.h \
    378379        src/runtime/UIIndicatorsPool.h \
     
    496497ifdef VBOX_WITH_NEW_RUNTIME_CORE
    497498VirtualBox_SOURCES += \
     499        src/runtime/UISession.cpp \
    498500        src/runtime/UIActionsPool.cpp \
    499501        src/runtime/UIIndicatorsPool.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIActionsPool.cpp

    r26647 r26691  
    390390};
    391391
    392 class PerformResetAction : public UISimpleAction
    393 {
    394     Q_OBJECT;
    395 
    396 public:
    397 
    398     PerformResetAction(QObject *pParent)
    399         : UISimpleAction(pParent,
    400                          ":/reset_16px.png", ":/reset_disabled_16px.png")
    401     {
    402         retranslateUi();
    403     }
    404 
    405 protected:
    406 
    407     void retranslateUi()
    408     {
    409         setText(VBoxGlobal::insertKeyToActionText(tr ("&Reset"), "R"));
    410         setStatusTip(tr("Reset the virtual machine"));
    411     }
    412 };
    413 
    414392class TogglePauseAction : public UIToggleAction
    415393{
     
    442420};
    443421
     422class PerformResetAction : public UISimpleAction
     423{
     424    Q_OBJECT;
     425
     426public:
     427
     428    PerformResetAction(QObject *pParent)
     429        : UISimpleAction(pParent,
     430                         ":/reset_16px.png", ":/reset_disabled_16px.png")
     431    {
     432        retranslateUi();
     433    }
     434
     435protected:
     436
     437    void retranslateUi()
     438    {
     439        setText(VBoxGlobal::insertKeyToActionText(tr ("&Reset"), "R"));
     440        setStatusTip(tr("Reset the virtual machine"));
     441    }
     442};
     443
    444444class PerformShutdownAction : public UISimpleAction
    445445{
     
    554554};
    555555
    556 class MenuNetworkAdaptersAction : public UIMenuAction
    557 {
    558     Q_OBJECT;
    559 
    560 public:
    561 
    562     MenuNetworkAdaptersAction(QObject *pParent)
    563         : UIMenuAction(pParent)
    564     {
    565         retranslateUi();
    566     }
    567 
    568 protected:
    569 
    570     void retranslateUi()
    571     {
    572     }
    573 };
    574 
    575 class ShowNetworkAdaptersDialogAction : public UISimpleAction
    576 {
    577     Q_OBJECT;
    578 
    579 public:
    580 
    581     ShowNetworkAdaptersDialogAction(QObject *pParent)
    582         : UISimpleAction(pParent,
    583                          ":/nw_16px.png", ":/nw_disabled_16px.png")
    584     {
    585         retranslateUi();
    586     }
    587 
    588 protected:
    589 
    590     void retranslateUi()
    591     {
    592         setText(tr("&Network Adapters..."));
    593         setStatusTip(tr("Change the settings of network adapters"));
    594     }
    595 };
    596 
    597 class MenuSharedFoldersAction : public UIMenuAction
    598 {
    599     Q_OBJECT;
    600 
    601 public:
    602 
    603     MenuSharedFoldersAction(QObject *pParent)
    604         : UIMenuAction(pParent)
    605     {
    606         retranslateUi();
    607     }
    608 
    609 protected:
    610 
    611     void retranslateUi()
    612     {
    613     }
    614 };
    615 
    616 class ShowSharedFoldersDialogAction : public UISimpleAction
    617 {
    618     Q_OBJECT;
    619 
    620 public:
    621 
    622     ShowSharedFoldersDialogAction(QObject *pParent)
    623         : UISimpleAction(pParent,
    624                          ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")
    625     {
    626         retranslateUi();
    627     }
    628 
    629 protected:
    630 
    631     void retranslateUi()
    632     {
    633         setText(tr("&Shared Folders..."));
    634         setStatusTip(tr("Create or modify shared folders"));
    635     }
    636 };
    637 
    638556class MenuUSBDevicesAction : public UIMenuAction
    639557{
     
    654572    {
    655573        menu()->setTitle(tr("&USB Devices"));
     574    }
     575};
     576
     577class MenuNetworkAdaptersAction : public UIMenuAction
     578{
     579    Q_OBJECT;
     580
     581public:
     582
     583    MenuNetworkAdaptersAction(QObject *pParent)
     584        : UIMenuAction(pParent)
     585    {
     586        retranslateUi();
     587    }
     588
     589protected:
     590
     591    void retranslateUi()
     592    {
     593    }
     594};
     595
     596class ShowNetworkAdaptersDialogAction : public UISimpleAction
     597{
     598    Q_OBJECT;
     599
     600public:
     601
     602    ShowNetworkAdaptersDialogAction(QObject *pParent)
     603        : UISimpleAction(pParent,
     604                         ":/nw_16px.png", ":/nw_disabled_16px.png")
     605    {
     606        retranslateUi();
     607    }
     608
     609protected:
     610
     611    void retranslateUi()
     612    {
     613        setText(tr("&Network Adapters..."));
     614        setStatusTip(tr("Change the settings of network adapters"));
     615    }
     616};
     617
     618class MenuSharedFoldersAction : public UIMenuAction
     619{
     620    Q_OBJECT;
     621
     622public:
     623
     624    MenuSharedFoldersAction(QObject *pParent)
     625        : UIMenuAction(pParent)
     626    {
     627        retranslateUi();
     628    }
     629
     630protected:
     631
     632    void retranslateUi()
     633    {
     634    }
     635};
     636
     637class ShowSharedFoldersDialogAction : public UISimpleAction
     638{
     639    Q_OBJECT;
     640
     641public:
     642
     643    ShowSharedFoldersDialogAction(QObject *pParent)
     644        : UISimpleAction(pParent,
     645                         ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png")
     646    {
     647        retranslateUi();
     648    }
     649
     650protected:
     651
     652    void retranslateUi()
     653    {
     654        setText(tr("&Shared Folders..."));
     655        setStatusTip(tr("Create or modify shared folders"));
    656656    }
    657657};
     
    809809    m_actionsPool[UIActionIndex_Simple_TakeSnapshot] = new PerformTakeSnapshotAction(this);
    810810    m_actionsPool[UIActionIndex_Simple_InformationDialog] = new ShowInformationDialogAction(this);
     811    m_actionsPool[UIActionIndex_Toggle_Pause] = new TogglePauseAction(this);
    811812    m_actionsPool[UIActionIndex_Simple_Reset] = new PerformResetAction(this);
    812     m_actionsPool[UIActionIndex_Toggle_Pause] = new TogglePauseAction(this);
    813813    m_actionsPool[UIActionIndex_Simple_Shutdown] = new PerformShutdownAction(this);
    814814    m_actionsPool[UIActionIndex_Simple_Close] = new PerformCloseAction(this);
     
    818818    m_actionsPool[UIActionIndex_Menu_OpticalDevices] = new MenuOpticalDevicesAction(this);
    819819    m_actionsPool[UIActionIndex_Menu_FloppyDevices] = new MenuFloppyDevicesAction(this);
     820    m_actionsPool[UIActionIndex_Menu_USBDevices] = new MenuUSBDevicesAction(this);
    820821    m_actionsPool[UIActionIndex_Menu_NetworkAdapters] = new MenuNetworkAdaptersAction(this);
    821822    m_actionsPool[UIActionIndex_Simple_NetworkAdaptersDialog] = new ShowNetworkAdaptersDialogAction(this);
    822823    m_actionsPool[UIActionIndex_Menu_SharedFolders] = new MenuSharedFoldersAction(this);
    823824    m_actionsPool[UIActionIndex_Simple_SharedFoldersDialog] = new ShowSharedFoldersDialogAction(this);
    824     m_actionsPool[UIActionIndex_Menu_USBDevices] = new MenuUSBDevicesAction(this);
    825825    m_actionsPool[UIActionIndex_Toggle_VRDP] = new ToggleVRDPAction(this);
    826826    m_actionsPool[UIActionIndex_Simple_InstallGuestTools] = new PerformInstallGuestToolsAction(this);
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIActionsPool.h

    r26637 r26691  
    7272    UIActionIndex_Simple_TakeSnapshot,
    7373    UIActionIndex_Simple_InformationDialog,
     74    UIActionIndex_Toggle_Pause,
    7475    UIActionIndex_Simple_Reset,
    75     UIActionIndex_Toggle_Pause,
    7676    UIActionIndex_Simple_Shutdown,
    7777    UIActionIndex_Simple_Close,
     
    8181    UIActionIndex_Menu_OpticalDevices,
    8282    UIActionIndex_Menu_FloppyDevices,
     83    UIActionIndex_Menu_USBDevices,
    8384    UIActionIndex_Menu_NetworkAdapters,
    8485    UIActionIndex_Simple_NetworkAdaptersDialog,
    8586    UIActionIndex_Menu_SharedFolders,
    8687    UIActionIndex_Simple_SharedFoldersDialog,
    87     UIActionIndex_Menu_USBDevices,
    8888    UIActionIndex_Toggle_VRDP,
    8989    UIActionIndex_Simple_InstallGuestTools,
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp

    r26637 r26691  
    2424#include "VBoxGlobal.h"
    2525#include "UIMachine.h"
     26#include "UISession.h"
    2627#include "UIActionsPool.h"
    2728#include "UIMachineLogic.h"
     
    3334public:
    3435
     36    /* Visual state holder constructor: */
    3537    UIVisualState(QObject *pParent) : QObject(pParent), m_pMachineLogic(0)
    3638    {
    37         /* Connect state-change handler */
     39        /* Connect state-change handler: */
    3840        connect(this, SIGNAL(sigChangeVisualState(UIVisualStateType)), parent(), SLOT(sltChangeVisualState(UIVisualStateType)));
    3941    }
     
    4547protected:
    4648
     49    /* Protected members: */
    4750    UIMachineLogic *m_pMachineLogic;
     51
     52    /* Friend classes: */
     53    friend class UIMachine;
    4854};
    4955
     
    5460public:
    5561
    56     UIVisualStateNormal(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool)
     62    /* Normal visual state holder constructor: */
     63    UIVisualStateNormal(QObject *pParent, UISession *pSession, UIActionsPool *pActionsPool)
    5764        : UIVisualState(pParent)
    5865    {
    59         /* Connect action handlers */
     66        /* Connect action handlers: */
    6067        connect(pActionsPool->action(UIActionIndex_Toggle_Fullscreen), SIGNAL(triggered(bool)),
    6168                this, SLOT(sltGoToFullscreenMode()));
     
    6370                this, SLOT(sltGoToSeamlessMode()));
    6471
    65         /* Create state logic */
    66         m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Normal);
     72        /* Create state logic: */
     73        m_pMachineLogic = UIMachineLogic::create(this, pSession, pActionsPool, UIVisualStateType_Normal);
    6774    }
    6875
     
    7178    void sltGoToFullscreenMode()
    7279    {
     80        /* Change visual state to fullscreen: */
    7381        emit sigChangeVisualState(UIVisualStateType_Fullscreen);
    7482    }
     
    7684    void sltGoToSeamlessMode()
    7785    {
     86        /* Change visual state to seamless: */
    7887        emit sigChangeVisualState(UIVisualStateType_Seamless);
    7988    }
     
    8695public:
    8796
    88     UIVisualStateFullscreen(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool)
     97    /* Fullscreen visual state holder constructor: */
     98    UIVisualStateFullscreen(QObject *pParent, UISession *pSession, UIActionsPool *pActionsPool)
    8999        : UIVisualState(pParent)
    90100    {
    91         /* Connect action handlers */
     101        /* Connect action handlers: */
    92102        connect(pActionsPool->action(UIActionIndex_Toggle_Fullscreen), SIGNAL(triggered(bool)),
    93103                this, SLOT(sltGoToNormalMode()));
     
    95105                this, SLOT(sltGoToSeamlessMode()));
    96106
    97         /* Create state logic */
    98         m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Fullscreen);
     107        /* Create state logic: */
     108        m_pMachineLogic = UIMachineLogic::create(this, pSession, pActionsPool, UIVisualStateType_Fullscreen);
    99109    }
    100110
     
    103113    void sltGoToNormalMode()
    104114    {
     115        /* Change visual state to normal: */
    105116        emit sigChangeVisualState(UIVisualStateType_Normal);
    106117    }
     
    108119    void sltGoToSeamlessMode()
    109120    {
     121        /* Change visual state to seamless: */
    110122        emit sigChangeVisualState(UIVisualStateType_Seamless);
    111123    }
     
    118130public:
    119131
    120     UIVisualStateSeamless(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool)
     132    /* Seamless visual state holder constructor: */
     133    UIVisualStateSeamless(QObject *pParent, UISession *pSession, UIActionsPool *pActionsPool)
    121134        : UIVisualState(pParent)
    122135    {
     
    128141
    129142        /* Create state logic */
    130         m_pMachineLogic = UIMachineLogic::create(this, session, pActionsPool, UIVisualStateType_Seamless);
     143        m_pMachineLogic = UIMachineLogic::create(this, pSession, pActionsPool, UIVisualStateType_Seamless);
    131144    }
    132145
     
    135148    void sltGoToFullscreenMode()
    136149    {
     150        /* Change visual state to fullscreen: */
    137151        emit sigChangeVisualState(UIVisualStateType_Fullscreen);
    138152    }
     
    140154    void sltGoToNormalMode()
    141155    {
     156        /* Change visual state to normal: */
    142157        emit sigChangeVisualState(UIVisualStateType_Normal);
    143158    }
     
    146161UIMachine::UIMachine(UIMachine **ppSelf, const CSession &session)
    147162    : QObject(0)
    148     , m_session(session)
     163    , m_pSession(new UISession(this, session))
    149164    , m_pActionsPool(new UIActionsPool(this))
    150165    , m_pVisualState(0)
     
    152167    /* Cache IMedium data: */
    153168    vboxGlobal().startEnumeratingMedia();
    154 
    155     /* Check CSession object */
    156     AssertMsg(!m_session.isNull(), ("CSession is not set!\n"));
    157169
    158170    /* Storing self */
     
    164176}
    165177
     178UIMachineLogic* UIMachine::machineLogic() const
     179{
     180    return m_pVisualState->m_pMachineLogic;
     181}
     182
    166183void UIMachine::sltChangeVisualState(UIVisualStateType visualStateType)
    167184{
    168     /* Delete previous state */
     185    /* Delete previous state: */
    169186    delete m_pVisualState;
    170187    m_pVisualState = 0;
    171188
    172     /* Create new state */
     189    /* Create new state: */
    173190    switch (visualStateType)
    174191    {
    175192        case UIVisualStateType_Normal:
    176193        {
    177             m_pVisualState = new UIVisualStateNormal(this, m_session, m_pActionsPool);
     194            /* Create normal visual state: */
     195            m_pVisualState = new UIVisualStateNormal(this, m_pSession, m_pActionsPool);
    178196            break;
    179197        }
    180198        case UIVisualStateType_Fullscreen:
    181199        {
    182             m_pVisualState = new UIVisualStateFullscreen(this, m_session, m_pActionsPool);
     200            /* Create fullscreen visual state: */
     201            m_pVisualState = new UIVisualStateFullscreen(this, m_pSession, m_pActionsPool);
    183202            break;
    184203        }
    185204        case UIVisualStateType_Seamless:
    186205        {
    187             m_pVisualState = new UIVisualStateSeamless(this, m_session, m_pActionsPool);
     206            /* Create seamless visual state: */
     207            m_pVisualState = new UIVisualStateSeamless(this, m_pSession, m_pActionsPool);
    188208            break;
    189209        }
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.h

    r26637 r26691  
    2424#define __UIMachine_h__
    2525
     26/* Global includes */
     27#include <QObject>
     28
    2629/* Local includes */
    27 #include "COMDefs.h"
    2830#include "UIMachineDefs.h"
    2931
    3032/* Local forwards */
     33class UISession;
    3134class UIActionsPool;
    3235class UIVisualState;
     36class UIMachineLogic;
     37class CSession;
    3338
    3439class UIMachine : public QObject
     
    3843public:
    3944
     45    /* Virtual Machine constructor: */
    4046    UIMachine(UIMachine **ppSelf, const CSession &session);
    4147
    4248private slots:
    4349
     50    /* Visual state-change handler: */
    4451    void sltChangeVisualState(UIVisualStateType visualStateType);
    4552
    4653private:
    4754
     55    /* Move VM to default (normal) state: */
    4856    void enterBaseVisualState();
    4957
    50     CSession m_session;
     58    /* Private getters: */
     59    UIMachineLogic* machineLogic() const;
     60
     61    /* Private variables: */
     62    UISession *m_pSession;
    5163    UIActionsPool *m_pActionsPool;
    5264    UIVisualState *m_pVisualState;
     65
     66    /* Friend classes: */
     67    friend class UISession;
    5368};
    5469
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp

    r26656 r26691  
    4141#include "QIHttp.h"
    4242
     43#include "UISession.h"
    4344#include "UIActionsPool.h"
    4445#include "UIMachineLogic.h"
     
    6566#endif
    6667
    67 struct MountTarget
    68 {
    69     MountTarget() : name(QString("")), port(0), device(0), id(QString()), type(VBoxDefs::MediumType_Invalid) {}
    70     MountTarget(const QString &strName, LONG iPort, LONG iDevice)
     68struct MediumTarget
     69{
     70    MediumTarget() : name(QString("")), port(0), device(0), id(QString()), type(VBoxDefs::MediumType_Invalid) {}
     71    MediumTarget(const QString &strName, LONG iPort, LONG iDevice)
    7172        : name(strName), port(iPort), device(iDevice), id(QString()), type(VBoxDefs::MediumType_Invalid) {}
    72     MountTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strId)
     73    MediumTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strId)
    7374        : name(strName), port(iPort), device(iDevice), id(strId), type(VBoxDefs::MediumType_Invalid) {}
    74     MountTarget(const QString &strName, LONG iPort, LONG iDevice, VBoxDefs::MediumType eType)
     75    MediumTarget(const QString &strName, LONG iPort, LONG iDevice, VBoxDefs::MediumType eType)
    7576        : name(strName), port(iPort), device(iDevice), id(QString()), type(eType) {}
    7677    QString name;
     
    8081    VBoxDefs::MediumType type;
    8182};
    82 Q_DECLARE_METATYPE(MountTarget);
     83Q_DECLARE_METATYPE(MediumTarget);
     84
     85struct USBTarget
     86{
     87    USBTarget() : attach(false), id(QString()) {}
     88    USBTarget(bool bAttach, const QString &strId)
     89        : attach(bAttach), id(strId) {}
     90    bool attach;
     91    QString id;
     92};
     93Q_DECLARE_METATYPE(USBTarget);
    8394
    8495class UINetworkAdaptersDialog : public QIWithRetranslateUI<QDialog>
     
    331342
    332343UIMachineLogic* UIMachineLogic::create(QObject *pParent,
    333                                        const CSession &session,
     344                                       UISession *pSession,
    334345                                       UIActionsPool *pActionsPool,
    335346                                       UIVisualStateType visualStateType)
     
    339350    {
    340351        case UIVisualStateType_Normal:
    341             logic = new UIMachineLogicNormal(pParent, session, pActionsPool);
     352            logic = new UIMachineLogicNormal(pParent, pSession, pActionsPool);
    342353            break;
    343354        case UIVisualStateType_Fullscreen:
    344             // logic = new UIMachineLogicFullscreen(pParent, session, pActionsPool);
    345             logic = new UIMachineLogicNormal(pParent, session, pActionsPool);
     355            // logic = new UIMachineLogicFullscreen(pParent, pSession, pActionsPool);
     356            logic = new UIMachineLogicNormal(pParent, pSession, pActionsPool);
    346357            break;
    347358        case UIVisualStateType_Seamless:
    348             // logic = new UIMachineLogicSeamless(pParent, session, pActionsPool);
    349             logic = new UIMachineLogicNormal(pParent, session, pActionsPool);
     359            // logic = new UIMachineLogicSeamless(pParent, pSession, pActionsPool);
     360            logic = new UIMachineLogicNormal(pParent, pSession, pActionsPool);
    350361            break;
    351362    }
     
    354365
    355366UIMachineLogic::UIMachineLogic(QObject *pParent,
    356                                const CSession &session,
     367                               UISession *pSession,
    357368                               UIActionsPool *pActionsPool,
    358369                               UIVisualStateType visualStateType)
     370    /* Initialize parent class: */
    359371    : QObject(pParent)
     372    /* Initialize protected members: */
    360373    , m_pMachineWindowContainer(0)
    361     , m_session(session)
     374    /* Initialize private members: */
     375    , m_pSession(pSession)
    362376    , m_pActionsPool(pActionsPool)
    363377    , m_machineState(KMachineState_Null)
    364378    , m_visualStateType(visualStateType)
     379    /* Action groups: */
    365380    , m_pRunningActions(0)
    366381    , m_pRunningOrPausedActions(0)
     382    /* Bool flags: */
    367383    , m_bIsFirstTimeStarted(false)
    368384    , m_bIsOpenViewFinished(false)
     
    376392UIMachineLogic::~UIMachineLogic()
    377393{
    378 #ifdef VBOX_WITH_DEBUGGER_GUI
     394#ifdef VBOX_WITH_DEBUGGER_GUI // TODO: Should we close debugger now?
    379395    /* Close debugger: */
    380     // TODO: Check that logic!
    381396    //dbgDestroy();
    382397#endif
    383398}
    384399
    385 void UIMachineLogic::updateAppearanceOf(int iElement)
    386 {
    387     /* Update logic: */
    388     CMachine machine = session().GetMachine();
    389 
    390     bool isRunningOrPaused = machineState() == KMachineState_Running ||
    391                              machineState() == KMachineState_Paused ||
    392                              machineState() == KMachineState_Teleporting ||
    393                              machineState() == KMachineState_LiveSnapshotting;
    394 
    395     if (iElement & UIVisualElement_PauseStuff)
    396     {
    397         actionsPool()->action(UIActionIndex_Toggle_Pause)->setEnabled(isRunningOrPaused);
    398     }
    399 
    400     /* Update window: */
    401     machineWindowWrapper()->updateAppearanceOf(iElement);
     400void UIMachineLogic::prepareConsoleConnections()
     401{
     402    connect(uisession(), SIGNAL(sigStateChange(KMachineState)), this, SLOT(sltMachineStateChanged(KMachineState)));
     403    connect(uisession(), SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged()));
    402404}
    403405
     
    416418    m_pRunningOrPausedActions->setExclusive(false);
    417419
    418     // TODO: Move actions into approprivate action groups!
     420    /* Move actions into first group: */
     421    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Toggle_Fullscreen));
     422    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Toggle_Seamless));
     423    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_AdjustWindow));
     424    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_TypeCAD));
     425#ifdef Q_WS_X11
     426    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_TypeCABS));
     427#endif
     428    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_Reset));
     429    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_Shutdown));
     430#ifdef VBOX_WITH_DEBUGGER_GUI
     431    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_Statistics));
     432    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Simple_CommandLine));
     433    m_pRunningActions->addAction(actionsPool()->action(UIActionIndex_Toggle_Logging));
     434#endif
     435
     436    /* Move actions into second group: */
     437    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize));
     438    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_MouseIntegration));
     439    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Toggle_MouseIntegration));
     440    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_TakeSnapshot));
     441    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_InformationDialog));
     442    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Toggle_Pause));
     443    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_Close));
     444    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_OpticalDevices));
     445    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_FloppyDevices));
     446    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_USBDevices));
     447    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_NetworkAdapters));
     448    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog));
     449    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Menu_SharedFolders));
     450    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog));
     451    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Toggle_VRDP));
     452    m_pRunningOrPausedActions->addAction(actionsPool()->action(UIActionIndex_Simple_InstallGuestTools));
    419453}
    420454
     
    422456{
    423457    /* "Machine" actions connections */
     458    connect(actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize), SIGNAL(toggled(bool)),
     459            this, SLOT(sltToggleGuestAutoresize(bool)));
    424460    connect(actionsPool()->action(UIActionIndex_Simple_AdjustWindow), SIGNAL(triggered()),
    425461            this, SLOT(sltAdjustWindow()));
     
    436472    connect(actionsPool()->action(UIActionIndex_Simple_InformationDialog), SIGNAL(triggered()),
    437473            this, SLOT(sltShowInformationDialog()));
     474    connect(actionsPool()->action(UIActionIndex_Toggle_Pause), SIGNAL(toggled(bool)),
     475            this, SLOT(sltPause(bool)));
    438476    connect(actionsPool()->action(UIActionIndex_Simple_Reset), SIGNAL(triggered()),
    439477            this, SLOT(sltReset()));
    440     connect(actionsPool()->action(UIActionIndex_Toggle_Pause), SIGNAL(toggled(bool)),
    441             this, SLOT(sltPause(bool)));
    442478    connect(actionsPool()->action(UIActionIndex_Simple_Shutdown), SIGNAL(triggered()),
    443479            this, SLOT(sltACPIShutdown()));
     
    450486    connect(actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu(), SIGNAL(aboutToShow()),
    451487            this, SLOT(sltPrepareStorageMenu()));
     488    connect(actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu(), SIGNAL(aboutToShow()),
     489            this, SLOT(sltPrepareUSBMenu()));
    452490    connect(actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog), SIGNAL(triggered()),
    453491            this, SLOT(sltOpenNetworkAdaptersDialog()));
    454492    connect(actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog), SIGNAL(triggered()),
    455493            this, SLOT(sltOpenSharedFoldersDialog()));
    456     connect(actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu(), SIGNAL(aboutToShow()),
    457             this, SLOT(sltPrepareUSBMenu()));
    458494    connect(actionsPool()->action(UIActionIndex_Toggle_VRDP), SIGNAL(toggled(bool)),
    459495            this, SLOT(sltSwitchVrdp(bool)));
     
    476512void UIMachineLogic::prepareRequiredFeatures()
    477513{
     514    /* Get current console: */
    478515    CConsole console = session().GetConsole();
    479516
     
    485522    if (fRecommendVirtEx && !bIsVirtEnabled)
    486523    {
    487         bool ret;
    488 
    489         // TODO: Check that logic!
    490         //sltPause(true);
     524        bool result;
     525
     526        pause();
    491527
    492528        bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx);
    493529
    494530        if (bIs64BitsGuest)
    495             ret = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
     531            result = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
    496532        else
    497             ret = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
    498 
    499         // TODO: Close application!
    500         //if (ret == true)
    501         //    machineWindowWrapper()->machineWindow()->close();
    502         // TODO: Check that logic!
    503         //else
    504         //    sltPause(false);
     533            result = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
     534
     535        if (result == true)
     536            sltClose();
     537        else
     538            unpause();
    505539    }
    506540
     
    514548void UIMachineLogic::loadLogicSettings()
    515549{
     550    /* Get current machine: */
    516551    CMachine machine = session().GetMachine();
    517552
    518     /* Extra-data settings */
     553    /* Extra-data settings: */
    519554    {
    520555        QString strSettings;
     
    533568    }
    534569
    535     /* Initial settings */
     570    /* Initial settings: */
    536571    {
    537572        /* Initialize storage stuff: */
     
    552587    }
    553588
    554     /* Availability settings */
     589    /* Availability settings: */
    555590    {
    556591        /* USB Stuff: */
     
    558593        if (usbController.isNull())
    559594        {
    560             /* Hide USB_Menu: */
    561             actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setVisible(false);
     595            /* Hide USB menu if controller is NULL: */
     596            actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(false);
    562597        }
    563598        else
    564599        {
    565             /* Enable/Disable USB_Menu: */
    566             actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(usbController.GetEnabled());
     600            /* Enable/Disable USB menu depending on USB controller: */
     601            actionsPool()->action(UIActionIndex_Menu_USBDevices)->setEnabled(usbController.GetEnabled());
    567602        }
    568603
     
    579614void UIMachineLogic::saveLogicSettings()
    580615{
     616    /* Get current machine: */
    581617    CMachine machine = session().GetMachine();
    582618
    583     /* Extra-data settings */
     619    /* Extra-data settings: */
    584620    {
    585621        machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
     
    591627        //machine.SetExtraData(VBoxDefs::GUI_MiniToolBarAutoHide, mMiniToolBar->isAutoHide() ? "on" : "off");
    592628    }
     629}
     630
     631CSession& UIMachineLogic::session()
     632{
     633    return m_pSession->session();
     634}
     635
     636void UIMachineLogic::sltMachineStateChanged(KMachineState newMachineState)
     637{
     638    if (m_machineState != newMachineState)
     639    {
     640        /* Variable flags: */
     641        bool bIsRunning = newMachineState == KMachineState_Running ||
     642                          newMachineState == KMachineState_Teleporting ||
     643                          newMachineState == KMachineState_LiveSnapshotting;
     644        bool bIsRunningOrPaused = bIsRunning ||
     645                                  newMachineState == KMachineState_Paused;
     646
     647        /* Update action groups: */
     648        m_pRunningActions->setEnabled(bIsRunning);
     649        m_pRunningOrPausedActions->setEnabled(bIsRunningOrPaused);
     650
     651        /* Do we have GURU? */
     652        bool bIsGuruMeditation = false;
     653
     654        switch (newMachineState)
     655        {
     656            case KMachineState_Stuck:
     657            {
     658                bIsGuruMeditation = true;
     659                break;
     660            }
     661            case KMachineState_Paused:
     662            {
     663                /* Was paused from CMachine side? */
     664                QAction *pPauseAction = actionsPool()->action(UIActionIndex_Toggle_Pause);
     665                if (!pPauseAction->isChecked())
     666                {
     667                    pPauseAction->blockSignals(true);
     668                    pPauseAction->setChecked(true);
     669                    pPauseAction->blockSignals(false);
     670                }
     671                break;
     672            }
     673            case KMachineState_Running:
     674            case KMachineState_Teleporting:
     675            case KMachineState_LiveSnapshotting:
     676            {
     677                /* Was started from CMachine side? */
     678                QAction *pPauseAction = actionsPool()->action(UIActionIndex_Toggle_Pause);
     679                if (isPaused() && pPauseAction->isChecked())
     680                {
     681                    pPauseAction->blockSignals(true);
     682                    pPauseAction->setChecked(false);
     683                    pPauseAction->blockSignals(false);
     684                }
     685                break;
     686            }
     687#ifdef Q_WS_X11
     688            case KMachineState_Starting:
     689            case KMachineState_Restoring:
     690            case KMachineState_TeleportingIn:
     691            {
     692                /* The keyboard handler may wish to do some release logging on startup.
     693                 * Tell it that the logger is now active. */
     694                doXKeyboardLogging(QX11Info::display());
     695                break;
     696            }
     697#endif
     698            default:
     699                break;
     700        }
     701
     702        /* Now storing new state: */
     703        m_machineState = newMachineState;
     704
     705        /* Close VM if was closed someway: */
     706        if (m_machineState == KMachineState_PoweredOff || m_machineState == KMachineState_Saved ||
     707            m_machineState == KMachineState_Teleported || m_machineState == KMachineState_Aborted)
     708        {
     709            /* VM has been powered off or saved or aborted, no matter internally or externally.
     710             * We must *safely* close the console window unless auto closure is disabled: */
     711            if (!m_bIsPreventAutoClose)
     712                machineWindowWrapper()->sltTryClose();
     713        }
     714
     715        /* Process GURU: */
     716        if (bIsGuruMeditation)
     717        {
     718            if (machineWindowWrapper()->machineView())
     719                machineWindowWrapper()->machineView()->setIgnoreGuestResize(true);
     720
     721            CConsole console = session().GetConsole();
     722            QString strLogFolder = console.GetMachine().GetLogFolder();
     723
     724            /* Take the screenshot for debugging purposes and save it */
     725            QString strFileName = strLogFolder + "/VBox.png";
     726            CDisplay display = console.GetDisplay();
     727            QImage shot = QImage(display.GetWidth(), display.GetHeight(), QImage::Format_RGB32);
     728            display.TakeScreenShot(shot.bits(), shot.width(), shot.height());
     729            shot.save(QFile::encodeName(strFileName), "PNG");
     730
     731            /* Warn the user about GURU: */
     732            if (vboxProblem().remindAboutGuruMeditation(console, QDir::toNativeSeparators(strLogFolder)))
     733            {
     734                qApp->processEvents();
     735                console.PowerDown();
     736                if (!console.isOk())
     737                    vboxProblem().cannotStopMachine(console);
     738            }
     739        }
     740
     741#ifdef Q_WS_MAC
     742        /* Update Dock Overlay: */
     743        if (machineWindowWrapper())
     744            machineWindowWrapper()->updateDockOverlay();
     745#endif
     746    }
     747}
     748
     749void UIMachineLogic::sltAdditionsStateChanged()
     750{
     751    /* Get console guest: */
     752    CGuest guest = session().GetConsole().GetGuest();
     753
     754    /* Variable flags: */
     755    bool bIsActive = guest.GetAdditionsActive();
     756    bool bIsGraphicsSupported = guest.GetSupportsGraphics();
     757    bool bIsSeamlessSupported = guest.GetSupportsSeamless();
     758
     759    /* Update action groups: */
     760    actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->setEnabled(bIsActive && bIsGraphicsSupported);
     761    actionsPool()->action(UIActionIndex_Toggle_Seamless)->setEnabled(bIsActive && bIsGraphicsSupported && bIsSeamlessSupported);
     762
     763    /* Store new values: */
     764    m_bIsSeamlessSupported = bIsSeamlessSupported;
     765    m_bIsGraphicsSupported = bIsGraphicsSupported;
     766
     767#if 0 // TODO: Re-activate seamless if necessary!
     768    /* If seamless mode should be enabled then check if it is enabled currently and re-enable it if open-view procedure is finished */
     769    if ((m_bIsSeamlessSupported != bIsSeamlessSupported) || (m_bIsGraphicsSupported != bIsGraphicsSupported))
     770    {
     771        if (actionsPool()->action(UIActionIndex_Toggle_Seamless)->isChecked() && m_bIsOpenViewFinished && bIsGraphicsSupported && bIsSeamlessSupported)
     772            toggleFullscreenMode(true, true);
     773    }
     774#endif
     775
     776    /* Check the GA version only in case of additions are active: */
     777    if (!bIsActive)
     778        return;
     779
     780    /* Check the Guest Additions version and warn the user about possible compatibility issues in case if the installed version is outdated. */
     781    QString strVersion = guest.GetAdditionsVersion();
     782    uint uVersion = strVersion.toUInt();
     783    /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/
     784    QString strRealVersion = QString("%1.%2").arg(RT_HIWORD(uVersion)).arg(RT_LOWORD(uVersion));
     785    QString strExpectedVersion = QString("%1.%2").arg(VMMDEV_VERSION_MAJOR).arg(VMMDEV_VERSION_MINOR);
     786    if (RT_HIWORD(uVersion) < VMMDEV_VERSION_MAJOR)
     787    {
     788        vboxProblem().warnAboutTooOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
     789    }
     790    else if (RT_HIWORD(uVersion) == VMMDEV_VERSION_MAJOR && RT_LOWORD(uVersion) <  VMMDEV_VERSION_MINOR)
     791    {
     792        vboxProblem().warnAboutOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
     793    }
     794    else if (uVersion > VMMDEV_VERSION)
     795    {
     796        vboxProblem().warnAboutNewAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
     797    }
     798}
     799
     800void UIMachineLogic::sltToggleGuestAutoresize(bool /* bEnabled */)
     801{
     802    /* Do not process if window or view is missing! */
     803    if (!machineWindowWrapper() || !machineWindowWrapper()->machineView())
     804        return;
     805
     806    // TODO: Enable/Disable guest-autoresize for machine view! */
    593807}
    594808
     
    654868        /* Suspend the VM and ignore the close event if failed to do so.
    655869         * pause() will show the error message to the user. */
    656         if (!pause(true))
     870        if (!pause())
    657871            return;
    658872    }
     
    690904    /* Restore the running state if needed. */
    691905    if (!bWasPaused)
    692         pause(false);
     906        unpause();
    693907}
    694908
     
    716930void UIMachineLogic::sltPause(bool aOn)
    717931{
    718     /* Do not process if window is missing! */
    719932    pause(aOn);
    720 
    721     /* Update appearance: */
    722     updateAppearanceOf(UIVisualElement_PauseStuff);
    723933}
    724934
     
    749959void UIMachineLogic::sltPrepareStorageMenu()
    750960{
     961    /* Get the sender() menu: */
    751962    QMenu *pMenu = qobject_cast<QMenu*>(sender());
    752963    AssertMsg(pMenu, ("This slot should only be called on hovering storage menu!\n"));
    753964    pMenu->clear();
    754965
     966    /* Short way to common storage menus: */
    755967    QMenu *pOpticalDevicesMenu = actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu();
    756968    QMenu *pFloppyDevicesMenu = actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu();
    757969
     970    /* Determine device type: */
    758971    KDeviceType deviceType = pMenu == pOpticalDevicesMenu ? KDeviceType_DVD :
    759972                             pMenu == pFloppyDevicesMenu  ? KDeviceType_Floppy :
     
    761974    AssertMsg(deviceType != KDeviceType_Null, ("Incorrect storage device type!\n"));
    762975
     976    /* Determine medium type: */
    763977    VBoxDefs::MediumType mediumType = pMenu == pOpticalDevicesMenu ? VBoxDefs::MediumType_DVD :
    764978                                      pMenu == pFloppyDevicesMenu  ? VBoxDefs::MediumType_Floppy :
     
    766980    AssertMsg(mediumType != VBoxDefs::MediumType_Invalid, ("Incorrect storage medium type!\n"));
    767981
     982    /* Fill attachments menu: */
    768983    CMachine machine = session().GetMachine();
    769984    const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
     
    773988        if (!controller.isNull() && (attachment.GetType() == deviceType))
    774989        {
    775             /* Attachment menu item */
     990            /* Attachment menu item: */
    776991            QMenu *pAttachmentMenu = 0;
    777992            if (pMenu->menuAction()->data().toInt() > 1)
     
    7991014            else pAttachmentMenu = pMenu;
    8001015
    801             /* Mount Medium actions */
     1016            /* Mount Medium actions: */
    8021017            CMediumVector mediums;
    8031018            switch (mediumType)
     
    8151030            }
    8161031
     1032            /* Mediums to be shown: */
    8171033            int mediumsToBeShown = 0;
    8181034            const int maxMediumsToBeShown = 5;
     
    8461062                    mountMediumAction->setCheckable(true);
    8471063                    mountMediumAction->setChecked(!currentMedium.isNull() && medium.GetId() == currentId);
    848                     mountMediumAction->setData(QVariant::fromValue(MountTarget(controller.GetName(),
    849                                                                                attachment.GetPort(),
    850                                                                                attachment.GetDevice(),
    851                                                                                medium.GetId())));
     1064                    mountMediumAction->setData(QVariant::fromValue(MediumTarget(controller.GetName(),
     1065                                                                                attachment.GetPort(),
     1066                                                                                attachment.GetDevice(),
     1067                                                                                medium.GetId())));
    8521068                    connect(mountMediumAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium()));
    8531069                    pAttachmentMenu->addAction(mountMediumAction);
     
    8581074            }
    8591075
    860             /* Virtual Media Manager action */
     1076            /* Virtual Media Manager action: */
    8611077            QAction *callVMMAction = new QAction(pAttachmentMenu);
    8621078            callVMMAction->setIcon(QIcon(":/diskimage_16px.png"));
    863             callVMMAction->setData(QVariant::fromValue(MountTarget(controller.GetName(),
    864                                                                    attachment.GetPort(),
    865                                                                    attachment.GetDevice(),
    866                                                                    mediumType)));
     1079            callVMMAction->setData(QVariant::fromValue(MediumTarget(controller.GetName(),
     1080                                                                    attachment.GetPort(),
     1081                                                                    attachment.GetDevice(),
     1082                                                                    mediumType)));
    8671083            connect(callVMMAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium()));
    8681084            pAttachmentMenu->addAction(callVMMAction);
    8691085
    870             /* Separator */
     1086            /* Insert separator: */
    8711087            pAttachmentMenu->addSeparator();
    8721088
    873             /* Unmount Medium action */
     1089            /* Unmount Medium action: */
    8741090            QAction *unmountMediumAction = new QAction(pAttachmentMenu);
    8751091            unmountMediumAction->setEnabled(!currentMedium.isNull());
    876             unmountMediumAction->setData(QVariant::fromValue(MountTarget(controller.GetName(),
    877                                                                          attachment.GetPort(),
    878                                                                          attachment.GetDevice())));
     1092            unmountMediumAction->setData(QVariant::fromValue(MediumTarget(controller.GetName(),
     1093                                                                          attachment.GetPort(),
     1094                                                                          attachment.GetDevice())));
    8791095            connect(unmountMediumAction, SIGNAL(triggered(bool)), this, SLOT(sltMountStorageMedium()));
    8801096            pAttachmentMenu->addAction(unmountMediumAction);
     
    9051121        /* Empty menu item */
    9061122        Assert(pMenu->isEmpty());
    907         QAction *emptyMenuAction = new QAction(pMenu);
    908         emptyMenuAction->setEnabled(false);
     1123        QAction *pEmptyMenuAction = new QAction(pMenu);
     1124        pEmptyMenuAction->setEnabled(false);
    9091125        switch (mediumType)
    9101126        {
    9111127            case VBoxDefs::MediumType_DVD:
    912                 emptyMenuAction->setText(tr("No CD/DVD Devices Attached"));
     1128                pEmptyMenuAction->setText(tr("No CD/DVD Devices Attached"));
     1129                pEmptyMenuAction->setToolTip(tr("No CD/DVD devices attached to that VM"));
    9131130                break;
    9141131            case VBoxDefs::MediumType_Floppy:
    915                 emptyMenuAction->setText(tr("No Floppy Devices Attached"));
     1132                pEmptyMenuAction->setText(tr("No Floppy Devices Attached"));
     1133                pEmptyMenuAction->setToolTip(tr("No floppy devices attached to that VM"));
    9161134                break;
    9171135            default:
    9181136                break;
    9191137        }
    920         emptyMenuAction->setIcon(VBoxGlobal::iconSet(":/delete_16px.png", ":/delete_dis_16px.png"));
    921         pMenu->addAction(emptyMenuAction);
     1138        pEmptyMenuAction->setIcon(VBoxGlobal::iconSet(":/delete_16px.png", ":/delete_dis_16px.png"));
     1139        pMenu->addAction(pEmptyMenuAction);
    9221140    }
    9231141}
     
    9251143void UIMachineLogic::sltMountStorageMedium()
    9261144{
    927     /* Get sender action */
     1145    /* Get sender action: */
    9281146    QAction *action = qobject_cast<QAction*>(sender());
    9291147    AssertMsg(action, ("This slot should only be called on selecting storage menu item!\n"));
    9301148
    931     /* Get current machine */
     1149    /* Get current machine: */
    9321150    CMachine machine = session().GetMachine();
    9331151
    934     /* Get mount-target */
    935     MountTarget target = action->data().value<MountTarget>();
    936 
    937     /* Current mount-target attributes */
     1152    /* Get mount-target: */
     1153    MediumTarget target = action->data().value<MediumTarget>();
     1154
     1155    /* Current mount-target attributes: */
    9381156    CMediumAttachment currentAttachment = machine.GetMediumAttachment(target.name, target.port, target.device);
    9391157    CMedium currentMedium = currentAttachment.GetMedium();
    9401158    QString currentId = currentMedium.isNull() ? QString("") : currentMedium.GetId();
    9411159
    942     /* New mount-target attributes */
     1160    /* New mount-target attributes: */
    9431161    QString newId = QString("");
    9441162    bool selectWithMediaManager = target.type != VBoxDefs::MediumType_Invalid;
    9451163
    946     /* Open Virtual Media Manager to select image id */
     1164    /* Open Virtual Media Manager to select image id: */
    9471165    if (selectWithMediaManager)
    9481166    {
    949         /* Search for already used images */
     1167        /* Search for already used images: */
    9501168        QStringList usedImages;
    9511169        foreach (const CMediumAttachment &attachment, machine.GetMediumAttachments())
     
    9551173                usedImages << medium.GetId();
    9561174        }
    957         /* Open VMM Dialog */
     1175        /* Open VMM Dialog: */
    9581176        VBoxMediaManagerDlg dlg(machineWindowWrapper()->machineWindow());
    9591177        dlg.setup(target.type, true /* select? */, true /* refresh? */, machine, currentId, true, usedImages);
     
    9621180        else return;
    9631181    }
    964     /* Use medium which was sent */
     1182    /* Use medium which was sent: */
    9651183    else if (!target.id.isNull() && target.id != currentId)
    9661184        newId = target.id;
     
    9681186    bool mount = !newId.isEmpty();
    9691187
    970     /* Remount medium to the predefined port/device */
     1188    /* Remount medium to the predefined port/device: */
    9711189    bool wasMounted = false;
    9721190    machine.MountMedium(target.name, target.port, target.device, newId, false /* force */);
     
    9751193    else
    9761194    {
    977         /* Ask for force remounting */
     1195        /* Ask for force remounting: */
    9781196        if (vboxProblem().cannotRemountMedium(machineWindowWrapper()->machineWindow(), machine, vboxGlobal().findMedium (mount ? newId : currentId), mount, true /* retry? */) == QIMessageBox::Ok)
    9791197        {
    980             /* Force remount medium to the predefined port/device. */
     1198            /* Force remount medium to the predefined port/device: */
    9811199            machine.MountMedium(target.name, target.port, target.device, newId, true /* force */);
    9821200            if (machine.isOk())
     
    9961214}
    9971215
     1216void UIMachineLogic::sltPrepareUSBMenu()
     1217{
     1218    /* Get the sender() menu: */
     1219    QMenu *pMenu = qobject_cast<QMenu*>(sender());
     1220    QMenu *pUSBDevicesMenu = actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu();
     1221    AssertMsg(pMenu == pUSBDevicesMenu, ("This slot should only be called on hovering USB menu!\n"));
     1222    pMenu->clear();
     1223
     1224    /* Get HOST: */
     1225    CHost host = vboxGlobal().virtualBox().GetHost();
     1226
     1227    /* Get USB devices list: */
     1228    CHostUSBDeviceVector devices = host.GetUSBDevices();
     1229
     1230    /* Fill USB devices menu: */
     1231    bool bIsUSBListEmpty = devices.size() == 0;
     1232    if (bIsUSBListEmpty)
     1233    {
     1234        /* Fill USB devices menu: */
     1235        QAction *pEmptyMenuAction = new QAction(pMenu);
     1236        pEmptyMenuAction->setEnabled(false);
     1237        pEmptyMenuAction->setText(tr("No USB Devices Connected"));
     1238        pEmptyMenuAction->setIcon(VBoxGlobal::iconSet(":/delete_16px.png", ":/delete_dis_16px.png"));
     1239        pEmptyMenuAction->setToolTip(tr("No supported devices connected to the host PC"));
     1240    }
     1241    else
     1242    {
     1243        foreach (const CHostUSBDevice hostDevice, devices)
     1244        {
     1245            /* Get common USB device: */
     1246            CUSBDevice device(hostDevice);
     1247
     1248            /* Create USB device action: */
     1249            QAction *attachUSBAction = new QAction(vboxGlobal().details(device), pMenu);
     1250            attachUSBAction->setCheckable(true);
     1251            connect(attachUSBAction, SIGNAL(triggered(bool)), this, SLOT(sltAttachUSBDevice()));
     1252            pMenu->addAction(attachUSBAction);
     1253
     1254            /* Check if that USB device was alread attached to this session: */
     1255            CConsole console = session().GetConsole();
     1256            CUSBDevice attachedDevice = console.FindUSBDeviceById(device.GetId());
     1257            attachUSBAction->setChecked(!attachedDevice.isNull());
     1258            attachUSBAction->setEnabled(hostDevice.GetState() != KUSBDeviceState_Unavailable);
     1259
     1260            /* Set USB attach data: */
     1261            attachUSBAction->setData(QVariant::fromValue(USBTarget(!attachUSBAction->isChecked(), device.GetId())));
     1262        }
     1263    }
     1264}
     1265
     1266void UIMachineLogic::sltAttachUSBDevice()
     1267{
     1268    /* Get sender action: */
     1269    QAction *action = qobject_cast<QAction*>(sender());
     1270    AssertMsg(action, ("This slot should only be called on selecting USB menu item!\n"));
     1271
     1272    /* Get current console: */
     1273    CConsole console = session().GetConsole();
     1274
     1275    /* Get USB target: */
     1276    USBTarget target = action->data().value<USBTarget>();
     1277    CUSBDevice device = console.FindUSBDeviceById(target.id);
     1278
     1279    /* Attach USB device: */
     1280    if (target.attach)
     1281    {
     1282        console.AttachUSBDevice(target.id);
     1283        if (!console.isOk())
     1284            vboxProblem().cannotAttachUSBDevice(console, vboxGlobal().details(device));
     1285    }
     1286    else
     1287    {
     1288        console.DetachUSBDevice(target.id);
     1289        if (!console.isOk())
     1290            vboxProblem().cannotDetachUSBDevice(console, vboxGlobal().details(device));
     1291    }
     1292}
     1293
    9981294void UIMachineLogic::sltOpenNetworkAdaptersDialog()
    9991295{
     
    10181314}
    10191315
    1020 void UIMachineLogic::sltPrepareUSBMenu()
    1021 {
    1022 }
    1023 
    1024 void UIMachineLogic::sltAttachUSBDevice()
    1025 {
    1026 }
    1027 
    10281316void UIMachineLogic::sltSwitchVrdp(bool aOn)
    10291317{
    10301318    /* Enable VRDP server if possible: */
    10311319    CVRDPServer server = session().GetMachine().GetVRDPServer();
    1032     AssertMsg(!server.isNull(), ("VRDP Server should not be null!\n"));
     1320    AssertMsg(!server.isNull(), ("VRDP server should not be null!\n"));
    10331321    server.SetEnabled(aOn);
    1034 
    1035     /* Update appearance: */
    1036     updateAppearanceOf(UIVisualElement_VRDPStuff);
    10371322}
    10381323
     
    10701355    }
    10711356
     1357#if 0 // TODO: Rework additions downloader logic...
    10721358    /* Download the required image */
    1073     // TODO: Rework additions downloader logic...
    1074     #if 0
    10751359    int result = vboxProblem().cannotFindGuestAdditions(QDir::toNativeSeparators(strSrc1), QDir::toNativeSeparators(strSrc2));
    10761360    if (result == QIMessageBox::Yes)
     
    10831367        //pdl->start();
    10841368    }
    1085     #endif
     1369#endif
    10861370}
    10871371
     
    11331417#endif
    11341418
    1135 void UIMachineLogic::sltUpdateMachineState(KMachineState machineState)
    1136 {
    1137     bool bGuruMeditation = false;
    1138 
    1139     if (machineWindowWrapper() && m_machineState != machineState)
    1140     {
    1141         switch (machineState)
    1142         {
    1143             case KMachineState_Stuck:
    1144             {
    1145                 bGuruMeditation = true;
    1146                 break;
    1147             }
    1148             case KMachineState_Paused:
    1149             {
    1150                 if (!actionsPool()->action(UIActionIndex_Toggle_Pause)->isChecked())
    1151                     actionsPool()->action(UIActionIndex_Toggle_Pause)->setChecked(true);
    1152                 break;
    1153             }
    1154             case KMachineState_Running:
    1155             case KMachineState_Teleporting:
    1156             case KMachineState_LiveSnapshotting:
    1157             {
    1158                 if ((m_machineState == KMachineState_Paused ||
    1159                      m_machineState == KMachineState_TeleportingPausedVM)
    1160                      && actionsPool()->action(UIActionIndex_Toggle_Pause)->isChecked())
    1161                      actionsPool()->action(UIActionIndex_Toggle_Pause)->setChecked(false);
    1162                 break;
    1163             }
    1164 #ifdef Q_WS_X11
    1165             case KMachineState_Starting:
    1166             case KMachineState_Restoring:
    1167             case KMachineState_TeleportingIn:
    1168             {
    1169                 /* The keyboard handler may wish to do some release logging on startup.
    1170                  * Tell it that the logger is now active. */
    1171                 doXKeyboardLogging(QX11Info::display());
    1172                 break;
    1173             }
    1174 #endif
    1175             default:
    1176                 break;
    1177         }
    1178 
    1179         bool bIsRunning = machineState == KMachineState_Running ||
    1180                           machineState == KMachineState_Teleporting ||
    1181                           machineState == KMachineState_LiveSnapshotting;
    1182 
    1183         bool bIsRunningOrPaused = machineState == KMachineState_Running ||
    1184                                   machineState == KMachineState_Teleporting ||
    1185                                   machineState == KMachineState_LiveSnapshotting ||
    1186                                   machineState == KMachineState_Paused;
    1187 
    1188         m_pRunningActions->setEnabled(bIsRunning);
    1189         m_pRunningOrPausedActions->setEnabled(bIsRunningOrPaused);
    1190 
    1191         m_machineState = machineState;
    1192 
    1193         updateAppearanceOf(UIVisualElement_WindowCaption |
    1194                            UIVisualElement_HDStuff | UIVisualElement_CDStuff | UIVisualElement_FDStuff |
    1195                            UIVisualElement_NetworkStuff | UIVisualElement_USBStuff | UIVisualElement_VRDPStuff |
    1196                            UIVisualElement_PauseStuff | UIVisualElement_MouseIntegrationStuff);
    1197 
    1198         if (machineState == KMachineState_PoweredOff ||
    1199             machineState == KMachineState_Saved ||
    1200             machineState == KMachineState_Teleported ||
    1201             machineState == KMachineState_Aborted)
    1202         {
    1203             /* VM has been powered off or saved or aborted, no matter internally or externally.
    1204              * We must *safely* close the console window unless auto closure is disabled: */
    1205             if (!m_bIsPreventAutoClose)
    1206                 machineWindowWrapper()->sltTryClose();
    1207         }
    1208     }
    1209 
    1210     if (bGuruMeditation)
    1211     {
    1212         machineWindowWrapper()->machineView()->setIgnoreGuestResize(true);
    1213 
    1214         CConsole console = session().GetConsole();
    1215         QString strLogFolder = console.GetMachine().GetLogFolder();
    1216 
    1217         /* Take the screenshot for debugging purposes and save it */
    1218         QString strFileName = strLogFolder + "/VBox.png";
    1219 
    1220         CDisplay display = console.GetDisplay();
    1221         QImage shot = QImage(display.GetWidth(), display.GetHeight(), QImage::Format_RGB32);
    1222         display.TakeScreenShot(shot.bits(), shot.width(), shot.height());
    1223         shot.save(QFile::encodeName(strFileName), "PNG");
    1224 
    1225         if (vboxProblem().remindAboutGuruMeditation(console, QDir::toNativeSeparators(strLogFolder)))
    1226         {
    1227             qApp->processEvents();
    1228             console.PowerDown();
    1229             if (!console.isOk())
    1230                 vboxProblem().cannotStopMachine(console);
    1231         }
    1232     }
    1233 
    1234 #ifdef Q_WS_MAC
    1235     if (machineWindowWrapper())
    1236         machineWindowWrapper()->updateDockOverlay();
    1237 #endif
    1238 }
    1239 
    1240 void UIMachineLogic::sltUpdateAdditionsState(const QString &strVersion, bool bIsActive,
    1241                                              bool bIsSeamlessSupported, bool bIsGraphicsSupported)
    1242 {
    1243     actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->setEnabled(bIsActive && bIsGraphicsSupported);
    1244     actionsPool()->action(UIActionIndex_Toggle_Seamless)->setEnabled(bIsActive && bIsGraphicsSupported && bIsSeamlessSupported);
    1245 
    1246     if ((m_bIsSeamlessSupported != bIsSeamlessSupported) || (m_bIsGraphicsSupported != bIsGraphicsSupported))
    1247     {
    1248         m_bIsSeamlessSupported = bIsSeamlessSupported;
    1249         m_bIsGraphicsSupported = bIsGraphicsSupported;
    1250 
    1251         // TODO: How should that be performed now?
    1252         /* If seamless mode should be enabled then check if it is enabled currently and re-enable it if open-view procedure is finished */
    1253         //if (actionsPool()->action(UIActionIndex_Toggle_Seamless)->isChecked() && m_bIsOpenViewFinished && bIsGraphicsSupported && bIsSeamlessSupported)
    1254         //    toggleFullscreenMode(true, true);
    1255     }
    1256 
    1257     /* Check the GA version only in case of additions are active */
    1258     if (!bIsActive)
    1259         return;
    1260 
    1261     /* Check the Guest Additions version and warn the user about possible
    1262      * compatibility issues in case if the installed version is outdated. */
    1263     uint uVersion = strVersion.toUInt();
    1264     /** @todo r=bird: This isn't want we want! We want the VirtualBox version of the additions, all three numbers. See @bugref{4084}.*/
    1265     QString strRealVersion = QString("%1.%2").arg(RT_HIWORD(uVersion)).arg(RT_LOWORD(uVersion));
    1266     QString strExpectedVersion = QString("%1.%2").arg(VMMDEV_VERSION_MAJOR).arg(VMMDEV_VERSION_MINOR);
    1267 
    1268     if (RT_HIWORD(uVersion) < VMMDEV_VERSION_MAJOR)
    1269     {
    1270         vboxProblem().warnAboutTooOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
    1271     }
    1272     else if (RT_HIWORD(uVersion) == VMMDEV_VERSION_MAJOR && RT_LOWORD(uVersion) <  VMMDEV_VERSION_MINOR)
    1273     {
    1274         vboxProblem().warnAboutOldAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
    1275     }
    1276     else if (uVersion > VMMDEV_VERSION)
    1277     {
    1278         vboxProblem().warnAboutNewAdditions(machineWindowWrapper()->machineWindow(), strRealVersion, strExpectedVersion);
    1279     }
    1280 }
    1281 
    1282 void UIMachineLogic::sltUpdateMouseState(int iState)
     1419void UIMachineLogic::sltMouseStateChanged(int iState)
    12831420{
    12841421    actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setEnabled(iState & UIMouseStateType_MouseAbsolute);
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h

    r26656 r26691  
    3535
    3636/* Local forwards */
     37class UISession;
    3738class UIActionsPool;
    3839class UIMachineWindow;
     
    4647    /* Factory function to create required logic sub-child: */
    4748    static UIMachineLogic* create(QObject *pParent,
    48                                   const CSession &session,
     49                                  UISession *pSession,
    4950                                  UIActionsPool *pActionsPool,
    5051                                  UIVisualStateType visualStateType);
    5152
    5253    /* Public getters: */
    53     CSession& session() { return m_session; }
     54    UISession* uisession() { return m_pSession; }
    5455    UIActionsPool* actionsPool() { return m_pActionsPool; }
     56    UIVisualStateType visualStateType() const { return m_visualStateType; }
     57    UIMachineWindow* machineWindowWrapper() { return m_pMachineWindowContainer; }
    5558    KMachineState machineState() const { return m_machineState; }
    56     UIVisualStateType visualStateType() const { return m_visualStateType; }
    57     bool isPaused() const { return m_machineState == KMachineState_Paused || m_machineState == KMachineState_TeleportingPausedVM; }
    58 
    59     /* Public setters: */
    60     bool pause(bool bPaused);
     59    bool isPaused() const { return m_machineState == KMachineState_Paused ||
     60                            m_machineState == KMachineState_TeleportingPausedVM; }
    6161
    6262protected:
    6363
    64     /* Common machine logic constructor: */
     64    /* Machine logic constructor/destructor: */
    6565    UIMachineLogic(QObject *pParent,
    66                    const CSession &session,
     66                   UISession *pSession,
    6767                   UIActionsPool *pActionsPool,
    6868                   UIVisualStateType visualStateType);
    69     /* Common machine logic destructor: */
    7069    virtual ~UIMachineLogic();
    7170
    72     /* Update routines: */
    73     virtual void updateAppearanceOf(int iElement);
    74 
    7571    /* Prepare helpers: */
     72    virtual void prepareConsoleConnections();
    7673    virtual void prepareActionGroups();
    7774    virtual void prepareActionConnections();
     
    8481    //void cleanupActionConnections();
    8582    //void cleanupActionGroups();
     83    //void cleanupConsoleConnections();
    8684
    8785    /* Protected getters: */
    88     UIMachineWindow* machineWindowWrapper() { return m_pMachineWindowContainer; }
     86    CSession& session();
    8987    bool isFirstTimeStarted() const { return m_bIsFirstTimeStarted; }
    9088    bool isPreventAutoClose() const { return m_bIsPreventAutoClose; }
     
    9593    void setOpenViewFinished(bool bIsOpenViewFinished) { m_bIsOpenViewFinished = bIsOpenViewFinished; }
    9694
     95    /* Console related routines: */
     96    bool pause() { return pause(true); }
     97    bool unpause() { return pause(false); }
     98
    9799    /* Protected variables: */
    98100    UIMachineWindow *m_pMachineWindowContainer;
     
    100102private slots:
    101103
     104    /* Console callback handlers: */
     105    void sltMachineStateChanged(KMachineState newMachineState);
     106    void sltAdditionsStateChanged();
     107
    102108    /* "Machine" menu funtionality */
     109    void sltToggleGuestAutoresize(bool bEnabled);
    103110    void sltAdjustWindow();
    104     void sltToggleMouseIntegration(bool bOff);
     111    void sltToggleMouseIntegration(bool bDisabled);
    105112    void sltTypeCAD();
    106113#ifdef Q_WS_X11
     
    117124    void sltPrepareStorageMenu();
    118125    void sltMountStorageMedium();
     126    void sltPrepareUSBMenu();
     127    void sltAttachUSBDevice();
    119128    void sltOpenNetworkAdaptersDialog();
    120129    void sltOpenSharedFoldersDialog();
    121     void sltPrepareUSBMenu();
    122     void sltAttachUSBDevice();
    123130    void sltSwitchVrdp(bool bOn);
    124131    void sltInstallGuestAdditions();
     
    131138#endif
    132139
    133     /* Machine state change handler */
    134     void sltUpdateMachineState(KMachineState machineState);
    135     /* Guest Additions state change handler */
    136     void sltUpdateAdditionsState(const QString &strVersion, bool bActive, bool bSeamlessSupported, bool bGraphicsSupported);
    137     /* Mouse Integration state change handler */
    138     void sltUpdateMouseState(int iState);
     140    /* Machine view handlers: */
     141    void sltMouseStateChanged(int iState);
    139142
    140143private:
    141144
    142145    /* Utility functions: */
     146    bool pause(bool bPaused);
    143147    void installGuestAdditionsFrom(const QString &strSource);
    144     static int searchMaxSnapshotIndex(const CMachine &machine, const CSnapshot &snapshot, const QString &strNameTemplate);
    145 #ifdef VBOX_WITH_DEBUGGER_GUI
    146     bool dbgCreated();
    147     void dbgDestroy();
    148     void dbgAdjustRelativePos();
    149 #endif
    150 
    151 #if 0 // TODO: Where to move that?
    152 # ifdef Q_WS_MAC
    153     void fadeToBlack();
    154     void fadeToNormal();
    155 # endif
    156     bool toggleFullscreenMode(bool aOn, bool aSeamless);
    157     void switchToFullscreen(bool aOn, bool aSeamless);
    158     void setViewInSeamlessMode(const QRect &aTargetRect);
    159 #endif
     148    static int searchMaxSnapshotIndex(const CMachine &machine,
     149                                      const CSnapshot &snapshot,
     150                                      const QString &strNameTemplate);
    160151
    161152    /* Private variables: */
    162     CSession m_session;
     153    UISession *m_pSession;
    163154    UIActionsPool *m_pActionsPool;
    164155    KMachineState m_machineState;
     
    175166    bool m_bIsPreventAutoClose : 1;
    176167
     168    /* Friend classes: */
     169    friend class UIMachineWindow;
     170
    177171#ifdef VBOX_WITH_DEBUGGER_GUI
     172    /* Debugger functionality: */
     173    bool dbgCreated();
     174    void dbgDestroy();
     175    void dbgAdjustRelativePos();
    178176    /* The handle to the debugger gui: */
    179177    PDBGGUI m_dbgGui;
     
    181179    PCDBGGUIVT m_dbgGuiVT;
    182180#endif
     181
     182#if 0 // TODO: Where to move that?
     183# ifdef Q_WS_MAC
     184    void fadeToBlack();
     185    void fadeToNormal();
     186# endif
     187    bool toggleFullscreenMode(bool aOn, bool aSeamless);
     188    void switchToFullscreen(bool aOn, bool aSeamless);
     189    void setViewInSeamlessMode(const QRect &aTargetRect);
     190#endif
    183191};
    184192
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r26637 r26691  
    3232#include "VBoxProblemReporter.h"
    3333#include "UIFrameBuffer.h"
     34#include "UISession.h"
    3435#include "UIActionsPool.h"
    3536#include "UIMachineLogic.h"
     
    8485#endif /* defined (Q_WS_MAC) */
    8586
    86 /** Guest mouse pointer shape change event. */
    87 class MousePointerChangeEvent : public QEvent
    88 {
    89 public:
    90 
    91     MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot, uint width, uint height, const uchar *shape)
    92         : QEvent((QEvent::Type)VBoxDefs::MousePointerChangeEventType)
    93         , vis(visible), alph(alpha), xh(xhot), yh(yhot), w(width), h(height), data(0)
    94     {
    95         uint dataSize = ((((width + 7) / 8 * height) + 3) & ~3) + width * 4 * height;
    96 
    97         if (shape)
    98         {
    99             data = new uchar[dataSize];
    100             memcpy((void*)data, (void*)shape, dataSize);
    101         }
    102     }
    103 
    104     ~MousePointerChangeEvent()
    105     {
    106         if (data) delete[] data;
    107     }
    108 
    109     bool isVisible() const { return vis; }
    110     bool hasAlpha() const { return alph; }
    111     uint xHot() const { return xh; }
    112     uint yHot() const { return yh; }
    113     uint width() const { return w; }
    114     uint height() const { return h; }
    115     const uchar *shapeData() const { return data; }
    116 
    117 private:
    118 
    119     bool vis, alph;
    120     uint xh, yh, w, h;
    121     const uchar *data;
    122 };
    123 
    124 /** Guest mouse absolute positioning capability change event. */
    125 class MouseCapabilityEvent : public QEvent
    126 {
    127 public:
    128 
    129     MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor)
    130         : QEvent((QEvent::Type) VBoxDefs::MouseCapabilityEventType)
    131         , can_abs(supportsAbsolute), needs_host_cursor(needsHostCursor) {}
    132 
    133     bool supportsAbsolute() const { return can_abs; }
    134     bool needsHostCursor() const { return needs_host_cursor; }
    135 
    136 private:
    137 
    138     bool can_abs;
    139     bool needs_host_cursor;
    140 };
    141 
    142 /** Machine state change. */
    143 class StateChangeEvent : public QEvent
    144 {
    145 public:
    146 
    147     StateChangeEvent (KMachineState state)
    148         : QEvent((QEvent::Type)VBoxDefs::MachineStateChangeEventType)
    149         , s (state) {}
    150 
    151     KMachineState machineState() const { return s; }
    152 
    153 private:
    154 
    155     KMachineState s;
    156 };
    157 
    158 /** Guest Additions property changes. */
    159 class GuestAdditionsEvent : public QEvent
    160 {
    161 public:
    162 
    163     GuestAdditionsEvent (const QString &aOsTypeId,
    164                          const QString &aAddVersion,
    165                          bool aAddActive,
    166                          bool aSupportsSeamless,
    167                          bool aSupportsGraphics)
    168         : QEvent((QEvent::Type)VBoxDefs::AdditionsStateChangeEventType)
    169         , mOsTypeId(aOsTypeId), mAddVersion(aAddVersion)
    170         , mAddActive(aAddActive), mSupportsSeamless(aSupportsSeamless)
    171         , mSupportsGraphics (aSupportsGraphics) {}
    172 
    173     const QString &osTypeId() const { return mOsTypeId; }
    174     const QString &additionVersion() const { return mAddVersion; }
    175     bool additionActive() const { return mAddActive; }
    176     bool supportsSeamless() const { return mSupportsSeamless; }
    177     bool supportsGraphics() const { return mSupportsGraphics; }
    178 
    179 private:
    180 
    181     QString mOsTypeId;
    182     QString mAddVersion;
    183     bool mAddActive;
    184     bool mSupportsSeamless;
    185     bool mSupportsGraphics;
    186 };
    187 
    188 /** DVD/Floppy drive change event */
    189 class MediaDriveChangeEvent : public QEvent
    190 {
    191 public:
    192 
    193     MediaDriveChangeEvent(VBoxDefs::MediumType aType)
    194         : QEvent ((QEvent::Type) VBoxDefs::MediaDriveChangeEventType)
    195         , mType (aType) {}
    196     VBoxDefs::MediumType type() const { return mType; }
    197 
    198 private:
    199 
    200     VBoxDefs::MediumType mType;
    201 };
    202 
    20387/** Menu activation event */
    20488class ActivateMenuEvent : public QEvent
     
    216100};
    217101
    218 /** VM Runtime error event */
    219 class RuntimeErrorEvent : public QEvent
    220 {
    221 public:
    222 
    223     RuntimeErrorEvent(bool aFatal, const QString &aErrorID, const QString &aMessage)
    224         : QEvent((QEvent::Type)VBoxDefs::RuntimeErrorEventType)
    225         , mFatal(aFatal), mErrorID(aErrorID), mMessage(aMessage) {}
    226 
    227     bool fatal() const { return mFatal; }
    228     QString errorID() const { return mErrorID; }
    229     QString message() const { return mMessage; }
    230 
    231 private:
    232 
    233     bool mFatal;
    234     QString mErrorID;
    235     QString mMessage;
    236 };
    237 
    238 /** Modifier key change event */
    239 class ModifierKeyChangeEvent : public QEvent
    240 {
    241 public:
    242 
    243     ModifierKeyChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
    244         : QEvent((QEvent::Type)VBoxDefs::ModifierKeyChangeEventType)
    245         , mNumLock(fNumLock), mCapsLock(fCapsLock), mScrollLock(fScrollLock) {}
    246 
    247     bool numLock()    const { return mNumLock; }
    248     bool capsLock()   const { return mCapsLock; }
    249     bool scrollLock() const { return mScrollLock; }
    250 
    251 private:
    252 
    253     bool mNumLock, mCapsLock, mScrollLock;
    254 };
    255 
    256 /** Network adapter change event */
    257 class NetworkAdapterChangeEvent : public QEvent
    258 {
    259 public:
    260 
    261     NetworkAdapterChangeEvent(INetworkAdapter *aAdapter)
    262         : QEvent((QEvent::Type)VBoxDefs::NetworkAdapterChangeEventType)
    263         , mAdapter(aAdapter) {}
    264 
    265     INetworkAdapter* networkAdapter() { return mAdapter; }
    266 
    267 private:
    268 
    269     INetworkAdapter *mAdapter;
    270 };
    271 
    272 /** USB controller state change event */
    273 class USBControllerStateChangeEvent : public QEvent
    274 {
    275 public:
    276 
    277     USBControllerStateChangeEvent()
    278         : QEvent((QEvent::Type)VBoxDefs::USBCtlStateChangeEventType) {}
    279 };
    280 
    281 /** USB device state change event */
    282 class USBDeviceStateChangeEvent : public QEvent
    283 {
    284 public:
    285 
    286     USBDeviceStateChangeEvent(const CUSBDevice &aDevice, bool aAttached, const CVirtualBoxErrorInfo &aError)
    287         : QEvent((QEvent::Type)VBoxDefs::USBDeviceStateChangeEventType)
    288         , mDevice(aDevice), mAttached(aAttached), mError(aError) {}
    289 
    290     CUSBDevice device() const { return mDevice; }
    291     bool attached() const { return mAttached; }
    292     CVirtualBoxErrorInfo error() const { return mError; }
    293 
    294 private:
    295 
    296     CUSBDevice mDevice;
    297     bool mAttached;
    298     CVirtualBoxErrorInfo mError;
    299 };
    300 
    301102class VBoxViewport: public QWidget
    302103{
     
    317118    }
    318119};
    319 
    320 class UIConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
    321 {
    322 public:
    323 
    324     UIConsoleCallback (UIMachineView *v)
    325     {
    326 #if defined (Q_WS_WIN)
    327         mRefCnt = 0;
    328 #endif
    329         mView = v;
    330     }
    331 
    332     virtual ~UIConsoleCallback() {}
    333 
    334     NS_DECL_ISUPPORTS
    335 
    336 #if defined (Q_WS_WIN)
    337     STDMETHOD_(ULONG, AddRef)()
    338     {
    339         return ::InterlockedIncrement(&mRefCnt);
    340     }
    341     STDMETHOD_(ULONG, Release)()
    342     {
    343         long cnt = ::InterlockedDecrement(&mRefCnt);
    344         if (cnt == 0)
    345             delete this;
    346         return cnt;
    347     }
    348 #endif
    349     VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
    350 
    351     STDMETHOD(OnMousePointerShapeChange) (BOOL visible, BOOL alpha,
    352                                           ULONG xhot, ULONG yhot,
    353                                           ULONG width, ULONG height,
    354                                           BYTE *shape)
    355     {
    356         QApplication::postEvent(mView, new MousePointerChangeEvent(visible, alpha, xhot, yhot, width, height, shape));
    357         return S_OK;
    358     }
    359 
    360     STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
    361     {
    362         QApplication::postEvent(mView, new MouseCapabilityEvent (supportsAbsolute, needsHostCursor));
    363         return S_OK;
    364     }
    365 
    366     STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
    367     {
    368         QApplication::postEvent(mView, new ModifierKeyChangeEvent (fNumLock, fCapsLock, fScrollLock));
    369         return S_OK;
    370     }
    371 
    372     STDMETHOD(OnStateChange)(MachineState_T machineState)
    373     {
    374         QApplication::postEvent(mView, new StateChangeEvent ((KMachineState) machineState));
    375         return S_OK;
    376     }
    377 
    378     STDMETHOD(OnAdditionsStateChange)()
    379     {
    380         CGuest guest = mView->console().GetGuest();
    381         QApplication::postEvent (mView, new GuestAdditionsEvent(guest.GetOSTypeId(), guest.GetAdditionsVersion(),
    382                                                                 guest.GetAdditionsActive(), guest.GetSupportsSeamless(),
    383                                                                 guest.GetSupportsGraphics()));
    384         return S_OK;
    385     }
    386 
    387     STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
    388     {
    389         QApplication::postEvent (mView, new NetworkAdapterChangeEvent (aNetworkAdapter));
    390         return S_OK;
    391     }
    392 
    393     STDMETHOD(OnStorageControllerChange) ()
    394     {
    395         //QApplication::postEvent(mView, new StorageControllerChangeEvent());
    396         return S_OK;
    397     }
    398 
    399     STDMETHOD(OnMediumChange)(IMediumAttachment *aMediumAttachment)
    400     {
    401         CMediumAttachment att(aMediumAttachment);
    402         switch (att.GetType())
    403         {
    404             case KDeviceType_Floppy:
    405                 QApplication::postEvent(mView, new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy));
    406                 break;
    407             case KDeviceType_DVD:
    408                 QApplication::postEvent(mView, new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD));
    409                 break;
    410             default:
    411                 break;
    412         }
    413         return S_OK;
    414     }
    415 
    416     STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove)
    417     {
    418         NOREF(aCPU);
    419         NOREF(aRemove);
    420         return S_OK;
    421     }
    422 
    423     STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
    424     {
    425         NOREF(aSerialPort);
    426         return S_OK;
    427     }
    428 
    429     STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
    430     {
    431         NOREF(aParallelPort);
    432         return S_OK;
    433     }
    434 
    435     STDMETHOD(OnVRDPServerChange)()
    436     {
    437         return S_OK;
    438     }
    439 
    440     STDMETHOD(OnRemoteDisplayInfoChange)()
    441     {
    442         return S_OK;
    443     }
    444 
    445     STDMETHOD(OnUSBControllerChange)()
    446     {
    447         QApplication::postEvent (mView, new USBControllerStateChangeEvent());
    448         return S_OK;
    449     }
    450 
    451     STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached, IVirtualBoxErrorInfo *aError)
    452     {
    453         QApplication::postEvent (mView, new USBDeviceStateChangeEvent(CUSBDevice(aDevice), bool(aAttached), CVirtualBoxErrorInfo(aError)));
    454         return S_OK;
    455     }
    456 
    457     STDMETHOD(OnSharedFolderChange) (Scope_T aScope)
    458     {
    459         NOREF(aScope);
    460         QApplication::postEvent (mView, new QEvent((QEvent::Type)VBoxDefs::SharedFolderChangeEventType));
    461         return S_OK;
    462     }
    463 
    464     STDMETHOD(OnRuntimeError)(BOOL fatal, IN_BSTR id, IN_BSTR message)
    465     {
    466         QApplication::postEvent (mView, new RuntimeErrorEvent(!!fatal, QString::fromUtf16(id), QString::fromUtf16(message)));
    467         return S_OK;
    468     }
    469 
    470     STDMETHOD(OnCanShowWindow) (BOOL *canShow)
    471     {
    472         if (!canShow)
    473             return E_POINTER;
    474 
    475         *canShow = TRUE;
    476         return S_OK;
    477     }
    478 
    479     STDMETHOD(OnShowWindow) (ULONG64 *winId)
    480     {
    481         if (!winId)
    482             return E_POINTER;
    483 
    484 #if defined (Q_WS_MAC)
    485         /*
    486          * Let's try the simple approach first - grab the focus.
    487          * Getting a window out of the dock (minimized or whatever it's called)
    488          * needs to be done on the GUI thread, so post it a note.
    489          */
    490         *winId = 0;
    491         if (!mView)
    492             return S_OK;
    493 
    494         ProcessSerialNumber psn = { 0, kCurrentProcess };
    495         OSErr rc = ::SetFrontProcess (&psn);
    496         if (!rc)
    497             QApplication::postEvent(mView, new QEvent((QEvent::Type)VBoxDefs::ShowWindowEventType));
    498         else
    499         {
    500             /*
    501              * It failed for some reason, send the other process our PSN so it can try.
    502              * (This is just a precaution should Mac OS X start imposing the same sensible
    503              * focus stealing restrictions that other window managers implement.)
    504              */
    505             AssertMsgFailed(("SetFrontProcess -> %#x\n", rc));
    506             if (::GetCurrentProcess (&psn))
    507                 *winId = RT_MAKE_U64(psn.lowLongOfPSN, psn.highLongOfPSN);
    508         }
    509 
    510 #else
    511         /* Return the ID of the top-level console window. */
    512         *winId = (ULONG64)mView->window()->winId();
    513 #endif
    514 
    515         return S_OK;
    516     }
    517 
    518 protected:
    519 
    520     UIMachineView *mView;
    521 
    522 #if defined (Q_WS_WIN)
    523 private:
    524     long mRefCnt;
    525 #endif
    526 };
    527 
    528 #if !defined (Q_WS_WIN)
    529 NS_DECL_CLASSINFO(UIConsoleCallback)
    530 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIConsoleCallback, IConsoleCallback)
    531 #endif
    532120
    533121UIMachineView* UIMachineView::create(  UIMachineWindow *pMachineWindow
     
    659247    /* Private members: */
    660248    , m_pMachineWindow(pMachineWindow)
    661     , m_console(pMachineWindow->machineLogic()->session().GetConsole())
     249    , m_console(pMachineWindow->machineLogic()->uisession()->session().GetConsole())
    662250    , m_globalSettings(vboxGlobal().settings())
    663251    , m_iLastMouseWheelDelta(0)
     
    861449    }
    862450
    863     /* setup the callback */
    864     mCallback = CConsoleCallback(new UIConsoleCallback(this));
    865     m_console.RegisterCallback(mCallback);
    866     AssertWrapperOk(m_console);
    867 
    868451    QPalette palette(viewport()->palette());
    869452    palette.setColor(viewport()->backgroundRole(), Qt::black);
     
    942525        mFrameBuf = NULL;
    943526    }
    944 
    945     m_console.UnregisterCallback(mCallback);
    946527
    947528#if defined (Q_WS_MAC)
     
    1224805            #endif
    1225806
    1226             case VBoxDefs::MousePointerChangeEventType:
    1227             {
    1228                 MousePointerChangeEvent *me = (MousePointerChangeEvent *) e;
    1229                 /* change cursor shape only when mouse integration is
    1230                  * supported (change mouse shape type event may arrive after
    1231                  * mouse capability change that disables integration */
    1232                 if (m_bIsMouseAbsolute)
    1233                     setPointerShape (me);
    1234                 else
    1235                     /* Note: actually we should still remember the requested
    1236                      * cursor shape.  If we can't do that, at least remember
    1237                      * the requested visiblilty. */
    1238                     mHideHostPointer = !me->isVisible();
    1239                 return true;
    1240             }
    1241             case VBoxDefs::MouseCapabilityEventType:
    1242             {
    1243                 MouseCapabilityEvent *me = (MouseCapabilityEvent *) e;
    1244                 if (m_bIsMouseAbsolute != me->supportsAbsolute())
    1245                 {
    1246                     m_bIsMouseAbsolute = me->supportsAbsolute();
    1247                     /* correct the mouse capture state and reset the cursor
    1248                      * to the default shape if necessary */
    1249                     if (m_bIsMouseAbsolute)
    1250                     {
    1251                         CMouse mouse = m_console.GetMouse();
    1252                         mouse.PutMouseEventAbsolute (-1, -1, 0,
    1253                                                      0 /* Horizontal wheel */,
    1254                                                      0);
    1255                         captureMouse (false, false);
    1256                     }
    1257                     else
    1258                         viewport()->unsetCursor();
    1259                     emitMouseStateChanged();
    1260                     vboxProblem().remindAboutMouseIntegration (m_bIsMouseAbsolute);
    1261                 }
    1262                 if (me->needsHostCursor())
    1263                     setMouseIntegrationLocked (false);
    1264                 else
    1265                     setMouseIntegrationLocked (true);
    1266                 return true;
    1267             }
    1268 
    1269             case VBoxDefs::ModifierKeyChangeEventType:
    1270             {
    1271                 ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )e;
    1272                 if (me->numLock() != mNumLock)
    1273                     muNumLockAdaptionCnt = 2;
    1274                 if (me->capsLock() != mCapsLock)
    1275                     muCapsLockAdaptionCnt = 2;
    1276                 mNumLock    = me->numLock();
    1277                 mCapsLock   = me->capsLock();
    1278                 mScrollLock = me->scrollLock();
    1279                 return true;
    1280             }
    1281 
    1282             case VBoxDefs::MachineStateChangeEventType:
    1283             {
    1284                 StateChangeEvent *me = (StateChangeEvent *) e;
    1285                 LogFlowFunc (("MachineStateChangeEventType: state=%d\n",
    1286                                me->machineState()));
    1287                 onStateChange (me->machineState());
    1288                 emit machineStateChanged (me->machineState());
    1289                 return true;
    1290             }
    1291 
    1292             case VBoxDefs::AdditionsStateChangeEventType:
    1293             {
    1294                 GuestAdditionsEvent *ge = (GuestAdditionsEvent *) e;
    1295                 LogFlowFunc (("AdditionsStateChangeEventType\n"));
    1296 
    1297                 /* Always send a size hint if we are in fullscreen or seamless
    1298                  * when the graphics capability is enabled, in case the host
    1299                  * resolution has changed since the VM was last run. */
    1300 #if 0
    1301                 if (!mDoResize && !m_bIsGuestSupportsGraphics &&
    1302                     ge->supportsGraphics() &&
    1303                     (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))
    1304                     mDoResize = true;
    1305 #endif
    1306 
    1307                 m_bIsGuestSupportsGraphics = ge->supportsGraphics();
    1308 
    1309                 maybeRestrictMinimumSize();
    1310 
    1311 #if 0
    1312                 /* This will only be acted upon if mDoResize is true. */
    1313                 doResizeHint();
    1314 #endif
    1315 
    1316                 emit additionsStateChanged (ge->additionVersion(),
    1317                                             ge->additionActive(),
    1318                                             ge->supportsSeamless(),
    1319                                             ge->supportsGraphics());
    1320                 return true;
    1321             }
    1322 
    1323             case VBoxDefs::MediaDriveChangeEventType:
    1324             {
    1325                 MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) e;
    1326                 LogFlowFunc (("MediaChangeEvent\n"));
    1327 
    1328                 emit mediaDriveChanged (mce->type());
    1329                 return true;
    1330             }
    1331 
    1332807            #if 0
    1333808            case VBoxDefs::ActivateMenuEventType:
     
    1350825            }
    1351826            #endif
    1352 
    1353             case VBoxDefs::NetworkAdapterChangeEventType:
    1354             {
    1355                 /* no specific adapter information stored in this
    1356                  * event is currently used */
    1357                 emit networkStateChange();
    1358                 return true;
    1359             }
    1360 
    1361             case VBoxDefs::USBCtlStateChangeEventType:
    1362             {
    1363                 emit usbStateChange();
    1364                 return true;
    1365             }
    1366 
    1367             case VBoxDefs::USBDeviceStateChangeEventType:
    1368             {
    1369                 USBDeviceStateChangeEvent *ue = (USBDeviceStateChangeEvent *)e;
    1370 
    1371                 bool success = ue->error().isNull();
    1372 
    1373                 if (!success)
    1374                 {
    1375                     if (ue->attached())
    1376                         vboxProblem().cannotAttachUSBDevice (
    1377                             m_console,
    1378                             vboxGlobal().details (ue->device()), ue->error());
    1379                     else
    1380                         vboxProblem().cannotDetachUSBDevice (
    1381                             m_console,
    1382                             vboxGlobal().details (ue->device()), ue->error());
    1383                 }
    1384 
    1385                 emit usbStateChange();
    1386 
    1387                 return true;
    1388             }
    1389 
    1390             case VBoxDefs::SharedFolderChangeEventType:
    1391             {
    1392                 emit sharedFoldersChanged();
    1393                 return true;
    1394             }
    1395 
    1396             case VBoxDefs::RuntimeErrorEventType:
    1397             {
    1398                 RuntimeErrorEvent *ee = (RuntimeErrorEvent *) e;
    1399                 vboxProblem().showRuntimeError (m_console, ee->fatal(),
    1400                                                 ee->errorID(), ee->message());
    1401                 return true;
    1402             }
    1403827
    1404828            case QEvent::KeyPress:
     
    34742898}
    34752899
     2900#if 0
    34762901void UIMachineView::setPointerShape(MousePointerChangeEvent *pEvent)
    34772902{
     
    37303155    mHideHostPointer = !pEvent->isVisible();
    37313156}
     3157#endif
    37323158
    37333159inline QRgb qRgbIntensity(QRgb rgb, int mul, int div)
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r26637 r26691  
    2828class UIMachineWindow;
    2929class VBoxGlobalSettings;
    30 class MousePointerChangeEvent;
    3130
    3231/* Global includes */
     
    200199    void sendChangedKeyStates();
    201200    void updateMouseClipping();
    202     void setPointerShape(MousePointerChangeEvent *pEvent);
     201    //void setPointerShape(MousePointerChangeEvent *pEvent);
    203202
    204203    enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
     
    264263
    265264    UIFrameBuffer *mFrameBuf;
    266     CConsoleCallback mCallback;
    267265
    268266    QPixmap mPausedShot;
     
    280278    bool mHideHostPointer;
    281279    QCursor mLastCursor;
    282 
    283     friend class UIConsoleCallback;
    284280};
    285281
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp

    r26656 r26691  
    2323/* Global includes */
    2424#include <QCloseEvent>
     25#include <QTimer>
    2526
    2627/* Local includes */
     
    2930#include "VBoxCloseVMDlg.h"
    3031
     32#include "UISession.h"
    3133#include "UIMachineLogic.h"
    3234#include "UIMachineWindow.h"
     
    6163}
    6264
     65void UIMachineWindow::sltTryClose()
     66{
     67    /* First close any open modal & popup widgets.
     68     * Use a single shot with timeout 0 to allow the widgets to cleany close and test then again.
     69     * If all open widgets are closed destroy ourself: */
     70    QWidget *widget = QApplication::activeModalWidget() ?
     71                      QApplication::activeModalWidget() :
     72                      QApplication::activePopupWidget() ?
     73                      QApplication::activePopupWidget() : 0;
     74    if (widget)
     75    {
     76        widget->close();
     77        QTimer::singleShot(0, machineWindow(), SLOT(sltTryClose()));
     78    }
     79    else
     80        machineWindow()->close();
     81}
     82
    6383UIMachineWindow::UIMachineWindow(UIMachineLogic *pMachineLogic)
    6484    : m_pMachineLogic(pMachineLogic)
     
    89109void UIMachineWindow::updateAppearanceOf(int iElement)
    90110{
    91     CMachine machine = machineLogic()->session().GetMachine();
     111    CMachine machine = session().GetMachine();
    92112
    93113    if (iElement & UIVisualElement_WindowCaption)
     
    119139#ifndef Q_WS_MAC
    120140    /* Set the VM-specific application icon except Mac OS X: */
    121     CMachine machine = machineLogic()->session().GetMachine();
    122     machineWindow()->setWindowIcon(vboxGlobal().vmGuestOSTypeIcon(machine.GetOSTypeId()));
    123 #endif
     141    machineWindow()->setWindowIcon(vboxGlobal().vmGuestOSTypeIcon(session().GetMachine().GetOSTypeId()));
     142#endif
     143}
     144
     145void UIMachineWindow::prepareConsoleConnections()
     146{
     147    QObject::connect(machineLogic()->uisession(), SIGNAL(sigStateChange(KMachineState)),
     148                     machineWindow(), SLOT(sltMachineStateChanged(KMachineState)));
    124149}
    125150
     
    130155    /* Default to true if it is an empty value */
    131156    bool bIsDockIconEnabled = testStr.isEmpty() || testStr == "true";
    132     machineView()->setDockIconEnabled(bIsDockIconEnabled);
    133     machineView()->updateDockOverlay();
     157    if (machineView())
     158    {
     159        machineView()->setDockIconEnabled(bIsDockIconEnabled);
     160        machineView()->updateDockOverlay();
     161    }
    134162#endif
    135163}
     
    142170    static const char *pstrDiscardCurState = "discardCurState";
    143171
    144     if (!machineView())
     172    if (!machineWindow())
    145173    {
    146174        pEvent->accept();
     
    174202            pEvent->ignore();
    175203
    176             bool isACPIEnabled = machineLogic()->session().GetConsole().GetGuestEnteredACPIMode();
     204            bool isACPIEnabled = session().GetConsole().GetGuestEnteredACPIMode();
    177205
    178206            bool success = true;
     
    185213                /* Suspend the VM and ignore the close event if failed to do so.
    186214                 * pause() will show the error message to the user. */
    187                 success = machineLogic()->pause(true);
     215                success = machineLogic()->pause();
    188216            }
    189217
     
    192220                success = false;
    193221
    194                 CMachine machine = machineLogic()->session().GetMachine();
     222                CMachine machine = session().GetMachine();
    195223                VBoxCloseVMDlg dlg(machineWindow());
    196224                QString typeId = machine.GetOSTypeId();
     
    243271                    //m_bNoAutoClose = true;
    244272
    245                     CConsole console = machineLogic()->session().GetConsole();
     273                    CConsole console = session().GetConsole();
    246274
    247275                    if (dlg.mRbSave->isChecked())
     
    264292                    {
    265293                        /* Unpause the VM to let it grab the ACPI shutdown event */
    266                         machineLogic()->pause(false);
     294                        machineLogic()->unpause();
    267295                        /* Prevent the subsequent unpause request */
    268296                        wasPaused = true;
     
    364392                    /* Restore the running state if needed */
    365393                    if (!wasPaused && machineLogic()->machineState() == KMachineState_Paused)
    366                         machineLogic()->pause(false);
     394                        machineLogic()->unpause();
    367395                }
    368396            }
     
    393421    }
    394422}
     423
     424CSession UIMachineWindow::session()
     425{
     426    return m_pMachineLogic->uisession()->session();
     427}
     428
     429void UIMachineWindow::sltMachineStateChanged(KMachineState /* machineState */)
     430{
     431    updateAppearanceOf(UIVisualElement_WindowCaption);
     432}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h

    r26656 r26691  
    2525
    2626/* Local includes */
     27#include "COMDefs.h"
    2728#include "UIMachineDefs.h"
    2829
    2930/* Global forwards */
    3031class QWidget;
     32class QCloseEvent;
    3133
    3234/* Local forwards */
     
    4345
    4446    /* Abstract slot to close machine window: */
    45     virtual void sltTryClose() = 0;
     47    virtual void sltTryClose();
    4648
    4749    /* Public getters: */
     
    6466    /* Prepare helpers: */
    6567    virtual void prepareWindowIcon();
     68    virtual void prepareConsoleConnections();
    6669    virtual void loadWindowSettings();
    6770
    6871    /* Cleanup helpers: */
    6972    //virtual void saveWindowSettings();
     73    //virtual void cleanupConsoleConnections();
    7074    //virtual void cleanupWindowIcon();
    7175
     
    7478
    7579    /* Protected getters: */
     80    CSession session();
    7681    const QString& defaultWindowTitle() const { return m_strWindowTitlePrefix; }
     82
     83    /* Protected signals: */
     84    void sltMachineStateChanged(KMachineState machineState);
    7785
    7886    /* Protected variables: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r26688 r26691  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * VBoxConsoleView class implementation
     4 * UISession stuff implementation
    55 */
    66
    77/*
    8  * Copyright (C) 22006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2010 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121 */
    2222
    23 #ifdef VBOX_WITH_PRECOMPILED_HEADERS
    24 # include "precomp.h"
    25 #else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
    26 #include <VBox/VBoxVideo.h>
    27 
    28 #include "VBoxConsoleView.h"
    29 #include "VBoxConsoleWnd.h"
    30 #include "VBoxUtils.h"
    31 
    32 #include "VBoxFrameBuffer.h"
    33 #include "VBoxGlobal.h"
    34 #include "VBoxProblemReporter.h"
    35 
    36 #ifdef Q_WS_PM
    37 #include "QIHotKeyEdit.h"
    38 #endif
    39 
    40 /* Qt includes */
    41 #include <QMenuBar>
    42 #include <QDesktopWidget>
    43 #include <QTimer>
    44 #include <QStatusBar>
    45 #include <QPainter>
    46 #include <QBitmap>
    47 
    48 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ /** @todo Move this further down! Requires some cleanup below though, so later. */
    49 
    50 #ifdef Q_WS_WIN
    51 // VBox/cdefs.h defines these:
    52 #undef LOWORD
    53 #undef HIWORD
    54 #undef LOBYTE
    55 #undef HIBYTE
    56 #include <windows.h>
    57 #endif
    58 
    59 #ifdef Q_WS_X11
    60 #include <QX11Info>
    61 // We need to capture some X11 events directly which
    62 // requires the XEvent structure to be defined. However,
    63 // including the Xlib header file will cause some nasty
    64 // conflicts with Qt. Therefore we use the following hack
    65 // to redefine those conflicting identifiers.
    66 #define XK_XKB_KEYS
    67 #define XK_MISCELLANY
    68 #include <X11/Xlib.h>
    69 #include <X11/Xutil.h>
    70 #include <X11/XKBlib.h>
    71 #include <X11/keysym.h>
    72 #ifdef KeyPress
    73 const int XFocusOut = FocusOut;
    74 const int XFocusIn = FocusIn;
    75 const int XKeyPress = KeyPress;
    76 const int XKeyRelease = KeyRelease;
    77 #undef KeyRelease
    78 #undef KeyPress
    79 #undef FocusOut
    80 #undef FocusIn
    81 #endif
    82 #include "XKeyboard.h"
    83 #ifndef VBOX_WITHOUT_XCURSOR
    84 # include <X11/Xcursor/Xcursor.h>
    85 #endif
    86 #endif // Q_WS_X11
     23/* Global inclues */
     24#include <QApplication>
     25#include <QWidget>
     26
     27/* Local includes */
     28#include "UISession.h"
     29
     30#include "UIMachine.h"
     31#include "UIMachineLogic.h"
     32#include "UIMachineWindow.h"
     33
     34/* Guest mouse pointer shape change event: */
     35class UIMousePointerShapeChangeEvent : public QEvent
     36{
     37public:
     38
     39    UIMousePointerShapeChangeEvent(bool bIsVisible, bool bIsAlpha, uint uXHot, uint uYHot, uint uWidth, uint uHeight, const uchar *pShape)
     40        : QEvent((QEvent::Type)UIConsoleEventType_MousePointerShapeChange)
     41        , m_bIsVisible(bIsVisible), m_bIsAlpha(bIsAlpha), m_uXHot(uXHot), m_uYHot(uYHot), m_uWidth(uWidth), m_uHeight(uHeight), m_pData(0)
     42    {
     43        uint dataSize = ((((m_uWidth + 7) / 8 * m_uHeight) + 3) & ~3) + m_uWidth * 4 * m_uHeight;
     44        if (pShape)
     45        {
     46            m_pData = new uchar[dataSize];
     47            memcpy((void*)m_pData, (void*)pShape, dataSize);
     48        }
     49    }
     50
     51    virtual ~UIMousePointerShapeChangeEvent()
     52    {
     53        if (m_pData) delete[] m_pData;
     54    }
     55
     56    bool isVisible() const { return m_bIsVisible; }
     57    bool hasAlpha() const { return m_bIsAlpha; }
     58    uint xHot() const { return m_uXHot; }
     59    uint yHot() const { return m_uYHot; }
     60    uint width() const { return m_uWidth; }
     61    uint height() const { return m_uHeight; }
     62    const uchar *shapeData() const { return m_pData; }
     63
     64private:
     65
     66    bool m_bIsVisible, m_bIsAlpha;
     67    uint m_uXHot, m_uYHot, m_uWidth, m_uHeight;
     68    const uchar *m_pData;
     69};
     70
     71/* Guest mouse absolute positioning capability change event: */
     72class UIMouseCapabilityChangeEvent : public QEvent
     73{
     74public:
     75
     76    UIMouseCapabilityChangeEvent(bool bSupportsAbsolute, bool bNeedsHostCursor)
     77        : QEvent((QEvent::Type)UIConsoleEventType_MouseCapabilityChange)
     78        , m_bSupportsAbsolute(bSupportsAbsolute), m_bNeedsHostCursor(bNeedsHostCursor) {}
     79
     80    bool supportsAbsolute() const { return m_bSupportsAbsolute; }
     81    bool needsHostCursor() const { return m_bNeedsHostCursor; }
     82
     83private:
     84
     85    bool m_bSupportsAbsolute;
     86    bool m_bNeedsHostCursor;
     87};
     88
     89/* Keyboard LEDs change event: */
     90class UIKeyboardLedsChangeEvent : public QEvent
     91{
     92public:
     93
     94    UIKeyboardLedsChangeEvent(bool bNumLock, bool bCapsLock, bool bScrollLock)
     95        : QEvent((QEvent::Type)UIConsoleEventType_KeyboardLedsChange)
     96        , m_bNumLock(bNumLock), m_bCapsLock(bCapsLock), m_bScrollLock(bScrollLock) {}
     97
     98    bool numLock() const { return m_bNumLock; }
     99    bool capsLock() const { return m_bCapsLock; }
     100    bool scrollLock() const { return m_bScrollLock; }
     101
     102private:
     103
     104    bool m_bNumLock;
     105    bool m_bCapsLock;
     106    bool m_bScrollLock;
     107};
     108
     109/* Machine state change event: */
     110class UIStateChangeEvent : public QEvent
     111{
     112public:
     113
     114    UIStateChangeEvent(KMachineState machineState)
     115        : QEvent((QEvent::Type)UIConsoleEventType_StateChange)
     116        , m_machineState(machineState) {}
     117
     118    KMachineState machineState() const { return m_machineState; }
     119
     120private:
     121
     122    KMachineState m_machineState;
     123};
     124
     125/* Guest Additions state change event: */
     126class UIAdditionsStateChangeEvent : public QEvent
     127{
     128public:
     129
     130    UIAdditionsStateChangeEvent()
     131        : QEvent((QEvent::Type)UIConsoleEventType_AdditionsStateChange) {}
     132};
     133
     134/* Network adapter change event: */
     135class UINetworkAdapterChangeEvent : public QEvent
     136{
     137public:
     138
     139    UINetworkAdapterChangeEvent(const CNetworkAdapter &networkAdapter)
     140        : QEvent((QEvent::Type)UIConsoleEventType_NetworkAdapterChange)
     141        , m_networkAdapter(networkAdapter) {}
     142
     143    const CNetworkAdapter& networkAdapter() { return m_networkAdapter; }
     144
     145private:
     146
     147    const CNetworkAdapter &m_networkAdapter;
     148};
     149
     150/* Serial port change event: */
     151class UISerialPortChangeEvent : public QEvent
     152{
     153public:
     154
     155    UISerialPortChangeEvent(const CSerialPort &serialPort)
     156        : QEvent((QEvent::Type)UIConsoleEventType_SerialPortChange)
     157        , m_serialPort(serialPort) {}
     158
     159    const CSerialPort& serialPort() { return m_serialPort; }
     160
     161private:
     162
     163    const CSerialPort &m_serialPort;
     164};
     165
     166/* Parallel port change event: */
     167class UIParallelPortChangeEvent : public QEvent
     168{
     169public:
     170
     171    UIParallelPortChangeEvent(const CParallelPort &parallelPort)
     172        : QEvent((QEvent::Type)UIConsoleEventType_ParallelPortChange)
     173        , m_parallelPort(parallelPort) {}
     174
     175    const CParallelPort& parallelPort() { return m_parallelPort; }
     176
     177private:
     178
     179    const CParallelPort &m_parallelPort;
     180};
     181
     182/* Storage controller change event: */
     183class UIStorageControllerChangeEvent : public QEvent
     184{
     185public:
     186
     187    UIStorageControllerChangeEvent()
     188        : QEvent((QEvent::Type)UIConsoleEventType_StorageControllerChange) {}
     189};
     190
     191/* Storage medium change event: */
     192class UIMediumChangeEvent : public QEvent
     193{
     194public:
     195
     196    UIMediumChangeEvent(const CMediumAttachment &mediumAttachment)
     197        : QEvent((QEvent::Type)UIConsoleEventType_MediumChange)
     198        , m_mediumAttachment(mediumAttachment) {}
     199    const CMediumAttachment& mediumAttahment() { return m_mediumAttachment; }
     200
     201private:
     202
     203    const CMediumAttachment &m_mediumAttachment;
     204};
     205
     206/* CPU change event: */
     207class UICPUChangeEvent : public QEvent
     208{
     209public:
     210
     211    UICPUChangeEvent(ulong uCPU, bool bRemove)
     212        : QEvent((QEvent::Type)UIConsoleEventType_CPUChange)
     213        , m_uCPU(uCPU), m_bRemove(bRemove) {}
     214
     215    ulong cpu() const { return m_uCPU; }
     216    bool remove() const { return m_bRemove; }
     217
     218private:
     219
     220    ulong m_uCPU;
     221    bool m_bRemove;
     222};
     223
     224/* VRDP server change event: */
     225class UIVRDPServerChangeEvent : public QEvent
     226{
     227public:
     228
     229    UIVRDPServerChangeEvent()
     230        : QEvent((QEvent::Type)UIConsoleEventType_VRDPServerChange) {}
     231};
     232
     233/* Remote display info change event: */
     234class UIRemoteDisplayInfoChangeEvent : public QEvent
     235{
     236public:
     237
     238    UIRemoteDisplayInfoChangeEvent()
     239        : QEvent((QEvent::Type)UIConsoleEventType_RemoteDisplayInfoChange) {}
     240};
     241
     242/* USB controller change event: */
     243class UIUSBControllerChangeEvent : public QEvent
     244{
     245public:
     246
     247    UIUSBControllerChangeEvent()
     248        : QEvent((QEvent::Type)UIConsoleEventType_USBControllerChange) {}
     249};
     250
     251/* USB device state change event: */
     252class UIUSBDeviceUIStateChangeEvent : public QEvent
     253{
     254public:
     255
     256    UIUSBDeviceUIStateChangeEvent(const CUSBDevice &device, bool bAttached, const CVirtualBoxErrorInfo &error)
     257        : QEvent((QEvent::Type)UIConsoleEventType_USBDeviceStateChange)
     258        , m_device(device), m_bAttached(bAttached), m_error(error) {}
     259
     260    const CUSBDevice& device() const { return m_device; }
     261    bool attached() const { return m_bAttached; }
     262    const CVirtualBoxErrorInfo& error() const { return m_error; }
     263
     264private:
     265
     266    const CUSBDevice &m_device;
     267    bool m_bAttached;
     268    const CVirtualBoxErrorInfo &m_error;
     269};
     270
     271/* Shared folder change event: */
     272class UISharedFolderChangeEvent : public QEvent
     273{
     274public:
     275
     276    UISharedFolderChangeEvent()
     277        : QEvent((QEvent::Type)UIConsoleEventType_SharedFolderChange) {}
     278};
     279
     280/* VM Runtime error event: */
     281class UIRuntimeErrorEvent : public QEvent
     282{
     283public:
     284
     285    UIRuntimeErrorEvent(bool bFatal, const QString &strErrorID, const QString &strMessage)
     286        : QEvent((QEvent::Type)UIConsoleEventType_RuntimeError)
     287        , m_bFatal(bFatal), m_strErrorID(strErrorID), m_strMessage(strMessage) {}
     288
     289    bool fatal() const { return m_bFatal; }
     290    QString errorID() const { return m_strErrorID; }
     291    QString message() const { return m_strMessage; }
     292
     293private:
     294
     295    bool m_bFatal;
     296    QString m_strErrorID;
     297    QString m_strMessage;
     298};
     299
     300/* Can show window event: */
     301class UICanUIShowWindowEvent : public QEvent
     302{
     303public:
     304
     305    UICanUIShowWindowEvent()
     306        : QEvent((QEvent::Type)UIConsoleEventType_CanShowWindow) {}
     307};
     308
     309/* Show window event: */
     310class UIShowWindowEvent : public QEvent
     311{
     312public:
     313
     314    UIShowWindowEvent()
     315        : QEvent((QEvent::Type)UIConsoleEventType_ShowWindow) {}
     316};
     317
     318class UIConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
     319{
     320public:
     321
     322    UIConsoleCallback(UISession *pEventHandler)
     323        : m_pEventHandler(pEventHandler)
     324#if defined (Q_WS_WIN)
     325        , m_iRefCount(0)
     326#endif
     327    {
     328    }
     329
     330    virtual ~UIConsoleCallback()
     331    {
     332    }
     333
     334    NS_DECL_ISUPPORTS
     335
     336#if defined (Q_WS_WIN)
     337    STDMETHOD_(ULONG, AddRef)()
     338    {
     339        return ::InterlockedIncrement(&m_iRefCount);
     340    }
     341    STDMETHOD_(ULONG, Release)()
     342    {
     343        long iCount = ::InterlockedDecrement(&m_iRefCount);
     344        if (iCount == 0)
     345            delete this;
     346        return iCount;
     347    }
     348#endif
     349
     350    VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
     351
     352    STDMETHOD(OnMousePointerShapeChange)(BOOL bIsVisible, BOOL bAlpha, ULONG uXHot, ULONG uYHot, ULONG uWidth, ULONG uHeight, BYTE *pShape)
     353    {
     354        QApplication::postEvent(m_pEventHandler, new UIMousePointerShapeChangeEvent(bIsVisible, bAlpha, uXHot, uYHot, uWidth, uHeight, pShape));
     355        return S_OK;
     356    }
     357
     358    STDMETHOD(OnMouseCapabilityChange)(BOOL bSupportsAbsolute, BOOL bNeedHostCursor)
     359    {
     360        QApplication::postEvent(m_pEventHandler, new UIMouseCapabilityChangeEvent(bSupportsAbsolute, bNeedHostCursor));
     361        return S_OK;
     362    }
     363
     364    STDMETHOD(OnKeyboardLedsChange)(BOOL bNumLock, BOOL bCapsLock, BOOL bScrollLock)
     365    {
     366        QApplication::postEvent(m_pEventHandler, new UIKeyboardLedsChangeEvent(bNumLock, bCapsLock, bScrollLock));
     367        return S_OK;
     368    }
     369
     370    STDMETHOD(OnStateChange)(MachineState_T machineState)
     371    {
     372        QApplication::postEvent(m_pEventHandler, new UIStateChangeEvent((KMachineState)machineState));
     373        return S_OK;
     374    }
     375
     376    STDMETHOD(OnAdditionsStateChange)()
     377    {
     378        QApplication::postEvent(m_pEventHandler, new UIAdditionsStateChangeEvent);
     379        return S_OK;
     380    }
     381
     382    STDMETHOD(OnNetworkAdapterChange)(INetworkAdapter *pNetworkAdapter)
     383    {
     384        QApplication::postEvent(m_pEventHandler, new UINetworkAdapterChangeEvent(CNetworkAdapter(pNetworkAdapter)));
     385        return S_OK;
     386    }
     387
     388    STDMETHOD(OnSerialPortChange)(ISerialPort *pSerialPort)
     389    {
     390        QApplication::postEvent(m_pEventHandler, new UISerialPortChangeEvent(CSerialPort(pSerialPort)));
     391        return S_OK;
     392    }
     393
     394    STDMETHOD(OnParallelPortChange)(IParallelPort *pParallelPort)
     395    {
     396        QApplication::postEvent(m_pEventHandler, new UIParallelPortChangeEvent(CParallelPort(pParallelPort)));
     397        return S_OK;
     398    }
     399
     400    STDMETHOD(OnStorageControllerChange)()
     401    {
     402        QApplication::postEvent(m_pEventHandler, new UIStorageControllerChangeEvent);
     403        return S_OK;
     404    }
     405
     406    STDMETHOD(OnMediumChange)(IMediumAttachment *pMediumAttachment)
     407    {
     408        QApplication::postEvent(m_pEventHandler, new UIMediumChangeEvent(CMediumAttachment(pMediumAttachment)));
     409        return S_OK;
     410    }
     411
     412    STDMETHOD(OnCPUChange)(ULONG uCPU, BOOL bRemove)
     413    {
     414        QApplication::postEvent(m_pEventHandler, new UICPUChangeEvent(uCPU, bRemove));
     415        return S_OK;
     416    }
     417
     418    STDMETHOD(OnVRDPServerChange)()
     419    {
     420        QApplication::postEvent(m_pEventHandler, new UIVRDPServerChangeEvent);
     421        return S_OK;
     422    }
     423
     424    STDMETHOD(OnRemoteDisplayInfoChange)()
     425    {
     426        QApplication::postEvent(m_pEventHandler, new UIRemoteDisplayInfoChangeEvent);
     427        return S_OK;
     428    }
     429
     430    STDMETHOD(OnUSBControllerChange)()
     431    {
     432        QApplication::postEvent(m_pEventHandler, new UIUSBControllerChangeEvent);
     433        return S_OK;
     434    }
     435
     436    STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *pDevice, BOOL bAttached, IVirtualBoxErrorInfo *pError)
     437    {
     438        QApplication::postEvent(m_pEventHandler, new UIUSBDeviceUIStateChangeEvent(CUSBDevice(pDevice), bAttached, CVirtualBoxErrorInfo(pError)));
     439        return S_OK;
     440    }
     441
     442    STDMETHOD(OnSharedFolderChange)(Scope_T scope)
     443    {
     444        NOREF(scope);
     445        QApplication::postEvent(m_pEventHandler, new UISharedFolderChangeEvent);
     446        return S_OK;
     447    }
     448
     449    STDMETHOD(OnRuntimeError)(BOOL bFatal, IN_BSTR strId, IN_BSTR strMessage)
     450    {
     451        QApplication::postEvent(m_pEventHandler, new UIRuntimeErrorEvent(bFatal, QString::fromUtf16(strId), QString::fromUtf16(strMessage)));
     452        return S_OK;
     453    }
     454
     455    STDMETHOD(OnCanShowWindow)(BOOL *pbCanShow)
     456    {
     457        if (!pbCanShow)
     458            return E_POINTER;
     459
     460        *pbCanShow = TRUE;
     461        return S_OK;
     462    }
     463
     464    STDMETHOD(OnShowWindow)(ULONG64 *puWinId)
     465    {
     466        if (!puWinId)
     467            return E_POINTER;
    87468
    88469#if defined (Q_WS_MAC)
    89 # include "DockIconPreview.h"
    90 # include "DarwinKeyboard.h"
    91 # ifdef QT_MAC_USE_COCOA
    92 #  include "darwin/VBoxCocoaApplication.h"
    93 # elif defined(VBOX_WITH_HACKED_QT)
    94 #  include "QIApplication.h"
    95 # endif
    96 # include <Carbon/Carbon.h>
    97 # include <VBox/err.h>
    98 #endif /* defined (Q_WS_MAC) */
    99 
    100 #if defined (Q_WS_WIN32)
    101 
    102 static HHOOK gKbdHook = NULL;
    103 static VBoxConsoleView *gView = 0;
    104 
    105 LRESULT CALLBACK VBoxConsoleView::lowLevelKeyboardProc (int nCode,
    106                                                         WPARAM wParam, LPARAM lParam)
    107 {
    108     Assert (gView);
    109     if (gView && nCode == HC_ACTION &&
    110             gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam))
    111         return 1;
    112 
    113     return CallNextHookEx (NULL, nCode, wParam, lParam);
    114 }
    115 
    116 #endif
    117 
    118 #if defined (Q_WS_MAC)
    119 # if defined (QT_MAC_USE_COCOA)
    120 /**
    121  * Event handler callback for Mac OS X, Cocoa variant.
    122  *
    123  * (Registered with and called from VBoxCocoaApplication.)
    124  *
    125  * @returns true if the event should be dropped, false if it should be passed
    126  *          along.
    127  * @param   pvCocoaEvent    The Cocoa event object.
    128  * @param   pvCarbonEvent   The Carbon event object reference.
    129  * @param   pvUser          The user argument.
    130  */
    131 /* static */
    132 bool VBoxConsoleView::darwinEventHandlerProc (const void *pvCocoaEvent,
    133                                               const void *pvCarbonEvent,
    134                                               void *pvUser)
    135 {
    136     VBoxConsoleView    *view       = (VBoxConsoleView *)pvUser;
    137     EventRef            inEvent    = (EventRef)pvCarbonEvent;
    138     UInt32              eventClass = ::GetEventClass (inEvent);
    139 
    140 #if 0
    141     /* For debugging events. */
    142     if (eventClass != 'cute')
    143         ::VBoxCocoaApplication_printEvent ("view: ", pvCocoaEvent);
    144 #endif
    145     /* Check if this is an application key combo. In that case we will not pass
    146        the event to the guest, but let the host process it. */
    147     if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent))
    148         return false;
    149 
    150     /*
    151      * All keyboard class events needs to be handled.
    152      */
    153     if (eventClass == kEventClassKeyboard)
    154     {
    155         if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
    156             return true;
    157     }
    158     /* Pass the event along. */
    159     return false;
    160 }
    161 
    162 # elif !defined (VBOX_WITH_HACKED_QT)
    163 /**
    164  *  Event handler callback for Mac OS X.
    165  */
    166 /* static */
    167 pascal OSStatus VBoxConsoleView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef,
    168                                                          EventRef inEvent, void *inUserData)
    169 {
    170     VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);
    171     UInt32 eventClass = ::GetEventClass (inEvent);
    172 
    173     /* For debugging events */
    174     /*
    175     if (eventClass != 'cute')
    176         ::darwinDebugPrintEvent ("view: ", inEvent);
    177     */
    178 
    179     /* Not sure but this seems an triggered event if the spotlight searchbar is
    180      * displayed. So flag that the host key isn't pressed alone. */
    181     if (   eventClass == 'cgs '
    182         && view->mIsHostkeyPressed
    183         && ::GetEventKind (inEvent) == 0x15)
    184         view->mIsHostkeyAlone = false;
    185 
    186     if (eventClass == kEventClassKeyboard)
    187     {
    188         if (view->darwinKeyboardEvent (NULL, inEvent))
    189             return 0;
    190     }
    191     /*
    192      * Command-H and Command-Q aren't properly disabled yet, and it's still
    193      * possible to use the left command key to invoke them when the keyboard
    194      * is captured. We discard the events these if the keyboard is captured
    195      * as a half measure to prevent unexpected behaviour. However, we don't
    196      * get any key down/up events, so these combinations are dead to the guest...
    197      */
    198     else if (eventClass == kEventClassCommand)
    199     {
    200         if (view->mKbdCaptured)
    201             return 0;
    202     }
    203     return ::CallNextEventHandler (inHandlerCallRef, inEvent);
    204 }
    205 
    206 # else /* VBOX_WITH_HACKED_QT */
    207 /**
    208  *  Event handler callback for Mac OS X.
    209  */
    210 /* static */
    211 bool VBoxConsoleView::macEventFilter (EventRef inEvent, void *inUserData)
    212 {
    213     VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);
    214     UInt32 eventClass = ::GetEventClass (inEvent);
    215     UInt32 eventKind = ::GetEventKind (inEvent);
    216 
    217     /* For debugging events */
    218     /*
    219     if (!(eventClass == 'cute'))
    220         ::darwinDebugPrintEvent ("view: ", inEvent);
    221     */
    222 
    223     /* Not sure but this seems an triggered event if the spotlight searchbar is
    224      * displayed. So flag that the host key isn't pressed alone. */
    225     if (eventClass == 'cgs ' && eventKind == 0x15 &&
    226         view->mIsHostkeyPressed)
    227         view->mIsHostkeyAlone = false;
    228 
    229     if (eventClass == kEventClassKeyboard)
    230     {
    231         if (view->darwinKeyboardEvent (NULL, inEvent))
    232             return true;
    233     }
    234     return false;
    235 }
    236 # endif /* VBOX_WITH_HACKED_QT */
    237 
    238 #endif /* Q_WS_MAC */
    239 
    240 /** Guest mouse pointer shape change event. */
    241 class MousePointerChangeEvent : public QEvent
    242 {
    243 public:
    244     MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot,
    245                              uint width, uint height,
    246                              const uchar *shape) :
    247         QEvent ((QEvent::Type) VBoxDefs::MousePointerChangeEventType),
    248         vis (visible), alph (alpha), xh (xhot), yh (yhot), w (width), h (height),
    249         data (NULL)
    250     {
    251         // make a copy of shape
    252         uint dataSize = ((((width + 7) / 8 * height) + 3) & ~3) + width * 4 * height;
    253 
    254         if (shape) {
    255             data = new uchar [dataSize];
    256             memcpy ((void *) data, (void *) shape, dataSize);
    257         }
    258     }
    259     ~MousePointerChangeEvent()
    260     {
    261         if (data) delete[] data;
    262     }
    263     bool isVisible() const { return vis; }
    264     bool hasAlpha() const { return alph; }
    265     uint xHot() const { return xh; }
    266     uint yHot() const { return yh; }
    267     uint width() const { return w; }
    268     uint height() const { return h; }
    269     const uchar *shapeData() const { return data; }
    270 private:
    271     bool vis, alph;
    272     uint xh, yh, w, h;
    273     const uchar *data;
    274 };
    275 
    276 /** Guest mouse absolute positioning capability change event. */
    277 class MouseCapabilityEvent : public QEvent
    278 {
    279 public:
    280     MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor) :
    281         QEvent ((QEvent::Type) VBoxDefs::MouseCapabilityEventType),
    282         can_abs (supportsAbsolute),
    283         needs_host_cursor (needsHostCursor) {}
    284     bool supportsAbsolute() const { return can_abs; }
    285     bool needsHostCursor() const { return needs_host_cursor; }
    286 private:
    287     bool can_abs;
    288     bool needs_host_cursor;
    289 };
    290 
    291 /** Machine state change. */
    292 class StateChangeEvent : public QEvent
    293 {
    294 public:
    295     StateChangeEvent (KMachineState state) :
    296         QEvent ((QEvent::Type) VBoxDefs::MachineStateChangeEventType),
    297         s (state) {}
    298     KMachineState machineState() const { return s; }
    299 private:
    300     KMachineState s;
    301 };
    302 
    303 /** Guest Additions property changes. */
    304 class GuestAdditionsEvent : public QEvent
    305 {
    306 public:
    307     GuestAdditionsEvent (const QString &aOsTypeId,
    308                          const QString &aAddVersion,
    309                          bool aAddActive,
    310                          bool aSupportsSeamless,
    311                          bool aSupportsGraphics) :
    312         QEvent ((QEvent::Type) VBoxDefs::AdditionsStateChangeEventType),
    313         mOsTypeId (aOsTypeId), mAddVersion (aAddVersion),
    314         mAddActive (aAddActive), mSupportsSeamless (aSupportsSeamless),
    315         mSupportsGraphics (aSupportsGraphics) {}
    316     const QString &osTypeId() const { return mOsTypeId; }
    317     const QString &additionVersion() const { return mAddVersion; }
    318     bool additionActive() const { return mAddActive; }
    319     bool supportsSeamless() const { return mSupportsSeamless; }
    320     bool supportsGraphics() const { return mSupportsGraphics; }
    321 private:
    322     QString mOsTypeId;
    323     QString mAddVersion;
    324     bool mAddActive;
    325     bool mSupportsSeamless;
    326     bool mSupportsGraphics;
    327 };
    328 
    329 /** DVD/Floppy drive change event */
    330 class MediaDriveChangeEvent : public QEvent
    331 {
    332 public:
    333     MediaDriveChangeEvent (VBoxDefs::MediumType aType)
    334         : QEvent ((QEvent::Type) VBoxDefs::MediaDriveChangeEventType)
    335         , mType (aType) {}
    336     VBoxDefs::MediumType type() const { return mType; }
    337 private:
    338     VBoxDefs::MediumType mType;
    339 };
    340 
    341 /** Menu activation event */
    342 class ActivateMenuEvent : public QEvent
    343 {
    344 public:
    345     ActivateMenuEvent (QAction *aData) :
    346         QEvent ((QEvent::Type) VBoxDefs::ActivateMenuEventType),
    347         mAction (aData) {}
    348     QAction *action() const { return mAction; }
    349 private:
    350     QAction *mAction;
    351 };
    352 
    353 /** VM Runtime error event */
    354 class RuntimeErrorEvent : public QEvent
    355 {
    356 public:
    357     RuntimeErrorEvent (bool aFatal, const QString &aErrorID,
    358                        const QString &aMessage) :
    359         QEvent ((QEvent::Type) VBoxDefs::RuntimeErrorEventType),
    360         mFatal (aFatal), mErrorID (aErrorID), mMessage (aMessage) {}
    361     bool fatal() const { return mFatal; }
    362     QString errorID() const { return mErrorID; }
    363     QString message() const { return mMessage; }
    364 private:
    365     bool mFatal;
    366     QString mErrorID;
    367     QString mMessage;
    368 };
    369 
    370 /** Modifier key change event */
    371 class ModifierKeyChangeEvent : public QEvent
    372 {
    373 public:
    374     ModifierKeyChangeEvent (bool fNumLock, bool fCapsLock, bool fScrollLock) :
    375         QEvent ((QEvent::Type) VBoxDefs::ModifierKeyChangeEventType),
    376         mNumLock (fNumLock), mCapsLock (fCapsLock), mScrollLock (fScrollLock) {}
    377     bool numLock()    const { return mNumLock; }
    378     bool capsLock()   const { return mCapsLock; }
    379     bool scrollLock() const { return mScrollLock; }
    380 private:
    381     bool mNumLock, mCapsLock, mScrollLock;
    382 };
    383 
    384 /** Network adapter change event */
    385 class NetworkAdapterChangeEvent : public QEvent
    386 {
    387 public:
    388     NetworkAdapterChangeEvent (INetworkAdapter *aAdapter) :
    389         QEvent ((QEvent::Type) VBoxDefs::NetworkAdapterChangeEventType),
    390         mAdapter (aAdapter) {}
    391     INetworkAdapter* networkAdapter() { return mAdapter; }
    392 private:
    393     INetworkAdapter *mAdapter;
    394 };
    395 
    396 /** USB controller state change event */
    397 class USBControllerStateChangeEvent : public QEvent
    398 {
    399 public:
    400     USBControllerStateChangeEvent()
    401         : QEvent ((QEvent::Type) VBoxDefs::USBCtlStateChangeEventType) {}
    402 };
    403 
    404 /** USB device state change event */
    405 class USBDeviceStateChangeEvent : public QEvent
    406 {
    407 public:
    408     USBDeviceStateChangeEvent (const CUSBDevice &aDevice, bool aAttached,
    409                                const CVirtualBoxErrorInfo &aError) :
    410         QEvent ((QEvent::Type) VBoxDefs::USBDeviceStateChangeEventType),
    411         mDevice (aDevice), mAttached (aAttached), mError (aError) {}
    412     CUSBDevice device() const { return mDevice; }
    413     bool attached() const { return mAttached; }
    414     CVirtualBoxErrorInfo error() const { return mError; }
    415 private:
    416     CUSBDevice mDevice;
    417     bool mAttached;
    418     CVirtualBoxErrorInfo mError;
    419 };
    420 
    421 //
    422 // VBoxConsoleCallback class
    423 /////////////////////////////////////////////////////////////////////////////
    424 
    425 class VBoxConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
    426 {
    427 public:
    428 
    429     VBoxConsoleCallback (VBoxConsoleView *v) {
    430 #if defined (Q_WS_WIN)
    431         mRefCnt = 0;
    432 #endif
    433         mView = v;
    434     }
    435 
    436     virtual ~VBoxConsoleCallback() {}
    437 
    438     NS_DECL_ISUPPORTS
    439 
    440 #if defined (Q_WS_WIN)
    441     STDMETHOD_(ULONG, AddRef)() {
    442         return ::InterlockedIncrement (&mRefCnt);
    443     }
    444     STDMETHOD_(ULONG, Release)()
    445     {
    446         long cnt = ::InterlockedDecrement (&mRefCnt);
    447         if (cnt == 0)
    448             delete this;
    449         return cnt;
    450     }
    451 #endif
    452     VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
    453 
    454     STDMETHOD(OnMousePointerShapeChange) (BOOL visible, BOOL alpha,
    455                                           ULONG xhot, ULONG yhot,
    456                                           ULONG width, ULONG height,
    457                                           BYTE *shape)
    458     {
    459         QApplication::postEvent (mView,
    460                                  new MousePointerChangeEvent (visible, alpha,
    461                                                               xhot, yhot,
    462                                                               width, height, shape));
    463         return S_OK;
    464     }
    465 
    466     STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
    467     {
    468         QApplication::postEvent (mView,
    469                                  new MouseCapabilityEvent (supportsAbsolute,
    470                                                            needsHostCursor));
    471         return S_OK;
    472     }
    473 
    474     STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
    475     {
    476         QApplication::postEvent (mView,
    477                                  new ModifierKeyChangeEvent (fNumLock, fCapsLock,
    478                                                              fScrollLock));
    479         return S_OK;
    480     }
    481 
    482     STDMETHOD(OnStateChange)(MachineState_T machineState)
    483     {
    484         LogFlowFunc (("machineState=%d\n", machineState));
    485         QApplication::postEvent (mView,
    486                                  new StateChangeEvent ((KMachineState) machineState));
    487         return S_OK;
    488     }
    489 
    490     STDMETHOD(OnAdditionsStateChange)()
    491     {
    492         CGuest guest = mView->console().GetGuest();
    493         LogFlowFunc (("ver=%s, active=%d\n",
    494                       guest.GetAdditionsVersion().toLatin1().constData(),
    495                       guest.GetAdditionsActive()));
    496         QApplication::postEvent (mView,
    497                                  new GuestAdditionsEvent (
    498                                      guest.GetOSTypeId(),
    499                                      guest.GetAdditionsVersion(),
    500                                      guest.GetAdditionsActive(),
    501                                      guest.GetSupportsSeamless(),
    502                                      guest.GetSupportsGraphics()));
    503         return S_OK;
    504     }
    505 
    506     STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
    507     {
    508         QApplication::postEvent (mView,
    509             new NetworkAdapterChangeEvent (aNetworkAdapter));
    510         return S_OK;
    511     }
    512 
    513     STDMETHOD(OnStorageControllerChange) ()
    514     {
    515         /* @todo */
    516         //QApplication::postEvent (mView,
    517         //    new StorageControllerChangeEvent ());
    518         return S_OK;
    519     }
    520 
    521     STDMETHOD(OnMediumChange)(IMediumAttachment *aMediumAttachment)
    522     {
    523         CMediumAttachment att(aMediumAttachment);
    524         switch (att.GetType())
    525         {
    526             case KDeviceType_Floppy:
    527                 QApplication::postEvent(mView,
    528                     new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy));
    529                 break;
    530             case KDeviceType_DVD:
    531                 QApplication::postEvent(mView,
    532                     new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD));
    533                 break;
    534             default:
    535                 /* @todo later add hard disk change as well */
    536                 break;
    537         }
    538         return S_OK;
    539     }
    540 
    541     STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove)
    542     {
    543         NOREF(aCPU);
    544         NOREF(aRemove);
    545         return S_OK;
    546     }
    547 
    548     STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
    549     {
    550         NOREF(aSerialPort);
    551         return S_OK;
    552     }
    553 
    554     STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
    555     {
    556         NOREF(aParallelPort);
    557         return S_OK;
    558     }
    559 
    560     STDMETHOD(OnVRDPServerChange)()
    561     {
    562         return S_OK;
    563     }
    564 
    565     STDMETHOD(OnRemoteDisplayInfoChange)()
    566     {
    567         return S_OK;
    568     }
    569 
    570     STDMETHOD(OnUSBControllerChange)()
    571     {
    572         QApplication::postEvent (mView,
    573                                  new USBControllerStateChangeEvent());
    574         return S_OK;
    575     }
    576 
    577     STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached,
    578                                       IVirtualBoxErrorInfo *aError)
    579     {
    580         QApplication::postEvent (mView,
    581                                  new USBDeviceStateChangeEvent (
    582                                      CUSBDevice (aDevice),
    583                                      bool (aAttached),
    584                                      CVirtualBoxErrorInfo (aError)));
    585         return S_OK;
    586     }
    587 
    588     STDMETHOD(OnSharedFolderChange) (Scope_T aScope)
    589     {
    590         NOREF(aScope);
    591         QApplication::postEvent (mView,
    592                                  new QEvent ((QEvent::Type)
    593                                              VBoxDefs::SharedFolderChangeEventType));
    594         return S_OK;
    595     }
    596 
    597     STDMETHOD(OnRuntimeError)(BOOL fatal, IN_BSTR id, IN_BSTR message)
    598     {
    599         QApplication::postEvent (mView,
    600                                  new RuntimeErrorEvent (!!fatal,
    601                                                         QString::fromUtf16 (id),
    602                                                         QString::fromUtf16 (message)));
    603         return S_OK;
    604     }
    605 
    606     STDMETHOD(OnCanShowWindow) (BOOL *canShow)
    607     {
    608         if (!canShow)
    609             return E_POINTER;
    610 
    611         /* as long as there is VBoxConsoleView (which creates/destroys us), it
    612          * can be shown */
    613         *canShow = TRUE;
    614         return S_OK;
    615     }
    616 
    617     STDMETHOD(OnShowWindow) (ULONG64 *winId)
    618     {
    619         if (!winId)
    620             return E_POINTER;
    621 
    622 #if defined (Q_WS_MAC)
    623         /*
    624          * Let's try the simple approach first - grab the focus.
     470        /* Let's try the simple approach first - grab the focus.
    625471         * Getting a window out of the dock (minimized or whatever it's called)
    626          * needs to be done on the GUI thread, so post it a note.
    627          */
    628         *winId = 0;
    629         if (!mView)
     472         * needs to be done on the GUI thread, so post it a note: */
     473        *puWinId = 0;
     474        if (!m_pEventHandler)
    630475            return S_OK;
    631476
    632477        ProcessSerialNumber psn = { 0, kCurrentProcess };
    633         OSErr rc = ::SetFrontProcess (&psn);
     478        OSErr rc = ::SetFrontProcess(&psn);
    634479        if (!rc)
    635             QApplication::postEvent (mView, new QEvent ((QEvent::Type)VBoxDefs::ShowWindowEventType));
     480            QApplication::postEvent(m_pEventHandler, new UIShowWindowEvent);
    636481        else
    637482        {
    638             /*
    639              * It failed for some reason, send the other process our PSN so it can try.
     483            /* It failed for some reason, send the other process our PSN so it can try.
    640484             * (This is just a precaution should Mac OS X start imposing the same sensible
    641              * focus stealing restrictions that other window managers implement.)
    642              */
     485             * focus stealing restrictions that other window managers implement). */
    643486            AssertMsgFailed(("SetFrontProcess -> %#x\n", rc));
    644             if (::GetCurrentProcess (&psn))
    645                 *winId = RT_MAKE_U64 (psn.lowLongOfPSN, psn.highLongOfPSN);
    646         }
    647 
     487            if (::GetCurrentProcess(&psn))
     488                *puWinId = RT_MAKE_U64(psn.lowLongOfPSN, psn.highLongOfPSN);
     489        }
    648490#else
    649491        /* Return the ID of the top-level console window. */
    650         *winId = (ULONG64) mView->window()->winId();
    651 #endif
    652 
    653         return S_OK;
    654     }
    655 
    656 protected:
    657 
    658     VBoxConsoleView *mView;
     492        *puWinId = m_pEventHandler->winId();
     493#endif
     494
     495        return S_OK;
     496    }
     497
     498private:
     499
     500    UISession *m_pEventHandler;
    659501
    660502#if defined (Q_WS_WIN)
    661 private:
    662     long mRefCnt;
     503    long m_iRefCount;
    663504#endif
    664505};
    665506
    666507#if !defined (Q_WS_WIN)
    667 NS_DECL_CLASSINFO (VBoxConsoleCallback)
    668 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (VBoxConsoleCallback, IConsoleCallback)
    669 #endif
    670 
    671 class VBoxViewport: public QWidget
    672 {
    673 public:
    674     VBoxViewport (QWidget *aParent)
    675         : QWidget (aParent)
    676     {
    677         /* No need for background drawing */
    678         setAttribute (Qt::WA_OpaquePaintEvent);
    679     }
    680     virtual QPaintEngine * paintEngine() const
    681     {
    682         if (testAttribute (Qt::WA_PaintOnScreen))
    683             return NULL;
    684         else
    685             return QWidget::paintEngine();
    686     }
    687 };
    688 
    689 //
    690 // VBoxConsoleView class
    691 /////////////////////////////////////////////////////////////////////////////
    692 
    693 /** @class VBoxConsoleView
    694  *
    695  *  The VBoxConsoleView class is a widget that implements a console
    696  *  for the running virtual machine.
    697  */
    698 
    699 VBoxConsoleView::VBoxConsoleView (VBoxConsoleWnd *mainWnd,
    700                                   const CConsole &console,
    701                                   VBoxDefs::RenderMode rm,
    702 #ifdef VBOX_WITH_VIDEOHWACCEL
    703                                   bool accelerate2DVideo,
    704 #endif
    705                                   QWidget *parent)
    706     : QAbstractScrollArea (parent)
    707     , mMainWnd (mainWnd)
    708     , mConsole (console)
    709     , gs (vboxGlobal().settings())
    710     , mAttached (false)
    711     , mKbdCaptured (false)
    712     , mMouseCaptured (false)
    713     , mMouseAbsolute (false)
    714     , mMouseIntegration (true)
    715     , m_iLastMouseWheelDelta(0)
    716     , mDisableAutoCapture (false)
    717     , mIsHostkeyPressed (false)
    718     , mIsHostkeyAlone (false)
    719     , mIgnoreMainwndResize (true)
    720     , mAutoresizeGuest (false)
    721     , mIgnoreFrameBufferResize (false)
    722     , mIgnoreGuestResize (false)
    723     , mDoResize (false)
    724     , mGuestSupportsGraphics (false)
    725     , mNumLock (false)
    726     , mScrollLock (false)
    727     , mCapsLock (false)
    728     , muNumLockAdaptionCnt (2)
    729     , muCapsLockAdaptionCnt (2)
    730     , mode (rm)
    731 #ifdef VBOX_WITH_VIDEOHWACCEL
    732     , mAccelerate2DVideo(accelerate2DVideo)
    733 #endif
    734 #if defined(Q_WS_WIN)
    735     , mAlphaCursor (NULL)
    736 #endif
    737 #if defined(Q_WS_MAC)
    738 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA)
    739     , mDarwinEventHandlerRef (NULL)
    740 # endif
    741     , mDarwinKeyModifiers (0)
    742     , mKeyboardGrabbed (false)
    743     , mDockIconEnabled (true)
    744 #endif
    745     , mDesktopGeo (DesktopGeo_Invalid)
    746     , mPassCAD (false)
    747       /* Don't show a hardware pointer until we have one to show */
    748     , mHideHostPointer (true)
    749 {
    750     Assert (!mConsole.isNull() &&
    751             !mConsole.GetDisplay().isNull() &&
    752             !mConsole.GetKeyboard().isNull() &&
    753             !mConsole.GetMouse().isNull());
    754 
    755 #ifdef Q_WS_MAC
    756     /* Overlay logo for the dock icon */
    757     QString osTypeId = mConsole.GetGuest().GetOSTypeId();
    758     mDockIconPreview = new VBoxDockIconPreview (mMainWnd, vboxGlobal().vmGuestOSTypeIcon (osTypeId));
    759 
    760 # ifdef QT_MAC_USE_COCOA
    761     /** @todo Carbon -> Cocoa */
    762 # else /* !QT_MAC_USE_COCOA */
    763     /* Install the event handler which will proceed external window handling */
    764     EventHandlerUPP eventHandler = ::NewEventHandlerUPP (::darwinOverlayWindowHandler);
    765     EventTypeSpec eventTypes[] =
    766     {
    767         { kEventClassVBox, kEventVBoxShowWindow },
    768         { kEventClassVBox, kEventVBoxHideWindow },
    769         { kEventClassVBox, kEventVBoxMoveWindow },
    770         { kEventClassVBox, kEventVBoxResizeWindow },
    771         { kEventClassVBox, kEventVBoxDisposeWindow },
    772         { kEventClassVBox, kEventVBoxUpdateDock }
    773     };
    774 
    775     mDarwinWindowOverlayHandlerRef = NULL;
    776     ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
    777                                       this, &mDarwinWindowOverlayHandlerRef);
    778     ::DisposeEventHandlerUPP (eventHandler);
    779 # endif /* !QT_MAC_USE_COCOA */
    780 #endif /* QT_WS_MAC */
    781 
    782     /* No frame around the view */
    783     setFrameStyle (QFrame::NoFrame);
    784 
    785 #ifdef VBOX_GUI_USE_QGL
    786     QWidget *pViewport;
    787     switch (mode)
    788     {
    789         case VBoxDefs::QGLMode:
    790             pViewport = new VBoxGLWidget (this, this, NULL);
    791             break;
    792         default:
    793             pViewport = new VBoxViewport (this);
    794     }
    795 #else
    796     VBoxViewport *pViewport = new VBoxViewport (this);
    797 #endif
    798     setViewport (pViewport);
    799 //    pViewport->vboxDoInit();
    800 
    801     /* enable MouseMove events */
    802     viewport()->setMouseTracking (true);
    803 
    804     /*
    805      *  QScrollView does the below on its own, but let's do it anyway
    806      *  for the case it will not do it in the future.
    807      */
    808     viewport()->installEventFilter (this);
    809 
    810     /* to fix some focus issues */
    811     mMainWnd->menuBar()->installEventFilter (this);
    812 
    813     /* we want to be notified on some parent's events */
    814     mMainWnd->installEventFilter (this);
    815 
    816 #ifdef Q_WS_X11
    817     /* initialize the X keyboard subsystem */
    818     initMappedX11Keyboard(QX11Info::display(),
    819             vboxGlobal().settings().publicProperty ("GUI/RemapScancodes"));
    820 #endif
    821 
    822     ::memset (mPressedKeys, 0, sizeof (mPressedKeys));
    823 
    824     /* setup rendering */
    825 
    826     CDisplay display = mConsole.GetDisplay();
    827     Assert (!display.isNull());
    828 
    829     mFrameBuf = NULL;
    830 
    831     LogFlowFunc (("Rendering mode: %d\n", mode));
    832 
    833     switch (mode)
    834     {
    835 #if defined (VBOX_GUI_USE_QGL)
    836         case VBoxDefs::QGLMode:
    837             mFrameBuf = new VBoxQGLFrameBuffer (this);
    838             break;
    839 //        case VBoxDefs::QGLOverlayMode:
    840 //            mFrameBuf = new VBoxQGLOverlayFrameBuffer (this);
    841 //            break;
    842 #endif
    843 #if defined (VBOX_GUI_USE_QIMAGE)
    844         case VBoxDefs::QImageMode:
    845             mFrameBuf =
    846 #ifdef VBOX_WITH_VIDEOHWACCEL
    847                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQImageFrameBuffer> (this, &mainWnd->session()) :
    848 #endif
    849                     new VBoxQImageFrameBuffer (this);
    850             break;
    851 #endif
    852 #if defined (VBOX_GUI_USE_SDL)
    853         case VBoxDefs::SDLMode:
    854             /* Indicate that we are doing all
    855              * drawing stuff ourself */
    856             pViewport->setAttribute (Qt::WA_PaintOnScreen);
    857 # ifdef Q_WS_X11
    858             /* This is somehow necessary to prevent strange X11 warnings on
    859              * i386 and segfaults on x86_64. */
    860             XFlush(QX11Info::display());
    861 # endif
    862             mFrameBuf =
    863 #if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
    864                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxSDLFrameBuffer> (this, &mainWnd->session()) :
    865 #endif
    866                     new VBoxSDLFrameBuffer (this);
    867             /*
    868              *  disable scrollbars because we cannot correctly draw in a
    869              *  scrolled window using SDL
    870              */
    871             horizontalScrollBar()->setEnabled (false);
    872             verticalScrollBar()->setEnabled (false);
    873             break;
    874 #endif
    875 #if defined (VBOX_GUI_USE_DDRAW)
    876         case VBoxDefs::DDRAWMode:
    877             mFrameBuf = new VBoxDDRAWFrameBuffer (this);
    878             break;
    879 #endif
    880 #if defined (VBOX_GUI_USE_QUARTZ2D)
    881         case VBoxDefs::Quartz2DMode:
    882             /* Indicate that we are doing all
    883              * drawing stuff ourself */
    884             pViewport->setAttribute (Qt::WA_PaintOnScreen);
    885             mFrameBuf =
    886 #ifdef VBOX_WITH_VIDEOHWACCEL
    887                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer> (this, &mainWnd->session()) :
    888 #endif
    889                     new VBoxQuartz2DFrameBuffer (this);
    890             break;
    891 #endif
    892         default:
    893             AssertReleaseMsgFailed (("Render mode must be valid: %d\n", mode));
    894             LogRel (("Invalid render mode: %d\n", mode));
    895             qApp->exit (1);
    896             break;
    897     }
    898 
    899 #if defined (VBOX_GUI_USE_DDRAW)
    900     if (!mFrameBuf || mFrameBuf->address() == NULL)
    901     {
    902         if (mFrameBuf)
    903             delete mFrameBuf;
    904         mode = VBoxDefs::QImageMode;
    905         mFrameBuf = new VBoxQImageFrameBuffer (this);
    906     }
    907 #endif
    908 
    909     if (mFrameBuf)
    910     {
    911         mFrameBuf->AddRef();
    912         display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer (mFrameBuf));
    913     }
    914 
    915     /* setup the callback */
    916     mCallback = CConsoleCallback (new VBoxConsoleCallback (this));
    917     mConsole.RegisterCallback (mCallback);
    918     AssertWrapperOk (mConsole);
    919 
    920     QPalette palette (viewport()->palette());
    921     palette.setColor (viewport()->backgroundRole(), Qt::black);
    922     viewport()->setPalette (palette);
    923 
    924     setSizePolicy (QSizePolicy (QSizePolicy::Maximum, QSizePolicy::Maximum));
    925     setMaximumSize (sizeHint());
    926 
    927     setFocusPolicy (Qt::WheelFocus);
    928 
    929     /* Remember the desktop geometry and register for geometry change
    930        events for telling the guest about video modes we like. */
    931 
    932     QString desktopGeometry = vboxGlobal().settings()
    933                                   .publicProperty ("GUI/MaxGuestResolution");
    934     if ((desktopGeometry == QString::null) ||
    935         (desktopGeometry == "auto"))
    936         setDesktopGeometry (DesktopGeo_Automatic, 0, 0);
    937     else if (desktopGeometry == "any")
    938         setDesktopGeometry (DesktopGeo_Any, 0, 0);
    939     else
    940     {
    941         int width = desktopGeometry.section (',', 0, 0).toInt();
    942         int height = desktopGeometry.section (',', 1, 1).toInt();
    943         setDesktopGeometry (DesktopGeo_Fixed, width, height);
    944     }
    945     connect (QApplication::desktop(), SIGNAL (resized (int)),
    946              this, SLOT (doResizeDesktop (int)));
    947 
    948     QString passCAD = mConsole.GetMachine().GetExtraData (VBoxDefs::GUI_PassCAD);
    949     if (!passCAD.isEmpty() &&
    950         ((passCAD != "false") || (passCAD != "no"))
    951        )
    952         mPassCAD = true;
    953 
    954 #if defined (Q_WS_WIN)
    955     gView = this;
    956 #endif
    957 
    958 #if defined (Q_WS_PM)
    959     bool ok = VBoxHlpInstallKbdHook (0, winId(), UM_PREACCEL_CHAR);
    960     Assert (ok);
    961     NOREF (ok);
    962 #endif
     508NS_DECL_CLASSINFO(UIConsoleCallback)
     509NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIConsoleCallback, IConsoleCallback)
     510#endif
     511
     512UISession::UISession(UIMachine *pMachine, const CSession &session)
     513    : QObject(pMachine)
     514    , m_pMachine(pMachine)
     515    , m_session(session)
     516    , m_pCallback(new UIConsoleCallback(this))
     517    , m_callback(CConsoleCallback(m_pCallback))
     518{
     519    /* Check CSession object */
     520    AssertMsg(!m_session.isNull(), ("CSession is not set!\n"));
     521
     522    /* Register console callback: */
     523    m_session.GetConsole().RegisterCallback(m_callback);
    963524}
    964525
    965 VBoxConsoleView::~VBoxConsoleView()
    966 {
    967 #if defined (Q_WS_PM)
    968     bool ok = VBoxHlpUninstallKbdHook (0, winId(), UM_PREACCEL_CHAR);
    969     Assert (ok);
    970     NOREF (ok);
    971 #endif
    972 
    973 #if defined (Q_WS_WIN)
    974     if (gKbdHook)
    975         UnhookWindowsHookEx (gKbdHook);
    976     gView = 0;
    977     if (mAlphaCursor)
    978         DestroyIcon (mAlphaCursor);
    979 #endif
    980 
    981     if (mFrameBuf)
    982     {
    983         /* detach our framebuffer from Display */
    984         CDisplay display = mConsole.GetDisplay();
    985         Assert (!display.isNull());
    986         display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL));
    987         /* release the reference */
    988         mFrameBuf->Release();
    989         mFrameBuf = NULL;
    990     }
    991 
    992     mConsole.UnregisterCallback (mCallback);
    993 
    994 #if defined (Q_WS_MAC)
    995 # if !defined (QT_MAC_USE_COCOA)
    996     if (mDarwinWindowOverlayHandlerRef)
    997     {
    998         ::RemoveEventHandler (mDarwinWindowOverlayHandlerRef);
    999         mDarwinWindowOverlayHandlerRef = NULL;
    1000     }
    1001 # endif
    1002     delete mDockIconPreview;
    1003     mDockIconPreview = NULL;
    1004 #endif
     526UISession::~UISession()
     527{
     528    /* Unregister console callback: */
     529    m_session.GetConsole().UnregisterCallback(m_callback);
     530    delete m_pCallback;
     531    m_pCallback = 0;
    1005532}
    1006533
    1007 //
    1008 // Public members
    1009 /////////////////////////////////////////////////////////////////////////////
    1010 
    1011 QSize VBoxConsoleView::sizeHint() const
    1012 {
    1013 #ifdef VBOX_WITH_DEBUGGER /** @todo figure out a more proper fix. */
    1014     /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done
    1015      *             by DevVGA if provoked before power on.  */
    1016     QSize fb(mFrameBuf->width(), mFrameBuf->height());
    1017     if (    (   fb.width()  < 16
    1018              || fb.height() < 16)
    1019         &&  (   vboxGlobal().isStartPausedEnabled()
    1020              || vboxGlobal().isDebuggerAutoShowEnabled()) )
    1021         fb = QSize(640, 480);
    1022     return QSize (fb.width() + frameWidth() * 2,
    1023                   fb.height() + frameWidth() * 2);
    1024 #else
    1025     return QSize (mFrameBuf->width() + frameWidth() * 2,
    1026                   mFrameBuf->height() + frameWidth() * 2);
    1027 #endif
    1028 }
    1029 
    1030 /**
    1031  *  Attaches this console view to the managed virtual machine.
    1032  *
    1033  *  @note This method is not really necessary these days -- the only place where
    1034  *        it gets called is VBoxConsole::openView(), right after powering the
    1035  *        VM up. We leave it as is just in case attaching/detaching will become
    1036  *        necessary some day (there are useful attached checks everywhere in the
    1037  *        code).
    1038  */
    1039 void VBoxConsoleView::attach()
    1040 {
    1041     if (!mAttached)
    1042     {
    1043         mAttached = true;
    1044     }
    1045 }
    1046 
    1047 /**
    1048  *  Detaches this console view from the VM. Must be called to indicate
    1049  *  that the virtual machine managed by this instance will be no more valid
    1050  *  after this call.
    1051  *
    1052  *  @note This method is not really necessary these days -- the only place where
    1053  *        it gets called is VBoxConsole::closeView(), when the VM is powered
    1054  *        down, before deleting VBoxConsoleView. We leave it as is just in case
    1055  *        attaching/detaching will become necessary some day (there are useful
    1056  *        attached checks everywhere in the code).
    1057  */
    1058 void VBoxConsoleView::detach()
    1059 {
    1060     if (mAttached)
    1061     {
    1062         /* reuse the focus event handler to uncapture everything */
    1063         focusEvent (false);
    1064         mAttached = false;
    1065     }
    1066 }
    1067 
    1068 /**
    1069  *  Resizes the toplevel widget to fit the console view w/o scrollbars.
    1070  *  If adjustPosition is true and such resize is not possible (because the
    1071  *  console view size is lagrer then the available screen space) the toplevel
    1072  *  widget is resized and moved to become as large as possible while staying
    1073  *  fully visible.
    1074  */
    1075 void VBoxConsoleView::normalizeGeometry (bool adjustPosition /* = false */)
    1076 {
    1077     /* Make no normalizeGeometry in case we are in manual resize
    1078      * mode or main window is maximized */
    1079     if (mMainWnd->isWindowMaximized() || mMainWnd->isWindowFullScreen())
    1080         return;
    1081 
    1082     QWidget *tlw = window();
    1083 
    1084     /* calculate client window offsets */
    1085     QRect fr = tlw->frameGeometry();
    1086     QRect r = tlw->geometry();
    1087     int dl = r.left() - fr.left();
    1088     int dt = r.top() - fr.top();
    1089     int dr = fr.right() - r.right();
    1090     int db = fr.bottom() - r.bottom();
    1091 
    1092     /* get the best size w/o scroll bars */
    1093     QSize s = tlw->sizeHint();
    1094 
    1095     /* resize the frame to fit the contents */
    1096     s -= tlw->size();
    1097     fr.setRight (fr.right() + s.width());
    1098     fr.setBottom (fr.bottom() + s.height());
    1099 
    1100     if (adjustPosition)
    1101     {
    1102         QRegion ar;
    1103         QDesktopWidget *dwt = QApplication::desktop();
    1104         if (dwt->isVirtualDesktop())
    1105             /* Compose complex available region */
    1106             for (int i = 0; i < dwt->numScreens(); ++ i)
    1107                 ar += dwt->availableGeometry (i);
    1108         else
    1109             /* Get just a simple available rectangle */
    1110             ar = dwt->availableGeometry (tlw->pos());
    1111 
    1112         fr = VBoxGlobal::normalizeGeometry (
    1113             fr, ar, mode != VBoxDefs::SDLMode /* canResize */);
    1114     }
    1115 
    1116 #if 0
    1117     /* center the frame on the desktop */
    1118     fr.moveCenter (ar.center());
    1119 #endif
    1120 
    1121     /* finally, set the frame geometry */
    1122     tlw->setGeometry (fr.left() + dl, fr.top() + dt,
    1123                       fr.width() - dl - dr, fr.height() - dt - db);
    1124 }
    1125 
    1126 /**
    1127  *  Pauses or resumes the VM execution.
    1128  */
    1129 bool VBoxConsoleView::pause (bool on)
    1130 {
    1131     /* QAction::setOn() emits the toggled() signal, so avoid recursion when
    1132      * QAction::setOn() is called from VBoxConsoleWnd::updateMachineState() */
    1133     if (isPaused() == on)
    1134         return true;
    1135 
    1136     if (on)
    1137         mConsole.Pause();
    1138     else
    1139         mConsole.Resume();
    1140 
    1141     bool ok = mConsole.isOk();
    1142     if (!ok)
    1143     {
    1144         if (on)
    1145             vboxProblem().cannotPauseMachine (mConsole);
    1146         else
    1147             vboxProblem().cannotResumeMachine (mConsole);
    1148     }
    1149 
    1150     return ok;
    1151 }
    1152 
    1153 /**
    1154  *  Temporarily disables the mouse integration (or enables it back).
    1155  */
    1156 void VBoxConsoleView::setMouseIntegrationEnabled (bool enabled)
    1157 {
    1158     if (mMouseIntegration == enabled)
    1159         return;
    1160 
    1161     if (mMouseAbsolute)
    1162         captureMouse (!enabled, false);
    1163 
    1164     /* Hiding host cursor in case we are entering mouse integration
    1165      * mode until it's shape is set to the guest cursor shape in
    1166      * OnMousePointerShapeChange event handler.
    1167      *
    1168      * This is necessary to avoid double-cursor issues where both the
    1169      * guest and the host cursors are displayed in one place, one above the
    1170      * other.
    1171      *
    1172      * This is a workaround because the correct decision would be to notify
    1173      * the Guest Additions about we are entering the mouse integration
    1174      * mode. The GuestOS should hide it's cursor to allow using of
    1175      * host cursor for the guest's manipulation.
    1176      *
    1177      * This notification is not always possible though, as not all guests
    1178      * support switching to a hardware pointer on demand. */
    1179     if (enabled)
    1180         viewport()->setCursor (QCursor (Qt::BlankCursor));
    1181 
    1182     mMouseIntegration = enabled;
    1183 
    1184     emitMouseStateChanged();
    1185 }
    1186 
    1187 void VBoxConsoleView::setAutoresizeGuest (bool on)
    1188 {
    1189     if (mAutoresizeGuest != on)
    1190     {
    1191         mAutoresizeGuest = on;
    1192 
    1193         maybeRestrictMinimumSize();
    1194 
    1195         if (mGuestSupportsGraphics && mAutoresizeGuest)
    1196             doResizeHint();
    1197     }
    1198 }
    1199 
    1200 /**
    1201  *  This method is called by VBoxConsoleWnd after it does everything necessary
    1202  *  on its side to go to or from fullscreen, but before it is shown.
    1203  */
    1204 void VBoxConsoleView::onFullscreenChange (bool /* on */)
    1205 {
    1206     /* Nothing to do here so far */
    1207 }
    1208 
    1209 /**
    1210  *  Notify the console scroll-view about the console-window is opened.
    1211  */
    1212 void VBoxConsoleView::onViewOpened()
    1213 {
    1214     /* Variable mIgnoreMainwndResize was initially "true" to ignore QT
    1215      * initial resize event in case of auto-resize feature is on.
    1216      * Currently, initial resize event is already processed, so we set
    1217      * mIgnoreMainwndResize to "false" to process all further resize
    1218      * events as user-initiated window resize events. */
    1219     mIgnoreMainwndResize = false;
    1220 }
    1221 
    1222 //
    1223 // Protected Events
    1224 /////////////////////////////////////////////////////////////////////////////
    1225 
    1226 bool VBoxConsoleView::event (QEvent *e)
    1227 {
    1228     if (mAttached)
    1229     {
    1230         switch (e->type())
    1231         {
    1232             case QEvent::FocusIn:
     534bool UISession::event(QEvent *pEvent)
     535{
     536    switch (pEvent->type())
     537    {
     538        case UIConsoleEventType_MousePointerShapeChange:
     539        {
     540#if 0 // TODO: Move to machine view!
     541            MousePointerChangeEvent *me = (MousePointerChangeEvent*)pEvent;
     542            /* Change cursor shape only when mouse integration is
     543             * supported (change mouse shape type event may arrive after
     544             * mouse capability change that disables integration. */
     545            if (m_bIsMouseAbsolute)
     546                setPointerShape (me);
     547            else
     548                /* Note: actually we should still remember the requested
     549                 * cursor shape.  If we can't do that, at least remember
     550                 * the requested visiblilty. */
     551                mHideHostPointer = !me->isVisible();
     552#endif
     553            UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent);
     554            emit sigMousePointerShapeChange(pConsoleEvent->isVisible(), pConsoleEvent->hasAlpha(),
     555                                            pConsoleEvent->xHot(), pConsoleEvent->yHot(),
     556                                            pConsoleEvent->width(), pConsoleEvent->height(),
     557                                            pConsoleEvent->shapeData());
     558            return true;
     559        }
     560
     561        case UIConsoleEventType_MouseCapabilityChange:
     562        {
     563#if 0 // TODO: Move to machine view!
     564            MouseCapabilityEvent *me = (MouseCapabilityEvent*)pEvent;
     565            if (m_bIsMouseAbsolute != me->supportsAbsolute())
    1233566            {
    1234                 if (isRunning())
    1235                     focusEvent (true);
    1236                 break;
    1237             }
    1238             case QEvent::FocusOut:
    1239             {
    1240                 if (isRunning())
    1241                     focusEvent (false);
    1242                 else
     567                m_bIsMouseAbsolute = me->supportsAbsolute();
     568                /* correct the mouse capture state and reset the cursor
     569                 * to the default shape if necessary */
     570                if (m_bIsMouseAbsolute)
    1243571                {
    1244                     /* release the host key and all other pressed keys too even
    1245                      * when paused (otherwise, we will get stuck keys in the
    1246                      * guest when doing sendChangedKeyStates() on resume because
    1247                      * key presses were already recorded in mPressedKeys but key
    1248                      * releases will most likely not reach us but the new focus
    1249                      * window instead). */
    1250                     releaseAllPressedKeys (true /* aReleaseHostKey */);
    1251                 }
    1252                 break;
    1253             }
    1254 
    1255             case VBoxDefs::ResizeEventType:
    1256             {
    1257                 /* Some situations require initial VGA Resize Request
    1258                  * to be ignored at all, leaving previous framebuffer,
    1259                  * console widget and vm window size preserved. */
    1260                 if (mIgnoreGuestResize)
    1261                     return true;
    1262 
    1263                 bool oldIgnoreMainwndResize = mIgnoreMainwndResize;
    1264                 mIgnoreMainwndResize = true;
    1265 
    1266                 VBoxResizeEvent *re = (VBoxResizeEvent *) e;
    1267                 LogRelFlowFunc (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n",
    1268                                  re->width(), re->height(),
    1269                                  re->bitsPerPixel()));
    1270 
    1271                 bool notifyMainWnd = mFrameBuf->width() != re->width()
    1272                         || mFrameBuf->height() != re->height();
    1273 
    1274                 /* Store the new size to prevent unwanted resize hints being
    1275                  * sent back. */
    1276                 storeConsoleSize(re->width(), re->height());
    1277                 /* do frame buffer dependent resize */
    1278 
    1279                 /* restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen
    1280                  * widgets are present. This is the case on linux with SDL. As
    1281                  * workaround we save/restore the arrow cursor manually. See
    1282                  * http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry
    1283                  * for details.
    1284                  *
    1285                  * Moreover the current cursor, which could be set by the guest,
    1286                  * should be restored after resize.
    1287                  */
    1288                 QCursor cursor;
    1289                 if (shouldHideHostPointer())
    1290                     cursor = QCursor (Qt::BlankCursor);
    1291                 else
    1292                     cursor = viewport()->cursor();
    1293                 mFrameBuf->resizeEvent (re);
    1294                 viewport()->setCursor (cursor);
    1295 
    1296 #ifdef Q_WS_MAC
    1297                 mDockIconPreview->setOriginalSize (re->width(), re->height());
    1298 #endif /* Q_WS_MAC */
    1299 
    1300                 /* This event appears in case of guest video was changed
    1301                  * for somehow even without video resolution change.
    1302                  * In this last case the host VM window will not be resized
    1303                  * according this event and the host mouse cursor which was
    1304                  * unset to default here will not be hidden in capture state.
    1305                  * So it is necessary to perform updateMouseClipping() for
    1306                  * the guest resize event if the mouse cursor was captured. */
    1307                 if (mMouseCaptured)
    1308                     updateMouseClipping();
    1309 
    1310                 /* apply maximum size restriction */
    1311                 setMaximumSize (sizeHint());
    1312 
    1313                 maybeRestrictMinimumSize();
    1314 
    1315                 /* resize the guest canvas */
    1316                 if (!mIgnoreFrameBufferResize)
    1317                     resize (re->width(), re->height());
    1318                 updateSliders();
    1319                 /* Let our toplevel widget calculate its sizeHint properly. */
    1320 #ifdef Q_WS_X11
    1321                 /* We use processEvents rather than sendPostedEvents & set the
    1322                  * time out value to max cause on X11 otherwise the layout
    1323                  * isn't calculated correctly. Dosn't find the bug in Qt, but
    1324                  * this could be triggered through the async nature of the X11
    1325                  * window event system. */
    1326                 QCoreApplication::processEvents (QEventLoop::AllEvents, INT_MAX);
    1327 #else /* Q_WS_X11 */
    1328                 QCoreApplication::sendPostedEvents (0, QEvent::LayoutRequest);
    1329 #endif /* Q_WS_X11 */
    1330 
    1331                 if (!mIgnoreFrameBufferResize)
    1332                     normalizeGeometry (true /* adjustPosition */);
    1333 
    1334                 /* report to the VM thread that we finished resizing */
    1335                 mConsole.GetDisplay().ResizeCompleted (0);
    1336 
    1337                 mIgnoreMainwndResize = oldIgnoreMainwndResize;
    1338 
    1339                 /* update geometry after entering fullscreen | seamless */
    1340                 if (mMainWnd->isTrueFullscreen() || mMainWnd->isTrueSeamless())
    1341                     updateGeometry();
    1342 
    1343                 /* make sure that all posted signals are processed */
    1344                 qApp->processEvents();
    1345 
    1346                 /* emit a signal about guest was resized */
    1347                 emit resizeHintDone();
    1348 
    1349                 /* We also recalculate the desktop geometry if this is determined
    1350                  * automatically.  In fact, we only need this on the first resize,
    1351                  * but it is done every time to keep the code simpler. */
    1352                 calculateDesktopGeometry();
    1353 
    1354                 /* Enable frame-buffer resize watching. */
    1355                 if (mIgnoreFrameBufferResize)
    1356                 {
    1357                     mIgnoreFrameBufferResize = false;
    1358                 }
    1359 
    1360                 if (notifyMainWnd)
    1361                     mMainWnd->onDisplayResize (re->width(), re->height());
    1362 
    1363                 return true;
    1364             }
    1365 
    1366             /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(). */
    1367             case VBoxDefs::RepaintEventType:
    1368             {
    1369                 VBoxRepaintEvent *re = (VBoxRepaintEvent *) e;
    1370                 viewport()->repaint (re->x() - contentsX(),
    1371                                      re->y() - contentsY(),
    1372                                      re->width(), re->height());
    1373                 /* mConsole.GetDisplay().UpdateCompleted(); - the event was acked already */
    1374                 return true;
    1375             }
    1376 
    1377 #ifdef VBOX_WITH_VIDEOHWACCEL
    1378             case VBoxDefs::VHWACommandProcessType:
    1379             {
    1380                 mFrameBuf->doProcessVHWACommand(e);
    1381                 return true;
    1382             }
    1383 #endif
    1384 
    1385             case VBoxDefs::SetRegionEventType:
    1386             {
    1387                 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e;
    1388                 if (mMainWnd->isTrueSeamless() &&
    1389                     sre->region() != mLastVisibleRegion)
    1390                 {
    1391                     mLastVisibleRegion = sre->region();
    1392                     mMainWnd->setMask (sre->region());
    1393                 }
    1394                 else if (!mLastVisibleRegion.isEmpty() &&
    1395                          !mMainWnd->isTrueSeamless())
    1396                     mLastVisibleRegion = QRegion();
    1397                 return true;
    1398             }
    1399 
    1400             case VBoxDefs::MousePointerChangeEventType:
    1401             {
    1402                 MousePointerChangeEvent *me = (MousePointerChangeEvent *) e;
    1403                 /* change cursor shape only when mouse integration is
    1404                  * supported (change mouse shape type event may arrive after
    1405                  * mouse capability change that disables integration */
    1406                 if (mMouseAbsolute)
    1407                     setPointerShape (me);
    1408                 else
    1409                     /* Note: actually we should still remember the requested
    1410                      * cursor shape.  If we can't do that, at least remember
    1411                      * the requested visiblilty. */
    1412                     mHideHostPointer = !me->isVisible();
    1413                 return true;
    1414             }
    1415             case VBoxDefs::MouseCapabilityEventType:
    1416             {
    1417                 MouseCapabilityEvent *me = (MouseCapabilityEvent *) e;
    1418                 if (mMouseAbsolute != me->supportsAbsolute())
    1419                 {
    1420                     mMouseAbsolute = me->supportsAbsolute();
    1421                     /* correct the mouse capture state and reset the cursor
    1422                      * to the default shape if necessary */
    1423                     if (mMouseAbsolute)
    1424                     {
    1425                         CMouse mouse = mConsole.GetMouse();
    1426                         mouse.PutMouseEventAbsolute (-1, -1, 0,
    1427                                                      0 /* Horizontal wheel */,
    1428                                                      0);
    1429                         captureMouse (false, false);
    1430                     }
    1431                     else
    1432                         viewport()->unsetCursor();
    1433                     emitMouseStateChanged();
    1434                     vboxProblem().remindAboutMouseIntegration (mMouseAbsolute);
    1435                 }
    1436                 if (me->needsHostCursor())
    1437                     mMainWnd->setMouseIntegrationLocked (false);
    1438                 else
    1439                     mMainWnd->setMouseIntegrationLocked (true);
    1440                 return true;
    1441             }
    1442 
    1443             case VBoxDefs::ModifierKeyChangeEventType:
    1444             {
    1445                 ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )e;
    1446                 if (me->numLock() != mNumLock)
    1447                     muNumLockAdaptionCnt = 2;
    1448                 if (me->capsLock() != mCapsLock)
    1449                     muCapsLockAdaptionCnt = 2;
    1450                 mNumLock    = me->numLock();
    1451                 mCapsLock   = me->capsLock();
    1452                 mScrollLock = me->scrollLock();
    1453                 return true;
    1454             }
    1455 
    1456             case VBoxDefs::MachineStateChangeEventType:
    1457             {
    1458                 StateChangeEvent *me = (StateChangeEvent *) e;
    1459                 LogFlowFunc (("MachineStateChangeEventType: state=%d\n",
    1460                                me->machineState()));
    1461                 onStateChange (me->machineState());
    1462                 emit machineStateChanged (me->machineState());
    1463                 return true;
    1464             }
    1465 
    1466             case VBoxDefs::AdditionsStateChangeEventType:
    1467             {
    1468                 GuestAdditionsEvent *ge = (GuestAdditionsEvent *) e;
    1469                 LogFlowFunc (("AdditionsStateChangeEventType\n"));
    1470 
    1471                 /* Always send a size hint if we are in fullscreen or seamless
    1472                  * when the graphics capability is enabled, in case the host
    1473                  * resolution has changed since the VM was last run. */
    1474 #if 0
    1475                 if (!mDoResize && !mGuestSupportsGraphics &&
    1476                     ge->supportsGraphics() &&
    1477                     (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen()))
    1478                     mDoResize = true;
    1479 #endif
    1480 
    1481                 mGuestSupportsGraphics = ge->supportsGraphics();
    1482 
    1483                 maybeRestrictMinimumSize();
    1484 
    1485 #if 0
    1486                 /* This will only be acted upon if mDoResize is true. */
    1487                 doResizeHint();
    1488 #endif
    1489 
    1490                 emit additionsStateChanged (ge->additionVersion(),
    1491                                             ge->additionActive(),
    1492                                             ge->supportsSeamless(),
    1493                                             ge->supportsGraphics());
    1494                 return true;
    1495             }
    1496 
    1497             case VBoxDefs::MediaDriveChangeEventType:
    1498             {
    1499                 MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) e;
    1500                 LogFlowFunc (("MediaChangeEvent\n"));
    1501 
    1502                 emit mediaDriveChanged (mce->type());
    1503                 return true;
    1504             }
    1505 
    1506             case VBoxDefs::ActivateMenuEventType:
    1507             {
    1508                 ActivateMenuEvent *ame = (ActivateMenuEvent *) e;
    1509                 ame->action()->trigger();
    1510 
    1511                 /*
    1512                  *  The main window and its children can be destroyed at this
    1513                  *  point (if, for example, the activated menu item closes the
    1514                  *  main window). Detect this situation to prevent calls to
    1515                  *  destroyed widgets.
    1516                  */
    1517                 QWidgetList list = QApplication::topLevelWidgets();
    1518                 bool destroyed = list.indexOf (mMainWnd) < 0;
    1519                 if (!destroyed && mMainWnd->statusBar())
    1520                     mMainWnd->statusBar()->clearMessage();
    1521 
    1522                 return true;
    1523             }
    1524 
    1525             case VBoxDefs::NetworkAdapterChangeEventType:
    1526             {
    1527                 /* no specific adapter information stored in this
    1528                  * event is currently used */
    1529                 emit networkStateChange();
    1530                 return true;
    1531             }
    1532 
    1533             case VBoxDefs::USBCtlStateChangeEventType:
    1534             {
    1535                 emit usbStateChange();
    1536                 return true;
    1537             }
    1538 
    1539             case VBoxDefs::USBDeviceStateChangeEventType:
    1540             {
    1541                 USBDeviceStateChangeEvent *ue = (USBDeviceStateChangeEvent *)e;
    1542 
    1543                 bool success = ue->error().isNull();
    1544 
    1545                 if (!success)
    1546                 {
    1547                     if (ue->attached())
    1548                         vboxProblem().cannotAttachUSBDevice (
    1549                             mConsole,
    1550                             vboxGlobal().details (ue->device()), ue->error());
    1551                     else
    1552                         vboxProblem().cannotDetachUSBDevice (
    1553                             mConsole,
    1554                             vboxGlobal().details (ue->device()), ue->error());
    1555                 }
    1556 
    1557                 emit usbStateChange();
    1558 
    1559                 return true;
    1560             }
    1561 
    1562             case VBoxDefs::SharedFolderChangeEventType:
    1563             {
    1564                 emit sharedFoldersChanged();
    1565                 return true;
    1566             }
    1567 
    1568             case VBoxDefs::RuntimeErrorEventType:
    1569             {
    1570                 RuntimeErrorEvent *ee = (RuntimeErrorEvent *) e;
    1571                 vboxProblem().showRuntimeError (mConsole, ee->fatal(),
    1572                                                 ee->errorID(), ee->message());
    1573                 return true;
    1574             }
    1575 
    1576             case QEvent::KeyPress:
    1577             case QEvent::KeyRelease:
    1578             {
    1579                 QKeyEvent *ke = (QKeyEvent *) e;
    1580 
    1581 #ifdef Q_WS_PM
    1582                 /// @todo temporary solution to send Alt+Tab and friends to
    1583                 //  the guest. The proper solution is to write a keyboard
    1584                 //  driver that will steal these combos from the host (it's
    1585                 //  impossible to do so using hooks on OS/2).
    1586 
    1587                 if (mIsHostkeyPressed)
    1588                 {
    1589                     bool pressed = e->type() == QEvent::KeyPress;
    1590                     CKeyboard keyboard = mConsole.GetKeyboard();
    1591 
    1592                     /* whether the host key is Shift so that it will modify
    1593                      * the hot key values? Note that we don't distinguish
    1594                      * between left and right shift here (too much hassle) */
    1595                     const bool kShift = (gs.hostKey() == VK_SHIFT ||
    1596                                         gs.hostKey() == VK_LSHIFT) &&
    1597                                         (ke->state() & Qt::ShiftModifier);
    1598                     /* define hot keys according to the Shift state */
    1599                     const int kAltTab      = kShift ? Qt::Key_Exclam     : Qt::Key_1;
    1600                     const int kAltShiftTab = kShift ? Qt::Key_At         : Qt::Key_2;
    1601                     const int kCtrlEsc     = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft;
    1602 
    1603                     /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */
    1604                     if (ke->key() == kAltTab || ke->key() == kAltShiftTab)
    1605                     {
    1606                         if (pressed)
    1607                         {
    1608                             /* Send the Alt press to the guest */
    1609                             if (!(mPressedKeysCopy [0x38] & IsKeyPressed))
    1610                             {
    1611                                 /* store the press in *Copy to have it automatically
    1612                                  * released when the Host key is released */
    1613                                 mPressedKeysCopy [0x38] |= IsKeyPressed;
    1614                                 keyboard.PutScancode (0x38);
    1615                             }
    1616 
    1617                             /* Make sure Shift is pressed if it's Key_2 and released
    1618                              * if it's Key_1 */
    1619                             if (ke->key() == kAltTab &&
    1620                                 (mPressedKeysCopy [0x2A] & IsKeyPressed))
    1621                             {
    1622                                 mPressedKeysCopy [0x2A] &= ~IsKeyPressed;
    1623                                 keyboard.PutScancode (0xAA);
    1624                             }
    1625                             else
    1626                             if (ke->key() == kAltShiftTab &&
    1627                                 !(mPressedKeysCopy [0x2A] & IsKeyPressed))
    1628                             {
    1629                                 mPressedKeysCopy [0x2A] |= IsKeyPressed;
    1630                                 keyboard.PutScancode (0x2A);
    1631                             }
    1632                         }
    1633 
    1634                         keyboard.PutScancode (pressed ? 0x0F : 0x8F);
    1635 
    1636                         ke->accept();
    1637                         return true;
    1638                     }
    1639 
    1640                     /* Simulate Ctrl+Esc on Host+Tilde */
    1641                     if (ke->key() == kCtrlEsc)
    1642                     {
    1643                         /* Send the Ctrl press to the guest */
    1644                         if (pressed && !(mPressedKeysCopy [0x1d] & IsKeyPressed))
    1645                         {
    1646                             /* store the press in *Copy to have it automatically
    1647                              * released when the Host key is released */
    1648                             mPressedKeysCopy [0x1d] |= IsKeyPressed;
    1649                             keyboard.PutScancode (0x1d);
    1650                         }
    1651 
    1652                         keyboard.PutScancode (pressed ? 0x01 : 0x81);
    1653 
    1654                         ke->accept();
    1655                         return true;
    1656                     }
    1657                 }
    1658 
    1659                 /* fall through to normal processing */
    1660 
    1661 #endif /* Q_WS_PM */
    1662 
    1663                 if (mIsHostkeyPressed && e->type() == QEvent::KeyPress)
    1664                 {
    1665                     if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12)
    1666                     {
    1667                         QVector <LONG> combo (6);
    1668                         combo [0] = 0x1d; /* Ctrl down */
    1669                         combo [1] = 0x38; /* Alt  down */
    1670                         combo [4] = 0xb8; /* Alt  up   */
    1671                         combo [5] = 0x9d; /* Ctrl up   */
    1672                         if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F10)
    1673                         {
    1674                             combo [2] = 0x3b + (ke->key() - Qt::Key_F1); /* F1-F10 down */
    1675                             combo [3] = 0xbb + (ke->key() - Qt::Key_F1); /* F1-F10 up   */
    1676                         }
    1677                         /* some scan slice */
    1678                         else if (ke->key() >= Qt::Key_F11 && ke->key() <= Qt::Key_F12)
    1679                         {
    1680                             combo [2] = 0x57 + (ke->key() - Qt::Key_F11); /* F11-F12 down */
    1681                             combo [3] = 0xd7 + (ke->key() - Qt::Key_F11); /* F11-F12 up   */
    1682                         }
    1683                         else
    1684                             Assert (0);
    1685 
    1686                         CKeyboard keyboard = mConsole.GetKeyboard();
    1687                         keyboard.PutScancodes (combo);
    1688                     }
    1689                     else if (ke->key() == Qt::Key_Home)
    1690                     {
    1691                         /* Activate the main menu */
    1692                         if (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen())
    1693                             mMainWnd->popupMainMenu (mMouseCaptured);
    1694                         else
    1695                         {
    1696                             /* In Qt4 it is not enough to just set the focus to
    1697                              * menu-bar. So to get the menu-bar we have to send
    1698                              * Qt::Key_Alt press/release events directly. */
    1699                             QKeyEvent e1 (QEvent::KeyPress, Qt::Key_Alt,
    1700                                           Qt::NoModifier);
    1701                             QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt,
    1702                                           Qt::NoModifier);
    1703                             QApplication::sendEvent (mMainWnd->menuBar(), &e1);
    1704                             QApplication::sendEvent (mMainWnd->menuBar(), &e2);
    1705                         }
    1706                     }
    1707                     else
    1708                     {
    1709                         /* process hot keys not processed in keyEvent()
    1710                          * (as in case of non-alphanumeric keys) */
    1711                         processHotKey (QKeySequence (ke->key()),
    1712                                        mMainWnd->menuBar()->actions());
    1713                     }
    1714                 }
    1715                 else if (!mIsHostkeyPressed && e->type() == QEvent::KeyRelease)
    1716                 {
    1717                     /* Show a possible warning on key release which seems to
    1718                      * be more expected by the end user */
    1719 
    1720                     if (isPaused())
    1721                     {
    1722                         /* if the reminder is disabled we pass the event to
    1723                          * Qt to enable normal keyboard functionality
    1724                          * (for example, menu access with Alt+Letter) */
    1725                         if (!vboxProblem().remindAboutPausedVMInput())
    1726                             break;
    1727                     }
    1728                 }
    1729 
    1730                 ke->accept();
    1731                 return true;
    1732             }
    1733 
    1734 #ifdef Q_WS_MAC
    1735             /* posted OnShowWindow */
    1736             case VBoxDefs::ShowWindowEventType:
    1737             {
    1738                 /*
    1739                  *  Dunno what Qt3 thinks a window that has minimized to the dock
    1740                  *  should be - it is not hidden, neither is it minimized. OTOH it is
    1741                  *  marked shown and visible, but not activated. This latter isn't of
    1742                  *  much help though, since at this point nothing is marked activated.
    1743                  *  I might have overlooked something, but I'm buggered what if I know
    1744                  *  what. So, I'll just always show & activate the stupid window to
    1745                  *  make it get out of the dock when the user wishes to show a VM.
    1746                  */
    1747                 window()->show();
    1748                 window()->activateWindow();
    1749                 return true;
    1750             }
    1751 #endif
    1752             default:
    1753                 break;
    1754         }
    1755     }
    1756 
    1757     return QAbstractScrollArea::event (e);
    1758 }
    1759 
    1760 #ifdef VBOX_WITH_VIDEOHWACCEL
    1761 void VBoxConsoleView::scrollContentsBy (int dx, int dy)
    1762 {
    1763     if (mAttached && mFrameBuf)
    1764     {
    1765         mFrameBuf->viewportScrolled(dx, dy);
    1766     }
    1767     QAbstractScrollArea::scrollContentsBy (dx, dy);
    1768 }
    1769 #endif
    1770 
    1771 
    1772 bool VBoxConsoleView::eventFilter (QObject *watched, QEvent *e)
    1773 {
    1774     if (mAttached && watched == viewport())
    1775     {
    1776         switch (e->type())
    1777         {
    1778             case QEvent::MouseMove:
    1779             case QEvent::MouseButtonPress:
    1780             case QEvent::MouseButtonDblClick:
    1781             case QEvent::MouseButtonRelease:
    1782             {
    1783                 QMouseEvent *me = (QMouseEvent *) e;
    1784                 m_iLastMouseWheelDelta = 0;
    1785                 if (mouseEvent (me->type(), me->pos(), me->globalPos(),
    1786                                 me->buttons(), me->modifiers(),
    1787                                 0, Qt::Horizontal))
    1788                     return true; /* stop further event handling */
    1789                 break;
    1790             }
    1791             case QEvent::Wheel:
    1792             {
    1793                 QWheelEvent *we = (QWheelEvent *) e;
    1794                 /* There are pointing devices which send smaller values for the
    1795                  * delta than 120. Here we sum them up until we are greater
    1796                  * than 120. This allows to have finer control over the speed
    1797                  * acceleration & enables such devices to send a valid wheel
    1798                  * event to our guest mouse device at all. */
    1799                 int iDelta = 0;
    1800                 m_iLastMouseWheelDelta += we->delta();
    1801                 if (qAbs(m_iLastMouseWheelDelta) >= 120)
    1802                 {
    1803                     iDelta = m_iLastMouseWheelDelta;
    1804                     m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
    1805                 }
    1806                 if (mouseEvent (we->type(), we->pos(), we->globalPos(),
    1807 #ifdef QT_MAC_USE_COCOA
    1808                                 /* Qt Cocoa is buggy. It always reports a left
    1809                                  * button pressed when the mouse wheel event
    1810                                  * occurs. A workaround is to ask the
    1811                                  * application which buttons are pressed
    1812                                  * currently. */
    1813                                 QApplication::mouseButtons(),
    1814 #else /* QT_MAC_USE_COCOA */
    1815                                 we->buttons(),
    1816 #endif /* QT_MAC_USE_COCOA */
    1817                                 we->modifiers(),
    1818                                 iDelta, we->orientation()))
    1819                     return true; /* stop further event handling */
    1820                 break;
    1821             }
    1822 #ifdef Q_WS_MAC
    1823             case QEvent::Leave:
    1824             {
    1825                 /* Enable mouse event compression if we leave the VM view. This
    1826                    is necessary for having smooth resizing of the VM/other
    1827                    windows. */
    1828                 setMouseCoalescingEnabled (true);
    1829                 break;
    1830             }
    1831             case QEvent::Enter:
    1832             {
    1833                 /* Disable mouse event compression if we enter the VM view. So
    1834                    all mouse events are registered in the VM. Only do this if
    1835                    the keyboard/mouse is grabbed (this is when we have a valid
    1836                    event handler). */
    1837                 setMouseCoalescingEnabled (false);
    1838                 break;
    1839             }
    1840 #endif /* Q_WS_MAC */
    1841             case QEvent::Resize:
    1842             {
    1843                 if (mMouseCaptured)
    1844                     updateMouseClipping();
    1845 #ifdef VBOX_WITH_VIDEOHWACCEL
    1846                 if (mFrameBuf)
    1847                 {
    1848                     mFrameBuf->viewportResized((QResizeEvent*)e);
    1849                 }
    1850 #endif
    1851                 break;
    1852             }
    1853             default:
    1854                 break;
    1855         }
    1856     }
    1857     else if (watched == mMainWnd)
    1858     {
    1859         switch (e->type())
    1860         {
    1861 #if defined (Q_WS_WIN32)
    1862 #if defined (VBOX_GUI_USE_DDRAW)
    1863             case QEvent::Move:
    1864             {
    1865                 /*
    1866                  *  notification from our parent that it has moved. We need this
    1867                  *  in order to possibly adjust the direct screen blitting.
    1868                  */
    1869                 if (mFrameBuf)
    1870                     mFrameBuf->moveEvent ((QMoveEvent *) e);
    1871                 break;
    1872             }
    1873 #endif
    1874             /*
    1875              *  install/uninstall low-level kbd hook on every
    1876              *  activation/deactivation to:
    1877              *  a) avoid excess hook calls when we're not active and
    1878              *  b) be always in front of any other possible hooks
    1879              */
    1880             case QEvent::WindowActivate:
    1881             {
    1882                 gKbdHook = SetWindowsHookEx (WH_KEYBOARD_LL, lowLevelKeyboardProc,
    1883                                               GetModuleHandle (NULL), 0);
    1884                 AssertMsg (gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));
    1885                 break;
    1886             }
    1887             case QEvent::WindowDeactivate:
    1888             {
    1889                 if (gKbdHook)
    1890                 {
    1891                     UnhookWindowsHookEx (gKbdHook);
    1892                     gKbdHook = NULL;
    1893                 }
    1894                 break;
    1895             }
    1896 #endif /* defined (Q_WS_WIN32) */
    1897 #if defined (Q_WS_MAC)
    1898             /*
    1899              *  Install/remove the keyboard event handler.
    1900              */
    1901             case QEvent::WindowActivate:
    1902                 darwinGrabKeyboardEvents (true);
    1903                 break;
    1904             case QEvent::WindowDeactivate:
    1905                 darwinGrabKeyboardEvents (false);
    1906                 break;
    1907 #endif /* defined (Q_WS_MAC) */
    1908             case QEvent::Resize:
    1909             {
    1910                 /* Set the "guest needs to resize" hint.  This hint is acted upon
    1911                  * when (and only when) the autoresize property is "true". */
    1912                 mDoResize = mGuestSupportsGraphics || mMainWnd->isTrueFullscreen();
    1913                 if (!mIgnoreMainwndResize &&
    1914                     mGuestSupportsGraphics && mAutoresizeGuest)
    1915                     QTimer::singleShot (300, this, SLOT (doResizeHint()));
    1916                 break;
    1917             }
    1918             case QEvent::WindowStateChange:
    1919             {
    1920                 /* During minimizing and state restoring mMainWnd gets the focus
    1921                  * which belongs to console view window, so returning it properly. */
    1922                 QWindowStateChangeEvent *ev = static_cast <QWindowStateChangeEvent*> (e);
    1923                 if (ev->oldState() & Qt::WindowMinimized)
    1924                 {
    1925                     if (QApplication::focusWidget())
    1926                     {
    1927                         QApplication::focusWidget()->clearFocus();
    1928                         qApp->processEvents();
    1929                     }
    1930                     QTimer::singleShot (0, this, SLOT (setFocus()));
    1931                 }
    1932                 break;
    1933             }
    1934 
    1935             default:
    1936                 break;
    1937         }
    1938     }
    1939     else if (watched == mMainWnd->menuBar())
    1940     {
    1941         /*
    1942          *  sometimes when we press ESC in the menu it brings the
    1943          *  focus away (Qt bug?) causing no widget to have a focus,
    1944          *  or holds the focus itself, instead of returning the focus
    1945          *  to the console window. here we fix this.
    1946          */
    1947         switch (e->type())
    1948         {
    1949             case QEvent::FocusOut:
    1950             {
    1951                 if (qApp->focusWidget() == 0)
    1952                     setFocus();
    1953                 break;
    1954             }
    1955             case QEvent::KeyPress:
    1956             {
    1957                 QKeyEvent *ke = (QKeyEvent *) e;
    1958                 if (ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier))
    1959                     if (mMainWnd->menuBar()->hasFocus())
    1960                         setFocus();
    1961                 break;
    1962             }
    1963             default:
    1964                 break;
    1965         }
    1966     }
    1967 
    1968     return QAbstractScrollArea::eventFilter (watched, e);
    1969 }
    1970 
    1971 #if defined(Q_WS_WIN32)
    1972 
    1973 /**
    1974  *  Low-level keyboard event handler,
    1975  *  @return
    1976  *      true to indicate that the message is processed and false otherwise
    1977  */
    1978 bool VBoxConsoleView::winLowKeyboardEvent (UINT msg, const KBDLLHOOKSTRUCT &event)
    1979 {
    1980 #if 0
    1981     LogFlow (("### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X (mKbdCaptured=%d)\n",
    1982               event.vkCode, event.scanCode, event.flags, event.dwExtraInfo, mKbdCaptured));
    1983     char buf [256];
    1984     sprintf (buf, "### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X",
    1985              event.vkCode, event.scanCode, event.flags, event.dwExtraInfo);
    1986     mMainWnd->statusBar()->message (buf);
    1987 #endif
    1988 
    1989     /* Sometimes it happens that Win inserts additional events on some key
    1990      * press/release. For example, it prepends ALT_GR in German layout with
    1991      * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
    1992      * to specially treat ALT_GR to enter additional chars to regular apps).
    1993      * These events are definitely unwanted in VM, so filter them out. */
    1994     /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
    1995      * code 0x23a. If this is not passed through then it is impossible to
    1996      * cancel CapsLock on a French keyboard.  I didn't find any other examples
    1997      * of these strange events.  Let's hope we are not missing anything else
    1998      * of importance! */
    1999     if (hasFocus() && (event.scanCode & ~0xFF))
    2000     {
    2001         if (event.vkCode == VK_CAPITAL)
    2002             return false;
    2003         else
    2004             return true;
    2005     }
    2006 
    2007     if (!mKbdCaptured)
    2008         return false;
    2009 
    2010     /* it's possible that a key has been pressed while the keyboard was not
    2011      * captured, but is being released under the capture. Detect this situation
    2012      * and return false to let Windows process the message normally and update
    2013      * its key state table (to avoid the stuck key effect). */
    2014     uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT)
    2015                            ? IsExtKeyPressed
    2016                            : IsKeyPressed;
    2017     if ((event.flags & 0x80) /* released */ &&
    2018         ((event.vkCode == gs.hostKey() && !hostkey_in_capture) ||
    2019          (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed))
    2020         return false;
    2021 
    2022     MSG message;
    2023     message.hwnd = winId();
    2024     message.message = msg;
    2025     message.wParam = event.vkCode;
    2026     message.lParam =
    2027         1 |
    2028         (event.scanCode & 0xFF) << 16 |
    2029         (event.flags & 0xFF) << 24;
    2030 
    2031     /* Windows sets here the extended bit when the Right Shift key is pressed,
    2032      * which is totally wrong. Undo it. */
    2033     if (event.vkCode == VK_RSHIFT)
    2034         message.lParam &= ~0x1000000;
    2035 
    2036     /* we suppose here that this hook is always called on the main GUI thread */
    2037     long dummyResult;
    2038     return winEvent (&message, &dummyResult);
    2039 }
    2040 
    2041 /**
    2042  * Get Win32 messages before they are passed to Qt. This allows us to get
    2043  * the keyboard events directly and bypass the harmful Qt translation. A
    2044  * return value of @c true indicates to Qt that the event has been handled.
    2045  */
    2046 bool VBoxConsoleView::winEvent (MSG *aMsg, long* /* aResult */)
    2047 {
    2048     if (!mAttached || ! (
    2049         aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN ||
    2050         aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP
    2051     ))
    2052         return false;
    2053 
    2054     /* check for the special flag possibly set at the end of this function */
    2055     if (aMsg->lParam & (0x1 << 25))
    2056     {
    2057         aMsg->lParam &= ~(0x1 << 25);
    2058         return false;
    2059     }
    2060 
    2061 #if 0
    2062     char buf [256];
    2063     sprintf (buf, "WM_%04X: vk=%04X rep=%05d scan=%02X ext=%01d rzv=%01X ctx=%01d prev=%01d tran=%01d",
    2064              aMsg->message, aMsg->wParam,
    2065              (aMsg->lParam & 0xFFFF),
    2066              ((aMsg->lParam >> 16) & 0xFF),
    2067              ((aMsg->lParam >> 24) & 0x1),
    2068              ((aMsg->lParam >> 25) & 0xF),
    2069              ((aMsg->lParam >> 29) & 0x1),
    2070              ((aMsg->lParam >> 30) & 0x1),
    2071              ((aMsg->lParam >> 31) & 0x1));
    2072     mMainWnd->statusBar()->message (buf);
    2073     LogFlow (("%s\n", buf));
    2074 #endif
    2075 
    2076     int scan = (aMsg->lParam >> 16) & 0x7F;
    2077     /* scancodes 0x80 and 0x00 are ignored */
    2078     if (!scan)
    2079         return true;
    2080 
    2081     int vkey = aMsg->wParam;
    2082 
    2083     /* When one of the SHIFT keys is held and one of the cursor movement
    2084      * keys is pressed, Windows duplicates SHIFT press/release messages,
    2085      * but with the virtual key code set to 0xFF. These virtual keys are also
    2086      * sent in some other situations (Pause, PrtScn, etc.). Ignore such
    2087      * messages. */
    2088     if (vkey == 0xFF)
    2089         return true;
    2090 
    2091     int flags = 0;
    2092     if (aMsg->lParam & 0x1000000)
    2093         flags |= KeyExtended;
    2094     if (!(aMsg->lParam & 0x80000000))
    2095         flags |= KeyPressed;
    2096 
    2097     switch (vkey)
    2098     {
    2099         case VK_SHIFT:
    2100         case VK_CONTROL:
    2101         case VK_MENU:
    2102         {
    2103             /* overcome stupid Win32 modifier key generalization */
    2104             int keyscan = scan;
    2105             if (flags & KeyExtended)
    2106                 keyscan |= 0xE000;
    2107             switch (keyscan)
    2108             {
    2109                 case 0x002A: vkey = VK_LSHIFT; break;
    2110                 case 0x0036: vkey = VK_RSHIFT; break;
    2111                 case 0x001D: vkey = VK_LCONTROL; break;
    2112                 case 0xE01D: vkey = VK_RCONTROL; break;
    2113                 case 0x0038: vkey = VK_LMENU; break;
    2114                 case 0xE038: vkey = VK_RMENU; break;
    2115             }
    2116             break;
    2117         }
    2118         case VK_NUMLOCK:
    2119             /* Win32 sets the extended bit for the NumLock key. Reset it. */
    2120             flags &= ~KeyExtended;
    2121             break;
    2122         case VK_SNAPSHOT:
    2123             flags |= KeyPrint;
    2124             break;
    2125         case VK_PAUSE:
    2126             flags |= KeyPause;
    2127             break;
    2128     }
    2129 
    2130     bool result = keyEvent (vkey, scan, flags);
    2131     if (!result && mKbdCaptured)
    2132     {
    2133         /* keyEvent() returned that it didn't process the message, but since the
    2134          * keyboard is captured, we don't want to pass it to Windows. We just want
    2135          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    2136          * shortcuts for example). So send it direcltly to the window with the
    2137          * special flag in the reserved area of lParam (to avoid recursion). */
    2138         ::SendMessage (aMsg->hwnd, aMsg->message,
    2139                        aMsg->wParam, aMsg->lParam | (0x1 << 25));
    2140         return true;
    2141     }
    2142 
    2143     /* These special keys have to be handled by Windows as well to update the
    2144      * internal modifier state and to enable/disable the keyboard LED */
    2145     if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT)
    2146         return false;
    2147 
    2148     return result;
    2149 }
    2150 
    2151 #elif defined (Q_WS_PM)
    2152 
    2153 /**
    2154  *  Get PM messages before they are passed to Qt. This allows us to get
    2155  *  the keyboard events directly and bypass the harmful Qt translation. A
    2156  *  return value of @c true indicates to Qt that the event has been handled.
    2157  */
    2158 bool VBoxConsoleView::pmEvent (QMSG *aMsg)
    2159 {
    2160     if (!mAttached)
    2161         return false;
    2162 
    2163     if (aMsg->msg == UM_PREACCEL_CHAR)
    2164     {
    2165         /* we are inside the input hook */
    2166 
    2167         /* let the message go through the normal system pipeline */
    2168         if (!mKbdCaptured)
    2169             return false;
    2170     }
    2171 
    2172     if (aMsg->msg != WM_CHAR &&
    2173         aMsg->msg != UM_PREACCEL_CHAR)
    2174         return false;
    2175 
    2176     /* check for the special flag possibly set at the end of this function */
    2177     if (SHORT2FROMMP (aMsg->mp2) & 0x8000)
    2178     {
    2179         aMsg->mp2 = MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2),
    2180                                   SHORT2FROMMP (aMsg->mp2) & ~0x8000);
    2181         return false;
    2182     }
    2183 
    2184 #if 0
    2185     {
    2186         char buf [256];
    2187         sprintf (buf, "*** %s: f=%04X rep=%03d scan=%02X ch=%04X vk=%04X",
    2188                  (aMsg->msg == WM_CHAR ? "WM_CHAR" : "UM_PREACCEL_CHAR"),
    2189                  SHORT1FROMMP (aMsg->mp1), CHAR3FROMMP (aMsg->mp1),
    2190                  CHAR4FROMMP (aMsg->mp1), SHORT1FROMMP (aMsg->mp2),
    2191                  SHORT2FROMMP (aMsg->mp2));
    2192         mMainWnd->statusBar()->message (buf);
    2193         LogFlow (("%s\n", buf));
    2194     }
    2195 #endif
    2196 
    2197     USHORT ch = SHORT1FROMMP (aMsg->mp2);
    2198     USHORT f = SHORT1FROMMP (aMsg->mp1);
    2199 
    2200     int scan = (unsigned int) CHAR4FROMMP (aMsg->mp1);
    2201     if (!scan || scan > 0x7F)
    2202         return true;
    2203 
    2204     int vkey = QIHotKeyEdit::virtualKey (aMsg);
    2205 
    2206     int flags = 0;
    2207 
    2208     if ((ch & 0xFF) == 0xE0)
    2209     {
    2210         flags |= KeyExtended;
    2211         scan = ch >> 8;
    2212     }
    2213     else if (scan == 0x5C && (ch & 0xFF) == '/')
    2214     {
    2215         /* this is the '/' key on the keypad */
    2216         scan = 0x35;
    2217         flags |= KeyExtended;
    2218     }
    2219     else
    2220     {
    2221         /* For some keys, the scan code passed in QMSG is a pseudo scan
    2222          * code. We replace it with a real hardware scan code, according to
    2223          * http://www.computer-engineering.org/ps2keyboard/scancodes1.html.
    2224          * Also detect Pause and PrtScn and set flags. */
    2225         switch (vkey)
    2226         {
    2227             case VK_ENTER:     scan = 0x1C; flags |= KeyExtended; break;
    2228             case VK_CTRL:      scan = 0x1D; flags |= KeyExtended; break;
    2229             case VK_ALTGRAF:   scan = 0x38; flags |= KeyExtended; break;
    2230             case VK_LWIN:      scan = 0x5B; flags |= KeyExtended; break;
    2231             case VK_RWIN:      scan = 0x5C; flags |= KeyExtended; break;
    2232             case VK_WINMENU:   scan = 0x5D; flags |= KeyExtended; break;
    2233             case VK_FORWARD:   scan = 0x69; flags |= KeyExtended; break;
    2234             case VK_BACKWARD:  scan = 0x6A; flags |= KeyExtended; break;
    2235 #if 0
    2236             /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully
    2237             // clear what is more correct
    2238             case VK_BREAK:     scan = 0x46; flags |= KeyExtended; break;
    2239 #else
    2240             case VK_BREAK:     scan = 0;    flags |= KeyPause; break;
    2241 #endif
    2242             case VK_PAUSE:     scan = 0;    flags |= KeyPause;    break;
    2243             case VK_PRINTSCRN: scan = 0;    flags |= KeyPrint;    break;
    2244             default:;
    2245         }
    2246     }
    2247 
    2248     if (!(f & KC_KEYUP))
    2249         flags |= KeyPressed;
    2250 
    2251     bool result = keyEvent (vkey, scan, flags);
    2252     if (!result && mKbdCaptured)
    2253     {
    2254         /* keyEvent() returned that it didn't process the message, but since the
    2255          * keyboard is captured, we don't want to pass it to PM. We just want
    2256          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    2257          * shortcuts for example). So send it direcltly to the window with the
    2258          * special flag in the reserved area of lParam (to avoid recursion). */
    2259         ::WinSendMsg (aMsg->hwnd, WM_CHAR,
    2260                       aMsg->mp1,
    2261                       MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2),
    2262                                     SHORT2FROMMP (aMsg->mp2) | 0x8000));
    2263         return true;
    2264     }
    2265     return result;
    2266 }
    2267 
    2268 #elif defined(Q_WS_X11)
    2269 
    2270 /**
    2271  * This function is a "predicate" for XCheckIfEvent().  It will check
    2272  * the XEvent passed to it to see if it is a keypress event matching
    2273  * the keyrelease event in @a pvArg.
    2274  * @returns True if the event matches, False otherwise
    2275  * @param   pEvent    the event to compare, taken from the event queue
    2276  * @param   pvArg     the keyrelease event we would like to compare against
    2277  */
    2278 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent,
    2279                                      XPointer pvArg)
    2280 {
    2281     XEvent *pKeyEvent = (XEvent *) pvArg;
    2282     if ((pEvent->type == XKeyPress) &&
    2283         (pEvent->xkey.keycode == pKeyEvent->xkey.keycode))
    2284         return True;
    2285     else
    2286         return False;
    2287 }
    2288 
    2289 /**
    2290  *  This routine gets X11 events before they are processed by Qt. This is
    2291  *  used for our platform specific keyboard implementation. A return value
    2292  *  of TRUE indicates that the event has been processed by us.
    2293  */
    2294 bool VBoxConsoleView::x11Event (XEvent *event)
    2295 {
    2296     switch (event->type)
    2297     {
    2298         /* We have to handle XFocusOut right here as this event is not passed
    2299          * to VBoxConsoleView::event(). Handling this event is important for
    2300          * releasing the keyboard before the screen saver gets active. */
    2301         case XFocusOut:
    2302         case XFocusIn:
    2303             if (isRunning())
    2304                 focusEvent (event->type == XFocusIn);
    2305             return false;
    2306         case XKeyPress:
    2307         case XKeyRelease:
    2308             if (mAttached)
    2309                 break;
    2310             /*  else fall through */
    2311         default:
    2312             return false; /* pass the event to Qt */
    2313     }
    2314 
    2315     /* Translate the keycode to a PC scan code. */
    2316     unsigned scan = handleXKeyEvent (event);
    2317 
    2318 #if 0
    2319     char buf [256];
    2320     sprintf (buf, "pr=%d kc=%08X st=%08X extended=%s scan=%04X",
    2321              event->type == XKeyPress ? 1 : 0, event->xkey.keycode,
    2322              event->xkey.state, scan >> 8 ? "true" : "false", scan & 0x7F);
    2323     mMainWnd->statusBar()->message (buf);
    2324     LogFlow (("### %s\n", buf));
    2325 #endif
    2326 
    2327     // scancodes 0x00 (no valid translation) and 0x80 are ignored
    2328     if (!scan & 0x7F)
    2329         return true;
    2330 
    2331     /* Fix for http://www.virtualbox.org/ticket/1296:
    2332      * when X11 sends events for repeated keys, it always inserts an
    2333      * XKeyRelease before the XKeyPress. */
    2334     XEvent returnEvent;
    2335     if ((event->type == XKeyRelease) &&
    2336         (XCheckIfEvent(event->xkey.display, &returnEvent,
    2337                        VBoxConsoleViewCompEvent, (XPointer) event) == True)) {
    2338         XPutBackEvent(event->xkey.display, &returnEvent);
    2339         /* Discard it, don't pass it to Qt. */
    2340         return true;
    2341     }
    2342 
    2343     KeySym ks = ::XKeycodeToKeysym (event->xkey.display, event->xkey.keycode, 0);
    2344 
    2345     int flags = 0;
    2346     if (scan >> 8)
    2347         flags |= KeyExtended;
    2348     if (event->type == XKeyPress)
    2349         flags |= KeyPressed;
    2350 
    2351     /* Remove the extended flag */
    2352     scan &= 0x7F;
    2353 
    2354     switch (ks)
    2355     {
    2356         case XK_Print:
    2357             flags |= KeyPrint;
    2358             break;
    2359         case XK_Pause:
    2360             if (event->xkey.state & ControlMask) /* Break */
    2361             {
    2362                 ks = XK_Break;
    2363                 flags |= KeyExtended;
    2364                 scan = 0x46;
    2365             }
    2366             else
    2367                 flags |= KeyPause;
    2368             break;
    2369     }
    2370 
    2371     return keyEvent (ks, scan, flags);
    2372 }
    2373 
    2374 #elif defined (Q_WS_MAC)
    2375 
    2376 /**
    2377  *  Invoked by VBoxConsoleView::darwinEventHandlerProc / VBoxConsoleView::macEventFilter when
    2378  *  it receives a raw keyboard event.
    2379  *
    2380  *  @param pvCocoaEvent The Cocoa keyboard event. Can be NULL in some configs.
    2381  *  @param inEvent      The keyboard event.
    2382  *
    2383  *  @return true if the key was processed, false if it wasn't processed and should be passed on.
    2384  */
    2385 bool VBoxConsoleView::darwinKeyboardEvent (const void *pvCocoaEvent, EventRef inEvent)
    2386 {
    2387     bool ret = false;
    2388     UInt32 EventKind = ::GetEventKind (inEvent);
    2389     if (EventKind != kEventRawKeyModifiersChanged)
    2390     {
    2391         /* convert keycode to set 1 scan code. */
    2392         UInt32 keyCode = ~0U;
    2393         ::GetEventParameter (inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
    2394         /* The usb keyboard driver translates these codes to different virtual
    2395          * key codes depending of the keyboard type. There are ANSI, ISO, JIS
    2396          * and unknown. For European keyboards (ISO) the key 0xa and 0x32 have
    2397          * to be switched. Here we are doing this at runtime, cause the user
    2398          * can have more than one keyboard (of different type), where he may
    2399          * switch at will all the time. Default is the ANSI standard as defined
    2400          * in g_aDarwinToSet1. */
    2401         if (   (keyCode == 0xa || keyCode == 0x32)
    2402             && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO)
    2403             keyCode = 0x3c - keyCode;
    2404         unsigned scanCode = ::DarwinKeycodeToSet1Scancode (keyCode);
    2405         if (scanCode)
    2406         {
    2407             /* calc flags. */
    2408             int flags = 0;
    2409             if (EventKind != kEventRawKeyUp)
    2410                 flags |= KeyPressed;
    2411             if (scanCode & VBOXKEY_EXTENDED)
    2412                 flags |= KeyExtended;
    2413             /** @todo KeyPause, KeyPrint. */
    2414             scanCode &= VBOXKEY_SCANCODE_MASK;
    2415 
    2416             /* get the unicode string (if present). */
    2417             AssertCompileSize (wchar_t, 2);
    2418             AssertCompileSize (UniChar, 2);
    2419             ByteCount cbWritten = 0;
    2420             wchar_t ucs[8];
    2421             if (::GetEventParameter (inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL,
    2422                                      sizeof (ucs), &cbWritten, &ucs[0]) != 0)
    2423                 cbWritten = 0;
    2424             ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */
    2425 
    2426             ret = keyEvent (keyCode, scanCode, flags, ucs[0] ? ucs : NULL);
    2427         }
    2428     }
    2429     else
    2430     {
    2431         /* May contain multiple modifier changes, kind of annoying. */
    2432         UInt32 newMask = 0;
    2433         ::GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
    2434                              sizeof (newMask), NULL, &newMask);
    2435         newMask = ::DarwinAdjustModifierMask (newMask, pvCocoaEvent);
    2436         UInt32 changed = newMask ^ mDarwinKeyModifiers;
    2437         if (changed)
    2438         {
    2439             for (UInt32 bit = 0; bit < 32; bit++)
    2440             {
    2441                 if (!(changed & (1 << bit)))
    2442                     continue;
    2443                 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode (1 << bit);
    2444                 if (!scanCode)
    2445                     continue;
    2446                 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode (1 << bit);
    2447                 Assert (keyCode);
    2448 
    2449                 if (!(scanCode & VBOXKEY_LOCK))
    2450                 {
    2451                     unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0;
    2452                     if (scanCode & VBOXKEY_EXTENDED)
    2453                         flags |= KeyExtended;
    2454                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2455                     ret |= keyEvent (keyCode, scanCode & 0xff, flags);
     572                    CMouse mouse = m_console.GetMouse();
     573                    mouse.PutMouseEventAbsolute (-1, -1, 0,
     574                                                 0 /* Horizontal wheel */,
     575                                                 0);
     576                    captureMouse (false, false);
    2456577                }
    2457578                else
    2458                 {
    2459                     unsigned flags = 0;
    2460                     if (scanCode & VBOXKEY_EXTENDED)
    2461                         flags |= KeyExtended;
    2462                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2463                     keyEvent (keyCode, scanCode, flags | KeyPressed);
    2464                     keyEvent (keyCode, scanCode, flags);
    2465                 }
     579                    viewport()->unsetCursor();
     580                emitMouseStateChanged();
     581                vboxProblem().remindAboutMouseIntegration (m_bIsMouseAbsolute);
    2466582            }
    2467         }
    2468 
    2469         mDarwinKeyModifiers = newMask;
    2470 
    2471         /* Always return true here because we'll otherwise getting a Qt event
    2472            we don't want and that will only cause the Pause warning to pop up. */
    2473         ret = true;
    2474     }
    2475 
    2476     return ret;
    2477 }
    2478 
    2479 
    2480 /**
    2481  * Installs or removes the keyboard event handler.
    2482  *
    2483  * @param   fGrab    True if we're to grab the events, false if we're not to.
    2484  */
    2485 void VBoxConsoleView::darwinGrabKeyboardEvents (bool fGrab)
    2486 {
    2487     mKeyboardGrabbed = fGrab;
    2488     if (fGrab)
    2489     {
    2490         /* Disable mouse and keyboard event compression/delaying to make sure
    2491            we *really* get all of the events. */
    2492         ::CGSetLocalEventsSuppressionInterval (0.0);
    2493         setMouseCoalescingEnabled (false);
    2494 
    2495         /* Register the event callback/hook and grab the keyboard. */
    2496 # ifdef QT_MAC_USE_COCOA
    2497         ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */
    2498                                             VBoxConsoleView::darwinEventHandlerProc, this);
    2499 
    2500 # elif !defined (VBOX_WITH_HACKED_QT)
    2501         EventTypeSpec eventTypes[6];
    2502         eventTypes[0].eventClass = kEventClassKeyboard;
    2503         eventTypes[0].eventKind  = kEventRawKeyDown;
    2504         eventTypes[1].eventClass = kEventClassKeyboard;
    2505         eventTypes[1].eventKind  = kEventRawKeyUp;
    2506         eventTypes[2].eventClass = kEventClassKeyboard;
    2507         eventTypes[2].eventKind  = kEventRawKeyRepeat;
    2508         eventTypes[3].eventClass = kEventClassKeyboard;
    2509         eventTypes[3].eventKind  = kEventRawKeyModifiersChanged;
    2510         /* For ignorning Command-H and Command-Q which aren't affected by the
    2511          * global hotkey stuff (doesn't work well): */
    2512         eventTypes[4].eventClass = kEventClassCommand;
    2513         eventTypes[4].eventKind  = kEventCommandProcess;
    2514         eventTypes[5].eventClass = kEventClassCommand;
    2515         eventTypes[5].eventKind  = kEventCommandUpdateStatus;
    2516 
    2517         EventHandlerUPP eventHandler = ::NewEventHandlerUPP (VBoxConsoleView::darwinEventHandlerProc);
    2518 
    2519         mDarwinEventHandlerRef = NULL;
    2520         ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
    2521                                           this, &mDarwinEventHandlerRef);
    2522         ::DisposeEventHandlerUPP (eventHandler);
    2523 
    2524 # else  /* VBOX_WITH_HACKED_QT */
    2525         ((QIApplication *)qApp)->setEventFilter (VBoxConsoleView::macEventFilter, this);
    2526 # endif /* VBOX_WITH_HACKED_QT */
    2527 
    2528         ::DarwinGrabKeyboard (false);
    2529     }
    2530     else
    2531     {
    2532         ::DarwinReleaseKeyboard();
    2533 # ifdef QT_MAC_USE_COCOA
    2534         ::VBoxCocoaApplication_unsetCallback (UINT32_MAX, /** @todo fix mask */
    2535                                               VBoxConsoleView::darwinEventHandlerProc, this);
    2536 # elif !defined(VBOX_WITH_HACKED_QT)
    2537         if (mDarwinEventHandlerRef)
    2538         {
    2539             ::RemoveEventHandler (mDarwinEventHandlerRef);
    2540             mDarwinEventHandlerRef = NULL;
    2541         }
    2542 # else  /* VBOX_WITH_HACKED_QT */
    2543         ((QIApplication *)qApp)->setEventFilter (NULL, NULL);
    2544 # endif /* VBOX_WITH_HACKED_QT */
    2545     }
    2546 }
    2547 
    2548 #endif // defined (Q_WS_MAC)
    2549 
    2550 //
    2551 // Private members
    2552 /////////////////////////////////////////////////////////////////////////////
    2553 
    2554 /**
    2555  *  Called on every focus change and also to forcibly capture/uncapture the
    2556  *  input in situations similar to gaining or losing focus.
    2557  *
    2558  *  @param aHasFocus        true if the window got focus and false otherwise.
    2559  *  @param aReleaseHostKey  true to release the host key (used only when
    2560  *                          @a aHasFocus is false.
    2561  */
    2562 void VBoxConsoleView::focusEvent (bool aHasFocus,
    2563                                   bool aReleaseHostKey /* = true */)
    2564 {
    2565     if (aHasFocus)
    2566     {
    2567 #ifdef RT_OS_WINDOWS
    2568         if (   !mDisableAutoCapture && gs.autoCapture()
    2569             && GetAncestor (winId(), GA_ROOT) == GetForegroundWindow())
    2570 #else
    2571         if (!mDisableAutoCapture && gs.autoCapture())
    2572 #endif /* RT_OS_WINDOWS */
    2573         {
    2574             captureKbd (true);
    2575 /// @todo (dmik)
    2576 //      the below is for the mouse auto-capture. disabled for now. in order to
    2577 //      properly support it, we need to know when *all* mouse buttons are
    2578 //      released after we got focus, and grab the mouse only after then.
    2579 //      btw, the similar would be good the for keyboard auto-capture, too.
    2580 //            if (!(mMouseAbsolute && mMouseIntegration))
    2581 //                captureMouse (true);
    2582         }
    2583 
    2584         /* reset the single-time disable capture flag */
    2585         if (mDisableAutoCapture)
    2586             mDisableAutoCapture = false;
    2587     }
    2588     else
    2589     {
    2590         captureMouse (false);
    2591         captureKbd (false, false);
    2592         releaseAllPressedKeys (aReleaseHostKey);
    2593     }
    2594 }
    2595 
    2596 /**
    2597  *  Synchronize the views of the host and the guest to the modifier keys.
    2598  *  This function will add up to 6 additional keycodes to codes.
    2599  *
    2600  *  @param  codes  pointer to keycodes which are sent to the keyboard
    2601  *  @param  count  pointer to the keycodes counter
    2602  */
    2603 void VBoxConsoleView::fixModifierState (LONG *codes, uint *count)
    2604 {
    2605 #if defined(Q_WS_X11)
    2606 
    2607     Window   wDummy1, wDummy2;
    2608     int      iDummy3, iDummy4, iDummy5, iDummy6;
    2609     unsigned uMask;
    2610     unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0;
    2611 
    2612     uKeyMaskCaps          = LockMask;
    2613     XModifierKeymap* map  = XGetModifierMapping(QX11Info::display());
    2614     KeyCode keyCodeNum    = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock);
    2615     KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock);
    2616 
    2617     for (int i = 0; i < 8; i++)
    2618     {
    2619         if (   keyCodeNum != NoSymbol
    2620             && map->modifiermap[map->max_keypermod * i] == keyCodeNum)
    2621             uKeyMaskNum    = 1 << i;
    2622         else if (   keyCodeScroll != NoSymbol
    2623                  && map->modifiermap[map->max_keypermod * i] == keyCodeScroll)
    2624             uKeyMaskScroll = 1 << i;
    2625     }
    2626     XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2,
    2627                   &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask);
    2628     XFreeModifiermap(map);
    2629 
    2630     if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum)))
    2631     {
    2632         muNumLockAdaptionCnt--;
    2633         codes[(*count)++] = 0x45;
    2634         codes[(*count)++] = 0x45 | 0x80;
    2635     }
    2636     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps)))
    2637     {
    2638         muCapsLockAdaptionCnt--;
    2639         codes[(*count)++] = 0x3a;
    2640         codes[(*count)++] = 0x3a | 0x80;
    2641         /* Some keyboard layouts require shift to be pressed to break
    2642          * capslock.  For simplicity, only do this if shift is not
    2643          * already held down. */
    2644         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2645         {
    2646             codes[(*count)++] = 0x2a;
    2647             codes[(*count)++] = 0x2a | 0x80;
    2648         }
    2649     }
    2650 
    2651 #elif defined(Q_WS_WIN32)
    2652 
    2653     if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK))))
    2654     {
    2655         muNumLockAdaptionCnt--;
    2656         codes[(*count)++] = 0x45;
    2657         codes[(*count)++] = 0x45 | 0x80;
    2658     }
    2659     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL))))
    2660     {
    2661         muCapsLockAdaptionCnt--;
    2662         codes[(*count)++] = 0x3a;
    2663         codes[(*count)++] = 0x3a | 0x80;
    2664         /* Some keyboard layouts require shift to be pressed to break
    2665          * capslock.  For simplicity, only do this if shift is not
    2666          * already held down. */
    2667         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2668         {
    2669             codes[(*count)++] = 0x2a;
    2670             codes[(*count)++] = 0x2a | 0x80;
    2671         }
    2672     }
    2673 
    2674 #elif defined (Q_WS_MAC)
    2675 
    2676     /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */
    2677     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
    2678     {
    2679         muCapsLockAdaptionCnt--;
    2680         codes[(*count)++] = 0x3a;
    2681         codes[(*count)++] = 0x3a | 0x80;
    2682         /* Some keyboard layouts require shift to be pressed to break
    2683          * capslock.  For simplicity, only do this if shift is not
    2684          * already held down. */
    2685         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2686         {
    2687             codes[(*count)++] = 0x2a;
    2688             codes[(*count)++] = 0x2a | 0x80;
    2689         }
    2690     }
    2691 
    2692 #else
    2693 
    2694 //#warning Adapt VBoxConsoleView::fixModifierState
    2695 
    2696 #endif
    2697 
    2698 
    2699 }
    2700 
    2701 /**
    2702  *  Called on enter/exit seamless/fullscreen mode.
    2703  */
    2704 void VBoxConsoleView::toggleFSMode (const QSize &aSize)
    2705 {
    2706     if ((mGuestSupportsGraphics && mAutoresizeGuest) ||
    2707         mMainWnd->isTrueSeamless() ||
    2708         mMainWnd->isTrueFullscreen())
    2709     {
    2710         QSize newSize;
    2711         if (aSize.isValid())
    2712         {
    2713             mNormalSize = aSize;
    2714             newSize = maximumSize();
    2715         }
    2716         else
    2717             newSize = mNormalSize;
    2718         doResizeHint (newSize);
    2719     }
    2720 
    2721     /* Reactivate the console window to preserve the focus position.
    2722      * Else focus will move to the mini-tool-bar. */
    2723     activateWindow();
    2724 }
    2725 
    2726 /**
    2727  * Get the current available desktop geometry for the console/framebuffer
    2728  *
    2729  * @returns the geometry.  An empty rectangle means unrestricted.
    2730  */
    2731 QRect VBoxConsoleView::desktopGeometry()
    2732 {
    2733     QRect rc;
    2734     switch (mDesktopGeo)
    2735     {
    2736         case DesktopGeo_Fixed:
    2737         case DesktopGeo_Automatic:
    2738             rc = QRect (0, 0,
    2739                         RT_MAX (mDesktopGeometry.width(), mStoredConsoleSize.width()),
    2740                         RT_MAX (mDesktopGeometry.height(), mStoredConsoleSize.height()));
    2741             break;
    2742         case DesktopGeo_Any:
    2743             rc = QRect (0, 0, 0, 0);
    2744             break;
    2745         default:
    2746             AssertMsgFailed (("Bad geometry type %d\n", mDesktopGeo));
    2747     }
    2748     return rc;
    2749 }
    2750 
    2751 QRegion VBoxConsoleView::lastVisibleRegion() const
    2752 {
    2753     return mLastVisibleRegion;
    2754 }
    2755 
    2756 bool VBoxConsoleView::isAutoresizeGuestActive()
    2757 {
    2758     return mGuestSupportsGraphics && mAutoresizeGuest;
    2759 }
    2760 
    2761 /**
    2762  *  Called on every key press and release (while in focus).
    2763  *
    2764  *  @param aKey        virtual scan code (virtual key on Win32 and KeySym on X11)
    2765  *  @param aScan       hardware scan code
    2766  *  @param aFlags      flags, a combination of Key* constants
    2767  *  @param aUniKey     Unicode translation of the key. Optional.
    2768  *
    2769  *  @return     true to consume the event and false to pass it to Qt
    2770  */
    2771 bool VBoxConsoleView::keyEvent (int aKey, uint8_t aScan, int aFlags,
    2772                                 wchar_t *aUniKey/* = NULL*/)
    2773 {
     583            if (me->needsHostCursor())
     584                setMouseIntegrationLocked (false);
     585            else
     586                setMouseIntegrationLocked (true);
     587            return true;
     588#endif
     589            UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent);
     590            emit sigMouseCapabilityChange(pConsoleEvent->supportsAbsolute(), pConsoleEvent->needsHostCursor());
     591            return true;
     592        }
     593
     594        case UIConsoleEventType_KeyboardLedsChange:
     595        {
     596#if 0 // TODO: Move to machine view!
     597            ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )pEvent;
     598            if (me->numLock() != mNumLock)
     599                muNumLockAdaptionCnt = 2;
     600            if (me->capsLock() != mCapsLock)
     601                muCapsLockAdaptionCnt = 2;
     602            mNumLock    = me->numLock();
     603            mCapsLock   = me->capsLock();
     604            mScrollLock = me->scrollLock();
     605#endif
     606            UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent);
     607            emit sigKeyboardLedsChange(pConsoleEvent->numLock(), pConsoleEvent->capsLock(), pConsoleEvent->scrollLock());
     608            return true;
     609        }
     610
     611        case UIConsoleEventType_StateChange:
     612        {
     613#if 0 // TODO: Move to machine view!
     614            MachineUIStateChangeEvent *me = (MachineUIStateChangeEvent *) pEvent;
     615            LogFlowFunc (("MachineUIStateChangeEventType: state=%d\n",
     616                           me->machineState()));
     617            onStateChange (me->machineState());
     618            emit machineStateChanged (me->machineState());
     619#endif
     620            UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent);
     621            emit sigStateChange(pConsoleEvent->machineState());
     622            return true;
     623        }
     624
     625        case UIConsoleEventType_AdditionsStateChange:
     626        {
     627#if 0 // TODO: Move to machine view!
     628            GuestAdditionsChangeEvent *ge = (GuestAdditionsChangeEvent *) pEvent;
     629            LogFlowFunc (("UIAdditionsStateChangeEventType\n"));
     630            /* Always send a size hint if we are in fullscreen or seamless
     631             * when the graphics capability is enabled, in case the host
     632             * resolution has changed since the VM was last run. */
    2774633#if 0
    2775     {
    2776         char buf [256];
    2777         sprintf (buf, "aKey=%08X aScan=%02X aFlags=%08X",
    2778                  aKey, aScan, aFlags);
    2779         mMainWnd->statusBar()->message (buf);
    2780     }
    2781 #endif
    2782 
    2783     const bool isHostKey = aKey == gs.hostKey();
    2784 
    2785     LONG buf [16];
    2786     LONG *codes = buf;
    2787     uint count = 0;
    2788     uint8_t whatPressed = 0;
    2789 
    2790     if (!isHostKey && !mIsHostkeyPressed)
    2791     {
    2792         if (aFlags & KeyPrint)
    2793         {
    2794             static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 };
    2795             static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA };
    2796             if (aFlags & KeyPressed)
     634            if (!mDoResize && !m_bIsGuestSupportsGraphics &&
     635                ge->supportsGraphics() &&
     636                (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))
     637                mDoResize = true;
     638#endif
     639            m_bIsGuestSupportsGraphics = ge->supportsGraphics();
     640
     641            maybeRestrictMinimumSize();
     642
     643#if 0
     644            /* This will only be acted upon if mDoResize is true. */
     645            doResizeHint();
     646#endif
     647
     648            emit additionsStateChanged (ge->additionVersion(),
     649                                        ge->additionActive(),
     650                                        ge->supportsSeamless(),
     651                                        ge->supportsGraphics());
     652#endif
     653            emit sigAdditionsStateChange();
     654            return true;
     655        }
     656
     657        case UIConsoleEventType_NetworkAdapterChange:
     658        {
     659#if 0 // TODO: Move to machine view!
     660            /* no specific adapter information stored in this
     661             * event is currently used */
     662            emit networkStateChange();
     663#endif
     664            UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent);
     665            emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter());
     666            return true;
     667        }
     668
     669        case UIConsoleEventType_SerialPortChange:
     670        {
     671            UISerialPortChangeEvent *pConsoleEvent = static_cast<UISerialPortChangeEvent*>(pEvent);
     672            emit sigSerialPortChange(pConsoleEvent->serialPort());
     673            return true;
     674        }
     675
     676        case UIConsoleEventType_ParallelPortChange:
     677        {
     678            UIParallelPortChangeEvent *pConsoleEvent = static_cast<UIParallelPortChangeEvent*>(pEvent);
     679            emit sigParallelPortChange(pConsoleEvent->parallelPort());
     680            return true;
     681        }
     682
     683        case UIConsoleEventType_StorageControllerChange:
     684        {
     685            emit sigStorageControllerChange();
     686            return true;
     687        }
     688
     689        case UIConsoleEventType_MediumChange:
     690        {
     691#if 0 // TODO: Move to machine view!
     692            MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) pEvent;
     693            LogFlowFunc (("MediaChangeEvent\n"));
     694
     695            emit mediaDriveChanged (mce->type());
     696#endif
     697            UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent);
     698            emit sigMediumChange(pConsoleEvent->mediumAttahment());
     699            return true;
     700        }
     701
     702        case UIConsoleEventType_CPUChange:
     703        {
     704            UICPUChangeEvent *pConsoleEvent = static_cast<UICPUChangeEvent*>(pEvent);
     705            emit sigCPUChange(pConsoleEvent->cpu(), pConsoleEvent->remove());
     706            return true;
     707        }
     708
     709        case UIConsoleEventType_VRDPServerChange:
     710        {
     711            emit sigVRDPServerChange();
     712            return true;
     713        }
     714
     715        case UIConsoleEventType_RemoteDisplayInfoChange:
     716        {
     717            emit sigRemoteDisplayInfoChange();
     718            return true;
     719        }
     720
     721        case UIConsoleEventType_USBControllerChange:
     722        {
     723            emit sigUSBControllerChange();
     724            return true;
     725        }
     726
     727        case UIConsoleEventType_USBDeviceStateChange:
     728        {
     729#if 0 // TODO: Move to machine view!
     730            UIUSBDeviceUIStateChangeEvent *ue = (UIUSBDeviceUIStateChangeEvent *)pEvent;
     731
     732            bool success = ue->error().isNull();
     733
     734            if (!success)
    2797735            {
    2798                 codes = PrintMake;
    2799                 count = SIZEOF_ARRAY (PrintMake);
     736                if (ue->attached())
     737                    vboxProblem().cannotAttachUSBDevice (
     738                        m_console,
     739                        vboxGlobal().details (ue->device()), ue->error());
     740                else
     741                    vboxProblem().cannotDetachUSBDevice (
     742                        m_console,
     743                        vboxGlobal().details (ue->device()), ue->error());
    2800744            }
    2801             else
    2802             {
    2803                 codes = PrintBreak;
    2804                 count = SIZEOF_ARRAY (PrintBreak);
    2805             }
    2806         }
    2807         else if (aFlags & KeyPause)
    2808         {
    2809             if (aFlags & KeyPressed)
    2810             {
    2811                 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 };
    2812                 codes = Pause;
    2813                 count = SIZEOF_ARRAY (Pause);
    2814             }
    2815             else
    2816             {
    2817                 /* Pause shall not produce a break code */
    2818                 return true;
    2819             }
    2820         }
    2821         else
    2822         {
    2823             if (aFlags & KeyPressed)
    2824             {
    2825                 /* Check if the guest has the same view on the modifier keys (NumLock,
    2826                  * CapsLock, ScrollLock) as the X server. If not, send KeyPress events
    2827                  * to synchronize the state. */
    2828                 fixModifierState (codes, &count);
    2829             }
    2830 
    2831             /* Check if it's C-A-D and GUI/PassCAD is not true */
    2832             if (!mPassCAD &&
    2833                 aScan == 0x53 /* Del */ &&
    2834                 ((mPressedKeys [0x38] & IsKeyPressed) /* Alt */ ||
    2835                  (mPressedKeys [0x38] & IsExtKeyPressed)) &&
    2836                 ((mPressedKeys [0x1d] & IsKeyPressed) /* Ctrl */ ||
    2837                  (mPressedKeys [0x1d] & IsExtKeyPressed)))
    2838             {
    2839                 /* Use the C-A-D combination as a last resort to get the
    2840                  * keyboard and mouse back to the host when the user forgets
    2841                  * the Host Key. Note that it's always possible to send C-A-D
    2842                  * to the guest using the Host+Del combination. BTW, it would
    2843                  * be preferrable to completely ignore C-A-D in guests, but
    2844                  * that's not possible because we cannot predict what other
    2845                  * keys will be pressed next when one of C, A, D is held. */
    2846 
    2847                 if (isRunning() && mKbdCaptured)
    2848                 {
    2849                     captureKbd (false);
    2850                     if (!(mMouseAbsolute && mMouseIntegration))
    2851                         captureMouse (false);
    2852                 }
    2853 
    2854                 return true;
    2855             }
    2856 
    2857             /* process the scancode and update the table of pressed keys */
    2858             whatPressed = IsKeyPressed;
    2859 
    2860             if (aFlags & KeyExtended)
    2861             {
    2862                 codes [count++] = 0xE0;
    2863                 whatPressed = IsExtKeyPressed;
    2864             }
    2865 
    2866             if (aFlags & KeyPressed)
    2867             {
    2868                 codes [count++] = aScan;
    2869                 mPressedKeys [aScan] |= whatPressed;
    2870             }
    2871             else
    2872             {
    2873                 /* if we haven't got this key's press message, we ignore its
    2874                  * release */
    2875                 if (!(mPressedKeys [aScan] & whatPressed))
    2876                     return true;
    2877                 codes [count++] = aScan | 0x80;
    2878                 mPressedKeys [aScan] &= ~whatPressed;
    2879             }
    2880 
    2881             if (mKbdCaptured)
    2882                 mPressedKeys [aScan] |= IsKbdCaptured;
    2883             else
    2884                 mPressedKeys [aScan] &= ~IsKbdCaptured;
    2885         }
    2886     }
    2887     else
    2888     {
    2889         /* currently this is used in winLowKeyboardEvent() only */
    2890         hostkey_in_capture = mKbdCaptured;
    2891     }
    2892 
    2893     bool emitSignal = false;
    2894     int hotkey = 0;
    2895 
    2896     /* process the host key */
    2897     if (aFlags & KeyPressed)
    2898     {
    2899         if (isHostKey)
    2900         {
    2901             if (!mIsHostkeyPressed)
    2902             {
    2903                 mIsHostkeyPressed = mIsHostkeyAlone = true;
    2904                 if (isRunning())
    2905                     saveKeyStates();
    2906                 emitSignal = true;
    2907             }
    2908         }
    2909         else
    2910         {
    2911             if (mIsHostkeyPressed)
    2912             {
    2913                 if (mIsHostkeyAlone)
    2914                 {
    2915                     hotkey = aKey;
    2916                     mIsHostkeyAlone = false;
    2917                 }
    2918             }
    2919         }
    2920     }
    2921     else
    2922     {
    2923         if (isHostKey)
    2924         {
    2925             if (mIsHostkeyPressed)
    2926             {
    2927                 mIsHostkeyPressed = false;
    2928 
    2929                 if (mIsHostkeyAlone)
    2930                 {
    2931                     if (isPaused())
    2932                     {
    2933                         vboxProblem().remindAboutPausedVMInput();
    2934                     }
    2935                     else
    2936                     if (isRunning())
    2937                     {
    2938                         bool captured = mKbdCaptured;
    2939                         bool ok = true;
    2940                         if (!captured)
    2941                         {
    2942                             /* temporarily disable auto capture that will take
    2943                              * place after this dialog is dismissed because
    2944                              * the capture state is to be defined by the
    2945                              * dialog result itself */
    2946                             mDisableAutoCapture = true;
    2947                             bool autoConfirmed = false;
    2948                             ok = vboxProblem().confirmInputCapture (&autoConfirmed);
    2949                             if (autoConfirmed)
    2950                                 mDisableAutoCapture = false;
    2951                             /* otherwise, the disable flag will be reset in
    2952                              * the next console view's foucs in event (since
    2953                              * may happen asynchronously on some platforms,
    2954                              * after we return from this code) */
    2955                         }
    2956 
    2957                         if (ok)
    2958                         {
    2959                             captureKbd (!captured, false);
    2960                             if (!(mMouseAbsolute && mMouseIntegration))
    2961                             {
    2962 #ifdef Q_WS_X11
    2963                                 /* make sure that pending FocusOut events from the
    2964                                  * previous message box are handled, otherwise the
    2965                                  * mouse is immediately ungrabbed. */
    2966                                 qApp->processEvents();
    2967 #endif
    2968                                 captureMouse (mKbdCaptured);
    2969                             }
    2970                         }
    2971                     }
    2972                 }
    2973 
    2974                 if (isRunning())
    2975                     sendChangedKeyStates();
    2976 
    2977                 emitSignal = true;
    2978             }
    2979         }
    2980         else
    2981         {
    2982             if (mIsHostkeyPressed)
    2983                 mIsHostkeyAlone = false;
    2984         }
    2985     }
    2986 
    2987     /* emit the keyboard state change signal */
    2988     if (emitSignal)
    2989         emitKeyboardStateChanged();
    2990 
    2991     /* Process Host+<key> shortcuts. currently, <key> is limited to
    2992      * alphanumeric chars. Other Host+<key> combinations are handled in
    2993      * event(). */
    2994     if (hotkey)
    2995     {
    2996         bool processed = false;
    2997 #if defined (Q_WS_WIN32)
    2998         NOREF(aUniKey);
    2999         int n = GetKeyboardLayoutList (0, NULL);
    3000         Assert (n);
    3001         HKL *list = new HKL [n];
    3002         GetKeyboardLayoutList (n, list);
    3003         for (int i = 0; i < n && !processed; i++)
    3004         {
    3005             wchar_t ch;
    3006             static BYTE keys [256] = {0};
    3007             if (!ToUnicodeEx (hotkey, 0, keys, &ch, 1, 0, list [i]) == 1)
    3008                 ch = 0;
    3009             if (ch)
    3010                 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3011                                                 QChar (ch).toUpper().unicode()),
    3012                                            mMainWnd->menuBar()->actions());
    3013         }
    3014         delete[] list;
    3015 #elif defined (Q_WS_X11)
    3016         NOREF(aUniKey);
    3017         Display *display = QX11Info::display();
    3018         int keysyms_per_keycode = getKeysymsPerKeycode();
    3019         KeyCode kc = XKeysymToKeycode (display, aKey);
    3020         // iterate over the first level (not shifted) keysyms in every group
    3021         for (int i = 0; i < keysyms_per_keycode && !processed; i += 2)
    3022         {
    3023             KeySym ks = XKeycodeToKeysym (display, kc, i);
    3024             char ch = 0;
    3025             if (!XkbTranslateKeySym (display, &ks, 0, &ch, 1, NULL) == 1)
    3026                 ch = 0;
    3027             if (ch)
    3028             {
    3029                 QChar c = QString::fromLocal8Bit (&ch, 1) [0];
    3030                 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3031                                                          c.toUpper().unicode()),
    3032                                            mMainWnd->menuBar()->actions());
    3033             }
    3034         }
    3035 #elif defined (Q_WS_MAC)
    3036         if (aUniKey && aUniKey [0] && !aUniKey [1])
    3037             processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3038                                                      QChar (aUniKey [0]).toUpper().unicode()),
    3039                                        mMainWnd->menuBar()->actions());
    3040 
    3041         /* Don't consider the hot key as pressed since the guest never saw
    3042          * it. (probably a generic thing) */
    3043         mPressedKeys [aScan] &= ~whatPressed;
    3044 #endif
    3045 
    3046         /* grab the key from Qt if processed, or pass it to Qt otherwise
    3047          * in order to process non-alphanumeric keys in event(), after they are
    3048          * converted to Qt virtual keys. */
    3049         return processed;
    3050     }
    3051 
    3052     /* no more to do, if the host key is in action or the VM is paused */
    3053     if (mIsHostkeyPressed || isHostKey || isPaused())
    3054     {
    3055         /* grab the key from Qt and from VM if it's a host key,
    3056          * otherwise just pass it to Qt */
    3057         return isHostKey;
    3058     }
    3059 
    3060     CKeyboard keyboard = mConsole.GetKeyboard();
    3061     Assert (!keyboard.isNull());
    3062 
    3063 #if defined (Q_WS_WIN32)
    3064     /* send pending WM_PAINT events */
    3065     ::UpdateWindow (viewport()->winId());
    3066 #endif
    3067 
    3068 #if 0
    3069     {
    3070         char buf [256];
    3071         sprintf (buf, "*** SCANS: ");
    3072         for (uint i = 0; i < count; ++ i)
    3073             sprintf (buf + strlen (buf), "%02X ", codes [i]);
    3074         mMainWnd->statusBar()->message (buf);
    3075         LogFlow (("%s\n", buf));
    3076     }
    3077 #endif
    3078 
    3079     std::vector <LONG> scancodes(codes, &codes[count]);
    3080     keyboard.PutScancodes (QVector<LONG>::fromStdVector(scancodes));
    3081 
    3082     /* grab the key from Qt */
    3083     return true;
    3084 }
    3085 
    3086 /**
    3087  *  Called on every mouse/wheel move and button press/release.
    3088  *
    3089  *  @return     true to consume the event and false to pass it to Qt
    3090  */
    3091 bool VBoxConsoleView::mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    3092                                   Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
    3093                                   int aWheelDelta, Qt::Orientation aWheelDir)
    3094 {
    3095 #if 1
    3096 
    3097     LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n",
    3098              __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(),
    3099                (aButtons & Qt::LeftButton ? 1 : 0)
    3100              | (aButtons & Qt::RightButton ? 2 : 0)
    3101              | (aButtons & Qt::MidButton ? 4 : 0)
    3102              | (aButtons & Qt::XButton1 ? 8 : 0)
    3103              | (aButtons & Qt::XButton2 ? 16 : 0),
    3104              aWheelDelta,
    3105                aWheelDir == Qt::Horizontal ? "Horizontal"
    3106              : aWheelDir == Qt::Vertical ? "Vertical" : "Unknown"));
    3107     Q_UNUSED (aModifiers);
    3108 #else
    3109     Q_UNUSED (aModifiers);
    3110 #endif
    3111 
    3112     int state = 0;
    3113     if (aButtons & Qt::LeftButton)
    3114         state |= KMouseButtonState_LeftButton;
    3115     if (aButtons & Qt::RightButton)
    3116         state |= KMouseButtonState_RightButton;
    3117     if (aButtons & Qt::MidButton)
    3118         state |= KMouseButtonState_MiddleButton;
    3119     if (aButtons & Qt::XButton1)
    3120         state |= KMouseButtonState_XButton1;
    3121     if (aButtons & Qt::XButton2)
    3122         state |= KMouseButtonState_XButton2;
     745
     746            emit usbStateChange();
     747#endif
     748            UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent);
     749            emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error());
     750            return true;
     751        }
     752
     753        case UIConsoleEventType_SharedFolderChange:
     754        {
     755            emit sigSharedFolderChange();
     756            return true;
     757        }
     758
     759        case UIConsoleEventType_RuntimeError:
     760        {
     761#if 0 // TODO: Move to machine view!
     762            UIRuntimeErrorEvent *pConsoleEvent = (UIRuntimeErrorEvent *) pEvent;
     763            vboxProblem().showRuntimeError(m_console, ee->fatal(), ee->errorID(), ee->message());
     764#endif
     765            UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent);
     766            emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message());
     767            return true;
     768        }
    3123769
    3124770#ifdef Q_WS_MAC
    3125     /* Simulate the right click on
    3126      * Host+Left Mouse */
    3127     if (mIsHostkeyPressed &&
    3128         mIsHostkeyAlone &&
    3129         state == KMouseButtonState_LeftButton)
    3130         state = KMouseButtonState_RightButton;
    3131 #endif /* Q_WS_MAC */
    3132 
    3133     int wheelVertical = 0;
    3134     int wheelHorizontal = 0;
    3135     if (aWheelDir == Qt::Vertical)
    3136     {
    3137         /* the absolute value of wheel delta is 120 units per every wheel
    3138          * move; positive deltas correspond to counterclockwize rotations
    3139          * (usually up), negative -- to clockwize (usually down). */
    3140         wheelVertical = - (aWheelDelta / 120);
    3141     }
    3142     else if (aWheelDir == Qt::Horizontal)
    3143         wheelHorizontal = aWheelDelta / 120;
    3144 
    3145     if (mMouseCaptured)
    3146     {
    3147 #ifdef Q_WS_WIN32
    3148         /* send pending WM_PAINT events */
    3149         ::UpdateWindow (viewport()->winId());
    3150 #endif
    3151 
    3152         CMouse mouse = mConsole.GetMouse();
    3153         mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(),
    3154                              aGlobalPos.y() - mLastPos.y(),
    3155                              wheelVertical, wheelHorizontal, state);
    3156 
    3157 #if defined (Q_WS_MAC)
    3158         /*
    3159          * Keep the mouse from leaving the widget.
    3160          *
    3161          * This is a bit tricky to get right because if it escapes we won't necessarily
    3162          * get mouse events any longer and can warp it back. So, we keep safety zone
    3163          * of up to 300 pixels around the borders of the widget to prevent this from
    3164          * happening. Also, the mouse is warped back to the center of the widget.
    3165          *
    3166          * (Note, aPos seems to be unreliable, it caused endless recursion here at one points...)
    3167          * (Note, synergy and other remote clients might not like this cursor warping.)
    3168          */
    3169         QRect rect = viewport()->visibleRegion().boundingRect();
    3170         QPoint pw = viewport()->mapToGlobal (viewport()->pos());
    3171         rect.translate (pw.x(), pw.y());
    3172 
    3173         QRect dpRect = QApplication::desktop()->screenGeometry (viewport());
    3174         if (rect.intersects (dpRect))
    3175             rect = rect.intersect (dpRect);
    3176 
    3177         int wsafe = rect.width() / 6;
    3178         rect.setWidth (rect.width() - wsafe * 2);
    3179         rect.setLeft (rect.left() + wsafe);
    3180 
    3181         int hsafe = rect.height() / 6;
    3182         rect.setWidth (rect.height() - hsafe * 2);
    3183         rect.setTop (rect.top() + hsafe);
    3184 
    3185         if (rect.contains (aGlobalPos, true))
    3186             mLastPos = aGlobalPos;
    3187         else
    3188         {
    3189             mLastPos = rect.center();
    3190             QCursor::setPos (mLastPos);
    3191         }
    3192 
    3193 #else /* !Q_WS_MAC */
    3194 
    3195         /* "jerk" the mouse by bringing it to the opposite side
    3196          * to simulate the endless moving */
    3197 
    3198 #ifdef Q_WS_WIN32
    3199         int we = viewport()->width() - 1;
    3200         int he = viewport()->height() - 1;
    3201         QPoint p = aPos;
    3202         if (aPos.x() == 0)
    3203             p.setX (we - 1);
    3204         else if (aPos.x() == we)
    3205             p.setX (1);
    3206         if (aPos.y() == 0 )
    3207             p.setY (he - 1);
    3208         else if (aPos.y() == he)
    3209             p.setY (1);
    3210 
    3211         if (p != aPos)
    3212         {
    3213             mLastPos = viewport()->mapToGlobal (p);
    3214             QCursor::setPos (mLastPos);
    3215         }
    3216         else
    3217         {
    3218             mLastPos = aGlobalPos;
    3219         }
    3220 #else
    3221         int we = QApplication::desktop()->width() - 1;
    3222         int he = QApplication::desktop()->height() - 1;
    3223         QPoint p = aGlobalPos;
    3224         if (aGlobalPos.x() == 0)
    3225             p.setX (we - 1);
    3226         else if (aGlobalPos.x() == we)
    3227             p.setX( 1 );
    3228         if (aGlobalPos.y() == 0)
    3229             p.setY (he - 1);
    3230         else if (aGlobalPos.y() == he)
    3231             p.setY (1);
    3232 
    3233         if (p != aGlobalPos)
    3234         {
    3235             mLastPos =  p;
    3236             QCursor::setPos (mLastPos);
    3237         }
    3238         else
    3239         {
    3240             mLastPos = aGlobalPos;
    3241         }
    3242 #endif
    3243 #endif /* !Q_WS_MAC */
    3244         return true; /* stop further event handling */
    3245     }
    3246     else /* !mMouseCaptured */
    3247     {
    3248         if (mMainWnd->isTrueFullscreen())
    3249         {
    3250             if (mode != VBoxDefs::SDLMode)
    3251             {
    3252                 /* try to automatically scroll the guest canvas if the
    3253                  * mouse is on the screen border */
    3254                 /// @todo (r=dmik) better use a timer for autoscroll
    3255                 QRect scrGeo = QApplication::desktop()->screenGeometry (this);
    3256                 int dx = 0, dy = 0;
    3257                 if (scrGeo.width() < contentsWidth())
    3258                 {
    3259                     if (scrGeo.left() == aGlobalPos.x()) dx = -1;
    3260                     if (scrGeo.right() == aGlobalPos.x()) dx = +1;
    3261                 }
    3262                 if (scrGeo.height() < contentsHeight())
    3263                 {
    3264                     if (scrGeo.top() == aGlobalPos.y()) dy = -1;
    3265                     if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
    3266                 }
    3267                 if (dx || dy)
    3268                     scrollBy (dx, dy);
    3269             }
    3270         }
    3271 
    3272         if (mMouseAbsolute && mMouseIntegration)
    3273         {
    3274             int cw = contentsWidth(), ch = contentsHeight();
    3275             int vw = visibleWidth(), vh = visibleHeight();
    3276 
    3277             if (mode != VBoxDefs::SDLMode)
    3278             {
    3279                 /* try to automatically scroll the guest canvas if the
    3280                  * mouse goes outside its visible part */
    3281 
    3282                 int dx = 0;
    3283                 if (aPos.x() > vw) dx = aPos.x() - vw;
    3284                 else if (aPos.x() < 0) dx = aPos.x();
    3285                 int dy = 0;
    3286                 if (aPos.y() > vh) dy = aPos.y() - vh;
    3287                 else if (aPos.y() < 0) dy = aPos.y();
    3288                 if (dx != 0 || dy != 0) scrollBy (dx, dy);
    3289             }
    3290 
    3291             QPoint cpnt = viewportToContents (aPos);
    3292             if (cpnt.x() < 0) cpnt.setX (0);
    3293             else if (cpnt.x() > cw) cpnt.setX (cw);
    3294             if (cpnt.y() < 0) cpnt.setY (0);
    3295             else if (cpnt.y() > ch) cpnt.setY (ch);
    3296 
    3297             CMouse mouse = mConsole.GetMouse();
    3298             mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical,
    3299                                          wheelHorizontal, state);
    3300             return true; /* stop further event handling */
    3301         }
    3302         else
    3303         {
    3304             if (hasFocus() &&
    3305                 (aType == QEvent::MouseButtonRelease &&
    3306                  aButtons == Qt::NoButton))
    3307             {
    3308                 if (isPaused())
    3309                 {
    3310                     vboxProblem().remindAboutPausedVMInput();
    3311                 }
    3312                 else if (isRunning())
    3313                 {
    3314                     /* temporarily disable auto capture that will take
    3315                      * place after this dialog is dismissed because
    3316                      * the capture state is to be defined by the
    3317                      * dialog result itself */
    3318                     mDisableAutoCapture = true;
    3319                     bool autoConfirmed = false;
    3320                     bool ok = vboxProblem().confirmInputCapture (&autoConfirmed);
    3321                     if (autoConfirmed)
    3322                         mDisableAutoCapture = false;
    3323                     /* otherwise, the disable flag will be reset in
    3324                      * the next console view's foucs in event (since
    3325                      * may happen asynchronously on some platforms,
    3326                      * after we return from this code) */
    3327 
    3328                     if (ok)
    3329                     {
    3330 #ifdef Q_WS_X11
    3331                         /* make sure that pending FocusOut events from the
    3332                          * previous message box are handled, otherwise the
    3333                          * mouse is immediately ungrabbed again */
    3334                         qApp->processEvents();
    3335 #endif
    3336                         captureKbd (true);
    3337                         captureMouse (true);
    3338                     }
    3339                 }
    3340             }
    3341         }
    3342     }
    3343 
    3344     return false;
    3345 }
    3346 
    3347 void VBoxConsoleView::onStateChange (KMachineState state)
    3348 {
    3349     switch (state)
    3350     {
    3351         case KMachineState_Paused:
    3352         case KMachineState_TeleportingPausedVM:
    3353         {
    3354             if (    mode != VBoxDefs::TimerMode
    3355                 &&  mFrameBuf
    3356                 &&  (   state      != KMachineState_TeleportingPausedVM
    3357                      || mLastState != KMachineState_Teleporting)
    3358                )
    3359             {
    3360                 /*
    3361                  *  Take a screen snapshot. Note that TakeScreenShot() always
    3362                  *  needs a 32bpp image
    3363                  */
    3364                 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32);
    3365                 CDisplay dsp = mConsole.GetDisplay();
    3366                 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height());
    3367                 /*
    3368                  *  TakeScreenShot() may fail if, e.g. the Paused notification
    3369                  *  was delivered after the machine execution was resumed. It's
    3370                  *  not fatal.
    3371                  */
    3372                 if (dsp.isOk())
    3373                 {
    3374                     dimImage (shot);
    3375                     mPausedShot = QPixmap::fromImage (shot);
    3376                     /* fully repaint to pick up mPausedShot */
    3377                     repaint();
    3378                 }
    3379             }
    3380             /* fall through */
    3381         }
    3382         case KMachineState_Stuck:
    3383         {
    3384             /* reuse the focus event handler to uncapture everything */
    3385             if (hasFocus())
    3386                 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */);
    3387             break;
    3388         }
    3389         case KMachineState_Running:
    3390         {
    3391             if (   mLastState == KMachineState_Paused
    3392                 || mLastState == KMachineState_TeleportingPausedVM
    3393                )
    3394             {
    3395                 if (mode != VBoxDefs::TimerMode && mFrameBuf)
    3396                 {
    3397                     /* reset the pixmap to free memory */
    3398                     mPausedShot = QPixmap ();
    3399                     /*
    3400                      *  ask for full guest display update (it will also update
    3401                      *  the viewport through IFramebuffer::NotifyUpdate)
    3402                      */
    3403                     CDisplay dsp = mConsole.GetDisplay();
    3404                     dsp.InvalidateAndUpdate();
    3405                 }
    3406             }
    3407             /* reuse the focus event handler to capture input */
    3408             if (hasFocus())
    3409                 focusEvent (true /* aHasFocus */);
    3410             break;
    3411         }
     771        /* posted OnShowWindow */
     772        case UIConsoleEventType_ShowWindow:
     773        {
     774            /* Dunno what Qt3 thinks a window that has minimized to the dock
     775             * should be - it is not hidden, neither is it minimized. OTOH it is
     776             * marked shown and visible, but not activated. This latter isn't of
     777             * much help though, since at this point nothing is marked activated.
     778             * I might have overlooked something, but I'm buggered what if I know
     779             * what. So, I'll just always show & activate the stupid window to
     780             * make it get out of the dock when the user wishes to show a VM. */
     781            window()->show();
     782            window()->activateWindow();
     783            return true;
     784        }
     785#endif
     786
    3412787        default:
    3413788            break;
    3414789    }
    3415 
    3416     mLastState = state;
     790    return QObject::event(pEvent);
    3417791}
    3418792
    3419 void VBoxConsoleView::doRefresh()
    3420 {
    3421     viewport()->repaint();
     793qulonglong UISession::winId() const
     794{
     795    return machine()->machineLogic()->machineWindowWrapper()->machineWindow()->winId();
    3422796}
    3423 
    3424 void VBoxConsoleView::resizeEvent (QResizeEvent *)
    3425 {
    3426     updateSliders();
    3427 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    3428     QRect r = viewport()->geometry();
    3429 //    printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height());
    3430     PostBoundsChanged (r);
    3431 #endif /* Q_WS_MAC */
    3432 }
    3433 
    3434 void VBoxConsoleView::moveEvent (QMoveEvent *)
    3435 {
    3436 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    3437     QRect r = viewport()->geometry();
    3438 //    printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height());
    3439     PostBoundsChanged (r);
    3440 #endif /* Q_WS_MAC */
    3441 }
    3442 
    3443 void VBoxConsoleView::paintEvent (QPaintEvent *pe)
    3444 {
    3445     if (mPausedShot.isNull())
    3446     {
    3447         /* delegate the paint function to the VBoxFrameBuffer interface */
    3448         if (mFrameBuf)
    3449             mFrameBuf->paintEvent (pe);
    3450 #ifdef Q_WS_MAC
    3451         /* Update the dock icon if we are in the running state */
    3452         if (isRunning())
    3453             updateDockIcon();
    3454 #endif
    3455         return;
    3456     }
    3457 
    3458 #ifdef VBOX_GUI_USE_QUARTZ2D
    3459     if (mode == VBoxDefs::Quartz2DMode && mFrameBuf)
    3460     {
    3461         mFrameBuf->paintEvent (pe);
    3462         updateDockIcon();
    3463     }
    3464     else
    3465 #endif
    3466     {
    3467         /* we have a snapshot for the paused state */
    3468         QRect r = pe->rect().intersect (viewport()->rect());
    3469         /* We have to disable paint on screen if we are using the regular painter */
    3470         bool paintOnScreen = viewport()->testAttribute (Qt::WA_PaintOnScreen);
    3471         viewport()->setAttribute (Qt::WA_PaintOnScreen, false);
    3472         QPainter pnt (viewport());
    3473         pnt.drawPixmap (r.x(), r.y(), mPausedShot,
    3474                         r.x() + contentsX(), r.y() + contentsY(),
    3475                         r.width(), r.height());
    3476         /* Restore the attribute to its previous state */
    3477         viewport()->setAttribute (Qt::WA_PaintOnScreen, paintOnScreen);
    3478 #ifdef Q_WS_MAC
    3479         updateDockIcon();
    3480 #endif
    3481     }
    3482 
    3483 }
    3484 
    3485 /**
    3486  *  Captures the keyboard. When captured, no keyboard input reaches the host
    3487  *  system (including most system combinations like Alt-Tab).
    3488  *
    3489  *  @param aCapture     true to capture, false to uncapture.
    3490  *  @param aEmitSignal  Whether to emit keyboardStateChanged() or not.
    3491  */
    3492 void VBoxConsoleView::captureKbd (bool aCapture, bool aEmitSignal /* = true */)
    3493 {
    3494     AssertMsg (mAttached, ("Console must be attached"));
    3495 
    3496     if (mKbdCaptured == aCapture)
    3497         return;
    3498 
    3499     /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is
    3500      * used instead. On X11, we use XGrabKey instead of XGrabKeyboard (called
    3501      * by QWidget::grabKeyboard()) because the latter causes problems under
    3502      * metacity 2.16 (in particular, due to a bug, a window cannot be moved
    3503      * using the mouse if it is currently grabing the keyboard). On Mac OS X,
    3504      * we use the Qt methods + disabling global hot keys + watching modifiers
    3505      * (for right/left separation). */
    3506 #if defined (Q_WS_WIN32)
    3507     /**/
    3508 #elif defined (Q_WS_X11)
    3509     if (aCapture)
    3510         XGrabKey (QX11Info::display(), AnyKey, AnyModifier,
    3511                   window()->winId(), False,
    3512                   GrabModeAsync, GrabModeAsync);
    3513     else
    3514         XUngrabKey (QX11Info::display(),  AnyKey, AnyModifier,
    3515                     window()->winId());
    3516 #elif defined (Q_WS_MAC)
    3517     if (aCapture)
    3518     {
    3519         ::DarwinDisableGlobalHotKeys (true);
    3520         grabKeyboard();
    3521     }
    3522     else
    3523     {
    3524         ::DarwinDisableGlobalHotKeys (false);
    3525         releaseKeyboard();
    3526     }
    3527 #else
    3528     if (aCapture)
    3529         grabKeyboard();
    3530     else
    3531         releaseKeyboard();
    3532 #endif
    3533 
    3534     mKbdCaptured = aCapture;
    3535 
    3536     if (aEmitSignal)
    3537         emitKeyboardStateChanged();
    3538 }
    3539 
    3540 /**
    3541  *  Captures the host mouse pointer. When captured, the mouse pointer is
    3542  *  unavailable to the host applications.
    3543  *
    3544  *  @param aCapture     true to capture, false to uncapture.
    3545  *  @param aEmitSignal  Whether to emit mouseStateChanged() or not.
    3546  */
    3547 void VBoxConsoleView::captureMouse (bool aCapture, bool aEmitSignal /* = true */)
    3548 {
    3549     AssertMsg (mAttached, ("Console must be attached"));
    3550 
    3551     if (mMouseCaptured == aCapture)
    3552         return;
    3553 
    3554     if (aCapture)
    3555     {
    3556         /* memorize the host position where the cursor was captured */
    3557         mCapturedPos = QCursor::pos();
    3558 #ifdef Q_WS_WIN32
    3559         viewport()->setCursor (QCursor (Qt::BlankCursor));
    3560         /* move the mouse to the center of the visible area */
    3561         QCursor::setPos (mapToGlobal (visibleRegion().boundingRect().center()));
    3562         mLastPos = QCursor::pos();
    3563 #elif defined (Q_WS_MAC)
    3564         /* move the mouse to the center of the visible area */
    3565         mLastPos = mapToGlobal (visibleRegion().boundingRect().center());
    3566         QCursor::setPos (mLastPos);
    3567         /* grab all mouse events. */
    3568         viewport()->grabMouse();
    3569 #else
    3570         viewport()->grabMouse();
    3571         mLastPos = QCursor::pos();
    3572 #endif
    3573     }
    3574     else
    3575     {
    3576 #ifndef Q_WS_WIN32
    3577         viewport()->releaseMouse();
    3578 #endif
    3579         /* release mouse buttons */
    3580         CMouse mouse = mConsole.GetMouse();
    3581         mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0);
    3582     }
    3583 
    3584     mMouseCaptured = aCapture;
    3585 
    3586     updateMouseClipping();
    3587 
    3588     if (aEmitSignal)
    3589         emitMouseStateChanged();
    3590 }
    3591 
    3592 /**
    3593  *  Searches for a menu item with a given hot key (shortcut). If the item
    3594  *  is found, activates it and returns true. Otherwise returns false.
    3595  */
    3596 bool VBoxConsoleView::processHotKey (const QKeySequence &aKey,
    3597                                      const QList <QAction*> &aData)
    3598 {
    3599     foreach (QAction *pAction, aData)
    3600     {
    3601         if (QMenu *menu = pAction->menu())
    3602         {
    3603             /* Process recursively for each sub-menu */
    3604             if (processHotKey (aKey, menu->actions()))
    3605                 return true;
    3606         }
    3607         else
    3608         {
    3609             QString hotkey = VBoxGlobal::extractKeyFromActionText (pAction->text());
    3610             if (pAction->isEnabled() && !hotkey.isEmpty())
    3611             {
    3612                 if (aKey.matches (QKeySequence (hotkey)) == QKeySequence::ExactMatch)
    3613                 {
    3614                     /* We asynchronously post a special event instead of calling
    3615                      * pAction->trigger() directly, to let key presses and
    3616                      * releases be processed correctly by Qt first.
    3617                      * Note: we assume that nobody will delete the menu item
    3618                      * corresponding to the key sequence, so that the pointer to
    3619                      * menu data posted along with the event will remain valid in
    3620                      * the event handler, at least until the main window is closed. */
    3621                     QApplication::postEvent (this, new ActivateMenuEvent (pAction));
    3622                     return true;
    3623                 }
    3624             }
    3625         }
    3626     }
    3627 
    3628     return false;
    3629 }
    3630 
    3631 /**
    3632  * Send the KEY BREAK code to the VM for all currently pressed keys.
    3633  *
    3634  * @param aReleaseHostKey @c true to set the host key state to unpressed.
    3635  */
    3636 void VBoxConsoleView::releaseAllPressedKeys (bool aReleaseHostKey /* = true*/)
    3637 {
    3638     AssertMsg (mAttached, ("Console must be attached"));
    3639 
    3640     CKeyboard keyboard = mConsole.GetKeyboard();
    3641     bool fSentRESEND = false;
    3642 
    3643     /* send a dummy scan code (RESEND) to prevent the guest OS from recognizing
    3644      * a single key click (for ex., Alt) and performing an unwanted action
    3645      * (for ex., activating the menu) when we release all pressed keys below.
    3646      * Note, that it's just a guess that sending RESEND will give the desired
    3647      * effect :), but at least it works with NT and W2k guests. */
    3648 
    3649     /// @todo Sending 0xFE is responsible for the warning
    3650     //
    3651     //         ``atkbd.c: Spurious NAK on isa0060/serio0. Some program might
    3652     //           be trying access hardware directly''
    3653     //
    3654     //       on Linux guests (#1944). It might also be responsible for #1949. Don't
    3655     //       send this command unless we really have to release any key modifier.
    3656     //                                                                    --frank
    3657 
    3658     for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++)
    3659     {
    3660         if (mPressedKeys [i] & IsKeyPressed)
    3661         {
    3662             if (!fSentRESEND)
    3663             {
    3664                 keyboard.PutScancode (0xFE);
    3665                 fSentRESEND = true;
    3666             }
    3667             keyboard.PutScancode (i | 0x80);
    3668         }
    3669         else if (mPressedKeys [i] & IsExtKeyPressed)
    3670         {
    3671             if (!fSentRESEND)
    3672             {
    3673                 keyboard.PutScancode (0xFE);
    3674                 fSentRESEND = true;
    3675             }
    3676             QVector <LONG> codes (2);
    3677             codes[0] = 0xE0;
    3678             codes[1] = i | 0x80;
    3679             keyboard.PutScancodes (codes);
    3680         }
    3681         mPressedKeys [i] = 0;
    3682     }
    3683 
    3684     if (aReleaseHostKey)
    3685         mIsHostkeyPressed = false;
    3686 
    3687 #ifdef Q_WS_MAC
    3688     /* clear most of the modifiers. */
    3689     mDarwinKeyModifiers &=
    3690         alphaLock | kEventKeyModifierNumLockMask |
    3691         (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (gs.hostKey()));
    3692 #endif
    3693 
    3694     emitKeyboardStateChanged();
    3695 }
    3696 
    3697 void VBoxConsoleView::saveKeyStates()
    3698 {
    3699     ::memcpy (mPressedKeysCopy, mPressedKeys, sizeof (mPressedKeys));
    3700 }
    3701 
    3702 void VBoxConsoleView::sendChangedKeyStates()
    3703 {
    3704     AssertMsg (mAttached, ("Console must be attached"));
    3705 
    3706     QVector <LONG> codes (2);
    3707     CKeyboard keyboard = mConsole.GetKeyboard();
    3708     for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); ++ i)
    3709     {
    3710         uint8_t os = mPressedKeysCopy [i];
    3711         uint8_t ns = mPressedKeys [i];
    3712         if ((os & IsKeyPressed) != (ns & IsKeyPressed))
    3713         {
    3714             codes [0] = i;
    3715             if (!(ns & IsKeyPressed))
    3716                 codes[0] |= 0x80;
    3717             keyboard.PutScancode (codes[0]);
    3718         }
    3719         else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed))
    3720         {
    3721             codes [0] = 0xE0;
    3722             codes [1] = i;
    3723             if (!(ns & IsExtKeyPressed))
    3724                 codes [1] |= 0x80;
    3725             keyboard.PutScancodes (codes);
    3726         }
    3727     }
    3728 }
    3729 
    3730 void VBoxConsoleView::updateMouseClipping()
    3731 {
    3732     AssertMsg (mAttached, ("Console must be attached"));
    3733 
    3734     if (mMouseCaptured)
    3735     {
    3736         viewport()->setCursor (QCursor (Qt::BlankCursor));
    3737 #ifdef Q_WS_WIN32
    3738         QRect r = viewport()->rect();
    3739         r.moveTopLeft (viewport()->mapToGlobal (QPoint (0, 0)));
    3740         RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
    3741         ::ClipCursor (&rect);
    3742 #endif
    3743     }
    3744     else
    3745     {
    3746 #ifdef Q_WS_WIN32
    3747         ::ClipCursor (NULL);
    3748 #endif
    3749         /* return the cursor to where it was when we captured it and show it */
    3750         QCursor::setPos (mCapturedPos);
    3751         viewport()->unsetCursor();
    3752     }
    3753 }
    3754 
    3755 void VBoxConsoleView::setPointerShape (MousePointerChangeEvent *me)
    3756 {
    3757     if (me->shapeData() != NULL)
    3758     {
    3759         bool ok = false;
    3760 
    3761         const uchar *srcAndMaskPtr = me->shapeData();
    3762         uint andMaskSize = (me->width() + 7) / 8 * me->height();
    3763         const uchar *srcShapePtr = me->shapeData() + ((andMaskSize + 3) & ~3);
    3764         uint srcShapePtrScan = me->width() * 4;
    3765 
    3766 #if defined (Q_WS_WIN)
    3767 
    3768         BITMAPV5HEADER bi;
    3769         HBITMAP hBitmap;
    3770         void *lpBits;
    3771 
    3772         ::ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
    3773         bi.bV5Size = sizeof (BITMAPV5HEADER);
    3774         bi.bV5Width = me->width();
    3775         bi.bV5Height = - (LONG) me->height();
    3776         bi.bV5Planes = 1;
    3777         bi.bV5BitCount = 32;
    3778         bi.bV5Compression = BI_BITFIELDS;
    3779         // specifiy a supported 32 BPP alpha format for Windows XP
    3780         bi.bV5RedMask   = 0x00FF0000;
    3781         bi.bV5GreenMask = 0x0000FF00;
    3782         bi.bV5BlueMask  = 0x000000FF;
    3783         if (me->hasAlpha())
    3784             bi.bV5AlphaMask = 0xFF000000;
    3785         else
    3786             bi.bV5AlphaMask = 0;
    3787 
    3788         HDC hdc = GetDC (NULL);
    3789 
    3790         // create the DIB section with an alpha channel
    3791         hBitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS,
    3792                                     (void **) &lpBits, NULL, (DWORD) 0);
    3793 
    3794         ReleaseDC (NULL, hdc);
    3795 
    3796         HBITMAP hMonoBitmap = NULL;
    3797         if (me->hasAlpha())
    3798         {
    3799             // create an empty mask bitmap
    3800             hMonoBitmap = CreateBitmap (me->width(), me->height(), 1, 1, NULL);
    3801         }
    3802         else
    3803         {
    3804             /* Word aligned AND mask. Will be allocated and created if necessary. */
    3805             uint8_t *pu8AndMaskWordAligned = NULL;
    3806 
    3807             /* Width in bytes of the original AND mask scan line. */
    3808             uint32_t cbAndMaskScan = (me->width() + 7) / 8;
    3809 
    3810             if (cbAndMaskScan & 1)
    3811             {
    3812                 /* Original AND mask is not word aligned. */
    3813 
    3814                 /* Allocate memory for aligned AND mask. */
    3815                 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ ((cbAndMaskScan + 1) * me->height());
    3816 
    3817                 Assert(pu8AndMaskWordAligned);
    3818 
    3819                 if (pu8AndMaskWordAligned)
    3820                 {
    3821                     /* According to MSDN the padding bits must be 0.
    3822                      * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask.
    3823                      */
    3824                     uint32_t u32PaddingBits = cbAndMaskScan * 8  - me->width();
    3825                     Assert(u32PaddingBits < 8);
    3826                     uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
    3827 
    3828                     Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
    3829                           u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, me->width(), cbAndMaskScan));
    3830 
    3831                     uint8_t *src = (uint8_t *)srcAndMaskPtr;
    3832                     uint8_t *dst = pu8AndMaskWordAligned;
    3833 
    3834                     unsigned i;
    3835                     for (i = 0; i < me->height(); i++)
    3836                     {
    3837                         memcpy (dst, src, cbAndMaskScan);
    3838 
    3839                         dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
    3840 
    3841                         src += cbAndMaskScan;
    3842                         dst += cbAndMaskScan + 1;
    3843                     }
    3844                 }
    3845             }
    3846 
    3847             /* create the AND mask bitmap */
    3848             hMonoBitmap = ::CreateBitmap (me->width(), me->height(), 1, 1,
    3849                                           pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
    3850 
    3851             if (pu8AndMaskWordAligned)
    3852             {
    3853                 RTMemTmpFree (pu8AndMaskWordAligned);
    3854             }
    3855         }
    3856 
    3857         Assert (hBitmap);
    3858         Assert (hMonoBitmap);
    3859         if (hBitmap && hMonoBitmap)
    3860         {
    3861             DWORD *dstShapePtr = (DWORD *) lpBits;
    3862 
    3863             for (uint y = 0; y < me->height(); y ++)
    3864             {
    3865                 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
    3866                 srcShapePtr += srcShapePtrScan;
    3867                 dstShapePtr += me->width();
    3868             }
    3869 
    3870             ICONINFO ii;
    3871             ii.fIcon = FALSE;
    3872             ii.xHotspot = me->xHot();
    3873             ii.yHotspot = me->yHot();
    3874             ii.hbmMask = hMonoBitmap;
    3875             ii.hbmColor = hBitmap;
    3876 
    3877             HCURSOR hAlphaCursor = CreateIconIndirect (&ii);
    3878             Assert (hAlphaCursor);
    3879             if (hAlphaCursor)
    3880             {
    3881                 viewport()->setCursor (QCursor (hAlphaCursor));
    3882                 ok = true;
    3883                 if (mAlphaCursor)
    3884                     DestroyIcon (mAlphaCursor);
    3885                 mAlphaCursor = hAlphaCursor;
    3886             }
    3887         }
    3888 
    3889         if (hMonoBitmap)
    3890             DeleteObject (hMonoBitmap);
    3891         if (hBitmap)
    3892             DeleteObject (hBitmap);
    3893 
    3894 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
    3895 
    3896         XcursorImage *img = XcursorImageCreate (me->width(), me->height());
    3897         Assert (img);
    3898         if (img)
    3899         {
    3900             img->xhot = me->xHot();
    3901             img->yhot = me->yHot();
    3902 
    3903             XcursorPixel *dstShapePtr = img->pixels;
    3904 
    3905             for (uint y = 0; y < me->height(); y ++)
    3906             {
    3907                 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
    3908 
    3909                 if (!me->hasAlpha())
    3910                 {
    3911                     /* convert AND mask to the alpha channel */
    3912                     uchar byte = 0;
    3913                     for (uint x = 0; x < me->width(); x ++)
    3914                     {
    3915                         if (!(x % 8))
    3916                             byte = *(srcAndMaskPtr ++);
    3917                         else
    3918                             byte <<= 1;
    3919 
    3920                         if (byte & 0x80)
    3921                         {
    3922                             /* Linux doesn't support inverted pixels (XOR ops,
    3923                              * to be exact) in cursor shapes, so we detect such
    3924                              * pixels and always replace them with black ones to
    3925                              * make them visible at least over light colors */
    3926                             if (dstShapePtr [x] & 0x00FFFFFF)
    3927                                 dstShapePtr [x] = 0xFF000000;
    3928                             else
    3929                                 dstShapePtr [x] = 0x00000000;
    3930                         }
    3931                         else
    3932                             dstShapePtr [x] |= 0xFF000000;
    3933                     }
    3934                 }
    3935 
    3936                 srcShapePtr += srcShapePtrScan;
    3937                 dstShapePtr += me->width();
    3938             }
    3939 
    3940             Cursor cur = XcursorImageLoadCursor (QX11Info::display(), img);
    3941             Assert (cur);
    3942             if (cur)
    3943             {
    3944                 viewport()->setCursor (QCursor (cur));
    3945                 ok = true;
    3946             }
    3947 
    3948             XcursorImageDestroy (img);
    3949         }
    3950 
    3951 #elif defined(Q_WS_MAC)
    3952 
    3953         /* Create a ARGB image out of the shape data. */
    3954         QImage image  (me->width(), me->height(), QImage::Format_ARGB32);
    3955         const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
    3956         unsigned cbSrcMaskLine = RT_ALIGN (me->width(), 8) / 8;
    3957         for (unsigned int y = 0; y < me->height(); ++y)
    3958         {
    3959             for (unsigned int x = 0; x < me->width(); ++x)
    3960             {
    3961                unsigned int color = ((unsigned int*)srcShapePtr)[y*me->width()+x];
    3962                /* If the alpha channel isn't in the shape data, we have to
    3963                 * create them from the and-mask. This is a bit field where 1
    3964                 * represent transparency & 0 opaque respectively. */
    3965                if (!me->hasAlpha())
    3966                {
    3967                    if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
    3968                        color  |= 0xff000000;
    3969                    else
    3970                    {
    3971                        /* This isn't quite right, but it's the best we can do I
    3972                         * think... */
    3973                        if (color & 0x00ffffff)
    3974                            color = 0xff000000;
    3975                        else
    3976                            color = 0x00000000;
    3977                    }
    3978                }
    3979                image.setPixel (x, y, color);
    3980             }
    3981             /* Move one scanline forward. */
    3982             pbSrcMask += cbSrcMaskLine;
    3983         }
    3984         /* Set the new cursor */
    3985         QCursor cursor (QPixmap::fromImage (image),
    3986                         me->xHot(), me->yHot());
    3987         viewport()->setCursor (cursor);
    3988         ok = true;
    3989         NOREF (srcShapePtrScan);
    3990 
    3991 #else
    3992 
    3993 # warning "port me"
    3994 
    3995 #endif
    3996         if (ok)
    3997             mLastCursor = viewport()->cursor();
    3998         else
    3999             viewport()->unsetCursor();
    4000     }
    4001     else
    4002     {
    4003         /*
    4004          * We did not get any shape data
    4005          */
    4006         if (me->isVisible())
    4007         {
    4008             viewport()->setCursor (mLastCursor);
    4009         }
    4010         else
    4011         {
    4012             viewport()->setCursor (Qt::BlankCursor);
    4013         }
    4014     }
    4015     mHideHostPointer = !me->isVisible();
    4016 }
    4017 
    4018 inline QRgb qRgbIntensity (QRgb rgb, int mul, int div)
    4019 {
    4020     int r = qRed (rgb);
    4021     int g = qGreen (rgb);
    4022     int b = qBlue (rgb);
    4023     return qRgb (mul * r / div, mul * g / div, mul * b / div);
    4024 }
    4025 
    4026 /* static */
    4027 void VBoxConsoleView::dimImage (QImage &img)
    4028 {
    4029     for (int y = 0; y < img.height(); y ++) {
    4030         if (y % 2) {
    4031             if (img.depth() == 32) {
    4032                 for (int x = 0; x < img.width(); x ++) {
    4033                     int gray = qGray (img.pixel (x, y)) / 2;
    4034                     img.setPixel (x, y, qRgb (gray, gray, gray));
    4035 //                    img.setPixel (x, y, qRgbIntensity (img.pixel (x, y), 1, 2));
    4036                 }
    4037             } else {
    4038                 ::memset (img.scanLine (y), 0, img.bytesPerLine());
    4039             }
    4040         } else {
    4041             if (img.depth() == 32) {
    4042                 for (int x = 0; x < img.width(); x ++) {
    4043                     int gray = (2 * qGray (img.pixel (x, y))) / 3;
    4044                     img.setPixel (x, y, qRgb (gray, gray, gray));
    4045 //                    img.setPixel (x, y, qRgbIntensity (img.pixel(x, y), 2, 3));
    4046                 }
    4047             }
    4048         }
    4049     }
    4050 }
    4051 
    4052 void VBoxConsoleView::doResizeHint (const QSize &aToSize)
    4053 {
    4054     if (mGuestSupportsGraphics && mAutoresizeGuest)
    4055     {
    4056         /* If this slot is invoked directly then use the passed size
    4057          * otherwise get the available size for the guest display.
    4058          * We assume here that the centralWidget() contains this view only
    4059          * and gives it all available space. */
    4060         QSize sz (aToSize.isValid() ? aToSize : mMainWnd->centralWidget()->size());
    4061         if (!aToSize.isValid())
    4062             sz -= QSize (frameWidth() * 2, frameWidth() * 2);
    4063         /* Do not send out useless hints. */
    4064         if ((sz.width() == mStoredConsoleSize.width()) &&
    4065             (sz.height() == mStoredConsoleSize.height()))
    4066             return;
    4067         /* We only actually send the hint if
    4068          * 1) the autoresize property is set to true and
    4069          * 2) either an explicit new size was given (e.g. if the request
    4070          *    was triggered directly by a console resize event) or if no
    4071          *    explicit size was specified but a resize is flagged as being
    4072          *    needed (e.g. the autoresize was just enabled and the console
    4073          *    was resized while it was disabled). */
    4074         if (mAutoresizeGuest &&
    4075             (aToSize.isValid() || mDoResize))
    4076         {
    4077             LogFlowFunc (("Will suggest %d x %d\n", sz.width(), sz.height()));
    4078 
    4079             /* Remember the new size. */
    4080             storeConsoleSize (sz.width(), sz.height());
    4081 
    4082             mConsole.GetDisplay().SetVideoModeHint (sz.width(), sz.height(), 0, 0);
    4083         }
    4084         /* we have resized now... */
    4085         mDoResize = false;
    4086     }
    4087 }
    4088 
    4089 
    4090 /* If the desktop geometry is set automatically, this will update it. */
    4091 void VBoxConsoleView::doResizeDesktop (int)
    4092 {
    4093     calculateDesktopGeometry();
    4094 }
    4095 
    4096 /**
    4097  * Store the current size of the console (i.e. the viewport to the guest).
    4098  * This has two purposes.  One is to suppress unwanted resize events for
    4099  * which the new size is the same as the stored size.  The other is to expand
    4100  * the maximum size to which we will let the guest resize itself.  It makes
    4101  * no sense to forbid guest resizes which are less than the current resolution
    4102  * anyway.
    4103  *
    4104  * @param aWidth  width of the resolution hint
    4105  * @param aHeight height of the resolution hint
    4106  */
    4107 void VBoxConsoleView::storeConsoleSize (int aWidth, int aHeight)
    4108 {
    4109     LogFlowThisFunc (("aWidth=%d, aHeight=%d\n", aWidth, aHeight));
    4110     mStoredConsoleSize = QRect (0, 0, aWidth, aHeight);
    4111 }
    4112 
    4113 /**
    4114  * Do initial setup of desktop geometry restrictions on the guest framebuffer.
    4115  * These determine the maximum size the guest framebuffer can take on.
    4116  *
    4117  * @note a hint from the host will always override these restrictions.
    4118  *
    4119  * @param aGeo    Fixed -     the guest has a fixed maximum framebuffer size
    4120  *                Automatic - we calculate the maximum size ourselves.  The
    4121  *                            calculations will not actually be done until
    4122  *                            @a calculateDesktopGeometry is called, since
    4123  *                            we don't initially have the information needed.
    4124  *                Any -       any size is allowed
    4125  * @param aWidth  The maximum width for the guest screen or zero for no change
    4126  *                (only used for fixed geometry)
    4127  * @param aHeight The maximum height for the guest screen or zero for no change
    4128  *                (only used for fixed geometry)
    4129  */
    4130 void VBoxConsoleView::setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight)
    4131 {
    4132     LogFlowThisFunc (("aGeo=%s, aWidth=%d, aHeight=%d\n",
    4133                       (aGeo == DesktopGeo_Fixed ? "Fixed" :
    4134                        aGeo == DesktopGeo_Automatic ? "Automatic" :
    4135                        aGeo == DesktopGeo_Any ? "Any" : "Invalid"),
    4136                       aWidth, aHeight));
    4137     switch (aGeo)
    4138     {
    4139         case DesktopGeo_Fixed:
    4140             mDesktopGeo = DesktopGeo_Fixed;
    4141             if (aWidth != 0 && aHeight != 0)
    4142                 mDesktopGeometry = QRect (0, 0, aWidth, aHeight);
    4143             else
    4144                 mDesktopGeometry = QRect (0, 0, 0, 0);
    4145             storeConsoleSize (0, 0);
    4146             break;
    4147         case DesktopGeo_Automatic:
    4148             mDesktopGeo = DesktopGeo_Automatic;
    4149             mDesktopGeometry = QRect (0, 0, 0, 0);
    4150             storeConsoleSize (0, 0);
    4151             break;
    4152         case DesktopGeo_Any:
    4153             mDesktopGeo = DesktopGeo_Any;
    4154             mDesktopGeometry = QRect (0, 0, 0, 0);
    4155             break;
    4156         default:
    4157             AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo));
    4158             mDesktopGeo = DesktopGeo_Invalid;
    4159     }
    4160 }
    4161 
    4162 
    4163 /**
    4164  * If we are in automatic mode, the geometry restrictions will be recalculated.
    4165  * This is needed in particular on the first widget resize, as we can't
    4166  * calculate them correctly before that.
    4167  *
    4168  * @note a hint from the host will always override these restrictions.
    4169  * @note we can't do calculations on the fly when they are needed, because
    4170  *       they require querying the X server on X11 hosts and this must be done
    4171  *       from within the GUI thread, due to the single threadedness of Xlib.
    4172  */
    4173 void VBoxConsoleView::calculateDesktopGeometry()
    4174 {
    4175     LogFlowThisFunc (("Entering\n"));
    4176     /* This method should not get called until we have initially set up the */
    4177     Assert ((mDesktopGeo != DesktopGeo_Invalid));
    4178     /* If we are not doing automatic geometry calculation then there is
    4179      * nothing to do. */
    4180     if (DesktopGeo_Automatic == mDesktopGeo)
    4181     {
    4182         /* Available geometry of the desktop.  If the desktop is a single
    4183          * screen, this will exclude space taken up by desktop taskbars
    4184          * and things, but this is unfortunately not true for the more
    4185          * complex case of a desktop spanning multiple screens. */
    4186         QRect desktop = availableGeometry();
    4187         /* The area taken up by the console window on the desktop,
    4188          * including window frame, title and menu bar and whatnot. */
    4189         QRect frame = mMainWnd->frameGeometry();
    4190         /* The area taken up by the console window, minus all
    4191          * decorations. */
    4192         QRect window = mMainWnd->centralWidget()->geometry();
    4193         /* To work out how big we can make the console window while still
    4194          * fitting on the desktop, we calculate desktop - frame + window.
    4195          * This works because the difference between frame and window
    4196          * (or at least its width and height) is a constant. */
    4197         mDesktopGeometry =
    4198             QRect (0, 0, desktop.width() - frame.width() + window.width(),
    4199                    desktop.height() - frame.height() + window.height());
    4200         LogFlowThisFunc (("Setting %d, %d\n", mDesktopGeometry.width(),
    4201                            mDesktopGeometry.height()));
    4202     }
    4203 }
    4204 
    4205 /**
    4206  *  Sets the minimum size restriction depending on the auto-resize feature
    4207  *  state and the current rendering mode.
    4208  *
    4209  *  Currently, the restriction is set only in SDL mode and only when the
    4210  *  auto-resize feature is inactive. We need to do that because we cannot
    4211  *  correctly draw in a scrolled window in SDL mode.
    4212  *
    4213  *  In all other modes, or when auto-resize is in force, this function does
    4214  *  nothing.
    4215  */
    4216 void VBoxConsoleView::maybeRestrictMinimumSize()
    4217 {
    4218     if (mode == VBoxDefs::SDLMode)
    4219     {
    4220         if (!mGuestSupportsGraphics || !mAutoresizeGuest)
    4221             setMinimumSize (sizeHint());
    4222         else
    4223             setMinimumSize (0, 0);
    4224     }
    4225 }
    4226 
    4227 QRect VBoxConsoleView::availableGeometry() const
    4228 {
    4229     return mMainWnd->isWindowFullScreen() ?
    4230            QApplication::desktop()->screenGeometry(this) :
    4231            QApplication::desktop()->availableGeometry(this);
    4232 }
    4233 
    4234 int VBoxConsoleView::contentsWidth() const
    4235 {
    4236     return mFrameBuf->width();
    4237 }
    4238 
    4239 int VBoxConsoleView::contentsHeight() const
    4240 {
    4241     return mFrameBuf->height();
    4242 }
    4243 
    4244 void VBoxConsoleView::updateSliders()
    4245 {
    4246     QSize p = viewport()->size();
    4247     QSize m = maximumViewportSize();
    4248 
    4249     QSize v = QSize (mFrameBuf->width(), mFrameBuf->height());
    4250     /* no scroll bars needed */
    4251     if (m.expandedTo(v) == m)
    4252         p = m;
    4253 
    4254     horizontalScrollBar()->setRange(0, v.width() - p.width());
    4255     verticalScrollBar()->setRange(0, v.height() - p.height());
    4256     horizontalScrollBar()->setPageStep(p.width());
    4257     verticalScrollBar()->setPageStep(p.height());
    4258 }
    4259 
    4260 void VBoxConsoleView::requestToResize (const QSize &aSize)
    4261 {
    4262     mIgnoreFrameBufferResize = true;
    4263     mNormalSize = aSize;
    4264 }
    4265 
    4266 #if defined(Q_WS_MAC)
    4267 
    4268 void VBoxConsoleView::updateDockIcon()
    4269 {
    4270     if (mDockIconEnabled)
    4271     {
    4272         if (!mPausedShot.isNull())
    4273         {
    4274             CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot);
    4275             /* Use the pause image as background */
    4276             mDockIconPreview->updateDockPreview (pauseImg);
    4277             CGImageRelease (pauseImg);
    4278         }
    4279         else
    4280         {
    4281 # if defined (VBOX_GUI_USE_QUARTZ2D)
    4282             if (mode == VBoxDefs::Quartz2DMode)
    4283             {
    4284                 /* If the render mode is Quartz2D we could use the CGImageRef
    4285                  * of the framebuffer for the dock icon creation. This saves
    4286                  * some conversion time. */
    4287                 mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef());
    4288             }
    4289             else
    4290 # endif
    4291                 /* In image mode we have to create the image ref out of the
    4292                  * framebuffer */
    4293                 mDockIconPreview->updateDockPreview (mFrameBuf);
    4294         }
    4295     }
    4296 }
    4297 
    4298 void VBoxConsoleView::updateDockOverlay()
    4299 {
    4300     /* Only to an update to the realtime preview if this is enabled by the user
    4301      * & we are in an state where the framebuffer is likely valid. Otherwise to
    4302      * the overlay stuff only. */
    4303     if (mDockIconEnabled &&
    4304         (mLastState == KMachineState_Running ||
    4305          mLastState == KMachineState_Paused ||
    4306          mLastState == KMachineState_Teleporting ||
    4307          mLastState == KMachineState_LiveSnapshotting ||
    4308          mLastState == KMachineState_Restoring ||
    4309          mLastState == KMachineState_TeleportingPausedVM ||
    4310          mLastState == KMachineState_TeleportingIn ||
    4311          mLastState == KMachineState_Saving))
    4312         updateDockIcon();
    4313     else
    4314         mDockIconPreview->updateDockOverlay();
    4315 }
    4316 
    4317 /**
    4318  * Wrapper for SetMouseCoalescingEnabled().
    4319  *
    4320  * Called by eventFilter() and darwinGrabKeyboardEvents().
    4321  *
    4322  * @param   aOn     Switch it on (true) or off (false).
    4323  */
    4324 void VBoxConsoleView::setMouseCoalescingEnabled (bool aOn)
    4325 {
    4326     /* Enable mouse event compression if we leave the VM view. This
    4327        is necessary for having smooth resizing of the VM/other
    4328        windows.
    4329        Disable mouse event compression if we enter the VM view. So
    4330        all mouse events are registered in the VM. Only do this if
    4331        the keyboard/mouse is grabbed (this is when we have a valid
    4332        event handler). */
    4333     if (aOn || mKeyboardGrabbed)
    4334         ::darwinSetMouseCoalescingEnabled (aOn);
    4335 }
    4336 
    4337 #endif /* Q_WS_MAC */
    4338 
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h

    r26688 r26691  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * VBoxConsoleView class implementation
     4 * UISession class declaration
    55 */
    66
    77/*
    8  * Copyright (C) 22006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2010 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121 */
    2222
    23 #ifdef VBOX_WITH_PRECOMPILED_HEADERS
    24 # include "precomp.h"
    25 #else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
    26 #include <VBox/VBoxVideo.h>
     23#ifndef ___UIConsole_h___
     24#define ___UIConsole_h___
    2725
    28 #include "VBoxConsoleView.h"
    29 #include "VBoxConsoleWnd.h"
    30 #include "VBoxUtils.h"
     26/* Global includes */
     27#include <QObject>
    3128
    32 #include "VBoxFrameBuffer.h"
    33 #include "VBoxGlobal.h"
    34 #include "VBoxProblemReporter.h"
     29/* Local includes */
     30#include "COMDefs.h"
    3531
    36 #ifdef Q_WS_PM
    37 #include "QIHotKeyEdit.h"
    38 #endif
     32/* Local forwards */
     33class UIMachine;
     34class UIConsoleCallback;
    3935
    40 /* Qt includes */
    41 #include <QMenuBar>
    42 #include <QDesktopWidget>
    43 #include <QTimer>
    44 #include <QStatusBar>
    45 #include <QPainter>
    46 #include <QBitmap>
    47 
    48 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ /** @todo Move this further down! Requires some cleanup below though, so later. */
    49 
    50 #ifdef Q_WS_WIN
    51 // VBox/cdefs.h defines these:
    52 #undef LOWORD
    53 #undef HIWORD
    54 #undef LOBYTE
    55 #undef HIBYTE
    56 #include <windows.h>
    57 #endif
    58 
    59 #ifdef Q_WS_X11
    60 #include <QX11Info>
    61 // We need to capture some X11 events directly which
    62 // requires the XEvent structure to be defined. However,
    63 // including the Xlib header file will cause some nasty
    64 // conflicts with Qt. Therefore we use the following hack
    65 // to redefine those conflicting identifiers.
    66 #define XK_XKB_KEYS
    67 #define XK_MISCELLANY
    68 #include <X11/Xlib.h>
    69 #include <X11/Xutil.h>
    70 #include <X11/XKBlib.h>
    71 #include <X11/keysym.h>
    72 #ifdef KeyPress
    73 const int XFocusOut = FocusOut;
    74 const int XFocusIn = FocusIn;
    75 const int XKeyPress = KeyPress;
    76 const int XKeyRelease = KeyRelease;
    77 #undef KeyRelease
    78 #undef KeyPress
    79 #undef FocusOut
    80 #undef FocusIn
    81 #endif
    82 #include "XKeyboard.h"
    83 #ifndef VBOX_WITHOUT_XCURSOR
    84 # include <X11/Xcursor/Xcursor.h>
    85 #endif
    86 #endif // Q_WS_X11
    87 
    88 #if defined (Q_WS_MAC)
    89 # include "DockIconPreview.h"
    90 # include "DarwinKeyboard.h"
    91 # ifdef QT_MAC_USE_COCOA
    92 #  include "darwin/VBoxCocoaApplication.h"
    93 # elif defined(VBOX_WITH_HACKED_QT)
    94 #  include "QIApplication.h"
    95 # endif
    96 # include <Carbon/Carbon.h>
    97 # include <VBox/err.h>
    98 #endif /* defined (Q_WS_MAC) */
    99 
    100 #if defined (Q_WS_WIN32)
    101 
    102 static HHOOK gKbdHook = NULL;
    103 static VBoxConsoleView *gView = 0;
    104 
    105 LRESULT CALLBACK VBoxConsoleView::lowLevelKeyboardProc (int nCode,
    106                                                         WPARAM wParam, LPARAM lParam)
     36/* CConsole callback event types: */
     37enum UIConsoleEventType
    10738{
    108     Assert (gView);
    109     if (gView && nCode == HC_ACTION &&
    110             gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam))
    111         return 1;
    112 
    113     return CallNextHookEx (NULL, nCode, wParam, lParam);
    114 }
    115 
    116 #endif
    117 
    118 #if defined (Q_WS_MAC)
    119 # if defined (QT_MAC_USE_COCOA)
    120 /**
    121  * Event handler callback for Mac OS X, Cocoa variant.
    122  *
    123  * (Registered with and called from VBoxCocoaApplication.)
    124  *
    125  * @returns true if the event should be dropped, false if it should be passed
    126  *          along.
    127  * @param   pvCocoaEvent    The Cocoa event object.
    128  * @param   pvCarbonEvent   The Carbon event object reference.
    129  * @param   pvUser          The user argument.
    130  */
    131 /* static */
    132 bool VBoxConsoleView::darwinEventHandlerProc (const void *pvCocoaEvent,
    133                                               const void *pvCarbonEvent,
    134                                               void *pvUser)
    135 {
    136     VBoxConsoleView    *view       = (VBoxConsoleView *)pvUser;
    137     EventRef            inEvent    = (EventRef)pvCarbonEvent;
    138     UInt32              eventClass = ::GetEventClass (inEvent);
    139 
    140 #if 0
    141     /* For debugging events. */
    142     if (eventClass != 'cute')
    143         ::VBoxCocoaApplication_printEvent ("view: ", pvCocoaEvent);
    144 #endif
    145     /* Check if this is an application key combo. In that case we will not pass
    146        the event to the guest, but let the host process it. */
    147     if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent))
    148         return false;
    149 
    150     /*
    151      * All keyboard class events needs to be handled.
    152      */
    153     if (eventClass == kEventClassKeyboard)
    154     {
    155         if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
    156             return true;
    157     }
    158     /* Pass the event along. */
    159     return false;
    160 }
    161 
    162 # elif !defined (VBOX_WITH_HACKED_QT)
    163 /**
    164  *  Event handler callback for Mac OS X.
    165  */
    166 /* static */
    167 pascal OSStatus VBoxConsoleView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef,
    168                                                          EventRef inEvent, void *inUserData)
    169 {
    170     VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);
    171     UInt32 eventClass = ::GetEventClass (inEvent);
    172 
    173     /* For debugging events */
    174     /*
    175     if (eventClass != 'cute')
    176         ::darwinDebugPrintEvent ("view: ", inEvent);
    177     */
    178 
    179     /* Not sure but this seems an triggered event if the spotlight searchbar is
    180      * displayed. So flag that the host key isn't pressed alone. */
    181     if (   eventClass == 'cgs '
    182         && view->mIsHostkeyPressed
    183         && ::GetEventKind (inEvent) == 0x15)
    184         view->mIsHostkeyAlone = false;
    185 
    186     if (eventClass == kEventClassKeyboard)
    187     {
    188         if (view->darwinKeyboardEvent (NULL, inEvent))
    189             return 0;
    190     }
    191     /*
    192      * Command-H and Command-Q aren't properly disabled yet, and it's still
    193      * possible to use the left command key to invoke them when the keyboard
    194      * is captured. We discard the events these if the keyboard is captured
    195      * as a half measure to prevent unexpected behaviour. However, we don't
    196      * get any key down/up events, so these combinations are dead to the guest...
    197      */
    198     else if (eventClass == kEventClassCommand)
    199     {
    200         if (view->mKbdCaptured)
    201             return 0;
    202     }
    203     return ::CallNextEventHandler (inHandlerCallRef, inEvent);
    204 }
    205 
    206 # else /* VBOX_WITH_HACKED_QT */
    207 /**
    208  *  Event handler callback for Mac OS X.
    209  */
    210 /* static */
    211 bool VBoxConsoleView::macEventFilter (EventRef inEvent, void *inUserData)
    212 {
    213     VBoxConsoleView *view = static_cast<VBoxConsoleView *> (inUserData);
    214     UInt32 eventClass = ::GetEventClass (inEvent);
    215     UInt32 eventKind = ::GetEventKind (inEvent);
    216 
    217     /* For debugging events */
    218     /*
    219     if (!(eventClass == 'cute'))
    220         ::darwinDebugPrintEvent ("view: ", inEvent);
    221     */
    222 
    223     /* Not sure but this seems an triggered event if the spotlight searchbar is
    224      * displayed. So flag that the host key isn't pressed alone. */
    225     if (eventClass == 'cgs ' && eventKind == 0x15 &&
    226         view->mIsHostkeyPressed)
    227         view->mIsHostkeyAlone = false;
    228 
    229     if (eventClass == kEventClassKeyboard)
    230     {
    231         if (view->darwinKeyboardEvent (NULL, inEvent))
    232             return true;
    233     }
    234     return false;
    235 }
    236 # endif /* VBOX_WITH_HACKED_QT */
    237 
    238 #endif /* Q_WS_MAC */
    239 
    240 /** Guest mouse pointer shape change event. */
    241 class MousePointerChangeEvent : public QEvent
    242 {
    243 public:
    244     MousePointerChangeEvent (bool visible, bool alpha, uint xhot, uint yhot,
    245                              uint width, uint height,
    246                              const uchar *shape) :
    247         QEvent ((QEvent::Type) VBoxDefs::MousePointerChangeEventType),
    248         vis (visible), alph (alpha), xh (xhot), yh (yhot), w (width), h (height),
    249         data (NULL)
    250     {
    251         // make a copy of shape
    252         uint dataSize = ((((width + 7) / 8 * height) + 3) & ~3) + width * 4 * height;
    253 
    254         if (shape) {
    255             data = new uchar [dataSize];
    256             memcpy ((void *) data, (void *) shape, dataSize);
    257         }
    258     }
    259     ~MousePointerChangeEvent()
    260     {
    261         if (data) delete[] data;
    262     }
    263     bool isVisible() const { return vis; }
    264     bool hasAlpha() const { return alph; }
    265     uint xHot() const { return xh; }
    266     uint yHot() const { return yh; }
    267     uint width() const { return w; }
    268     uint height() const { return h; }
    269     const uchar *shapeData() const { return data; }
    270 private:
    271     bool vis, alph;
    272     uint xh, yh, w, h;
    273     const uchar *data;
     39    UIConsoleEventType_MousePointerShapeChange = QEvent::User + 1,
     40    UIConsoleEventType_MouseCapabilityChange,
     41    UIConsoleEventType_KeyboardLedsChange,
     42    UIConsoleEventType_StateChange,
     43    UIConsoleEventType_AdditionsStateChange,
     44    UIConsoleEventType_NetworkAdapterChange,
     45    UIConsoleEventType_SerialPortChange,
     46    UIConsoleEventType_ParallelPortChange,
     47    UIConsoleEventType_StorageControllerChange,
     48    UIConsoleEventType_MediumChange,
     49    UIConsoleEventType_CPUChange,
     50    UIConsoleEventType_VRDPServerChange,
     51    UIConsoleEventType_RemoteDisplayInfoChange,
     52    UIConsoleEventType_USBControllerChange,
     53    UIConsoleEventType_USBDeviceStateChange,
     54    UIConsoleEventType_SharedFolderChange,
     55    UIConsoleEventType_RuntimeError,
     56    UIConsoleEventType_CanShowWindow,
     57    UIConsoleEventType_ShowWindow,
     58    UIConsoleEventType_MAX
    27459};
    27560
    276 /** Guest mouse absolute positioning capability change event. */
    277 class MouseCapabilityEvent : public QEvent
     61class UISession : public QObject
    27862{
     63    Q_OBJECT;
     64
    27965public:
    280     MouseCapabilityEvent (bool supportsAbsolute, bool needsHostCursor) :
    281         QEvent ((QEvent::Type) VBoxDefs::MouseCapabilityEventType),
    282         can_abs (supportsAbsolute),
    283         needs_host_cursor (needsHostCursor) {}
    284     bool supportsAbsolute() const { return can_abs; }
    285     bool needsHostCursor() const { return needs_host_cursor; }
     66
     67    /* Machine session constructor/destructor: */
     68    UISession(UIMachine *pMachine, const CSession &session);
     69    virtual ~UISession();
     70
     71    /* Public getters: */
     72    CSession& session() { return m_session; }
     73
     74signals:
     75
     76    /* Console signals: */
     77    void sigMousePointerShapeChange(bool bIsVisible, bool bHasAlpha, bool uXHot, bool uYHot, bool uWidth, bool uHeight, const uchar *pShapeData);
     78    void sigMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor);
     79    void sigKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock);
     80    void sigStateChange(KMachineState machineState);
     81    void sigAdditionsStateChange();
     82    void sigNetworkAdapterChange(const CNetworkAdapter &networkAdapter);
     83    void sigSerialPortChange(const CSerialPort &serialPort);
     84    void sigParallelPortChange(const CParallelPort &parallelPort);
     85    void sigStorageControllerChange();
     86    void sigMediumChange(const CMediumAttachment &mediumAttachment);
     87    void sigCPUChange(ulong uCPU, bool bRemove);
     88    void sigVRDPServerChange();
     89    void sigRemoteDisplayInfoChange();
     90    void sigUSBControllerChange();
     91    void sigUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error);
     92    void sigSharedFolderChange();
     93    void sigRuntimeError(bool bIsFatal, QString strErrorId, QString strMessage);
     94
    28695private:
    287     bool can_abs;
    288     bool needs_host_cursor;
     96
     97    /* Private getters: */
     98    UIMachine* machine() const { return m_pMachine; }
     99
     100    /* Event handlers: */
     101    bool event(QEvent *pEvent);
     102
     103    /* Helper routines: */
     104    qulonglong winId() const;
     105
     106    /* Private variables: */
     107    UIMachine *m_pMachine;
     108    CSession m_session;
     109    UIConsoleCallback *m_pCallback;
     110    const CConsoleCallback &m_callback;
     111
     112    /* Friend classes: */
     113    friend class UIConsoleCallback;
    289114};
    290115
    291 /** Machine state change. */
    292 class StateChangeEvent : public QEvent
    293 {
    294 public:
    295     StateChangeEvent (KMachineState state) :
    296         QEvent ((QEvent::Type) VBoxDefs::MachineStateChangeEventType),
    297         s (state) {}
    298     KMachineState machineState() const { return s; }
    299 private:
    300     KMachineState s;
    301 };
    302 
    303 /** Guest Additions property changes. */
    304 class GuestAdditionsEvent : public QEvent
    305 {
    306 public:
    307     GuestAdditionsEvent (const QString &aOsTypeId,
    308                          const QString &aAddVersion,
    309                          bool aAddActive,
    310                          bool aSupportsSeamless,
    311                          bool aSupportsGraphics) :
    312         QEvent ((QEvent::Type) VBoxDefs::AdditionsStateChangeEventType),
    313         mOsTypeId (aOsTypeId), mAddVersion (aAddVersion),
    314         mAddActive (aAddActive), mSupportsSeamless (aSupportsSeamless),
    315         mSupportsGraphics (aSupportsGraphics) {}
    316     const QString &osTypeId() const { return mOsTypeId; }
    317     const QString &additionVersion() const { return mAddVersion; }
    318     bool additionActive() const { return mAddActive; }
    319     bool supportsSeamless() const { return mSupportsSeamless; }
    320     bool supportsGraphics() const { return mSupportsGraphics; }
    321 private:
    322     QString mOsTypeId;
    323     QString mAddVersion;
    324     bool mAddActive;
    325     bool mSupportsSeamless;
    326     bool mSupportsGraphics;
    327 };
    328 
    329 /** DVD/Floppy drive change event */
    330 class MediaDriveChangeEvent : public QEvent
    331 {
    332 public:
    333     MediaDriveChangeEvent (VBoxDefs::MediumType aType)
    334         : QEvent ((QEvent::Type) VBoxDefs::MediaDriveChangeEventType)
    335         , mType (aType) {}
    336     VBoxDefs::MediumType type() const { return mType; }
    337 private:
    338     VBoxDefs::MediumType mType;
    339 };
    340 
    341 /** Menu activation event */
    342 class ActivateMenuEvent : public QEvent
    343 {
    344 public:
    345     ActivateMenuEvent (QAction *aData) :
    346         QEvent ((QEvent::Type) VBoxDefs::ActivateMenuEventType),
    347         mAction (aData) {}
    348     QAction *action() const { return mAction; }
    349 private:
    350     QAction *mAction;
    351 };
    352 
    353 /** VM Runtime error event */
    354 class RuntimeErrorEvent : public QEvent
    355 {
    356 public:
    357     RuntimeErrorEvent (bool aFatal, const QString &aErrorID,
    358                        const QString &aMessage) :
    359         QEvent ((QEvent::Type) VBoxDefs::RuntimeErrorEventType),
    360         mFatal (aFatal), mErrorID (aErrorID), mMessage (aMessage) {}
    361     bool fatal() const { return mFatal; }
    362     QString errorID() const { return mErrorID; }
    363     QString message() const { return mMessage; }
    364 private:
    365     bool mFatal;
    366     QString mErrorID;
    367     QString mMessage;
    368 };
    369 
    370 /** Modifier key change event */
    371 class ModifierKeyChangeEvent : public QEvent
    372 {
    373 public:
    374     ModifierKeyChangeEvent (bool fNumLock, bool fCapsLock, bool fScrollLock) :
    375         QEvent ((QEvent::Type) VBoxDefs::ModifierKeyChangeEventType),
    376         mNumLock (fNumLock), mCapsLock (fCapsLock), mScrollLock (fScrollLock) {}
    377     bool numLock()    const { return mNumLock; }
    378     bool capsLock()   const { return mCapsLock; }
    379     bool scrollLock() const { return mScrollLock; }
    380 private:
    381     bool mNumLock, mCapsLock, mScrollLock;
    382 };
    383 
    384 /** Network adapter change event */
    385 class NetworkAdapterChangeEvent : public QEvent
    386 {
    387 public:
    388     NetworkAdapterChangeEvent (INetworkAdapter *aAdapter) :
    389         QEvent ((QEvent::Type) VBoxDefs::NetworkAdapterChangeEventType),
    390         mAdapter (aAdapter) {}
    391     INetworkAdapter* networkAdapter() { return mAdapter; }
    392 private:
    393     INetworkAdapter *mAdapter;
    394 };
    395 
    396 /** USB controller state change event */
    397 class USBControllerStateChangeEvent : public QEvent
    398 {
    399 public:
    400     USBControllerStateChangeEvent()
    401         : QEvent ((QEvent::Type) VBoxDefs::USBCtlStateChangeEventType) {}
    402 };
    403 
    404 /** USB device state change event */
    405 class USBDeviceStateChangeEvent : public QEvent
    406 {
    407 public:
    408     USBDeviceStateChangeEvent (const CUSBDevice &aDevice, bool aAttached,
    409                                const CVirtualBoxErrorInfo &aError) :
    410         QEvent ((QEvent::Type) VBoxDefs::USBDeviceStateChangeEventType),
    411         mDevice (aDevice), mAttached (aAttached), mError (aError) {}
    412     CUSBDevice device() const { return mDevice; }
    413     bool attached() const { return mAttached; }
    414     CVirtualBoxErrorInfo error() const { return mError; }
    415 private:
    416     CUSBDevice mDevice;
    417     bool mAttached;
    418     CVirtualBoxErrorInfo mError;
    419 };
    420 
    421 //
    422 // VBoxConsoleCallback class
    423 /////////////////////////////////////////////////////////////////////////////
    424 
    425 class VBoxConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
    426 {
    427 public:
    428 
    429     VBoxConsoleCallback (VBoxConsoleView *v) {
    430 #if defined (Q_WS_WIN)
    431         mRefCnt = 0;
    432 #endif
    433         mView = v;
    434     }
    435 
    436     virtual ~VBoxConsoleCallback() {}
    437 
    438     NS_DECL_ISUPPORTS
    439 
    440 #if defined (Q_WS_WIN)
    441     STDMETHOD_(ULONG, AddRef)() {
    442         return ::InterlockedIncrement (&mRefCnt);
    443     }
    444     STDMETHOD_(ULONG, Release)()
    445     {
    446         long cnt = ::InterlockedDecrement (&mRefCnt);
    447         if (cnt == 0)
    448             delete this;
    449         return cnt;
    450     }
    451 #endif
    452     VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
    453 
    454     STDMETHOD(OnMousePointerShapeChange) (BOOL visible, BOOL alpha,
    455                                           ULONG xhot, ULONG yhot,
    456                                           ULONG width, ULONG height,
    457                                           BYTE *shape)
    458     {
    459         QApplication::postEvent (mView,
    460                                  new MousePointerChangeEvent (visible, alpha,
    461                                                               xhot, yhot,
    462                                                               width, height, shape));
    463         return S_OK;
    464     }
    465 
    466     STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
    467     {
    468         QApplication::postEvent (mView,
    469                                  new MouseCapabilityEvent (supportsAbsolute,
    470                                                            needsHostCursor));
    471         return S_OK;
    472     }
    473 
    474     STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
    475     {
    476         QApplication::postEvent (mView,
    477                                  new ModifierKeyChangeEvent (fNumLock, fCapsLock,
    478                                                              fScrollLock));
    479         return S_OK;
    480     }
    481 
    482     STDMETHOD(OnStateChange)(MachineState_T machineState)
    483     {
    484         LogFlowFunc (("machineState=%d\n", machineState));
    485         QApplication::postEvent (mView,
    486                                  new StateChangeEvent ((KMachineState) machineState));
    487         return S_OK;
    488     }
    489 
    490     STDMETHOD(OnAdditionsStateChange)()
    491     {
    492         CGuest guest = mView->console().GetGuest();
    493         LogFlowFunc (("ver=%s, active=%d\n",
    494                       guest.GetAdditionsVersion().toLatin1().constData(),
    495                       guest.GetAdditionsActive()));
    496         QApplication::postEvent (mView,
    497                                  new GuestAdditionsEvent (
    498                                      guest.GetOSTypeId(),
    499                                      guest.GetAdditionsVersion(),
    500                                      guest.GetAdditionsActive(),
    501                                      guest.GetSupportsSeamless(),
    502                                      guest.GetSupportsGraphics()));
    503         return S_OK;
    504     }
    505 
    506     STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
    507     {
    508         QApplication::postEvent (mView,
    509             new NetworkAdapterChangeEvent (aNetworkAdapter));
    510         return S_OK;
    511     }
    512 
    513     STDMETHOD(OnStorageControllerChange) ()
    514     {
    515         /* @todo */
    516         //QApplication::postEvent (mView,
    517         //    new StorageControllerChangeEvent ());
    518         return S_OK;
    519     }
    520 
    521     STDMETHOD(OnMediumChange)(IMediumAttachment *aMediumAttachment)
    522     {
    523         CMediumAttachment att(aMediumAttachment);
    524         switch (att.GetType())
    525         {
    526             case KDeviceType_Floppy:
    527                 QApplication::postEvent(mView,
    528                     new MediaDriveChangeEvent(VBoxDefs::MediumType_Floppy));
    529                 break;
    530             case KDeviceType_DVD:
    531                 QApplication::postEvent(mView,
    532                     new MediaDriveChangeEvent(VBoxDefs::MediumType_DVD));
    533                 break;
    534             default:
    535                 /* @todo later add hard disk change as well */
    536                 break;
    537         }
    538         return S_OK;
    539     }
    540 
    541     STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove)
    542     {
    543         NOREF(aCPU);
    544         NOREF(aRemove);
    545         return S_OK;
    546     }
    547 
    548     STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
    549     {
    550         NOREF(aSerialPort);
    551         return S_OK;
    552     }
    553 
    554     STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
    555     {
    556         NOREF(aParallelPort);
    557         return S_OK;
    558     }
    559 
    560     STDMETHOD(OnVRDPServerChange)()
    561     {
    562         return S_OK;
    563     }
    564 
    565     STDMETHOD(OnRemoteDisplayInfoChange)()
    566     {
    567         return S_OK;
    568     }
    569 
    570     STDMETHOD(OnUSBControllerChange)()
    571     {
    572         QApplication::postEvent (mView,
    573                                  new USBControllerStateChangeEvent());
    574         return S_OK;
    575     }
    576 
    577     STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached,
    578                                       IVirtualBoxErrorInfo *aError)
    579     {
    580         QApplication::postEvent (mView,
    581                                  new USBDeviceStateChangeEvent (
    582                                      CUSBDevice (aDevice),
    583                                      bool (aAttached),
    584                                      CVirtualBoxErrorInfo (aError)));
    585         return S_OK;
    586     }
    587 
    588     STDMETHOD(OnSharedFolderChange) (Scope_T aScope)
    589     {
    590         NOREF(aScope);
    591         QApplication::postEvent (mView,
    592                                  new QEvent ((QEvent::Type)
    593                                              VBoxDefs::SharedFolderChangeEventType));
    594         return S_OK;
    595     }
    596 
    597     STDMETHOD(OnRuntimeError)(BOOL fatal, IN_BSTR id, IN_BSTR message)
    598     {
    599         QApplication::postEvent (mView,
    600                                  new RuntimeErrorEvent (!!fatal,
    601                                                         QString::fromUtf16 (id),
    602                                                         QString::fromUtf16 (message)));
    603         return S_OK;
    604     }
    605 
    606     STDMETHOD(OnCanShowWindow) (BOOL *canShow)
    607     {
    608         if (!canShow)
    609             return E_POINTER;
    610 
    611         /* as long as there is VBoxConsoleView (which creates/destroys us), it
    612          * can be shown */
    613         *canShow = TRUE;
    614         return S_OK;
    615     }
    616 
    617     STDMETHOD(OnShowWindow) (ULONG64 *winId)
    618     {
    619         if (!winId)
    620             return E_POINTER;
    621 
    622 #if defined (Q_WS_MAC)
    623         /*
    624          * Let's try the simple approach first - grab the focus.
    625          * Getting a window out of the dock (minimized or whatever it's called)
    626          * needs to be done on the GUI thread, so post it a note.
    627          */
    628         *winId = 0;
    629         if (!mView)
    630             return S_OK;
    631 
    632         ProcessSerialNumber psn = { 0, kCurrentProcess };
    633         OSErr rc = ::SetFrontProcess (&psn);
    634         if (!rc)
    635             QApplication::postEvent (mView, new QEvent ((QEvent::Type)VBoxDefs::ShowWindowEventType));
    636         else
    637         {
    638             /*
    639              * It failed for some reason, send the other process our PSN so it can try.
    640              * (This is just a precaution should Mac OS X start imposing the same sensible
    641              * focus stealing restrictions that other window managers implement.)
    642              */
    643             AssertMsgFailed(("SetFrontProcess -> %#x\n", rc));
    644             if (::GetCurrentProcess (&psn))
    645                 *winId = RT_MAKE_U64 (psn.lowLongOfPSN, psn.highLongOfPSN);
    646         }
    647 
    648 #else
    649         /* Return the ID of the top-level console window. */
    650         *winId = (ULONG64) mView->window()->winId();
    651 #endif
    652 
    653         return S_OK;
    654     }
    655 
    656 protected:
    657 
    658     VBoxConsoleView *mView;
    659 
    660 #if defined (Q_WS_WIN)
    661 private:
    662     long mRefCnt;
    663 #endif
    664 };
    665 
    666 #if !defined (Q_WS_WIN)
    667 NS_DECL_CLASSINFO (VBoxConsoleCallback)
    668 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (VBoxConsoleCallback, IConsoleCallback)
    669 #endif
    670 
    671 class VBoxViewport: public QWidget
    672 {
    673 public:
    674     VBoxViewport (QWidget *aParent)
    675         : QWidget (aParent)
    676     {
    677         /* No need for background drawing */
    678         setAttribute (Qt::WA_OpaquePaintEvent);
    679     }
    680     virtual QPaintEngine * paintEngine() const
    681     {
    682         if (testAttribute (Qt::WA_PaintOnScreen))
    683             return NULL;
    684         else
    685             return QWidget::paintEngine();
    686     }
    687 };
    688 
    689 //
    690 // VBoxConsoleView class
    691 /////////////////////////////////////////////////////////////////////////////
    692 
    693 /** @class VBoxConsoleView
    694  *
    695  *  The VBoxConsoleView class is a widget that implements a console
    696  *  for the running virtual machine.
    697  */
    698 
    699 VBoxConsoleView::VBoxConsoleView (VBoxConsoleWnd *mainWnd,
    700                                   const CConsole &console,
    701                                   VBoxDefs::RenderMode rm,
    702 #ifdef VBOX_WITH_VIDEOHWACCEL
    703                                   bool accelerate2DVideo,
    704 #endif
    705                                   QWidget *parent)
    706     : QAbstractScrollArea (parent)
    707     , mMainWnd (mainWnd)
    708     , mConsole (console)
    709     , gs (vboxGlobal().settings())
    710     , mAttached (false)
    711     , mKbdCaptured (false)
    712     , mMouseCaptured (false)
    713     , mMouseAbsolute (false)
    714     , mMouseIntegration (true)
    715     , m_iLastMouseWheelDelta(0)
    716     , mDisableAutoCapture (false)
    717     , mIsHostkeyPressed (false)
    718     , mIsHostkeyAlone (false)
    719     , mIgnoreMainwndResize (true)
    720     , mAutoresizeGuest (false)
    721     , mIgnoreFrameBufferResize (false)
    722     , mIgnoreGuestResize (false)
    723     , mDoResize (false)
    724     , mGuestSupportsGraphics (false)
    725     , mNumLock (false)
    726     , mScrollLock (false)
    727     , mCapsLock (false)
    728     , muNumLockAdaptionCnt (2)
    729     , muCapsLockAdaptionCnt (2)
    730     , mode (rm)
    731 #ifdef VBOX_WITH_VIDEOHWACCEL
    732     , mAccelerate2DVideo(accelerate2DVideo)
    733 #endif
    734 #if defined(Q_WS_WIN)
    735     , mAlphaCursor (NULL)
    736 #endif
    737 #if defined(Q_WS_MAC)
    738 # if !defined (VBOX_WITH_HACKED_QT) && !defined (QT_MAC_USE_COCOA)
    739     , mDarwinEventHandlerRef (NULL)
    740 # endif
    741     , mDarwinKeyModifiers (0)
    742     , mKeyboardGrabbed (false)
    743     , mDockIconEnabled (true)
    744 #endif
    745     , mDesktopGeo (DesktopGeo_Invalid)
    746     , mPassCAD (false)
    747       /* Don't show a hardware pointer until we have one to show */
    748     , mHideHostPointer (true)
    749 {
    750     Assert (!mConsole.isNull() &&
    751             !mConsole.GetDisplay().isNull() &&
    752             !mConsole.GetKeyboard().isNull() &&
    753             !mConsole.GetMouse().isNull());
    754 
    755 #ifdef Q_WS_MAC
    756     /* Overlay logo for the dock icon */
    757     QString osTypeId = mConsole.GetGuest().GetOSTypeId();
    758     mDockIconPreview = new VBoxDockIconPreview (mMainWnd, vboxGlobal().vmGuestOSTypeIcon (osTypeId));
    759 
    760 # ifdef QT_MAC_USE_COCOA
    761     /** @todo Carbon -> Cocoa */
    762 # else /* !QT_MAC_USE_COCOA */
    763     /* Install the event handler which will proceed external window handling */
    764     EventHandlerUPP eventHandler = ::NewEventHandlerUPP (::darwinOverlayWindowHandler);
    765     EventTypeSpec eventTypes[] =
    766     {
    767         { kEventClassVBox, kEventVBoxShowWindow },
    768         { kEventClassVBox, kEventVBoxHideWindow },
    769         { kEventClassVBox, kEventVBoxMoveWindow },
    770         { kEventClassVBox, kEventVBoxResizeWindow },
    771         { kEventClassVBox, kEventVBoxDisposeWindow },
    772         { kEventClassVBox, kEventVBoxUpdateDock }
    773     };
    774 
    775     mDarwinWindowOverlayHandlerRef = NULL;
    776     ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
    777                                       this, &mDarwinWindowOverlayHandlerRef);
    778     ::DisposeEventHandlerUPP (eventHandler);
    779 # endif /* !QT_MAC_USE_COCOA */
    780 #endif /* QT_WS_MAC */
    781 
    782     /* No frame around the view */
    783     setFrameStyle (QFrame::NoFrame);
    784 
    785 #ifdef VBOX_GUI_USE_QGL
    786     QWidget *pViewport;
    787     switch (mode)
    788     {
    789         case VBoxDefs::QGLMode:
    790             pViewport = new VBoxGLWidget (this, this, NULL);
    791             break;
    792         default:
    793             pViewport = new VBoxViewport (this);
    794     }
    795 #else
    796     VBoxViewport *pViewport = new VBoxViewport (this);
    797 #endif
    798     setViewport (pViewport);
    799 //    pViewport->vboxDoInit();
    800 
    801     /* enable MouseMove events */
    802     viewport()->setMouseTracking (true);
    803 
    804     /*
    805      *  QScrollView does the below on its own, but let's do it anyway
    806      *  for the case it will not do it in the future.
    807      */
    808     viewport()->installEventFilter (this);
    809 
    810     /* to fix some focus issues */
    811     mMainWnd->menuBar()->installEventFilter (this);
    812 
    813     /* we want to be notified on some parent's events */
    814     mMainWnd->installEventFilter (this);
    815 
    816 #ifdef Q_WS_X11
    817     /* initialize the X keyboard subsystem */
    818     initMappedX11Keyboard(QX11Info::display(),
    819             vboxGlobal().settings().publicProperty ("GUI/RemapScancodes"));
    820 #endif
    821 
    822     ::memset (mPressedKeys, 0, sizeof (mPressedKeys));
    823 
    824     /* setup rendering */
    825 
    826     CDisplay display = mConsole.GetDisplay();
    827     Assert (!display.isNull());
    828 
    829     mFrameBuf = NULL;
    830 
    831     LogFlowFunc (("Rendering mode: %d\n", mode));
    832 
    833     switch (mode)
    834     {
    835 #if defined (VBOX_GUI_USE_QGL)
    836         case VBoxDefs::QGLMode:
    837             mFrameBuf = new VBoxQGLFrameBuffer (this);
    838             break;
    839 //        case VBoxDefs::QGLOverlayMode:
    840 //            mFrameBuf = new VBoxQGLOverlayFrameBuffer (this);
    841 //            break;
    842 #endif
    843 #if defined (VBOX_GUI_USE_QIMAGE)
    844         case VBoxDefs::QImageMode:
    845             mFrameBuf =
    846 #ifdef VBOX_WITH_VIDEOHWACCEL
    847                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQImageFrameBuffer> (this, &mainWnd->session()) :
    848 #endif
    849                     new VBoxQImageFrameBuffer (this);
    850             break;
    851 #endif
    852 #if defined (VBOX_GUI_USE_SDL)
    853         case VBoxDefs::SDLMode:
    854             /* Indicate that we are doing all
    855              * drawing stuff ourself */
    856             pViewport->setAttribute (Qt::WA_PaintOnScreen);
    857 # ifdef Q_WS_X11
    858             /* This is somehow necessary to prevent strange X11 warnings on
    859              * i386 and segfaults on x86_64. */
    860             XFlush(QX11Info::display());
    861 # endif
    862             mFrameBuf =
    863 #if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
    864                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxSDLFrameBuffer> (this, &mainWnd->session()) :
    865 #endif
    866                     new VBoxSDLFrameBuffer (this);
    867             /*
    868              *  disable scrollbars because we cannot correctly draw in a
    869              *  scrolled window using SDL
    870              */
    871             horizontalScrollBar()->setEnabled (false);
    872             verticalScrollBar()->setEnabled (false);
    873             break;
    874 #endif
    875 #if defined (VBOX_GUI_USE_DDRAW)
    876         case VBoxDefs::DDRAWMode:
    877             mFrameBuf = new VBoxDDRAWFrameBuffer (this);
    878             break;
    879 #endif
    880 #if defined (VBOX_GUI_USE_QUARTZ2D)
    881         case VBoxDefs::Quartz2DMode:
    882             /* Indicate that we are doing all
    883              * drawing stuff ourself */
    884             pViewport->setAttribute (Qt::WA_PaintOnScreen);
    885             mFrameBuf =
    886 #ifdef VBOX_WITH_VIDEOHWACCEL
    887                     mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer> (this, &mainWnd->session()) :
    888 #endif
    889                     new VBoxQuartz2DFrameBuffer (this);
    890             break;
    891 #endif
    892         default:
    893             AssertReleaseMsgFailed (("Render mode must be valid: %d\n", mode));
    894             LogRel (("Invalid render mode: %d\n", mode));
    895             qApp->exit (1);
    896             break;
    897     }
    898 
    899 #if defined (VBOX_GUI_USE_DDRAW)
    900     if (!mFrameBuf || mFrameBuf->address() == NULL)
    901     {
    902         if (mFrameBuf)
    903             delete mFrameBuf;
    904         mode = VBoxDefs::QImageMode;
    905         mFrameBuf = new VBoxQImageFrameBuffer (this);
    906     }
    907 #endif
    908 
    909     if (mFrameBuf)
    910     {
    911         mFrameBuf->AddRef();
    912         display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer (mFrameBuf));
    913     }
    914 
    915     /* setup the callback */
    916     mCallback = CConsoleCallback (new VBoxConsoleCallback (this));
    917     mConsole.RegisterCallback (mCallback);
    918     AssertWrapperOk (mConsole);
    919 
    920     QPalette palette (viewport()->palette());
    921     palette.setColor (viewport()->backgroundRole(), Qt::black);
    922     viewport()->setPalette (palette);
    923 
    924     setSizePolicy (QSizePolicy (QSizePolicy::Maximum, QSizePolicy::Maximum));
    925     setMaximumSize (sizeHint());
    926 
    927     setFocusPolicy (Qt::WheelFocus);
    928 
    929     /* Remember the desktop geometry and register for geometry change
    930        events for telling the guest about video modes we like. */
    931 
    932     QString desktopGeometry = vboxGlobal().settings()
    933                                   .publicProperty ("GUI/MaxGuestResolution");
    934     if ((desktopGeometry == QString::null) ||
    935         (desktopGeometry == "auto"))
    936         setDesktopGeometry (DesktopGeo_Automatic, 0, 0);
    937     else if (desktopGeometry == "any")
    938         setDesktopGeometry (DesktopGeo_Any, 0, 0);
    939     else
    940     {
    941         int width = desktopGeometry.section (',', 0, 0).toInt();
    942         int height = desktopGeometry.section (',', 1, 1).toInt();
    943         setDesktopGeometry (DesktopGeo_Fixed, width, height);
    944     }
    945     connect (QApplication::desktop(), SIGNAL (resized (int)),
    946              this, SLOT (doResizeDesktop (int)));
    947 
    948     QString passCAD = mConsole.GetMachine().GetExtraData (VBoxDefs::GUI_PassCAD);
    949     if (!passCAD.isEmpty() &&
    950         ((passCAD != "false") || (passCAD != "no"))
    951        )
    952         mPassCAD = true;
    953 
    954 #if defined (Q_WS_WIN)
    955     gView = this;
    956 #endif
    957 
    958 #if defined (Q_WS_PM)
    959     bool ok = VBoxHlpInstallKbdHook (0, winId(), UM_PREACCEL_CHAR);
    960     Assert (ok);
    961     NOREF (ok);
    962 #endif
    963 }
    964 
    965 VBoxConsoleView::~VBoxConsoleView()
    966 {
    967 #if defined (Q_WS_PM)
    968     bool ok = VBoxHlpUninstallKbdHook (0, winId(), UM_PREACCEL_CHAR);
    969     Assert (ok);
    970     NOREF (ok);
    971 #endif
    972 
    973 #if defined (Q_WS_WIN)
    974     if (gKbdHook)
    975         UnhookWindowsHookEx (gKbdHook);
    976     gView = 0;
    977     if (mAlphaCursor)
    978         DestroyIcon (mAlphaCursor);
    979 #endif
    980 
    981     if (mFrameBuf)
    982     {
    983         /* detach our framebuffer from Display */
    984         CDisplay display = mConsole.GetDisplay();
    985         Assert (!display.isNull());
    986         display.SetFramebuffer (VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL));
    987         /* release the reference */
    988         mFrameBuf->Release();
    989         mFrameBuf = NULL;
    990     }
    991 
    992     mConsole.UnregisterCallback (mCallback);
    993 
    994 #if defined (Q_WS_MAC)
    995 # if !defined (QT_MAC_USE_COCOA)
    996     if (mDarwinWindowOverlayHandlerRef)
    997     {
    998         ::RemoveEventHandler (mDarwinWindowOverlayHandlerRef);
    999         mDarwinWindowOverlayHandlerRef = NULL;
    1000     }
    1001 # endif
    1002     delete mDockIconPreview;
    1003     mDockIconPreview = NULL;
    1004 #endif
    1005 }
    1006 
    1007 //
    1008 // Public members
    1009 /////////////////////////////////////////////////////////////////////////////
    1010 
    1011 QSize VBoxConsoleView::sizeHint() const
    1012 {
    1013 #ifdef VBOX_WITH_DEBUGGER /** @todo figure out a more proper fix. */
    1014     /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done
    1015      *             by DevVGA if provoked before power on.  */
    1016     QSize fb(mFrameBuf->width(), mFrameBuf->height());
    1017     if (    (   fb.width()  < 16
    1018              || fb.height() < 16)
    1019         &&  (   vboxGlobal().isStartPausedEnabled()
    1020              || vboxGlobal().isDebuggerAutoShowEnabled()) )
    1021         fb = QSize(640, 480);
    1022     return QSize (fb.width() + frameWidth() * 2,
    1023                   fb.height() + frameWidth() * 2);
    1024 #else
    1025     return QSize (mFrameBuf->width() + frameWidth() * 2,
    1026                   mFrameBuf->height() + frameWidth() * 2);
    1027 #endif
    1028 }
    1029 
    1030 /**
    1031  *  Attaches this console view to the managed virtual machine.
    1032  *
    1033  *  @note This method is not really necessary these days -- the only place where
    1034  *        it gets called is VBoxConsole::openView(), right after powering the
    1035  *        VM up. We leave it as is just in case attaching/detaching will become
    1036  *        necessary some day (there are useful attached checks everywhere in the
    1037  *        code).
    1038  */
    1039 void VBoxConsoleView::attach()
    1040 {
    1041     if (!mAttached)
    1042     {
    1043         mAttached = true;
    1044     }
    1045 }
    1046 
    1047 /**
    1048  *  Detaches this console view from the VM. Must be called to indicate
    1049  *  that the virtual machine managed by this instance will be no more valid
    1050  *  after this call.
    1051  *
    1052  *  @note This method is not really necessary these days -- the only place where
    1053  *        it gets called is VBoxConsole::closeView(), when the VM is powered
    1054  *        down, before deleting VBoxConsoleView. We leave it as is just in case
    1055  *        attaching/detaching will become necessary some day (there are useful
    1056  *        attached checks everywhere in the code).
    1057  */
    1058 void VBoxConsoleView::detach()
    1059 {
    1060     if (mAttached)
    1061     {
    1062         /* reuse the focus event handler to uncapture everything */
    1063         focusEvent (false);
    1064         mAttached = false;
    1065     }
    1066 }
    1067 
    1068 /**
    1069  *  Resizes the toplevel widget to fit the console view w/o scrollbars.
    1070  *  If adjustPosition is true and such resize is not possible (because the
    1071  *  console view size is lagrer then the available screen space) the toplevel
    1072  *  widget is resized and moved to become as large as possible while staying
    1073  *  fully visible.
    1074  */
    1075 void VBoxConsoleView::normalizeGeometry (bool adjustPosition /* = false */)
    1076 {
    1077     /* Make no normalizeGeometry in case we are in manual resize
    1078      * mode or main window is maximized */
    1079     if (mMainWnd->isWindowMaximized() || mMainWnd->isWindowFullScreen())
    1080         return;
    1081 
    1082     QWidget *tlw = window();
    1083 
    1084     /* calculate client window offsets */
    1085     QRect fr = tlw->frameGeometry();
    1086     QRect r = tlw->geometry();
    1087     int dl = r.left() - fr.left();
    1088     int dt = r.top() - fr.top();
    1089     int dr = fr.right() - r.right();
    1090     int db = fr.bottom() - r.bottom();
    1091 
    1092     /* get the best size w/o scroll bars */
    1093     QSize s = tlw->sizeHint();
    1094 
    1095     /* resize the frame to fit the contents */
    1096     s -= tlw->size();
    1097     fr.setRight (fr.right() + s.width());
    1098     fr.setBottom (fr.bottom() + s.height());
    1099 
    1100     if (adjustPosition)
    1101     {
    1102         QRegion ar;
    1103         QDesktopWidget *dwt = QApplication::desktop();
    1104         if (dwt->isVirtualDesktop())
    1105             /* Compose complex available region */
    1106             for (int i = 0; i < dwt->numScreens(); ++ i)
    1107                 ar += dwt->availableGeometry (i);
    1108         else
    1109             /* Get just a simple available rectangle */
    1110             ar = dwt->availableGeometry (tlw->pos());
    1111 
    1112         fr = VBoxGlobal::normalizeGeometry (
    1113             fr, ar, mode != VBoxDefs::SDLMode /* canResize */);
    1114     }
    1115 
    1116 #if 0
    1117     /* center the frame on the desktop */
    1118     fr.moveCenter (ar.center());
    1119 #endif
    1120 
    1121     /* finally, set the frame geometry */
    1122     tlw->setGeometry (fr.left() + dl, fr.top() + dt,
    1123                       fr.width() - dl - dr, fr.height() - dt - db);
    1124 }
    1125 
    1126 /**
    1127  *  Pauses or resumes the VM execution.
    1128  */
    1129 bool VBoxConsoleView::pause (bool on)
    1130 {
    1131     /* QAction::setOn() emits the toggled() signal, so avoid recursion when
    1132      * QAction::setOn() is called from VBoxConsoleWnd::updateMachineState() */
    1133     if (isPaused() == on)
    1134         return true;
    1135 
    1136     if (on)
    1137         mConsole.Pause();
    1138     else
    1139         mConsole.Resume();
    1140 
    1141     bool ok = mConsole.isOk();
    1142     if (!ok)
    1143     {
    1144         if (on)
    1145             vboxProblem().cannotPauseMachine (mConsole);
    1146         else
    1147             vboxProblem().cannotResumeMachine (mConsole);
    1148     }
    1149 
    1150     return ok;
    1151 }
    1152 
    1153 /**
    1154  *  Temporarily disables the mouse integration (or enables it back).
    1155  */
    1156 void VBoxConsoleView::setMouseIntegrationEnabled (bool enabled)
    1157 {
    1158     if (mMouseIntegration == enabled)
    1159         return;
    1160 
    1161     if (mMouseAbsolute)
    1162         captureMouse (!enabled, false);
    1163 
    1164     /* Hiding host cursor in case we are entering mouse integration
    1165      * mode until it's shape is set to the guest cursor shape in
    1166      * OnMousePointerShapeChange event handler.
    1167      *
    1168      * This is necessary to avoid double-cursor issues where both the
    1169      * guest and the host cursors are displayed in one place, one above the
    1170      * other.
    1171      *
    1172      * This is a workaround because the correct decision would be to notify
    1173      * the Guest Additions about we are entering the mouse integration
    1174      * mode. The GuestOS should hide it's cursor to allow using of
    1175      * host cursor for the guest's manipulation.
    1176      *
    1177      * This notification is not always possible though, as not all guests
    1178      * support switching to a hardware pointer on demand. */
    1179     if (enabled)
    1180         viewport()->setCursor (QCursor (Qt::BlankCursor));
    1181 
    1182     mMouseIntegration = enabled;
    1183 
    1184     emitMouseStateChanged();
    1185 }
    1186 
    1187 void VBoxConsoleView::setAutoresizeGuest (bool on)
    1188 {
    1189     if (mAutoresizeGuest != on)
    1190     {
    1191         mAutoresizeGuest = on;
    1192 
    1193         maybeRestrictMinimumSize();
    1194 
    1195         if (mGuestSupportsGraphics && mAutoresizeGuest)
    1196             doResizeHint();
    1197     }
    1198 }
    1199 
    1200 /**
    1201  *  This method is called by VBoxConsoleWnd after it does everything necessary
    1202  *  on its side to go to or from fullscreen, but before it is shown.
    1203  */
    1204 void VBoxConsoleView::onFullscreenChange (bool /* on */)
    1205 {
    1206     /* Nothing to do here so far */
    1207 }
    1208 
    1209 /**
    1210  *  Notify the console scroll-view about the console-window is opened.
    1211  */
    1212 void VBoxConsoleView::onViewOpened()
    1213 {
    1214     /* Variable mIgnoreMainwndResize was initially "true" to ignore QT
    1215      * initial resize event in case of auto-resize feature is on.
    1216      * Currently, initial resize event is already processed, so we set
    1217      * mIgnoreMainwndResize to "false" to process all further resize
    1218      * events as user-initiated window resize events. */
    1219     mIgnoreMainwndResize = false;
    1220 }
    1221 
    1222 //
    1223 // Protected Events
    1224 /////////////////////////////////////////////////////////////////////////////
    1225 
    1226 bool VBoxConsoleView::event (QEvent *e)
    1227 {
    1228     if (mAttached)
    1229     {
    1230         switch (e->type())
    1231         {
    1232             case QEvent::FocusIn:
    1233             {
    1234                 if (isRunning())
    1235                     focusEvent (true);
    1236                 break;
    1237             }
    1238             case QEvent::FocusOut:
    1239             {
    1240                 if (isRunning())
    1241                     focusEvent (false);
    1242                 else
    1243                 {
    1244                     /* release the host key and all other pressed keys too even
    1245                      * when paused (otherwise, we will get stuck keys in the
    1246                      * guest when doing sendChangedKeyStates() on resume because
    1247                      * key presses were already recorded in mPressedKeys but key
    1248                      * releases will most likely not reach us but the new focus
    1249                      * window instead). */
    1250                     releaseAllPressedKeys (true /* aReleaseHostKey */);
    1251                 }
    1252                 break;
    1253             }
    1254 
    1255             case VBoxDefs::ResizeEventType:
    1256             {
    1257                 /* Some situations require initial VGA Resize Request
    1258                  * to be ignored at all, leaving previous framebuffer,
    1259                  * console widget and vm window size preserved. */
    1260                 if (mIgnoreGuestResize)
    1261                     return true;
    1262 
    1263                 bool oldIgnoreMainwndResize = mIgnoreMainwndResize;
    1264                 mIgnoreMainwndResize = true;
    1265 
    1266                 VBoxResizeEvent *re = (VBoxResizeEvent *) e;
    1267                 LogRelFlowFunc (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n",
    1268                                  re->width(), re->height(),
    1269                                  re->bitsPerPixel()));
    1270 
    1271                 bool notifyMainWnd = mFrameBuf->width() != re->width()
    1272                         || mFrameBuf->height() != re->height();
    1273 
    1274                 /* Store the new size to prevent unwanted resize hints being
    1275                  * sent back. */
    1276                 storeConsoleSize(re->width(), re->height());
    1277                 /* do frame buffer dependent resize */
    1278 
    1279                 /* restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen
    1280                  * widgets are present. This is the case on linux with SDL. As
    1281                  * workaround we save/restore the arrow cursor manually. See
    1282                  * http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry
    1283                  * for details.
    1284                  *
    1285                  * Moreover the current cursor, which could be set by the guest,
    1286                  * should be restored after resize.
    1287                  */
    1288                 QCursor cursor;
    1289                 if (shouldHideHostPointer())
    1290                     cursor = QCursor (Qt::BlankCursor);
    1291                 else
    1292                     cursor = viewport()->cursor();
    1293                 mFrameBuf->resizeEvent (re);
    1294                 viewport()->setCursor (cursor);
    1295 
    1296 #ifdef Q_WS_MAC
    1297                 mDockIconPreview->setOriginalSize (re->width(), re->height());
    1298 #endif /* Q_WS_MAC */
    1299 
    1300                 /* This event appears in case of guest video was changed
    1301                  * for somehow even without video resolution change.
    1302                  * In this last case the host VM window will not be resized
    1303                  * according this event and the host mouse cursor which was
    1304                  * unset to default here will not be hidden in capture state.
    1305                  * So it is necessary to perform updateMouseClipping() for
    1306                  * the guest resize event if the mouse cursor was captured. */
    1307                 if (mMouseCaptured)
    1308                     updateMouseClipping();
    1309 
    1310                 /* apply maximum size restriction */
    1311                 setMaximumSize (sizeHint());
    1312 
    1313                 maybeRestrictMinimumSize();
    1314 
    1315                 /* resize the guest canvas */
    1316                 if (!mIgnoreFrameBufferResize)
    1317                     resize (re->width(), re->height());
    1318                 updateSliders();
    1319                 /* Let our toplevel widget calculate its sizeHint properly. */
    1320 #ifdef Q_WS_X11
    1321                 /* We use processEvents rather than sendPostedEvents & set the
    1322                  * time out value to max cause on X11 otherwise the layout
    1323                  * isn't calculated correctly. Dosn't find the bug in Qt, but
    1324                  * this could be triggered through the async nature of the X11
    1325                  * window event system. */
    1326                 QCoreApplication::processEvents (QEventLoop::AllEvents, INT_MAX);
    1327 #else /* Q_WS_X11 */
    1328                 QCoreApplication::sendPostedEvents (0, QEvent::LayoutRequest);
    1329 #endif /* Q_WS_X11 */
    1330 
    1331                 if (!mIgnoreFrameBufferResize)
    1332                     normalizeGeometry (true /* adjustPosition */);
    1333 
    1334                 /* report to the VM thread that we finished resizing */
    1335                 mConsole.GetDisplay().ResizeCompleted (0);
    1336 
    1337                 mIgnoreMainwndResize = oldIgnoreMainwndResize;
    1338 
    1339                 /* update geometry after entering fullscreen | seamless */
    1340                 if (mMainWnd->isTrueFullscreen() || mMainWnd->isTrueSeamless())
    1341                     updateGeometry();
    1342 
    1343                 /* make sure that all posted signals are processed */
    1344                 qApp->processEvents();
    1345 
    1346                 /* emit a signal about guest was resized */
    1347                 emit resizeHintDone();
    1348 
    1349                 /* We also recalculate the desktop geometry if this is determined
    1350                  * automatically.  In fact, we only need this on the first resize,
    1351                  * but it is done every time to keep the code simpler. */
    1352                 calculateDesktopGeometry();
    1353 
    1354                 /* Enable frame-buffer resize watching. */
    1355                 if (mIgnoreFrameBufferResize)
    1356                 {
    1357                     mIgnoreFrameBufferResize = false;
    1358                 }
    1359 
    1360                 if (notifyMainWnd)
    1361                     mMainWnd->onDisplayResize (re->width(), re->height());
    1362 
    1363                 return true;
    1364             }
    1365 
    1366             /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(). */
    1367             case VBoxDefs::RepaintEventType:
    1368             {
    1369                 VBoxRepaintEvent *re = (VBoxRepaintEvent *) e;
    1370                 viewport()->repaint (re->x() - contentsX(),
    1371                                      re->y() - contentsY(),
    1372                                      re->width(), re->height());
    1373                 /* mConsole.GetDisplay().UpdateCompleted(); - the event was acked already */
    1374                 return true;
    1375             }
    1376 
    1377 #ifdef VBOX_WITH_VIDEOHWACCEL
    1378             case VBoxDefs::VHWACommandProcessType:
    1379             {
    1380                 mFrameBuf->doProcessVHWACommand(e);
    1381                 return true;
    1382             }
    1383 #endif
    1384 
    1385             case VBoxDefs::SetRegionEventType:
    1386             {
    1387                 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e;
    1388                 if (mMainWnd->isTrueSeamless() &&
    1389                     sre->region() != mLastVisibleRegion)
    1390                 {
    1391                     mLastVisibleRegion = sre->region();
    1392                     mMainWnd->setMask (sre->region());
    1393                 }
    1394                 else if (!mLastVisibleRegion.isEmpty() &&
    1395                          !mMainWnd->isTrueSeamless())
    1396                     mLastVisibleRegion = QRegion();
    1397                 return true;
    1398             }
    1399 
    1400             case VBoxDefs::MousePointerChangeEventType:
    1401             {
    1402                 MousePointerChangeEvent *me = (MousePointerChangeEvent *) e;
    1403                 /* change cursor shape only when mouse integration is
    1404                  * supported (change mouse shape type event may arrive after
    1405                  * mouse capability change that disables integration */
    1406                 if (mMouseAbsolute)
    1407                     setPointerShape (me);
    1408                 else
    1409                     /* Note: actually we should still remember the requested
    1410                      * cursor shape.  If we can't do that, at least remember
    1411                      * the requested visiblilty. */
    1412                     mHideHostPointer = !me->isVisible();
    1413                 return true;
    1414             }
    1415             case VBoxDefs::MouseCapabilityEventType:
    1416             {
    1417                 MouseCapabilityEvent *me = (MouseCapabilityEvent *) e;
    1418                 if (mMouseAbsolute != me->supportsAbsolute())
    1419                 {
    1420                     mMouseAbsolute = me->supportsAbsolute();
    1421                     /* correct the mouse capture state and reset the cursor
    1422                      * to the default shape if necessary */
    1423                     if (mMouseAbsolute)
    1424                     {
    1425                         CMouse mouse = mConsole.GetMouse();
    1426                         mouse.PutMouseEventAbsolute (-1, -1, 0,
    1427                                                      0 /* Horizontal wheel */,
    1428                                                      0);
    1429                         captureMouse (false, false);
    1430                     }
    1431                     else
    1432                         viewport()->unsetCursor();
    1433                     emitMouseStateChanged();
    1434                     vboxProblem().remindAboutMouseIntegration (mMouseAbsolute);
    1435                 }
    1436                 if (me->needsHostCursor())
    1437                     mMainWnd->setMouseIntegrationLocked (false);
    1438                 else
    1439                     mMainWnd->setMouseIntegrationLocked (true);
    1440                 return true;
    1441             }
    1442 
    1443             case VBoxDefs::ModifierKeyChangeEventType:
    1444             {
    1445                 ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )e;
    1446                 if (me->numLock() != mNumLock)
    1447                     muNumLockAdaptionCnt = 2;
    1448                 if (me->capsLock() != mCapsLock)
    1449                     muCapsLockAdaptionCnt = 2;
    1450                 mNumLock    = me->numLock();
    1451                 mCapsLock   = me->capsLock();
    1452                 mScrollLock = me->scrollLock();
    1453                 return true;
    1454             }
    1455 
    1456             case VBoxDefs::MachineStateChangeEventType:
    1457             {
    1458                 StateChangeEvent *me = (StateChangeEvent *) e;
    1459                 LogFlowFunc (("MachineStateChangeEventType: state=%d\n",
    1460                                me->machineState()));
    1461                 onStateChange (me->machineState());
    1462                 emit machineStateChanged (me->machineState());
    1463                 return true;
    1464             }
    1465 
    1466             case VBoxDefs::AdditionsStateChangeEventType:
    1467             {
    1468                 GuestAdditionsEvent *ge = (GuestAdditionsEvent *) e;
    1469                 LogFlowFunc (("AdditionsStateChangeEventType\n"));
    1470 
    1471                 /* Always send a size hint if we are in fullscreen or seamless
    1472                  * when the graphics capability is enabled, in case the host
    1473                  * resolution has changed since the VM was last run. */
    1474 #if 0
    1475                 if (!mDoResize && !mGuestSupportsGraphics &&
    1476                     ge->supportsGraphics() &&
    1477                     (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen()))
    1478                     mDoResize = true;
    1479 #endif
    1480 
    1481                 mGuestSupportsGraphics = ge->supportsGraphics();
    1482 
    1483                 maybeRestrictMinimumSize();
    1484 
    1485 #if 0
    1486                 /* This will only be acted upon if mDoResize is true. */
    1487                 doResizeHint();
    1488 #endif
    1489 
    1490                 emit additionsStateChanged (ge->additionVersion(),
    1491                                             ge->additionActive(),
    1492                                             ge->supportsSeamless(),
    1493                                             ge->supportsGraphics());
    1494                 return true;
    1495             }
    1496 
    1497             case VBoxDefs::MediaDriveChangeEventType:
    1498             {
    1499                 MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) e;
    1500                 LogFlowFunc (("MediaChangeEvent\n"));
    1501 
    1502                 emit mediaDriveChanged (mce->type());
    1503                 return true;
    1504             }
    1505 
    1506             case VBoxDefs::ActivateMenuEventType:
    1507             {
    1508                 ActivateMenuEvent *ame = (ActivateMenuEvent *) e;
    1509                 ame->action()->trigger();
    1510 
    1511                 /*
    1512                  *  The main window and its children can be destroyed at this
    1513                  *  point (if, for example, the activated menu item closes the
    1514                  *  main window). Detect this situation to prevent calls to
    1515                  *  destroyed widgets.
    1516                  */
    1517                 QWidgetList list = QApplication::topLevelWidgets();
    1518                 bool destroyed = list.indexOf (mMainWnd) < 0;
    1519                 if (!destroyed && mMainWnd->statusBar())
    1520                     mMainWnd->statusBar()->clearMessage();
    1521 
    1522                 return true;
    1523             }
    1524 
    1525             case VBoxDefs::NetworkAdapterChangeEventType:
    1526             {
    1527                 /* no specific adapter information stored in this
    1528                  * event is currently used */
    1529                 emit networkStateChange();
    1530                 return true;
    1531             }
    1532 
    1533             case VBoxDefs::USBCtlStateChangeEventType:
    1534             {
    1535                 emit usbStateChange();
    1536                 return true;
    1537             }
    1538 
    1539             case VBoxDefs::USBDeviceStateChangeEventType:
    1540             {
    1541                 USBDeviceStateChangeEvent *ue = (USBDeviceStateChangeEvent *)e;
    1542 
    1543                 bool success = ue->error().isNull();
    1544 
    1545                 if (!success)
    1546                 {
    1547                     if (ue->attached())
    1548                         vboxProblem().cannotAttachUSBDevice (
    1549                             mConsole,
    1550                             vboxGlobal().details (ue->device()), ue->error());
    1551                     else
    1552                         vboxProblem().cannotDetachUSBDevice (
    1553                             mConsole,
    1554                             vboxGlobal().details (ue->device()), ue->error());
    1555                 }
    1556 
    1557                 emit usbStateChange();
    1558 
    1559                 return true;
    1560             }
    1561 
    1562             case VBoxDefs::SharedFolderChangeEventType:
    1563             {
    1564                 emit sharedFoldersChanged();
    1565                 return true;
    1566             }
    1567 
    1568             case VBoxDefs::RuntimeErrorEventType:
    1569             {
    1570                 RuntimeErrorEvent *ee = (RuntimeErrorEvent *) e;
    1571                 vboxProblem().showRuntimeError (mConsole, ee->fatal(),
    1572                                                 ee->errorID(), ee->message());
    1573                 return true;
    1574             }
    1575 
    1576             case QEvent::KeyPress:
    1577             case QEvent::KeyRelease:
    1578             {
    1579                 QKeyEvent *ke = (QKeyEvent *) e;
    1580 
    1581 #ifdef Q_WS_PM
    1582                 /// @todo temporary solution to send Alt+Tab and friends to
    1583                 //  the guest. The proper solution is to write a keyboard
    1584                 //  driver that will steal these combos from the host (it's
    1585                 //  impossible to do so using hooks on OS/2).
    1586 
    1587                 if (mIsHostkeyPressed)
    1588                 {
    1589                     bool pressed = e->type() == QEvent::KeyPress;
    1590                     CKeyboard keyboard = mConsole.GetKeyboard();
    1591 
    1592                     /* whether the host key is Shift so that it will modify
    1593                      * the hot key values? Note that we don't distinguish
    1594                      * between left and right shift here (too much hassle) */
    1595                     const bool kShift = (gs.hostKey() == VK_SHIFT ||
    1596                                         gs.hostKey() == VK_LSHIFT) &&
    1597                                         (ke->state() & Qt::ShiftModifier);
    1598                     /* define hot keys according to the Shift state */
    1599                     const int kAltTab      = kShift ? Qt::Key_Exclam     : Qt::Key_1;
    1600                     const int kAltShiftTab = kShift ? Qt::Key_At         : Qt::Key_2;
    1601                     const int kCtrlEsc     = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft;
    1602 
    1603                     /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */
    1604                     if (ke->key() == kAltTab || ke->key() == kAltShiftTab)
    1605                     {
    1606                         if (pressed)
    1607                         {
    1608                             /* Send the Alt press to the guest */
    1609                             if (!(mPressedKeysCopy [0x38] & IsKeyPressed))
    1610                             {
    1611                                 /* store the press in *Copy to have it automatically
    1612                                  * released when the Host key is released */
    1613                                 mPressedKeysCopy [0x38] |= IsKeyPressed;
    1614                                 keyboard.PutScancode (0x38);
    1615                             }
    1616 
    1617                             /* Make sure Shift is pressed if it's Key_2 and released
    1618                              * if it's Key_1 */
    1619                             if (ke->key() == kAltTab &&
    1620                                 (mPressedKeysCopy [0x2A] & IsKeyPressed))
    1621                             {
    1622                                 mPressedKeysCopy [0x2A] &= ~IsKeyPressed;
    1623                                 keyboard.PutScancode (0xAA);
    1624                             }
    1625                             else
    1626                             if (ke->key() == kAltShiftTab &&
    1627                                 !(mPressedKeysCopy [0x2A] & IsKeyPressed))
    1628                             {
    1629                                 mPressedKeysCopy [0x2A] |= IsKeyPressed;
    1630                                 keyboard.PutScancode (0x2A);
    1631                             }
    1632                         }
    1633 
    1634                         keyboard.PutScancode (pressed ? 0x0F : 0x8F);
    1635 
    1636                         ke->accept();
    1637                         return true;
    1638                     }
    1639 
    1640                     /* Simulate Ctrl+Esc on Host+Tilde */
    1641                     if (ke->key() == kCtrlEsc)
    1642                     {
    1643                         /* Send the Ctrl press to the guest */
    1644                         if (pressed && !(mPressedKeysCopy [0x1d] & IsKeyPressed))
    1645                         {
    1646                             /* store the press in *Copy to have it automatically
    1647                              * released when the Host key is released */
    1648                             mPressedKeysCopy [0x1d] |= IsKeyPressed;
    1649                             keyboard.PutScancode (0x1d);
    1650                         }
    1651 
    1652                         keyboard.PutScancode (pressed ? 0x01 : 0x81);
    1653 
    1654                         ke->accept();
    1655                         return true;
    1656                     }
    1657                 }
    1658 
    1659                 /* fall through to normal processing */
    1660 
    1661 #endif /* Q_WS_PM */
    1662 
    1663                 if (mIsHostkeyPressed && e->type() == QEvent::KeyPress)
    1664                 {
    1665                     if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12)
    1666                     {
    1667                         QVector <LONG> combo (6);
    1668                         combo [0] = 0x1d; /* Ctrl down */
    1669                         combo [1] = 0x38; /* Alt  down */
    1670                         combo [4] = 0xb8; /* Alt  up   */
    1671                         combo [5] = 0x9d; /* Ctrl up   */
    1672                         if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F10)
    1673                         {
    1674                             combo [2] = 0x3b + (ke->key() - Qt::Key_F1); /* F1-F10 down */
    1675                             combo [3] = 0xbb + (ke->key() - Qt::Key_F1); /* F1-F10 up   */
    1676                         }
    1677                         /* some scan slice */
    1678                         else if (ke->key() >= Qt::Key_F11 && ke->key() <= Qt::Key_F12)
    1679                         {
    1680                             combo [2] = 0x57 + (ke->key() - Qt::Key_F11); /* F11-F12 down */
    1681                             combo [3] = 0xd7 + (ke->key() - Qt::Key_F11); /* F11-F12 up   */
    1682                         }
    1683                         else
    1684                             Assert (0);
    1685 
    1686                         CKeyboard keyboard = mConsole.GetKeyboard();
    1687                         keyboard.PutScancodes (combo);
    1688                     }
    1689                     else if (ke->key() == Qt::Key_Home)
    1690                     {
    1691                         /* Activate the main menu */
    1692                         if (mMainWnd->isTrueSeamless() || mMainWnd->isTrueFullscreen())
    1693                             mMainWnd->popupMainMenu (mMouseCaptured);
    1694                         else
    1695                         {
    1696                             /* In Qt4 it is not enough to just set the focus to
    1697                              * menu-bar. So to get the menu-bar we have to send
    1698                              * Qt::Key_Alt press/release events directly. */
    1699                             QKeyEvent e1 (QEvent::KeyPress, Qt::Key_Alt,
    1700                                           Qt::NoModifier);
    1701                             QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt,
    1702                                           Qt::NoModifier);
    1703                             QApplication::sendEvent (mMainWnd->menuBar(), &e1);
    1704                             QApplication::sendEvent (mMainWnd->menuBar(), &e2);
    1705                         }
    1706                     }
    1707                     else
    1708                     {
    1709                         /* process hot keys not processed in keyEvent()
    1710                          * (as in case of non-alphanumeric keys) */
    1711                         processHotKey (QKeySequence (ke->key()),
    1712                                        mMainWnd->menuBar()->actions());
    1713                     }
    1714                 }
    1715                 else if (!mIsHostkeyPressed && e->type() == QEvent::KeyRelease)
    1716                 {
    1717                     /* Show a possible warning on key release which seems to
    1718                      * be more expected by the end user */
    1719 
    1720                     if (isPaused())
    1721                     {
    1722                         /* if the reminder is disabled we pass the event to
    1723                          * Qt to enable normal keyboard functionality
    1724                          * (for example, menu access with Alt+Letter) */
    1725                         if (!vboxProblem().remindAboutPausedVMInput())
    1726                             break;
    1727                     }
    1728                 }
    1729 
    1730                 ke->accept();
    1731                 return true;
    1732             }
    1733 
    1734 #ifdef Q_WS_MAC
    1735             /* posted OnShowWindow */
    1736             case VBoxDefs::ShowWindowEventType:
    1737             {
    1738                 /*
    1739                  *  Dunno what Qt3 thinks a window that has minimized to the dock
    1740                  *  should be - it is not hidden, neither is it minimized. OTOH it is
    1741                  *  marked shown and visible, but not activated. This latter isn't of
    1742                  *  much help though, since at this point nothing is marked activated.
    1743                  *  I might have overlooked something, but I'm buggered what if I know
    1744                  *  what. So, I'll just always show & activate the stupid window to
    1745                  *  make it get out of the dock when the user wishes to show a VM.
    1746                  */
    1747                 window()->show();
    1748                 window()->activateWindow();
    1749                 return true;
    1750             }
    1751 #endif
    1752             default:
    1753                 break;
    1754         }
    1755     }
    1756 
    1757     return QAbstractScrollArea::event (e);
    1758 }
    1759 
    1760 #ifdef VBOX_WITH_VIDEOHWACCEL
    1761 void VBoxConsoleView::scrollContentsBy (int dx, int dy)
    1762 {
    1763     if (mAttached && mFrameBuf)
    1764     {
    1765         mFrameBuf->viewportScrolled(dx, dy);
    1766     }
    1767     QAbstractScrollArea::scrollContentsBy (dx, dy);
    1768 }
    1769 #endif
    1770 
    1771 
    1772 bool VBoxConsoleView::eventFilter (QObject *watched, QEvent *e)
    1773 {
    1774     if (mAttached && watched == viewport())
    1775     {
    1776         switch (e->type())
    1777         {
    1778             case QEvent::MouseMove:
    1779             case QEvent::MouseButtonPress:
    1780             case QEvent::MouseButtonDblClick:
    1781             case QEvent::MouseButtonRelease:
    1782             {
    1783                 QMouseEvent *me = (QMouseEvent *) e;
    1784                 m_iLastMouseWheelDelta = 0;
    1785                 if (mouseEvent (me->type(), me->pos(), me->globalPos(),
    1786                                 me->buttons(), me->modifiers(),
    1787                                 0, Qt::Horizontal))
    1788                     return true; /* stop further event handling */
    1789                 break;
    1790             }
    1791             case QEvent::Wheel:
    1792             {
    1793                 QWheelEvent *we = (QWheelEvent *) e;
    1794                 /* There are pointing devices which send smaller values for the
    1795                  * delta than 120. Here we sum them up until we are greater
    1796                  * than 120. This allows to have finer control over the speed
    1797                  * acceleration & enables such devices to send a valid wheel
    1798                  * event to our guest mouse device at all. */
    1799                 int iDelta = 0;
    1800                 m_iLastMouseWheelDelta += we->delta();
    1801                 if (qAbs(m_iLastMouseWheelDelta) >= 120)
    1802                 {
    1803                     iDelta = m_iLastMouseWheelDelta;
    1804                     m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
    1805                 }
    1806                 if (mouseEvent (we->type(), we->pos(), we->globalPos(),
    1807 #ifdef QT_MAC_USE_COCOA
    1808                                 /* Qt Cocoa is buggy. It always reports a left
    1809                                  * button pressed when the mouse wheel event
    1810                                  * occurs. A workaround is to ask the
    1811                                  * application which buttons are pressed
    1812                                  * currently. */
    1813                                 QApplication::mouseButtons(),
    1814 #else /* QT_MAC_USE_COCOA */
    1815                                 we->buttons(),
    1816 #endif /* QT_MAC_USE_COCOA */
    1817                                 we->modifiers(),
    1818                                 iDelta, we->orientation()))
    1819                     return true; /* stop further event handling */
    1820                 break;
    1821             }
    1822 #ifdef Q_WS_MAC
    1823             case QEvent::Leave:
    1824             {
    1825                 /* Enable mouse event compression if we leave the VM view. This
    1826                    is necessary for having smooth resizing of the VM/other
    1827                    windows. */
    1828                 setMouseCoalescingEnabled (true);
    1829                 break;
    1830             }
    1831             case QEvent::Enter:
    1832             {
    1833                 /* Disable mouse event compression if we enter the VM view. So
    1834                    all mouse events are registered in the VM. Only do this if
    1835                    the keyboard/mouse is grabbed (this is when we have a valid
    1836                    event handler). */
    1837                 setMouseCoalescingEnabled (false);
    1838                 break;
    1839             }
    1840 #endif /* Q_WS_MAC */
    1841             case QEvent::Resize:
    1842             {
    1843                 if (mMouseCaptured)
    1844                     updateMouseClipping();
    1845 #ifdef VBOX_WITH_VIDEOHWACCEL
    1846                 if (mFrameBuf)
    1847                 {
    1848                     mFrameBuf->viewportResized((QResizeEvent*)e);
    1849                 }
    1850 #endif
    1851                 break;
    1852             }
    1853             default:
    1854                 break;
    1855         }
    1856     }
    1857     else if (watched == mMainWnd)
    1858     {
    1859         switch (e->type())
    1860         {
    1861 #if defined (Q_WS_WIN32)
    1862 #if defined (VBOX_GUI_USE_DDRAW)
    1863             case QEvent::Move:
    1864             {
    1865                 /*
    1866                  *  notification from our parent that it has moved. We need this
    1867                  *  in order to possibly adjust the direct screen blitting.
    1868                  */
    1869                 if (mFrameBuf)
    1870                     mFrameBuf->moveEvent ((QMoveEvent *) e);
    1871                 break;
    1872             }
    1873 #endif
    1874             /*
    1875              *  install/uninstall low-level kbd hook on every
    1876              *  activation/deactivation to:
    1877              *  a) avoid excess hook calls when we're not active and
    1878              *  b) be always in front of any other possible hooks
    1879              */
    1880             case QEvent::WindowActivate:
    1881             {
    1882                 gKbdHook = SetWindowsHookEx (WH_KEYBOARD_LL, lowLevelKeyboardProc,
    1883                                               GetModuleHandle (NULL), 0);
    1884                 AssertMsg (gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));
    1885                 break;
    1886             }
    1887             case QEvent::WindowDeactivate:
    1888             {
    1889                 if (gKbdHook)
    1890                 {
    1891                     UnhookWindowsHookEx (gKbdHook);
    1892                     gKbdHook = NULL;
    1893                 }
    1894                 break;
    1895             }
    1896 #endif /* defined (Q_WS_WIN32) */
    1897 #if defined (Q_WS_MAC)
    1898             /*
    1899              *  Install/remove the keyboard event handler.
    1900              */
    1901             case QEvent::WindowActivate:
    1902                 darwinGrabKeyboardEvents (true);
    1903                 break;
    1904             case QEvent::WindowDeactivate:
    1905                 darwinGrabKeyboardEvents (false);
    1906                 break;
    1907 #endif /* defined (Q_WS_MAC) */
    1908             case QEvent::Resize:
    1909             {
    1910                 /* Set the "guest needs to resize" hint.  This hint is acted upon
    1911                  * when (and only when) the autoresize property is "true". */
    1912                 mDoResize = mGuestSupportsGraphics || mMainWnd->isTrueFullscreen();
    1913                 if (!mIgnoreMainwndResize &&
    1914                     mGuestSupportsGraphics && mAutoresizeGuest)
    1915                     QTimer::singleShot (300, this, SLOT (doResizeHint()));
    1916                 break;
    1917             }
    1918             case QEvent::WindowStateChange:
    1919             {
    1920                 /* During minimizing and state restoring mMainWnd gets the focus
    1921                  * which belongs to console view window, so returning it properly. */
    1922                 QWindowStateChangeEvent *ev = static_cast <QWindowStateChangeEvent*> (e);
    1923                 if (ev->oldState() & Qt::WindowMinimized)
    1924                 {
    1925                     if (QApplication::focusWidget())
    1926                     {
    1927                         QApplication::focusWidget()->clearFocus();
    1928                         qApp->processEvents();
    1929                     }
    1930                     QTimer::singleShot (0, this, SLOT (setFocus()));
    1931                 }
    1932                 break;
    1933             }
    1934 
    1935             default:
    1936                 break;
    1937         }
    1938     }
    1939     else if (watched == mMainWnd->menuBar())
    1940     {
    1941         /*
    1942          *  sometimes when we press ESC in the menu it brings the
    1943          *  focus away (Qt bug?) causing no widget to have a focus,
    1944          *  or holds the focus itself, instead of returning the focus
    1945          *  to the console window. here we fix this.
    1946          */
    1947         switch (e->type())
    1948         {
    1949             case QEvent::FocusOut:
    1950             {
    1951                 if (qApp->focusWidget() == 0)
    1952                     setFocus();
    1953                 break;
    1954             }
    1955             case QEvent::KeyPress:
    1956             {
    1957                 QKeyEvent *ke = (QKeyEvent *) e;
    1958                 if (ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier))
    1959                     if (mMainWnd->menuBar()->hasFocus())
    1960                         setFocus();
    1961                 break;
    1962             }
    1963             default:
    1964                 break;
    1965         }
    1966     }
    1967 
    1968     return QAbstractScrollArea::eventFilter (watched, e);
    1969 }
    1970 
    1971 #if defined(Q_WS_WIN32)
    1972 
    1973 /**
    1974  *  Low-level keyboard event handler,
    1975  *  @return
    1976  *      true to indicate that the message is processed and false otherwise
    1977  */
    1978 bool VBoxConsoleView::winLowKeyboardEvent (UINT msg, const KBDLLHOOKSTRUCT &event)
    1979 {
    1980 #if 0
    1981     LogFlow (("### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X (mKbdCaptured=%d)\n",
    1982               event.vkCode, event.scanCode, event.flags, event.dwExtraInfo, mKbdCaptured));
    1983     char buf [256];
    1984     sprintf (buf, "### vkCode=%08X, scanCode=%08X, flags=%08X, dwExtraInfo=%08X",
    1985              event.vkCode, event.scanCode, event.flags, event.dwExtraInfo);
    1986     mMainWnd->statusBar()->message (buf);
    1987 #endif
    1988 
    1989     /* Sometimes it happens that Win inserts additional events on some key
    1990      * press/release. For example, it prepends ALT_GR in German layout with
    1991      * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
    1992      * to specially treat ALT_GR to enter additional chars to regular apps).
    1993      * These events are definitely unwanted in VM, so filter them out. */
    1994     /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
    1995      * code 0x23a. If this is not passed through then it is impossible to
    1996      * cancel CapsLock on a French keyboard.  I didn't find any other examples
    1997      * of these strange events.  Let's hope we are not missing anything else
    1998      * of importance! */
    1999     if (hasFocus() && (event.scanCode & ~0xFF))
    2000     {
    2001         if (event.vkCode == VK_CAPITAL)
    2002             return false;
    2003         else
    2004             return true;
    2005     }
    2006 
    2007     if (!mKbdCaptured)
    2008         return false;
    2009 
    2010     /* it's possible that a key has been pressed while the keyboard was not
    2011      * captured, but is being released under the capture. Detect this situation
    2012      * and return false to let Windows process the message normally and update
    2013      * its key state table (to avoid the stuck key effect). */
    2014     uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT)
    2015                            ? IsExtKeyPressed
    2016                            : IsKeyPressed;
    2017     if ((event.flags & 0x80) /* released */ &&
    2018         ((event.vkCode == gs.hostKey() && !hostkey_in_capture) ||
    2019          (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed))
    2020         return false;
    2021 
    2022     MSG message;
    2023     message.hwnd = winId();
    2024     message.message = msg;
    2025     message.wParam = event.vkCode;
    2026     message.lParam =
    2027         1 |
    2028         (event.scanCode & 0xFF) << 16 |
    2029         (event.flags & 0xFF) << 24;
    2030 
    2031     /* Windows sets here the extended bit when the Right Shift key is pressed,
    2032      * which is totally wrong. Undo it. */
    2033     if (event.vkCode == VK_RSHIFT)
    2034         message.lParam &= ~0x1000000;
    2035 
    2036     /* we suppose here that this hook is always called on the main GUI thread */
    2037     long dummyResult;
    2038     return winEvent (&message, &dummyResult);
    2039 }
    2040 
    2041 /**
    2042  * Get Win32 messages before they are passed to Qt. This allows us to get
    2043  * the keyboard events directly and bypass the harmful Qt translation. A
    2044  * return value of @c true indicates to Qt that the event has been handled.
    2045  */
    2046 bool VBoxConsoleView::winEvent (MSG *aMsg, long* /* aResult */)
    2047 {
    2048     if (!mAttached || ! (
    2049         aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN ||
    2050         aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP
    2051     ))
    2052         return false;
    2053 
    2054     /* check for the special flag possibly set at the end of this function */
    2055     if (aMsg->lParam & (0x1 << 25))
    2056     {
    2057         aMsg->lParam &= ~(0x1 << 25);
    2058         return false;
    2059     }
    2060 
    2061 #if 0
    2062     char buf [256];
    2063     sprintf (buf, "WM_%04X: vk=%04X rep=%05d scan=%02X ext=%01d rzv=%01X ctx=%01d prev=%01d tran=%01d",
    2064              aMsg->message, aMsg->wParam,
    2065              (aMsg->lParam & 0xFFFF),
    2066              ((aMsg->lParam >> 16) & 0xFF),
    2067              ((aMsg->lParam >> 24) & 0x1),
    2068              ((aMsg->lParam >> 25) & 0xF),
    2069              ((aMsg->lParam >> 29) & 0x1),
    2070              ((aMsg->lParam >> 30) & 0x1),
    2071              ((aMsg->lParam >> 31) & 0x1));
    2072     mMainWnd->statusBar()->message (buf);
    2073     LogFlow (("%s\n", buf));
    2074 #endif
    2075 
    2076     int scan = (aMsg->lParam >> 16) & 0x7F;
    2077     /* scancodes 0x80 and 0x00 are ignored */
    2078     if (!scan)
    2079         return true;
    2080 
    2081     int vkey = aMsg->wParam;
    2082 
    2083     /* When one of the SHIFT keys is held and one of the cursor movement
    2084      * keys is pressed, Windows duplicates SHIFT press/release messages,
    2085      * but with the virtual key code set to 0xFF. These virtual keys are also
    2086      * sent in some other situations (Pause, PrtScn, etc.). Ignore such
    2087      * messages. */
    2088     if (vkey == 0xFF)
    2089         return true;
    2090 
    2091     int flags = 0;
    2092     if (aMsg->lParam & 0x1000000)
    2093         flags |= KeyExtended;
    2094     if (!(aMsg->lParam & 0x80000000))
    2095         flags |= KeyPressed;
    2096 
    2097     switch (vkey)
    2098     {
    2099         case VK_SHIFT:
    2100         case VK_CONTROL:
    2101         case VK_MENU:
    2102         {
    2103             /* overcome stupid Win32 modifier key generalization */
    2104             int keyscan = scan;
    2105             if (flags & KeyExtended)
    2106                 keyscan |= 0xE000;
    2107             switch (keyscan)
    2108             {
    2109                 case 0x002A: vkey = VK_LSHIFT; break;
    2110                 case 0x0036: vkey = VK_RSHIFT; break;
    2111                 case 0x001D: vkey = VK_LCONTROL; break;
    2112                 case 0xE01D: vkey = VK_RCONTROL; break;
    2113                 case 0x0038: vkey = VK_LMENU; break;
    2114                 case 0xE038: vkey = VK_RMENU; break;
    2115             }
    2116             break;
    2117         }
    2118         case VK_NUMLOCK:
    2119             /* Win32 sets the extended bit for the NumLock key. Reset it. */
    2120             flags &= ~KeyExtended;
    2121             break;
    2122         case VK_SNAPSHOT:
    2123             flags |= KeyPrint;
    2124             break;
    2125         case VK_PAUSE:
    2126             flags |= KeyPause;
    2127             break;
    2128     }
    2129 
    2130     bool result = keyEvent (vkey, scan, flags);
    2131     if (!result && mKbdCaptured)
    2132     {
    2133         /* keyEvent() returned that it didn't process the message, but since the
    2134          * keyboard is captured, we don't want to pass it to Windows. We just want
    2135          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    2136          * shortcuts for example). So send it direcltly to the window with the
    2137          * special flag in the reserved area of lParam (to avoid recursion). */
    2138         ::SendMessage (aMsg->hwnd, aMsg->message,
    2139                        aMsg->wParam, aMsg->lParam | (0x1 << 25));
    2140         return true;
    2141     }
    2142 
    2143     /* These special keys have to be handled by Windows as well to update the
    2144      * internal modifier state and to enable/disable the keyboard LED */
    2145     if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT)
    2146         return false;
    2147 
    2148     return result;
    2149 }
    2150 
    2151 #elif defined (Q_WS_PM)
    2152 
    2153 /**
    2154  *  Get PM messages before they are passed to Qt. This allows us to get
    2155  *  the keyboard events directly and bypass the harmful Qt translation. A
    2156  *  return value of @c true indicates to Qt that the event has been handled.
    2157  */
    2158 bool VBoxConsoleView::pmEvent (QMSG *aMsg)
    2159 {
    2160     if (!mAttached)
    2161         return false;
    2162 
    2163     if (aMsg->msg == UM_PREACCEL_CHAR)
    2164     {
    2165         /* we are inside the input hook */
    2166 
    2167         /* let the message go through the normal system pipeline */
    2168         if (!mKbdCaptured)
    2169             return false;
    2170     }
    2171 
    2172     if (aMsg->msg != WM_CHAR &&
    2173         aMsg->msg != UM_PREACCEL_CHAR)
    2174         return false;
    2175 
    2176     /* check for the special flag possibly set at the end of this function */
    2177     if (SHORT2FROMMP (aMsg->mp2) & 0x8000)
    2178     {
    2179         aMsg->mp2 = MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2),
    2180                                   SHORT2FROMMP (aMsg->mp2) & ~0x8000);
    2181         return false;
    2182     }
    2183 
    2184 #if 0
    2185     {
    2186         char buf [256];
    2187         sprintf (buf, "*** %s: f=%04X rep=%03d scan=%02X ch=%04X vk=%04X",
    2188                  (aMsg->msg == WM_CHAR ? "WM_CHAR" : "UM_PREACCEL_CHAR"),
    2189                  SHORT1FROMMP (aMsg->mp1), CHAR3FROMMP (aMsg->mp1),
    2190                  CHAR4FROMMP (aMsg->mp1), SHORT1FROMMP (aMsg->mp2),
    2191                  SHORT2FROMMP (aMsg->mp2));
    2192         mMainWnd->statusBar()->message (buf);
    2193         LogFlow (("%s\n", buf));
    2194     }
    2195 #endif
    2196 
    2197     USHORT ch = SHORT1FROMMP (aMsg->mp2);
    2198     USHORT f = SHORT1FROMMP (aMsg->mp1);
    2199 
    2200     int scan = (unsigned int) CHAR4FROMMP (aMsg->mp1);
    2201     if (!scan || scan > 0x7F)
    2202         return true;
    2203 
    2204     int vkey = QIHotKeyEdit::virtualKey (aMsg);
    2205 
    2206     int flags = 0;
    2207 
    2208     if ((ch & 0xFF) == 0xE0)
    2209     {
    2210         flags |= KeyExtended;
    2211         scan = ch >> 8;
    2212     }
    2213     else if (scan == 0x5C && (ch & 0xFF) == '/')
    2214     {
    2215         /* this is the '/' key on the keypad */
    2216         scan = 0x35;
    2217         flags |= KeyExtended;
    2218     }
    2219     else
    2220     {
    2221         /* For some keys, the scan code passed in QMSG is a pseudo scan
    2222          * code. We replace it with a real hardware scan code, according to
    2223          * http://www.computer-engineering.org/ps2keyboard/scancodes1.html.
    2224          * Also detect Pause and PrtScn and set flags. */
    2225         switch (vkey)
    2226         {
    2227             case VK_ENTER:     scan = 0x1C; flags |= KeyExtended; break;
    2228             case VK_CTRL:      scan = 0x1D; flags |= KeyExtended; break;
    2229             case VK_ALTGRAF:   scan = 0x38; flags |= KeyExtended; break;
    2230             case VK_LWIN:      scan = 0x5B; flags |= KeyExtended; break;
    2231             case VK_RWIN:      scan = 0x5C; flags |= KeyExtended; break;
    2232             case VK_WINMENU:   scan = 0x5D; flags |= KeyExtended; break;
    2233             case VK_FORWARD:   scan = 0x69; flags |= KeyExtended; break;
    2234             case VK_BACKWARD:  scan = 0x6A; flags |= KeyExtended; break;
    2235 #if 0
    2236             /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully
    2237             // clear what is more correct
    2238             case VK_BREAK:     scan = 0x46; flags |= KeyExtended; break;
    2239 #else
    2240             case VK_BREAK:     scan = 0;    flags |= KeyPause; break;
    2241 #endif
    2242             case VK_PAUSE:     scan = 0;    flags |= KeyPause;    break;
    2243             case VK_PRINTSCRN: scan = 0;    flags |= KeyPrint;    break;
    2244             default:;
    2245         }
    2246     }
    2247 
    2248     if (!(f & KC_KEYUP))
    2249         flags |= KeyPressed;
    2250 
    2251     bool result = keyEvent (vkey, scan, flags);
    2252     if (!result && mKbdCaptured)
    2253     {
    2254         /* keyEvent() returned that it didn't process the message, but since the
    2255          * keyboard is captured, we don't want to pass it to PM. We just want
    2256          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    2257          * shortcuts for example). So send it direcltly to the window with the
    2258          * special flag in the reserved area of lParam (to avoid recursion). */
    2259         ::WinSendMsg (aMsg->hwnd, WM_CHAR,
    2260                       aMsg->mp1,
    2261                       MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2),
    2262                                     SHORT2FROMMP (aMsg->mp2) | 0x8000));
    2263         return true;
    2264     }
    2265     return result;
    2266 }
    2267 
    2268 #elif defined(Q_WS_X11)
    2269 
    2270 /**
    2271  * This function is a "predicate" for XCheckIfEvent().  It will check
    2272  * the XEvent passed to it to see if it is a keypress event matching
    2273  * the keyrelease event in @a pvArg.
    2274  * @returns True if the event matches, False otherwise
    2275  * @param   pEvent    the event to compare, taken from the event queue
    2276  * @param   pvArg     the keyrelease event we would like to compare against
    2277  */
    2278 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent,
    2279                                      XPointer pvArg)
    2280 {
    2281     XEvent *pKeyEvent = (XEvent *) pvArg;
    2282     if ((pEvent->type == XKeyPress) &&
    2283         (pEvent->xkey.keycode == pKeyEvent->xkey.keycode))
    2284         return True;
    2285     else
    2286         return False;
    2287 }
    2288 
    2289 /**
    2290  *  This routine gets X11 events before they are processed by Qt. This is
    2291  *  used for our platform specific keyboard implementation. A return value
    2292  *  of TRUE indicates that the event has been processed by us.
    2293  */
    2294 bool VBoxConsoleView::x11Event (XEvent *event)
    2295 {
    2296     switch (event->type)
    2297     {
    2298         /* We have to handle XFocusOut right here as this event is not passed
    2299          * to VBoxConsoleView::event(). Handling this event is important for
    2300          * releasing the keyboard before the screen saver gets active. */
    2301         case XFocusOut:
    2302         case XFocusIn:
    2303             if (isRunning())
    2304                 focusEvent (event->type == XFocusIn);
    2305             return false;
    2306         case XKeyPress:
    2307         case XKeyRelease:
    2308             if (mAttached)
    2309                 break;
    2310             /*  else fall through */
    2311         default:
    2312             return false; /* pass the event to Qt */
    2313     }
    2314 
    2315     /* Translate the keycode to a PC scan code. */
    2316     unsigned scan = handleXKeyEvent (event);
    2317 
    2318 #if 0
    2319     char buf [256];
    2320     sprintf (buf, "pr=%d kc=%08X st=%08X extended=%s scan=%04X",
    2321              event->type == XKeyPress ? 1 : 0, event->xkey.keycode,
    2322              event->xkey.state, scan >> 8 ? "true" : "false", scan & 0x7F);
    2323     mMainWnd->statusBar()->message (buf);
    2324     LogFlow (("### %s\n", buf));
    2325 #endif
    2326 
    2327     // scancodes 0x00 (no valid translation) and 0x80 are ignored
    2328     if (!scan & 0x7F)
    2329         return true;
    2330 
    2331     /* Fix for http://www.virtualbox.org/ticket/1296:
    2332      * when X11 sends events for repeated keys, it always inserts an
    2333      * XKeyRelease before the XKeyPress. */
    2334     XEvent returnEvent;
    2335     if ((event->type == XKeyRelease) &&
    2336         (XCheckIfEvent(event->xkey.display, &returnEvent,
    2337                        VBoxConsoleViewCompEvent, (XPointer) event) == True)) {
    2338         XPutBackEvent(event->xkey.display, &returnEvent);
    2339         /* Discard it, don't pass it to Qt. */
    2340         return true;
    2341     }
    2342 
    2343     KeySym ks = ::XKeycodeToKeysym (event->xkey.display, event->xkey.keycode, 0);
    2344 
    2345     int flags = 0;
    2346     if (scan >> 8)
    2347         flags |= KeyExtended;
    2348     if (event->type == XKeyPress)
    2349         flags |= KeyPressed;
    2350 
    2351     /* Remove the extended flag */
    2352     scan &= 0x7F;
    2353 
    2354     switch (ks)
    2355     {
    2356         case XK_Print:
    2357             flags |= KeyPrint;
    2358             break;
    2359         case XK_Pause:
    2360             if (event->xkey.state & ControlMask) /* Break */
    2361             {
    2362                 ks = XK_Break;
    2363                 flags |= KeyExtended;
    2364                 scan = 0x46;
    2365             }
    2366             else
    2367                 flags |= KeyPause;
    2368             break;
    2369     }
    2370 
    2371     return keyEvent (ks, scan, flags);
    2372 }
    2373 
    2374 #elif defined (Q_WS_MAC)
    2375 
    2376 /**
    2377  *  Invoked by VBoxConsoleView::darwinEventHandlerProc / VBoxConsoleView::macEventFilter when
    2378  *  it receives a raw keyboard event.
    2379  *
    2380  *  @param pvCocoaEvent The Cocoa keyboard event. Can be NULL in some configs.
    2381  *  @param inEvent      The keyboard event.
    2382  *
    2383  *  @return true if the key was processed, false if it wasn't processed and should be passed on.
    2384  */
    2385 bool VBoxConsoleView::darwinKeyboardEvent (const void *pvCocoaEvent, EventRef inEvent)
    2386 {
    2387     bool ret = false;
    2388     UInt32 EventKind = ::GetEventKind (inEvent);
    2389     if (EventKind != kEventRawKeyModifiersChanged)
    2390     {
    2391         /* convert keycode to set 1 scan code. */
    2392         UInt32 keyCode = ~0U;
    2393         ::GetEventParameter (inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
    2394         /* The usb keyboard driver translates these codes to different virtual
    2395          * key codes depending of the keyboard type. There are ANSI, ISO, JIS
    2396          * and unknown. For European keyboards (ISO) the key 0xa and 0x32 have
    2397          * to be switched. Here we are doing this at runtime, cause the user
    2398          * can have more than one keyboard (of different type), where he may
    2399          * switch at will all the time. Default is the ANSI standard as defined
    2400          * in g_aDarwinToSet1. */
    2401         if (   (keyCode == 0xa || keyCode == 0x32)
    2402             && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO)
    2403             keyCode = 0x3c - keyCode;
    2404         unsigned scanCode = ::DarwinKeycodeToSet1Scancode (keyCode);
    2405         if (scanCode)
    2406         {
    2407             /* calc flags. */
    2408             int flags = 0;
    2409             if (EventKind != kEventRawKeyUp)
    2410                 flags |= KeyPressed;
    2411             if (scanCode & VBOXKEY_EXTENDED)
    2412                 flags |= KeyExtended;
    2413             /** @todo KeyPause, KeyPrint. */
    2414             scanCode &= VBOXKEY_SCANCODE_MASK;
    2415 
    2416             /* get the unicode string (if present). */
    2417             AssertCompileSize (wchar_t, 2);
    2418             AssertCompileSize (UniChar, 2);
    2419             ByteCount cbWritten = 0;
    2420             wchar_t ucs[8];
    2421             if (::GetEventParameter (inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL,
    2422                                      sizeof (ucs), &cbWritten, &ucs[0]) != 0)
    2423                 cbWritten = 0;
    2424             ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */
    2425 
    2426             ret = keyEvent (keyCode, scanCode, flags, ucs[0] ? ucs : NULL);
    2427         }
    2428     }
    2429     else
    2430     {
    2431         /* May contain multiple modifier changes, kind of annoying. */
    2432         UInt32 newMask = 0;
    2433         ::GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
    2434                              sizeof (newMask), NULL, &newMask);
    2435         newMask = ::DarwinAdjustModifierMask (newMask, pvCocoaEvent);
    2436         UInt32 changed = newMask ^ mDarwinKeyModifiers;
    2437         if (changed)
    2438         {
    2439             for (UInt32 bit = 0; bit < 32; bit++)
    2440             {
    2441                 if (!(changed & (1 << bit)))
    2442                     continue;
    2443                 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode (1 << bit);
    2444                 if (!scanCode)
    2445                     continue;
    2446                 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode (1 << bit);
    2447                 Assert (keyCode);
    2448 
    2449                 if (!(scanCode & VBOXKEY_LOCK))
    2450                 {
    2451                     unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0;
    2452                     if (scanCode & VBOXKEY_EXTENDED)
    2453                         flags |= KeyExtended;
    2454                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2455                     ret |= keyEvent (keyCode, scanCode & 0xff, flags);
    2456                 }
    2457                 else
    2458                 {
    2459                     unsigned flags = 0;
    2460                     if (scanCode & VBOXKEY_EXTENDED)
    2461                         flags |= KeyExtended;
    2462                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2463                     keyEvent (keyCode, scanCode, flags | KeyPressed);
    2464                     keyEvent (keyCode, scanCode, flags);
    2465                 }
    2466             }
    2467         }
    2468 
    2469         mDarwinKeyModifiers = newMask;
    2470 
    2471         /* Always return true here because we'll otherwise getting a Qt event
    2472            we don't want and that will only cause the Pause warning to pop up. */
    2473         ret = true;
    2474     }
    2475 
    2476     return ret;
    2477 }
    2478 
    2479 
    2480 /**
    2481  * Installs or removes the keyboard event handler.
    2482  *
    2483  * @param   fGrab    True if we're to grab the events, false if we're not to.
    2484  */
    2485 void VBoxConsoleView::darwinGrabKeyboardEvents (bool fGrab)
    2486 {
    2487     mKeyboardGrabbed = fGrab;
    2488     if (fGrab)
    2489     {
    2490         /* Disable mouse and keyboard event compression/delaying to make sure
    2491            we *really* get all of the events. */
    2492         ::CGSetLocalEventsSuppressionInterval (0.0);
    2493         setMouseCoalescingEnabled (false);
    2494 
    2495         /* Register the event callback/hook and grab the keyboard. */
    2496 # ifdef QT_MAC_USE_COCOA
    2497         ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */
    2498                                             VBoxConsoleView::darwinEventHandlerProc, this);
    2499 
    2500 # elif !defined (VBOX_WITH_HACKED_QT)
    2501         EventTypeSpec eventTypes[6];
    2502         eventTypes[0].eventClass = kEventClassKeyboard;
    2503         eventTypes[0].eventKind  = kEventRawKeyDown;
    2504         eventTypes[1].eventClass = kEventClassKeyboard;
    2505         eventTypes[1].eventKind  = kEventRawKeyUp;
    2506         eventTypes[2].eventClass = kEventClassKeyboard;
    2507         eventTypes[2].eventKind  = kEventRawKeyRepeat;
    2508         eventTypes[3].eventClass = kEventClassKeyboard;
    2509         eventTypes[3].eventKind  = kEventRawKeyModifiersChanged;
    2510         /* For ignorning Command-H and Command-Q which aren't affected by the
    2511          * global hotkey stuff (doesn't work well): */
    2512         eventTypes[4].eventClass = kEventClassCommand;
    2513         eventTypes[4].eventKind  = kEventCommandProcess;
    2514         eventTypes[5].eventClass = kEventClassCommand;
    2515         eventTypes[5].eventKind  = kEventCommandUpdateStatus;
    2516 
    2517         EventHandlerUPP eventHandler = ::NewEventHandlerUPP (VBoxConsoleView::darwinEventHandlerProc);
    2518 
    2519         mDarwinEventHandlerRef = NULL;
    2520         ::InstallApplicationEventHandler (eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
    2521                                           this, &mDarwinEventHandlerRef);
    2522         ::DisposeEventHandlerUPP (eventHandler);
    2523 
    2524 # else  /* VBOX_WITH_HACKED_QT */
    2525         ((QIApplication *)qApp)->setEventFilter (VBoxConsoleView::macEventFilter, this);
    2526 # endif /* VBOX_WITH_HACKED_QT */
    2527 
    2528         ::DarwinGrabKeyboard (false);
    2529     }
    2530     else
    2531     {
    2532         ::DarwinReleaseKeyboard();
    2533 # ifdef QT_MAC_USE_COCOA
    2534         ::VBoxCocoaApplication_unsetCallback (UINT32_MAX, /** @todo fix mask */
    2535                                               VBoxConsoleView::darwinEventHandlerProc, this);
    2536 # elif !defined(VBOX_WITH_HACKED_QT)
    2537         if (mDarwinEventHandlerRef)
    2538         {
    2539             ::RemoveEventHandler (mDarwinEventHandlerRef);
    2540             mDarwinEventHandlerRef = NULL;
    2541         }
    2542 # else  /* VBOX_WITH_HACKED_QT */
    2543         ((QIApplication *)qApp)->setEventFilter (NULL, NULL);
    2544 # endif /* VBOX_WITH_HACKED_QT */
    2545     }
    2546 }
    2547 
    2548 #endif // defined (Q_WS_MAC)
    2549 
    2550 //
    2551 // Private members
    2552 /////////////////////////////////////////////////////////////////////////////
    2553 
    2554 /**
    2555  *  Called on every focus change and also to forcibly capture/uncapture the
    2556  *  input in situations similar to gaining or losing focus.
    2557  *
    2558  *  @param aHasFocus        true if the window got focus and false otherwise.
    2559  *  @param aReleaseHostKey  true to release the host key (used only when
    2560  *                          @a aHasFocus is false.
    2561  */
    2562 void VBoxConsoleView::focusEvent (bool aHasFocus,
    2563                                   bool aReleaseHostKey /* = true */)
    2564 {
    2565     if (aHasFocus)
    2566     {
    2567 #ifdef RT_OS_WINDOWS
    2568         if (   !mDisableAutoCapture && gs.autoCapture()
    2569             && GetAncestor (winId(), GA_ROOT) == GetForegroundWindow())
    2570 #else
    2571         if (!mDisableAutoCapture && gs.autoCapture())
    2572 #endif /* RT_OS_WINDOWS */
    2573         {
    2574             captureKbd (true);
    2575 /// @todo (dmik)
    2576 //      the below is for the mouse auto-capture. disabled for now. in order to
    2577 //      properly support it, we need to know when *all* mouse buttons are
    2578 //      released after we got focus, and grab the mouse only after then.
    2579 //      btw, the similar would be good the for keyboard auto-capture, too.
    2580 //            if (!(mMouseAbsolute && mMouseIntegration))
    2581 //                captureMouse (true);
    2582         }
    2583 
    2584         /* reset the single-time disable capture flag */
    2585         if (mDisableAutoCapture)
    2586             mDisableAutoCapture = false;
    2587     }
    2588     else
    2589     {
    2590         captureMouse (false);
    2591         captureKbd (false, false);
    2592         releaseAllPressedKeys (aReleaseHostKey);
    2593     }
    2594 }
    2595 
    2596 /**
    2597  *  Synchronize the views of the host and the guest to the modifier keys.
    2598  *  This function will add up to 6 additional keycodes to codes.
    2599  *
    2600  *  @param  codes  pointer to keycodes which are sent to the keyboard
    2601  *  @param  count  pointer to the keycodes counter
    2602  */
    2603 void VBoxConsoleView::fixModifierState (LONG *codes, uint *count)
    2604 {
    2605 #if defined(Q_WS_X11)
    2606 
    2607     Window   wDummy1, wDummy2;
    2608     int      iDummy3, iDummy4, iDummy5, iDummy6;
    2609     unsigned uMask;
    2610     unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0;
    2611 
    2612     uKeyMaskCaps          = LockMask;
    2613     XModifierKeymap* map  = XGetModifierMapping(QX11Info::display());
    2614     KeyCode keyCodeNum    = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock);
    2615     KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock);
    2616 
    2617     for (int i = 0; i < 8; i++)
    2618     {
    2619         if (   keyCodeNum != NoSymbol
    2620             && map->modifiermap[map->max_keypermod * i] == keyCodeNum)
    2621             uKeyMaskNum    = 1 << i;
    2622         else if (   keyCodeScroll != NoSymbol
    2623                  && map->modifiermap[map->max_keypermod * i] == keyCodeScroll)
    2624             uKeyMaskScroll = 1 << i;
    2625     }
    2626     XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2,
    2627                   &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask);
    2628     XFreeModifiermap(map);
    2629 
    2630     if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum)))
    2631     {
    2632         muNumLockAdaptionCnt--;
    2633         codes[(*count)++] = 0x45;
    2634         codes[(*count)++] = 0x45 | 0x80;
    2635     }
    2636     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps)))
    2637     {
    2638         muCapsLockAdaptionCnt--;
    2639         codes[(*count)++] = 0x3a;
    2640         codes[(*count)++] = 0x3a | 0x80;
    2641         /* Some keyboard layouts require shift to be pressed to break
    2642          * capslock.  For simplicity, only do this if shift is not
    2643          * already held down. */
    2644         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2645         {
    2646             codes[(*count)++] = 0x2a;
    2647             codes[(*count)++] = 0x2a | 0x80;
    2648         }
    2649     }
    2650 
    2651 #elif defined(Q_WS_WIN32)
    2652 
    2653     if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK))))
    2654     {
    2655         muNumLockAdaptionCnt--;
    2656         codes[(*count)++] = 0x45;
    2657         codes[(*count)++] = 0x45 | 0x80;
    2658     }
    2659     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL))))
    2660     {
    2661         muCapsLockAdaptionCnt--;
    2662         codes[(*count)++] = 0x3a;
    2663         codes[(*count)++] = 0x3a | 0x80;
    2664         /* Some keyboard layouts require shift to be pressed to break
    2665          * capslock.  For simplicity, only do this if shift is not
    2666          * already held down. */
    2667         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2668         {
    2669             codes[(*count)++] = 0x2a;
    2670             codes[(*count)++] = 0x2a | 0x80;
    2671         }
    2672     }
    2673 
    2674 #elif defined (Q_WS_MAC)
    2675 
    2676     /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */
    2677     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
    2678     {
    2679         muCapsLockAdaptionCnt--;
    2680         codes[(*count)++] = 0x3a;
    2681         codes[(*count)++] = 0x3a | 0x80;
    2682         /* Some keyboard layouts require shift to be pressed to break
    2683          * capslock.  For simplicity, only do this if shift is not
    2684          * already held down. */
    2685         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
    2686         {
    2687             codes[(*count)++] = 0x2a;
    2688             codes[(*count)++] = 0x2a | 0x80;
    2689         }
    2690     }
    2691 
    2692 #else
    2693 
    2694 //#warning Adapt VBoxConsoleView::fixModifierState
    2695 
    2696 #endif
    2697 
    2698 
    2699 }
    2700 
    2701 /**
    2702  *  Called on enter/exit seamless/fullscreen mode.
    2703  */
    2704 void VBoxConsoleView::toggleFSMode (const QSize &aSize)
    2705 {
    2706     if ((mGuestSupportsGraphics && mAutoresizeGuest) ||
    2707         mMainWnd->isTrueSeamless() ||
    2708         mMainWnd->isTrueFullscreen())
    2709     {
    2710         QSize newSize;
    2711         if (aSize.isValid())
    2712         {
    2713             mNormalSize = aSize;
    2714             newSize = maximumSize();
    2715         }
    2716         else
    2717             newSize = mNormalSize;
    2718         doResizeHint (newSize);
    2719     }
    2720 
    2721     /* Reactivate the console window to preserve the focus position.
    2722      * Else focus will move to the mini-tool-bar. */
    2723     activateWindow();
    2724 }
    2725 
    2726 /**
    2727  * Get the current available desktop geometry for the console/framebuffer
    2728  *
    2729  * @returns the geometry.  An empty rectangle means unrestricted.
    2730  */
    2731 QRect VBoxConsoleView::desktopGeometry()
    2732 {
    2733     QRect rc;
    2734     switch (mDesktopGeo)
    2735     {
    2736         case DesktopGeo_Fixed:
    2737         case DesktopGeo_Automatic:
    2738             rc = QRect (0, 0,
    2739                         RT_MAX (mDesktopGeometry.width(), mStoredConsoleSize.width()),
    2740                         RT_MAX (mDesktopGeometry.height(), mStoredConsoleSize.height()));
    2741             break;
    2742         case DesktopGeo_Any:
    2743             rc = QRect (0, 0, 0, 0);
    2744             break;
    2745         default:
    2746             AssertMsgFailed (("Bad geometry type %d\n", mDesktopGeo));
    2747     }
    2748     return rc;
    2749 }
    2750 
    2751 QRegion VBoxConsoleView::lastVisibleRegion() const
    2752 {
    2753     return mLastVisibleRegion;
    2754 }
    2755 
    2756 bool VBoxConsoleView::isAutoresizeGuestActive()
    2757 {
    2758     return mGuestSupportsGraphics && mAutoresizeGuest;
    2759 }
    2760 
    2761 /**
    2762  *  Called on every key press and release (while in focus).
    2763  *
    2764  *  @param aKey        virtual scan code (virtual key on Win32 and KeySym on X11)
    2765  *  @param aScan       hardware scan code
    2766  *  @param aFlags      flags, a combination of Key* constants
    2767  *  @param aUniKey     Unicode translation of the key. Optional.
    2768  *
    2769  *  @return     true to consume the event and false to pass it to Qt
    2770  */
    2771 bool VBoxConsoleView::keyEvent (int aKey, uint8_t aScan, int aFlags,
    2772                                 wchar_t *aUniKey/* = NULL*/)
    2773 {
    2774 #if 0
    2775     {
    2776         char buf [256];
    2777         sprintf (buf, "aKey=%08X aScan=%02X aFlags=%08X",
    2778                  aKey, aScan, aFlags);
    2779         mMainWnd->statusBar()->message (buf);
    2780     }
    2781 #endif
    2782 
    2783     const bool isHostKey = aKey == gs.hostKey();
    2784 
    2785     LONG buf [16];
    2786     LONG *codes = buf;
    2787     uint count = 0;
    2788     uint8_t whatPressed = 0;
    2789 
    2790     if (!isHostKey && !mIsHostkeyPressed)
    2791     {
    2792         if (aFlags & KeyPrint)
    2793         {
    2794             static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 };
    2795             static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA };
    2796             if (aFlags & KeyPressed)
    2797             {
    2798                 codes = PrintMake;
    2799                 count = SIZEOF_ARRAY (PrintMake);
    2800             }
    2801             else
    2802             {
    2803                 codes = PrintBreak;
    2804                 count = SIZEOF_ARRAY (PrintBreak);
    2805             }
    2806         }
    2807         else if (aFlags & KeyPause)
    2808         {
    2809             if (aFlags & KeyPressed)
    2810             {
    2811                 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 };
    2812                 codes = Pause;
    2813                 count = SIZEOF_ARRAY (Pause);
    2814             }
    2815             else
    2816             {
    2817                 /* Pause shall not produce a break code */
    2818                 return true;
    2819             }
    2820         }
    2821         else
    2822         {
    2823             if (aFlags & KeyPressed)
    2824             {
    2825                 /* Check if the guest has the same view on the modifier keys (NumLock,
    2826                  * CapsLock, ScrollLock) as the X server. If not, send KeyPress events
    2827                  * to synchronize the state. */
    2828                 fixModifierState (codes, &count);
    2829             }
    2830 
    2831             /* Check if it's C-A-D and GUI/PassCAD is not true */
    2832             if (!mPassCAD &&
    2833                 aScan == 0x53 /* Del */ &&
    2834                 ((mPressedKeys [0x38] & IsKeyPressed) /* Alt */ ||
    2835                  (mPressedKeys [0x38] & IsExtKeyPressed)) &&
    2836                 ((mPressedKeys [0x1d] & IsKeyPressed) /* Ctrl */ ||
    2837                  (mPressedKeys [0x1d] & IsExtKeyPressed)))
    2838             {
    2839                 /* Use the C-A-D combination as a last resort to get the
    2840                  * keyboard and mouse back to the host when the user forgets
    2841                  * the Host Key. Note that it's always possible to send C-A-D
    2842                  * to the guest using the Host+Del combination. BTW, it would
    2843                  * be preferrable to completely ignore C-A-D in guests, but
    2844                  * that's not possible because we cannot predict what other
    2845                  * keys will be pressed next when one of C, A, D is held. */
    2846 
    2847                 if (isRunning() && mKbdCaptured)
    2848                 {
    2849                     captureKbd (false);
    2850                     if (!(mMouseAbsolute && mMouseIntegration))
    2851                         captureMouse (false);
    2852                 }
    2853 
    2854                 return true;
    2855             }
    2856 
    2857             /* process the scancode and update the table of pressed keys */
    2858             whatPressed = IsKeyPressed;
    2859 
    2860             if (aFlags & KeyExtended)
    2861             {
    2862                 codes [count++] = 0xE0;
    2863                 whatPressed = IsExtKeyPressed;
    2864             }
    2865 
    2866             if (aFlags & KeyPressed)
    2867             {
    2868                 codes [count++] = aScan;
    2869                 mPressedKeys [aScan] |= whatPressed;
    2870             }
    2871             else
    2872             {
    2873                 /* if we haven't got this key's press message, we ignore its
    2874                  * release */
    2875                 if (!(mPressedKeys [aScan] & whatPressed))
    2876                     return true;
    2877                 codes [count++] = aScan | 0x80;
    2878                 mPressedKeys [aScan] &= ~whatPressed;
    2879             }
    2880 
    2881             if (mKbdCaptured)
    2882                 mPressedKeys [aScan] |= IsKbdCaptured;
    2883             else
    2884                 mPressedKeys [aScan] &= ~IsKbdCaptured;
    2885         }
    2886     }
    2887     else
    2888     {
    2889         /* currently this is used in winLowKeyboardEvent() only */
    2890         hostkey_in_capture = mKbdCaptured;
    2891     }
    2892 
    2893     bool emitSignal = false;
    2894     int hotkey = 0;
    2895 
    2896     /* process the host key */
    2897     if (aFlags & KeyPressed)
    2898     {
    2899         if (isHostKey)
    2900         {
    2901             if (!mIsHostkeyPressed)
    2902             {
    2903                 mIsHostkeyPressed = mIsHostkeyAlone = true;
    2904                 if (isRunning())
    2905                     saveKeyStates();
    2906                 emitSignal = true;
    2907             }
    2908         }
    2909         else
    2910         {
    2911             if (mIsHostkeyPressed)
    2912             {
    2913                 if (mIsHostkeyAlone)
    2914                 {
    2915                     hotkey = aKey;
    2916                     mIsHostkeyAlone = false;
    2917                 }
    2918             }
    2919         }
    2920     }
    2921     else
    2922     {
    2923         if (isHostKey)
    2924         {
    2925             if (mIsHostkeyPressed)
    2926             {
    2927                 mIsHostkeyPressed = false;
    2928 
    2929                 if (mIsHostkeyAlone)
    2930                 {
    2931                     if (isPaused())
    2932                     {
    2933                         vboxProblem().remindAboutPausedVMInput();
    2934                     }
    2935                     else
    2936                     if (isRunning())
    2937                     {
    2938                         bool captured = mKbdCaptured;
    2939                         bool ok = true;
    2940                         if (!captured)
    2941                         {
    2942                             /* temporarily disable auto capture that will take
    2943                              * place after this dialog is dismissed because
    2944                              * the capture state is to be defined by the
    2945                              * dialog result itself */
    2946                             mDisableAutoCapture = true;
    2947                             bool autoConfirmed = false;
    2948                             ok = vboxProblem().confirmInputCapture (&autoConfirmed);
    2949                             if (autoConfirmed)
    2950                                 mDisableAutoCapture = false;
    2951                             /* otherwise, the disable flag will be reset in
    2952                              * the next console view's foucs in event (since
    2953                              * may happen asynchronously on some platforms,
    2954                              * after we return from this code) */
    2955                         }
    2956 
    2957                         if (ok)
    2958                         {
    2959                             captureKbd (!captured, false);
    2960                             if (!(mMouseAbsolute && mMouseIntegration))
    2961                             {
    2962 #ifdef Q_WS_X11
    2963                                 /* make sure that pending FocusOut events from the
    2964                                  * previous message box are handled, otherwise the
    2965                                  * mouse is immediately ungrabbed. */
    2966                                 qApp->processEvents();
    2967 #endif
    2968                                 captureMouse (mKbdCaptured);
    2969                             }
    2970                         }
    2971                     }
    2972                 }
    2973 
    2974                 if (isRunning())
    2975                     sendChangedKeyStates();
    2976 
    2977                 emitSignal = true;
    2978             }
    2979         }
    2980         else
    2981         {
    2982             if (mIsHostkeyPressed)
    2983                 mIsHostkeyAlone = false;
    2984         }
    2985     }
    2986 
    2987     /* emit the keyboard state change signal */
    2988     if (emitSignal)
    2989         emitKeyboardStateChanged();
    2990 
    2991     /* Process Host+<key> shortcuts. currently, <key> is limited to
    2992      * alphanumeric chars. Other Host+<key> combinations are handled in
    2993      * event(). */
    2994     if (hotkey)
    2995     {
    2996         bool processed = false;
    2997 #if defined (Q_WS_WIN32)
    2998         NOREF(aUniKey);
    2999         int n = GetKeyboardLayoutList (0, NULL);
    3000         Assert (n);
    3001         HKL *list = new HKL [n];
    3002         GetKeyboardLayoutList (n, list);
    3003         for (int i = 0; i < n && !processed; i++)
    3004         {
    3005             wchar_t ch;
    3006             static BYTE keys [256] = {0};
    3007             if (!ToUnicodeEx (hotkey, 0, keys, &ch, 1, 0, list [i]) == 1)
    3008                 ch = 0;
    3009             if (ch)
    3010                 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3011                                                 QChar (ch).toUpper().unicode()),
    3012                                            mMainWnd->menuBar()->actions());
    3013         }
    3014         delete[] list;
    3015 #elif defined (Q_WS_X11)
    3016         NOREF(aUniKey);
    3017         Display *display = QX11Info::display();
    3018         int keysyms_per_keycode = getKeysymsPerKeycode();
    3019         KeyCode kc = XKeysymToKeycode (display, aKey);
    3020         // iterate over the first level (not shifted) keysyms in every group
    3021         for (int i = 0; i < keysyms_per_keycode && !processed; i += 2)
    3022         {
    3023             KeySym ks = XKeycodeToKeysym (display, kc, i);
    3024             char ch = 0;
    3025             if (!XkbTranslateKeySym (display, &ks, 0, &ch, 1, NULL) == 1)
    3026                 ch = 0;
    3027             if (ch)
    3028             {
    3029                 QChar c = QString::fromLocal8Bit (&ch, 1) [0];
    3030                 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3031                                                          c.toUpper().unicode()),
    3032                                            mMainWnd->menuBar()->actions());
    3033             }
    3034         }
    3035 #elif defined (Q_WS_MAC)
    3036         if (aUniKey && aUniKey [0] && !aUniKey [1])
    3037             processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    3038                                                      QChar (aUniKey [0]).toUpper().unicode()),
    3039                                        mMainWnd->menuBar()->actions());
    3040 
    3041         /* Don't consider the hot key as pressed since the guest never saw
    3042          * it. (probably a generic thing) */
    3043         mPressedKeys [aScan] &= ~whatPressed;
    3044 #endif
    3045 
    3046         /* grab the key from Qt if processed, or pass it to Qt otherwise
    3047          * in order to process non-alphanumeric keys in event(), after they are
    3048          * converted to Qt virtual keys. */
    3049         return processed;
    3050     }
    3051 
    3052     /* no more to do, if the host key is in action or the VM is paused */
    3053     if (mIsHostkeyPressed || isHostKey || isPaused())
    3054     {
    3055         /* grab the key from Qt and from VM if it's a host key,
    3056          * otherwise just pass it to Qt */
    3057         return isHostKey;
    3058     }
    3059 
    3060     CKeyboard keyboard = mConsole.GetKeyboard();
    3061     Assert (!keyboard.isNull());
    3062 
    3063 #if defined (Q_WS_WIN32)
    3064     /* send pending WM_PAINT events */
    3065     ::UpdateWindow (viewport()->winId());
    3066 #endif
    3067 
    3068 #if 0
    3069     {
    3070         char buf [256];
    3071         sprintf (buf, "*** SCANS: ");
    3072         for (uint i = 0; i < count; ++ i)
    3073             sprintf (buf + strlen (buf), "%02X ", codes [i]);
    3074         mMainWnd->statusBar()->message (buf);
    3075         LogFlow (("%s\n", buf));
    3076     }
    3077 #endif
    3078 
    3079     std::vector <LONG> scancodes(codes, &codes[count]);
    3080     keyboard.PutScancodes (QVector<LONG>::fromStdVector(scancodes));
    3081 
    3082     /* grab the key from Qt */
    3083     return true;
    3084 }
    3085 
    3086 /**
    3087  *  Called on every mouse/wheel move and button press/release.
    3088  *
    3089  *  @return     true to consume the event and false to pass it to Qt
    3090  */
    3091 bool VBoxConsoleView::mouseEvent (int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    3092                                   Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
    3093                                   int aWheelDelta, Qt::Orientation aWheelDir)
    3094 {
    3095 #if 1
    3096 
    3097     LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n",
    3098              __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(),
    3099                (aButtons & Qt::LeftButton ? 1 : 0)
    3100              | (aButtons & Qt::RightButton ? 2 : 0)
    3101              | (aButtons & Qt::MidButton ? 4 : 0)
    3102              | (aButtons & Qt::XButton1 ? 8 : 0)
    3103              | (aButtons & Qt::XButton2 ? 16 : 0),
    3104              aWheelDelta,
    3105                aWheelDir == Qt::Horizontal ? "Horizontal"
    3106              : aWheelDir == Qt::Vertical ? "Vertical" : "Unknown"));
    3107     Q_UNUSED (aModifiers);
    3108 #else
    3109     Q_UNUSED (aModifiers);
    3110 #endif
    3111 
    3112     int state = 0;
    3113     if (aButtons & Qt::LeftButton)
    3114         state |= KMouseButtonState_LeftButton;
    3115     if (aButtons & Qt::RightButton)
    3116         state |= KMouseButtonState_RightButton;
    3117     if (aButtons & Qt::MidButton)
    3118         state |= KMouseButtonState_MiddleButton;
    3119     if (aButtons & Qt::XButton1)
    3120         state |= KMouseButtonState_XButton1;
    3121     if (aButtons & Qt::XButton2)
    3122         state |= KMouseButtonState_XButton2;
    3123 
    3124 #ifdef Q_WS_MAC
    3125     /* Simulate the right click on
    3126      * Host+Left Mouse */
    3127     if (mIsHostkeyPressed &&
    3128         mIsHostkeyAlone &&
    3129         state == KMouseButtonState_LeftButton)
    3130         state = KMouseButtonState_RightButton;
    3131 #endif /* Q_WS_MAC */
    3132 
    3133     int wheelVertical = 0;
    3134     int wheelHorizontal = 0;
    3135     if (aWheelDir == Qt::Vertical)
    3136     {
    3137         /* the absolute value of wheel delta is 120 units per every wheel
    3138          * move; positive deltas correspond to counterclockwize rotations
    3139          * (usually up), negative -- to clockwize (usually down). */
    3140         wheelVertical = - (aWheelDelta / 120);
    3141     }
    3142     else if (aWheelDir == Qt::Horizontal)
    3143         wheelHorizontal = aWheelDelta / 120;
    3144 
    3145     if (mMouseCaptured)
    3146     {
    3147 #ifdef Q_WS_WIN32
    3148         /* send pending WM_PAINT events */
    3149         ::UpdateWindow (viewport()->winId());
    3150 #endif
    3151 
    3152         CMouse mouse = mConsole.GetMouse();
    3153         mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(),
    3154                              aGlobalPos.y() - mLastPos.y(),
    3155                              wheelVertical, wheelHorizontal, state);
    3156 
    3157 #if defined (Q_WS_MAC)
    3158         /*
    3159          * Keep the mouse from leaving the widget.
    3160          *
    3161          * This is a bit tricky to get right because if it escapes we won't necessarily
    3162          * get mouse events any longer and can warp it back. So, we keep safety zone
    3163          * of up to 300 pixels around the borders of the widget to prevent this from
    3164          * happening. Also, the mouse is warped back to the center of the widget.
    3165          *
    3166          * (Note, aPos seems to be unreliable, it caused endless recursion here at one points...)
    3167          * (Note, synergy and other remote clients might not like this cursor warping.)
    3168          */
    3169         QRect rect = viewport()->visibleRegion().boundingRect();
    3170         QPoint pw = viewport()->mapToGlobal (viewport()->pos());
    3171         rect.translate (pw.x(), pw.y());
    3172 
    3173         QRect dpRect = QApplication::desktop()->screenGeometry (viewport());
    3174         if (rect.intersects (dpRect))
    3175             rect = rect.intersect (dpRect);
    3176 
    3177         int wsafe = rect.width() / 6;
    3178         rect.setWidth (rect.width() - wsafe * 2);
    3179         rect.setLeft (rect.left() + wsafe);
    3180 
    3181         int hsafe = rect.height() / 6;
    3182         rect.setWidth (rect.height() - hsafe * 2);
    3183         rect.setTop (rect.top() + hsafe);
    3184 
    3185         if (rect.contains (aGlobalPos, true))
    3186             mLastPos = aGlobalPos;
    3187         else
    3188         {
    3189             mLastPos = rect.center();
    3190             QCursor::setPos (mLastPos);
    3191         }
    3192 
    3193 #else /* !Q_WS_MAC */
    3194 
    3195         /* "jerk" the mouse by bringing it to the opposite side
    3196          * to simulate the endless moving */
    3197 
    3198 #ifdef Q_WS_WIN32
    3199         int we = viewport()->width() - 1;
    3200         int he = viewport()->height() - 1;
    3201         QPoint p = aPos;
    3202         if (aPos.x() == 0)
    3203             p.setX (we - 1);
    3204         else if (aPos.x() == we)
    3205             p.setX (1);
    3206         if (aPos.y() == 0 )
    3207             p.setY (he - 1);
    3208         else if (aPos.y() == he)
    3209             p.setY (1);
    3210 
    3211         if (p != aPos)
    3212         {
    3213             mLastPos = viewport()->mapToGlobal (p);
    3214             QCursor::setPos (mLastPos);
    3215         }
    3216         else
    3217         {
    3218             mLastPos = aGlobalPos;
    3219         }
    3220 #else
    3221         int we = QApplication::desktop()->width() - 1;
    3222         int he = QApplication::desktop()->height() - 1;
    3223         QPoint p = aGlobalPos;
    3224         if (aGlobalPos.x() == 0)
    3225             p.setX (we - 1);
    3226         else if (aGlobalPos.x() == we)
    3227             p.setX( 1 );
    3228         if (aGlobalPos.y() == 0)
    3229             p.setY (he - 1);
    3230         else if (aGlobalPos.y() == he)
    3231             p.setY (1);
    3232 
    3233         if (p != aGlobalPos)
    3234         {
    3235             mLastPos =  p;
    3236             QCursor::setPos (mLastPos);
    3237         }
    3238         else
    3239         {
    3240             mLastPos = aGlobalPos;
    3241         }
    3242 #endif
    3243 #endif /* !Q_WS_MAC */
    3244         return true; /* stop further event handling */
    3245     }
    3246     else /* !mMouseCaptured */
    3247     {
    3248         if (mMainWnd->isTrueFullscreen())
    3249         {
    3250             if (mode != VBoxDefs::SDLMode)
    3251             {
    3252                 /* try to automatically scroll the guest canvas if the
    3253                  * mouse is on the screen border */
    3254                 /// @todo (r=dmik) better use a timer for autoscroll
    3255                 QRect scrGeo = QApplication::desktop()->screenGeometry (this);
    3256                 int dx = 0, dy = 0;
    3257                 if (scrGeo.width() < contentsWidth())
    3258                 {
    3259                     if (scrGeo.left() == aGlobalPos.x()) dx = -1;
    3260                     if (scrGeo.right() == aGlobalPos.x()) dx = +1;
    3261                 }
    3262                 if (scrGeo.height() < contentsHeight())
    3263                 {
    3264                     if (scrGeo.top() == aGlobalPos.y()) dy = -1;
    3265                     if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
    3266                 }
    3267                 if (dx || dy)
    3268                     scrollBy (dx, dy);
    3269             }
    3270         }
    3271 
    3272         if (mMouseAbsolute && mMouseIntegration)
    3273         {
    3274             int cw = contentsWidth(), ch = contentsHeight();
    3275             int vw = visibleWidth(), vh = visibleHeight();
    3276 
    3277             if (mode != VBoxDefs::SDLMode)
    3278             {
    3279                 /* try to automatically scroll the guest canvas if the
    3280                  * mouse goes outside its visible part */
    3281 
    3282                 int dx = 0;
    3283                 if (aPos.x() > vw) dx = aPos.x() - vw;
    3284                 else if (aPos.x() < 0) dx = aPos.x();
    3285                 int dy = 0;
    3286                 if (aPos.y() > vh) dy = aPos.y() - vh;
    3287                 else if (aPos.y() < 0) dy = aPos.y();
    3288                 if (dx != 0 || dy != 0) scrollBy (dx, dy);
    3289             }
    3290 
    3291             QPoint cpnt = viewportToContents (aPos);
    3292             if (cpnt.x() < 0) cpnt.setX (0);
    3293             else if (cpnt.x() > cw) cpnt.setX (cw);
    3294             if (cpnt.y() < 0) cpnt.setY (0);
    3295             else if (cpnt.y() > ch) cpnt.setY (ch);
    3296 
    3297             CMouse mouse = mConsole.GetMouse();
    3298             mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical,
    3299                                          wheelHorizontal, state);
    3300             return true; /* stop further event handling */
    3301         }
    3302         else
    3303         {
    3304             if (hasFocus() &&
    3305                 (aType == QEvent::MouseButtonRelease &&
    3306                  aButtons == Qt::NoButton))
    3307             {
    3308                 if (isPaused())
    3309                 {
    3310                     vboxProblem().remindAboutPausedVMInput();
    3311                 }
    3312                 else if (isRunning())
    3313                 {
    3314                     /* temporarily disable auto capture that will take
    3315                      * place after this dialog is dismissed because
    3316                      * the capture state is to be defined by the
    3317                      * dialog result itself */
    3318                     mDisableAutoCapture = true;
    3319                     bool autoConfirmed = false;
    3320                     bool ok = vboxProblem().confirmInputCapture (&autoConfirmed);
    3321                     if (autoConfirmed)
    3322                         mDisableAutoCapture = false;
    3323                     /* otherwise, the disable flag will be reset in
    3324                      * the next console view's foucs in event (since
    3325                      * may happen asynchronously on some platforms,
    3326                      * after we return from this code) */
    3327 
    3328                     if (ok)
    3329                     {
    3330 #ifdef Q_WS_X11
    3331                         /* make sure that pending FocusOut events from the
    3332                          * previous message box are handled, otherwise the
    3333                          * mouse is immediately ungrabbed again */
    3334                         qApp->processEvents();
    3335 #endif
    3336                         captureKbd (true);
    3337                         captureMouse (true);
    3338                     }
    3339                 }
    3340             }
    3341         }
    3342     }
    3343 
    3344     return false;
    3345 }
    3346 
    3347 void VBoxConsoleView::onStateChange (KMachineState state)
    3348 {
    3349     switch (state)
    3350     {
    3351         case KMachineState_Paused:
    3352         case KMachineState_TeleportingPausedVM:
    3353         {
    3354             if (    mode != VBoxDefs::TimerMode
    3355                 &&  mFrameBuf
    3356                 &&  (   state      != KMachineState_TeleportingPausedVM
    3357                      || mLastState != KMachineState_Teleporting)
    3358                )
    3359             {
    3360                 /*
    3361                  *  Take a screen snapshot. Note that TakeScreenShot() always
    3362                  *  needs a 32bpp image
    3363                  */
    3364                 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32);
    3365                 CDisplay dsp = mConsole.GetDisplay();
    3366                 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height());
    3367                 /*
    3368                  *  TakeScreenShot() may fail if, e.g. the Paused notification
    3369                  *  was delivered after the machine execution was resumed. It's
    3370                  *  not fatal.
    3371                  */
    3372                 if (dsp.isOk())
    3373                 {
    3374                     dimImage (shot);
    3375                     mPausedShot = QPixmap::fromImage (shot);
    3376                     /* fully repaint to pick up mPausedShot */
    3377                     repaint();
    3378                 }
    3379             }
    3380             /* fall through */
    3381         }
    3382         case KMachineState_Stuck:
    3383         {
    3384             /* reuse the focus event handler to uncapture everything */
    3385             if (hasFocus())
    3386                 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */);
    3387             break;
    3388         }
    3389         case KMachineState_Running:
    3390         {
    3391             if (   mLastState == KMachineState_Paused
    3392                 || mLastState == KMachineState_TeleportingPausedVM
    3393                )
    3394             {
    3395                 if (mode != VBoxDefs::TimerMode && mFrameBuf)
    3396                 {
    3397                     /* reset the pixmap to free memory */
    3398                     mPausedShot = QPixmap ();
    3399                     /*
    3400                      *  ask for full guest display update (it will also update
    3401                      *  the viewport through IFramebuffer::NotifyUpdate)
    3402                      */
    3403                     CDisplay dsp = mConsole.GetDisplay();
    3404                     dsp.InvalidateAndUpdate();
    3405                 }
    3406             }
    3407             /* reuse the focus event handler to capture input */
    3408             if (hasFocus())
    3409                 focusEvent (true /* aHasFocus */);
    3410             break;
    3411         }
    3412         default:
    3413             break;
    3414     }
    3415 
    3416     mLastState = state;
    3417 }
    3418 
    3419 void VBoxConsoleView::doRefresh()
    3420 {
    3421     viewport()->repaint();
    3422 }
    3423 
    3424 void VBoxConsoleView::resizeEvent (QResizeEvent *)
    3425 {
    3426     updateSliders();
    3427 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    3428     QRect r = viewport()->geometry();
    3429 //    printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height());
    3430     PostBoundsChanged (r);
    3431 #endif /* Q_WS_MAC */
    3432 }
    3433 
    3434 void VBoxConsoleView::moveEvent (QMoveEvent *)
    3435 {
    3436 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    3437     QRect r = viewport()->geometry();
    3438 //    printf ("qt resize: %d %d %d %d\n", r.x(), r.y(), r.width(), r.height());
    3439     PostBoundsChanged (r);
    3440 #endif /* Q_WS_MAC */
    3441 }
    3442 
    3443 void VBoxConsoleView::paintEvent (QPaintEvent *pe)
    3444 {
    3445     if (mPausedShot.isNull())
    3446     {
    3447         /* delegate the paint function to the VBoxFrameBuffer interface */
    3448         if (mFrameBuf)
    3449             mFrameBuf->paintEvent (pe);
    3450 #ifdef Q_WS_MAC
    3451         /* Update the dock icon if we are in the running state */
    3452         if (isRunning())
    3453             updateDockIcon();
    3454 #endif
    3455         return;
    3456     }
    3457 
    3458 #ifdef VBOX_GUI_USE_QUARTZ2D
    3459     if (mode == VBoxDefs::Quartz2DMode && mFrameBuf)
    3460     {
    3461         mFrameBuf->paintEvent (pe);
    3462         updateDockIcon();
    3463     }
    3464     else
    3465 #endif
    3466     {
    3467         /* we have a snapshot for the paused state */
    3468         QRect r = pe->rect().intersect (viewport()->rect());
    3469         /* We have to disable paint on screen if we are using the regular painter */
    3470         bool paintOnScreen = viewport()->testAttribute (Qt::WA_PaintOnScreen);
    3471         viewport()->setAttribute (Qt::WA_PaintOnScreen, false);
    3472         QPainter pnt (viewport());
    3473         pnt.drawPixmap (r.x(), r.y(), mPausedShot,
    3474                         r.x() + contentsX(), r.y() + contentsY(),
    3475                         r.width(), r.height());
    3476         /* Restore the attribute to its previous state */
    3477         viewport()->setAttribute (Qt::WA_PaintOnScreen, paintOnScreen);
    3478 #ifdef Q_WS_MAC
    3479         updateDockIcon();
    3480 #endif
    3481     }
    3482 
    3483 }
    3484 
    3485 /**
    3486  *  Captures the keyboard. When captured, no keyboard input reaches the host
    3487  *  system (including most system combinations like Alt-Tab).
    3488  *
    3489  *  @param aCapture     true to capture, false to uncapture.
    3490  *  @param aEmitSignal  Whether to emit keyboardStateChanged() or not.
    3491  */
    3492 void VBoxConsoleView::captureKbd (bool aCapture, bool aEmitSignal /* = true */)
    3493 {
    3494     AssertMsg (mAttached, ("Console must be attached"));
    3495 
    3496     if (mKbdCaptured == aCapture)
    3497         return;
    3498 
    3499     /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is
    3500      * used instead. On X11, we use XGrabKey instead of XGrabKeyboard (called
    3501      * by QWidget::grabKeyboard()) because the latter causes problems under
    3502      * metacity 2.16 (in particular, due to a bug, a window cannot be moved
    3503      * using the mouse if it is currently grabing the keyboard). On Mac OS X,
    3504      * we use the Qt methods + disabling global hot keys + watching modifiers
    3505      * (for right/left separation). */
    3506 #if defined (Q_WS_WIN32)
    3507     /**/
    3508 #elif defined (Q_WS_X11)
    3509     if (aCapture)
    3510         XGrabKey (QX11Info::display(), AnyKey, AnyModifier,
    3511                   window()->winId(), False,
    3512                   GrabModeAsync, GrabModeAsync);
    3513     else
    3514         XUngrabKey (QX11Info::display(),  AnyKey, AnyModifier,
    3515                     window()->winId());
    3516 #elif defined (Q_WS_MAC)
    3517     if (aCapture)
    3518     {
    3519         ::DarwinDisableGlobalHotKeys (true);
    3520         grabKeyboard();
    3521     }
    3522     else
    3523     {
    3524         ::DarwinDisableGlobalHotKeys (false);
    3525         releaseKeyboard();
    3526     }
    3527 #else
    3528     if (aCapture)
    3529         grabKeyboard();
    3530     else
    3531         releaseKeyboard();
    3532 #endif
    3533 
    3534     mKbdCaptured = aCapture;
    3535 
    3536     if (aEmitSignal)
    3537         emitKeyboardStateChanged();
    3538 }
    3539 
    3540 /**
    3541  *  Captures the host mouse pointer. When captured, the mouse pointer is
    3542  *  unavailable to the host applications.
    3543  *
    3544  *  @param aCapture     true to capture, false to uncapture.
    3545  *  @param aEmitSignal  Whether to emit mouseStateChanged() or not.
    3546  */
    3547 void VBoxConsoleView::captureMouse (bool aCapture, bool aEmitSignal /* = true */)
    3548 {
    3549     AssertMsg (mAttached, ("Console must be attached"));
    3550 
    3551     if (mMouseCaptured == aCapture)
    3552         return;
    3553 
    3554     if (aCapture)
    3555     {
    3556         /* memorize the host position where the cursor was captured */
    3557         mCapturedPos = QCursor::pos();
    3558 #ifdef Q_WS_WIN32
    3559         viewport()->setCursor (QCursor (Qt::BlankCursor));
    3560         /* move the mouse to the center of the visible area */
    3561         QCursor::setPos (mapToGlobal (visibleRegion().boundingRect().center()));
    3562         mLastPos = QCursor::pos();
    3563 #elif defined (Q_WS_MAC)
    3564         /* move the mouse to the center of the visible area */
    3565         mLastPos = mapToGlobal (visibleRegion().boundingRect().center());
    3566         QCursor::setPos (mLastPos);
    3567         /* grab all mouse events. */
    3568         viewport()->grabMouse();
    3569 #else
    3570         viewport()->grabMouse();
    3571         mLastPos = QCursor::pos();
    3572 #endif
    3573     }
    3574     else
    3575     {
    3576 #ifndef Q_WS_WIN32
    3577         viewport()->releaseMouse();
    3578 #endif
    3579         /* release mouse buttons */
    3580         CMouse mouse = mConsole.GetMouse();
    3581         mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0);
    3582     }
    3583 
    3584     mMouseCaptured = aCapture;
    3585 
    3586     updateMouseClipping();
    3587 
    3588     if (aEmitSignal)
    3589         emitMouseStateChanged();
    3590 }
    3591 
    3592 /**
    3593  *  Searches for a menu item with a given hot key (shortcut). If the item
    3594  *  is found, activates it and returns true. Otherwise returns false.
    3595  */
    3596 bool VBoxConsoleView::processHotKey (const QKeySequence &aKey,
    3597                                      const QList <QAction*> &aData)
    3598 {
    3599     foreach (QAction *pAction, aData)
    3600     {
    3601         if (QMenu *menu = pAction->menu())
    3602         {
    3603             /* Process recursively for each sub-menu */
    3604             if (processHotKey (aKey, menu->actions()))
    3605                 return true;
    3606         }
    3607         else
    3608         {
    3609             QString hotkey = VBoxGlobal::extractKeyFromActionText (pAction->text());
    3610             if (pAction->isEnabled() && !hotkey.isEmpty())
    3611             {
    3612                 if (aKey.matches (QKeySequence (hotkey)) == QKeySequence::ExactMatch)
    3613                 {
    3614                     /* We asynchronously post a special event instead of calling
    3615                      * pAction->trigger() directly, to let key presses and
    3616                      * releases be processed correctly by Qt first.
    3617                      * Note: we assume that nobody will delete the menu item
    3618                      * corresponding to the key sequence, so that the pointer to
    3619                      * menu data posted along with the event will remain valid in
    3620                      * the event handler, at least until the main window is closed. */
    3621                     QApplication::postEvent (this, new ActivateMenuEvent (pAction));
    3622                     return true;
    3623                 }
    3624             }
    3625         }
    3626     }
    3627 
    3628     return false;
    3629 }
    3630 
    3631 /**
    3632  * Send the KEY BREAK code to the VM for all currently pressed keys.
    3633  *
    3634  * @param aReleaseHostKey @c true to set the host key state to unpressed.
    3635  */
    3636 void VBoxConsoleView::releaseAllPressedKeys (bool aReleaseHostKey /* = true*/)
    3637 {
    3638     AssertMsg (mAttached, ("Console must be attached"));
    3639 
    3640     CKeyboard keyboard = mConsole.GetKeyboard();
    3641     bool fSentRESEND = false;
    3642 
    3643     /* send a dummy scan code (RESEND) to prevent the guest OS from recognizing
    3644      * a single key click (for ex., Alt) and performing an unwanted action
    3645      * (for ex., activating the menu) when we release all pressed keys below.
    3646      * Note, that it's just a guess that sending RESEND will give the desired
    3647      * effect :), but at least it works with NT and W2k guests. */
    3648 
    3649     /// @todo Sending 0xFE is responsible for the warning
    3650     //
    3651     //         ``atkbd.c: Spurious NAK on isa0060/serio0. Some program might
    3652     //           be trying access hardware directly''
    3653     //
    3654     //       on Linux guests (#1944). It might also be responsible for #1949. Don't
    3655     //       send this command unless we really have to release any key modifier.
    3656     //                                                                    --frank
    3657 
    3658     for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++)
    3659     {
    3660         if (mPressedKeys [i] & IsKeyPressed)
    3661         {
    3662             if (!fSentRESEND)
    3663             {
    3664                 keyboard.PutScancode (0xFE);
    3665                 fSentRESEND = true;
    3666             }
    3667             keyboard.PutScancode (i | 0x80);
    3668         }
    3669         else if (mPressedKeys [i] & IsExtKeyPressed)
    3670         {
    3671             if (!fSentRESEND)
    3672             {
    3673                 keyboard.PutScancode (0xFE);
    3674                 fSentRESEND = true;
    3675             }
    3676             QVector <LONG> codes (2);
    3677             codes[0] = 0xE0;
    3678             codes[1] = i | 0x80;
    3679             keyboard.PutScancodes (codes);
    3680         }
    3681         mPressedKeys [i] = 0;
    3682     }
    3683 
    3684     if (aReleaseHostKey)
    3685         mIsHostkeyPressed = false;
    3686 
    3687 #ifdef Q_WS_MAC
    3688     /* clear most of the modifiers. */
    3689     mDarwinKeyModifiers &=
    3690         alphaLock | kEventKeyModifierNumLockMask |
    3691         (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (gs.hostKey()));
    3692 #endif
    3693 
    3694     emitKeyboardStateChanged();
    3695 }
    3696 
    3697 void VBoxConsoleView::saveKeyStates()
    3698 {
    3699     ::memcpy (mPressedKeysCopy, mPressedKeys, sizeof (mPressedKeys));
    3700 }
    3701 
    3702 void VBoxConsoleView::sendChangedKeyStates()
    3703 {
    3704     AssertMsg (mAttached, ("Console must be attached"));
    3705 
    3706     QVector <LONG> codes (2);
    3707     CKeyboard keyboard = mConsole.GetKeyboard();
    3708     for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); ++ i)
    3709     {
    3710         uint8_t os = mPressedKeysCopy [i];
    3711         uint8_t ns = mPressedKeys [i];
    3712         if ((os & IsKeyPressed) != (ns & IsKeyPressed))
    3713         {
    3714             codes [0] = i;
    3715             if (!(ns & IsKeyPressed))
    3716                 codes[0] |= 0x80;
    3717             keyboard.PutScancode (codes[0]);
    3718         }
    3719         else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed))
    3720         {
    3721             codes [0] = 0xE0;
    3722             codes [1] = i;
    3723             if (!(ns & IsExtKeyPressed))
    3724                 codes [1] |= 0x80;
    3725             keyboard.PutScancodes (codes);
    3726         }
    3727     }
    3728 }
    3729 
    3730 void VBoxConsoleView::updateMouseClipping()
    3731 {
    3732     AssertMsg (mAttached, ("Console must be attached"));
    3733 
    3734     if (mMouseCaptured)
    3735     {
    3736         viewport()->setCursor (QCursor (Qt::BlankCursor));
    3737 #ifdef Q_WS_WIN32
    3738         QRect r = viewport()->rect();
    3739         r.moveTopLeft (viewport()->mapToGlobal (QPoint (0, 0)));
    3740         RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
    3741         ::ClipCursor (&rect);
    3742 #endif
    3743     }
    3744     else
    3745     {
    3746 #ifdef Q_WS_WIN32
    3747         ::ClipCursor (NULL);
    3748 #endif
    3749         /* return the cursor to where it was when we captured it and show it */
    3750         QCursor::setPos (mCapturedPos);
    3751         viewport()->unsetCursor();
    3752     }
    3753 }
    3754 
    3755 void VBoxConsoleView::setPointerShape (MousePointerChangeEvent *me)
    3756 {
    3757     if (me->shapeData() != NULL)
    3758     {
    3759         bool ok = false;
    3760 
    3761         const uchar *srcAndMaskPtr = me->shapeData();
    3762         uint andMaskSize = (me->width() + 7) / 8 * me->height();
    3763         const uchar *srcShapePtr = me->shapeData() + ((andMaskSize + 3) & ~3);
    3764         uint srcShapePtrScan = me->width() * 4;
    3765 
    3766 #if defined (Q_WS_WIN)
    3767 
    3768         BITMAPV5HEADER bi;
    3769         HBITMAP hBitmap;
    3770         void *lpBits;
    3771 
    3772         ::ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
    3773         bi.bV5Size = sizeof (BITMAPV5HEADER);
    3774         bi.bV5Width = me->width();
    3775         bi.bV5Height = - (LONG) me->height();
    3776         bi.bV5Planes = 1;
    3777         bi.bV5BitCount = 32;
    3778         bi.bV5Compression = BI_BITFIELDS;
    3779         // specifiy a supported 32 BPP alpha format for Windows XP
    3780         bi.bV5RedMask   = 0x00FF0000;
    3781         bi.bV5GreenMask = 0x0000FF00;
    3782         bi.bV5BlueMask  = 0x000000FF;
    3783         if (me->hasAlpha())
    3784             bi.bV5AlphaMask = 0xFF000000;
    3785         else
    3786             bi.bV5AlphaMask = 0;
    3787 
    3788         HDC hdc = GetDC (NULL);
    3789 
    3790         // create the DIB section with an alpha channel
    3791         hBitmap = CreateDIBSection (hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS,
    3792                                     (void **) &lpBits, NULL, (DWORD) 0);
    3793 
    3794         ReleaseDC (NULL, hdc);
    3795 
    3796         HBITMAP hMonoBitmap = NULL;
    3797         if (me->hasAlpha())
    3798         {
    3799             // create an empty mask bitmap
    3800             hMonoBitmap = CreateBitmap (me->width(), me->height(), 1, 1, NULL);
    3801         }
    3802         else
    3803         {
    3804             /* Word aligned AND mask. Will be allocated and created if necessary. */
    3805             uint8_t *pu8AndMaskWordAligned = NULL;
    3806 
    3807             /* Width in bytes of the original AND mask scan line. */
    3808             uint32_t cbAndMaskScan = (me->width() + 7) / 8;
    3809 
    3810             if (cbAndMaskScan & 1)
    3811             {
    3812                 /* Original AND mask is not word aligned. */
    3813 
    3814                 /* Allocate memory for aligned AND mask. */
    3815                 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ ((cbAndMaskScan + 1) * me->height());
    3816 
    3817                 Assert(pu8AndMaskWordAligned);
    3818 
    3819                 if (pu8AndMaskWordAligned)
    3820                 {
    3821                     /* According to MSDN the padding bits must be 0.
    3822                      * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask.
    3823                      */
    3824                     uint32_t u32PaddingBits = cbAndMaskScan * 8  - me->width();
    3825                     Assert(u32PaddingBits < 8);
    3826                     uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
    3827 
    3828                     Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
    3829                           u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, me->width(), cbAndMaskScan));
    3830 
    3831                     uint8_t *src = (uint8_t *)srcAndMaskPtr;
    3832                     uint8_t *dst = pu8AndMaskWordAligned;
    3833 
    3834                     unsigned i;
    3835                     for (i = 0; i < me->height(); i++)
    3836                     {
    3837                         memcpy (dst, src, cbAndMaskScan);
    3838 
    3839                         dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
    3840 
    3841                         src += cbAndMaskScan;
    3842                         dst += cbAndMaskScan + 1;
    3843                     }
    3844                 }
    3845             }
    3846 
    3847             /* create the AND mask bitmap */
    3848             hMonoBitmap = ::CreateBitmap (me->width(), me->height(), 1, 1,
    3849                                           pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
    3850 
    3851             if (pu8AndMaskWordAligned)
    3852             {
    3853                 RTMemTmpFree (pu8AndMaskWordAligned);
    3854             }
    3855         }
    3856 
    3857         Assert (hBitmap);
    3858         Assert (hMonoBitmap);
    3859         if (hBitmap && hMonoBitmap)
    3860         {
    3861             DWORD *dstShapePtr = (DWORD *) lpBits;
    3862 
    3863             for (uint y = 0; y < me->height(); y ++)
    3864             {
    3865                 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
    3866                 srcShapePtr += srcShapePtrScan;
    3867                 dstShapePtr += me->width();
    3868             }
    3869 
    3870             ICONINFO ii;
    3871             ii.fIcon = FALSE;
    3872             ii.xHotspot = me->xHot();
    3873             ii.yHotspot = me->yHot();
    3874             ii.hbmMask = hMonoBitmap;
    3875             ii.hbmColor = hBitmap;
    3876 
    3877             HCURSOR hAlphaCursor = CreateIconIndirect (&ii);
    3878             Assert (hAlphaCursor);
    3879             if (hAlphaCursor)
    3880             {
    3881                 viewport()->setCursor (QCursor (hAlphaCursor));
    3882                 ok = true;
    3883                 if (mAlphaCursor)
    3884                     DestroyIcon (mAlphaCursor);
    3885                 mAlphaCursor = hAlphaCursor;
    3886             }
    3887         }
    3888 
    3889         if (hMonoBitmap)
    3890             DeleteObject (hMonoBitmap);
    3891         if (hBitmap)
    3892             DeleteObject (hBitmap);
    3893 
    3894 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
    3895 
    3896         XcursorImage *img = XcursorImageCreate (me->width(), me->height());
    3897         Assert (img);
    3898         if (img)
    3899         {
    3900             img->xhot = me->xHot();
    3901             img->yhot = me->yHot();
    3902 
    3903             XcursorPixel *dstShapePtr = img->pixels;
    3904 
    3905             for (uint y = 0; y < me->height(); y ++)
    3906             {
    3907                 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
    3908 
    3909                 if (!me->hasAlpha())
    3910                 {
    3911                     /* convert AND mask to the alpha channel */
    3912                     uchar byte = 0;
    3913                     for (uint x = 0; x < me->width(); x ++)
    3914                     {
    3915                         if (!(x % 8))
    3916                             byte = *(srcAndMaskPtr ++);
    3917                         else
    3918                             byte <<= 1;
    3919 
    3920                         if (byte & 0x80)
    3921                         {
    3922                             /* Linux doesn't support inverted pixels (XOR ops,
    3923                              * to be exact) in cursor shapes, so we detect such
    3924                              * pixels and always replace them with black ones to
    3925                              * make them visible at least over light colors */
    3926                             if (dstShapePtr [x] & 0x00FFFFFF)
    3927                                 dstShapePtr [x] = 0xFF000000;
    3928                             else
    3929                                 dstShapePtr [x] = 0x00000000;
    3930                         }
    3931                         else
    3932                             dstShapePtr [x] |= 0xFF000000;
    3933                     }
    3934                 }
    3935 
    3936                 srcShapePtr += srcShapePtrScan;
    3937                 dstShapePtr += me->width();
    3938             }
    3939 
    3940             Cursor cur = XcursorImageLoadCursor (QX11Info::display(), img);
    3941             Assert (cur);
    3942             if (cur)
    3943             {
    3944                 viewport()->setCursor (QCursor (cur));
    3945                 ok = true;
    3946             }
    3947 
    3948             XcursorImageDestroy (img);
    3949         }
    3950 
    3951 #elif defined(Q_WS_MAC)
    3952 
    3953         /* Create a ARGB image out of the shape data. */
    3954         QImage image  (me->width(), me->height(), QImage::Format_ARGB32);
    3955         const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
    3956         unsigned cbSrcMaskLine = RT_ALIGN (me->width(), 8) / 8;
    3957         for (unsigned int y = 0; y < me->height(); ++y)
    3958         {
    3959             for (unsigned int x = 0; x < me->width(); ++x)
    3960             {
    3961                unsigned int color = ((unsigned int*)srcShapePtr)[y*me->width()+x];
    3962                /* If the alpha channel isn't in the shape data, we have to
    3963                 * create them from the and-mask. This is a bit field where 1
    3964                 * represent transparency & 0 opaque respectively. */
    3965                if (!me->hasAlpha())
    3966                {
    3967                    if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
    3968                        color  |= 0xff000000;
    3969                    else
    3970                    {
    3971                        /* This isn't quite right, but it's the best we can do I
    3972                         * think... */
    3973                        if (color & 0x00ffffff)
    3974                            color = 0xff000000;
    3975                        else
    3976                            color = 0x00000000;
    3977                    }
    3978                }
    3979                image.setPixel (x, y, color);
    3980             }
    3981             /* Move one scanline forward. */
    3982             pbSrcMask += cbSrcMaskLine;
    3983         }
    3984         /* Set the new cursor */
    3985         QCursor cursor (QPixmap::fromImage (image),
    3986                         me->xHot(), me->yHot());
    3987         viewport()->setCursor (cursor);
    3988         ok = true;
    3989         NOREF (srcShapePtrScan);
    3990 
    3991 #else
    3992 
    3993 # warning "port me"
    3994 
    3995 #endif
    3996         if (ok)
    3997             mLastCursor = viewport()->cursor();
    3998         else
    3999             viewport()->unsetCursor();
    4000     }
    4001     else
    4002     {
    4003         /*
    4004          * We did not get any shape data
    4005          */
    4006         if (me->isVisible())
    4007         {
    4008             viewport()->setCursor (mLastCursor);
    4009         }
    4010         else
    4011         {
    4012             viewport()->setCursor (Qt::BlankCursor);
    4013         }
    4014     }
    4015     mHideHostPointer = !me->isVisible();
    4016 }
    4017 
    4018 inline QRgb qRgbIntensity (QRgb rgb, int mul, int div)
    4019 {
    4020     int r = qRed (rgb);
    4021     int g = qGreen (rgb);
    4022     int b = qBlue (rgb);
    4023     return qRgb (mul * r / div, mul * g / div, mul * b / div);
    4024 }
    4025 
    4026 /* static */
    4027 void VBoxConsoleView::dimImage (QImage &img)
    4028 {
    4029     for (int y = 0; y < img.height(); y ++) {
    4030         if (y % 2) {
    4031             if (img.depth() == 32) {
    4032                 for (int x = 0; x < img.width(); x ++) {
    4033                     int gray = qGray (img.pixel (x, y)) / 2;
    4034                     img.setPixel (x, y, qRgb (gray, gray, gray));
    4035 //                    img.setPixel (x, y, qRgbIntensity (img.pixel (x, y), 1, 2));
    4036                 }
    4037             } else {
    4038                 ::memset (img.scanLine (y), 0, img.bytesPerLine());
    4039             }
    4040         } else {
    4041             if (img.depth() == 32) {
    4042                 for (int x = 0; x < img.width(); x ++) {
    4043                     int gray = (2 * qGray (img.pixel (x, y))) / 3;
    4044                     img.setPixel (x, y, qRgb (gray, gray, gray));
    4045 //                    img.setPixel (x, y, qRgbIntensity (img.pixel(x, y), 2, 3));
    4046                 }
    4047             }
    4048         }
    4049     }
    4050 }
    4051 
    4052 void VBoxConsoleView::doResizeHint (const QSize &aToSize)
    4053 {
    4054     if (mGuestSupportsGraphics && mAutoresizeGuest)
    4055     {
    4056         /* If this slot is invoked directly then use the passed size
    4057          * otherwise get the available size for the guest display.
    4058          * We assume here that the centralWidget() contains this view only
    4059          * and gives it all available space. */
    4060         QSize sz (aToSize.isValid() ? aToSize : mMainWnd->centralWidget()->size());
    4061         if (!aToSize.isValid())
    4062             sz -= QSize (frameWidth() * 2, frameWidth() * 2);
    4063         /* Do not send out useless hints. */
    4064         if ((sz.width() == mStoredConsoleSize.width()) &&
    4065             (sz.height() == mStoredConsoleSize.height()))
    4066             return;
    4067         /* We only actually send the hint if
    4068          * 1) the autoresize property is set to true and
    4069          * 2) either an explicit new size was given (e.g. if the request
    4070          *    was triggered directly by a console resize event) or if no
    4071          *    explicit size was specified but a resize is flagged as being
    4072          *    needed (e.g. the autoresize was just enabled and the console
    4073          *    was resized while it was disabled). */
    4074         if (mAutoresizeGuest &&
    4075             (aToSize.isValid() || mDoResize))
    4076         {
    4077             LogFlowFunc (("Will suggest %d x %d\n", sz.width(), sz.height()));
    4078 
    4079             /* Remember the new size. */
    4080             storeConsoleSize (sz.width(), sz.height());
    4081 
    4082             mConsole.GetDisplay().SetVideoModeHint (sz.width(), sz.height(), 0, 0);
    4083         }
    4084         /* we have resized now... */
    4085         mDoResize = false;
    4086     }
    4087 }
    4088 
    4089 
    4090 /* If the desktop geometry is set automatically, this will update it. */
    4091 void VBoxConsoleView::doResizeDesktop (int)
    4092 {
    4093     calculateDesktopGeometry();
    4094 }
    4095 
    4096 /**
    4097  * Store the current size of the console (i.e. the viewport to the guest).
    4098  * This has two purposes.  One is to suppress unwanted resize events for
    4099  * which the new size is the same as the stored size.  The other is to expand
    4100  * the maximum size to which we will let the guest resize itself.  It makes
    4101  * no sense to forbid guest resizes which are less than the current resolution
    4102  * anyway.
    4103  *
    4104  * @param aWidth  width of the resolution hint
    4105  * @param aHeight height of the resolution hint
    4106  */
    4107 void VBoxConsoleView::storeConsoleSize (int aWidth, int aHeight)
    4108 {
    4109     LogFlowThisFunc (("aWidth=%d, aHeight=%d\n", aWidth, aHeight));
    4110     mStoredConsoleSize = QRect (0, 0, aWidth, aHeight);
    4111 }
    4112 
    4113 /**
    4114  * Do initial setup of desktop geometry restrictions on the guest framebuffer.
    4115  * These determine the maximum size the guest framebuffer can take on.
    4116  *
    4117  * @note a hint from the host will always override these restrictions.
    4118  *
    4119  * @param aGeo    Fixed -     the guest has a fixed maximum framebuffer size
    4120  *                Automatic - we calculate the maximum size ourselves.  The
    4121  *                            calculations will not actually be done until
    4122  *                            @a calculateDesktopGeometry is called, since
    4123  *                            we don't initially have the information needed.
    4124  *                Any -       any size is allowed
    4125  * @param aWidth  The maximum width for the guest screen or zero for no change
    4126  *                (only used for fixed geometry)
    4127  * @param aHeight The maximum height for the guest screen or zero for no change
    4128  *                (only used for fixed geometry)
    4129  */
    4130 void VBoxConsoleView::setDesktopGeometry (DesktopGeo aGeo, int aWidth, int aHeight)
    4131 {
    4132     LogFlowThisFunc (("aGeo=%s, aWidth=%d, aHeight=%d\n",
    4133                       (aGeo == DesktopGeo_Fixed ? "Fixed" :
    4134                        aGeo == DesktopGeo_Automatic ? "Automatic" :
    4135                        aGeo == DesktopGeo_Any ? "Any" : "Invalid"),
    4136                       aWidth, aHeight));
    4137     switch (aGeo)
    4138     {
    4139         case DesktopGeo_Fixed:
    4140             mDesktopGeo = DesktopGeo_Fixed;
    4141             if (aWidth != 0 && aHeight != 0)
    4142                 mDesktopGeometry = QRect (0, 0, aWidth, aHeight);
    4143             else
    4144                 mDesktopGeometry = QRect (0, 0, 0, 0);
    4145             storeConsoleSize (0, 0);
    4146             break;
    4147         case DesktopGeo_Automatic:
    4148             mDesktopGeo = DesktopGeo_Automatic;
    4149             mDesktopGeometry = QRect (0, 0, 0, 0);
    4150             storeConsoleSize (0, 0);
    4151             break;
    4152         case DesktopGeo_Any:
    4153             mDesktopGeo = DesktopGeo_Any;
    4154             mDesktopGeometry = QRect (0, 0, 0, 0);
    4155             break;
    4156         default:
    4157             AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo));
    4158             mDesktopGeo = DesktopGeo_Invalid;
    4159     }
    4160 }
    4161 
    4162 
    4163 /**
    4164  * If we are in automatic mode, the geometry restrictions will be recalculated.
    4165  * This is needed in particular on the first widget resize, as we can't
    4166  * calculate them correctly before that.
    4167  *
    4168  * @note a hint from the host will always override these restrictions.
    4169  * @note we can't do calculations on the fly when they are needed, because
    4170  *       they require querying the X server on X11 hosts and this must be done
    4171  *       from within the GUI thread, due to the single threadedness of Xlib.
    4172  */
    4173 void VBoxConsoleView::calculateDesktopGeometry()
    4174 {
    4175     LogFlowThisFunc (("Entering\n"));
    4176     /* This method should not get called until we have initially set up the */
    4177     Assert ((mDesktopGeo != DesktopGeo_Invalid));
    4178     /* If we are not doing automatic geometry calculation then there is
    4179      * nothing to do. */
    4180     if (DesktopGeo_Automatic == mDesktopGeo)
    4181     {
    4182         /* Available geometry of the desktop.  If the desktop is a single
    4183          * screen, this will exclude space taken up by desktop taskbars
    4184          * and things, but this is unfortunately not true for the more
    4185          * complex case of a desktop spanning multiple screens. */
    4186         QRect desktop = availableGeometry();
    4187         /* The area taken up by the console window on the desktop,
    4188          * including window frame, title and menu bar and whatnot. */
    4189         QRect frame = mMainWnd->frameGeometry();
    4190         /* The area taken up by the console window, minus all
    4191          * decorations. */
    4192         QRect window = mMainWnd->centralWidget()->geometry();
    4193         /* To work out how big we can make the console window while still
    4194          * fitting on the desktop, we calculate desktop - frame + window.
    4195          * This works because the difference between frame and window
    4196          * (or at least its width and height) is a constant. */
    4197         mDesktopGeometry =
    4198             QRect (0, 0, desktop.width() - frame.width() + window.width(),
    4199                    desktop.height() - frame.height() + window.height());
    4200         LogFlowThisFunc (("Setting %d, %d\n", mDesktopGeometry.width(),
    4201                            mDesktopGeometry.height()));
    4202     }
    4203 }
    4204 
    4205 /**
    4206  *  Sets the minimum size restriction depending on the auto-resize feature
    4207  *  state and the current rendering mode.
    4208  *
    4209  *  Currently, the restriction is set only in SDL mode and only when the
    4210  *  auto-resize feature is inactive. We need to do that because we cannot
    4211  *  correctly draw in a scrolled window in SDL mode.
    4212  *
    4213  *  In all other modes, or when auto-resize is in force, this function does
    4214  *  nothing.
    4215  */
    4216 void VBoxConsoleView::maybeRestrictMinimumSize()
    4217 {
    4218     if (mode == VBoxDefs::SDLMode)
    4219     {
    4220         if (!mGuestSupportsGraphics || !mAutoresizeGuest)
    4221             setMinimumSize (sizeHint());
    4222         else
    4223             setMinimumSize (0, 0);
    4224     }
    4225 }
    4226 
    4227 QRect VBoxConsoleView::availableGeometry() const
    4228 {
    4229     return mMainWnd->isWindowFullScreen() ?
    4230            QApplication::desktop()->screenGeometry(this) :
    4231            QApplication::desktop()->availableGeometry(this);
    4232 }
    4233 
    4234 int VBoxConsoleView::contentsWidth() const
    4235 {
    4236     return mFrameBuf->width();
    4237 }
    4238 
    4239 int VBoxConsoleView::contentsHeight() const
    4240 {
    4241     return mFrameBuf->height();
    4242 }
    4243 
    4244 void VBoxConsoleView::updateSliders()
    4245 {
    4246     QSize p = viewport()->size();
    4247     QSize m = maximumViewportSize();
    4248 
    4249     QSize v = QSize (mFrameBuf->width(), mFrameBuf->height());
    4250     /* no scroll bars needed */
    4251     if (m.expandedTo(v) == m)
    4252         p = m;
    4253 
    4254     horizontalScrollBar()->setRange(0, v.width() - p.width());
    4255     verticalScrollBar()->setRange(0, v.height() - p.height());
    4256     horizontalScrollBar()->setPageStep(p.width());
    4257     verticalScrollBar()->setPageStep(p.height());
    4258 }
    4259 
    4260 void VBoxConsoleView::requestToResize (const QSize &aSize)
    4261 {
    4262     mIgnoreFrameBufferResize = true;
    4263     mNormalSize = aSize;
    4264 }
    4265 
    4266 #if defined(Q_WS_MAC)
    4267 
    4268 void VBoxConsoleView::updateDockIcon()
    4269 {
    4270     if (mDockIconEnabled)
    4271     {
    4272         if (!mPausedShot.isNull())
    4273         {
    4274             CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot);
    4275             /* Use the pause image as background */
    4276             mDockIconPreview->updateDockPreview (pauseImg);
    4277             CGImageRelease (pauseImg);
    4278         }
    4279         else
    4280         {
    4281 # if defined (VBOX_GUI_USE_QUARTZ2D)
    4282             if (mode == VBoxDefs::Quartz2DMode)
    4283             {
    4284                 /* If the render mode is Quartz2D we could use the CGImageRef
    4285                  * of the framebuffer for the dock icon creation. This saves
    4286                  * some conversion time. */
    4287                 mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef());
    4288             }
    4289             else
    4290 # endif
    4291                 /* In image mode we have to create the image ref out of the
    4292                  * framebuffer */
    4293                 mDockIconPreview->updateDockPreview (mFrameBuf);
    4294         }
    4295     }
    4296 }
    4297 
    4298 void VBoxConsoleView::updateDockOverlay()
    4299 {
    4300     /* Only to an update to the realtime preview if this is enabled by the user
    4301      * & we are in an state where the framebuffer is likely valid. Otherwise to
    4302      * the overlay stuff only. */
    4303     if (mDockIconEnabled &&
    4304         (mLastState == KMachineState_Running ||
    4305          mLastState == KMachineState_Paused ||
    4306          mLastState == KMachineState_Teleporting ||
    4307          mLastState == KMachineState_LiveSnapshotting ||
    4308          mLastState == KMachineState_Restoring ||
    4309          mLastState == KMachineState_TeleportingPausedVM ||
    4310          mLastState == KMachineState_TeleportingIn ||
    4311          mLastState == KMachineState_Saving))
    4312         updateDockIcon();
    4313     else
    4314         mDockIconPreview->updateDockOverlay();
    4315 }
    4316 
    4317 /**
    4318  * Wrapper for SetMouseCoalescingEnabled().
    4319  *
    4320  * Called by eventFilter() and darwinGrabKeyboardEvents().
    4321  *
    4322  * @param   aOn     Switch it on (true) or off (false).
    4323  */
    4324 void VBoxConsoleView::setMouseCoalescingEnabled (bool aOn)
    4325 {
    4326     /* Enable mouse event compression if we leave the VM view. This
    4327        is necessary for having smooth resizing of the VM/other
    4328        windows.
    4329        Disable mouse event compression if we enter the VM view. So
    4330        all mouse events are registered in the VM. Only do this if
    4331        the keyboard/mouse is grabbed (this is when we have a valid
    4332        event handler). */
    4333     if (aOn || mKeyboardGrabbed)
    4334         ::darwinSetMouseCoalescingEnabled (aOn);
    4335 }
    4336 
    4337 #endif /* Q_WS_MAC */
    4338 
     116#endif // !___UIConsole_h___
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp

    r26656 r26691  
    3131#include "UIFirstRunWzd.h"
    3232
     33#include "UISession.h"
    3334#include "UIActionsPool.h"
    3435#include "UIMachineLogicNormal.h"
     
    3637#include "UIMachineView.h"
    3738
    38 UIMachineLogicNormal::UIMachineLogicNormal(QObject *pParent, const CSession &session, UIActionsPool *pActionsPool)
    39     : UIMachineLogic(pParent, session, pActionsPool, UIVisualStateType_Normal)
    40 {
     39UIMachineLogicNormal::UIMachineLogicNormal(QObject *pParent, UISession *pSession, UIActionsPool *pActionsPool)
     40    : UIMachineLogic(pParent, pSession, pActionsPool, UIVisualStateType_Normal)
     41{
     42    /* Prepare console connections: */
     43    prepareConsoleConnections();
     44
    4145    /* Prepare action groups: */
    4246    prepareActionGroups();
     
    5357    /* Load common logic settings: */
    5458    loadLogicSettings();
    55 
    56     /* Update all the elements: */
    57     updateAppearanceOf(UIVisualElement_AllStuff);
    5859}
    5960
     
    8384}
    8485
    85 void UIMachineLogicNormal::updateAppearanceOf(int iElement)
    86 {
    87     /* Update parent-class elements: */
    88     UIMachineLogic::updateAppearanceOf(iElement);
     86void UIMachineLogicNormal::sltPrepareMouseIntegrationMenu()
     87{
     88    QMenu *menu = qobject_cast<QMenu*>(sender());
     89    AssertMsg(menu, ("This slot should be called only on Mouse Integration Menu show!\n"));
     90    menu->clear();
     91    menu->addAction(actionsPool()->action(UIActionIndex_Toggle_MouseIntegration));
    8992}
    9093
     
    99102    connect(actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu(), SIGNAL(aboutToShow()),
    100103            this, SLOT(sltPrepareSharedFoldersMenu()));
     104    connect(actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->menu(), SIGNAL(aboutToShow()),
     105            this, SLOT(sltPrepareMouseIntegrationMenu()));
    101106}
    102107
     
    120125    setMachineState(session().GetConsole().GetState());
    121126
    122     /* Notify user about mouse&keyboard auto-capturing: */
    123     if (vboxGlobal().settings().autoCapture())
    124         vboxProblem().remindAboutAutoCapture();
    125 
    126     bool saved = machineState() == KMachineState_Saved;
    127 
    128     CMachine machine = session().GetMachine();
    129     CConsole console = session().GetConsole();
    130 
    131     /* Shows first run wizard if necessary: */
    132     if (isFirstTimeStarted())
     127    bool bIsSaved = machineState() == KMachineState_Saved;
     128    bool bIsRunning = machineState() == KMachineState_Running ||
     129                      machineState() == KMachineState_Teleporting ||
     130                      machineState() == KMachineState_LiveSnapshotting;
     131    bool bIsRunningOrPaused = bIsRunning ||
     132                              machineState() == KMachineState_Paused;
     133
     134    /* If we are not started yet: */
     135    if (!bIsRunningOrPaused)
    133136    {
    134         UIFirstRunWzd wzd(machineWindowWrapper()->machineWindow(), machine);
    135         wzd.exec();
    136         machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
    137     }
    138 
    139 
    140     // TODO: Do not start VM yet!
    141     return;
    142 
    143 
    144     /* Start VM: */
    145     CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ?
    146                          console.PowerUpPaused() : console.PowerUp();
    147     /* Check for an immediate failure */
    148     if (!console.isOk())
    149     {
    150         vboxProblem().cannotStartMachine(console);
    151         machineWindowWrapper()->machineWindow()->close();
    152         return;
    153     }
    154 
    155     /* Disable auto closure because we want to have a chance to show the error dialog on startup failure: */
    156     setPreventAutoClose(true);
    157 
    158     /* Show "Starting/Restoring" progress dialog: */
    159     if (saved)
    160         vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineView(), 0);
    161     else
    162         vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineView());
    163 
    164     /* Check for an progress failure */
    165     if (progress.GetResultCode() != 0)
    166     {
    167         vboxProblem().cannotStartMachine(progress);
    168         machineWindowWrapper()->machineWindow()->close();
    169         return;
    170     }
    171 
    172     /* Enable auto closure again: */
    173     setPreventAutoClose(false);
    174 
    175     /* Check if we missed a really quick termination after successful startup, and process it if we did: */
    176     if (machineState() == KMachineState_PoweredOff || machineState() == KMachineState_Saved ||
    177         machineState() == KMachineState_Teleported || machineState() == KMachineState_Aborted)
    178     {
    179         machineWindowWrapper()->machineWindow()->close();
    180         return;
    181     }
     137        /* Get current machine/console: */
     138        CMachine machine = session().GetMachine();
     139        CConsole console = session().GetConsole();
     140
     141        /* Notify user about mouse&keyboard auto-capturing: */
     142        if (vboxGlobal().settings().autoCapture())
     143            vboxProblem().remindAboutAutoCapture();
     144
     145        /* Shows first run wizard if necessary: */
     146        if (isFirstTimeStarted())
     147        {
     148            UIFirstRunWzd wzd(machineWindowWrapper()->machineWindow(), machine);
     149            wzd.exec();
     150        }
     151
     152        /* Start VM: */
     153        CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ?
     154                             console.PowerUpPaused() : console.PowerUp();
     155        /* Check for an immediate failure */
     156        if (!console.isOk())
     157        {
     158            vboxProblem().cannotStartMachine(console);
     159            machineWindowWrapper()->machineWindow()->close();
     160            return;
     161        }
     162
     163        /* Disable auto closure because we want to have a chance to show the error dialog on startup failure: */
     164        setPreventAutoClose(true);
     165
     166        /* Show "Starting/Restoring" progress dialog: */
     167        if (bIsSaved)
     168            vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineWindow(), 0);
     169        else
     170            vboxProblem().showModalProgressDialog(progress, machine.GetName(), machineWindowWrapper()->machineWindow());
     171
     172        /* Check for an progress failure */
     173        if (progress.GetResultCode() != 0)
     174        {
     175            vboxProblem().cannotStartMachine(progress);
     176            machineWindowWrapper()->machineWindow()->close();
     177            return;
     178        }
     179
     180        /* Process pending events: */
     181        qApp->processEvents();
     182
     183        /* Enable auto closure again: */
     184        setPreventAutoClose(false);
     185
     186        /* Check if we missed a really quick termination after successful startup, and process it if we did: */
     187        if (machineState() == KMachineState_PoweredOff || machineState() == KMachineState_Saved ||
     188            machineState() == KMachineState_Teleported || machineState() == KMachineState_Aborted)
     189        {
     190            machineWindowWrapper()->machineWindow()->close();
     191            return;
     192        }
    182193
    183194#if 0 // TODO: Rework debugger logic!
    184195# ifdef VBOX_WITH_DEBUGGER_GUI
    185     /* Open the debugger in "full screen" mode requested by the user. */
    186     else if (vboxGlobal().isDebuggerAutoShowEnabled())
    187     {
    188         /* console in upper left corner of the desktop. */
    189         QRect rct (0, 0, 0, 0);
    190         QDesktopWidget *desktop = QApplication::desktop();
    191         if (desktop)
    192             rct = desktop->availableGeometry(pos());
    193         move (QPoint (rct.x(), rct.y()));
    194 
    195         if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled())
    196             sltShowDebugStatistics();
    197         if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled())
    198             sltShowDebugCommandLine();
    199 
    200         if (!vboxGlobal().isStartPausedEnabled())
    201             machineWindowWrapper()->machineView()->pause (false);
    202     }
     196        /* Open the debugger in "full screen" mode requested by the user. */
     197        else if (vboxGlobal().isDebuggerAutoShowEnabled())
     198        {
     199            /* console in upper left corner of the desktop. */
     200            QRect rct (0, 0, 0, 0);
     201            QDesktopWidget *desktop = QApplication::desktop();
     202            if (desktop)
     203                rct = desktop->availableGeometry(pos());
     204            move (QPoint (rct.x(), rct.y()));
     205
     206            if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled())
     207                sltShowDebugStatistics();
     208            if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled())
     209                sltShowDebugCommandLine();
     210
     211            if (!vboxGlobal().isStartPausedEnabled())
     212                machineWindowWrapper()->machineView()->pause (false);
     213        }
    203214# endif
    204215#endif
    205216
    206     setOpenViewFinished(true);
    207 
    208217#ifdef VBOX_WITH_UPDATE_REQUEST
    209     /* Check for updates if necessary: */
    210     vboxGlobal().showUpdateDialog(false /* aForce */);
     218        /* Check for updates if necessary: */
     219        vboxGlobal().showUpdateDialog(false /* aForce */);
    211220#endif
     221    }
    212222
    213223    /* Configure view connections: */
    214224    if (machineWindowWrapper()->machineView())
    215225    {
    216         connect(machineWindowWrapper()->machineView(), SIGNAL(machineStateChanged(KMachineState)),
    217                 this, SLOT(sltUpdateMachineState(KMachineState)));
    218         connect(machineWindowWrapper()->machineView(), SIGNAL(additionsStateChanged(const QString&, bool, bool, bool)),
    219                 this, SLOT(sltUpdateAdditionsState(const QString &, bool, bool, bool)));
    220226        connect(machineWindowWrapper()->machineView(), SIGNAL(mouseStateChanged(int)),
    221                 this, SLOT(sltUpdateMouseState(int)));
     227                this, SLOT(sltMouseStateChanged(int)));
    222228    }
     229
     230    /* Set what view opened: */
     231    setOpenViewFinished(true);
    223232}
    224233
     
    232241    UIMachineWindow::destroy(m_pMachineWindowContainer);
    233242    m_pMachineWindowContainer = 0;
    234 
    235     // TODO: What should be done on window destruction?
    236     //machineWindowWrapper()->machineView()->detach();
    237     //m_session.Close();
    238     //m_session.detach();
    239 }
     243}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.h

    r26656 r26691  
    3636protected:
    3737
    38     /* Normal machine logic constructor: */
     38    /* Normal machine logic constructor/destructor: */
    3939    UIMachineLogicNormal(QObject *pParent,
    40                          const CSession &session,
     40                         UISession *pSession,
    4141                         UIActionsPool *pActionsPool);
    42     /* Normal machine logic destructor: */
    4342    virtual ~UIMachineLogicNormal();
    4443
    4544private slots:
    4645
    47     /* Status-bar LED funtionality: */
     46    /* Windowed mode funtionality: */
    4847    void sltPrepareNetworkAdaptersMenu();
    4948    void sltPrepareSharedFoldersMenu();
     49    void sltPrepareMouseIntegrationMenu();
    5050
    5151private:
    52 
    53     /* Update routines: */
    54     void updateAppearanceOf(int);
    5552
    5653    /* Prepare helpers: */
     
    6461    //void cleanupActionConnections();
    6562
     63    /* Friend classes: */
    6664    friend class UIMachineLogic;
    6765};
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp

    r26637 r26691  
    4545                   )
    4646{
    47     /* Connect actions to view: */
    48     connect(machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize),
    49             SIGNAL(toggled(bool)), this, SLOT(sltToggleGuestAutoresize(bool)));
    50 
    5147    /* Connect view to handlers */
    5248    connect(this, SIGNAL(additionsStateChanged(const QString&, bool, bool, bool)),
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp

    r26656 r26691  
    3232#include "VBoxVMInformationDlg.h"
    3333
     34#include "UISession.h"
    3435#include "UIActionsPool.h"
    3536#include "UIIndicatorsPool.h"
     
    5455    prepareWindowIcon();
    5556
     57    /* Prepare console connections: */
     58    prepareConsoleConnections();
     59
    5660    /* Prepare menu: */
    5761    prepareMenu();
     
    9094void UIMachineWindowNormal::sltTryClose()
    9195{
    92     // TODO: Could be moved to parent class?
    93 
    94     /* First close any open modal & popup widgets.
    95      * Use a single shot with timeout 0 to allow the widgets to cleany close and test then again.
    96      * If all open widgets are closed destroy ourself: */
    97     QWidget *widget = QApplication::activeModalWidget() ?
    98                       QApplication::activeModalWidget() :
    99                       QApplication::activePopupWidget() ?
    100                       QApplication::activePopupWidget() : 0;
    101     if (widget)
    102     {
    103         widget->close();
    104         QTimer::singleShot(0, this, SLOT(sltTryClose()));
    105     }
    106     else
    107         close();
     96    UIMachineWindow::sltTryClose();
     97}
     98
     99void UIMachineWindowNormal::sltMachineStateChanged(KMachineState machineState)
     100{
     101    UIMachineWindow::sltMachineStateChanged(machineState);
     102}
     103
     104void UIMachineWindowNormal::sltMediumChange(const CMediumAttachment &attachment)
     105{
     106    KDeviceType type = attachment.GetType();
     107    Assert(type == KDeviceType_DVD || type == KDeviceType_Floppy);
     108    updateAppearanceOf(type == KDeviceType_DVD ? UIVisualElement_CDStuff :
     109                       type == KDeviceType_Floppy ? UIVisualElement_FDStuff :
     110                       UIVisualElement_AllStuff);
     111}
     112
     113void UIMachineWindowNormal::sltUSBControllerChange()
     114{
     115    updateAppearanceOf(UIVisualElement_USBStuff);
     116}
     117
     118void UIMachineWindowNormal::sltUSBDeviceStateChange()
     119{
     120    updateAppearanceOf(UIVisualElement_USBStuff);
     121}
     122
     123void UIMachineWindowNormal::sltNetworkAdapterChange()
     124{
     125    updateAppearanceOf(UIVisualElement_NetworkStuff);
     126}
     127
     128void UIMachineWindowNormal::sltSharedFolderChange()
     129{
     130    updateAppearanceOf(UIVisualElement_SharedFolderStuff);
    108131}
    109132
     
    132155    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_InformationDialog));
    133156    menu->addSeparator();
     157    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Pause));
    134158    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Reset));
    135     menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_Pause));
    136159    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_Shutdown));
    137160#ifndef Q_WS_MAC
     
    152175    menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu());
    153176    menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices)->menu());
     177    menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu());
    154178    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog));
    155179    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Simple_SharedFoldersDialog));
    156     menu->addMenu(machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu());
    157180    menu->addSeparator();
    158181    menu->addAction(machineLogic()->actionsPool()->action(UIActionIndex_Toggle_VRDP));
     
    179202void UIMachineWindowNormal::sltUpdateIndicators()
    180203{
    181     CConsole console = machineLogic()->session().GetConsole();
     204    CConsole console = session().GetConsole();
    182205    QIStateIndicator *pStateIndicator = 0;
    183206
     
    196219            pStateIndicator->setState(state);
    197220    }
     221    pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices);
     222    if (pStateIndicator->state() != KDeviceActivity_Null)
     223    {
     224        int state = console.GetDeviceActivity(KDeviceType_USB);
     225        if (pStateIndicator->state() != state)
     226            pStateIndicator->setState(state);
     227    }
    198228    pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters);
    199229    if (pStateIndicator->state() != KDeviceActivity_Null)
     
    203233            pStateIndicator->setState(state);
    204234    }
    205     pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices);
    206     if (pStateIndicator->state() != KDeviceActivity_Null)
    207     {
    208         int state = console.GetDeviceActivity(KDeviceType_USB);
    209         if (pStateIndicator->state() != state)
    210             pStateIndicator->setState(state);
    211     }
    212235    pStateIndicator = indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders);
    213236    if (pStateIndicator->state() != KDeviceActivity_Null)
     
    223246    if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks))
    224247    {
    225         if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu()->isEnabled())
     248        if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->isEnabled())
    226249            machineLogic()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices)->menu()->exec(pEvent->globalPos());
    227250    }
     251    else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_USBDevices))
     252    {
     253        if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->isEnabled())
     254            machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->exec(pEvent->globalPos());
     255    }
    228256    else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters))
    229257    {
    230         if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->menu()->isEnabled())
     258        if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->isEnabled())
    231259            machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->menu()->exec(pEvent->globalPos());
    232260    }
    233     else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_USBDevices))
    234     {
    235         if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->isEnabled())
    236             machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->exec(pEvent->globalPos());
    237     }
    238261    else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders))
    239262    {
    240         if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->isEnabled())
     263        if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->isEnabled())
    241264            machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->exec(pEvent->globalPos());
    242265    }
    243266    else if (pIndicator == indicatorsPool()->indicator(UIIndicatorIndex_Mouse))
    244267    {
    245         if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->menu()->isEnabled())
     268        if (machineLogic()->actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->isEnabled())
    246269            machineLogic()->actionsPool()->action(UIActionIndex_Menu_MouseIntegration)->menu()->exec(pEvent->globalPos());
    247270    }
     
    251274{
    252275    m_pNameHostkey->setText(QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey()));
    253 }
    254 
    255 void UIMachineWindowNormal::sltUpdateMediaDriveState(VBoxDefs::MediumType type)
    256 {
    257     Assert(type == VBoxDefs::MediumType_DVD || type == VBoxDefs::MediumType_Floppy);
    258     updateAppearanceOf(type == VBoxDefs::MediumType_DVD ? UIVisualElement_CDStuff :
    259                        type == VBoxDefs::MediumType_Floppy ? UIVisualElement_FDStuff :
    260                        UIVisualElement_AllStuff);
    261 }
    262 
    263 void UIMachineWindowNormal::sltUpdateNetworkAdaptersState()
    264 {
    265     updateAppearanceOf(UIVisualElement_NetworkStuff);
    266 }
    267 
    268 void UIMachineWindowNormal::sltUpdateUsbState()
    269 {
    270     updateAppearanceOf(UIVisualElement_USBStuff);
    271 }
    272 
    273 void UIMachineWindowNormal::sltUpdateSharedFoldersState()
    274 {
    275     updateAppearanceOf(UIVisualElement_SharedFolderStuff);
    276276}
    277277
     
    305305
    306306    /* Update that machine window: */
    307     CMachine machine = machineLogic()->session().GetMachine();
    308     CConsole console = machineLogic()->session().GetConsole();
    309     bool bIsStrictRunningOrPaused = machineLogic()->machineState() == KMachineState_Running ||
    310                                     machineLogic()->machineState() == KMachineState_Paused;
     307    CMachine machine = session().GetMachine();
     308    CConsole console = session().GetConsole();
    311309
    312310    if (iElement & UIVisualElement_HDStuff)
     
    376374        indicatorsPool()->indicator(UIIndicatorIndex_OpticalDisks)->setState(bAttachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null);
    377375    }
    378     if (iElement & UIVisualElement_NetworkStuff)
    379     {
    380         ulong uMaxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
    381         ulong uCount = 0;
    382         for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot)
    383             if (machine.GetNetworkAdapter(uSlot).GetEnabled())
    384                 ++ uCount;
    385         indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setState(uCount > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null);
    386 
    387         machineLogic()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)->setEnabled(bIsStrictRunningOrPaused && uCount > 0);
    388         machineLogic()->actionsPool()->action(UIActionIndex_Menu_NetworkAdapters)->setEnabled(bIsStrictRunningOrPaused && uCount > 0);
    389 
    390         QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity of the "
    391                                 "network interfaces:</nobr>%1</p>", "Network adapters tooltip");
    392         QString strFullData;
    393 
    394         for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot)
    395         {
    396             CNetworkAdapter adapter = machine.GetNetworkAdapter(uSlot);
    397             if (adapter.GetEnabled())
    398                 strFullData += tr("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip")
    399                     .arg(uSlot + 1)
    400                     .arg(vboxGlobal().toString(adapter.GetAttachmentType()))
    401                     .arg(adapter.GetCableConnected() ?
    402                           tr("connected", "Network adapters tooltip") :
    403                           tr("disconnected", "Network adapters tooltip"));
    404         }
    405 
    406         if (strFullData.isNull())
    407             strFullData = tr("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip");
    408 
    409         indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setToolTip(strToolTip.arg(strFullData));
    410     }
    411376    if (iElement & UIVisualElement_USBStuff)
    412377    {
     
    420385            if (!usbctl.isNull() && usbctl.GetEnabled())
    421386            {
    422                 machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(bIsStrictRunningOrPaused);
    423 
    424387                CUSBDeviceVector devsvec = console.GetUSBDevices();
    425388                for (int i = 0; i < devsvec.size(); ++ i)
     
    433396            else
    434397            {
    435                 machineLogic()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->menu()->setEnabled(false);
    436398                strFullData = tr("<br><nobr><b>USB Controller is disabled</b></nobr>", "USB device tooltip");
    437399            }
     
    440402        }
    441403    }
    442     if (iElement & UIVisualElement_VRDPStuff)
    443     {
    444         CVRDPServer vrdpsrv = machineLogic()->session().GetMachine().GetVRDPServer();
    445         if (!vrdpsrv.isNull())
    446         {
    447             /* Update menu&status icon state */
    448             bool isVRDPEnabled = vrdpsrv.GetEnabled();
    449             machineLogic()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setChecked(isVRDPEnabled);
    450         }
     404    if (iElement & UIVisualElement_NetworkStuff)
     405    {
     406        ulong uMaxCount = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
     407        ulong uCount = 0;
     408        for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot)
     409            if (machine.GetNetworkAdapter(uSlot).GetEnabled())
     410                ++ uCount;
     411        indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setState(uCount > 0 ? KDeviceActivity_Idle : KDeviceActivity_Null);
     412
     413        QString strToolTip = tr("<p style='white-space:pre'><nobr>Indicates the activity of the "
     414                                "network interfaces:</nobr>%1</p>", "Network adapters tooltip");
     415        QString strFullData;
     416
     417        for (ulong uSlot = 0; uSlot < uMaxCount; ++ uSlot)
     418        {
     419            CNetworkAdapter adapter = machine.GetNetworkAdapter(uSlot);
     420            if (adapter.GetEnabled())
     421                strFullData += tr("<br><nobr><b>Adapter %1 (%2)</b>: cable %3</nobr>", "Network adapters tooltip")
     422                    .arg(uSlot + 1)
     423                    .arg(vboxGlobal().toString(adapter.GetAttachmentType()))
     424                    .arg(adapter.GetCableConnected() ?
     425                          tr("connected", "Network adapters tooltip") :
     426                          tr("disconnected", "Network adapters tooltip"));
     427        }
     428
     429        if (strFullData.isNull())
     430            strFullData = tr("<br><nobr><b>All network adapters are disabled</b></nobr>", "Network adapters tooltip");
     431
     432        indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters)->setToolTip(strToolTip.arg(strFullData));
    451433    }
    452434    if (iElement & UIVisualElement_SharedFolderStuff)
     
    457439        QString strFullData;
    458440        QMap<QString, QString> sfs;
    459 
    460         machineLogic()->actionsPool()->action(UIActionIndex_Menu_SharedFolders)->menu()->setEnabled(true);
    461441
    462442        /* Permanent folders */
     
    493473
    494474        indicatorsPool()->indicator(UIIndicatorIndex_SharedFolders)->setToolTip(strToolTip.arg(strFullData));
     475    }
     476    if (iElement & UIVisualElement_VRDPStuff)
     477    {
     478        CVRDPServer vrdpsrv = session().GetMachine().GetVRDPServer();
     479        if (!vrdpsrv.isNull())
     480        {
     481            /* Update menu&status icon state */
     482            bool isVRDPEnabled = vrdpsrv.GetEnabled();
     483            machineLogic()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setChecked(isVRDPEnabled);
     484        }
    495485    }
    496486    if (iElement & UIVisualElement_VirtualizationStuff)
     
    582572#endif
    583573
     574void UIMachineWindowNormal::prepareConsoleConnections()
     575{
     576    /* Parent class connections: */
     577    UIMachineWindow::prepareConsoleConnections();
     578    /* Other console connections: */
     579    connect(machineLogic()->uisession(), SIGNAL(sigMediumChange(const CMediumAttachment &)),
     580            this, SLOT(sltMediumChange(const CMediumAttachment &)));
     581    connect(machineLogic()->uisession(), SIGNAL(sigUSBControllerChange()),
     582            this, SLOT(sltUSBControllerChange()));
     583    connect(machineLogic()->uisession(), SIGNAL(sigUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)),
     584            this, SLOT(sltUSBDeviceStateChange()));
     585    connect(machineLogic()->uisession(), SIGNAL(sigNetworkAdapterChange(const CNetworkAdapter &)),
     586            this, SLOT(sltNetworkAdapterChange()));
     587    connect(machineLogic()->uisession(), SIGNAL(sigSharedFolderChange()),
     588            this, SLOT(sltSharedFolderChange()));
     589}
     590
    584591void UIMachineWindowNormal::prepareMenu()
    585592{
     
    622629            this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*)));
    623630
     631    /* USB Devices: */
     632    QIStateIndicator *pLedUSBDevices = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices);
     633    pIndicatorBoxHLayout->addWidget(pLedUSBDevices);
     634    connect(pLedUSBDevices, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)),
     635            this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*)));
     636
    624637    /* Network Adapters: */
    625638    QIStateIndicator *pLedNetworkAdapters = indicatorsPool()->indicator(UIIndicatorIndex_NetworkAdapters);
    626639    pIndicatorBoxHLayout->addWidget(pLedNetworkAdapters);
    627640    connect(pLedNetworkAdapters, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)),
    628             this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*)));
    629 
    630     /* USB Devices: */
    631     QIStateIndicator *pLedUSBDevices = indicatorsPool()->indicator(UIIndicatorIndex_USBDevices);
    632     pIndicatorBoxHLayout->addWidget(pLedUSBDevices);
    633     connect(pLedUSBDevices, SIGNAL(contextMenuRequested(QIStateIndicator*, QContextMenuEvent*)),
    634641            this, SLOT(sltShowIndicatorsContextMenu(QIStateIndicator*, QContextMenuEvent*)));
    635642
     
    689696    return; // TODO: Do not create view for now!
    690697
    691     CMachine machine = machineLogic()->session().GetMachine();
     698    CMachine machine = session().GetMachine();
    692699
    693700#ifdef VBOX_WITH_VIDEOHWACCEL
     
    707714    connect(machineView(), SIGNAL(keyboardStateChanged(int)),
    708715            indicatorsPool()->indicator(UIIndicatorIndex_Hostkey), SLOT(setState(int)));
    709     // TODO: Update these 5 indicators through indicators pool!
    710     connect(machineView(), SIGNAL(mediaDriveChanged(VBoxDefs::MediumType)),
    711             this, SLOT(sltUpdateMediaDriveState(VBoxDefs::MediumType)));
    712     connect(machineView(), SIGNAL(networkStateChange()), this, SLOT(sltUpdateNetworkAdaptersState()));
    713     connect(machineView(), SIGNAL(usbStateChange()), this, SLOT(sltUpdateUsbState()));
    714     connect(machineView(), SIGNAL(sharedFoldersChanged()), this, SLOT(sltUpdateSharedFoldersState()));
    715716    connect(machineView(), SIGNAL(mouseStateChanged(int)), this, SLOT(sltUpdateMouseState(int)));
    716717}
     
    722723
    723724    /* Load this class settings: */
    724     CMachine machine = machineLogic()->session().GetMachine();
     725    CMachine machine = session().GetMachine();
    725726
    726727    /* Extra-data settings */
     
    796797void UIMachineWindowNormal::saveWindowSettings()
    797798{
    798     CMachine machine = machineLogic()->session().GetMachine();
     799    CMachine machine = session().GetMachine();
    799800
    800801    /* Extra-data settings */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.h

    r26637 r26691  
    5353    void sltTryClose();
    5454
     55    void sltMachineStateChanged(KMachineState machineState);
     56    void sltMediumChange(const CMediumAttachment &attachment);
     57    void sltUSBControllerChange();
     58    void sltUSBDeviceStateChange();
     59    void sltNetworkAdapterChange();
     60    void sltSharedFolderChange();
     61
    5562    void sltPrepareMenuMachine();
    5663    void sltPrepareMenuDevices();
     
    6471    void sltProcessGlobalSettingChange(const char *aPublicName, const char *aName);
    6572
    66     void sltUpdateMediaDriveState(VBoxDefs::MediumType type);
    67     void sltUpdateNetworkAdaptersState();
    68     void sltUpdateUsbState();
    69     void sltUpdateSharedFoldersState();
    7073    void sltUpdateMouseState(int iState);
    7174
     
    8891
    8992    /* Prepare helpers: */
     93    void prepareConsoleConnections();
    9094    void prepareMenu();
    9195    void prepareStatusBar();
     
    100104    void cleanupStatusBar();
    101105    //void cleanupMenu();
     106    void cleanupConsoleConnections();
    102107
    103108    /* Indicators pool: */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette