VirtualBox

Changeset 26754 in vbox for trunk


Ignore:
Timestamp:
Feb 24, 2010 4:34:48 PM (15 years ago)
Author:
vboxsync
Message:

Fe/Qt4: New running VM core: cumulative patch, restoring some of mouse/keyboard processing.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/runtime
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp

    r26709 r26754  
    403403    connect(uisession(), SIGNAL(sigStateChange(KMachineState)), this, SLOT(sltMachineStateChanged(KMachineState)));
    404404    connect(uisession(), SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged()));
     405    connect(uisession(), SIGNAL(sigUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)),
     406            this, SLOT(sltUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)));
     407    connect(uisession(), SIGNAL(sigRuntimeError(bool, const QString &, const QString &)),
     408            this, SLOT(sltRuntimeError(bool, const QString &, const QString &)));
    405409}
    406410
     
    800804}
    801805
     806void UIMachineLogic::sltUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error)
     807{
     808    bool success = error.isNull();
     809
     810    if (!success)
     811    {
     812        if (bIsAttached)
     813            vboxProblem().cannotAttachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
     814        else
     815            vboxProblem().cannotDetachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
     816    }
     817}
     818
     819void UIMachineLogic::sltRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage)
     820{
     821    vboxProblem().showRuntimeError(session().GetConsole(), bIsFatal, strErrorId, strMessage);
     822}
     823
    802824void UIMachineLogic::sltToggleGuestAutoresize(bool /* bEnabled */)
    803825{
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h

    r26709 r26754  
    7777
    7878    /* Cleanup helpers: */
    79     void saveLogicSettings();
    80     //void cleanupRequiredFeatures();
    81     //void cleanupActionConnections();
    82     //void cleanupActionGroups();
    83     //void cleanupConsoleConnections();
     79    virtual void saveLogicSettings();
     80    //virtual void cleanupRequiredFeatures();
     81    //virtual void cleanupActionConnections();
     82    //virtual void cleanupActionGroups();
     83    //virtual void cleanupConsoleConnections();
    8484
    8585    /* Protected getters: */
     
    105105    void sltMachineStateChanged(KMachineState newMachineState);
    106106    void sltAdditionsStateChanged();
     107    void sltUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error);
     108    void sltRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage);
    107109
    108110    /* "Machine" menu funtionality */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r26730 r26754  
    119119};
    120120
     121enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 };
     122enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 };
     123
    121124UIMachineView* UIMachineView::create(  UIMachineWindow *pMachineWindow
    122125                                     , VBoxDefs::RenderMode renderMode
     
    197200                            )
    198201    : QAbstractScrollArea(pMachineWindow->machineWindow())
    199     /* Protected members: */
    200     , mode(renderMode)
    201     , m_bIsGuestSupportsGraphics(false)
    202202    /* Private members: */
    203203    , m_pMachineWindow(pMachineWindow)
    204204    , m_console(pMachineWindow->machineLogic()->uisession()->session().GetConsole())
     205    , m_mode(renderMode)
    205206    , m_globalSettings(vboxGlobal().settings())
     207    , m_machineState(KMachineState_Null)
     208    , m_pFrameBuffer(0)
     209#if defined(Q_WS_WIN)
     210    , m_alphaCursor(0)
     211#endif
    206212    , m_iLastMouseWheelDelta(0)
    207     , muNumLockAdaptionCnt(2)
    208     , muCapsLockAdaptionCnt(2)
     213    , m_uNumLockAdaptionCnt(2)
     214    , m_uCapsLockAdaptionCnt(2)
    209215    , m_bIsAutoCaptureDisabled(false)
    210216    , m_bIsKeyboardCaptured(false)
     
    214220    , m_bIsHostkeyPressed(false)
    215221    , m_bIsHostkeyAlone (false)
     222    , m_bIsGuestSupportsGraphics(false)
    216223    , m_bIsMachineWindowResizeIgnored(true)
    217224    , m_bIsFrameBufferResizeIgnored(false)
    218225    , m_bIsGuestResizeIgnored(false)
     226    , m_numLock(false)
     227    , m_scrollLock(false)
     228    , m_capsLock(false)
     229    , m_fPassCAD (false)
     230    , m_fHideHostPointer(true)
     231#ifdef VBOX_WITH_VIDEOHWACCEL
     232    , m_fAccelerate2DVideo(bAccelerate2DVideo)
     233#endif
     234#if 0 // TODO: Do we need this?
    219235    , mDoResize(false)
    220     , mNumLock(false)
    221     , mScrollLock(false)
    222     , mCapsLock(false)
    223 #ifdef VBOX_WITH_VIDEOHWACCEL
    224     , mAccelerate2DVideo(bAccelerate2DVideo)
    225 #endif
    226 #if defined(Q_WS_WIN)
    227     , mAlphaCursor (NULL)
    228236#endif
    229237#if defined(Q_WS_MAC)
    230238# ifndef QT_MAC_USE_COCOA
    231     , mDarwinEventHandlerRef (NULL)
     239    , m_darwinEventHandlerRef(NULL)
    232240# endif /* !QT_MAC_USE_COCOA */
    233     , mDarwinKeyModifiers (0)
    234     , mKeyboardGrabbed (false)
     241    , m_darwinKeyModifiers (0)
     242    , m_fKeyboardGrabbed (false)
    235243    , mDockIconEnabled (true)
    236244#endif
    237     , mDesktopGeo (DesktopGeo_Invalid)
    238     , mPassCAD (false)
     245    , m_desktopGeometryType(DesktopGeo_Invalid)
    239246      /* Don't show a hardware pointer until we have one to show */
    240     , mHideHostPointer (true)
    241247{
    242248}
     
    252258    /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done
    253259     *             by DevVGA if provoked before power on. */
    254     QSize fb(mFrameBuf->width(), mFrameBuf->height());
     260    QSize fb(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    255261    if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled()))
    256262        fb = QSize(640, 480);
    257263    return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2);
    258264#else
    259     return QSize(mFrameBuf->width() + frameWidth() * 2, mFrameBuf->height() + frameWidth() * 2);
     265    return QSize(m_pFrameBuffer->width() + frameWidth() * 2, m_pFrameBuffer->height() + frameWidth() * 2);
    260266#endif
    261267}
     
    273279int UIMachineView::contentsWidth() const
    274280{
    275     return mFrameBuf->width();
     281    return m_pFrameBuffer->width();
    276282}
    277283
    278284int UIMachineView::contentsHeight() const
    279285{
    280     return mFrameBuf->height();
     286    return m_pFrameBuffer->height();
    281287}
    282288
     
    291297}
    292298
     299QRect UIMachineView::desktopGeometry() const
     300{
     301    QRect geometry;
     302    switch (m_desktopGeometryType)
     303    {
     304        case DesktopGeo_Fixed:
     305        case DesktopGeo_Automatic:
     306            geometry = QRect(0, 0,
     307                            qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
     308                            qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
     309            break;
     310        case DesktopGeo_Any:
     311            geometry = QRect(0, 0, 0, 0);
     312            break;
     313        default:
     314            AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
     315    }
     316    return geometry;
     317}
     318
    293319void UIMachineView::calculateDesktopGeometry()
    294320{
    295     /* This method should not get called until we have initially set up the mDesktopGeo: */
    296     Assert((mDesktopGeo != DesktopGeo_Invalid));
     321    /* This method should not get called until we have initially set up the m_desktopGeometryType: */
     322    Assert((m_desktopGeometryType != DesktopGeo_Invalid));
    297323    /* If we are not doing automatic geometry calculation then there is nothing to do: */
    298     if (DesktopGeo_Automatic == mDesktopGeo)
     324    if (DesktopGeo_Automatic == m_desktopGeometryType)
    299325    {
    300326        /* Available geometry of the desktop.  If the desktop is a single
     
    303329         * complex case of a desktop spanning multiple screens: */
    304330        QRect desktop = availableGeometry();
    305         /* The area taken up by the console window on the desktop,
    306          * including window frame, title and menu bar and whatnot. */
     331        /* The area taken up by the machine window on the desktop,
     332         * including window frame, title and menu bar and whatnot: */
    307333        QRect frame = machineWindowWrapper()->machineWindow()->frameGeometry();
    308         /* The area taken up by the console window, minus all decorations. */
     334        /* The area taken up by the machine view, so excluding all decorations: */
    309335        QRect window = geometry();
    310336        /* To work out how big we can make the console window while still
     
    312338         * This works because the difference between frame and window
    313339         * (or at least its width and height) is a constant. */
    314         mDesktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(),
     340        m_desktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(),
    315341                                       desktop.height() - frame.height() + window.height());
    316342    }
    317343}
    318344
    319 QRect UIMachineView::desktopGeometry() const
    320 {
    321     QRect rc;
    322     switch (mDesktopGeo)
     345void UIMachineView::setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight)
     346{
     347    switch (aGeo)
    323348    {
    324349        case DesktopGeo_Fixed:
     350            m_desktopGeometryType = DesktopGeo_Fixed;
     351            if (aWidth != 0 && aHeight != 0)
     352                m_desktopGeometry = QRect(0, 0, aWidth, aHeight);
     353            else
     354                m_desktopGeometry = QRect(0, 0, 0, 0);
     355            storeConsoleSize(0, 0);
     356            break;
    325357        case DesktopGeo_Automatic:
    326             rc = QRect(0, 0,
    327                        qMax(mDesktopGeometry.width(), mStoredConsoleSize.width()),
    328                        qMax(mDesktopGeometry.height(), mStoredConsoleSize.height()));
     358            m_desktopGeometryType = DesktopGeo_Automatic;
     359            m_desktopGeometry = QRect(0, 0, 0, 0);
     360            storeConsoleSize(0, 0);
    329361            break;
    330362        case DesktopGeo_Any:
    331             rc = QRect(0, 0, 0, 0);
     363            m_desktopGeometryType = DesktopGeo_Any;
     364            m_desktopGeometry = QRect(0, 0, 0, 0);
    332365            break;
    333366        default:
    334             AssertMsgFailed(("Bad geometry type %d\n", mDesktopGeo));
    335     }
    336     return rc;
     367            AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo));
     368            m_desktopGeometryType = DesktopGeo_Invalid;
     369    }
     370}
     371
     372void UIMachineView::storeConsoleSize(int aWidth, int aHeight)
     373{
     374    LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight));
     375    m_storedConsoleSize = QRect(0, 0, aWidth, aHeight);
     376}
     377
     378QRect UIMachineView::availableGeometry()
     379{
     380    return machineWindowWrapper()->machineWindow()->isFullScreen() ?
     381           QApplication::desktop()->screenGeometry(this) :
     382           QApplication::desktop()->availableGeometry(this);
    337383}
    338384
     
    341387    CDisplay display = m_console.GetDisplay();
    342388    Assert(!display.isNull());
    343     mFrameBuf = NULL;
    344 
    345     switch (mode)
     389    m_pFrameBuffer = NULL;
     390
     391    switch (mode())
    346392    {
    347393#if defined (VBOX_GUI_USE_QIMAGE)
     
    349395#if 0 // TODO: Enable QImage + Video Acceleration!
    350396# ifdef VBOX_WITH_VIDEOHWACCEL
    351             mFrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UIFrameBufferQImage>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQImage(this);
     397            m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UIFrameBufferQImage>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQImage(this);
    352398# else
    353             mFrameBuf = new UIFrameBufferQImage(this);
     399            m_pFrameBuffer = new UIFrameBufferQImage(this);
    354400# endif
    355401#endif
    356             mFrameBuf = new UIFrameBufferQImage(this);
     402            m_pFrameBuffer = new UIFrameBufferQImage(this);
    357403            break;
    358404#endif
     
    360406#if defined (VBOX_GUI_USE_QGL)
    361407        case VBoxDefs::QGLMode:
    362             mFrameBuf = new UIQGLFrameBuffer(this);
     408            m_pFrameBuffer = new UIQGLFrameBuffer(this);
    363409            break;
    364410        case VBoxDefs::QGLOverlayMode:
    365             mFrameBuf = new UIQGLOverlayFrameBuffer(this);
     411            m_pFrameBuffer = new UIQGLOverlayFrameBuffer(this);
    366412            break;
    367413#endif
     
    377423# endif
    378424# if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
    379             mFrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UISDLFrameBuffer> (this, &machineWindowWrapper()->session()) : new UISDLFrameBuffer(this);
     425            m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<UISDLFrameBuffer> (this, &machineWindowWrapper()->session()) : new UISDLFrameBuffer(this);
    380426# else
    381             mFrameBuf = new UISDLFrameBuffer(this);
     427            m_pFrameBuffer = new UISDLFrameBuffer(this);
    382428# endif
    383429            /* Disable scrollbars because we cannot correctly draw in a scrolled window using SDL: */
     
    390436#if defined (VBOX_GUI_USE_DDRAW)
    391437        case VBoxDefs::DDRAWMode:
    392             mFrameBuf = new UIDDRAWFrameBuffer(this);
    393             if (!mFrameBuf || mFrameBuf->address() == NULL)
    394             {
    395                 if (mFrameBuf)
    396                     delete mFrameBuf;
    397                 mode = VBoxDefs::QImageMode;
    398                 mFrameBuf = new UIFrameBufferQImage(this);
     438            m_pFrameBuffer = new UIDDRAWFrameBuffer(this);
     439            if (!m_pFrameBuffer || m_pFrameBuffer->address() == NULL)
     440            {
     441                if (m_pFrameBuffer)
     442                    delete m_pFrameBuffer;
     443                m_mode = VBoxDefs::QImageMode;
     444                m_pFrameBuffer = new UIFrameBufferQImage(this);
    399445            }
    400446            break;
     
    407453            pViewport->setAttribute(Qt::WA_PaintOnScreen);
    408454# ifdef VBOX_WITH_VIDEOHWACCEL
    409             mFrameBuf = mAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQuartz2D(this);
     455            m_pFrameBuffer = m_fAccelerate2DVideo ? new VBoxOverlayFrameBuffer<VBoxQuartz2DFrameBuffer>(this, &machineWindowWrapper()->session()) : new UIFrameBufferQuartz2D(this);
    410456# else
    411             mFrameBuf = new UIFrameBufferQuartz2D(this);
     457            m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
    412458# endif
    413459            break;
     
    415461#endif
    416462        default:
    417             AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode));
    418             LogRel(("Invalid render mode: %d\n", mode));
     463            AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode()));
     464            LogRel(("Invalid render mode: %d\n", mode()));
    419465            qApp->exit(1);
    420466            break;
    421467    }
    422     if (mFrameBuf)
    423     {
    424         mFrameBuf->AddRef();
    425         display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(mFrameBuf));
     468    if (m_pFrameBuffer)
     469    {
     470        m_pFrameBuffer->AddRef();
     471        display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(m_pFrameBuffer));
    426472    }
    427473}
     
    433479
    434480    /* Pressed keys: */
    435     ::memset(mPressedKeys, 0, sizeof(mPressedKeys));
     481    ::memset(m_pressedKeys, 0, sizeof(m_pressedKeys));
    436482
    437483    /* Prepare viewport: */
    438484#ifdef VBOX_GUI_USE_QGL
    439485    QWidget *pViewport;
    440     switch (mode)
     486    switch (mode())
    441487    {
    442488#if 0 // TODO: Create Open GL viewport!
     
    521567    viewport()->installEventFilter(this);
    522568
    523     /* To fix some focus issues: */
    524     //qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);
    525 
    526569    /* We want to be notified on some parent's events: */
    527570    machineWindowWrapper()->machineWindow()->installEventFilter(this);
     571}
     572
     573void UIMachineView::prepareConsoleConnections()
     574{
     575    UISession *sender = machineWindowWrapper()->machineLogic()->uisession();
     576    connect(sender, SIGNAL(sigMousePointerShapeChange(bool, bool, uint, uint, uint, uint, const uchar *)),
     577            this, SLOT(sltMousePointerShapeChange(bool, bool, uint, uint, uint, uint, const uchar *)));
     578    connect(sender, SIGNAL(sigMouseCapabilityChange(bool, bool)), this, SLOT(sltMouseCapabilityChange(bool, bool)));
     579    connect(sender, SIGNAL(sigKeyboardLedsChange(bool, bool, bool)), this, SLOT(sltKeyboardLedsChange(bool, bool, bool)));
     580    connect(sender, SIGNAL(sigStateChange(KMachineState)), this, SLOT(sltStateChange(KMachineState)));
     581    connect(sender, SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChange()));
    528582}
    529583
     
    558612        QString passCAD = m_console.GetMachine().GetExtraData(VBoxDefs::GUI_PassCAD);
    559613        if (!passCAD.isEmpty() && ((passCAD != "false") || (passCAD != "no")))
    560             mPassCAD = true;
     614            m_fPassCAD = true;
    561615    }
    562616}
     
    574628        UnhookWindowsHookEx(gKbdHook);
    575629    gView = 0;
    576     if (mAlphaCursor)
    577         DestroyIcon(mAlphaCursor);
     630    if (m_alphaCursor)
     631        DestroyIcon(m_alphaCursor);
    578632#endif
    579633
     
    594648{
    595649    /* Cleanup: */
    596     if (mFrameBuf)
     650    if (m_pFrameBuffer)
    597651    {
    598652        /* Detach framebuffer from Display: */
     
    600654        display.SetFramebuffer(VBOX_VIDEO_PRIMARY_SCREEN, CFramebuffer(NULL));
    601655        /* Release the reference: */
    602         mFrameBuf->Release();
    603         mFrameBuf = NULL;
    604     }
     656        m_pFrameBuffer->Release();
     657        m_pFrameBuffer = NULL;
     658    }
     659}
     660
     661void UIMachineView::sltMousePointerShapeChange(bool fIsVisible, bool fHasAlpha,
     662                                               uint uXHot, uint uYHot, uint uWidth, uint uHeight,
     663                                               const uchar *pShapeData)
     664{
     665    if (m_bIsMouseAbsolute)
     666    {
     667        /* Do we have new shape data? */
     668        if (pShapeData)
     669            setPointerShape(pShapeData, fHasAlpha, uXHot, uYHot, uWidth, uHeight);
     670
     671        /* Should we hide/show pointer? */
     672        if (fIsVisible)
     673            viewport()->setCursor(m_lastCursor);
     674        else
     675            viewport()->setCursor(Qt::BlankCursor);
     676    }
     677    m_fHideHostPointer = !fIsVisible;
     678}
     679
     680void UIMachineView::sltMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor)
     681{
     682    if (m_bIsMouseAbsolute != bIsSupportsAbsolute)
     683    {
     684        m_bIsMouseAbsolute = bIsSupportsAbsolute;
     685        /* Correct the mouse capture state and reset the cursor to the default shape if necessary: */
     686        if (m_bIsMouseAbsolute)
     687        {
     688            CMouse mouse = m_console.GetMouse();
     689            mouse.PutMouseEventAbsolute(-1, -1, 0, 0 /* Horizontal wheel */, 0);
     690            captureMouse(false, false);
     691        }
     692        else
     693            viewport()->unsetCursor();
     694        emitMouseStateChanged();
     695        vboxProblem().remindAboutMouseIntegration(m_bIsMouseAbsolute);
     696    }
     697    if (bNeedsHostCursor)
     698        setMouseIntegrationLocked(false);
     699    else
     700        setMouseIntegrationLocked(true);
     701}
     702
     703void UIMachineView::sltKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock)
     704{
     705    if (bNumLock != m_numLock)
     706        m_uNumLockAdaptionCnt = 2;
     707    if (bCapsLock != m_capsLock)
     708        m_uCapsLockAdaptionCnt = 2;
     709    m_numLock    = bNumLock;
     710    m_capsLock   = bCapsLock;
     711    m_scrollLock = bScrollLock;
     712}
     713
     714void UIMachineView::sltStateChange(KMachineState state)
     715{
     716    switch (state)
     717    {
     718        case KMachineState_Paused:
     719        case KMachineState_TeleportingPausedVM:
     720        {
     721            if (mode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
     722                (state != KMachineState_TeleportingPausedVM || m_machineState != KMachineState_Teleporting))
     723            {
     724                /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
     725                QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
     726                CDisplay dsp = m_console.GetDisplay();
     727                dsp.TakeScreenShot(shot.bits(), shot.width(), shot.height());
     728                /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
     729                 * after the machine execution was resumed. It's not fatal: */
     730                if (dsp.isOk())
     731                {
     732                    dimImage(shot);
     733                    m_pauseShot = QPixmap::fromImage(shot);
     734                    /* Fully repaint to pick up m_pauseShot: */
     735                    repaint();
     736                }
     737            }
     738        }
     739        case KMachineState_Stuck:
     740        {
     741            /* Reuse the focus event handler to uncapture everything: */
     742            if (hasFocus())
     743                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     744            break;
     745        }
     746        case KMachineState_Running:
     747        {
     748            if (m_machineState == KMachineState_Paused || m_machineState == KMachineState_TeleportingPausedVM)
     749            {
     750                if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer)
     751                {
     752                    /* Reset the pixmap to free memory: */
     753                    m_pauseShot = QPixmap();
     754                    /* Ask for full guest display update (it will also update
     755                     * the viewport through IFramebuffer::NotifyUpdate): */
     756                    CDisplay dsp = m_console.GetDisplay();
     757                    dsp.InvalidateAndUpdate();
     758                }
     759            }
     760            /* Reuse the focus event handler to capture input: */
     761            if (hasFocus())
     762                focusEvent(true /* aHasFocus */);
     763            break;
     764        }
     765        default:
     766            break;
     767    }
     768
     769    m_machineState = state;
     770}
     771
     772void UIMachineView::sltAdditionsStateChange()
     773{
     774    CGuest guest = console().GetGuest();
     775    bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
     776
     777#if 0 // TODO: Do we need this?
     778    if (!mDoResize && !isGuestSupportsGraphics() && fIsGuestSupportsGraphics &&
     779        (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))
     780        mDoResize = true;
     781#endif
     782    m_bIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
     783
     784    maybeRestrictMinimumSize();
     785
     786#if 0 // TODO: Do we need this?
     787    /* This will only be acted upon if mDoResize is true: */
     788    doResizeHint();
     789#endif
    605790}
    606791
     
    639824#endif
    640825
    641 bool UIMachineView::event(QEvent *e)
    642 {
    643     //if (m_bIsAttached)
    644     {
    645         switch (e->type())
    646         {
    647             case QEvent::FocusIn:
    648             {
    649                 if (isRunning())
    650                     focusEvent (true);
    651                 break;
    652             }
    653             case QEvent::FocusOut:
    654             {
    655                 if (isRunning())
    656                     focusEvent (false);
     826bool UIMachineView::event(QEvent *pEvent)
     827{
     828    switch (pEvent->type())
     829    {
     830        case QEvent::FocusIn:
     831        {
     832            if (isRunning())
     833                focusEvent(true);
     834            break;
     835        }
     836        case QEvent::FocusOut:
     837        {
     838            if (isRunning())
     839                focusEvent(false);
     840            else
     841            {
     842                /* Release the host key and all other pressed keys too even when paused (otherwise, we will get stuck
     843                 * keys in the guest when doing sendChangedKeyStates() on resume because key presses were already
     844                 * recorded in m_pressedKeys but key releases will most likely not reach us but the new focus window instead): */
     845                releaseAllPressedKeys(true /* fReleaseHostKey */);
     846            }
     847            break;
     848        }
     849
     850        case VBoxDefs::ResizeEventType:
     851        {
     852            /* Some situations require initial VGA Resize Request
     853             * to be ignored at all, leaving previous framebuffer,
     854             * machine view and machine window sizes preserved: */
     855            if (m_bIsGuestResizeIgnored)
     856                return true;
     857
     858            bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored;
     859            m_bIsMachineWindowResizeIgnored = true;
     860
     861            UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);
     862
     863            /* Store the new size to prevent unwanted resize hints being sent back. */
     864            storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());
     865
     866            /* Unfortunately restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen widgets are present.
     867             * This is the case on linux with SDL. As workaround we save/restore the arrow cursor manually.
     868             * See http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry for details.
     869             * Moreover the current cursor, which could be set by the guest, should be restored after resize: */
     870            QCursor cursor;
     871            if (shouldHideHostPointer())
     872                cursor = QCursor(Qt::BlankCursor);
     873            else
     874                cursor = viewport()->cursor();
     875            m_pFrameBuffer->resizeEvent(pResizeEvent);
     876            viewport()->setCursor(cursor);
     877
     878#ifdef Q_WS_MAC
     879            mDockIconPreview->setOriginalSize(pResizeEvent->width(), pResizeEvent->height());
     880#endif /* Q_WS_MAC */
     881
     882            /* This event appears in case of guest video was changed for somehow even without video resolution change.
     883             * In this last case the host VM window will not be resized according this event and the host mouse cursor
     884             * which was unset to default here will not be hidden in capture state. So it is necessary to perform
     885             * updateMouseClipping() for the guest resize event if the mouse cursor was captured: */
     886            if (m_bIsMouseCaptured)
     887                updateMouseClipping();
     888
     889            /* Apply maximum size restriction: */
     890            setMaximumSize(sizeHint());
     891
     892            /* May be we have to restrict minimum size? */
     893            maybeRestrictMinimumSize();
     894
     895            /* Resize the guest canvas: */
     896            if (!m_bIsFrameBufferResizeIgnored)
     897                resize(pResizeEvent->width(), pResizeEvent->height());
     898            updateSliders();
     899
     900            /* Let our toplevel widget calculate its sizeHint properly. */
     901#ifdef Q_WS_X11
     902            /* We use processEvents rather than sendPostedEvents & set the time out value to max cause on X11 otherwise
     903             * the layout isn't calculated correctly. Dosn't find the bug in Qt, but this could be triggered through
     904             * the async nature of the X11 window event system. */
     905            QCoreApplication::processEvents(QEventLoop::AllEvents, INT_MAX);
     906#else /* Q_WS_X11 */
     907            QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
     908#endif /* Q_WS_X11 */
     909
     910            if (!m_bIsFrameBufferResizeIgnored)
     911                normalizeGeometry(true /* adjustPosition */);
     912
     913            /* Report to the VM thread that we finished resizing */
     914            m_console.GetDisplay().ResizeCompleted(0);
     915
     916            m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize;
     917
     918            /* Make sure that all posted signals are processed: */
     919            qApp->processEvents();
     920
     921            /* Emit a signal about guest was resized: */
     922            emit resizeHintDone();
     923
     924            /* We also recalculate the desktop geometry if this is determined
     925             * automatically.  In fact, we only need this on the first resize,
     926             * but it is done every time to keep the code simpler. */
     927            calculateDesktopGeometry();
     928
     929            /* Enable frame-buffer resize watching only now: */
     930            if (m_bIsFrameBufferResizeIgnored)
     931                m_bIsFrameBufferResizeIgnored = false;
     932
     933            return true;
     934        }
     935
     936        /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(): */
     937        case VBoxDefs::RepaintEventType:
     938        {
     939            UIRepaintEvent *pPaintEvent = static_cast<UIRepaintEvent*>(pEvent);
     940            viewport()->repaint(pPaintEvent->x() - contentsX(), pPaintEvent->y() - contentsY(),
     941                                pPaintEvent->width(), pPaintEvent->height());
     942            /* m_console.GetDisplay().UpdateCompleted(); - the event was acked already */
     943            return true;
     944        }
     945
     946#ifdef VBOX_WITH_VIDEOHWACCEL
     947        case VBoxDefs::VHWACommandProcessType:
     948        {
     949            m_pFrameBuffer->doProcessVHWACommand(pEvent);
     950            return true;
     951        }
     952#endif
     953
     954#if 0 // TODO: Move that to seamless mode event hadler!
     955        case VBoxDefs::SetRegionEventType:
     956        {
     957            VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) pEvent;
     958            if (machineWindowWrapper()->isTrueSeamless() && sre->region() != mLastVisibleRegion)
     959            {
     960                mLastVisibleRegion = sre->region();
     961                machineWindowWrapper()->setMask (sre->region());
     962            }
     963            else if (!mLastVisibleRegion.isEmpty() && !machineWindowWrapper()->isTrueSeamless())
     964                mLastVisibleRegion = QRegion();
     965            return true;
     966        }
     967#endif
     968
     969#if 0 // TODO: Move that to specific event handler!
     970        case VBoxDefs::ActivateMenuEventType:
     971        {
     972            ActivateMenuEvent *pMenuEvent = static_cast<ActivateMenuEvent*>(pEvent);
     973            pMenuEvent->action()->trigger();
     974
     975            /* The main window and its children can be destroyed at this point (if, for example, the activated menu
     976             * item closes the main window). Detect this situation to prevent calls to destroyed widgets: */
     977            QWidgetList list = QApplication::topLevelWidgets();
     978            bool destroyed = list.indexOf(machineWindowWrapper()->machineWindow()) < 0;
     979            if (!destroyed && machineWindowWrapper()->machineWindow()->statusBar())
     980                machineWindowWrapper()->machineWindow()->statusBar()->clearMessage();
     981
     982            return true;
     983        }
     984#endif
     985
     986        case QEvent::KeyPress:
     987        case QEvent::KeyRelease:
     988        {
     989            QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
     990
     991#ifdef Q_WS_PM
     992            // TODO: that a temporary solution to send Alt+Tab and friends to the guest.
     993            // The proper solution is to write a keyboard driver that will steal these combos from the host
     994            // (it's impossible to do so using hooks on OS/2):
     995
     996            if (m_bIsHostkeyPressed)
     997            {
     998                bool pressed = pEvent->type() == QEvent::KeyPress;
     999                CKeyboard keyboard = m_console.GetKeyboard();
     1000
     1001                /* Whether the host key is Shift so that it will modify the hot key values?
     1002                 * Note that we don't distinguish between left and right shift here (too much hassle): */
     1003                const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT ||
     1004                                    m_globalSettings.hostKey() == VK_LSHIFT) &&
     1005                                    (pKeyEvent->state() & Qt::ShiftModifier);
     1006                /* define hot keys according to the Shift state */
     1007                const int kAltTab      = kShift ? Qt::Key_Exclam     : Qt::Key_1;
     1008                const int kAltShiftTab = kShift ? Qt::Key_At         : Qt::Key_2;
     1009                const int kCtrlEsc     = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft;
     1010
     1011                /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */
     1012                if (pKeyEvent->key() == kAltTab || pKeyEvent->key() == kAltShiftTab)
     1013                {
     1014                    if (pressed)
     1015                    {
     1016                        /* Send the Alt press to the guest */
     1017                        if (!(m_pressedKeysCopy[0x38] & IsKeyPressed))
     1018                        {
     1019                            /* Store the press in *Copy to have it automatically
     1020                             * released when the Host key is released: */
     1021                            m_pressedKeysCopy[0x38] |= IsKeyPressed;
     1022                            keyboard.PutScancode(0x38);
     1023                        }
     1024
     1025                        /* Make sure Shift is pressed if it's Key_2 and released if it's Key_1: */
     1026                        if (pKeyEvent->key() == kAltTab &&
     1027                            (m_pressedKeysCopy[0x2A] & IsKeyPressed))
     1028                        {
     1029                            m_pressedKeysCopy[0x2A] &= ~IsKeyPressed;
     1030                            keyboard.PutScancode(0xAA);
     1031                        }
     1032                        else
     1033                        if (pKeyEvent->key() == kAltShiftTab &&
     1034                            !(m_pressedKeysCopy[0x2A] & IsKeyPressed))
     1035                        {
     1036                            m_pressedKeysCopy[0x2A] |= IsKeyPressed;
     1037                            keyboard.PutScancode(0x2A);
     1038                        }
     1039                    }
     1040
     1041                    keyboard.PutScancode(pressed ? 0x0F : 0x8F);
     1042
     1043                    pKeyEvent->accept();
     1044                    return true;
     1045                }
     1046
     1047                /* Simulate Ctrl+Esc on Host+Tilde */
     1048                if (pKeyEvent->key() == kCtrlEsc)
     1049                {
     1050                    /* Send the Ctrl press to the guest */
     1051                    if (pressed && !(m_pressedKeysCopy[0x1d] & IsKeyPressed))
     1052                    {
     1053                        /* store the press in *Copy to have it automatically
     1054                         * released when the Host key is released */
     1055                        m_pressedKeysCopy[0x1d] |= IsKeyPressed;
     1056                        keyboard.PutScancode(0x1d);
     1057                    }
     1058
     1059                    keyboard.PutScancode(pressed ? 0x01 : 0x81);
     1060
     1061                    pKeyEvent->accept();
     1062                    return true;
     1063                }
     1064            }
     1065#endif /* Q_WS_PM */
     1066
     1067            if (m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyPress)
     1068            {
     1069                if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F12)
     1070                {
     1071                    QVector <LONG> combo(6);
     1072                    combo[0] = 0x1d; /* Ctrl down */
     1073                    combo[1] = 0x38; /* Alt  down */
     1074                    combo[4] = 0xb8; /* Alt  up   */
     1075                    combo[5] = 0x9d; /* Ctrl up   */
     1076                    if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F10)
     1077                    {
     1078                        combo[2] = 0x3b + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 down */
     1079                        combo[3] = 0xbb + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 up   */
     1080                    }
     1081                    /* some scan slice */
     1082                    else if (pKeyEvent->key() >= Qt::Key_F11 && pKeyEvent->key() <= Qt::Key_F12)
     1083                    {
     1084                        combo[2] = 0x57 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 down */
     1085                        combo[3] = 0xd7 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 up   */
     1086                    }
     1087                    else
     1088                        Assert(0);
     1089
     1090                    CKeyboard keyboard = m_console.GetKeyboard();
     1091                    keyboard.PutScancodes(combo);
     1092                }
     1093
     1094#if 0 // TODO: Divide tha code to specific parts and move it there:
     1095                if (pKeyEvent->key() == Qt::Key_Home)
     1096                {
     1097                    /* Activate the main menu */
     1098                    if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen())
     1099                        machineWindowWrapper()->popupMainMenu (m_bIsMouseCaptured);
     1100                    else
     1101                    {
     1102                        /* In Qt4 it is not enough to just set the focus to menu-bar.
     1103                         * So to get the menu-bar we have to send Qt::Key_Alt press/release events directly: */
     1104                        QKeyEvent e1(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier);
     1105                        QKeyEvent e2(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier);
     1106                        QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e1);
     1107                        QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e2);
     1108                    }
     1109                }
    6571110                else
    6581111                {
    659                     /* release the host key and all other pressed keys too even
    660                      * when paused (otherwise, we will get stuck keys in the
    661                      * guest when doing sendChangedKeyStates() on resume because
    662                      * key presses were already recorded in mPressedKeys but key
    663                      * releases will most likely not reach us but the new focus
    664                      * window instead). */
    665                     releaseAllPressedKeys (true /* aReleaseHostKey */);
     1112                    /* Process hot keys not processed in keyEvent() (as in case of non-alphanumeric keys): */
     1113                    processHotKey(QKeySequence (pKeyEvent->key()), machineWindowWrapper()->menuBar()->actions());
    6661114                }
    667                 break;
    668             }
    669 
    670             case VBoxDefs::ResizeEventType:
    671             {
    672                 /* Some situations require initial VGA Resize Request
    673                  * to be ignored at all, leaving previous framebuffer,
    674                  * console widget and vm window size preserved. */
    675                 if (m_bIsGuestResizeIgnored)
    676                     return true;
    677 
    678                 bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored;
    679                 m_bIsMachineWindowResizeIgnored = true;
    680 
    681                 UIResizeEvent *re = (UIResizeEvent *) e;
    682                 LogFlow (("VBoxDefs::ResizeEventType: %d x %d x %d bpp\n",
    683                           re->width(), re->height(), re->bitsPerPixel()));
    684 #ifdef DEBUG_michael
    685                 LogRel (("Resize event from guest: %d x %d x %d bpp\n",
    686                          re->width(), re->height(), re->bitsPerPixel()));
    687 #endif
    688 
    689                 /* Store the new size to prevent unwanted resize hints being
    690                  * sent back. */
    691                 storeConsoleSize(re->width(), re->height());
    692                 /* do frame buffer dependent resize */
    693 
    694                 /* restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen
    695                  * widgets are present. This is the case on linux with SDL. As
    696                  * workaround we save/restore the arrow cursor manually. See
    697                  * http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry
    698                  * for details.
    699                  *
    700                  * Moreover the current cursor, which could be set by the guest,
    701                  * should be restored after resize.
    702                  */
    703                 QCursor cursor;
    704                 if (shouldHideHostPointer())
    705                     cursor = QCursor (Qt::BlankCursor);
    706                 else
    707                     cursor = viewport()->cursor();
    708                 mFrameBuf->resizeEvent (re);
    709                 viewport()->setCursor (cursor);
     1115#endif
     1116            }
     1117            else if (!m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyRelease)
     1118            {
     1119                /* Show a possible warning on key release which seems to be more expected by the end user: */
     1120                if (machineWindowWrapper()->machineLogic()->isPaused())
     1121                {
     1122                    /* Iif the reminder is disabled we pass the event to Qt to enable normal
     1123                     * keyboard functionality (for example, menu access with Alt+Letter): */
     1124                    if (!vboxProblem().remindAboutPausedVMInput())
     1125                        break;
     1126                }
     1127            }
     1128
     1129            pKeyEvent->accept();
     1130            return true;
     1131        }
    7101132
    7111133#ifdef Q_WS_MAC
    712                 mDockIconPreview->setOriginalSize (re->width(), re->height());
    713 #endif /* Q_WS_MAC */
    714 
    715                 /* This event appears in case of guest video was changed
    716                  * for somehow even without video resolution change.
    717                  * In this last case the host VM window will not be resized
    718                  * according this event and the host mouse cursor which was
    719                  * unset to default here will not be hidden in capture state.
    720                  * So it is necessary to perform updateMouseClipping() for
    721                  * the guest resize event if the mouse cursor was captured. */
    722                 if (m_bIsMouseCaptured)
    723                     updateMouseClipping();
    724 
    725                 /* apply maximum size restriction */
    726                 setMaximumSize (sizeHint());
    727 
    728                 maybeRestrictMinimumSize();
    729 
    730                 /* resize the guest canvas */
    731                 if (!m_bIsFrameBufferResizeIgnored)
    732                     resize (re->width(), re->height());
    733                 updateSliders();
    734                 /* Let our toplevel widget calculate its sizeHint properly. */
    735 #ifdef Q_WS_X11
    736                 /* We use processEvents rather than sendPostedEvents & set the
    737                  * time out value to max cause on X11 otherwise the layout
    738                  * isn't calculated correctly. Dosn't find the bug in Qt, but
    739                  * this could be triggered through the async nature of the X11
    740                  * window event system. */
    741                 QCoreApplication::processEvents (QEventLoop::AllEvents, INT_MAX);
    742 #else /* Q_WS_X11 */
    743                 QCoreApplication::sendPostedEvents (0, QEvent::LayoutRequest);
    744 #endif /* Q_WS_X11 */
    745 
    746                 if (!m_bIsFrameBufferResizeIgnored)
    747                     normalizeGeometry (true /* adjustPosition */);
    748 
    749                 /* report to the VM thread that we finished resizing */
    750                 m_console.GetDisplay().ResizeCompleted (0);
    751 
    752                 m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize;
    753 
    754                 /* update geometry after entering fullscreen | seamless */
    755                 // if (machineWindowWrapper()->isTrueFullscreen() || machineWindowWrapper()->isTrueSeamless()) TODO check that!
    756                     updateGeometry();
    757 
    758                 /* make sure that all posted signals are processed */
    759                 qApp->processEvents();
    760 
    761                 /* emit a signal about guest was resized */
    762                 emit resizeHintDone();
    763 
    764                 /* We also recalculate the desktop geometry if this is determined
    765                  * automatically.  In fact, we only need this on the first resize,
    766                  * but it is done every time to keep the code simpler. */
    767                 calculateDesktopGeometry();
    768 
    769                 /* Enable frame-buffer resize watching. */
    770                 if (m_bIsFrameBufferResizeIgnored)
    771                 {
    772                     m_bIsFrameBufferResizeIgnored = false;
    773                 }
    774 
    775                 // machineWindowWrapper()->onDisplayResize (re->width(), re->height()); TODO check that!
    776 
    777                 return true;
    778             }
    779 
    780             /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(). */
    781             case VBoxDefs::RepaintEventType:
    782             {
    783                 UIRepaintEvent *re = (UIRepaintEvent *) e;
    784                 viewport()->repaint (re->x() - contentsX(),
    785                                      re->y() - contentsY(),
    786                                      re->width(), re->height());
    787                 /* m_console.GetDisplay().UpdateCompleted(); - the event was acked already */
    788                 return true;
    789             }
    790 
    791 #ifdef VBOX_WITH_VIDEOHWACCEL
    792             case VBoxDefs::VHWACommandProcessType:
    793             {
    794                 mFrameBuf->doProcessVHWACommand(e);
    795                 return true;
    796             }
    797 #endif
    798 
    799             #if 0
    800             // TODO check that!
    801             case VBoxDefs::SetRegionEventType:
    802             {
    803                 VBoxSetRegionEvent *sre = (VBoxSetRegionEvent*) e;
    804                 if (machineWindowWrapper()->isTrueSeamless() && sre->region() != mLastVisibleRegion)
    805                 {
    806                     mLastVisibleRegion = sre->region();
    807                     machineWindowWrapper()->setMask (sre->region());
    808                 }
    809                 else if (!mLastVisibleRegion.isEmpty() && !machineWindowWrapper()->isTrueSeamless())
    810                     mLastVisibleRegion = QRegion();
    811                 return true;
    812             }
    813             #endif
    814 
    815             #if 0
    816             case VBoxDefs::ActivateMenuEventType:
    817             {
    818                 ActivateMenuEvent *ame = (ActivateMenuEvent *) e;
    819                 ame->action()->trigger();
    820 
    821                 /*
    822                  *  The main window and its children can be destroyed at this
    823                  *  point (if, for example, the activated menu item closes the
    824                  *  main window). Detect this situation to prevent calls to
    825                  *  destroyed widgets.
    826                  */
    827                 QWidgetList list = QApplication::topLevelWidgets();
    828                 bool destroyed = list.indexOf (machineWindowWrapper()->machineWindow()) < 0;
    829                 if (!destroyed && machineWindowWrapper()->machineWindow()->statusBar())
    830                     machineWindowWrapper()->machineWindow()->statusBar()->clearMessage();
    831 
    832                 return true;
    833             }
    834             #endif
    835 
    836             case QEvent::KeyPress:
    837             case QEvent::KeyRelease:
    838             {
    839                 QKeyEvent *ke = (QKeyEvent *) e;
    840 
    841 #ifdef Q_WS_PM
    842                 /// @todo temporary solution to send Alt+Tab and friends to
    843                 //  the guest. The proper solution is to write a keyboard
    844                 //  driver that will steal these combos from the host (it's
    845                 //  impossible to do so using hooks on OS/2).
    846 
    847                 if (m_bIsHostkeyPressed)
    848                 {
    849                     bool pressed = e->type() == QEvent::KeyPress;
    850                     CKeyboard keyboard = m_console.GetKeyboard();
    851 
    852                     /* whether the host key is Shift so that it will modify
    853                      * the hot key values? Note that we don't distinguish
    854                      * between left and right shift here (too much hassle) */
    855                     const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT ||
    856                                         m_globalSettings.hostKey() == VK_LSHIFT) &&
    857                                         (ke->state() & Qt::ShiftModifier);
    858                     /* define hot keys according to the Shift state */
    859                     const int kAltTab      = kShift ? Qt::Key_Exclam     : Qt::Key_1;
    860                     const int kAltShiftTab = kShift ? Qt::Key_At         : Qt::Key_2;
    861                     const int kCtrlEsc     = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft;
    862 
    863                     /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */
    864                     if (ke->key() == kAltTab || ke->key() == kAltShiftTab)
    865                     {
    866                         if (pressed)
    867                         {
    868                             /* Send the Alt press to the guest */
    869                             if (!(mPressedKeysCopy [0x38] & IsKeyPressed))
    870                             {
    871                                 /* store the press in *Copy to have it automatically
    872                                  * released when the Host key is released */
    873                                 mPressedKeysCopy [0x38] |= IsKeyPressed;
    874                                 keyboard.PutScancode (0x38);
    875                             }
    876 
    877                             /* Make sure Shift is pressed if it's Key_2 and released
    878                              * if it's Key_1 */
    879                             if (ke->key() == kAltTab &&
    880                                 (mPressedKeysCopy [0x2A] & IsKeyPressed))
    881                             {
    882                                 mPressedKeysCopy [0x2A] &= ~IsKeyPressed;
    883                                 keyboard.PutScancode (0xAA);
    884                             }
    885                             else
    886                             if (ke->key() == kAltShiftTab &&
    887                                 !(mPressedKeysCopy [0x2A] & IsKeyPressed))
    888                             {
    889                                 mPressedKeysCopy [0x2A] |= IsKeyPressed;
    890                                 keyboard.PutScancode (0x2A);
    891                             }
    892                         }
    893 
    894                         keyboard.PutScancode (pressed ? 0x0F : 0x8F);
    895 
    896                         ke->accept();
    897                         return true;
    898                     }
    899 
    900                     /* Simulate Ctrl+Esc on Host+Tilde */
    901                     if (ke->key() == kCtrlEsc)
    902                     {
    903                         /* Send the Ctrl press to the guest */
    904                         if (pressed && !(mPressedKeysCopy [0x1d] & IsKeyPressed))
    905                         {
    906                             /* store the press in *Copy to have it automatically
    907                              * released when the Host key is released */
    908                             mPressedKeysCopy [0x1d] |= IsKeyPressed;
    909                             keyboard.PutScancode (0x1d);
    910                         }
    911 
    912                         keyboard.PutScancode (pressed ? 0x01 : 0x81);
    913 
    914                         ke->accept();
    915                         return true;
    916                     }
    917                 }
    918 
    919                 /* fall through to normal processing */
    920 
    921 #endif /* Q_WS_PM */
    922 
    923                 if (m_bIsHostkeyPressed && e->type() == QEvent::KeyPress)
    924                 {
    925                     if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F12)
    926                     {
    927                         QVector <LONG> combo (6);
    928                         combo [0] = 0x1d; /* Ctrl down */
    929                         combo [1] = 0x38; /* Alt  down */
    930                         combo [4] = 0xb8; /* Alt  up   */
    931                         combo [5] = 0x9d; /* Ctrl up   */
    932                         if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F10)
    933                         {
    934                             combo [2] = 0x3b + (ke->key() - Qt::Key_F1); /* F1-F10 down */
    935                             combo [3] = 0xbb + (ke->key() - Qt::Key_F1); /* F1-F10 up   */
    936                         }
    937                         /* some scan slice */
    938                         else if (ke->key() >= Qt::Key_F11 && ke->key() <= Qt::Key_F12)
    939                         {
    940                             combo [2] = 0x57 + (ke->key() - Qt::Key_F11); /* F11-F12 down */
    941                             combo [3] = 0xd7 + (ke->key() - Qt::Key_F11); /* F11-F12 up   */
    942                         }
    943                         else
    944                             Assert (0);
    945 
    946                         CKeyboard keyboard = m_console.GetKeyboard();
    947                         keyboard.PutScancodes (combo);
    948                     }
    949                     #if 0
    950                     // TODO check that!
    951                     else if (ke->key() == Qt::Key_Home)
    952                     {
    953                         /* Activate the main menu */
    954                         if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen())
    955                             machineWindowWrapper()->popupMainMenu (m_bIsMouseCaptured);
    956                         else
    957                         {
    958                             /* In Qt4 it is not enough to just set the focus to
    959                              * menu-bar. So to get the menu-bar we have to send
    960                              * Qt::Key_Alt press/release events directly. */
    961                             QKeyEvent e1 (QEvent::KeyPress, Qt::Key_Alt,
    962                                           Qt::NoModifier);
    963                             QKeyEvent e2 (QEvent::KeyRelease, Qt::Key_Alt,
    964                                           Qt::NoModifier);
    965                             QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e1);
    966                             QApplication::sendEvent (machineWindowWrapper()->menuBar(), &e2);
    967                         }
    968                     }
    969                     else
    970                     {
    971                         /* process hot keys not processed in keyEvent()
    972                          * (as in case of non-alphanumeric keys) */
    973                         processHotKey (QKeySequence (ke->key()),
    974                                        machineWindowWrapper()->menuBar()->actions());
    975                     }
    976                     #endif
    977                 }
    978                 else if (!m_bIsHostkeyPressed && e->type() == QEvent::KeyRelease)
    979                 {
    980                     /* Show a possible warning on key release which seems to
    981                      * be more expected by the end user */
    982 
    983                     if (machineWindowWrapper()->machineLogic()->isPaused())
    984                     {
    985                         /* if the reminder is disabled we pass the event to
    986                          * Qt to enable normal keyboard functionality
    987                          * (for example, menu access with Alt+Letter) */
    988                         if (!vboxProblem().remindAboutPausedVMInput())
    989                             break;
    990                     }
    991                 }
    992 
    993                 ke->accept();
    994                 return true;
    995             }
    996 
    997 #ifdef Q_WS_MAC
    998             /* posted OnShowWindow */
    999             case VBoxDefs::ShowWindowEventType:
    1000             {
    1001                 /*
    1002                  *  Dunno what Qt3 thinks a window that has minimized to the dock
    1003                  *  should be - it is not hidden, neither is it minimized. OTOH it is
    1004                  *  marked shown and visible, but not activated. This latter isn't of
    1005                  *  much help though, since at this point nothing is marked activated.
    1006                  *  I might have overlooked something, but I'm buggered what if I know
    1007                  *  what. So, I'll just always show & activate the stupid window to
    1008                  *  make it get out of the dock when the user wishes to show a VM.
    1009                  */
    1010                 window()->show();
    1011                 window()->activateWindow();
    1012                 return true;
    1013             }
    1014 #endif
    1015             default:
    1016                 break;
    1017         }
    1018     }
    1019 
    1020     return QAbstractScrollArea::event (e);
    1021 }
    1022 
    1023 bool UIMachineView::eventFilter(QObject *watched, QEvent *e)
    1024 {
    1025     if (watched == viewport())
    1026     {
    1027         switch (e->type())
     1134        /* posted OnShowWindow */
     1135        case VBoxDefs::ShowWindowEventType:
     1136        {
     1137            /* Dunno what Qt3 thinks a window that has minimized to the dock should be - it is not hidden,
     1138             * neither is it minimized. OTOH it is marked shown and visible, but not activated.
     1139             * This latter isn't of much help though, since at this point nothing is marked activated.
     1140             * I might have overlooked something, but I'm buggered what if I know what. So, I'll just always
     1141             * show & activate the stupid window to make it get out of the dock when the user wishes to show a VM: */
     1142            window()->show();
     1143            window()->activateWindow();
     1144            return true;
     1145        }
     1146#endif
     1147
     1148        default:
     1149            break;
     1150    }
     1151
     1152    return QAbstractScrollArea::event(pEvent);
     1153}
     1154
     1155bool UIMachineView::eventFilter(QObject *pWatched, QEvent *pEvent)
     1156{
     1157    if (pWatched == viewport())
     1158    {
     1159        switch (pEvent->type())
    10281160        {
    10291161            case QEvent::MouseMove:
     
    10321164            case QEvent::MouseButtonRelease:
    10331165            {
    1034                 QMouseEvent *me = (QMouseEvent *) e;
     1166                QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
    10351167                m_iLastMouseWheelDelta = 0;
    1036                 if (mouseEvent (me->type(), me->pos(), me->globalPos(),
    1037                                 me->buttons(), me->modifiers(),
    1038                                 0, Qt::Horizontal))
    1039                     return true; /* stop further event handling */
     1168                if (mouseEvent(pMouseEvent->type(), pMouseEvent->pos(), pMouseEvent->globalPos(),
     1169                               pMouseEvent->buttons(), pMouseEvent->modifiers(), 0, Qt::Horizontal))
     1170                    return true;
    10401171                break;
    10411172            }
    10421173            case QEvent::Wheel:
    10431174            {
    1044                 QWheelEvent *we = (QWheelEvent *) e;
    1045                 /* There are pointing devices which send smaller values for the
    1046                  * delta than 120. Here we sum them up until we are greater
    1047                  * than 120. This allows to have finer control over the speed
    1048                  * acceleration & enables such devices to send a valid wheel
    1049                  * event to our guest mouse device at all. */
     1175                QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent);
     1176                /* There are pointing devices which send smaller values for the delta than 120.
     1177                 * Here we sum them up until we are greater than 120. This allows to have finer control
     1178                 * over the speed acceleration & enables such devices to send a valid wheel event to our
     1179                 * guest mouse device at all: */
    10501180                int iDelta = 0;
    1051                 m_iLastMouseWheelDelta += we->delta();
     1181                m_iLastMouseWheelDelta += pWheelEvent->delta();
    10521182                if (qAbs(m_iLastMouseWheelDelta) >= 120)
    10531183                {
     
    10551185                    m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
    10561186                }
    1057                 if (mouseEvent (we->type(), we->pos(), we->globalPos(),
     1187                if (mouseEvent(pWheelEvent->type(), pWheelEvent->pos(), pWheelEvent->globalPos(),
    10581188#ifdef QT_MAC_USE_COCOA
    1059                                 /* Qt Cocoa is buggy. It always reports a left
    1060                                  * button pressed when the mouse wheel event
    1061                                  * occurs. A workaround is to ask the
    1062                                  * application which buttons are pressed
    1063                                  * currently. */
     1189                                /* Qt Cocoa is buggy. It always reports a left button pressed when the
     1190                                 * mouse wheel event occurs. A workaround is to ask the application which
     1191                                 * buttons are pressed currently: */
    10641192                                QApplication::mouseButtons(),
    10651193#else /* QT_MAC_USE_COCOA */
    1066                                 we->buttons(),
     1194                                pWheelEvent->buttons(),
    10671195#endif /* QT_MAC_USE_COCOA */
    1068                                 we->modifiers(),
    1069                                 iDelta, we->orientation()))
    1070                     return true; /* stop further event handling */
     1196                                pWheelEvent->modifiers(),
     1197                                iDelta, pWheelEvent->orientation()))
     1198                    return true;
    10711199                break;
    10721200            }
     
    10741202            case QEvent::Leave:
    10751203            {
    1076                 /* Enable mouse event compression if we leave the VM view. This
    1077                    is necessary for having smooth resizing of the VM/other
    1078                    windows. */
    1079                 setMouseCoalescingEnabled (true);
     1204                /* Enable mouse event compression if we leave the VM view. This is necessary for
     1205                 * having smooth resizing of the VM/other windows: */
     1206                setMouseCoalescingEnabled(true);
    10801207                break;
    10811208            }
    10821209            case QEvent::Enter:
    10831210            {
    1084                 /* Disable mouse event compression if we enter the VM view. So
    1085                    all mouse events are registered in the VM. Only do this if
    1086                    the keyboard/mouse is grabbed (this is when we have a valid
    1087                    event handler). */
     1211                /* Disable mouse event compression if we enter the VM view. So all mouse events are
     1212                 * registered in the VM. Only do this if the keyboard/mouse is grabbed (this is when
     1213                 * we have a valid event handler): */
    10881214                setMouseCoalescingEnabled (false);
    10891215                break;
     
    10951221                    updateMouseClipping();
    10961222#ifdef VBOX_WITH_VIDEOHWACCEL
    1097                 if (mFrameBuf)
     1223                if (m_pFrameBuffer)
    10981224                {
    1099                     mFrameBuf->viewportResized((QResizeEvent*)e);
     1225                    m_pFrameBuffer->viewportResized(static_cast<QResizeEvent*>(pEvent));
    11001226                }
    11011227#endif
     
    11061232        }
    11071233    }
    1108     else if (watched == machineWindowWrapper()->machineWindow())
    1109     {
    1110         switch (e->type())
    1111         {
    1112 #if defined (Q_WS_WIN32)
    1113 #if defined (VBOX_GUI_USE_DDRAW)
    1114             case QEvent::Move:
    1115             {
    1116                 /*
    1117                  *  notification from our parent that it has moved. We need this
    1118                  *  in order to possibly adjust the direct screen blitting.
    1119                  */
    1120                 if (mFrameBuf)
    1121                     mFrameBuf->moveEvent ((QMoveEvent *) e);
     1234    else if (pWatched == machineWindowWrapper()->machineWindow())
     1235    {
     1236        switch (pEvent->type())
     1237        {
     1238#if 0 // TODO Move to normal specific event handler:
     1239            case QEvent::Resize:
     1240            {
     1241                /* Set the "guest needs to resize" hint. This hint is acted upon when (and only when)
     1242                 * the autoresize property is "true": */
     1243                mDoResize = isGuestSupportsGraphics() || machineWindowWrapper()->isTrueFullscreen();
     1244                if (!m_bIsMachineWindowResizeIgnored && isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
     1245                    QTimer::singleShot(300, this, SLOT(doResizeHint()));
    11221246                break;
    11231247            }
    11241248#endif
    1125             /*
    1126              *  install/uninstall low-level kbd hook on every
    1127              *  activation/deactivation to:
    1128              *  a) avoid excess hook calls when we're not active and
    1129              *  b) be always in front of any other possible hooks
    1130              */
    1131             case QEvent::WindowActivate:
    1132             {
    1133                 gKbdHook = SetWindowsHookEx (WH_KEYBOARD_LL, lowLevelKeyboardProc,
    1134                                               GetModuleHandle (NULL), 0);
    1135                 AssertMsg (gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));
    1136                 break;
    1137             }
    1138             case QEvent::WindowDeactivate:
    1139             {
    1140                 if (gKbdHook)
    1141                 {
    1142                     UnhookWindowsHookEx (gKbdHook);
    1143                     gKbdHook = NULL;
    1144                 }
    1145                 break;
    1146             }
    1147 #endif /* defined (Q_WS_WIN32) */
    1148 #if defined (Q_WS_MAC)
    1149             /*
    1150              *  Install/remove the keyboard event handler.
    1151              */
    1152             case QEvent::WindowActivate:
    1153                 darwinGrabKeyboardEvents (true);
    1154                 break;
    1155             case QEvent::WindowDeactivate:
    1156                 darwinGrabKeyboardEvents (false);
    1157                 break;
    1158 #endif /* defined (Q_WS_MAC) */
    1159             #if 0
    1160             // TODO check that!
    1161             case QEvent::Resize:
    1162             {
    1163                 /* Set the "guest needs to resize" hint.  This hint is acted upon
    1164                  * when (and only when) the autoresize property is "true". */
    1165                 mDoResize = m_bIsGuestSupportsGraphics || machineWindowWrapper()->isTrueFullscreen();
    1166                 if (!m_bIsMachineWindowResizeIgnored &&
    1167                     m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled)
    1168                     QTimer::singleShot (300, this, SLOT (doResizeHint()));
    1169                 break;
    1170             }
    1171             #endif
    11721249            case QEvent::WindowStateChange:
    11731250            {
    11741251                /* During minimizing and state restoring machineWindowWrapper() gets the focus
    11751252                 * which belongs to console view window, so returning it properly. */
    1176                 QWindowStateChangeEvent *ev = static_cast <QWindowStateChangeEvent*> (e);
    1177                 if (ev->oldState() & Qt::WindowMinimized)
     1253                QWindowStateChangeEvent *pWindowEvent = static_cast<QWindowStateChangeEvent*>(pEvent);
     1254                if (pWindowEvent->oldState() & Qt::WindowMinimized)
    11781255                {
    11791256                    if (QApplication::focusWidget())
     
    11821259                        qApp->processEvents();
    11831260                    }
    1184                     QTimer::singleShot (0, this, SLOT (setFocus()));
     1261                    QTimer::singleShot(0, this, SLOT(setFocus()));
    11851262                }
    11861263                break;
    11871264            }
    1188 
     1265#if defined (Q_WS_WIN32)
     1266#if defined (VBOX_GUI_USE_DDRAW)
     1267            case QEvent::Move:
     1268            {
     1269                /* Notification from our parent that it has moved. We need this in order
     1270                 * to possibly adjust the direct screen blitting: */
     1271                if (m_pFrameBuffer)
     1272                    m_pFrameBuffer->moveEvent(static_cast<QMoveEvent*>(pEvent));
     1273                break;
     1274            }
     1275#endif
     1276            /* Install/uninstall low-level kbd hook on every activation/deactivation to:
     1277             * a) avoid excess hook calls when we're not active and
     1278             * b) be always in front of any other possible hooks */
     1279            case QEvent::WindowActivate:
     1280            {
     1281                gKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0);
     1282                AssertMsg(gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));
     1283                break;
     1284            }
     1285            case QEvent::WindowDeactivate:
     1286            {
     1287                if (gKbdHook)
     1288                {
     1289                    UnhookWindowsHookEx(gKbdHook);
     1290                    gKbdHook = NULL;
     1291                }
     1292                break;
     1293            }
     1294#endif /* defined (Q_WS_WIN32) */
     1295#if defined (Q_WS_MAC)
     1296            /* Install/remove the keyboard event handler: */
     1297            case QEvent::WindowActivate:
     1298                darwinGrabKeyboardEvents(true);
     1299                break;
     1300            case QEvent::WindowDeactivate:
     1301                darwinGrabKeyboardEvents(false);
     1302                break;
     1303#endif /* defined (Q_WS_MAC) */
    11891304            default:
    11901305                break;
    11911306        }
    11921307    }
    1193     #if 0 // TODO check that
    1194     else if (watched == machineWindowWrapper()->menuBar())
    1195     {
    1196         /*
    1197          *  sometimes when we press ESC in the menu it brings the
    1198          *  focus away (Qt bug?) causing no widget to have a focus,
    1199          *  or holds the focus itself, instead of returning the focus
    1200          *  to the console window. here we fix this.
    1201          */
    1202         switch (e->type())
     1308#if 0 // TODO Move to normal specific event handler:
     1309    else if (pWatched == machineWindowWrapper()->menuBar())
     1310    {
     1311        /* Sometimes when we press ESC in the menu it brings the focus away (Qt bug?)
     1312         * causing no widget to have a focus, or holds the focus itself, instead of
     1313         * returning the focus to the console window. Here we fix this: */
     1314        switch (pEvent->type())
    12031315        {
    12041316            case QEvent::FocusOut:
     
    12101322            case QEvent::KeyPress:
    12111323            {
    1212                 QKeyEvent *ke = (QKeyEvent *) e;
    1213                 if (ke->key() == Qt::Key_Escape && (ke->modifiers() == Qt::NoModifier))
     1324                QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
     1325                if (pKeyEvent->key() == Qt::Key_Escape && (pKeyEvent->modifiers() == Qt::NoModifier))
    12141326                    if (machineWindowWrapper()->menuBar()->hasFocus())
    12151327                        setFocus();
     
    12201332        }
    12211333    }
    1222     #endif
    1223 
    1224     return QAbstractScrollArea::eventFilter (watched, e);
    1225 }
    1226 
    1227 #if defined(Q_WS_WIN32)
    1228 
    1229 bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event)
    1230 {
    1231     /* Sometimes it happens that Win inserts additional events on some key
    1232      * press/release. For example, it prepends ALT_GR in German layout with
    1233      * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
    1234      * to specially treat ALT_GR to enter additional chars to regular apps).
    1235      * These events are definitely unwanted in VM, so filter them out. */
    1236     /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
    1237      * code 0x23a. If this is not passed through then it is impossible to
    1238      * cancel CapsLock on a French keyboard.  I didn't find any other examples
    1239      * of these strange events.  Let's hope we are not missing anything else
    1240      * of importance! */
    1241     if (hasFocus() && (event.scanCode & ~0xFF))
    1242     {
    1243         if (event.vkCode == VK_CAPITAL)
    1244             return false;
    1245         else
    1246             return true;
    1247     }
    1248 
    1249     if (!m_bIsKeyboardCaptured)
    1250         return false;
    1251 
    1252     /* it's possible that a key has been pressed while the keyboard was not
    1253      * captured, but is being released under the capture. Detect this situation
    1254      * and return false to let Windows process the message normally and update
    1255      * its key state table (to avoid the stuck key effect). */
    1256     uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed;
    1257     if ((event.flags & 0x80) /* released */ &&
    1258         ((event.vkCode == m_globalSettings.hostKey() && !hostkey_in_capture) ||
    1259          (mPressedKeys [event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed))
    1260         return false;
    1261 
    1262     MSG message;
    1263     message.hwnd = winId();
    1264     message.message = msg;
    1265     message.wParam = event.vkCode;
    1266     message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24;
    1267 
    1268     /* Windows sets here the extended bit when the Right Shift key is pressed,
    1269      * which is totally wrong. Undo it. */
    1270     if (event.vkCode == VK_RSHIFT)
    1271         message.lParam &= ~0x1000000;
    1272 
    1273     /* we suppose here that this hook is always called on the main GUI thread */
    1274     long dummyResult;
    1275     return winEvent(&message, &dummyResult);
    1276 }
    1277 
    1278 bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */)
    1279 {
    1280     if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN ||
    1281           aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP))
    1282         return false;
    1283 
    1284     /* Check for the special flag possibly set at the end of this function */
    1285     if (aMsg->lParam & (0x1 << 25))
    1286     {
    1287         aMsg->lParam &= ~(0x1 << 25);
    1288         return false;
    1289     }
    1290 
    1291     int scan = (aMsg->lParam >> 16) & 0x7F;
    1292     /* scancodes 0x80 and 0x00 are ignored */
    1293     if (!scan)
    1294         return true;
    1295 
    1296     int vkey = aMsg->wParam;
    1297 
    1298     /* When one of the SHIFT keys is held and one of the cursor movement
    1299      * keys is pressed, Windows duplicates SHIFT press/release messages,
    1300      * but with the virtual key code set to 0xFF. These virtual keys are also
    1301      * sent in some other situations (Pause, PrtScn, etc.). Ignore such
    1302      * messages. */
    1303     if (vkey == 0xFF)
    1304         return true;
    1305 
    1306     int flags = 0;
    1307     if (aMsg->lParam & 0x1000000)
    1308         flags |= KeyExtended;
    1309     if (!(aMsg->lParam & 0x80000000))
    1310         flags |= KeyPressed;
    1311 
    1312     switch (vkey)
    1313     {
    1314         case VK_SHIFT:
    1315         case VK_CONTROL:
    1316         case VK_MENU:
    1317         {
    1318             /* overcome stupid Win32 modifier key generalization */
    1319             int keyscan = scan;
    1320             if (flags & KeyExtended)
    1321                 keyscan |= 0xE000;
    1322             switch (keyscan)
    1323             {
    1324                 case 0x002A: vkey = VK_LSHIFT; break;
    1325                 case 0x0036: vkey = VK_RSHIFT; break;
    1326                 case 0x001D: vkey = VK_LCONTROL; break;
    1327                 case 0xE01D: vkey = VK_RCONTROL; break;
    1328                 case 0x0038: vkey = VK_LMENU; break;
    1329                 case 0xE038: vkey = VK_RMENU; break;
    1330             }
    1331             break;
    1332         }
    1333         case VK_NUMLOCK:
    1334             /* Win32 sets the extended bit for the NumLock key. Reset it. */
    1335             flags &= ~KeyExtended;
    1336             break;
    1337         case VK_SNAPSHOT:
    1338             flags |= KeyPrint;
    1339             break;
    1340         case VK_PAUSE:
    1341             flags |= KeyPause;
    1342             break;
    1343     }
    1344 
    1345     bool result = keyEvent(vkey, scan, flags);
    1346     if (!result && m_bIsKeyboardCaptured)
    1347     {
    1348         /* keyEvent() returned that it didn't process the message, but since the
    1349          * keyboard is captured, we don't want to pass it to Windows. We just want
    1350          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    1351          * shortcuts for example). So send it direcltly to the window with the
    1352          * special flag in the reserved area of lParam (to avoid recursion). */
    1353         ::SendMessage(aMsg->hwnd, aMsg->message,
    1354                       aMsg->wParam, aMsg->lParam | (0x1 << 25));
    1355         return true;
    1356     }
    1357 
    1358     /* These special keys have to be handled by Windows as well to update the
    1359      * internal modifier state and to enable/disable the keyboard LED */
    1360     if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT)
    1361         return false;
    1362 
    1363     return result;
    1364 }
    1365 
    1366 #elif defined (Q_WS_PM)
    1367 
    1368 bool UIMachineView::pmEvent(QMSG *aMsg)
    1369 {
    1370     if (aMsg->msg == UM_PREACCEL_CHAR)
    1371     {
    1372         /* We are inside the input hook
    1373          * let the message go through the normal system pipeline. */
    1374         if (!m_bIsKeyboardCaptured)
    1375             return false;
    1376     }
    1377 
    1378     if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR)
    1379         return false;
    1380 
    1381     /* check for the special flag possibly set at the end of this function */
    1382     if (SHORT2FROMMP(aMsg->mp2) & 0x8000)
    1383     {
    1384         aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000);
    1385         return false;
    1386     }
    1387 
    1388     USHORT ch = SHORT1FROMMP(aMsg->mp2);
    1389     USHORT f = SHORT1FROMMP(aMsg->mp1);
    1390 
    1391     int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1);
    1392     if (!scan || scan > 0x7F)
    1393         return true;
    1394 
    1395     int vkey = QIHotKeyEdit::virtualKey(aMsg);
    1396 
    1397     int flags = 0;
    1398 
    1399     if ((ch & 0xFF) == 0xE0)
    1400     {
    1401         flags |= KeyExtended;
    1402         scan = ch >> 8;
    1403     }
    1404     else if (scan == 0x5C && (ch & 0xFF) == '/')
    1405     {
    1406         /* this is the '/' key on the keypad */
    1407         scan = 0x35;
    1408         flags |= KeyExtended;
    1409     }
    1410     else
    1411     {
    1412         /* For some keys, the scan code passed in QMSG is a pseudo scan
    1413          * code. We replace it with a real hardware scan code, according to
    1414          * http://www.computer-engineering.org/ps2keyboard/scancodes1.html.
    1415          * Also detect Pause and PrtScn and set flags. */
    1416         switch (vkey)
    1417         {
    1418             case VK_ENTER:     scan = 0x1C; flags |= KeyExtended; break;
    1419             case VK_CTRL:      scan = 0x1D; flags |= KeyExtended; break;
    1420             case VK_ALTGRAF:   scan = 0x38; flags |= KeyExtended; break;
    1421             case VK_LWIN:      scan = 0x5B; flags |= KeyExtended; break;
    1422             case VK_RWIN:      scan = 0x5C; flags |= KeyExtended; break;
    1423             case VK_WINMENU:   scan = 0x5D; flags |= KeyExtended; break;
    1424             case VK_FORWARD:   scan = 0x69; flags |= KeyExtended; break;
    1425             case VK_BACKWARD:  scan = 0x6A; flags |= KeyExtended; break;
    1426 #if 0
    1427             /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully
    1428             // clear what is more correct
    1429             case VK_BREAK:     scan = 0x46; flags |= KeyExtended; break;
    1430 #else
    1431             case VK_BREAK:     scan = 0;    flags |= KeyPause; break;
    1432 #endif
    1433             case VK_PAUSE:     scan = 0;    flags |= KeyPause;    break;
    1434             case VK_PRINTSCRN: scan = 0;    flags |= KeyPrint;    break;
    1435             default:;
    1436         }
    1437     }
    1438 
    1439     if (!(f & KC_KEYUP))
    1440         flags |= KeyPressed;
    1441 
    1442     bool result = keyEvent (vkey, scan, flags);
    1443     if (!result && m_bIsKeyboardCaptured)
    1444     {
    1445         /* keyEvent() returned that it didn't process the message, but since the
    1446          * keyboard is captured, we don't want to pass it to PM. We just want
    1447          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    1448          * shortcuts for example). So send it direcltly to the window with the
    1449          * special flag in the reserved area of lParam (to avoid recursion). */
    1450         ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1,
    1451                       MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000));
    1452         return true;
    1453     }
    1454     return result;
    1455 }
    1456 
    1457 #elif defined(Q_WS_X11)
    1458 
    1459 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg)
    1460 {
    1461     XEvent *pKeyEvent = (XEvent *) pvArg;
    1462     if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode))
    1463         return True;
    1464     else
    1465         return False;
    1466 }
    1467 
    1468 bool UIMachineView::x11Event(XEvent *event)
    1469 {
    1470     switch (event->type)
    1471     {
    1472         /* We have to handle XFocusOut right here as this event is not passed
    1473          * to UIMachineView::event(). Handling this event is important for
    1474          * releasing the keyboard before the screen saver gets active. */
    1475         case XFocusOut:
    1476         case XFocusIn:
    1477             if (isRunning())
    1478                 focusEvent(event->type == XFocusIn);
    1479             return false;
    1480         case XKeyPress:
    1481         case XKeyRelease:
    1482             break;
    1483         default:
    1484             return false; /* pass the event to Qt */
    1485     }
    1486 
    1487     /* Translate the keycode to a PC scan code. */
    1488     unsigned scan = handleXKeyEvent(event);
    1489 
    1490     // scancodes 0x00 (no valid translation) and 0x80 are ignored
    1491     if (!scan & 0x7F)
    1492         return true;
    1493 
    1494     /* Fix for http://www.virtualbox.org/ticket/1296:
    1495      * when X11 sends events for repeated keys, it always inserts an
    1496      * XKeyRelease before the XKeyPress. */
    1497     XEvent returnEvent;
    1498     if ((event->type == XKeyRelease) && (XCheckIfEvent(event->xkey.display, &returnEvent,
    1499         VBoxConsoleViewCompEvent, (XPointer) event) == True))
    1500     {
    1501         XPutBackEvent(event->xkey.display, &returnEvent);
    1502         /* Discard it, don't pass it to Qt. */
    1503         return true;
    1504     }
    1505 
    1506     KeySym ks = ::XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0);
    1507 
    1508     int flags = 0;
    1509     if (scan >> 8)
    1510         flags |= KeyExtended;
    1511     if (event->type == XKeyPress)
    1512         flags |= KeyPressed;
    1513 
    1514     /* Remove the extended flag */
    1515     scan &= 0x7F;
    1516 
    1517     switch (ks)
    1518     {
    1519         case XK_Print:
    1520             flags |= KeyPrint;
    1521             break;
    1522         case XK_Pause:
    1523             flags |= KeyPause;
    1524             break;
    1525     }
    1526 
    1527     return keyEvent(ks, scan, flags);
    1528 }
    1529 
    1530 #elif defined (Q_WS_MAC)
    1531 
    1532 bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
    1533 {
    1534     bool ret = false;
    1535     UInt32 EventKind = ::GetEventKind(inEvent);
    1536     if (EventKind != kEventRawKeyModifiersChanged)
    1537     {
    1538         /* convert keycode to set 1 scan code. */
    1539         UInt32 keyCode = ~0U;
    1540         ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
    1541         unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode);
    1542         if (scanCode)
    1543         {
    1544             /* calc flags. */
    1545             int flags = 0;
    1546             if (EventKind != kEventRawKeyUp)
    1547                 flags |= KeyPressed;
    1548             if (scanCode & VBOXKEY_EXTENDED)
    1549                 flags |= KeyExtended;
    1550             /** @todo KeyPause, KeyPrint. */
    1551             scanCode &= VBOXKEY_SCANCODE_MASK;
    1552 
    1553             /* get the unicode string (if present). */
    1554             AssertCompileSize(wchar_t, 2);
    1555             AssertCompileSize(UniChar, 2);
    1556             ByteCount cbWritten = 0;
    1557             wchar_t ucs[8];
    1558             if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL,
    1559                                     sizeof(ucs), &cbWritten, &ucs[0]) != 0)
    1560                 cbWritten = 0;
    1561             ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */
    1562 
    1563             ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL);
    1564         }
    1565     }
    1566     else
    1567     {
    1568         /* May contain multiple modifier changes, kind of annoying. */
    1569         UInt32 newMask = 0;
    1570         ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
    1571                             sizeof(newMask), NULL, &newMask);
    1572         newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent);
    1573         UInt32 changed = newMask ^ mDarwinKeyModifiers;
    1574         if (changed)
    1575         {
    1576             for (UInt32 bit = 0; bit < 32; bit++)
    1577             {
    1578                 if (!(changed & (1 << bit)))
    1579                     continue;
    1580                 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit);
    1581                 if (!scanCode)
    1582                     continue;
    1583                 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit);
    1584                 Assert(keyCode);
    1585 
    1586                 if (!(scanCode & VBOXKEY_LOCK))
    1587                 {
    1588                     unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0;
    1589                     if (scanCode & VBOXKEY_EXTENDED)
    1590                         flags |= KeyExtended;
    1591                     scanCode &= VBOXKEY_SCANCODE_MASK;
    1592                     ret |= keyEvent(keyCode, scanCode & 0xff, flags);
    1593                 }
    1594                 else
    1595                 {
    1596                     unsigned flags = 0;
    1597                     if (scanCode & VBOXKEY_EXTENDED)
    1598                         flags |= KeyExtended;
    1599                     scanCode &= VBOXKEY_SCANCODE_MASK;
    1600                     keyEvent(keyCode, scanCode, flags | KeyPressed);
    1601                     keyEvent(keyCode, scanCode, flags);
    1602                 }
    1603             }
    1604         }
    1605 
    1606         mDarwinKeyModifiers = newMask;
    1607 
    1608         /* Always return true here because we'll otherwise getting a Qt event
    1609            we don't want and that will only cause the Pause warning to pop up. */
    1610         ret = true;
    1611     }
    1612 
    1613     return ret;
    1614 }
    1615 
    1616 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab)
    1617 {
    1618     mKeyboardGrabbed = fGrab;
    1619     if (fGrab)
    1620     {
    1621         /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
    1622         ::CGSetLocalEventsSuppressionInterval(0.0);
    1623         setMouseCoalescingEnabled(false);
    1624 
    1625         /* Register the event callback/hook and grab the keyboard. */
    1626 # ifdef QT_MAC_USE_COCOA
    1627         ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */
    1628                                             UIMachineView::darwinEventHandlerProc, this);
    1629 
    1630 # else /* QT_MAC_USE_COCOA */
    1631         EventTypeSpec eventTypes[6];
    1632         eventTypes[0].eventClass = kEventClassKeyboard;
    1633         eventTypes[0].eventKind  = kEventRawKeyDown;
    1634         eventTypes[1].eventClass = kEventClassKeyboard;
    1635         eventTypes[1].eventKind  = kEventRawKeyUp;
    1636         eventTypes[2].eventClass = kEventClassKeyboard;
    1637         eventTypes[2].eventKind  = kEventRawKeyRepeat;
    1638         eventTypes[3].eventClass = kEventClassKeyboard;
    1639         eventTypes[3].eventKind  = kEventRawKeyModifiersChanged;
    1640         /* For ignorning Command-H and Command-Q which aren't affected by the
    1641          * global hotkey stuff (doesn't work well): */
    1642         eventTypes[4].eventClass = kEventClassCommand;
    1643         eventTypes[4].eventKind  = kEventCommandProcess;
    1644         eventTypes[5].eventClass = kEventClassCommand;
    1645         eventTypes[5].eventKind  = kEventCommandUpdateStatus;
    1646 
    1647         EventHandlerUPP eventHandler = ::NewEventHandlerUPP(UIMachineView::darwinEventHandlerProc);
    1648 
    1649         mDarwinEventHandlerRef = NULL;
    1650         ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
    1651                                          this, &mDarwinEventHandlerRef);
    1652         ::DisposeEventHandlerUPP(eventHandler);
    1653 # endif /* !QT_MAC_USE_COCOA */
    1654 
    1655         ::DarwinGrabKeyboard (false);
    1656     }
    1657     else
    1658     {
    1659         ::DarwinReleaseKeyboard();
    1660 # ifdef QT_MAC_USE_COCOA
    1661         ::VBoxCocoaApplication_unsetCallback(UINT32_MAX, /** @todo fix mask */
    1662                                              UIMachineView::darwinEventHandlerProc, this);
    1663 # else /* QT_MAC_USE_COCOA */
    1664         if (mDarwinEventHandlerRef)
    1665         {
    1666             ::RemoveEventHandler(mDarwinEventHandlerRef);
    1667             mDarwinEventHandlerRef = NULL;
    1668         }
    1669 # endif /* !QT_MAC_USE_COCOA */
    1670     }
    1671 }
    1672 
    1673 #endif
    1674 
    1675 #if defined (Q_WS_WIN32)
    1676 static HHOOK gKbdHook = NULL;
    1677 static UIMachineView *gView = 0;
    1678 LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    1679 {
    1680     Assert (gView);
    1681     if (gView && nCode == HC_ACTION &&
    1682             gView->winLowKeyboardEvent (wParam, *(KBDLLHOOKSTRUCT *) lParam))
    1683         return 1;
    1684 
    1685     return CallNextHookEx (NULL, nCode, wParam, lParam);
    1686 }
    1687 #endif
    1688 
    1689 #if defined (Q_WS_MAC)
    1690 # ifdef QT_MAC_USE_COCOA
    1691 bool UIMachineView::darwinEventHandlerProc (const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
    1692 {
    1693     UIMachineView *view = (UIMachineView*)pvUser;
    1694     EventRef inEvent = (EventRef)pvCarbonEvent;
    1695     UInt32 eventClass = ::GetEventClass(inEvent);
    1696 
    1697     /* Check if this is an application key combo. In that case we will not pass
    1698        the event to the guest, but let the host process it. */
    1699     if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent))
    1700         return false;
    1701 
    1702     /* All keyboard class events needs to be handled. */
    1703     if (eventClass == kEventClassKeyboard)
    1704     {
    1705         if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
    1706             return true;
    1707     }
    1708     /* Pass the event along. */
    1709     return false;
    1710 }
    1711 
    1712 # else /* QT_MAC_USE_COCOA */
    1713 
    1714 pascal OSStatus UIMachineView::darwinEventHandlerProc (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
    1715 {
    1716     UIMachineView *view = static_cast<UIMachineView *> (inUserData);
    1717     UInt32 eventClass = ::GetEventClass (inEvent);
    1718 
    1719     /* Not sure but this seems an triggered event if the spotlight searchbar is
    1720      * displayed. So flag that the host key isn't pressed alone. */
    1721     if (eventClass == 'cgs ' && view->m_bIsHostkeyPressed && ::GetEventKind (inEvent) == 0x15)
    1722         view->m_bIsHostkeyAlone = false;
    1723 
    1724     if (eventClass == kEventClassKeyboard)
    1725     {
    1726         if (view->darwinKeyboardEvent (NULL, inEvent))
    1727             return 0;
    1728     }
    1729 
    1730     /*
    1731      * Command-H and Command-Q aren't properly disabled yet, and it's still
    1732      * possible to use the left command key to invoke them when the keyboard
    1733      * is captured. We discard the events these if the keyboard is captured
    1734      * as a half measure to prevent unexpected behaviour. However, we don't
    1735      * get any key down/up events, so these combinations are dead to the guest...
    1736      */
    1737     else if (eventClass == kEventClassCommand)
    1738     {
    1739         if (view->m_bIsKeyboardCaptured)
    1740             return 0;
    1741     }
    1742     return ::CallNextEventHandler(inHandlerCallRef, inEvent);
    1743 }
    1744 # endif /* !QT_MAC_USE_COCOA */
    1745 
    1746 #endif /* Q_WS_MAC */
    1747 
    1748 void UIMachineView::focusEvent(bool aHasFocus, bool aReleaseHostKey /* = true */)
    1749 {
    1750     if (aHasFocus)
    1751     {
    1752 #ifdef RT_OS_WINDOWS
     1334#endif
     1335
     1336    return QAbstractScrollArea::eventFilter (pWatched, pEvent);
     1337}
     1338
     1339void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */)
     1340{
     1341    if (fHasFocus)
     1342    {
     1343#ifdef Q_WS_WIN32
    17531344        if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture() && GetAncestor(winId(), GA_ROOT) == GetForegroundWindow())
    17541345#else
    17551346        if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture())
    1756 #endif /* RT_OS_WINDOWS */
     1347#endif
    17571348        {
    17581349            captureKbd(true);
    17591350        }
    17601351
    1761         /* reset the single-time disable capture flag */
     1352        /* Reset the single-time disable capture flag: */
    17621353        if (m_bIsAutoCaptureDisabled)
    17631354            m_bIsAutoCaptureDisabled = false;
     
    17671358        captureMouse(false);
    17681359        captureKbd(false, false);
    1769         releaseAllPressedKeys(aReleaseHostKey);
    1770     }
    1771 }
    1772 
    1773 bool UIMachineView::keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey /* = NULL */)
    1774 {
    1775     const bool isHostKey = aKey == m_globalSettings.hostKey();
     1360        releaseAllPressedKeys(fReleaseHostKey);
     1361    }
     1362}
     1363
     1364bool UIMachineView::keyEvent(int iKey, uint8_t uScan, int fFlags, wchar_t *pUniKey /* = NULL */)
     1365{
     1366    const bool isHostKey = iKey == m_globalSettings.hostKey();
    17761367
    17771368    LONG buf[16];
     
    17821373    if (!isHostKey && !m_bIsHostkeyPressed)
    17831374    {
    1784         if (aFlags & KeyPrint)
     1375        if (fFlags & KeyPrint)
    17851376        {
    17861377            static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 };
    17871378            static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA };
    1788             if (aFlags & KeyPressed)
     1379            if (fFlags & KeyPressed)
    17891380            {
    17901381                codes = PrintMake;
     
    17971388            }
    17981389        }
    1799         else if (aFlags & KeyPause)
    1800         {
    1801             if (aFlags & KeyPressed)
     1390        else if (fFlags & KeyPause)
     1391        {
     1392            if (fFlags & KeyPressed)
    18021393            {
    18031394                static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 };
     
    18131404        else
    18141405        {
    1815             if (aFlags & KeyPressed)
     1406            if (fFlags & KeyPressed)
    18161407            {
    18171408                /* Check if the guest has the same view on the modifier keys (NumLock,
     
    18221413
    18231414            /* Check if it's C-A-D and GUI/PassCAD is not true */
    1824             if (!mPassCAD &&
    1825                 aScan == 0x53 /* Del */ &&
    1826                 ((mPressedKeys [0x38] & IsKeyPressed) /* Alt */ ||
    1827                  (mPressedKeys [0x38] & IsExtKeyPressed)) &&
    1828                 ((mPressedKeys [0x1d] & IsKeyPressed) /* Ctrl */ ||
    1829                  (mPressedKeys [0x1d] & IsExtKeyPressed)))
     1415            if (!m_fPassCAD &&
     1416                uScan == 0x53 /* Del */ &&
     1417                ((m_pressedKeys[0x38] & IsKeyPressed) /* Alt */ ||
     1418                 (m_pressedKeys[0x38] & IsExtKeyPressed)) &&
     1419                ((m_pressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ ||
     1420                 (m_pressedKeys[0x1d] & IsExtKeyPressed)))
    18301421            {
    18311422                /* Use the C-A-D combination as a last resort to get the
     
    18361427                 * that's not possible because we cannot predict what other
    18371428                 * keys will be pressed next when one of C, A, D is held. */
    1838 
    18391429                if (isRunning() && m_bIsKeyboardCaptured)
    18401430                {
     
    18471437            }
    18481438
    1849             /* process the scancode and update the table of pressed keys */
     1439            /* Process the scancode and update the table of pressed keys: */
    18501440            whatPressed = IsKeyPressed;
    18511441
    1852             if (aFlags & KeyExtended)
     1442            if (fFlags & KeyExtended)
    18531443            {
    18541444                codes[count++] = 0xE0;
     
    18561446            }
    18571447
    1858             if (aFlags & KeyPressed)
    1859             {
    1860                 codes[count++] = aScan;
    1861                 mPressedKeys[aScan] |= whatPressed;
     1448            if (fFlags & KeyPressed)
     1449            {
     1450                codes[count++] = uScan;
     1451                m_pressedKeys[uScan] |= whatPressed;
    18621452            }
    18631453            else
    18641454            {
    1865                 /* if we haven't got this key's press message, we ignore its
    1866                  * release */
    1867                 if (!(mPressedKeys [aScan] & whatPressed))
     1455                /* If we haven't got this key's press message, we ignore its release: */
     1456                if (!(m_pressedKeys[uScan] & whatPressed))
    18681457                    return true;
    1869                 codes[count++] = aScan | 0x80;
    1870                 mPressedKeys[aScan] &= ~whatPressed;
     1458                codes[count++] = uScan | 0x80;
     1459                m_pressedKeys[uScan] &= ~whatPressed;
    18711460            }
    18721461
    18731462            if (m_bIsKeyboardCaptured)
    1874                 mPressedKeys[aScan] |= IsKbdCaptured;
     1463                m_pressedKeys[uScan] |= IsKbdCaptured;
    18751464            else
    1876                 mPressedKeys[aScan] &= ~IsKbdCaptured;
     1465                m_pressedKeys[uScan] &= ~IsKbdCaptured;
    18771466        }
    18781467    }
    18791468    else
    18801469    {
    1881         /* currently this is used in winLowKeyboardEvent() only */
    1882         hostkey_in_capture = m_bIsKeyboardCaptured;
     1470        /* Currently this is used in winLowKeyboardEvent() only: */
     1471        m_bHostkeyInCapture = m_bIsKeyboardCaptured;
    18831472    }
    18841473
     
    18861475    int hotkey = 0;
    18871476
    1888     /* process the host key */
    1889     if (aFlags & KeyPressed)
     1477    /* Process the host key: */
     1478    if (fFlags & KeyPressed)
    18901479    {
    18911480        if (isHostKey)
     
    19051494                if (m_bIsHostkeyAlone)
    19061495                {
    1907                     hotkey = aKey;
     1496                    hotkey = iKey;
    19081497                    m_bIsHostkeyAlone = false;
    19091498                }
     
    19871576        bool processed = false;
    19881577#if defined (Q_WS_WIN32)
    1989         NOREF(aUniKey);
    1990         int n = GetKeyboardLayoutList (0, NULL);
     1578        NOREF(pUniKey);
     1579        int n = GetKeyboardLayoutList(0, NULL);
    19911580        Assert (n);
    1992         HKL *list = new HKL [n];
    1993         GetKeyboardLayoutList (n, list);
     1581        HKL *list = new HKL[n];
     1582        GetKeyboardLayoutList(n, list);
    19941583        for (int i = 0; i < n && !processed; i++)
    19951584        {
    19961585            wchar_t ch;
    1997             static BYTE keys [256] = {0};
    1998             if (!ToUnicodeEx (hotkey, 0, keys, &ch, 1, 0, list [i]) == 1)
     1586            static BYTE keys[256] = {0};
     1587            if (!ToUnicodeEx(hotkey, 0, keys, &ch, 1, 0, list[i]) == 1)
    19991588                ch = 0;
    20001589            if (ch)
    2001                 processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    2002                                                 QChar (ch).toUpper().unicode()),
    2003                                            machineWindowWrapper()->menuBar()->actions());
     1590                processed = processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(ch).toUpper().unicode()),
     1591                                          machineWindowWrapper()->menuBar()->actions());
    20041592        }
    20051593        delete[] list;
    20061594#elif defined (Q_WS_X11)
    2007         NOREF(aUniKey);
     1595        NOREF(pUniKey);
    20081596        Display *display = QX11Info::display();
    20091597        int keysyms_per_keycode = getKeysymsPerKeycode();
    2010         KeyCode kc = XKeysymToKeycode (display, aKey);
    2011         // iterate over the first level (not shifted) keysyms in every group
     1598        KeyCode kc = XKeysymToKeycode (display, iKey);
    20121599        for (int i = 0; i < keysyms_per_keycode && !processed; i += 2)
    20131600        {
    2014             KeySym ks = XKeycodeToKeysym (display, kc, i);
     1601            KeySym ks = XKeycodeToKeysym(display, kc, i);
    20151602            char ch = 0;
    2016             if (!XkbTranslateKeySym (display, &ks, 0, &ch, 1, NULL) == 1)
     1603            if (!XkbTranslateKeySym(display, &ks, 0, &ch, 1, NULL) == 1)
    20171604                ch = 0;
    20181605            if (ch)
    2019             {
    2020                 QChar c = QString::fromLocal8Bit (&ch, 1) [0];
    2021             }
     1606                QChar c = QString::fromLocal8Bit(&ch, 1)[0];
    20221607        }
    20231608#elif defined (Q_WS_MAC)
    20241609        // TODO_NEW_CORE
    2025 //        if (aUniKey && aUniKey [0] && !aUniKey [1])
    2026 //            processed = processHotKey (QKeySequence (Qt::UNICODE_ACCEL +
    2027 //                                                     QChar (aUniKey [0]).toUpper().unicode()),
    2028 //                                       machineWindowWrapper()->menuBar()->actions());
     1610//        if (pUniKey && pUniKey [0] && !pUniKey [1])
     1611//            processed = processHotKey(QKeySequence (Qt::UNICODE_ACCEL + QChar(pUniKey[0]).toUpper().unicode()),
     1612//                                      machineWindowWrapper()->menuBar()->actions());
    20291613
    20301614        /* Don't consider the hot key as pressed since the guest never saw
    20311615         * it. (probably a generic thing) */
    2032         mPressedKeys [aScan] &= ~whatPressed;
    2033 #endif
    2034 
    2035         /* grab the key from Qt if processed, or pass it to Qt otherwise
     1616        m_pressedKeys[uScan] &= ~whatPressed;
     1617#endif
     1618
     1619        /* Grab the key from Qt if processed, or pass it to Qt otherwise
    20361620         * in order to process non-alphanumeric keys in event(), after they are
    20371621         * converted to Qt virtual keys. */
     
    20391623    }
    20401624
    2041     /* no more to do, if the host key is in action or the VM is paused */
     1625    /* No more to do, if the host key is in action or the VM is paused: */
    20421626    if (m_bIsHostkeyPressed || isHostKey || machineWindowWrapper()->machineLogic()->isPaused())
    20431627    {
    2044         /* grab the key from Qt and from VM if it's a host key,
     1628        /* Grab the key from Qt and from VM if it's a host key,
    20451629         * otherwise just pass it to Qt */
    20461630        return isHostKey;
     
    20481632
    20491633    CKeyboard keyboard = m_console.GetKeyboard();
    2050     Assert (!keyboard.isNull());
     1634    Assert(!keyboard.isNull());
    20511635
    20521636#if defined (Q_WS_WIN32)
    20531637    /* send pending WM_PAINT events */
    2054     ::UpdateWindow (viewport()->winId());
     1638    ::UpdateWindow(viewport()->winId());
    20551639#endif
    20561640
    20571641    std::vector <LONG> scancodes(codes, &codes[count]);
    2058     keyboard.PutScancodes (QVector<LONG>::fromStdVector(scancodes));
    2059 
    2060     /* grab the key from Qt */
     1642    keyboard.PutScancodes(QVector<LONG>::fromStdVector(scancodes));
     1643
     1644    /* Grab the key from Qt: */
    20611645    return true;
    20621646}
     
    20661650                               int aWheelDelta, Qt::Orientation aWheelDir)
    20671651{
    2068 #if 1
     1652#if 0
    20691653    LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n",
    20701654             __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(),
     
    21231707
    21241708        CMouse mouse = m_console.GetMouse();
    2125         mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(),
    2126                              aGlobalPos.y() - mLastPos.y(),
    2127                              wheelVertical, wheelHorizontal, state);
     1709        mouse.PutMouseEvent(aGlobalPos.x() - m_lastMousePos.x(),
     1710                            aGlobalPos.y() - m_lastMousePos.y(),
     1711                            wheelVertical, wheelHorizontal, state);
    21281712
    21291713#if defined (Q_WS_MAC)
     
    21561740
    21571741        if (rect.contains (aGlobalPos, true))
    2158             mLastPos = aGlobalPos;
     1742            m_lastMousePos = aGlobalPos;
    21591743        else
    21601744        {
    2161             mLastPos = rect.center();
    2162             QCursor::setPos (mLastPos);
    2163         }
    2164 
     1745            m_lastMousePos = rect.center();
     1746            QCursor::setPos (m_lastMousePos);
     1747        }
    21651748#else /* !Q_WS_MAC */
    21661749
     
    21681751         * to simulate the endless moving */
    21691752
    2170 #ifdef Q_WS_WIN32
     1753# ifdef Q_WS_WIN32
    21711754        int we = viewport()->width() - 1;
    21721755        int he = viewport()->height() - 1;
     
    21831766        if (p != aPos)
    21841767        {
    2185             mLastPos = viewport()->mapToGlobal (p);
    2186             QCursor::setPos (mLastPos);
     1768            m_lastMousePos = viewport()->mapToGlobal (p);
     1769            QCursor::setPos (m_lastMousePos);
    21871770        }
    21881771        else
    21891772        {
    2190             mLastPos = aGlobalPos;
    2191         }
    2192 #else
     1773            m_lastMousePos = aGlobalPos;
     1774        }
     1775# else
    21931776        int we = QApplication::desktop()->width() - 1;
    21941777        int he = QApplication::desktop()->height() - 1;
     
    22051788        if (p != aGlobalPos)
    22061789        {
    2207             mLastPos =  p;
    2208             QCursor::setPos (mLastPos);
     1790            m_lastMousePos =  p;
     1791            QCursor::setPos (m_lastMousePos);
    22091792        }
    22101793        else
    22111794        {
    2212             mLastPos = aGlobalPos;
    2213         }
    2214 #endif
     1795            m_lastMousePos = aGlobalPos;
     1796        }
     1797# endif
    22151798#endif /* !Q_WS_MAC */
    22161799        return true; /* stop further event handling */
     
    22181801    else /* !m_bIsMouseCaptured */
    22191802    {
    2220         //if (machineWindowWrapper()->isTrueFullscreen()) // TODO check that!
    2221         {
    2222             if (mode != VBoxDefs::SDLMode)
    2223             {
    2224                 /* try to automatically scroll the guest canvas if the
    2225                  * mouse is on the screen border */
    2226                 /// @todo (r=dmik) better use a timer for autoscroll
    2227                 QRect scrGeo = QApplication::desktop()->screenGeometry (this);
    2228                 int dx = 0, dy = 0;
    2229                 if (scrGeo.width() < contentsWidth())
    2230                 {
    2231                     if (scrGeo.left() == aGlobalPos.x()) dx = -1;
    2232                     if (scrGeo.right() == aGlobalPos.x()) dx = +1;
    2233                 }
    2234                 if (scrGeo.height() < contentsHeight())
    2235                 {
    2236                     if (scrGeo.top() == aGlobalPos.y()) dy = -1;
    2237                     if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
    2238                 }
    2239                 if (dx || dy)
    2240                     scrollBy (dx, dy);
    2241             }
    2242         }
     1803#if 0 // TODO: Move that to fullscreen event-hjadler:
     1804        if (mode() != VBoxDefs::SDLMode)
     1805        {
     1806            /* try to automatically scroll the guest canvas if the
     1807             * mouse is on the screen border */
     1808            /// @todo (r=dmik) better use a timer for autoscroll
     1809            QRect scrGeo = QApplication::desktop()->screenGeometry (this);
     1810            int dx = 0, dy = 0;
     1811            if (scrGeo.width() < contentsWidth())
     1812            {
     1813                if (scrGeo.left() == aGlobalPos.x()) dx = -1;
     1814                if (scrGeo.right() == aGlobalPos.x()) dx = +1;
     1815            }
     1816            if (scrGeo.height() < contentsHeight())
     1817            {
     1818                if (scrGeo.top() == aGlobalPos.y()) dy = -1;
     1819                if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
     1820            }
     1821            if (dx || dy)
     1822                scrollBy(dx, dy);
     1823        }
     1824#endif
    22431825
    22441826        if (m_bIsMouseAbsolute && m_bIsMouseIntegrated)
     
    22471829            int vw = visibleWidth(), vh = visibleHeight();
    22481830
    2249             if (mode != VBoxDefs::SDLMode)
    2250             {
    2251                 /* try to automatically scroll the guest canvas if the
    2252                  * mouse goes outside its visible part */
     1831            if (mode() != VBoxDefs::SDLMode)
     1832            {
     1833                /* Try to automatically scroll the guest canvas if the
     1834                 * mouse goes outside its visible part: */
    22531835
    22541836                int dx = 0;
     
    22701852            mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical,
    22711853                                         wheelHorizontal, state);
    2272             return true; /* stop further event handling */
     1854            return true;
    22731855        }
    22741856        else
    22751857        {
    2276             if (hasFocus() &&
    2277                 (aType == QEvent::MouseButtonRelease &&
    2278                  aButtons == Qt::NoButton))
     1858            if (hasFocus() && (aType == QEvent::MouseButtonRelease && aButtons == Qt::NoButton))
    22791859            {
    22801860                if (machineWindowWrapper()->machineLogic()->isPaused())
     
    22841864                else if (isRunning())
    22851865                {
    2286                     /* temporarily disable auto capture that will take
    2287                      * place after this dialog is dismissed because
    2288                      * the capture state is to be defined by the
    2289                      * dialog result itself */
     1866                    /* Temporarily disable auto capture that will take place after this dialog is dismissed because
     1867                     * the capture state is to be defined by the dialog result itself: */
    22901868                    m_bIsAutoCaptureDisabled = true;
    22911869                    bool autoConfirmed = false;
     
    22931871                    if (autoConfirmed)
    22941872                        m_bIsAutoCaptureDisabled = false;
    2295                     /* otherwise, the disable flag will be reset in
    2296                      * the next console view's foucs in event (since
    2297                      * may happen asynchronously on some platforms,
    2298                      * after we return from this code) */
    2299 
     1873                    /* Otherwise, the disable flag will be reset in the next console view's foucs in event (since
     1874                     * may happen asynchronously on some platforms, after we return from this code): */
    23001875                    if (ok)
    23011876                    {
    23021877#ifdef Q_WS_X11
    2303                         /* make sure that pending FocusOut events from the
    2304                          * previous message box are handled, otherwise the
    2305                          * mouse is immediately ungrabbed again */
     1878                        /* Make sure that pending FocusOut events from the previous message box are handled,
     1879                         * otherwise the mouse is immediately ungrabbed again: */
    23061880                        qApp->processEvents();
    23071881#endif
    2308                         captureKbd (true);
    2309                         captureMouse (true);
     1882                        captureKbd(true);
     1883                        captureMouse(true);
    23101884                    }
    23111885                }
     
    23171891}
    23181892
    2319 void UIMachineView::resizeEvent(QResizeEvent *)
     1893void UIMachineView::resizeEvent(QResizeEvent *pEvent)
    23201894{
    23211895    updateSliders();
    23221896#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    2323     QRect r = viewport()->geometry();
    2324     PostBoundsChanged(r);
     1897    QRect rectangle = viewport()->geometry();
     1898    PostBoundsChanged(rectangle);
    23251899#endif /* Q_WS_MAC */
    2326 }
    2327 
    2328 void UIMachineView::moveEvent(QMoveEvent *)
     1900    return QAbstractScrollArea::resizeEvent(pEvent);
     1901}
     1902
     1903void UIMachineView::moveEvent(QMoveEvent *pEvent)
    23291904{
    23301905#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
     
    23321907    PostBoundsChanged (r);
    23331908#endif /* Q_WS_MAC */
    2334 }
    2335 
    2336 void UIMachineView::paintEvent(QPaintEvent *pe)
    2337 {
    2338     if (mPausedShot.isNull())
    2339     {
    2340         /* delegate the paint function to the VBoxFrameBuffer interface */
    2341         if (mFrameBuf)
    2342             mFrameBuf->paintEvent(pe);
     1909    return QAbstractScrollArea::moveEvent(pEvent);
     1910}
     1911
     1912void UIMachineView::paintEvent(QPaintEvent *pPaintEvent)
     1913{
     1914    if (m_pauseShot.isNull())
     1915    {
     1916        /* Delegate the paint function to the VBoxFrameBuffer interface: */
     1917        if (m_pFrameBuffer)
     1918            m_pFrameBuffer->paintEvent(pPaintEvent);
    23431919#ifdef Q_WS_MAC
    23441920        /* Update the dock icon if we are in the running state */
     
    23501926
    23511927#ifdef VBOX_GUI_USE_QUARTZ2D
    2352     if (mode == VBoxDefs::Quartz2DMode && mFrameBuf)
    2353     {
    2354         mFrameBuf->paintEvent(pe);
     1928    if (mode() == VBoxDefs::Quartz2DMode && m_pFrameBuffer)
     1929    {
     1930        m_pFrameBuffer->paintEvent(pPaintEvent);
    23551931        updateDockIcon();
    23561932    }
     
    23591935    {
    23601936        /* We have a snapshot for the paused state: */
    2361         QRect r = pe->rect().intersect (viewport()->rect());
     1937        QRect r = pPaintEvent->rect().intersect (viewport()->rect());
    23621938        /* We have to disable paint on screen if we are using the regular painter */
    23631939        bool paintOnScreen = viewport()->testAttribute(Qt::WA_PaintOnScreen);
    23641940        viewport()->setAttribute(Qt::WA_PaintOnScreen, false);
    23651941        QPainter pnt(viewport());
    2366         pnt.drawPixmap(r.x(), r.y(), mPausedShot,
    2367                        r.x() + contentsX(), r.y() + contentsY(),
    2368                        r.width(), r.height());
     1942        pnt.drawPixmap(r.x(), r.y(), m_pauseShot, r.x() + contentsX(), r.y() + contentsY(), r.width(), r.height());
    23691943        /* Restore the attribute to its previous state */
    23701944        viewport()->setAttribute(Qt::WA_PaintOnScreen, paintOnScreen);
     
    23751949}
    23761950
     1951#if defined(Q_WS_WIN32)
     1952
     1953static HHOOK gKbdHook = NULL;
     1954static UIMachineView *gView = 0;
     1955LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
     1956{
     1957    Assert(gView);
     1958    if (gView && nCode == HC_ACTION && gView->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT *)lParam))
     1959        return 1;
     1960
     1961    return CallNextHookEx(NULL, nCode, wParam, lParam);
     1962}
     1963
     1964bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event)
     1965{
     1966    /* Sometimes it happens that Win inserts additional events on some key
     1967     * press/release. For example, it prepends ALT_GR in German layout with
     1968     * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
     1969     * to specially treat ALT_GR to enter additional chars to regular apps).
     1970     * These events are definitely unwanted in VM, so filter them out. */
     1971    /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
     1972     * code 0x23a. If this is not passed through then it is impossible to
     1973     * cancel CapsLock on a French keyboard.  I didn't find any other examples
     1974     * of these strange events.  Let's hope we are not missing anything else
     1975     * of importance! */
     1976    if (hasFocus() && (event.scanCode & ~0xFF))
     1977    {
     1978        if (event.vkCode == VK_CAPITAL)
     1979            return false;
     1980        else
     1981            return true;
     1982    }
     1983
     1984    if (!m_bIsKeyboardCaptured)
     1985        return false;
     1986
     1987    /* it's possible that a key has been pressed while the keyboard was not
     1988     * captured, but is being released under the capture. Detect this situation
     1989     * and return false to let Windows process the message normally and update
     1990     * its key state table (to avoid the stuck key effect). */
     1991    uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed;
     1992    if ((event.flags & 0x80) /* released */ &&
     1993        ((event.vkCode == m_globalSettings.hostKey() && !m_bHostkeyInCapture) ||
     1994         (m_pressedKeys[event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed))
     1995        return false;
     1996
     1997    MSG message;
     1998    message.hwnd = winId();
     1999    message.message = msg;
     2000    message.wParam = event.vkCode;
     2001    message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24;
     2002
     2003    /* Windows sets here the extended bit when the Right Shift key is pressed,
     2004     * which is totally wrong. Undo it. */
     2005    if (event.vkCode == VK_RSHIFT)
     2006        message.lParam &= ~0x1000000;
     2007
     2008    /* we suppose here that this hook is always called on the main GUI thread */
     2009    long dummyResult;
     2010    return winEvent(&message, &dummyResult);
     2011}
     2012
     2013bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */)
     2014{
     2015    if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN ||
     2016          aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP))
     2017        return false;
     2018
     2019    /* Check for the special flag possibly set at the end of this function */
     2020    if (aMsg->lParam & (0x1 << 25))
     2021    {
     2022        aMsg->lParam &= ~(0x1 << 25);
     2023        return false;
     2024    }
     2025
     2026    int scan = (aMsg->lParam >> 16) & 0x7F;
     2027    /* scancodes 0x80 and 0x00 are ignored */
     2028    if (!scan)
     2029        return true;
     2030
     2031    int vkey = aMsg->wParam;
     2032
     2033    /* When one of the SHIFT keys is held and one of the cursor movement
     2034     * keys is pressed, Windows duplicates SHIFT press/release messages,
     2035     * but with the virtual key code set to 0xFF. These virtual keys are also
     2036     * sent in some other situations (Pause, PrtScn, etc.). Ignore such
     2037     * messages. */
     2038    if (vkey == 0xFF)
     2039        return true;
     2040
     2041    int flags = 0;
     2042    if (aMsg->lParam & 0x1000000)
     2043        flags |= KeyExtended;
     2044    if (!(aMsg->lParam & 0x80000000))
     2045        flags |= KeyPressed;
     2046
     2047    switch (vkey)
     2048    {
     2049        case VK_SHIFT:
     2050        case VK_CONTROL:
     2051        case VK_MENU:
     2052        {
     2053            /* overcome stupid Win32 modifier key generalization */
     2054            int keyscan = scan;
     2055            if (flags & KeyExtended)
     2056                keyscan |= 0xE000;
     2057            switch (keyscan)
     2058            {
     2059                case 0x002A: vkey = VK_LSHIFT; break;
     2060                case 0x0036: vkey = VK_RSHIFT; break;
     2061                case 0x001D: vkey = VK_LCONTROL; break;
     2062                case 0xE01D: vkey = VK_RCONTROL; break;
     2063                case 0x0038: vkey = VK_LMENU; break;
     2064                case 0xE038: vkey = VK_RMENU; break;
     2065            }
     2066            break;
     2067        }
     2068        case VK_NUMLOCK:
     2069            /* Win32 sets the extended bit for the NumLock key. Reset it. */
     2070            flags &= ~KeyExtended;
     2071            break;
     2072        case VK_SNAPSHOT:
     2073            flags |= KeyPrint;
     2074            break;
     2075        case VK_PAUSE:
     2076            flags |= KeyPause;
     2077            break;
     2078    }
     2079
     2080    bool result = keyEvent(vkey, scan, flags);
     2081    if (!result && m_bIsKeyboardCaptured)
     2082    {
     2083        /* keyEvent() returned that it didn't process the message, but since the
     2084         * keyboard is captured, we don't want to pass it to Windows. We just want
     2085         * to let Qt process the message (to handle non-alphanumeric <HOST>+key
     2086         * shortcuts for example). So send it direcltly to the window with the
     2087         * special flag in the reserved area of lParam (to avoid recursion). */
     2088        ::SendMessage(aMsg->hwnd, aMsg->message,
     2089                      aMsg->wParam, aMsg->lParam | (0x1 << 25));
     2090        return true;
     2091    }
     2092
     2093    /* These special keys have to be handled by Windows as well to update the
     2094     * internal modifier state and to enable/disable the keyboard LED */
     2095    if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT)
     2096        return false;
     2097
     2098    return result;
     2099}
     2100
     2101#elif defined(Q_WS_PM)
     2102
     2103bool UIMachineView::pmEvent(QMSG *aMsg)
     2104{
     2105    if (aMsg->msg == UM_PREACCEL_CHAR)
     2106    {
     2107        /* We are inside the input hook
     2108         * let the message go through the normal system pipeline. */
     2109        if (!m_bIsKeyboardCaptured)
     2110            return false;
     2111    }
     2112
     2113    if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR)
     2114        return false;
     2115
     2116    /* check for the special flag possibly set at the end of this function */
     2117    if (SHORT2FROMMP(aMsg->mp2) & 0x8000)
     2118    {
     2119        aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000);
     2120        return false;
     2121    }
     2122
     2123    USHORT ch = SHORT1FROMMP(aMsg->mp2);
     2124    USHORT f = SHORT1FROMMP(aMsg->mp1);
     2125
     2126    int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1);
     2127    if (!scan || scan > 0x7F)
     2128        return true;
     2129
     2130    int vkey = QIHotKeyEdit::virtualKey(aMsg);
     2131
     2132    int flags = 0;
     2133
     2134    if ((ch & 0xFF) == 0xE0)
     2135    {
     2136        flags |= KeyExtended;
     2137        scan = ch >> 8;
     2138    }
     2139    else if (scan == 0x5C && (ch & 0xFF) == '/')
     2140    {
     2141        /* this is the '/' key on the keypad */
     2142        scan = 0x35;
     2143        flags |= KeyExtended;
     2144    }
     2145    else
     2146    {
     2147        /* For some keys, the scan code passed in QMSG is a pseudo scan
     2148         * code. We replace it with a real hardware scan code, according to
     2149         * http://www.computer-engineering.org/ps2keyboard/scancodes1.html.
     2150         * Also detect Pause and PrtScn and set flags. */
     2151        switch (vkey)
     2152        {
     2153            case VK_ENTER:     scan = 0x1C; flags |= KeyExtended; break;
     2154            case VK_CTRL:      scan = 0x1D; flags |= KeyExtended; break;
     2155            case VK_ALTGRAF:   scan = 0x38; flags |= KeyExtended; break;
     2156            case VK_LWIN:      scan = 0x5B; flags |= KeyExtended; break;
     2157            case VK_RWIN:      scan = 0x5C; flags |= KeyExtended; break;
     2158            case VK_WINMENU:   scan = 0x5D; flags |= KeyExtended; break;
     2159            case VK_FORWARD:   scan = 0x69; flags |= KeyExtended; break;
     2160            case VK_BACKWARD:  scan = 0x6A; flags |= KeyExtended; break;
     2161#if 0
     2162            /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully
     2163            // clear what is more correct
     2164            case VK_BREAK:     scan = 0x46; flags |= KeyExtended; break;
     2165#else
     2166            case VK_BREAK:     scan = 0;    flags |= KeyPause; break;
     2167#endif
     2168            case VK_PAUSE:     scan = 0;    flags |= KeyPause;    break;
     2169            case VK_PRINTSCRN: scan = 0;    flags |= KeyPrint;    break;
     2170            default:;
     2171        }
     2172    }
     2173
     2174    if (!(f & KC_KEYUP))
     2175        flags |= KeyPressed;
     2176
     2177    bool result = keyEvent (vkey, scan, flags);
     2178    if (!result && m_bIsKeyboardCaptured)
     2179    {
     2180        /* keyEvent() returned that it didn't process the message, but since the
     2181         * keyboard is captured, we don't want to pass it to PM. We just want
     2182         * to let Qt process the message (to handle non-alphanumeric <HOST>+key
     2183         * shortcuts for example). So send it direcltly to the window with the
     2184         * special flag in the reserved area of lParam (to avoid recursion). */
     2185        ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1,
     2186                      MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000));
     2187        return true;
     2188    }
     2189    return result;
     2190}
     2191
     2192#elif defined(Q_WS_X11)
     2193
     2194static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg)
     2195{
     2196    XEvent *pKeyEvent = (XEvent*)pvArg;
     2197    if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode))
     2198        return True;
     2199    else
     2200        return False;
     2201}
     2202
     2203bool UIMachineView::x11Event(XEvent *pEvent)
     2204{
     2205    switch (pEvent->type)
     2206    {
     2207        /* We have to handle XFocusOut right here as this event is not passed
     2208         * to UIMachineView::event(). Handling this event is important for
     2209         * releasing the keyboard before the screen saver gets active. */
     2210        case XFocusOut:
     2211        case XFocusIn:
     2212            if (isRunning())
     2213                focusEvent(pEvent->type == XFocusIn);
     2214            return false;
     2215        case XKeyPress:
     2216        case XKeyRelease:
     2217            break;
     2218        default:
     2219            return false; /* pass the event to Qt */
     2220    }
     2221
     2222    /* Translate the keycode to a PC scan code. */
     2223    unsigned scan = handleXKeyEvent(pEvent);
     2224
     2225    /* scancodes 0x00 (no valid translation) and 0x80 are ignored */
     2226    if (!scan & 0x7F)
     2227        return true;
     2228
     2229    /* Fix for http://www.virtualbox.org/ticket/1296:
     2230     * when X11 sends events for repeated keys, it always inserts an
     2231     * XKeyRelease before the XKeyPress. */
     2232    XEvent returnEvent;
     2233    if ((pEvent->type == XKeyRelease) && (XCheckIfEvent(pEvent->xkey.display, &returnEvent,
     2234        VBoxConsoleViewCompEvent, (XPointer)pEvent) == True))
     2235    {
     2236        XPutBackEvent(pEvent->xkey.display, &returnEvent);
     2237        /* Discard it, don't pass it to Qt. */
     2238        return true;
     2239    }
     2240
     2241    KeySym ks = ::XKeycodeToKeysym(pEvent->xkey.display, pEvent->xkey.keycode, 0);
     2242
     2243    int flags = 0;
     2244    if (scan >> 8)
     2245        flags |= KeyExtended;
     2246    if (pEvent->type == XKeyPress)
     2247        flags |= KeyPressed;
     2248
     2249    /* Remove the extended flag */
     2250    scan &= 0x7F;
     2251
     2252    switch (ks)
     2253    {
     2254        case XK_Print:
     2255            flags |= KeyPrint;
     2256            break;
     2257        case XK_Pause:
     2258            flags |= KeyPause;
     2259            break;
     2260    }
     2261
     2262    return keyEvent(ks, scan, flags);
     2263}
     2264
     2265#elif defined(Q_WS_MAC)
     2266
     2267bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
     2268{
     2269    bool ret = false;
     2270    UInt32 EventKind = ::GetEventKind(inEvent);
     2271    if (EventKind != kEventRawKeyModifiersChanged)
     2272    {
     2273        /* convert keycode to set 1 scan code. */
     2274        UInt32 keyCode = ~0U;
     2275        ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
     2276        unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode);
     2277        if (scanCode)
     2278        {
     2279            /* calc flags. */
     2280            int flags = 0;
     2281            if (EventKind != kEventRawKeyUp)
     2282                flags |= KeyPressed;
     2283            if (scanCode & VBOXKEY_EXTENDED)
     2284                flags |= KeyExtended;
     2285            /** @todo KeyPause, KeyPrint. */
     2286            scanCode &= VBOXKEY_SCANCODE_MASK;
     2287
     2288            /* get the unicode string (if present). */
     2289            AssertCompileSize(wchar_t, 2);
     2290            AssertCompileSize(UniChar, 2);
     2291            ByteCount cbWritten = 0;
     2292            wchar_t ucs[8];
     2293            if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL,
     2294                                    sizeof(ucs), &cbWritten, &ucs[0]) != 0)
     2295                cbWritten = 0;
     2296            ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */
     2297
     2298            ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL);
     2299        }
     2300    }
     2301    else
     2302    {
     2303        /* May contain multiple modifier changes, kind of annoying. */
     2304        UInt32 newMask = 0;
     2305        ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
     2306                            sizeof(newMask), NULL, &newMask);
     2307        newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent);
     2308        UInt32 changed = newMask ^ m_darwinKeyModifiers;
     2309        if (changed)
     2310        {
     2311            for (UInt32 bit = 0; bit < 32; bit++)
     2312            {
     2313                if (!(changed & (1 << bit)))
     2314                    continue;
     2315                unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit);
     2316                if (!scanCode)
     2317                    continue;
     2318                unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit);
     2319                Assert(keyCode);
     2320
     2321                if (!(scanCode & VBOXKEY_LOCK))
     2322                {
     2323                    unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0;
     2324                    if (scanCode & VBOXKEY_EXTENDED)
     2325                        flags |= KeyExtended;
     2326                    scanCode &= VBOXKEY_SCANCODE_MASK;
     2327                    ret |= keyEvent(keyCode, scanCode & 0xff, flags);
     2328                }
     2329                else
     2330                {
     2331                    unsigned flags = 0;
     2332                    if (scanCode & VBOXKEY_EXTENDED)
     2333                        flags |= KeyExtended;
     2334                    scanCode &= VBOXKEY_SCANCODE_MASK;
     2335                    keyEvent(keyCode, scanCode, flags | KeyPressed);
     2336                    keyEvent(keyCode, scanCode, flags);
     2337                }
     2338            }
     2339        }
     2340
     2341        m_darwinKeyModifiers = newMask;
     2342
     2343        /* Always return true here because we'll otherwise getting a Qt event
     2344           we don't want and that will only cause the Pause warning to pop up. */
     2345        ret = true;
     2346    }
     2347
     2348    return ret;
     2349}
     2350
     2351void UIMachineView::darwinGrabKeyboardEvents(bool fGrab)
     2352{
     2353    m_fKeyboardGrabbed = fGrab;
     2354    if (fGrab)
     2355    {
     2356        /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
     2357        ::CGSetLocalEventsSuppressionInterval(0.0);
     2358        setMouseCoalescingEnabled(false);
     2359
     2360        /* Register the event callback/hook and grab the keyboard. */
     2361# ifdef QT_MAC_USE_COCOA
     2362        ::VBoxCocoaApplication_setCallback (UINT32_MAX, /** @todo fix mask */
     2363                                            UIMachineView::darwinEventHandlerProc, this);
     2364
     2365# else /* QT_MAC_USE_COCOA */
     2366        EventTypeSpec eventTypes[6];
     2367        eventTypes[0].eventClass = kEventClassKeyboard;
     2368        eventTypes[0].eventKind  = kEventRawKeyDown;
     2369        eventTypes[1].eventClass = kEventClassKeyboard;
     2370        eventTypes[1].eventKind  = kEventRawKeyUp;
     2371        eventTypes[2].eventClass = kEventClassKeyboard;
     2372        eventTypes[2].eventKind  = kEventRawKeyRepeat;
     2373        eventTypes[3].eventClass = kEventClassKeyboard;
     2374        eventTypes[3].eventKind  = kEventRawKeyModifiersChanged;
     2375        /* For ignorning Command-H and Command-Q which aren't affected by the
     2376         * global hotkey stuff (doesn't work well): */
     2377        eventTypes[4].eventClass = kEventClassCommand;
     2378        eventTypes[4].eventKind  = kEventCommandProcess;
     2379        eventTypes[5].eventClass = kEventClassCommand;
     2380        eventTypes[5].eventKind  = kEventCommandUpdateStatus;
     2381
     2382        EventHandlerUPP eventHandler = ::NewEventHandlerUPP(UIMachineView::darwinEventHandlerProc);
     2383
     2384        m_darwinEventHandlerRef = NULL;
     2385        ::InstallApplicationEventHandler(eventHandler, RT_ELEMENTS (eventTypes), &eventTypes[0],
     2386                                         this, &m_darwinEventHandlerRef);
     2387        ::DisposeEventHandlerUPP(eventHandler);
     2388# endif /* !QT_MAC_USE_COCOA */
     2389
     2390        ::DarwinGrabKeyboard (false);
     2391    }
     2392    else
     2393    {
     2394        ::DarwinReleaseKeyboard();
     2395# ifdef QT_MAC_USE_COCOA
     2396        ::VBoxCocoaApplication_unsetCallback(UINT32_MAX, /** @todo fix mask */
     2397                                             UIMachineView::darwinEventHandlerProc, this);
     2398# else /* QT_MAC_USE_COCOA */
     2399        if (m_darwinEventHandlerRef)
     2400        {
     2401            ::RemoveEventHandler(m_darwinEventHandlerRef);
     2402            m_darwinEventHandlerRef = NULL;
     2403        }
     2404# endif /* !QT_MAC_USE_COCOA */
     2405    }
     2406}
     2407
     2408# ifdef QT_MAC_USE_COCOA
     2409bool UIMachineView::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
     2410{
     2411    UIMachineView *view = (UIMachineView*)pvUser;
     2412    EventRef inEvent = (EventRef)pvCarbonEvent;
     2413    UInt32 eventClass = ::GetEventClass(inEvent);
     2414
     2415    /* Check if this is an application key combo. In that case we will not pass
     2416     * the event to the guest, but let the host process it. */
     2417    if (VBoxCocoaApplication_isApplicationCommand(pvCocoaEvent))
     2418        return false;
     2419
     2420    /* All keyboard class events needs to be handled. */
     2421    if (eventClass == kEventClassKeyboard)
     2422    {
     2423        if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
     2424            return true;
     2425    }
     2426    /* Pass the event along. */
     2427    return false;
     2428}
     2429# else /* QT_MAC_USE_COCOA */
     2430
     2431pascal OSStatus UIMachineView::darwinEventHandlerProc(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
     2432{
     2433    UIMachineView *view = static_cast<UIMachineView *> (inUserData);
     2434    UInt32 eventClass = ::GetEventClass (inEvent);
     2435
     2436    /* Not sure but this seems an triggered event if the spotlight searchbar is
     2437     * displayed. So flag that the host key isn't pressed alone. */
     2438    if (eventClass == 'cgs ' && view->m_bIsHostkeyPressed && ::GetEventKind (inEvent) == 0x15)
     2439        view->m_bIsHostkeyAlone = false;
     2440
     2441    if (eventClass == kEventClassKeyboard)
     2442    {
     2443        if (view->darwinKeyboardEvent (NULL, inEvent))
     2444            return 0;
     2445    }
     2446
     2447    /*
     2448     * Command-H and Command-Q aren't properly disabled yet, and it's still
     2449     * possible to use the left command key to invoke them when the keyboard
     2450     * is captured. We discard the events these if the keyboard is captured
     2451     * as a half measure to prevent unexpected behaviour. However, we don't
     2452     * get any key down/up events, so these combinations are dead to the guest...
     2453     */
     2454    else if (eventClass == kEventClassCommand)
     2455    {
     2456        if (view->m_bIsKeyboardCaptured)
     2457            return 0;
     2458    }
     2459    return ::CallNextEventHandler(inHandlerCallRef, inEvent);
     2460}
     2461# endif /* !QT_MAC_USE_COCOA */
     2462
     2463#endif
     2464
    23772465void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount)
    23782466{
     
    23802468     * This function will add up to 6 additional keycodes to codes. */
    23812469
    2382 #if defined (Q_WS_X11)
     2470#if defined(Q_WS_X11)
    23832471
    23842472    Window   wDummy1, wDummy2;
     
    24032491    XFreeModifiermap(map);
    24042492
    2405     if (muNumLockAdaptionCnt && (mNumLock ^ !!(uMask & uKeyMaskNum)))
    2406     {
    2407         -- muNumLockAdaptionCnt;
     2493    if (m_uNumLockAdaptionCnt && (m_numLock ^ !!(uMask & uKeyMaskNum)))
     2494    {
     2495        -- m_uNumLockAdaptionCnt;
    24082496        piCodes[(*puCount)++] = 0x45;
    24092497        piCodes[(*puCount)++] = 0x45 | 0x80;
    24102498    }
    2411     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(uMask & uKeyMaskCaps)))
    2412     {
    2413         muCapsLockAdaptionCnt--;
     2499    if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(uMask & uKeyMaskCaps)))
     2500    {
     2501        m_uCapsLockAdaptionCnt--;
    24142502        piCodes[(*puCount)++] = 0x3a;
    24152503        piCodes[(*puCount)++] = 0x3a | 0x80;
     
    24172505         * capslock.  For simplicity, only do this if shift is not
    24182506         * already held down. */
    2419         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
     2507        if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed))
    24202508        {
    24212509            piCodes[(*puCount)++] = 0x2a;
     
    24242512    }
    24252513
    2426 #elif defined (Q_WS_WIN32)
    2427 
    2428     if (muNumLockAdaptionCnt && (mNumLock ^ !!(GetKeyState(VK_NUMLOCK))))
    2429     {
    2430         muNumLockAdaptionCnt--;
     2514#elif defined(Q_WS_WIN32)
     2515
     2516    if (m_uNumLockAdaptionCnt && (m_numLock ^ !!(GetKeyState(VK_NUMLOCK))))
     2517    {
     2518        m_uNumLockAdaptionCnt--;
    24312519        piCodes[(*puCount)++] = 0x45;
    24322520        piCodes[(*puCount)++] = 0x45 | 0x80;
    24332521    }
    2434     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(GetKeyState(VK_CAPITAL))))
    2435     {
    2436         muCapsLockAdaptionCnt--;
     2522    if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(GetKeyState(VK_CAPITAL))))
     2523    {
     2524        m_uCapsLockAdaptionCnt--;
    24372525        piCodes[(*puCount)++] = 0x3a;
    24382526        piCodes[(*puCount)++] = 0x3a | 0x80;
     
    24402528         * capslock.  For simplicity, only do this if shift is not
    24412529         * already held down. */
    2442         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
     2530        if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed))
    24432531        {
    24442532            piCodes[(*puCount)++] = 0x2a;
     
    24472535    }
    24482536
    2449 #elif defined (Q_WS_MAC)
    2450 
    2451     /* if (muNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */
    2452     if (muCapsLockAdaptionCnt && (mCapsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
    2453     {
    2454         muCapsLockAdaptionCnt--;
     2537#elif defined(Q_WS_MAC)
     2538
     2539    /* if (m_uNumLockAdaptionCnt) ... - NumLock isn't implemented by Mac OS X so ignore it. */
     2540    if (m_uCapsLockAdaptionCnt && (m_capsLock ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
     2541    {
     2542        m_uCapsLockAdaptionCnt--;
    24552543        piCodes[(*puCount)++] = 0x3a;
    24562544        piCodes[(*puCount)++] = 0x3a | 0x80;
     
    24582546         * capslock.  For simplicity, only do this if shift is not
    24592547         * already held down. */
    2460         if (mCapsLock && !(mPressedKeys [0x2a] & IsKeyPressed))
     2548        if (m_capsLock && !(m_pressedKeys[0x2a] & IsKeyPressed))
    24612549        {
    24622550            piCodes[(*puCount)++] = 0x2a;
     
    24722560}
    24732561
    2474 void UIMachineView::scrollBy(int dx, int dy)
    2475 {
    2476     horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
    2477     verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
    2478 }
    2479 
    24802562QPoint UIMachineView::viewportToContents(const QPoint &vp) const
    24812563{
     
    24882570    QSize m = maximumViewportSize();
    24892571
    2490     QSize v = QSize(mFrameBuf->width(), mFrameBuf->height());
     2572    QSize v = QSize(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    24912573    /* no scroll bars needed */
    24922574    if (m.expandedTo(v) == m)
     
    24992581}
    25002582
     2583void UIMachineView::scrollBy(int dx, int dy)
     2584{
     2585    horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
     2586    verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
     2587}
     2588
    25012589#ifdef VBOX_WITH_VIDEOHWACCEL
    2502 void UIMachineView::scrollContentsBy (int dx, int dy)
    2503 {
    2504     if (mFrameBuf)
    2505     {
    2506         mFrameBuf->viewportScrolled(dx, dy);
    2507     }
    2508     QAbstractScrollArea::scrollContentsBy (dx, dy);
    2509 }
    2510 #endif
    2511 
    2512 void UIMachineView::onStateChange(KMachineState state)
    2513 {
    2514     switch (state)
    2515     {
    2516         case KMachineState_Paused:
    2517         case KMachineState_TeleportingPausedVM:
    2518         {
    2519             if (    mode != VBoxDefs::TimerMode
    2520                 &&  mFrameBuf
    2521                 &&  (   state      != KMachineState_TeleportingPausedVM
    2522                      || mLastState != KMachineState_Teleporting)
    2523                )
    2524             {
    2525                 /*
    2526                  *  Take a screen snapshot. Note that TakeScreenShot() always
    2527                  *  needs a 32bpp image
    2528                  */
    2529                 QImage shot = QImage (mFrameBuf->width(), mFrameBuf->height(), QImage::Format_RGB32);
    2530                 CDisplay dsp = m_console.GetDisplay();
    2531                 dsp.TakeScreenShot (shot.bits(), shot.width(), shot.height());
    2532                 /*
    2533                  *  TakeScreenShot() may fail if, e.g. the Paused notification
    2534                  *  was delivered after the machine execution was resumed. It's
    2535                  *  not fatal.
    2536                  */
    2537                 if (dsp.isOk())
    2538                 {
    2539                     dimImage (shot);
    2540                     mPausedShot = QPixmap::fromImage (shot);
    2541                     /* fully repaint to pick up mPausedShot */
    2542                     repaint();
    2543                 }
    2544             }
    2545             /* fall through */
    2546         }
    2547         case KMachineState_Stuck:
    2548         {
    2549             /* reuse the focus event handler to uncapture everything */
    2550             if (hasFocus())
    2551                 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */);
    2552             break;
    2553         }
    2554         case KMachineState_Running:
    2555         {
    2556             if (   mLastState == KMachineState_Paused
    2557                 || mLastState == KMachineState_TeleportingPausedVM
    2558                )
    2559             {
    2560                 if (mode != VBoxDefs::TimerMode && mFrameBuf)
    2561                 {
    2562                     /* reset the pixmap to free memory */
    2563                     mPausedShot = QPixmap ();
    2564                     /*
    2565                      *  ask for full guest display update (it will also update
    2566                      *  the viewport through IFramebuffer::NotifyUpdate)
    2567                      */
    2568                     CDisplay dsp = m_console.GetDisplay();
    2569                     dsp.InvalidateAndUpdate();
    2570                 }
    2571             }
    2572             /* reuse the focus event handler to capture input */
    2573             if (hasFocus())
    2574                 focusEvent (true /* aHasFocus */);
    2575             break;
    2576         }
    2577         default:
    2578             break;
    2579     }
    2580 
    2581     mLastState = state;
    2582 }
    2583 
    2584 void UIMachineView::captureKbd(bool aCapture, bool aEmitSignal /* = true */)
    2585 {
    2586     //AssertMsg(m_bIsAttached, ("Console must be attached"));
    2587 
    2588     if (m_bIsKeyboardCaptured == aCapture)
     2590void UIMachineView::scrollContentsBy(int dx, int dy)
     2591{
     2592    if (m_pFrameBuffer)
     2593    {
     2594        m_pFrameBuffer->viewportScrolled(dx, dy);
     2595    }
     2596    QAbstractScrollArea::scrollContentsBy(dx, dy);
     2597}
     2598#endif
     2599
     2600void UIMachineView::emitKeyboardStateChanged()
     2601{
     2602    emit keyboardStateChanged((m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) |
     2603                              (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0));
     2604}
     2605
     2606void UIMachineView::emitMouseStateChanged()
     2607{
     2608    emit mouseStateChanged((m_bIsMouseCaptured ? UIMouseStateType_MouseCaptured : 0) |
     2609                           (m_bIsMouseAbsolute ? UIMouseStateType_MouseAbsolute : 0) |
     2610                           (!m_bIsMouseIntegrated ? UIMouseStateType_MouseAbsoluteDisabled : 0));
     2611}
     2612
     2613void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */)
     2614{
     2615    if (m_bIsKeyboardCaptured == fCapture)
    25892616        return;
    25902617
    2591     /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is
    2592      * used instead. On X11, we use XGrabKey instead of XGrabKeyboard (called
    2593      * by QWidget::grabKeyboard()) because the latter causes problems under
    2594      * metacity 2.16 (in particular, due to a bug, a window cannot be moved
    2595      * using the mouse if it is currently grabing the keyboard). On Mac OS X,
    2596      * we use the Qt methods + disabling global hot keys + watching modifiers
     2618    /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is used instead.
     2619     * On X11, we use XGrabKey instead of XGrabKeyboard (called by QWidget::grabKeyboard())
     2620     * because the latter causes problems under metacity 2.16 (in particular, due to a bug,
     2621     * a window cannot be moved using the mouse if it is currently grabing the keyboard).
     2622     * On Mac OS X, we use the Qt methods + disabling global hot keys + watching modifiers
    25972623     * (for right/left separation). */
    2598 #if defined (Q_WS_WIN32)
     2624#if defined(Q_WS_WIN32)
    25992625    /**/
    2600 #elif defined (Q_WS_X11)
    2601         if (aCapture)
     2626#elif defined(Q_WS_X11)
     2627        if (fCapture)
    26022628                XGrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId(), False, GrabModeAsync, GrabModeAsync);
    26032629        else
    2604                 XUngrabKey(QX11Info::display(),  AnyKey, AnyModifier, window()->winId());
    2605 #elif defined (Q_WS_MAC)
    2606     if (aCapture)
     2630                XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId());
     2631#elif defined(Q_WS_MAC)
     2632    if (fCapture)
    26072633    {
    26082634        ::DarwinDisableGlobalHotKeys(true);
     
    26152641    }
    26162642#else
    2617     if (aCapture)
     2643    if (fCapture)
    26182644        grabKeyboard();
    26192645    else
     
    26212647#endif
    26222648
    2623     m_bIsKeyboardCaptured = aCapture;
    2624 
    2625     if (aEmitSignal)
     2649    m_bIsKeyboardCaptured = fCapture;
     2650
     2651    if (fEmitSignal)
    26262652        emitKeyboardStateChanged();
    26272653}
    26282654
    2629 void UIMachineView::captureMouse(bool aCapture, bool aEmitSignal /* = true */)
    2630 {
    2631     //AssertMsg (m_bIsAttached, ("Console must be attached"));
    2632 
    2633     if (m_bIsMouseCaptured == aCapture)
     2655void UIMachineView::captureMouse(bool fCapture, bool fEmitSignal /* = true */)
     2656{
     2657    if (m_bIsMouseCaptured == fCapture)
    26342658        return;
    26352659
    2636     if (aCapture)
    2637     {
    2638         /* memorize the host position where the cursor was captured */
    2639         mCapturedPos = QCursor::pos();
     2660    if (fCapture)
     2661    {
     2662        /* Memorize the host position where the cursor was captured: */
     2663        m_capturedMousePos = QCursor::pos();
    26402664#ifdef Q_WS_WIN32
    26412665        viewport()->setCursor (QCursor (Qt::BlankCursor));
    2642         /* move the mouse to the center of the visible area */
     2666        /* Move the mouse to the center of the visible area: */
    26432667        QCursor::setPos (mapToGlobal (visibleRegion().boundingRect().center()));
    2644         mLastPos = QCursor::pos();
     2668        m_lastMousePos = QCursor::pos();
    26452669#elif defined (Q_WS_MAC)
    2646         /* move the mouse to the center of the visible area */
    2647         mLastPos = mapToGlobal (visibleRegion().boundingRect().center());
    2648         QCursor::setPos (mLastPos);
    2649         /* grab all mouse events. */
     2670        /* Move the mouse to the center of the visible area: */
     2671        m_lastMousePos = mapToGlobal (visibleRegion().boundingRect().center());
     2672        QCursor::setPos (m_lastMousePos);
     2673        /* Grab all mouse events: */
    26502674        viewport()->grabMouse();
    26512675#else
    26522676        viewport()->grabMouse();
    2653         mLastPos = QCursor::pos();
     2677        m_lastMousePos = QCursor::pos();
    26542678#endif
    26552679    }
     
    26592683        viewport()->releaseMouse();
    26602684#endif
    2661         /* release mouse buttons */
     2685        /* Release mouse buttons: */
    26622686        CMouse mouse = m_console.GetMouse();
    26632687        mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0);
    26642688    }
    26652689
    2666     m_bIsMouseCaptured = aCapture;
     2690    m_bIsMouseCaptured = fCapture;
    26672691
    26682692    updateMouseClipping();
    26692693
    2670     if (aEmitSignal)
     2694    if (fEmitSignal)
    26712695        emitMouseStateChanged();
    26722696}
    26732697
    2674 bool UIMachineView::processHotKey(const QKeySequence &aKey, const QList <QAction*> &aData)
    2675 {
    2676     foreach (QAction *pAction, aData)
     2698void UIMachineView::saveKeyStates()
     2699{
     2700    ::memcpy(m_pressedKeysCopy, m_pressedKeys, sizeof(m_pressedKeys));
     2701}
     2702
     2703bool UIMachineView::processHotKey(const QKeySequence &key, const QList<QAction*> &actions)
     2704{
     2705    // TODO: Make it work for all modes:
     2706    foreach (QAction *pAction, actions)
    26772707    {
    26782708        if (QMenu *menu = pAction->menu())
    26792709        {
    26802710            /* Process recursively for each sub-menu */
    2681             if (processHotKey(aKey, menu->actions()))
     2711            if (processHotKey(key, menu->actions()))
    26822712                return true;
    26832713        }
     
    26872717            if (pAction->isEnabled() && !hotkey.isEmpty())
    26882718            {
    2689                 if (aKey.matches(QKeySequence (hotkey)) == QKeySequence::ExactMatch)
     2719                if (key.matches(QKeySequence (hotkey)) == QKeySequence::ExactMatch)
    26902720                {
    26912721                    /* We asynchronously post a special event instead of calling
     
    27082738void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */)
    27092739{
    2710     //AssertMsg(m_bIsAttached, ("Console must be attached"));
    2711 
    27122740    CKeyboard keyboard = m_console.GetKeyboard();
    27132741    bool fSentRESEND = false;
    27142742
    2715     /* send a dummy scan code (RESEND) to prevent the guest OS from recognizing
     2743    /* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing
    27162744     * a single key click (for ex., Alt) and performing an unwanted action
    27172745     * (for ex., activating the menu) when we release all pressed keys below.
    27182746     * Note, that it's just a guess that sending RESEND will give the desired
    27192747     * effect :), but at least it works with NT and W2k guests. */
    2720 
    2721     for (uint i = 0; i < SIZEOF_ARRAY (mPressedKeys); i++)
    2722     {
    2723         if (mPressedKeys[i] & IsKeyPressed)
     2748    for (uint i = 0; i < SIZEOF_ARRAY (m_pressedKeys); i++)
     2749    {
     2750        if (m_pressedKeys[i] & IsKeyPressed)
    27242751        {
    27252752            if (!fSentRESEND)
     
    27302757            keyboard.PutScancode(i | 0x80);
    27312758        }
    2732         else if (mPressedKeys[i] & IsExtKeyPressed)
     2759        else if (m_pressedKeys[i] & IsExtKeyPressed)
    27332760        {
    27342761            if (!fSentRESEND)
     
    27422769            keyboard.PutScancodes(codes);
    27432770        }
    2744         mPressedKeys[i] = 0;
     2771        m_pressedKeys[i] = 0;
    27452772    }
    27462773
     
    27492776
    27502777#ifdef Q_WS_MAC
    2751     /* clear most of the modifiers. */
    2752     mDarwinKeyModifiers &=
     2778    /* Clear most of the modifiers: */
     2779    m_darwinKeyModifiers &=
    27532780        alphaLock | kEventKeyModifierNumLockMask |
    27542781        (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey()));
     
    27582785}
    27592786
    2760 void UIMachineView::saveKeyStates()
    2761 {
    2762     ::memcpy(mPressedKeysCopy, mPressedKeys, sizeof(mPressedKeys));
    2763 }
    2764 
    27652787void UIMachineView::sendChangedKeyStates()
    27662788{
    2767     //AssertMsg(m_bIsAttached, ("Console must be attached"));
    2768 
    27692789    QVector <LONG> codes(2);
    27702790    CKeyboard keyboard = m_console.GetKeyboard();
    2771     for (uint i = 0; i < SIZEOF_ARRAY(mPressedKeys); ++ i)
    2772     {
    2773         uint8_t os = mPressedKeysCopy[i];
    2774         uint8_t ns = mPressedKeys[i];
     2791    for (uint i = 0; i < SIZEOF_ARRAY(m_pressedKeys); ++ i)
     2792    {
     2793        uint8_t os = m_pressedKeysCopy[i];
     2794        uint8_t ns = m_pressedKeys[i];
    27752795        if ((os & IsKeyPressed) != (ns & IsKeyPressed))
    27762796        {
     
    27932813void UIMachineView::updateMouseClipping()
    27942814{
    2795     //AssertMsg(m_bIsAttached, ("Console must be attached"));
    2796 
    27972815    if (m_bIsMouseCaptured)
    27982816    {
     
    28112829#endif
    28122830        /* return the cursor to where it was when we captured it and show it */
    2813         QCursor::setPos(mCapturedPos);
     2831        QCursor::setPos(m_capturedMousePos);
    28142832        viewport()->unsetCursor();
    28152833    }
    28162834}
    28172835
    2818 #if 0
    2819 void UIMachineView::setPointerShape(MousePointerChangeEvent *pEvent)
    2820 {
    2821     if (pEvent->shapeData() != NULL)
    2822     {
    2823         bool ok = false;
    2824 
    2825         const uchar *srcAndMaskPtr = pEvent->shapeData();
    2826         uint andMaskSize = (pEvent->width() + 7) / 8 * pEvent->height();
    2827         const uchar *srcShapePtr = pEvent->shapeData() + ((andMaskSize + 3) & ~3);
    2828         uint srcShapePtrScan = pEvent->width() * 4;
     2836void UIMachineView::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
     2837                                    uint uXHot, uint uYHot, uint uWidth, uint uHeight)
     2838{
     2839    AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
     2840
     2841    bool ok = false;
     2842
     2843    const uchar *srcAndMaskPtr = pShapeData;
     2844    uint andMaskSize = (uWidth + 7) / 8 * uHeight;
     2845    const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
     2846    uint srcShapePtrScan = uWidth * 4;
    28292847
    28302848#if defined (Q_WS_WIN)
    28312849
    2832         BITMAPV5HEADER bi;
    2833         HBITMAP hBitmap;
    2834         void *lpBits;
    2835 
    2836         ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
    2837         bi.bV5Size = sizeof(BITMAPV5HEADER);
    2838         bi.bV5Width = pEvent->width();
    2839         bi.bV5Height = - (LONG)pEvent->height();
    2840         bi.bV5Planes = 1;
    2841         bi.bV5BitCount = 32;
    2842         bi.bV5Compression = BI_BITFIELDS;
    2843         bi.bV5RedMask   = 0x00FF0000;
    2844         bi.bV5GreenMask = 0x0000FF00;
    2845         bi.bV5BlueMask  = 0x000000FF;
    2846         if (pEvent->hasAlpha())
    2847             bi.bV5AlphaMask = 0xFF000000;
    2848         else
    2849             bi.bV5AlphaMask = 0;
    2850 
    2851         HDC hdc = GetDC(NULL);
    2852 
    2853         // create the DIB section with an alpha channel
    2854         hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
    2855 
    2856         ReleaseDC(NULL, hdc);
    2857 
    2858         HBITMAP hMonoBitmap = NULL;
    2859         if (pEvent->hasAlpha())
    2860         {
    2861             // create an empty mask bitmap
    2862             hMonoBitmap = CreateBitmap(pEvent->width(), pEvent->height(), 1, 1, NULL);
    2863         }
    2864         else
    2865         {
    2866             /* Word aligned AND mask. Will be allocated and created if necessary. */
    2867             uint8_t *pu8AndMaskWordAligned = NULL;
    2868 
    2869             /* Width in bytes of the original AND mask scan line. */
    2870             uint32_t cbAndMaskScan = (pEvent->width() + 7) / 8;
    2871 
    2872             if (cbAndMaskScan & 1)
    2873             {
    2874                 /* Original AND mask is not word aligned. */
    2875 
    2876                 /* Allocate memory for aligned AND mask. */
    2877                 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * pEvent->height());
    2878 
    2879                 Assert(pu8AndMaskWordAligned);
    2880 
    2881                 if (pu8AndMaskWordAligned)
     2850    BITMAPV5HEADER bi;
     2851    HBITMAP hBitmap;
     2852    void *lpBits;
     2853
     2854    ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
     2855    bi.bV5Size = sizeof(BITMAPV5HEADER);
     2856    bi.bV5Width = uWidth;
     2857    bi.bV5Height = - (LONG)uHeight;
     2858    bi.bV5Planes = 1;
     2859    bi.bV5BitCount = 32;
     2860    bi.bV5Compression = BI_BITFIELDS;
     2861    bi.bV5RedMask   = 0x00FF0000;
     2862    bi.bV5GreenMask = 0x0000FF00;
     2863    bi.bV5BlueMask  = 0x000000FF;
     2864    if (fHasAlpha)
     2865        bi.bV5AlphaMask = 0xFF000000;
     2866    else
     2867        bi.bV5AlphaMask = 0;
     2868
     2869    HDC hdc = GetDC(NULL);
     2870
     2871    /* Create the DIB section with an alpha channel: */
     2872    hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
     2873
     2874    ReleaseDC(NULL, hdc);
     2875
     2876    HBITMAP hMonoBitmap = NULL;
     2877    if (fHasAlpha)
     2878    {
     2879        /* Create an empty mask bitmap: */
     2880        hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
     2881    }
     2882    else
     2883    {
     2884        /* Word aligned AND mask. Will be allocated and created if necessary. */
     2885        uint8_t *pu8AndMaskWordAligned = NULL;
     2886
     2887        /* Width in bytes of the original AND mask scan line. */
     2888        uint32_t cbAndMaskScan = (uWidth + 7) / 8;
     2889
     2890        if (cbAndMaskScan & 1)
     2891        {
     2892            /* Original AND mask is not word aligned. */
     2893
     2894            /* Allocate memory for aligned AND mask. */
     2895            pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
     2896
     2897            Assert(pu8AndMaskWordAligned);
     2898
     2899            if (pu8AndMaskWordAligned)
     2900            {
     2901                /* According to MSDN the padding bits must be 0.
     2902                 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
     2903                uint32_t u32PaddingBits = cbAndMaskScan * 8  - uWidth;
     2904                Assert(u32PaddingBits < 8);
     2905                uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
     2906
     2907                Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
     2908                      u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
     2909
     2910                uint8_t *src = (uint8_t *)srcAndMaskPtr;
     2911                uint8_t *dst = pu8AndMaskWordAligned;
     2912
     2913                unsigned i;
     2914                for (i = 0; i < uHeight; i++)
    28822915                {
    2883                     /* According to MSDN the padding bits must be 0.
    2884                      * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
    2885                     uint32_t u32PaddingBits = cbAndMaskScan * 8  - pEvent->width();
    2886                     Assert(u32PaddingBits < 8);
    2887                     uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
    2888 
    2889                     Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
    2890                           u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, pEvent->width(), cbAndMaskScan));
    2891 
    2892                     uint8_t *src = (uint8_t *)srcAndMaskPtr;
    2893                     uint8_t *dst = pu8AndMaskWordAligned;
    2894 
    2895                     unsigned i;
    2896                     for (i = 0; i < pEvent->height(); i++)
     2916                    memcpy(dst, src, cbAndMaskScan);
     2917
     2918                    dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
     2919
     2920                    src += cbAndMaskScan;
     2921                    dst += cbAndMaskScan + 1;
     2922                }
     2923            }
     2924        }
     2925
     2926        /* Create the AND mask bitmap: */
     2927        hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
     2928                                     pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
     2929
     2930        if (pu8AndMaskWordAligned)
     2931        {
     2932            RTMemTmpFree(pu8AndMaskWordAligned);
     2933        }
     2934    }
     2935
     2936    Assert(hBitmap);
     2937    Assert(hMonoBitmap);
     2938    if (hBitmap && hMonoBitmap)
     2939    {
     2940        DWORD *dstShapePtr = (DWORD *) lpBits;
     2941
     2942        for (uint y = 0; y < uHeight; y ++)
     2943        {
     2944            memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
     2945            srcShapePtr += srcShapePtrScan;
     2946            dstShapePtr += uWidth;
     2947        }
     2948
     2949        ICONINFO ii;
     2950        ii.fIcon = FALSE;
     2951        ii.xHotspot = uXHot;
     2952        ii.yHotspot = uYHot;
     2953        ii.hbmMask = hMonoBitmap;
     2954        ii.hbmColor = hBitmap;
     2955
     2956        HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
     2957        Assert(hAlphaCursor);
     2958        if (hAlphaCursor)
     2959        {
     2960            viewport()->setCursor(QCursor(hAlphaCursor));
     2961            ok = true;
     2962            if (m_alphaCursor)
     2963                DestroyIcon(m_alphaCursor);
     2964            m_alphaCursor = hAlphaCursor;
     2965        }
     2966    }
     2967
     2968    if (hMonoBitmap)
     2969        DeleteObject(hMonoBitmap);
     2970    if (hBitmap)
     2971        DeleteObject(hBitmap);
     2972
     2973#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
     2974
     2975    XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
     2976    Assert(img);
     2977    if (img)
     2978    {
     2979        img->xhot = uXHot;
     2980        img->yhot = uYHot;
     2981
     2982        XcursorPixel *dstShapePtr = img->pixels;
     2983
     2984        for (uint y = 0; y < uHeight; y ++)
     2985        {
     2986            memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
     2987
     2988            if (!fHasAlpha)
     2989            {
     2990                /* Convert AND mask to the alpha channel: */
     2991                uchar byte = 0;
     2992                for (uint x = 0; x < uWidth; x ++)
     2993                {
     2994                    if (!(x % 8))
     2995                        byte = *(srcAndMaskPtr ++);
     2996                    else
     2997                        byte <<= 1;
     2998
     2999                    if (byte & 0x80)
    28973000                    {
    2898                         memcpy(dst, src, cbAndMaskScan);
    2899 
    2900                         dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
    2901 
    2902                         src += cbAndMaskScan;
    2903                         dst += cbAndMaskScan + 1;
     3001                        /* Linux doesn't support inverted pixels (XOR ops,
     3002                         * to be exact) in cursor shapes, so we detect such
     3003                         * pixels and always replace them with black ones to
     3004                         * make them visible at least over light colors */
     3005                        if (dstShapePtr [x] & 0x00FFFFFF)
     3006                            dstShapePtr [x] = 0xFF000000;
     3007                        else
     3008                            dstShapePtr [x] = 0x00000000;
    29043009                    }
     3010                    else
     3011                        dstShapePtr [x] |= 0xFF000000;
    29053012                }
    29063013            }
    29073014
    2908             /* create the AND mask bitmap */
    2909             hMonoBitmap = ::CreateBitmap(pEvent->width(), pEvent->height(), 1, 1,
    2910                                          pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
    2911 
    2912             if (pu8AndMaskWordAligned)
    2913             {
    2914                 RTMemTmpFree(pu8AndMaskWordAligned);
    2915             }
    2916         }
    2917 
    2918         Assert(hBitmap);
    2919         Assert(hMonoBitmap);
    2920         if (hBitmap && hMonoBitmap)
    2921         {
    2922             DWORD *dstShapePtr = (DWORD *) lpBits;
    2923 
    2924             for (uint y = 0; y < pEvent->height(); y ++)
    2925             {
    2926                 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
    2927                 srcShapePtr += srcShapePtrScan;
    2928                 dstShapePtr += pEvent->width();
    2929             }
    2930 
    2931             ICONINFO ii;
    2932             ii.fIcon = FALSE;
    2933             ii.xHotspot = pEvent->xHot();
    2934             ii.yHotspot = pEvent->yHot();
    2935             ii.hbmMask = hMonoBitmap;
    2936             ii.hbmColor = hBitmap;
    2937 
    2938             HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
    2939             Assert(hAlphaCursor);
    2940             if (hAlphaCursor)
    2941             {
    2942                 viewport()->setCursor(QCursor(hAlphaCursor));
    2943                 ok = true;
    2944                 if (mAlphaCursor)
    2945                     DestroyIcon(mAlphaCursor);
    2946                 mAlphaCursor = hAlphaCursor;
    2947             }
    2948         }
    2949 
    2950         if (hMonoBitmap)
    2951             DeleteObject(hMonoBitmap);
    2952         if (hBitmap)
    2953             DeleteObject(hBitmap);
    2954 
    2955 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
    2956 
    2957         XcursorImage *img = XcursorImageCreate (pEvent->width(), pEvent->height());
    2958         Assert (img);
    2959         if (img)
    2960         {
    2961             img->xhot = pEvent->xHot();
    2962             img->yhot = pEvent->yHot();
    2963 
    2964             XcursorPixel *dstShapePtr = img->pixels;
    2965 
    2966             for (uint y = 0; y < pEvent->height(); y ++)
    2967             {
    2968                 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
    2969 
    2970                 if (!pEvent->hasAlpha())
    2971                 {
    2972                     /* convert AND mask to the alpha channel */
    2973                     uchar byte = 0;
    2974                     for (uint x = 0; x < pEvent->width(); x ++)
    2975                     {
    2976                         if (!(x % 8))
    2977                             byte = *(srcAndMaskPtr ++);
    2978                         else
    2979                             byte <<= 1;
    2980 
    2981                         if (byte & 0x80)
    2982                         {
    2983                             /* Linux doesn't support inverted pixels (XOR ops,
    2984                              * to be exact) in cursor shapes, so we detect such
    2985                              * pixels and always replace them with black ones to
    2986                              * make them visible at least over light colors */
    2987                             if (dstShapePtr [x] & 0x00FFFFFF)
    2988                                 dstShapePtr [x] = 0xFF000000;
    2989                             else
    2990                                 dstShapePtr [x] = 0x00000000;
    2991                         }
    2992                         else
    2993                             dstShapePtr [x] |= 0xFF000000;
    2994                     }
    2995                 }
    2996 
    2997                 srcShapePtr += srcShapePtrScan;
    2998                 dstShapePtr += pEvent->width();
    2999             }
    3000 
    3001             Cursor cur = XcursorImageLoadCursor (QX11Info::display(), img);
    3002             Assert (cur);
    3003             if (cur)
    3004             {
    3005                 viewport()->setCursor (QCursor (cur));
    3006                 ok = true;
    3007             }
    3008 
    3009             XcursorImageDestroy (img);
    3010         }
     3015            srcShapePtr += srcShapePtrScan;
     3016            dstShapePtr += uWidth;
     3017        }
     3018
     3019        Cursor cur = XcursorImageLoadCursor(QX11Info::display(), img);
     3020        Assert (cur);
     3021        if (cur)
     3022        {
     3023            viewport()->setCursor(QCursor(cur));
     3024            ok = true;
     3025        }
     3026
     3027        XcursorImageDestroy(img);
     3028    }
    30113029
    30123030#elif defined(Q_WS_MAC)
    30133031
    3014         /* Create a ARGB image out of the shape data. */
    3015         QImage image  (pEvent->width(), pEvent->height(), QImage::Format_ARGB32);
    3016         const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
    3017         unsigned cbSrcMaskLine = RT_ALIGN (pEvent->width(), 8) / 8;
    3018         for (unsigned int y = 0; y < pEvent->height(); ++y)
    3019         {
    3020             for (unsigned int x = 0; x < pEvent->width(); ++x)
    3021             {
    3022                unsigned int color = ((unsigned int*)srcShapePtr)[y*pEvent->width()+x];
    3023                /* If the alpha channel isn't in the shape data, we have to
    3024                 * create them from the and-mask. This is a bit field where 1
    3025                 * represent transparency & 0 opaque respectively. */
    3026                if (!pEvent->hasAlpha())
     3032    /* Create a ARGB image out of the shape data. */
     3033    QImage image  (uWidth, uHeight, QImage::Format_ARGB32);
     3034    const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
     3035    unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
     3036    for (unsigned int y = 0; y < uHeight; ++y)
     3037    {
     3038        for (unsigned int x = 0; x < uWidth; ++x)
     3039        {
     3040           unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
     3041           /* If the alpha channel isn't in the shape data, we have to
     3042            * create them from the and-mask. This is a bit field where 1
     3043            * represent transparency & 0 opaque respectively. */
     3044           if (!fHasAlpha)
     3045           {
     3046               if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
     3047                   color  |= 0xff000000;
     3048               else
    30273049               {
    3028                    if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
    3029                        color  |= 0xff000000;
     3050                   /* This isn't quite right, but it's the best we can do I think... */
     3051                   if (color & 0x00ffffff)
     3052                       color = 0xff000000;
    30303053                   else
    3031                    {
    3032                        /* This isn't quite right, but it's the best we can do I
    3033                         * think... */
    3034                        if (color & 0x00ffffff)
    3035                            color = 0xff000000;
    3036                        else
    3037                            color = 0x00000000;
    3038                    }
     3054                       color = 0x00000000;
    30393055               }
    3040                image.setPixel (x, y, color);
    3041             }
    3042             /* Move one scanline forward. */
    3043             pbSrcMask += cbSrcMaskLine;
    3044         }
    3045         /* Set the new cursor */
    3046         QCursor cursor (QPixmap::fromImage (image), pEvent->xHot(), pEvent->yHot());
    3047         viewport()->setCursor (cursor);
    3048         ok = true;
    3049         NOREF (srcShapePtrScan);
     3056           }
     3057           image.setPixel (x, y, color);
     3058        }
     3059        /* Move one scanline forward. */
     3060        pbSrcMask += cbSrcMaskLine;
     3061    }
     3062    /* Set the new cursor: */
     3063    QCursor cursor(QPixmap::fromImage(image), uXHot, uYHot);
     3064    viewport()->setCursor(cursor);
     3065    ok = true;
     3066    NOREF(srcShapePtrScan);
    30503067
    30513068#else
     
    30553072#endif
    30563073
    3057         if (ok)
    3058             mLastCursor = viewport()->cursor();
    3059         else
    3060             viewport()->unsetCursor();
    3061     }
     3074    if (ok)
     3075        m_lastCursor = viewport()->cursor();
    30623076    else
    3063     {
    3064         if (pEvent->isVisible())
    3065         {
    3066             viewport()->setCursor(mLastCursor);
    3067         }
    3068         else
    3069         {
    3070             viewport()->setCursor(Qt::BlankCursor);
    3071         }
    3072     }
    3073     mHideHostPointer = !pEvent->isVisible();
    3074 }
    3075 #endif
    3076 
    3077 inline QRgb qRgbIntensity(QRgb rgb, int mul, int div)
    3078 {
    3079     int r = qRed(rgb);
    3080     int g = qGreen(rgb);
    3081     int b = qBlue(rgb);
    3082     return qRgb(mul * r / div, mul * g / div, mul * b / div);
    3083 }
    3084 
    3085 void UIMachineView::storeConsoleSize(int aWidth, int aHeight)
    3086 {
    3087     LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight));
    3088     mStoredConsoleSize = QRect(0, 0, aWidth, aHeight);
     3077        viewport()->unsetCursor();
    30893078}
    30903079
     
    30933082    machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setChecked(false);
    30943083    machineWindowWrapper()->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_MouseIntegration)->setEnabled(bDisabled);
    3095 }
    3096 
    3097 void UIMachineView::setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight)
    3098 {
    3099     switch (aGeo)
    3100     {
    3101         case DesktopGeo_Fixed:
    3102             mDesktopGeo = DesktopGeo_Fixed;
    3103             if (aWidth != 0 && aHeight != 0)
    3104                 mDesktopGeometry = QRect(0, 0, aWidth, aHeight);
    3105             else
    3106                 mDesktopGeometry = QRect(0, 0, 0, 0);
    3107             storeConsoleSize(0, 0);
    3108             break;
    3109         case DesktopGeo_Automatic:
    3110             mDesktopGeo = DesktopGeo_Automatic;
    3111             mDesktopGeometry = QRect(0, 0, 0, 0);
    3112             storeConsoleSize(0, 0);
    3113             break;
    3114         case DesktopGeo_Any:
    3115             mDesktopGeo = DesktopGeo_Any;
    3116             mDesktopGeometry = QRect(0, 0, 0, 0);
    3117             break;
    3118         default:
    3119             AssertMsgFailed(("Invalid desktop geometry type %d\n", aGeo));
    3120             mDesktopGeo = DesktopGeo_Invalid;
    3121     }
    3122 }
    3123 
    3124 QRect UIMachineView::availableGeometry()
    3125 {
    3126     return machineWindowWrapper()->machineWindow()->isFullScreen() ?
    3127            QApplication::desktop()->screenGeometry(this) :
    3128            QApplication::desktop()->availableGeometry(this);
    31293084}
    31303085
     
    31673122    if (mDockIconEnabled)
    31683123    {
    3169         if (!mPausedShot.isNull())
    3170         {
    3171             CGImageRef pauseImg = ::darwinToCGImageRef (&mPausedShot);
     3124        if (!m_pauseShot.isNull())
     3125        {
     3126            CGImageRef pauseImg = ::darwinToCGImageRef (&m_pauseShot);
    31723127            /* Use the pause image as background */
    31733128            mDockIconPreview->updateDockPreview (pauseImg);
     
    31783133# if defined (VBOX_GUI_USE_QUARTZ2D)
    31793134                // TODO_NEW_CORE
    3180 //            if (mode == VBoxDefs::Quartz2DMode)
     3135//            if (mode() == VBoxDefs::Quartz2DMode)
    31813136//            {
    31823137                /* If the render mode is Quartz2D we could use the CGImageRef
    31833138                 * of the framebuffer for the dock icon creation. This saves
    31843139                 * some conversion time. */
    3185 //                mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (mFrameBuf)->imageRef());
     3140//                mDockIconPreview->updateDockPreview (static_cast <VBoxQuartz2DFrameBuffer *> (m_pFrameBuffer)->imageRef());
    31863141//            }
    31873142//            else
     
    31903145                 * framebuffer */
    31913146                // TODO_NEW_CORE
    3192 //                mDockIconPreview->updateDockPreview (mFrameBuf);
     3147//                mDockIconPreview->updateDockPreview (m_pFrameBuffer);
    31933148        }
    31943149    }
     
    32013156     * the overlay stuff only. */
    32023157    if (mDockIconEnabled &&
    3203         (mLastState == KMachineState_Running ||
    3204          mLastState == KMachineState_Paused ||
    3205          mLastState == KMachineState_Teleporting ||
    3206          mLastState == KMachineState_LiveSnapshotting ||
    3207          mLastState == KMachineState_Restoring ||
    3208          mLastState == KMachineState_TeleportingPausedVM ||
    3209          mLastState == KMachineState_TeleportingIn ||
    3210          mLastState == KMachineState_Saving))
     3158        (m_machineState == KMachineState_Running ||
     3159         m_machineState == KMachineState_Paused ||
     3160         m_machineState == KMachineState_Teleporting ||
     3161         m_machineState == KMachineState_LiveSnapshotting ||
     3162         m_machineState == KMachineState_Restoring ||
     3163         m_machineState == KMachineState_TeleportingPausedVM ||
     3164         m_machineState == KMachineState_TeleportingIn ||
     3165         m_machineState == KMachineState_Saving))
    32113166        updateDockIcon();
    32123167    else
     
    32233178       the keyboard/mouse is grabbed (this is when we have a valid
    32243179       event handler). */
    3225     if (aOn || mKeyboardGrabbed)
     3180    if (aOn || m_fKeyboardGrabbed)
    32263181        ::darwinSetMouseCoalescingEnabled (aOn);
    32273182}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r26752 r26754  
    4040#endif /* Q_WS_MAC */
    4141
    42 /* Local forward declarations */
     42/* Local forwards */
     43#ifdef Q_WS_MAC
    4344class VBoxChangeDockIconUpdateEvent;
    4445class VBoxChangePresentationModeEvent;
    4546class VBoxDockIconPreview;
     47#endif /* Q_WS_MAC */
    4648
    4749class UIMachineView : public QAbstractScrollArea
     
    5961                                 , UIVisualStateType visualStateType);
    6062
     63    /* Public virtual members: */
     64    virtual void normalizeGeometry(bool bAdjustPosition = false) = 0;
     65
    6166    /* Public setters: */
    6267    void setIgnoreGuestResize(bool bIgnore) { m_bIsGuestResizeIgnored = bIgnore; }
    6368    void setMouseIntegrationEnabled(bool bEnabled);
    64     virtual void normalizeGeometry(bool bAdjustPosition = false) = 0;
    6569    //void setMachineViewFinalized(bool fTrue = true) { m_bIsMachineWindowResizeIgnored = !fTrue; }
    6670
     
    7074    void setMouseCoalescingEnabled(bool aOn);
    7175    void setDockIconEnabled(bool aOn) { mDockIconEnabled = aOn; };
    72 
    73     const QPixmap& pauseShot() const { return mPausedShot; }
    7476#endif
    7577
    7678signals:
    7779
    78     /* Machine view signals: */
     80    /* Mouse/Keyboard state-change signals: */
    7981    void keyboardStateChanged(int iState);
    8082    void mouseStateChanged(int iState);
     
    9799    );
    98100    virtual ~UIMachineView();
     101
     102    /* Desktop geometry types: */
     103    enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
    99104
    100105    /* Protected getters: */
     
    102107    CConsole &console() { return m_console; }
    103108
    104     /* Protected members: */
     109    /* Protected getters: */
     110    VBoxDefs::RenderMode mode() const { return m_mode; }
    105111    QSize sizeHint() const;
    106112    int contentsX() const;
     
    110116    int visibleWidth() const;
    111117    int visibleHeight() const;
     118    QRect desktopGeometry() const;
     119    bool isGuestSupportsGraphics() const { return m_bIsGuestSupportsGraphics; }
     120    const QPixmap& pauseShot() const { return m_pauseShot; }
     121    //bool isMouseAbsolute() const { return m_bIsMouseAbsolute; }
     122
     123    /* Protected members: */
    112124    void calculateDesktopGeometry();
    113     QRect desktopGeometry() const;
    114     //bool isMouseAbsolute() const { return m_bIsMouseAbsolute; }
     125    void setDesktopGeometry(DesktopGeo geometry, int iWidth, int iHeight);
     126    void storeConsoleSize(int iWidth, int iHeight);
     127    QRect availableGeometry();
     128    virtual void maybeRestrictMinimumSize() = 0;
    115129
    116130    /* Prepare routines: */
    117     void prepareFrameBuffer();
    118     void prepareCommon();
    119     void prepareFilters();
    120     void loadMachineViewSettings();
     131    virtual void prepareFrameBuffer();
     132    virtual void prepareCommon();
     133    virtual void prepareFilters();
     134    virtual void prepareConsoleConnections();
     135    virtual void loadMachineViewSettings();
    121136
    122137    /* Cleanup routines: */
    123     //void saveMachineViewSettings();
    124     //void cleanupFilters();
    125     void cleanupCommon();
    126     void cleanupFrameBuffer();
    127 
    128     /* Protected variables: */
    129     VBoxDefs::RenderMode mode;
    130     bool m_bIsGuestSupportsGraphics : 1;
     138    //virtual void saveMachineViewSettings();
     139    //virtual void cleanupConsoleConnections();
     140    //virtual void cleanupFilters();
     141    virtual void cleanupCommon();
     142    virtual void cleanupFrameBuffer();
    131143
    132144private slots:
     145
     146    void sltMousePointerShapeChange(bool fIsVisible, bool fHasAlpha,
     147                                    uint uXHot, uint uYHot, uint uWidth, uint uHeight,
     148                                    const uchar *pShapeData);
     149    void sltMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor);
     150    void sltKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock);
     151    void sltStateChange(KMachineState state);
     152    void sltAdditionsStateChange();
    133153
    134154#ifdef Q_WS_MAC
     
    143163private:
    144164
    145     /* Event processors: */
     165    /* Cross-platforms event processors: */
    146166    bool event(QEvent *pEvent);
    147167    bool eventFilter(QObject *pWatched, QEvent *pEvent);
     168    void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
     169    bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
     170    bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
     171                    Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
     172                    int aWheelDelta, Qt::Orientation aWheelDir);
     173    void resizeEvent(QResizeEvent *pEvent);
     174    void moveEvent(QMoveEvent *pEvent);
     175    void paintEvent(QPaintEvent *pEvent);
     176
     177    /* Platform specific event processors: */
    148178#if defined(Q_WS_WIN32)
     179    static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    149180    bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event);
    150181    bool winEvent(MSG *aMsg, long *aResult);
     
    156187    bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent);
    157188    void darwinGrabKeyboardEvents(bool fGrab);
    158 #endif
    159 #if defined (Q_WS_WIN32)
    160     static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    161 #elif defined (Q_WS_MAC)
    162189# ifdef QT_MAC_USE_COCOA
    163190    static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser);
     
    167194#endif
    168195
    169     /* Flags for keyEvent() */
    170     enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 };
    171     void emitKeyboardStateChanged()
    172     {
    173         emit keyboardStateChanged((m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) |
    174                                   (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0));
    175     }
    176     void emitMouseStateChanged()
    177     {
    178         emit mouseStateChanged((m_bIsMouseCaptured ? UIMouseStateType_MouseCaptured : 0) |
    179                                (m_bIsMouseAbsolute ? UIMouseStateType_MouseAbsolute : 0) |
    180                                (!m_bIsMouseIntegrated ? UIMouseStateType_MouseAbsoluteDisabled : 0));
    181     }
    182 
    183     void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
    184     bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
    185     bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    186                     Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
    187                     int aWheelDelta, Qt::Orientation aWheelDir);
    188     void resizeEvent(QResizeEvent *pEvent);
    189     void moveEvent(QMoveEvent *pEvent);
    190     void paintEvent(QPaintEvent *pEvent);
    191 
    192     /* Private members: */
    193     bool shouldHideHostPointer() const { return m_bIsMouseCaptured || (m_bIsMouseAbsolute && mHideHostPointer); }
    194     bool isRunning() { return mLastState == KMachineState_Running || mLastState == KMachineState_Teleporting || mLastState == KMachineState_LiveSnapshotting; }
     196    /* Private helpers: */
    195197    void fixModifierState(LONG *piCodes, uint *puCount);
    196     void scrollBy(int dx, int dy);
    197198    QPoint viewportToContents(const QPoint &vp) const;
    198199    void updateSliders();
     200    void scrollBy(int dx, int dy);
    199201#ifdef VBOX_WITH_VIDEOHWACCEL
    200202    void scrollContentsBy(int dx, int dy);
    201203#endif
    202     void onStateChange(KMachineState state);
    203     void captureKbd(bool aCapture, bool aEmitSignal = true);
    204     void captureMouse(bool aCapture, bool aEmitSignal = true);
     204    void emitKeyboardStateChanged();
     205    void emitMouseStateChanged();
     206    void captureKbd(bool fCapture, bool fEmitSignal = true);
     207    void captureMouse(bool fCapture, bool fEmitSignal = true);
     208    void saveKeyStates();
    205209    bool processHotKey(const QKeySequence &key, const QList<QAction*> &data);
    206210    void releaseAllPressedKeys(bool aReleaseHostKey = true);
    207     void saveKeyStates();
    208211    void sendChangedKeyStates();
    209212    void updateMouseClipping();
    210     //void setPointerShape(MousePointerChangeEvent *pEvent);
    211 
    212     enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
    213     void storeConsoleSize(int aWidth, int aHeight);
    214     void setMouseIntegrationLocked(bool bDisabled);
    215     void setDesktopGeometry(DesktopGeo aGeo, int aWidth, int aHeight);
    216     virtual void maybeRestrictMinimumSize() = 0;
    217     QRect availableGeometry();
     213    void setPointerShape(const uchar *pShapeData, bool fHasAlpha,
     214                         uint uXHot, uint uYHot, uint uWidth, uint uHeight);
     215    void setMouseIntegrationLocked(bool fDisabled);
     216
     217    /* Private getters: */
     218    bool isRunning() { return m_machineState == KMachineState_Running || m_machineState == KMachineState_Teleporting || m_machineState == KMachineState_LiveSnapshotting; }
     219    bool shouldHideHostPointer() const { return m_bIsMouseCaptured || (m_bIsMouseAbsolute && m_fHideHostPointer); }
    218220
    219221    static void dimImage(QImage &img);
     
    222224    UIMachineWindow *m_pMachineWindow;
    223225    CConsole m_console;
     226    VBoxDefs::RenderMode m_mode;
    224227    const VBoxGlobalSettings &m_globalSettings;
    225     KMachineState mLastState;
    226 
    227     QPoint mLastPos;
    228     QPoint mCapturedPos;
     228    KMachineState m_machineState;
     229    UIFrameBuffer *m_pFrameBuffer;
     230
     231    QCursor m_lastCursor;
     232#if defined(Q_WS_WIN)
     233    HCURSOR m_alphaCursor;
     234#endif
     235    QPoint m_lastMousePos;
     236    QPoint m_capturedMousePos;
    229237    int m_iLastMouseWheelDelta;
    230238
    231     enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 };
    232     uint8_t mPressedKeys[128];
    233     uint8_t mPressedKeysCopy[128];
    234 
    235     long muNumLockAdaptionCnt;
    236     long muCapsLockAdaptionCnt;
     239    uint8_t m_pressedKeys[128];
     240    uint8_t m_pressedKeysCopy[128];
     241
     242    long m_uNumLockAdaptionCnt;
     243    long m_uCapsLockAdaptionCnt;
    237244
    238245    bool m_bIsAutoCaptureDisabled : 1;
     
    243250    bool m_bIsHostkeyPressed : 1;
    244251    bool m_bIsHostkeyAlone : 1;
    245     bool hostkey_in_capture : 1;
     252    bool m_bHostkeyInCapture : 1;
     253    bool m_bIsGuestSupportsGraphics : 1;
    246254    bool m_bIsMachineWindowResizeIgnored : 1;
    247255    bool m_bIsFrameBufferResizeIgnored : 1;
    248256    bool m_bIsGuestResizeIgnored : 1;
     257    bool m_numLock : 1;
     258    bool m_scrollLock : 1;
     259    bool m_capsLock : 1;
     260    bool m_fPassCAD;
     261    bool m_fHideHostPointer;
     262#ifdef VBOX_WITH_VIDEOHWACCEL
     263    bool m_fAccelerate2DVideo;
     264#endif
     265#if 0 // TODO: Do we need this flag?
    249266    bool mDoResize : 1;
    250     bool mNumLock : 1;
    251     bool mScrollLock : 1;
    252     bool mCapsLock : 1;
    253 
    254 #ifdef VBOX_WITH_VIDEOHWACCEL
    255     bool mAccelerate2DVideo;
    256 #endif
    257 
    258 #if defined(Q_WS_WIN)
    259     HCURSOR mAlphaCursor;
    260267#endif
    261268
     
    263270# ifndef QT_MAC_USE_COCOA
    264271    /** Event handler reference. NULL if the handler isn't installed. */
    265     EventHandlerRef mDarwinEventHandlerRef;
     272    EventHandlerRef m_darwinEventHandlerRef;
    266273# endif /* !QT_MAC_USE_COCOA */
    267274    /** The current modifier key mask. Used to figure out which modifier
    268275     *  key was pressed when we get a kEventRawKeyModifiersChanged event. */
    269     UInt32 mDarwinKeyModifiers;
    270     bool mKeyboardGrabbed;
    271 #endif
    272 
    273     UIFrameBuffer *mFrameBuf;
    274 
    275     QPixmap mPausedShot;
     276    UInt32 m_darwinKeyModifiers;
     277    bool m_fKeyboardGrabbed;
     278#endif
     279
     280    QPixmap m_pauseShot;
    276281#if defined(Q_WS_MAC)
    277282# if !defined (QT_MAC_USE_COCOA)
     
    281286    bool mDockIconEnabled;
    282287#endif
    283     DesktopGeo mDesktopGeo;
    284     QRect mDesktopGeometry;
    285     QRect mStoredConsoleSize;
    286     bool mPassCAD;
    287     bool mHideHostPointer;
    288     QCursor mLastCursor;
     288    DesktopGeo m_desktopGeometryType;
     289    QRect m_desktopGeometry;
     290    QRect m_storedConsoleSize;
    289291
    290292    /* Friend classes: */
    291293    friend class UIFrameBuffer;
    292294    friend class UIFrameBufferQImage;
     295    friend class UIFrameBufferQuartz2D;
    293296};
    294297
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r26709 r26754  
    537537        case UIConsoleEventType_MousePointerShapeChange:
    538538        {
    539 #if 0 // TODO: Move to machine view!
    540             MousePointerChangeEvent *me = (MousePointerChangeEvent*)pEvent;
    541             /* Change cursor shape only when mouse integration is
    542              * supported (change mouse shape type event may arrive after
    543              * mouse capability change that disables integration. */
    544             if (m_bIsMouseAbsolute)
    545                 setPointerShape (me);
    546             else
    547                 /* Note: actually we should still remember the requested
    548                  * cursor shape.  If we can't do that, at least remember
    549                  * the requested visiblilty. */
    550                 mHideHostPointer = !me->isVisible();
    551 #endif
    552539            UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent);
    553540            emit sigMousePointerShapeChange(pConsoleEvent->isVisible(), pConsoleEvent->hasAlpha(),
     
    560547        case UIConsoleEventType_MouseCapabilityChange:
    561548        {
    562 #if 0 // TODO: Move to machine view!
    563             MouseCapabilityEvent *me = (MouseCapabilityEvent*)pEvent;
    564             if (m_bIsMouseAbsolute != me->supportsAbsolute())
    565             {
    566                 m_bIsMouseAbsolute = me->supportsAbsolute();
    567                 /* correct the mouse capture state and reset the cursor
    568                  * to the default shape if necessary */
    569                 if (m_bIsMouseAbsolute)
    570                 {
    571                     CMouse mouse = m_console.GetMouse();
    572                     mouse.PutMouseEventAbsolute (-1, -1, 0,
    573                                                  0 /* Horizontal wheel */,
    574                                                  0);
    575                     captureMouse (false, false);
    576                 }
    577                 else
    578                     viewport()->unsetCursor();
    579                 emitMouseStateChanged();
    580                 vboxProblem().remindAboutMouseIntegration (m_bIsMouseAbsolute);
    581             }
    582             if (me->needsHostCursor())
    583                 setMouseIntegrationLocked (false);
    584             else
    585                 setMouseIntegrationLocked (true);
    586             return true;
    587 #endif
    588549            UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent);
    589550            emit sigMouseCapabilityChange(pConsoleEvent->supportsAbsolute(), pConsoleEvent->needsHostCursor());
     
    593554        case UIConsoleEventType_KeyboardLedsChange:
    594555        {
    595 #if 0 // TODO: Move to machine view!
    596             ModifierKeyChangeEvent *me = (ModifierKeyChangeEvent* )pEvent;
    597             if (me->numLock() != mNumLock)
    598                 muNumLockAdaptionCnt = 2;
    599             if (me->capsLock() != mCapsLock)
    600                 muCapsLockAdaptionCnt = 2;
    601             mNumLock    = me->numLock();
    602             mCapsLock   = me->capsLock();
    603             mScrollLock = me->scrollLock();
    604 #endif
    605556            UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent);
    606557            emit sigKeyboardLedsChange(pConsoleEvent->numLock(), pConsoleEvent->capsLock(), pConsoleEvent->scrollLock());
     
    610561        case UIConsoleEventType_StateChange:
    611562        {
    612 #if 0 // TODO: Move to machine view!
    613             MachineUIStateChangeEvent *me = (MachineUIStateChangeEvent *) pEvent;
    614             LogFlowFunc (("MachineUIStateChangeEventType: state=%d\n",
    615                            me->machineState()));
    616             onStateChange (me->machineState());
    617             emit machineStateChanged (me->machineState());
    618 #endif
    619563            UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent);
    620564            emit sigStateChange(pConsoleEvent->machineState());
     
    624568        case UIConsoleEventType_AdditionsStateChange:
    625569        {
    626 #if 0 // TODO: Move to machine view!
    627             GuestAdditionsChangeEvent *ge = (GuestAdditionsChangeEvent *) pEvent;
    628             LogFlowFunc (("UIAdditionsStateChangeEventType\n"));
    629             /* Always send a size hint if we are in fullscreen or seamless
    630              * when the graphics capability is enabled, in case the host
    631              * resolution has changed since the VM was last run. */
    632 #if 0
    633             if (!mDoResize && !m_bIsGuestSupportsGraphics &&
    634                 ge->supportsGraphics() &&
    635                 (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))
    636                 mDoResize = true;
    637 #endif
    638             m_bIsGuestSupportsGraphics = ge->supportsGraphics();
    639 
    640             maybeRestrictMinimumSize();
    641 
    642 #if 0
    643             /* This will only be acted upon if mDoResize is true. */
    644             doResizeHint();
    645 #endif
    646 
    647             emit additionsStateChanged (ge->additionVersion(),
    648                                         ge->additionActive(),
    649                                         ge->supportsSeamless(),
    650                                         ge->supportsGraphics());
    651 #endif
    652570            emit sigAdditionsStateChange();
    653571            return true;
     
    656574        case UIConsoleEventType_NetworkAdapterChange:
    657575        {
    658 #if 0 // TODO: Move to machine view!
    659             /* no specific adapter information stored in this
    660              * event is currently used */
    661             emit networkStateChange();
    662 #endif
    663576            UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent);
    664577            emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter());
     
    688601        case UIConsoleEventType_MediumChange:
    689602        {
    690 #if 0 // TODO: Move to machine view!
    691             MediaDriveChangeEvent *mce = (MediaDriveChangeEvent *) pEvent;
    692             LogFlowFunc (("MediaChangeEvent\n"));
    693 
    694             emit mediaDriveChanged (mce->type());
    695 #endif
    696603            UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent);
    697604            emit sigMediumChange(pConsoleEvent->mediumAttahment());
     
    726633        case UIConsoleEventType_USBDeviceStateChange:
    727634        {
    728 #if 0 // TODO: Move to machine view!
    729             UIUSBDeviceUIStateChangeEvent *ue = (UIUSBDeviceUIStateChangeEvent *)pEvent;
    730 
    731             bool success = ue->error().isNull();
    732 
    733             if (!success)
    734             {
    735                 if (ue->attached())
    736                     vboxProblem().cannotAttachUSBDevice (
    737                         m_console,
    738                         vboxGlobal().details (ue->device()), ue->error());
    739                 else
    740                     vboxProblem().cannotDetachUSBDevice (
    741                         m_console,
    742                         vboxGlobal().details (ue->device()), ue->error());
    743             }
    744 
    745             emit usbStateChange();
    746 #endif
    747635            UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent);
    748636            emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error());
     
    758646        case UIConsoleEventType_RuntimeError:
    759647        {
    760 #if 0 // TODO: Move to machine view!
    761             UIRuntimeErrorEvent *pConsoleEvent = (UIRuntimeErrorEvent *) pEvent;
    762             vboxProblem().showRuntimeError(m_console, ee->fatal(), ee->errorID(), ee->message());
    763 #endif
    764648            UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent);
    765649            emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message());
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h

    r26709 r26754  
    7575
    7676    /* Console signals: */
    77     void sigMousePointerShapeChange(bool bIsVisible, bool bHasAlpha, bool uXHot, bool uYHot, bool uWidth, bool uHeight, const uchar *pShapeData);
     77    void sigMousePointerShapeChange(bool bIsVisible, bool bHasAlpha, uint uXHot, uint uYHot, uint uWidth, uint uHeight, const uchar *pShapeData);
    7878    void sigMouseCapabilityChange(bool bIsSupportsAbsolute, bool bNeedsHostCursor);
    7979    void sigKeyboardLedsChange(bool bNumLock, bool bCapsLock, bool bScrollLock);
     
    9191    void sigUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error);
    9292    void sigSharedFolderChange();
    93     void sigRuntimeError(bool bIsFatal, QString strErrorId, QString strMessage);
     93    void sigRuntimeError(bool bIsFatal, const QString &strErrorId, const QString &strMessage);
    9494
    9595private:
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp

    r26730 r26754  
    2525#include <QApplication>
    2626#include <QDesktopWidget>
     27#include <QMainWindow>
     28#include <QMenuBar>
    2729
    2830/* Local includes */
     
    5456    /* Prepare event-filters: */
    5557    prepareFilters();
     58
     59    /* Prepare console connections: */
     60    prepareConsoleConnections();
    5661
    5762    /* Load machine view settings: */
     
    104109            ar = dwt->availableGeometry(pTopLevelWidget->pos());
    105110
    106         fr = VBoxGlobal::normalizeGeometry(fr, ar, mode != VBoxDefs::SDLMode /* canResize */);
     111        fr = VBoxGlobal::normalizeGeometry(fr, ar, mode() != VBoxDefs::SDLMode /* canResize */);
    107112    }
    108113
     
    122127     * We need to do that because we cannot correctly draw in a scrolled window in SDL mode.
    123128     * In all other modes, or when auto-resize is in force, this function does nothing. */
    124     if (mode == VBoxDefs::SDLMode)
    125     {
    126         if (!m_bIsGuestSupportsGraphics || !m_bIsGuestAutoresizeEnabled)
     129    if (mode() == VBoxDefs::SDLMode)
     130    {
     131        if (!isGuestSupportsGraphics() || !m_bIsGuestAutoresizeEnabled)
    127132            setMinimumSize(sizeHint());
    128133        else
     
    134139{
    135140#if 0 // TODO: fix that logic!
    136     if (m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled)
     141    if (isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
    137142    {
    138143        /* If this slot is invoked directly then use the passed size
     
    180185        maybeRestrictMinimumSize();
    181186
    182         if (m_bIsGuestSupportsGraphics && m_bIsGuestAutoresizeEnabled)
     187        if (isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
    183188            doResizeHint();
    184189    }
     
    192197}
    193198
     199void UIMachineViewNormal::prepareFilters()
     200{
     201    /* Parent class filters: */
     202    UIMachineView::prepareFilters();
     203
     204    /* Normal window filters: */
     205    qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);
     206}
     207
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.h

    r26730 r26754  
    5757private:
    5858
     59    /* Prepare routines: */
     60    void prepareFilters();
     61
    5962    bool m_bIsGuestAutoresizeEnabled : 1;
    6063
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