VirtualBox

Changeset 30408 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 24, 2010 3:41:27 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
63034
Message:

FE/Qt: 5078: Separate UI Mouse-Handler for running VM - initial implementation commit.

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

Legend:

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

    r30407 r30408  
    327327        src/runtime/UIActionsPool.h \
    328328        src/runtime/UIIndicatorsPool.h \
     329        src/runtime/UIMouseHandler.h \
    329330        src/runtime/UIMachineLogic.h \
    330331        src/runtime/UIMachineView.h \
     
    460461        src/runtime/UIActionsPool.cpp \
    461462        src/runtime/UIIndicatorsPool.cpp \
     463        src/runtime/UIMouseHandler.cpp \
    462464        src/runtime/UIFrameBuffer.cpp \
    463465        src/runtime/UIFrameBufferQGL.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp

    r30330 r30408  
    2424#include "UIDownloaderAdditions.h"
    2525#include "UIIconPool.h"
     26#include "UIMouseHandler.h"
    2627#include "UIMachineLogic.h"
    2728#include "UIMachineLogicFullscreen.h"
     
    337338    , m_pActionsPool(pActionsPool)
    338339    , m_visualStateType(visualStateType)
     340    , m_pMouseHandler(0)
    339341    , m_pRunningActions(0)
    340342    , m_pRunningOrPausedActions(0)
     
    370372{
    371373    m_machineWindowsList << pMachineWindow;
     374}
     375
     376void UIMachineLogic::setMouseHandler(UIMouseHandler *pMouseHandler)
     377{
     378    m_pMouseHandler = pMouseHandler;
    372379}
    373380
     
    904911
    905912    /* Disable/Enable mouse-integration for all view(s): */
    906     foreach(UIMachineWindow *pMachineWindow, machineWindows())
    907         pMachineWindow->machineView()->setMouseIntegrationEnabled(!fOff);
     913    m_pMouseHandler->setMouseIntegrationEnabled(!fOff);
    908914}
    909915
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h

    r30330 r30408  
    3939class UISession;
    4040class UIActionsPool;
     41class UIMouseHandler;
    4142class UIMachineWindow;
    4243class UIMachineView;
     
    6869    UIVisualStateType visualStateType() const { return m_visualStateType; }
    6970    const QList<UIMachineWindow*>& machineWindows() const { return m_machineWindowsList; }
     71    UIMouseHandler* mouseHandler() const { return m_pMouseHandler; }
    7072    UIMachineWindow* mainMachineWindow() const;
    7173    UIMachineWindow* defaultMachineWindow() const;
     
    100102
    101103    /* Protected members: */
     104    void setMouseHandler(UIMouseHandler *pMouseHandler);
    102105    void addMachineWindow(UIMachineWindow *pMachineWindow);
    103106    void retranslateUi();
     
    192195    UIActionsPool *m_pActionsPool;
    193196    UIVisualStateType m_visualStateType;
     197    UIMouseHandler *m_pMouseHandler;
    194198    QList<UIMachineWindow*> m_machineWindowsList;
    195199
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r30407 r30408  
    3636#include "UISession.h"
    3737#include "UIActionsPool.h"
     38#include "UIMouseHandler.h"
    3839#include "UIMachineLogic.h"
    3940#include "UIMachineWindow.h"
     
    157158}
    158159
    159 int UIMachineView::mouseState() const
    160 {
    161     return (uisession()->isMouseCaptured() ? UIMouseStateType_MouseCaptured : 0) |
    162            (uisession()->isMouseSupportsAbsolute() ? UIMouseStateType_MouseAbsolute : 0) |
    163            (uisession()->isMouseIntegrated() ? 0 : UIMouseStateType_MouseAbsoluteDisabled);
    164 }
    165 
    166 void UIMachineView::setMouseIntegrationEnabled(bool fEnabled)
    167 {
    168     /* Do not change anything if its already so: */
    169     if (uisession()->isMouseIntegrated() == fEnabled)
    170         return;
    171 
    172     /* Store new mouse 'integrated' state value: */
    173     uisession()->setMouseIntegrated(fEnabled);
    174 
    175     /* We should capture/release mouse depending on mouse 'integrated' state value: */
    176     captureMouse(!uisession()->isMouseIntegrated(), false /* emit signal? */);
    177 
    178     /* Update mouse cursor shape: */
    179     updateMouseCursorShape();
    180 
    181     /* If mouse is integrated and supports absolute pointing
    182      * we should switch guest mouse to the absolute mode: */
    183     if (uisession()->isMouseIntegrated() && uisession()->isMouseSupportsAbsolute())
    184     {
    185         CMouse mouse = session().GetConsole().GetMouse();
    186         mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
    187     }
    188 
    189     /* Notify all listeners: */
    190     emitMouseStateChanged();
    191 }
    192 
    193160UIMachineView::UIMachineView(  UIMachineWindow *pMachineWindow
    194161#ifdef VBOX_WITH_VIDEOHWACCEL
     
    205172    , m_previousState(KMachineState_Null)
    206173    , m_desktopGeometryType(DesktopGeo_Invalid)
    207     , m_iLastMouseWheelDelta(0)
    208174    , m_bIsKeyboardCaptured(false)
    209175    , m_bIsHostkeyPressed(false)
     
    215181    , m_fAccelerate2DVideo(bAccelerate2DVideo)
    216182#endif /* VBOX_WITH_VIDEOHWACCEL */
    217 #ifdef Q_WS_WIN
    218     , m_fItsMeWhoCapturedMouse(false)
    219 #endif
    220183#ifdef Q_WS_MAC
    221184    , m_darwinKeyModifiers(0)
     
    385348    machine.SetExtraData(strKey, strValue);
    386349}
    387 
    388 void UIMachineView::updateMouseCursorShape()
    389 {
    390     /* First of all, we should check if the host pointer should be visible.
    391      * We should hide host pointer in case of:
    392      * 1. mouse is 'captured' or
    393      * 2. mouse is 'not captured', 'integrated', 'absolute', host pointer is hidden by the guest. */
    394     if (uisession()->isMouseCaptured() ||
    395         (uisession()->isMouseIntegrated() &&
    396          uisession()->isMouseSupportsAbsolute() &&
    397          uisession()->isHidingHostPointer()))
    398     {
    399         viewport()->setCursor(Qt::BlankCursor);
    400     }
    401 
    402     else
    403 
    404     /* Otherwise we should show host pointer with guest shape assigned to it if:
    405      * mouse is 'integrated', 'absolute', valid pointer shape is present. */
    406     if (uisession()->isMouseIntegrated() &&
    407         uisession()->isMouseSupportsAbsolute() &&
    408         uisession()->isValidPointerShapePresent())
    409     {
    410         viewport()->setCursor(uisession()->cursor());
    411     }
    412 
    413     else
    414 
    415     /* There could be other states covering such situations as:
    416      * 1. mouse is 'not captured', 'integrated', 'not absolute' or
    417      * 2. mouse is 'not captured', 'not integrated', 'absolute'.
    418      * We have nothing to do with that except just unset the cursor. */
    419     viewport()->unsetCursor();
    420 }
    421 
    422 #ifdef Q_WS_WIN
    423 /* This method is actually required only because under win-host
    424  * we do not really grab the mouse in case of capturing it.
    425  * I have to check if its really need, may be just grabMouse() will be enought: */
    426 void UIMachineView::updateMouseCursorClipping()
    427 {
    428     if (m_fItsMeWhoCapturedMouse)
    429     {
    430         QRect r = viewport()->rect();
    431         r.moveTopLeft(viewport()->mapToGlobal(QPoint(0, 0)));
    432         RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
    433         ::ClipCursor(&rect);
    434     }
    435 }
    436 #endif
    437350
    438351void UIMachineView::updateSliders()
     
    643556    NOREF(ok);
    644557#endif
     558
     559    /* Register mouse-handler: */
     560    machineLogic()->mouseHandler()->addMachineView(screenId(), this);
    645561}
    646562
     
    662578    /* Machine state-change updater: */
    663579    connect(uisession(), SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged()));
    664 
    665     /* Mouse pointer shape state-change updater: */
    666     connect(uisession(), SIGNAL(sigMousePointerShapeChange()), this, SLOT(sltMousePointerShapeChanged()));
    667 
    668     /* Mouse capability state-change updater: */
    669     connect(uisession(), SIGNAL(sigMouseCapabilityChange()), this, SLOT(sltMouseCapabilityChanged()));
    670 
    671     /* Mouse captivity status-change updater: */
    672     connect(uisession(), SIGNAL(sigMouseCapturedStatusChanged()), this, SLOT(sltMouseCapturedStatusChanged()));
    673580}
    674581
     
    708615void UIMachineView::cleanupCommon()
    709616{
     617    /* Unregister mouse-handler: */
     618    machineLogic()->mouseHandler()->delMachineView(screenId());
     619
    710620#ifdef Q_WS_PM
    711621    bool ok = VBoxHlpUninstallKbdHook(0, winId(), UM_PREACCEL_CHAR);
     
    953863bool UIMachineView::eventFilter(QObject *pWatched, QEvent *pEvent)
    954864{
     865#ifdef VBOX_WITH_VIDEOHWACCEL
    955866    if (pWatched == viewport())
    956867    {
    957868        switch (pEvent->type())
    958869        {
    959             case QEvent::MouseMove:
    960             case QEvent::MouseButtonRelease:
    961             {
    962                 /* Check if we should propagate this event to another window: */
    963                 QWidget *pWidgetAt = QApplication::widgetAt(QCursor::pos());
    964                 if (pWidgetAt && pWidgetAt->window() && pWidgetAt->window()->inherits("UIMachineWindow") &&
    965                     pWidgetAt->window() != machineWindowWrapper()->machineWindow())
    966                 {
    967                     /* Get current mouse-move event: */
    968                     QMouseEvent *pOldMouseEvent = static_cast<QMouseEvent*>(pEvent);
    969 
    970                     /* Get real destination window of that event: */
    971                     UIMachineWindow *pMachineWindow =
    972                         pWidgetAt->window()->inherits("UIMachineWindowNormal") ?
    973                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowNormal*>(pWidgetAt->window())) :
    974                         pWidgetAt->window()->inherits("UIMachineWindowFullscreen") ?
    975                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowFullscreen*>(pWidgetAt->window())) :
    976                         pWidgetAt->window()->inherits("UIMachineWindowSeamless") ?
    977                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowSeamless*>(pWidgetAt->window())) : 0;
    978                     if (pMachineWindow)
    979                     {
    980                         /* Get viewport: */
    981                         QWidget *pOtherViewport = pMachineWindow->machineView()->viewport();
    982 
    983                         /* Prepare redirected mouse-move event: */
    984                         QMouseEvent *pNewMouseEvent = new QMouseEvent(pOldMouseEvent->type(),
    985                                                                       pOtherViewport->mapFromGlobal(pOldMouseEvent->globalPos()),
    986                                                                       pOldMouseEvent->globalPos(),
    987                                                                       pOldMouseEvent->button(),
    988                                                                       pOldMouseEvent->buttons(),
    989                                                                       pOldMouseEvent->modifiers());
    990 
    991                         /* Send that event to real destination: */
    992                         QApplication::postEvent(pOtherViewport, pNewMouseEvent);
    993 
    994                         /* Filter out that event: */
    995                         return true;
    996                     }
    997                 }
    998 
    999                 /* Check if we should activate window under cursor: */
    1000                 if (QApplication::activeWindow() &&
    1001                     QApplication::activeWindow()->inherits("UIMachineWindow") &&
    1002                     QApplication::activeWindow() != machineWindowWrapper()->machineWindow())
    1003                 {
    1004                     /* Activating hovered machine window: */
    1005                     machineWindowWrapper()->machineWindow()->activateWindow();
    1006 #ifdef Q_WS_X11
    1007                     /* On X11 its not enough to just activate window if you
    1008                      * want to raise it also, so we will make it separately: */
    1009                     machineWindowWrapper()->machineWindow()->raise();
    1010 #endif /* Q_WS_X11 */
    1011                 }
    1012 
    1013                 /* This event should be also processed using next 'case': */
    1014             }
    1015             case QEvent::MouseButtonPress:
    1016             case QEvent::MouseButtonDblClick:
    1017             {
    1018                 QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
    1019                 m_iLastMouseWheelDelta = 0;
    1020                 if (mouseEvent(pMouseEvent->type(), pMouseEvent->pos(), pMouseEvent->globalPos(),
    1021                                pMouseEvent->buttons(), pMouseEvent->modifiers(), 0, Qt::Horizontal))
    1022                     return true;
    1023                 break;
    1024             }
    1025             case QEvent::Wheel:
    1026             {
    1027                 QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent);
    1028                 /* There are pointing devices which send smaller values for the delta than 120.
    1029                  * Here we sum them up until we are greater than 120. This allows to have finer control
    1030                  * over the speed acceleration & enables such devices to send a valid wheel event to our
    1031                  * guest mouse device at all: */
    1032                 int iDelta = 0;
    1033                 m_iLastMouseWheelDelta += pWheelEvent->delta();
    1034                 if (qAbs(m_iLastMouseWheelDelta) >= 120)
    1035                 {
    1036                     iDelta = m_iLastMouseWheelDelta;
    1037                     m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
    1038                 }
    1039                 if (mouseEvent(pWheelEvent->type(), pWheelEvent->pos(), pWheelEvent->globalPos(),
    1040 #ifdef QT_MAC_USE_COCOA
    1041                                /* Qt Cocoa is buggy. It always reports a left button pressed when the
    1042                                 * mouse wheel event occurs. A workaround is to ask the application which
    1043                                 * buttons are pressed currently: */
    1044                                QApplication::mouseButtons(),
    1045 #else /* QT_MAC_USE_COCOA */
    1046                                pWheelEvent->buttons(),
    1047 #endif /* !QT_MAC_USE_COCOA */
    1048                                pWheelEvent->modifiers(),
    1049                                iDelta, pWheelEvent->orientation()))
    1050                     return true;
    1051                 break;
    1052             }
    1053 #ifdef Q_WS_MAC
    1054             case QEvent::Leave:
    1055             {
    1056                 /* Enable mouse event compression if we leave the VM view. This is necessary for
    1057                  * having smooth resizing of the VM/other windows: */
    1058                 setMouseCoalescingEnabled(true);
    1059                 break;
    1060             }
    1061             case QEvent::Enter:
    1062             {
    1063                 /* Disable mouse event compression if we enter the VM view. So all mouse events are
    1064                  * registered in the VM. Only do this if the keyboard/mouse is grabbed (this is when
    1065                  * we have a valid event handler): */
    1066                 setMouseCoalescingEnabled(false);
    1067                 break;
    1068             }
    1069 #endif /* Q_WS_MAC */
    1070870            case QEvent::Resize:
    1071871            {
    1072 #ifdef Q_WS_WIN32
    1073                 updateMouseCursorClipping();
    1074 #endif
    1075 #ifdef VBOX_WITH_VIDEOHWACCEL
    1076872                if (m_pFrameBuffer)
    1077                 {
    1078873                    m_pFrameBuffer->viewportResized(static_cast<QResizeEvent*>(pEvent));
    1079                 }
    1080 #endif
    1081874                break;
    1082875            }
     
    1085878        }
    1086879    }
    1087     else if (pWatched == machineWindowWrapper()->machineWindow())
     880#endif /* VBOX_WITH_VIDEOHWACCEL */
     881    if (pWatched == machineWindowWrapper()->machineWindow())
    1088882    {
    1089883        switch (pEvent->type())
     
    1173967                viewport()->repaint();
    1174968            }
    1175             /* Reuse the focus event handler to uncapture everything: */
     969            /* Reuse the focus event handler to uncapture keyboard: */
    1176970            if (hasFocus())
    1177971                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     
    1180974        case KMachineState_Stuck:
    1181975        {
    1182             /* Reuse the focus event handler to uncapture everything: */
     976            /* Reuse the focus event handler to uncapture keyboard: */
    1183977            if (hasFocus())
    1184978                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     
    12131007}
    12141008
    1215 void UIMachineView::sltMousePointerShapeChanged()
    1216 {
    1217     /* Update mouse cursor: */
    1218     updateMouseCursorShape();
    1219 }
    1220 
    1221 void UIMachineView::sltMouseCapabilityChanged()
    1222 {
    1223     /* We should release mouse if guest notified us about it supports 'absolute' mouse
    1224      * and mouse is in 'integrated' mode, which could be chosen from main machine menu: */
    1225     if (uisession()->isMouseIntegrated() && uisession()->isMouseSupportsAbsolute())
    1226     {
    1227         CMouse mouse = session().GetConsole().GetMouse();
    1228         mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
    1229         captureMouse(false, false);
    1230     }
    1231 
    1232     /* Update mouse cursor shape: */
    1233     updateMouseCursorShape();
    1234 
    1235     /* Notify user about mouse 'absolute' state if method was called by signal: */
    1236     if (sender()) vboxProblem().remindAboutMouseIntegration(uisession()->isMouseSupportsAbsolute());
    1237 
    1238     /* Notify all listeners: */
    1239     emitMouseStateChanged();
    1240 }
    1241 
    1242 void UIMachineView::sltMouseCapturedStatusChanged()
    1243 {
    1244     /* If mouse 'captured' state value changed to 'false': */
    1245     if (!uisession()->isMouseCaptured())
    1246     {
    1247         /* Releasing grabbed mouse from that window: */
    1248 #ifdef Q_WS_WIN
    1249         m_fItsMeWhoCapturedMouse = false;
    1250         ::ClipCursor(NULL);
    1251 #else
    1252         viewport()->releaseMouse();
    1253 #endif /* Q_WS_WIN */
    1254     }
    1255 
    1256     /* Update mouse cursor shape: */
    1257     updateMouseCursorShape();
    1258 }
    1259 
    12601009void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */)
    12611010{
     
    12771026    else
    12781027    {
    1279         captureMouse(false);
    12801028        captureKbd(false, false);
    12811029        releaseAllPressedKeys(fReleaseHostKey);
     
    13521100                    captureKbd(false);
    13531101                    if (!(uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated()))
    1354                         captureMouse(false);
     1102                        machineLogic()->mouseHandler()->captureMouse(screenId());
    13551103                }
    13561104
     
    14671215                                qApp->processEvents();
    14681216#endif
    1469                                 captureMouse(m_bIsKeyboardCaptured);
     1217                                if (m_bIsKeyboardCaptured)
     1218                                    machineLogic()->mouseHandler()->captureMouse(screenId());
     1219                                else
     1220                                    machineLogic()->mouseHandler()->releaseMouse();
    14701221                            }
    14711222                        }
     
    15621313    /* Grab the key from Qt: */
    15631314    return true;
    1564 }
    1565 
    1566 bool UIMachineView::mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    1567                                Qt::MouseButtons aButtons, Qt::KeyboardModifiers /* aModifiers */,
    1568                                int aWheelDelta, Qt::Orientation aWheelDir)
    1569 {
    1570     int state = 0;
    1571     if (aButtons & Qt::LeftButton)
    1572         state |= KMouseButtonState_LeftButton;
    1573     if (aButtons & Qt::RightButton)
    1574         state |= KMouseButtonState_RightButton;
    1575     if (aButtons & Qt::MidButton)
    1576         state |= KMouseButtonState_MiddleButton;
    1577     if (aButtons & Qt::XButton1)
    1578         state |= KMouseButtonState_XButton1;
    1579     if (aButtons & Qt::XButton2)
    1580         state |= KMouseButtonState_XButton2;
    1581 
    1582 #ifdef Q_WS_MAC
    1583     /* Simulate the right click on Host+Left Mouse: */
    1584     if (m_bIsHostkeyPressed &&
    1585         m_bIsHostkeyAlone &&
    1586         state == KMouseButtonState_LeftButton)
    1587         state = KMouseButtonState_RightButton;
    1588 #endif /* Q_WS_MAC */
    1589 
    1590     int wheelVertical = 0;
    1591     int wheelHorizontal = 0;
    1592     if (aWheelDir == Qt::Vertical)
    1593     {
    1594         /* The absolute value of wheel delta is 120 units per every wheel move;
    1595          * positive deltas correspond to counterclockwize rotations (usually up),
    1596          * negative deltas correspond to clockwize (usually down). */
    1597         wheelVertical = - (aWheelDelta / 120);
    1598     }
    1599     else if (aWheelDir == Qt::Horizontal)
    1600         wheelHorizontal = aWheelDelta / 120;
    1601 
    1602     if (uisession()->isMouseCaptured())
    1603     {
    1604 #ifdef Q_WS_WIN32
    1605         /* Send pending WM_PAINT events: */
    1606         ::UpdateWindow(viewport()->winId());
    1607 #endif
    1608 
    1609         CMouse mouse = session().GetConsole().GetMouse();
    1610         mouse.PutMouseEvent(aGlobalPos.x() - m_lastMousePos.x(),
    1611                             aGlobalPos.y() - m_lastMousePos.y(),
    1612                             wheelVertical, wheelHorizontal, state);
    1613 
    1614 #if defined (Q_WS_MAC)
    1615         /*
    1616          * Keep the mouse from leaving the widget.
    1617          *
    1618          * This is a bit tricky to get right because if it escapes we won't necessarily
    1619          * get mouse events any longer and can warp it back. So, we keep safety zone
    1620          * of up to 300 pixels around the borders of the widget to prevent this from
    1621          * happening. Also, the mouse is warped back to the center of the widget.
    1622          *
    1623          * (Note, aPos seems to be unreliable, it caused endless recursion here at one points...)
    1624          * (Note, synergy and other remote clients might not like this cursor warping.)
    1625          */
    1626         QRect rect = viewport()->visibleRegion().boundingRect();
    1627         QPoint pw = viewport()->mapToGlobal(viewport()->pos());
    1628         rect.translate(pw.x(), pw.y());
    1629 
    1630         QRect dpRect = QApplication::desktop()->screenGeometry(viewport());
    1631         if (rect.intersects (dpRect))
    1632             rect = rect.intersect(dpRect);
    1633 
    1634         int wsafe = rect.width() / 6;
    1635         rect.setWidth(rect.width() - wsafe * 2);
    1636         rect.setLeft(rect.left() + wsafe);
    1637 
    1638         int hsafe = rect.height() / 6;
    1639         rect.setWidth(rect.height() - hsafe * 2);
    1640         rect.setTop(rect.top() + hsafe);
    1641 
    1642         if (rect.contains(aGlobalPos, true))
    1643             m_lastMousePos = aGlobalPos;
    1644         else
    1645         {
    1646             m_lastMousePos = rect.center();
    1647             QCursor::setPos(m_lastMousePos);
    1648         }
    1649 #else /* !Q_WS_MAC */
    1650 
    1651         /* "jerk" the mouse by bringing it to the opposite side
    1652          * to simulate the endless moving */
    1653 
    1654 # ifdef Q_WS_WIN32
    1655         int we = viewport()->width() - 1;
    1656         int he = viewport()->height() - 1;
    1657         QPoint p = aPos;
    1658         if (aPos.x() == 0)
    1659             p.setX(we - 1);
    1660         else if (aPos.x() == we)
    1661             p.setX(1);
    1662         if (aPos.y() == 0 )
    1663             p.setY(he - 1);
    1664         else if (aPos.y() == he)
    1665             p.setY(1);
    1666 
    1667         if (p != aPos)
    1668         {
    1669             m_lastMousePos = viewport()->mapToGlobal (p);
    1670             QCursor::setPos(m_lastMousePos);
    1671         }
    1672         else
    1673         {
    1674             m_lastMousePos = aGlobalPos;
    1675         }
    1676 # else
    1677         int we = QApplication::desktop()->width() - 1;
    1678         int he = QApplication::desktop()->height() - 1;
    1679         QPoint p = aGlobalPos;
    1680         if (aGlobalPos.x() == 0)
    1681             p.setX (we - 1);
    1682         else if (aGlobalPos.x() == we)
    1683             p.setX( 1 );
    1684         if (aGlobalPos.y() == 0)
    1685             p.setY (he - 1);
    1686         else if (aGlobalPos.y() == he)
    1687             p.setY (1);
    1688 
    1689         if (p != aGlobalPos)
    1690         {
    1691             m_lastMousePos =  p;
    1692             QCursor::setPos(m_lastMousePos);
    1693         }
    1694         else
    1695         {
    1696             m_lastMousePos = aGlobalPos;
    1697         }
    1698 # endif
    1699 #endif /* !Q_WS_MAC */
    1700         return true; /* stop further event handling */
    1701     }
    1702     else /* !uisession()->isMouseCaptured() */
    1703     {
    1704 #if 0 // TODO: Move that to fullscreen event-hjadler:
    1705         if (vboxGlobal().vmRenderMode() != VBoxDefs::SDLMode)
    1706         {
    1707             /* try to automatically scroll the guest canvas if the
    1708              * mouse is on the screen border */
    1709             /// @todo (r=dmik) better use a timer for autoscroll
    1710             QRect scrGeo = QApplication::desktop()->screenGeometry (this);
    1711             int dx = 0, dy = 0;
    1712             if (scrGeo.width() < contentsWidth())
    1713             {
    1714                 if (scrGeo.left() == aGlobalPos.x()) dx = -1;
    1715                 if (scrGeo.right() == aGlobalPos.x()) dx = +1;
    1716             }
    1717             if (scrGeo.height() < contentsHeight())
    1718             {
    1719                 if (scrGeo.top() == aGlobalPos.y()) dy = -1;
    1720                 if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
    1721             }
    1722             if (dx || dy)
    1723                 scrollBy(dx, dy);
    1724         }
    1725 #endif
    1726 
    1727         if (uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated())
    1728         {
    1729             int cw = contentsWidth(), ch = contentsHeight();
    1730             int vw = visibleWidth(), vh = visibleHeight();
    1731 
    1732             if (vboxGlobal().vmRenderMode() != VBoxDefs::SDLMode)
    1733             {
    1734                 /* Try to automatically scroll the guest canvas if the
    1735                  * mouse goes outside its visible part: */
    1736                 int dx = 0;
    1737                 if (aPos.x() > vw) dx = aPos.x() - vw;
    1738                 else if (aPos.x() < 0) dx = aPos.x();
    1739                 int dy = 0;
    1740                 if (aPos.y() > vh) dy = aPos.y() - vh;
    1741                 else if (aPos.y() < 0) dy = aPos.y();
    1742                 if (dx != 0 || dy != 0) scrollBy (dx, dy);
    1743             }
    1744 
    1745             QPoint cpnt = viewportToContents(aPos);
    1746             if (cpnt.x() < 0) cpnt.setX(0);
    1747             else if (cpnt.x() > cw - 1) cpnt.setX(cw - 1);
    1748             if (cpnt.y() < 0) cpnt.setY(0);
    1749             else if (cpnt.y() > ch - 1) cpnt.setY(ch - 1);
    1750 
    1751             // TODO: Where to put that actually?
    1752             /* Get & Setup absolute-event shift: */
    1753             CFramebuffer framebuffer;
    1754             LONG xShift = 0, yShift = 0;
    1755             session().GetConsole().GetDisplay().GetFramebuffer(screenId(), framebuffer, xShift, yShift);
    1756             cpnt.setX(cpnt.x() + xShift);
    1757             cpnt.setY(cpnt.y() + yShift);
    1758 
    1759             CMouse mouse = session().GetConsole().GetMouse();
    1760             // AssertMsgFailed(("x=%d, y=%d", cpnt.x(), cpnt.y())); // this shows what absolute coordinates are correct!
    1761             mouse.PutMouseEventAbsolute(cpnt.x() + 1, cpnt.y() + 1, wheelVertical, wheelHorizontal, state);
    1762             return true;
    1763         }
    1764         else
    1765         {
    1766             if (hasFocus() && (aType == QEvent::MouseButtonRelease && aButtons == Qt::NoButton))
    1767             {
    1768                 if (uisession()->isPaused())
    1769                 {
    1770                     vboxProblem().remindAboutPausedVMInput();
    1771                 }
    1772                 else if (uisession()->isRunning())
    1773                 {
    1774                     /* Temporarily disable auto capture that will take place after this dialog is dismissed because
    1775                      * the capture state is to be defined by the dialog result itself: */
    1776                     uisession()->setAutoCaptureDisabled(true);
    1777                     bool autoConfirmed = false;
    1778                     bool ok = vboxProblem().confirmInputCapture(&autoConfirmed);
    1779                     if (autoConfirmed)
    1780                         uisession()->setAutoCaptureDisabled(false);
    1781                     /* Otherwise, the disable flag will be reset in the next console view's foucs in event (since
    1782                      * may happen asynchronously on some platforms, after we return from this code): */
    1783                     if (ok)
    1784                     {
    1785 #ifdef Q_WS_X11
    1786                         /* Make sure that pending FocusOut events from the previous message box are handled,
    1787                          * otherwise the mouse is immediately ungrabbed again: */
    1788                         qApp->processEvents();
    1789 #endif
    1790                         captureKbd(true);
    1791                         captureMouse(true);
    1792                     }
    1793                 }
    1794             }
    1795         }
    1796     }
    1797 
    1798     return false;
    17991315}
    18001316
     
    21141630            {
    21151631                if (VBoxGlobal::qtRTVersion() < ((4 << 16) | (5 << 8) | 0))
    2116                     focusEvent (pEvent->type == XFocusIn);
     1632                {
     1633                    focusEvent(pEvent->type == XFocusIn);
     1634                    if (pEvent->type == XFocusOut)
     1635                        machineLogic()->mouseHandler()->releaseMouse();
     1636                }
    21171637            }
    21181638            return false;
     
    24231943}
    24241944
    2425 void UIMachineView::emitMouseStateChanged()
    2426 {
    2427     emit mouseStateChanged(mouseState());
    2428 }
    2429 
    24301945void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */)
    24311946{
     
    24962011    if (fEmitSignal)
    24972012        emitKeyboardStateChanged();
    2498 }
    2499 
    2500 void UIMachineView::captureMouse(bool fCapture, bool fEmitSignal /* = true */)
    2501 {
    2502     /* Do not change anything if its already so: */
    2503     if (uisession()->isMouseCaptured() == fCapture)
    2504         return;
    2505 
    2506     /* Store new mouse 'captured' state value: */
    2507     uisession()->setMouseCaptured(fCapture);
    2508 
    2509     if (fCapture)
    2510     {
    2511         /* Memorize the host position where the cursor was captured: */
    2512         m_capturedMousePos = QCursor::pos();
    2513 #ifdef Q_WS_WIN32
    2514         /* Remember what this window captured mouse: */
    2515         m_fItsMeWhoCapturedMouse = true;
    2516         /* Move the mouse to the center of the visible area: */
    2517         m_lastMousePos = mapToGlobal(visibleRegion().boundingRect().center());
    2518         QCursor::setPos(m_lastMousePos);
    2519         /* Update mouse clipping: */
    2520         updateMouseCursorClipping();
    2521 #elif defined (Q_WS_MAC)
    2522         /* Move the mouse to the center of the visible area: */
    2523         m_lastMousePos = mapToGlobal(visibleRegion().boundingRect().center());
    2524         QCursor::setPos(m_lastMousePos);
    2525         /* Grab all mouse events: */
    2526         viewport()->grabMouse();
    2527 #else
    2528         /* Grab all mouse events: */
    2529         viewport()->grabMouse();
    2530         m_lastMousePos = QCursor::pos();
    2531 #endif
    2532     }
    2533     else
    2534     {
    2535         /* Return the cursor to where it was when we captured it: */
    2536         QCursor::setPos(m_capturedMousePos);
    2537     }
    2538 
    2539     /* Updating guest mouse: */
    2540     CMouse mouse = session().GetConsole().GetMouse();
    2541     mouse.PutMouseEvent(0, 0, 0, 0, 0);
    2542 
    2543     /* Emit signal if required: */
    2544     if (fEmitSignal)
    2545         emitMouseStateChanged();
    25462013}
    25472014
     
    27102177    machineLogic()->updateDockIcon();
    27112178}
    2712 
    2713 void UIMachineView::setMouseCoalescingEnabled(bool fOn)
    2714 {
    2715     /* Enable mouse event compression if we leave the VM view. This
    2716        is necessary for having smooth resizing of the VM/other
    2717        windows.
    2718        Disable mouse event compression if we enter the VM view. So
    2719        all mouse events are registered in the VM. Only do this if
    2720        the keyboard/mouse is grabbed (this is when we have a valid
    2721        event handler). */
    2722     if (fOn || m_fKeyboardGrabbed)
    2723         ::darwinSetMouseCoalescingEnabled(fOn);
    2724 }
    27252179#endif /* Q_WS_MAC */
    27262180
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r30348 r30408  
    5959    /* Public getters: */
    6060    int keyboardState() const;
    61     int mouseState() const;
    6261    virtual QRegion lastVisibleRegion() const { return QRegion(); }
    6362
    6463    /* Public setters: */
    6564    virtual void setGuestAutoresizeEnabled(bool /* fEnabled */) {}
    66     virtual void setMouseIntegrationEnabled(bool fEnabled);
    6765
    6866    /* Public members: */
     
    7169signals:
    7270
    73     /* Mouse/Keyboard state-change signals: */
     71    /* Keyboard state-change signals: */
    7472    void keyboardStateChanged(int iState);
    75     void mouseStateChanged(int iState);
    7673
    7774    /* Utility signals: */
     
    109106    QSize desktopGeometry() const;
    110107    QSize guestSizeHint();
     108#ifdef Q_WS_MAC
     109    /* These getters are temporary here while UIKeyboardHandler is not implemented: */
     110    bool isHostKeyAlone() const { return m_bIsHostkeyAlone; }
     111    bool isKeyboardGrabbed() const { return m_fKeyboardGrabbed; }
     112#endif /* Q_WS_MAC */
    111113
    112114    /* Protected setters: */
     
    117119
    118120    /* Protected helpers: */
    119     void updateMouseCursorShape();
    120 #ifdef Q_WS_WIN32
    121     void updateMouseCursorClipping();
    122 #endif
    123121    virtual QRect workingArea() = 0;
    124122    virtual void calculateDesktopGeometry() = 0;
     
    128126#ifdef Q_WS_MAC
    129127    void updateDockIcon();
    130     void setMouseCoalescingEnabled(bool fOn);
    131128    CGImageRef vmContentImage();
    132129    CGImageRef frameBuffertoCGImageRef(UIFrameBuffer *pFrameBuffer);
     
    158155    /* Console callback handlers: */
    159156    virtual void sltMachineStateChanged();
    160     virtual void sltMousePointerShapeChanged();
    161     virtual void sltMouseCapabilityChanged();
    162157    virtual void sltPerformGuestResize(const QSize & /* toSize */) {};
    163 
    164     /* Session callback handlers: */
    165     virtual void sltMouseCapturedStatusChanged();
    166158
    167159    /* Various helper slots: */
     
    173165    void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
    174166    bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
    175     bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    176                     Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
    177                     int aWheelDelta, Qt::Orientation aWheelDir);
    178167    void resizeEvent(QResizeEvent *pEvent);
    179168    void moveEvent(QMoveEvent *pEvent);
     
    203192#endif
    204193    void emitKeyboardStateChanged();
    205     void emitMouseStateChanged();
    206194    void captureKbd(bool fCapture, bool fEmitSignal = true);
    207     void captureMouse(bool fCapture, bool fEmitSignal = true);
    208195    void saveKeyStates();
    209196    void releaseAllPressedKeys(bool aReleaseHostKey = true);
     
    222209    QSize m_storedConsoleSize;
    223210
    224     QPoint m_lastMousePos;
    225     QPoint m_capturedMousePos;
    226     int m_iLastMouseWheelDelta;
    227 
    228211    uint8_t m_pressedKeys[128];
    229212    uint8_t m_pressedKeysCopy[128];
     
    239222#endif
    240223
    241 #ifdef Q_WS_WIN
    242     bool m_fItsMeWhoCapturedMouse;
    243 #endif /* Q_WS_WIN */
    244224#ifdef Q_WS_MAC
    245225    /** The current modifier key mask. Used to figure out which modifier
     
    252232
    253233    /* Friend classes: */
     234    friend class UIMouseHandler;
    254235    friend class UIMachineLogic;
    255236    friend class UIFrameBuffer;
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp

    r30291 r30408  
    33 *
    44 * VBox frontends: Qt GUI ("VirtualBox"):
    5  * UIMachineView class implementation
     5 * UIMouseHandler class implementation
    66 */
    77
     
    2020/* Global includes */
    2121#include <QDesktopWidget>
    22 #include <QTimer>
    23 #include <QPainter>
    24 #include <QScrollBar>
    25 #include <VBox/VBoxVideo.h>
     22#include <QMouseEvent>
    2623
    2724/* Local includes */
    2825#include "VBoxGlobal.h"
    2926#include "VBoxProblemReporter.h"
    30 #include "UIFrameBuffer.h"
    31 #include "UIFrameBufferQGL.h"
    32 #include "UIFrameBufferQImage.h"
    33 #include "UIFrameBufferQuartz2D.h"
    34 #include "UIFrameBufferSDL.h"
    35 #include "VBoxFBOverlay.h"
     27#include "UIMouseHandler.h"
    3628#include "UISession.h"
    37 #include "UIActionsPool.h"
    3829#include "UIMachineLogic.h"
    39 #include "UIMachineWindow.h"
    4030#include "UIMachineView.h"
    41 #include "UIMachineWindowNormal.h"
    42 #include "UIMachineWindowFullscreen.h"
    43 #include "UIMachineWindowSeamless.h"
    44 #include "UIMachineViewNormal.h"
    45 #include "UIMachineViewFullscreen.h"
    46 #include "UIMachineViewSeamless.h"
    47 
    48 #ifdef Q_WS_PM
    49 # include "QIHotKeyEdit.h"
    50 #endif /* defined (Q_WS_PM) */
    51 
    52 #ifdef Q_WS_WIN
    53 #undef LOWORD
    54 #undef HIWORD
    55 #undef LOBYTE
    56 #undef HIBYTE
    57 #include <windows.h>
    58 static UIMachineView *gView = 0;
    59 static HHOOK gKbdHook = 0;
    60 #endif /* defined (Q_WS_WIN) */
    61 
    62 #ifdef Q_WS_X11
    63 # include <QX11Info>
    64 # define XK_XKB_KEYS
    65 # define XK_MISCELLANY
    66 # include <X11/XKBlib.h>
    67 # include <X11/keysym.h>
    68 # ifdef KeyPress
    69 const int XFocusOut = FocusOut;
    70 const int XFocusIn = FocusIn;
    71 const int XKeyPress = KeyPress;
    72 const int XKeyRelease = KeyRelease;
    73 #  undef KeyRelease
    74 #  undef KeyPress
    75 #  undef FocusOut
    76 #  undef FocusIn
    77 # endif
    78 # include "XKeyboard.h"
    79 #endif /* defined (Q_WS_X11) */
    80 
    81 #ifdef Q_WS_MAC
    82 # include "DockIconPreview.h"
    83 # include "DarwinKeyboard.h"
    84 # include "UICocoaApplication.h"
    85 # include <VBox/err.h>
    86 # include <Carbon/Carbon.h>
    87 #endif /* Q_WS_MAC */
    88 
    89 class VBoxViewport: public QWidget
    90 {
    91 public:
    92 
    93     VBoxViewport(QWidget *pParent) : QWidget(pParent)
    94     {
    95         /* No need for background drawing: */
    96         setAttribute(Qt::WA_OpaquePaintEvent);
    97     }
    98 
    99     QPaintEngine *paintEngine() const
    100     {
    101         if (testAttribute(Qt::WA_PaintOnScreen))
    102             return NULL;
    103         else
    104             return QWidget::paintEngine();
    105     }
    106 };
    107 
    108 enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 };
    109 enum { IsKeyPressed = 0x01, IsExtKeyPressed = 0x02, IsKbdCaptured = 0x80 };
    110 
    111 UIMachineView* UIMachineView::create(  UIMachineWindow *pMachineWindow
    112                                      , VBoxDefs::RenderMode renderMode
    113 #ifdef VBOX_WITH_VIDEOHWACCEL
    114                                      , bool bAccelerate2DVideo
    115 #endif
    116                                      , UIVisualStateType visualStateType
    117                                      , ulong uScreenId)
    118 {
    119     UIMachineView *view = 0;
     31
     32/* Factory function to create mouse-handler: */
     33UIMouseHandler* UIMouseHandler::create(UIMachineLogic *pMachineLogic,
     34                                       UIVisualStateType visualStateType)
     35{
     36    /* Prepare mouse-handler: */
     37    UIMouseHandler *pMouseHandler = 0;
     38    /* Depending on visual-state type: */
    12039    switch (visualStateType)
    12140    {
     41        /* For now all the states using common mouse-handler: */
    12242        case UIVisualStateType_Normal:
    123             view = new UIMachineViewNormal(  pMachineWindow
    124                                            , renderMode
    125 #ifdef VBOX_WITH_VIDEOHWACCEL
    126                                            , bAccelerate2DVideo
    127 #endif
    128                                            , uScreenId);
    129             break;
    13043        case UIVisualStateType_Fullscreen:
    131             view = new UIMachineViewFullscreen(  pMachineWindow
    132                                                , renderMode
    133 #ifdef VBOX_WITH_VIDEOHWACCEL
    134                                                , bAccelerate2DVideo
    135 #endif
    136                                                , uScreenId);
    137             break;
    13844        case UIVisualStateType_Seamless:
    139             view = new UIMachineViewSeamless(  pMachineWindow
    140                                              , renderMode
    141 #ifdef VBOX_WITH_VIDEOHWACCEL
    142                                              , bAccelerate2DVideo
    143 #endif
    144                                              , uScreenId);
     45            pMouseHandler = new UIMouseHandler(pMachineLogic);
    14546            break;
    14647        default:
    14748            break;
    14849    }
    149     return view;
    150 }
    151 
    152 void UIMachineView::destroy(UIMachineView *pWhichView)
    153 {
    154     delete pWhichView;
    155 }
    156 
    157 int UIMachineView::keyboardState() const
    158 {
    159     return (m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) |
    160            (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0);
    161 }
    162 
    163 int UIMachineView::mouseState() const
     50    /* Return prepared mouse-handler: */
     51    return pMouseHandler;
     52}
     53
     54/* Factory function to destroy mouse-handler: */
     55void UIMouseHandler::destroy(UIMouseHandler *pMouseHandler)
     56{
     57    /* Delete mouse-handler: */
     58    delete pMouseHandler;
     59}
     60
     61/* Registers new machine-view: */
     62void UIMouseHandler::addMachineView(ulong uViewIndex, UIMachineView *pMachineView)
     63{
     64    /* If that view is NOT registered yet: */
     65    if (!m_views.contains(uViewIndex))
     66    {
     67        /* Register machine-view: */
     68        m_views.insert(uViewIndex, pMachineView);
     69        /* Install event-filter for machine-view: */
     70        m_views[uViewIndex]->installEventFilter(this);
     71        /* Make machine-view notify mouse-handler about resizeHintDone(): */
     72        connect(m_views[uViewIndex], SIGNAL(resizeHintDone()), this, SLOT(sltMousePointerShapeChanged()));
     73    }
     74
     75    /* If that viewport is NOT registered yet: */
     76    if (!m_viewports.contains(uViewIndex))
     77    {
     78        /* Register machine-view-viewport: */
     79        m_viewports.insert(uViewIndex, pMachineView->viewport());
     80        /* Install event-filter for machine-view-viewport: */
     81        m_viewports[uViewIndex]->installEventFilter(this);
     82    }
     83}
     84
     85/* Remove registered machine-view: */
     86void UIMouseHandler::delMachineView(ulong uViewIndex)
     87{
     88    /* If that view is registered yet: */
     89    if (m_views.contains(uViewIndex))
     90    {
     91        /* Unregister machine-view: */
     92        m_views.remove(uViewIndex);
     93    }
     94
     95    /* If that viewport is registered yet: */
     96    if (m_viewports.contains(uViewIndex))
     97    {
     98        /* Unregister machine-view-viewport: */
     99        m_viewports.remove(uViewIndex);
     100    }
     101}
     102
     103void UIMouseHandler::captureMouse(ulong uScreenId)
     104{
     105    /* Do not try to capture mouse if its captured already: */
     106    if (uisession()->isMouseCaptured())
     107        return;
     108
     109    /* If such viewport exists: */
     110    if (m_viewports.contains(uScreenId))
     111    {
     112        /* Store mouse-capturing state value: */
     113        uisession()->setMouseCaptured(true);
     114
     115        /* Memorize the index of machine-view-viewport captured mouse: */
     116        m_iMouseCaptureViewIndex = uScreenId;
     117
     118        /* Memorize the host position where the cursor was captured: */
     119        m_capturedMousePos = QCursor::pos();
     120#ifdef Q_WS_WIN
     121        /* Move the mouse to the center of the visible area: */
     122        m_lastMousePos = m_views[m_iMouseCaptureViewIndex]->mapToGlobal(m_views[m_iMouseCaptureViewIndex]->visibleRegion().boundingRect().center());
     123        QCursor::setPos(m_lastMousePos);
     124        /* Update mouse clipping: */
     125        updateMouseCursorClipping();
     126#elif defined (Q_WS_MAC)
     127        /* Move the mouse to the center of the visible area: */
     128        m_lastMousePos = m_views[m_iMouseCaptureViewIndex]->mapToGlobal(m_views[m_iMouseCaptureViewIndex]->visibleRegion().boundingRect().center());
     129        QCursor::setPos(m_lastMousePos);
     130        /* Grab all mouse events: */
     131        m_viewports[m_iMouseCaptureViewIndex]->grabMouse();
     132#else /* Q_WS_MAC */
     133        /* Remember current mouse position: */
     134        m_lastMousePos = QCursor::pos();
     135        /* Grab all mouse events: */
     136        m_viewports[m_iMouseCaptureViewIndex]->grabMouse();
     137#endif /* !Q_WS_MAC */
     138
     139        /* Switch guest mouse to the relative mode: */
     140        CMouse mouse = session().GetConsole().GetMouse();
     141        mouse.PutMouseEvent(0, 0, 0, 0, 0);
     142
     143        /* Emit signal if required: */
     144        emit mouseStateChanged(mouseState());
     145    }
     146}
     147
     148void UIMouseHandler::releaseMouse()
     149{
     150    /* Do not try to release mouse if its released already: */
     151    if (!uisession()->isMouseCaptured())
     152        return;
     153
     154    /* If such viewport exists: */
     155    if (m_viewports.contains(m_iMouseCaptureViewIndex))
     156    {
     157        /* Store mouse-capturing state value: */
     158        uisession()->setMouseCaptured(false);
     159
     160        /* Return the cursor to where it was when we captured it: */
     161        QCursor::setPos(m_capturedMousePos);
     162#ifdef Q_WS_WIN
     163        /* Update mouse clipping: */
     164        updateMouseCursorClipping();
     165#else /* Q_WS_WIN */
     166        /* Releasing grabbed mouse from that view: */
     167        m_viewports[m_iMouseCaptureViewIndex]->releaseMouse();
     168#endif /* !Q_WS_WIN */
     169        /* Reset mouse-capture index: */
     170        m_iMouseCaptureViewIndex = -1;
     171
     172        /* Emit signal if required: */
     173        emit mouseStateChanged(mouseState());
     174    }
     175}
     176
     177/* Setter for mouse-integration feature: */
     178void UIMouseHandler::setMouseIntegrationEnabled(bool fEnabled)
     179{
     180    /* Do not do anything if its already done: */
     181    if (uisession()->isMouseIntegrated() == fEnabled)
     182        return;
     183
     184    /* Store mouse-integration state value: */
     185    uisession()->setMouseIntegrated(fEnabled);
     186
     187    /* Reuse sltMouseCapabilityChanged() to update mouse state: */
     188    sltMouseCapabilityChanged();
     189}
     190
     191/* Current mouse state: */
     192int UIMouseHandler::mouseState() const
    164193{
    165194    return (uisession()->isMouseCaptured() ? UIMouseStateType_MouseCaptured : 0) |
     
    168197}
    169198
    170 void UIMachineView::setMouseIntegrationEnabled(bool fEnabled)
    171 {
    172     /* Do not change anything if its already so: */
    173     if (uisession()->isMouseIntegrated() == fEnabled)
    174         return;
    175 
    176     /* Store new mouse 'integrated' state value: */
    177     uisession()->setMouseIntegrated(fEnabled);
    178 
    179     /* We should capture/release mouse depending on mouse 'integrated' state value: */
    180     captureMouse(!uisession()->isMouseIntegrated(), false /* emit signal? */);
    181 
    182     /* Update mouse cursor shape: */
    183     updateMouseCursorShape();
    184 
    185     /* If mouse is integrated and supports absolute pointing
    186      * we should switch guest mouse to the absolute mode: */
    187     if (uisession()->isMouseIntegrated() && uisession()->isMouseSupportsAbsolute())
    188     {
     199/* Machine state-change handler: */
     200void UIMouseHandler::sltMachineStateChanged()
     201{
     202    /* Get machine state: */
     203    KMachineState state = uisession()->machineState();
     204    /* Handle particular machine states: */
     205    switch (state)
     206    {
     207        case KMachineState_Paused:
     208        case KMachineState_TeleportingPausedVM:
     209        case KMachineState_Stuck:
     210        {
     211            /* Release the mouse: */
     212            releaseMouse();
     213            break;
     214        }
     215        default:
     216            break;
     217    }
     218}
     219
     220/* Mouse capability-change handler: */
     221void UIMouseHandler::sltMouseCapabilityChanged()
     222{
     223    /* If mouse supports absolute pointing and mouse-integration activated: */
     224    if (uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated())
     225    {
     226        /* Release the mouse: */
     227        releaseMouse();
     228        /* Also we should switch guest mouse to the absolute mode: */
    189229        CMouse mouse = session().GetConsole().GetMouse();
    190230        mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
    191231    }
     232    /* If mouse-integration deactivated or mouse doesn't supports absolute pointing: */
     233    else
     234    {
     235        /* Search for the machine-view focused now: */
     236        int iFocusedView = -1;
     237        QList<ulong> screenIds = m_views.keys();
     238        for (int i = 0; i < screenIds.size(); ++i)
     239        {
     240            if (m_views[screenIds[i]]->hasFocus())
     241            {
     242                iFocusedView = screenIds[i];
     243                break;
     244            }
     245        }
     246        /* If there is no focused view but views are present we will use the first one: */
     247        if (iFocusedView == -1 && !screenIds.isEmpty())
     248            iFocusedView = screenIds[0];
     249        /* Capture mouse using that view: */
     250        if (iFocusedView != -1)
     251            captureMouse(iFocusedView);
     252    }
     253
     254    /* Notify user about mouse supports or not absolute pointing if that method was called by signal: */
     255    if (sender())
     256        vboxProblem().remindAboutMouseIntegration(uisession()->isMouseSupportsAbsolute());
    192257
    193258    /* Notify all listeners: */
    194     emitMouseStateChanged();
    195 }
    196 
    197 UIMachineView::UIMachineView(  UIMachineWindow *pMachineWindow
    198                              , VBoxDefs::RenderMode renderMode
    199 #ifdef VBOX_WITH_VIDEOHWACCEL
    200                              , bool bAccelerate2DVideo
    201 #endif
    202                              , ulong uScreenId)
    203 // TODO_NEW_CORE: really think of if this is right
    204 //    : QAbstractScrollArea(((QMainWindow*)pMachineWindow->machineWindow())->centralWidget())
    205     : QAbstractScrollArea(pMachineWindow->machineWindow())
    206     , m_pMachineWindow(pMachineWindow)
    207     , m_mode(renderMode)
    208     , m_uScreenId(uScreenId)
    209     , m_globalSettings(vboxGlobal().settings())
    210     , m_pFrameBuffer(0)
    211     , m_previousState(KMachineState_Null)
    212     , m_desktopGeometryType(DesktopGeo_Invalid)
    213     , m_iLastMouseWheelDelta(0)
    214     , m_bIsAutoCaptureDisabled(false)
    215     , m_bIsKeyboardCaptured(false)
    216     , m_bIsHostkeyPressed(false)
    217     , m_bIsHostkeyAlone (false)
    218     , m_bIsHostkeyInCapture(false)
    219     , m_bIsMachineWindowResizeIgnored(false)
    220     , m_fPassCAD(false)
    221 #ifdef VBOX_WITH_VIDEOHWACCEL
    222     , m_fAccelerate2DVideo(bAccelerate2DVideo)
    223 #endif /* VBOX_WITH_VIDEOHWACCEL */
    224 #ifdef Q_WS_WIN
    225     , m_fItsMeWhoCapturedMouse(false)
    226 #endif
    227 #ifdef Q_WS_MAC
    228     , m_darwinKeyModifiers(0)
    229     , m_fKeyboardGrabbed (false)
    230 #endif /* Q_WS_MAC */
    231 {
    232 }
    233 
    234 UIMachineView::~UIMachineView()
    235 {
    236 }
    237 
    238 UISession* UIMachineView::uisession() const
    239 {
    240     return machineWindowWrapper()->machineLogic()->uisession();
    241 }
    242 
    243 CSession& UIMachineView::session()
    244 {
    245     return uisession()->session();
    246 }
    247 
    248 QSize UIMachineView::sizeHint() const
    249 {
    250 #ifdef VBOX_WITH_DEBUGGER
    251     // TODO: Fix all DEBUGGER stuff!
    252     /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done by DevVGA if provoked before power on. */
    253     QSize fb(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    254     if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled()))
    255         fb = QSize(640, 480);
    256     return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2);
    257 #else
    258     return QSize(m_pFrameBuffer->width() + frameWidth() * 2, m_pFrameBuffer->height() + frameWidth() * 2);
    259 #endif
    260 }
    261 
    262 int UIMachineView::contentsX() const
    263 {
    264     return horizontalScrollBar()->value();
    265 }
    266 
    267 int UIMachineView::contentsY() const
    268 {
    269     return verticalScrollBar()->value();
    270 }
    271 
    272 int UIMachineView::contentsWidth() const
    273 {
    274     return m_pFrameBuffer->width();
    275 }
    276 
    277 int UIMachineView::contentsHeight() const
    278 {
    279     return m_pFrameBuffer->height();
    280 }
    281 
    282 int UIMachineView::visibleWidth() const
    283 {
    284     return horizontalScrollBar()->pageStep();
    285 }
    286 
    287 int UIMachineView::visibleHeight() const
    288 {
    289     return verticalScrollBar()->pageStep();
    290 }
    291 
    292 UIMachineLogic* UIMachineView::machineLogic() const
    293 {
    294     return machineWindowWrapper()->machineLogic();
    295 }
    296 
    297 QSize UIMachineView::desktopGeometry() const
    298 {
    299     QSize geometry;
    300     switch (m_desktopGeometryType)
    301     {
    302         case DesktopGeo_Fixed:
    303         case DesktopGeo_Automatic:
    304             geometry = QSize(qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
    305                              qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
    306             break;
    307         case DesktopGeo_Any:
    308             geometry = QSize(0, 0);
    309             break;
    310         default:
    311             AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
    312     }
    313     return geometry;
    314 }
    315 
    316 QSize UIMachineView::guestSizeHint()
    317 {
    318     /* Result: */
    319     QSize sizeHint;
    320 
    321     /* Get current machine: */
    322     CMachine machine = session().GetMachine();
    323 
    324     /* Load machine view hint: */
    325     QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
    326                      QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
    327     QString strValue = machine.GetExtraData(strKey);
    328 
    329     bool ok = true;
    330     int width = 0, height = 0;
    331     if (ok)
    332         width = strValue.section(',', 0, 0).toInt(&ok);
    333     if (ok)
    334         height = strValue.section(',', 1, 1).toInt(&ok);
    335 
    336     if (ok /* If previous parameters were read correctly! */)
    337     {
    338         /* Compose guest size hint from loaded values: */
    339         sizeHint = QSize(width, height);
    340     }
    341     else
    342     {
    343         /* Compose guest size hint from default attributes: */
    344         sizeHint = QSize(800, 600);
    345     }
    346 
    347     /* Return result: */
    348     return sizeHint;
    349 }
    350 
    351 void UIMachineView::setDesktopGeometry(DesktopGeo geometry, int aWidth, int aHeight)
    352 {
    353     switch (geometry)
    354     {
    355         case DesktopGeo_Fixed:
    356             m_desktopGeometryType = DesktopGeo_Fixed;
    357             if (aWidth != 0 && aHeight != 0)
    358                 m_desktopGeometry = QSize(aWidth, aHeight);
    359             else
    360                 m_desktopGeometry = QSize(0, 0);
    361             storeConsoleSize(0, 0);
    362             break;
    363         case DesktopGeo_Automatic:
    364             m_desktopGeometryType = DesktopGeo_Automatic;
    365             m_desktopGeometry = QSize(0, 0);
    366             storeConsoleSize(0, 0);
    367             break;
    368         case DesktopGeo_Any:
    369             m_desktopGeometryType = DesktopGeo_Any;
    370             m_desktopGeometry = QSize(0, 0);
    371             break;
    372         default:
    373             AssertMsgFailed(("Invalid desktop geometry type %d\n", geometry));
    374             m_desktopGeometryType = DesktopGeo_Invalid;
    375     }
    376 }
    377 
    378 void UIMachineView::storeConsoleSize(int iWidth, int iHeight)
    379 {
    380     m_storedConsoleSize = QSize(iWidth, iHeight);
    381 }
    382 
    383 void UIMachineView::storeGuestSizeHint(const QSize &sizeHint)
    384 {
    385     /* Get current machine: */
    386     CMachine machine = session().GetMachine();
    387 
    388     /* Save machine view hint: */
    389     QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
    390                      QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
    391     QString strValue = QString("%1,%2").arg(sizeHint.width()).arg(sizeHint.height());
    392     machine.SetExtraData(strKey, strValue);
    393 }
    394 
    395 void UIMachineView::updateMouseCursorShape()
     259    emit mouseStateChanged(mouseState());
     260}
     261
     262/* Mouse pointer-shape-change handler: */
     263void UIMouseHandler::sltMousePointerShapeChanged()
    396264{
    397265    /* First of all, we should check if the host pointer should be visible.
     
    404272         uisession()->isHidingHostPointer()))
    405273    {
    406         viewport()->setCursor(Qt::BlankCursor);
     274        QList<ulong> screenIds = m_viewports.keys();
     275        for (int i = 0; i < screenIds.size(); ++i)
     276            m_viewports[screenIds[i]]->setCursor(Qt::BlankCursor);
    407277    }
    408278
     
    415285        uisession()->isValidPointerShapePresent())
    416286    {
    417         viewport()->setCursor(uisession()->cursor());
     287        QList<ulong> screenIds = m_viewports.keys();
     288        for (int i = 0; i < screenIds.size(); ++i)
     289            m_viewports[screenIds[i]]->setCursor(uisession()->cursor());
    418290    }
    419291
     
    424296     * 2. mouse is 'not captured', 'not integrated', 'absolute'.
    425297     * We have nothing to do with that except just unset the cursor. */
    426     viewport()->unsetCursor();
    427 }
    428 
    429 #ifdef Q_WS_WIN
    430 /* This method is actually required only because under win-host
    431  * we do not really grab the mouse in case of capturing it.
    432  * I have to check if its really need, may be just grabMouse() will be enought: */
    433 void UIMachineView::updateMouseCursorClipping()
    434 {
    435     if (m_fItsMeWhoCapturedMouse)
    436     {
    437         QRect r = viewport()->rect();
    438         r.moveTopLeft(viewport()->mapToGlobal(QPoint(0, 0)));
    439         RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
    440         ::ClipCursor(&rect);
    441     }
    442 }
    443 #endif
    444 
    445 void UIMachineView::updateSliders()
    446 {
    447     QSize p = viewport()->size();
    448     QSize m = maximumViewportSize();
    449 
    450     QSize v = QSize(frameBuffer()->width(), frameBuffer()->height());
    451     /* No scroll bars needed: */
    452     if (m.expandedTo(v) == m)
    453         p = m;
    454 
    455     horizontalScrollBar()->setRange(0, v.width() - p.width());
    456     verticalScrollBar()->setRange(0, v.height() - p.height());
    457     horizontalScrollBar()->setPageStep(p.width());
    458     verticalScrollBar()->setPageStep(p.height());
    459 }
    460 
    461 void UIMachineView::prepareFrameBuffer()
    462 {
    463     /* Prepare viewport: */
    464 #ifdef VBOX_GUI_USE_QGLFB
    465     QWidget *pViewport;
    466     switch (mode())
    467     {
    468         case VBoxDefs::QGLMode:
    469             pViewport = new VBoxGLWidget(session().GetConsole(), this, NULL);
    470             break;
    471         default:
    472             pViewport = new VBoxViewport(this);
    473     }
    474 #else
    475     VBoxViewport *pViewport = new VBoxViewport(this);
    476 #endif
    477     setViewport(pViewport);
    478 
    479     CDisplay display = session().GetConsole().GetDisplay();
    480     Assert(!display.isNull());
    481     m_pFrameBuffer = NULL;
    482 
    483     switch (mode())
    484     {
    485 #ifdef VBOX_GUI_USE_QIMAGE
    486         case VBoxDefs::QImageMode:
    487 # ifdef VBOX_WITH_VIDEOHWACCEL
    488             if (m_fAccelerate2DVideo)
    489             {
    490                 UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
    491                 if (pFramebuffer)
    492                     pFramebuffer->setView(this);
    493                 else
    494                 {
    495                     /* these two additional template args is a workaround to this [VBox|UI] duplication
    496                      * @todo: they are to be removed once VBox stuff is gone */
    497                     pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferQImage, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
    498                     uisession()->setFrameBuffer(screenId(), pFramebuffer);
    499                 }
    500                 m_pFrameBuffer = pFramebuffer;
    501             }
    502             else
    503                 m_pFrameBuffer = new UIFrameBufferQImage(this);
    504 # else
    505             m_pFrameBuffer = new UIFrameBufferQImage(this);
    506 # endif
    507             break;
    508 #endif /* VBOX_GUI_USE_QIMAGE */
    509 #ifdef VBOX_GUI_USE_QGLFB
    510         case VBoxDefs::QGLMode:
    511             m_pFrameBuffer = new UIFrameBufferQGL(this);
    512             break;
    513 //        case VBoxDefs::QGLOverlayMode:
    514 //            m_pFrameBuffer = new UIQGLOverlayFrameBuffer(this);
    515 //            break;
    516 #endif /* VBOX_GUI_USE_QGLFB */
    517 #ifdef VBOX_GUI_USE_SDL
    518         case VBoxDefs::SDLMode:
    519             /* Indicate that we are doing all drawing stuff ourself: */
    520             // TODO_NEW_CORE
    521             viewport()->setAttribute(Qt::WA_PaintOnScreen);
    522 # ifdef Q_WS_X11
    523             /* This is somehow necessary to prevent strange X11 warnings on i386 and segfaults on x86_64: */
    524             XFlush(QX11Info::display());
    525 # endif
    526 # if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
    527             if (m_fAccelerate2DVideo)
    528             {
    529                 class UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
    530                 if (pFramebuffer)
    531                     pFramebuffer->setView(this);
    532                 else
    533                 {
    534                     /* these two additional template args is a workaround to this [VBox|UI] duplication
    535                      * @todo: they are to be removed once VBox stuff is gone */
    536                     pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferSDL, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
    537                     uisession()->setFrameBuffer(screenId(), pFramebuffer);
    538                 }
    539                 m_pFrameBuffer = pFramebuffer;
    540             }
    541             else
    542                 m_pFrameBuffer = new UIFrameBufferSDL(this);
    543 # else
    544             m_pFrameBuffer = new UIFrameBufferSDL(this);
    545 # endif
    546             /* Disable scrollbars because we cannot correctly draw in a scrolled window using SDL: */
    547             horizontalScrollBar()->setEnabled(false);
    548             verticalScrollBar()->setEnabled(false);
    549             break;
    550 #endif /* VBOX_GUI_USE_SDL */
    551 #if 0 // TODO: Enable DDraw frame buffer!
    552 #ifdef VBOX_GUI_USE_DDRAW
    553         case VBoxDefs::DDRAWMode:
    554             m_pFrameBuffer = new UIDDRAWFrameBuffer(this);
    555             if (!m_pFrameBuffer || m_pFrameBuffer->address() == NULL)
    556             {
    557                 if (m_pFrameBuffer)
    558                     delete m_pFrameBuffer;
    559                 m_mode = VBoxDefs::QImageMode;
    560                 m_pFrameBuffer = new UIFrameBufferQImage(this);
    561             }
    562             break;
    563 #endif /* VBOX_GUI_USE_DDRAW */
    564 #endif
    565 #ifdef VBOX_GUI_USE_QUARTZ2D
    566         case VBoxDefs::Quartz2DMode:
    567             /* Indicate that we are doing all drawing stuff ourself: */
    568             viewport()->setAttribute(Qt::WA_PaintOnScreen);
    569 # ifdef VBOX_WITH_VIDEOHWACCEL
    570             if (m_fAccelerate2DVideo)
    571             {
    572                 UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
    573                 if (pFramebuffer)
    574                     pFramebuffer->setView(this);
    575                 else
    576                 {
    577                     /* these two additional template args is a workaround to this [VBox|UI] duplication
    578                      * @todo: they are to be removed once VBox stuff is gone */
    579                     pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferQuartz2D, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
    580                     uisession()->setFrameBuffer(screenId(), pFramebuffer);
    581                 }
    582                 m_pFrameBuffer = pFramebuffer;
    583             }
    584             else
    585                 m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
    586 # else
    587             m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
    588 # endif
    589             break;
    590 #endif /* VBOX_GUI_USE_QUARTZ2D */
    591         default:
    592             AssertReleaseMsgFailed(("Render mode must be valid: %d\n", mode()));
    593             LogRel(("Invalid render mode: %d\n", mode()));
    594             qApp->exit(1);
    595             break;
    596     }
    597     if (m_pFrameBuffer)
    598     {
    599 #ifdef VBOX_WITH_VIDEOHWACCEL
    600         CFramebuffer fb(NULL);
    601         if (m_fAccelerate2DVideo)
    602         {
    603             LONG XOrigin, YOrigin;
    604             /* check if the framebuffer is already assigned
    605              * in this case we do not need to re-assign it
    606              * neither do we need to AddRef */
    607             display.GetFramebuffer(m_uScreenId, fb, XOrigin, YOrigin);
    608         }
    609         if (fb.raw() != m_pFrameBuffer) /* <-this will evaluate to true iff m_fAccelerate2DVideo is disabled or iff no framebuffer is yet assigned */
    610 #endif
    611         {
    612             m_pFrameBuffer->AddRef();
    613         }
    614 
    615         /* always perform SetFramebuffer to ensure 3D gets notified */
    616         display.SetFramebuffer(m_uScreenId, CFramebuffer(m_pFrameBuffer));
    617     }
    618 
    619 #ifdef Q_WS_X11
    620     /* Processing pseudo resize-event to synchronize frame-buffer
    621      * with stored framebuffer size in case of machine state was 'saved': */
    622     if (session().GetMachine().GetState() == KMachineState_Saved)
    623     {
    624         QSize size = guestSizeHint();
    625         UIResizeEvent event(FramebufferPixelFormat_Opaque, NULL, 0, 0, size.width(), size.height());
    626         frameBuffer()->resizeEvent(&event);
    627     }
    628 #endif /* Q_WS_X11 */
    629 }
    630 
    631 void UIMachineView::prepareCommon()
    632 {
    633     /* Prepare view frame: */
    634     setFrameStyle(QFrame::NoFrame);
    635 
    636     /* Pressed keys: */
    637     ::memset(m_pressedKeys, 0, sizeof(m_pressedKeys));
    638 
    639     /* Setup palette: */
    640     QPalette palette(viewport()->palette());
    641     palette.setColor(viewport()->backgroundRole(), Qt::black);
    642     viewport()->setPalette(palette);
    643 
    644     /* Setup focus policy: */
    645     setFocusPolicy(Qt::WheelFocus);
    646 
    647 #if defined Q_WS_PM
    648     bool ok = VBoxHlpInstallKbdHook(0, winId(), UM_PREACCEL_CHAR);
    649     Assert(ok);
    650     NOREF(ok);
    651 #endif
    652 }
    653 
    654 void UIMachineView::prepareFilters()
    655 {
    656     /* Enable MouseMove events: */
    657     viewport()->setMouseTracking(true);
    658 
    659     /* QScrollView does the below on its own, but let's
    660      * do it anyway for the case it will not do it in the future: */
    661     viewport()->installEventFilter(this);
    662 
    663     /* We want to be notified on some parent's events: */
    664     machineWindowWrapper()->machineWindow()->installEventFilter(this);
    665 }
    666 
    667 void UIMachineView::prepareConsoleConnections()
     298    {
     299        QList<ulong> screenIds = m_viewports.keys();
     300        for (int i = 0; i < screenIds.size(); ++i)
     301            m_viewports[screenIds[i]]->unsetCursor();
     302    }
     303}
     304
     305/* Mouse-handler constructor: */
     306UIMouseHandler::UIMouseHandler(UIMachineLogic *pMachineLogic)
     307    : QObject(pMachineLogic)
     308    , m_pMachineLogic(pMachineLogic)
     309    , m_iLastMouseWheelDelta(0)
     310    , m_iMouseCaptureViewIndex(-1)
    668311{
    669312    /* Machine state-change updater: */
    670313    connect(uisession(), SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged()));
    671314
    672     /* Mouse pointer shape state-change updater: */
    673     connect(uisession(), SIGNAL(sigMousePointerShapeChange()), this, SLOT(sltMousePointerShapeChanged()));
    674 
    675315    /* Mouse capability state-change updater: */
    676316    connect(uisession(), SIGNAL(sigMouseCapabilityChange()), this, SLOT(sltMouseCapabilityChanged()));
    677317
    678     /* Mouse captivity status-change updater: */
    679     connect(uisession(), SIGNAL(sigMouseCapturedStatusChanged()), this, SLOT(sltMouseCapturedStatusChanged()));
    680 }
    681 
    682 void UIMachineView::loadMachineViewSettings()
    683 {
    684     /* Global settings: */
    685     {
    686 #ifdef Q_WS_X11
    687         /* Initialize the X keyboard subsystem: */
    688         initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
    689 #endif
    690 
    691         /* Remember the desktop geometry and register for geometry
    692          * change events for telling the guest about video modes we like: */
    693         QString desktopGeometry = vboxGlobal().settings().publicProperty("GUI/MaxGuestResolution");
    694         if ((desktopGeometry == QString::null) || (desktopGeometry == "auto"))
    695             setDesktopGeometry(DesktopGeo_Automatic, 0, 0);
    696         else if (desktopGeometry == "any")
    697             setDesktopGeometry(DesktopGeo_Any, 0, 0);
    698         else
    699         {
    700             int width = desktopGeometry.section(',', 0, 0).toInt();
    701             int height = desktopGeometry.section(',', 1, 1).toInt();
    702             setDesktopGeometry(DesktopGeo_Fixed, width, height);
    703         }
    704     }
    705 
    706     /* Exatra data settings: */
    707     {
    708         /* CAD settings: */
    709         QString passCAD = session().GetConsole().GetMachine().GetExtraData(VBoxDefs::GUI_PassCAD);
    710         if (!passCAD.isEmpty() && ((passCAD != "false") || (passCAD != "no")))
    711             m_fPassCAD = true;
    712     }
    713 }
    714 
    715 void UIMachineView::cleanupCommon()
    716 {
    717 #ifdef Q_WS_PM
    718     bool ok = VBoxHlpUninstallKbdHook(0, winId(), UM_PREACCEL_CHAR);
    719     Assert(ok);
    720     NOREF(ok);
    721 #endif /* Q_WS_PM */
    722 
    723 #ifdef Q_WS_WIN
    724     if (gKbdHook)
    725         UnhookWindowsHookEx(gKbdHook);
    726     gView = 0;
    727 #endif /* Q_WS_WIN */
    728 
    729 #ifdef Q_WS_MAC
    730     /* We have to make sure the callback for the keyboard events is released
    731      * when closing this view. */
    732     if (m_fKeyboardGrabbed)
    733         darwinGrabKeyboardEvents (false);
    734 #endif /* Q_WS_MAC */
    735 }
    736 
    737 void UIMachineView::cleanupFrameBuffer()
    738 {
    739     if (m_pFrameBuffer)
    740     {
    741         /* Process pending frame-buffer resize events: */
    742         QApplication::sendPostedEvents(this, VBoxDefs::ResizeEventType);
    743 #ifdef VBOX_WITH_VIDEOHWACCEL
    744         if (m_fAccelerate2DVideo)
    745         {
    746             /* When 2D is enabled we do not re-create Framebuffers. This is done to
    747              * 1. avoid 2D command loss during the time slot when no framebuffer is assigned to the display
    748              * 2. make it easier to preserve the current 2D state */
    749             Assert(m_pFrameBuffer == uisession()->frameBuffer(screenId()));
    750             m_pFrameBuffer->setView(NULL);
    751         }
    752         else
    753 #endif
    754         {
    755             /* Warn framebuffer about its no more necessary: */
    756             m_pFrameBuffer->setDeleted(true);
    757             /* Detach framebuffer from Display: */
    758             CDisplay display = session().GetConsole().GetDisplay();
    759             display.SetFramebuffer(m_uScreenId, CFramebuffer(NULL));
    760             /* Release the reference: */
    761             m_pFrameBuffer->Release();
    762 //          delete m_pFrameBuffer; // TODO_NEW_CORE: possibly necessary to really cleanup
    763             m_pFrameBuffer = NULL;
    764         }
    765     }
    766 }
    767 
    768 bool UIMachineView::event(QEvent *pEvent)
    769 {
    770     switch (pEvent->type())
    771     {
    772         case QEvent::FocusIn:
    773         {
    774             if (uisession()->isRunning())
    775                 focusEvent(true);
    776             break;
    777         }
    778         case QEvent::FocusOut:
    779         {
    780             if (uisession()->isRunning())
    781                 focusEvent(false);
    782             else
     318    /* Mouse pointer shape state-change updaters: */
     319    connect(uisession(), SIGNAL(sigMousePointerShapeChange()), this, SLOT(sltMousePointerShapeChanged()));
     320    connect(this, SIGNAL(mouseStateChanged(int)), this, SLOT(sltMousePointerShapeChanged()));
     321
     322    /* Initialize: */
     323    sltMachineStateChanged();
     324    sltMousePointerShapeChanged();
     325    sltMouseCapabilityChanged();
     326}
     327
     328/* Mouse-handler destructor: */
     329UIMouseHandler::~UIMouseHandler()
     330{
     331}
     332
     333/* Machine-logic getter: */
     334UIMachineLogic* UIMouseHandler::machineLogic() const
     335{
     336    return m_pMachineLogic;
     337}
     338
     339/* UI Session getter: */
     340UISession* UIMouseHandler::uisession() const
     341{
     342    return machineLogic()->uisession();
     343}
     344
     345/* Main Session getter: */
     346CSession& UIMouseHandler::session() const
     347{
     348    return uisession()->session();
     349}
     350
     351/* Event handler for registered machine-view(s): */
     352bool UIMouseHandler::eventFilter(QObject *pWatched, QEvent *pEvent)
     353{
     354    /* If that object is of QWidget type: */
     355    if (QWidget *pWatchedWidget = qobject_cast<QWidget*>(pWatched))
     356    {
     357        /* If thats machine-view-viewport: */
     358        if (m_viewports.values().contains(pWatchedWidget))
     359        {
     360            /* Get current watched widget screen id: */
     361            ulong uScreenId = m_viewports.key(pWatchedWidget);
     362            /* Handle viewport events: */
     363            switch (pEvent->type())
    783364            {
    784                 /* Release the host key and all other pressed keys too even when paused
    785                  * (otherwise, we will get stuck keys in the guest when doing sendChangedKeyStates() on resume
    786                  * because key presses were already recorded in m_pressedKeys but key releases will most likely
    787                  * not reach us but the new focus window instead): */
    788                 releaseAllPressedKeys(true /* including host key? */);
    789             }
    790             break;
    791         }
    792 
    793         case VBoxDefs::RepaintEventType:
    794         {
    795             UIRepaintEvent *pPaintEvent = static_cast<UIRepaintEvent*>(pEvent);
    796             viewport()->repaint(pPaintEvent->x() - contentsX(), pPaintEvent->y() - contentsY(),
    797                                 pPaintEvent->width(), pPaintEvent->height());
    798 
    799             return true;
    800         }
    801 
    802 #ifdef VBOX_WITH_VIDEOHWACCEL
    803         case VBoxDefs::VHWACommandProcessType:
    804         {
    805             m_pFrameBuffer->doProcessVHWACommand(pEvent);
    806             return true;
    807         }
    808 #endif
    809 
    810         case QEvent::KeyPress:
    811         case QEvent::KeyRelease:
    812         {
    813             QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
    814 
    815 #ifdef Q_WS_PM
    816             // TODO: that a temporary solution to send Alt+Tab and friends to the guest.
    817             // The proper solution is to write a keyboard driver that will steal these combos from the host
    818             // (it's impossible to do so using hooks on OS/2):
    819 
    820             if (m_bIsHostkeyPressed)
    821             {
    822                 bool pressed = pEvent->type() == QEvent::KeyPress;
    823                 CKeyboard keyboard = session().GetConsole().GetKeyboard();
    824 
    825                 /* Whether the host key is Shift so that it will modify the hot key values?
    826                  * Note that we don't distinguish between left and right shift here (too much hassle): */
    827                 const bool kShift = (m_globalSettings.hostKey() == VK_SHIFT ||
    828                                     m_globalSettings.hostKey() == VK_LSHIFT) &&
    829                                     (pKeyEvent->state() & Qt::ShiftModifier);
    830                 /* define hot keys according to the Shift state */
    831                 const int kAltTab      = kShift ? Qt::Key_Exclam     : Qt::Key_1;
    832                 const int kAltShiftTab = kShift ? Qt::Key_At         : Qt::Key_2;
    833                 const int kCtrlEsc     = kShift ? Qt::Key_AsciiTilde : Qt::Key_QuoteLeft;
    834 
    835                 /* Simulate Alt+Tab on Host+1 and Alt+Shift+Tab on Host+2 */
    836                 if (pKeyEvent->key() == kAltTab || pKeyEvent->key() == kAltShiftTab)
    837                 {
    838                     if (pressed)
     365                case QEvent::MouseMove:
     366                case QEvent::MouseButtonRelease:
     367                {
     368                    /* Check if we should propagate this event to another window: */
     369                    QWidget *pHoveredWidget = QApplication::widgetAt(QCursor::pos());
     370                    if (pHoveredWidget && pHoveredWidget != pWatchedWidget && m_viewports.values().contains(pHoveredWidget))
    839371                    {
    840                         /* Send the Alt press to the guest */
    841                         if (!(m_pressedKeysCopy[0x38] & IsKeyPressed))
    842                         {
    843                             /* Store the press in *Copy to have it automatically
    844                              * released when the Host key is released: */
    845                             m_pressedKeysCopy[0x38] |= IsKeyPressed;
    846                             keyboard.PutScancode(0x38);
    847                         }
    848 
    849                         /* Make sure Shift is pressed if it's Key_2 and released if it's Key_1: */
    850                         if (pKeyEvent->key() == kAltTab &&
    851                             (m_pressedKeysCopy[0x2A] & IsKeyPressed))
    852                         {
    853                             m_pressedKeysCopy[0x2A] &= ~IsKeyPressed;
    854                             keyboard.PutScancode(0xAA);
    855                         }
    856                         else
    857                         if (pKeyEvent->key() == kAltShiftTab &&
    858                             !(m_pressedKeysCopy[0x2A] & IsKeyPressed))
    859                         {
    860                             m_pressedKeysCopy[0x2A] |= IsKeyPressed;
    861                             keyboard.PutScancode(0x2A);
    862                         }
    863                     }
    864 
    865                     keyboard.PutScancode(pressed ? 0x0F : 0x8F);
    866 
    867                     pKeyEvent->accept();
    868                     return true;
    869                 }
    870 
    871                 /* Simulate Ctrl+Esc on Host+Tilde */
    872                 if (pKeyEvent->key() == kCtrlEsc)
    873                 {
    874                     /* Send the Ctrl press to the guest */
    875                     if (pressed && !(m_pressedKeysCopy[0x1d] & IsKeyPressed))
    876                     {
    877                         /* store the press in *Copy to have it automatically
    878                          * released when the Host key is released */
    879                         m_pressedKeysCopy[0x1d] |= IsKeyPressed;
    880                         keyboard.PutScancode(0x1d);
    881                     }
    882 
    883                     keyboard.PutScancode(pressed ? 0x01 : 0x81);
    884 
    885                     pKeyEvent->accept();
    886                     return true;
    887                 }
    888             }
    889 #endif /* Q_WS_PM */
    890 
    891             if (m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyPress)
    892             {
    893                 /* Passing F1-F12 keys to the guest: */
    894                 if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F12)
    895                 {
    896                     QVector <LONG> combo(6);
    897                     combo[0] = 0x1d; /* Ctrl down */
    898                     combo[1] = 0x38; /* Alt  down */
    899                     combo[4] = 0xb8; /* Alt  up   */
    900                     combo[5] = 0x9d; /* Ctrl up   */
    901                     if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F10)
    902                     {
    903                         combo[2] = 0x3b + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 down */
    904                         combo[3] = 0xbb + (pKeyEvent->key() - Qt::Key_F1); /* F1-F10 up   */
    905                     }
    906                     /* some scan slice */
    907                     else if (pKeyEvent->key() >= Qt::Key_F11 && pKeyEvent->key() <= Qt::Key_F12)
    908                     {
    909                         combo[2] = 0x57 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 down */
    910                         combo[3] = 0xd7 + (pKeyEvent->key() - Qt::Key_F11); /* F11-F12 up   */
    911                     }
    912                     else
    913                         Assert(0);
    914 
    915                     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    916                     keyboard.PutScancodes(combo);
    917                 }
    918 
    919                 /* Process hot keys not processed in keyEvent() (as in case of non-alphanumeric keys): */
    920                 machineWindowWrapper()->machineLogic()->actionsPool()->processHotKey(QKeySequence(pKeyEvent->key()));
    921             }
    922             else if (!m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyRelease)
    923             {
    924                 /* Show a possible warning on key release which seems to be more expected by the end user: */
    925                 if (uisession()->isPaused())
    926                 {
    927                     /* Iif the reminder is disabled we pass the event to Qt to enable normal
    928                      * keyboard functionality (for example, menu access with Alt+Letter): */
    929                     if (!vboxProblem().remindAboutPausedVMInput())
    930                         break;
    931                 }
    932             }
    933 
    934             pKeyEvent->accept();
    935             return true;
    936         }
    937 
    938 #ifdef Q_WS_MAC
    939         /* posted OnShowWindow */
    940         case VBoxDefs::ShowWindowEventType:
    941         {
    942             /* Dunno what Qt3 thinks a window that has minimized to the dock should be - it is not hidden,
    943              * neither is it minimized. OTOH it is marked shown and visible, but not activated.
    944              * This latter isn't of much help though, since at this point nothing is marked activated.
    945              * I might have overlooked something, but I'm buggered what if I know what. So, I'll just always
    946              * show & activate the stupid window to make it get out of the dock when the user wishes to show a VM: */
    947             window()->show();
    948             window()->activateWindow();
    949             return true;
    950         }
    951 #endif
    952 
    953         default:
    954             break;
    955     }
    956 
    957     return QAbstractScrollArea::event(pEvent);
    958 }
    959 
    960 bool UIMachineView::eventFilter(QObject *pWatched, QEvent *pEvent)
    961 {
    962     if (pWatched == viewport())
    963     {
    964         switch (pEvent->type())
    965         {
    966             case QEvent::MouseMove:
    967             case QEvent::MouseButtonRelease:
    968             {
    969                 /* Check if we should propagate this event to another window: */
    970                 QWidget *pWidgetAt = QApplication::widgetAt(QCursor::pos());
    971                 if (pWidgetAt && pWidgetAt->window() && pWidgetAt->window()->inherits("UIMachineWindow") &&
    972                     pWidgetAt->window() != machineWindowWrapper()->machineWindow())
    973                 {
    974                     /* Get current mouse-move event: */
    975                     QMouseEvent *pOldMouseEvent = static_cast<QMouseEvent*>(pEvent);
    976 
    977                     /* Get real destination window of that event: */
    978                     UIMachineWindow *pMachineWindow =
    979                         pWidgetAt->window()->inherits("UIMachineWindowNormal") ?
    980                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowNormal*>(pWidgetAt->window())) :
    981                         pWidgetAt->window()->inherits("UIMachineWindowFullscreen") ?
    982                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowFullscreen*>(pWidgetAt->window())) :
    983                         pWidgetAt->window()->inherits("UIMachineWindowSeamless") ?
    984                         static_cast<UIMachineWindow*>(qobject_cast<UIMachineWindowSeamless*>(pWidgetAt->window())) : 0;
    985                     if (pMachineWindow)
    986                     {
    987                         /* Get viewport: */
    988                         QWidget *pOtherViewport = pMachineWindow->machineView()->viewport();
     372                        /* Get current mouse-move event: */
     373                        QMouseEvent *pOldMouseEvent = static_cast<QMouseEvent*>(pEvent);
    989374
    990375                        /* Prepare redirected mouse-move event: */
    991376                        QMouseEvent *pNewMouseEvent = new QMouseEvent(pOldMouseEvent->type(),
    992                                                                       pOtherViewport->mapFromGlobal(pOldMouseEvent->globalPos()),
     377                                                                      pHoveredWidget->mapFromGlobal(pOldMouseEvent->globalPos()),
    993378                                                                      pOldMouseEvent->globalPos(),
    994379                                                                      pOldMouseEvent->button(),
     
    997382
    998383                        /* Send that event to real destination: */
    999                         QApplication::postEvent(pOtherViewport, pNewMouseEvent);
     384                        QApplication::postEvent(pHoveredWidget, pNewMouseEvent);
    1000385
    1001386                        /* Filter out that event: */
    1002387                        return true;
    1003388                    }
    1004                 }
    1005 
    1006                 /* Check if we should activate window under cursor: */
    1007                 if (QApplication::activeWindow() &&
    1008                     QApplication::activeWindow()->inherits("UIMachineWindow") &&
    1009                     QApplication::activeWindow() != machineWindowWrapper()->machineWindow())
    1010                 {
    1011                     /* Activating hovered machine window: */
    1012                     machineWindowWrapper()->machineWindow()->activateWindow();
     389
     390                    /* Check if we should activate window under cursor: */
     391                    if (!uisession()->isMouseCaptured() &&
     392                        QApplication::activeWindow() &&
     393                        QApplication::activeWindow()->inherits("UIMachineWindow") &&
     394                        QApplication::activeWindow() != pWatchedWidget->window())
     395                    {
     396                        /* Activating hovered machine window: */
     397                        pWatchedWidget->window()->activateWindow();
    1013398#ifdef Q_WS_X11
    1014                     /* On X11 its not enough to just activate window if you
    1015                      * want to raise it also, so we will make it separately: */
    1016                     machineWindowWrapper()->machineWindow()->raise();
     399                        /* On X11 its not enough to just activate window if you
     400                         * want to raise it also, so we will make it separately: */
     401                        pWatchedWidget->window()->raise();
    1017402#endif /* Q_WS_X11 */
    1018                 }
    1019 
    1020                 /* This event should be also processed using next 'case': */
     403                    }
     404
     405                    /* This event should be also processed using next 'case': */
     406                }
     407                case QEvent::MouseButtonPress:
     408                case QEvent::MouseButtonDblClick:
     409                {
     410                    QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
     411                    m_iLastMouseWheelDelta = 0;
     412                    if (mouseEvent(pMouseEvent->type(), uScreenId,
     413                                   pMouseEvent->pos(), pMouseEvent->globalPos(),
     414                                   pMouseEvent->buttons(), 0, Qt::Horizontal))
     415                        return true;
     416                    break;
     417                }
     418                case QEvent::Wheel:
     419                {
     420                    QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent);
     421                    /* There are pointing devices which send smaller values for the delta than 120.
     422                     * Here we sum them up until we are greater than 120. This allows to have finer control
     423                     * over the speed acceleration & enables such devices to send a valid wheel event to our
     424                     * guest mouse device at all: */
     425                    int iDelta = 0;
     426                    m_iLastMouseWheelDelta += pWheelEvent->delta();
     427                    if (qAbs(m_iLastMouseWheelDelta) >= 120)
     428                    {
     429                        iDelta = m_iLastMouseWheelDelta;
     430                        m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
     431                    }
     432                    if (mouseEvent(pWheelEvent->type(), uScreenId,
     433                                   pWheelEvent->pos(), pWheelEvent->globalPos(),
     434#ifdef QT_MAC_USE_COCOA
     435                                   /* Qt Cocoa is buggy. It always reports a left button pressed when the
     436                                    * mouse wheel event occurs. A workaround is to ask the application which
     437                                    * buttons are pressed currently: */
     438                                   QApplication::mouseButtons(),
     439#else /* QT_MAC_USE_COCOA */
     440                                   pWheelEvent->buttons(),
     441#endif /* !QT_MAC_USE_COCOA */
     442                                   iDelta, pWheelEvent->orientation()))
     443                        return true;
     444                    break;
     445                }
     446#ifdef Q_WS_MAC
     447                case QEvent::Leave:
     448                {
     449                    /* Enable mouse event compression if we leave the VM view.
     450                     * This is necessary for having smooth resizing of the VM/other windows: */
     451                    ::darwinSetMouseCoalescingEnabled(true);
     452                    break;
     453                }
     454                case QEvent::Enter:
     455                {
     456                    /* Disable mouse event compression if we enter the VM view.
     457                     * So all mouse events are registered in the VM.
     458                     * Only do this if the keyboard/mouse is grabbed
     459                     * (this is when we have a valid event handler): */
     460                    if (m_views[uScreenId]->isKeyboardGrabbed())
     461                        ::darwinSetMouseCoalescingEnabled(false);
     462                    break;
     463                }
     464#endif /* Q_WS_MAC */
     465#ifdef Q_WS_WIN
     466                case QEvent::Resize:
     467                {
     468                    /* Update mouse clipping: */
     469                    updateMouseCursorClipping();
     470                    break;
     471                }
     472#endif /* Q_WS_WIN */
     473                default:
     474                    break;
    1021475            }
    1022             case QEvent::MouseButtonPress:
    1023             case QEvent::MouseButtonDblClick:
     476        }
     477        /* If no => check if that widget is of UIMachineView type: */
     478        else if (UIMachineView *pWatchedMachineView = qobject_cast<UIMachineView*>(pWatchedWidget))
     479        {
     480            /* If thats machine-view itself => handle machine-view events: */
     481            if (m_views.values().contains(pWatchedMachineView))
    1024482            {
    1025                 QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
    1026                 m_iLastMouseWheelDelta = 0;
    1027                 if (mouseEvent(pMouseEvent->type(), pMouseEvent->pos(), pMouseEvent->globalPos(),
    1028                                pMouseEvent->buttons(), pMouseEvent->modifiers(), 0, Qt::Horizontal))
    1029                     return true;
    1030                 break;
     483                switch (pEvent->type())
     484                {
     485                    case QEvent::FocusOut:
     486                        /* Just release the mouse: */
     487                        releaseMouse();
     488                        break;
     489                    default:
     490                        break;
     491                }
    1031492            }
    1032             case QEvent::Wheel:
    1033             {
    1034                 QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent);
    1035                 /* There are pointing devices which send smaller values for the delta than 120.
    1036                  * Here we sum them up until we are greater than 120. This allows to have finer control
    1037                  * over the speed acceleration & enables such devices to send a valid wheel event to our
    1038                  * guest mouse device at all: */
    1039                 int iDelta = 0;
    1040                 m_iLastMouseWheelDelta += pWheelEvent->delta();
    1041                 if (qAbs(m_iLastMouseWheelDelta) >= 120)
    1042                 {
    1043                     iDelta = m_iLastMouseWheelDelta;
    1044                     m_iLastMouseWheelDelta = m_iLastMouseWheelDelta % 120;
    1045                 }
    1046                 if (mouseEvent(pWheelEvent->type(), pWheelEvent->pos(), pWheelEvent->globalPos(),
    1047 #ifdef QT_MAC_USE_COCOA
    1048                                /* Qt Cocoa is buggy. It always reports a left button pressed when the
    1049                                 * mouse wheel event occurs. A workaround is to ask the application which
    1050                                 * buttons are pressed currently: */
    1051                                QApplication::mouseButtons(),
    1052 #else /* QT_MAC_USE_COCOA */
    1053                                pWheelEvent->buttons(),
    1054 #endif /* !QT_MAC_USE_COCOA */
    1055                                pWheelEvent->modifiers(),
    1056                                iDelta, pWheelEvent->orientation()))
    1057                     return true;
    1058                 break;
    1059             }
     493        }
     494    }
     495    return QObject::eventFilter(pWatched, pEvent);
     496}
     497
     498/* Separate function to handle most of existing mouse-events: */
     499bool UIMouseHandler::mouseEvent(int iEventType, ulong uScreenId,
     500                                const QPoint &relativePos, const QPoint &globalPos,
     501                                Qt::MouseButtons mouseButtons,
     502                                int wheelDelta, Qt::Orientation wheelDirection)
     503{
     504    /* Check if such view & viewport are registered: */
     505    if (!m_views.contains(uScreenId) || !m_viewports.contains(uScreenId))
     506        return true;
     507
     508    int iMouseButtonsState = 0;
     509    if (mouseButtons & Qt::LeftButton)
     510        iMouseButtonsState |= KMouseButtonState_LeftButton;
     511    if (mouseButtons & Qt::RightButton)
     512        iMouseButtonsState |= KMouseButtonState_RightButton;
     513    if (mouseButtons & Qt::MidButton)
     514        iMouseButtonsState |= KMouseButtonState_MiddleButton;
     515    if (mouseButtons & Qt::XButton1)
     516        iMouseButtonsState |= KMouseButtonState_XButton1;
     517    if (mouseButtons & Qt::XButton2)
     518        iMouseButtonsState |= KMouseButtonState_XButton2;
     519
    1060520#ifdef Q_WS_MAC
    1061             case QEvent::Leave:
    1062             {
    1063                 /* Enable mouse event compression if we leave the VM view. This is necessary for
    1064                  * having smooth resizing of the VM/other windows: */
    1065                 setMouseCoalescingEnabled(true);
    1066                 break;
    1067             }
    1068             case QEvent::Enter:
    1069             {
    1070                 /* Disable mouse event compression if we enter the VM view. So all mouse events are
    1071                  * registered in the VM. Only do this if the keyboard/mouse is grabbed (this is when
    1072                  * we have a valid event handler): */
    1073                 setMouseCoalescingEnabled(false);
    1074                 break;
    1075             }
     521    /* Simulate the right click on host-key + left-mouse-button: */
     522    if (m_views[uScreenId]->isHostKeyPressed() &&
     523        m_views[uScreenId]->isHostKeyAlone() &&
     524        iMouseButtonsState == KMouseButtonState_LeftButton)
     525        iMouseButtonsState = KMouseButtonState_RightButton;
    1076526#endif /* Q_WS_MAC */
    1077             case QEvent::Resize:
    1078             {
    1079 #ifdef Q_WS_WIN32
    1080                 updateMouseCursorClipping();
    1081 #endif
    1082 #ifdef VBOX_WITH_VIDEOHWACCEL
    1083                 if (m_pFrameBuffer)
    1084                 {
    1085                     m_pFrameBuffer->viewportResized(static_cast<QResizeEvent*>(pEvent));
    1086                 }
    1087 #endif
    1088                 break;
    1089             }
    1090             default:
    1091                 break;
    1092         }
    1093     }
    1094     else if (pWatched == machineWindowWrapper()->machineWindow())
    1095     {
    1096         switch (pEvent->type())
    1097         {
    1098             case QEvent::WindowStateChange:
    1099             {
    1100                 /* During minimizing and state restoring machineWindowWrapper() gets
    1101                  * the focus which belongs to console view window, so returning it properly. */
    1102                 QWindowStateChangeEvent *pWindowEvent = static_cast<QWindowStateChangeEvent*>(pEvent);
    1103                 if (pWindowEvent->oldState() & Qt::WindowMinimized)
    1104                 {
    1105                     if (QApplication::focusWidget())
    1106                     {
    1107                         QApplication::focusWidget()->clearFocus();
    1108                         qApp->processEvents();
    1109                     }
    1110                     QTimer::singleShot(0, this, SLOT(setFocus()));
    1111                 }
    1112                 break;
    1113             }
    1114 #if defined (Q_WS_WIN32)
    1115             /* Install/uninstall low-level kbd hook on every activation/deactivation to:
    1116              * a) avoid excess hook calls when we're not active and
    1117              * b) be always in front of any other possible hooks */
    1118             case QEvent::WindowActivate:
    1119             {
    1120                 gView = this;
    1121                 gKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0);
    1122                 AssertMsg(gKbdHook, ("SetWindowsHookEx(): err=%d", GetLastError()));
    1123                 break;
    1124             }
    1125             case QEvent::WindowDeactivate:
    1126             {
    1127                 if (gKbdHook)
    1128                 {
    1129                     UnhookWindowsHookEx(gKbdHook);
    1130                     gKbdHook = NULL;
    1131                     if (gView == this)
    1132                         gView = 0;
    1133                 }
    1134                 break;
    1135             }
    1136 #endif /* defined (Q_WS_WIN32) */
    1137 #ifdef Q_WS_MAC
    1138             /* Install/remove the keyboard event handler: */
    1139             case QEvent::WindowActivate:
    1140                 darwinGrabKeyboardEvents(true);
    1141                 break;
    1142             case QEvent::WindowDeactivate:
    1143                 darwinGrabKeyboardEvents(false);
    1144                 break;
    1145 #endif /* Q_WS_MAC */
    1146             default:
    1147                 break;
    1148         }
    1149     }
    1150 
    1151     return QAbstractScrollArea::eventFilter (pWatched, pEvent);
    1152 }
    1153 
    1154 void UIMachineView::sltMachineStateChanged()
    1155 {
    1156     /* Get machine state: */
    1157     KMachineState state = uisession()->machineState();
    1158     switch (state)
    1159     {
    1160         case KMachineState_Paused:
    1161         case KMachineState_TeleportingPausedVM:
    1162         {
    1163             if (mode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
    1164                 (state != KMachineState_TeleportingPausedVM || m_previousState != KMachineState_Teleporting))
    1165             {
    1166                 /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
    1167                 QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
    1168                 /* If TakeScreenShot fails or returns no image, just show a black image. */
    1169                 shot.fill(0);
    1170                 CDisplay dsp = session().GetConsole().GetDisplay();
    1171                 dsp.TakeScreenShot(screenId(), shot.bits(), shot.width(), shot.height());
    1172                 /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
    1173                  * after the machine execution was resumed. It's not fatal: */
    1174                 if (dsp.isOk())
    1175                 {
    1176                     dimImage(shot);
    1177                 }
    1178                 m_pauseShot = QPixmap::fromImage(shot);
    1179                 /* Fully repaint to pick up m_pauseShot: */
    1180                 viewport()->repaint();
    1181             }
    1182             /* reuse the focus event handler to uncapture everything */
    1183             if (hasFocus())
    1184                 focusEvent (false /* aHasFocus*/, false /* aReleaseHostKey */);
    1185             break;
    1186         }
    1187         case KMachineState_Stuck:
    1188         {
    1189             /* Reuse the focus event handler to uncapture everything: */
    1190             if (hasFocus())
    1191                 focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
    1192             break;
    1193         }
    1194         case KMachineState_Running:
    1195         {
    1196             if (   m_previousState == KMachineState_Paused
    1197                 || m_previousState == KMachineState_TeleportingPausedVM
    1198                 || m_previousState == KMachineState_Restoring)
    1199             {
    1200                 if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer)
    1201                 {
    1202                     /* Reset the pixmap to free memory: */
    1203                     m_pauseShot = QPixmap();
    1204                     /* Ask for full guest display update (it will also update
    1205                      * the viewport through IFramebuffer::NotifyUpdate): */
    1206                     CDisplay dsp = session().GetConsole().GetDisplay();
    1207                     dsp.InvalidateAndUpdate();
    1208                 }
    1209             }
    1210             /* Reuse the focus event handler to capture input: */
    1211             if (hasFocus())
    1212                 focusEvent(true /* aHasFocus */);
    1213             break;
    1214         }
    1215         default:
    1216             break;
    1217     }
    1218 
    1219     m_previousState = state;
    1220 }
    1221 
    1222 void UIMachineView::sltMousePointerShapeChanged()
    1223 {
    1224     /* Update mouse cursor: */
    1225     updateMouseCursorShape();
    1226 }
    1227 
    1228 void UIMachineView::sltMouseCapabilityChanged()
    1229 {
    1230     /* We should release mouse if guest notified us about it supports 'absolute' mouse
    1231      * and mouse is in 'integrated' mode, which could be chosen from main machine menu: */
    1232     if (uisession()->isMouseIntegrated() && uisession()->isMouseSupportsAbsolute())
    1233     {
    1234         CMouse mouse = session().GetConsole().GetMouse();
    1235         mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
    1236         captureMouse(false, false);
    1237     }
    1238 
    1239     /* Update mouse cursor shape: */
    1240     updateMouseCursorShape();
    1241 
    1242     /* Notify user about mouse 'absolute' state if method was called by signal: */
    1243     if (sender()) vboxProblem().remindAboutMouseIntegration(uisession()->isMouseSupportsAbsolute());
    1244 
    1245     /* Notify all listeners: */
    1246     emitMouseStateChanged();
    1247 }
    1248 
    1249 void UIMachineView::sltMouseCapturedStatusChanged()
    1250 {
    1251     /* If mouse 'captured' state value changed to 'false': */
    1252     if (!uisession()->isMouseCaptured())
    1253     {
    1254         /* Releasing grabbed mouse from that window: */
    1255 #ifdef Q_WS_WIN
    1256         m_fItsMeWhoCapturedMouse = false;
    1257         ::ClipCursor(NULL);
    1258 #else
    1259         viewport()->releaseMouse();
    1260 #endif /* Q_WS_WIN */
    1261     }
    1262 
    1263     /* Update mouse cursor shape: */
    1264     updateMouseCursorShape();
    1265 }
    1266 
    1267 void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */)
    1268 {
    1269     if (fHasFocus)
    1270     {
    1271 #ifdef Q_WS_WIN32
    1272         if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture() && GetAncestor(winId(), GA_ROOT) == GetForegroundWindow())
    1273 #else
    1274         if (!m_bIsAutoCaptureDisabled && m_globalSettings.autoCapture())
    1275 #endif
    1276         {
    1277             captureKbd(true);
    1278         }
    1279 
    1280         /* Reset the single-time disable capture flag: */
    1281         if (m_bIsAutoCaptureDisabled)
    1282             m_bIsAutoCaptureDisabled = false;
    1283     }
    1284     else
    1285     {
    1286         captureMouse(false);
    1287         captureKbd(false, false);
    1288         releaseAllPressedKeys(fReleaseHostKey);
    1289     }
    1290 }
    1291 
    1292 bool UIMachineView::keyEvent(int iKey, uint8_t uScan, int fFlags, wchar_t *pUniKey /* = NULL */)
    1293 {
    1294     const bool isHostKey = iKey == m_globalSettings.hostKey();
    1295 
    1296     LONG buf[16];
    1297     LONG *codes = buf;
    1298     uint count = 0;
    1299     uint8_t whatPressed = 0;
    1300 
    1301     if (!isHostKey && !m_bIsHostkeyPressed)
    1302     {
    1303         if (fFlags & KeyPrint)
    1304         {
    1305             static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 };
    1306             static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA };
    1307             if (fFlags & KeyPressed)
    1308             {
    1309                 codes = PrintMake;
    1310                 count = SIZEOF_ARRAY(PrintMake);
    1311             }
    1312             else
    1313             {
    1314                 codes = PrintBreak;
    1315                 count = SIZEOF_ARRAY(PrintBreak);
    1316             }
    1317         }
    1318         else if (fFlags & KeyPause)
    1319         {
    1320             if (fFlags & KeyPressed)
    1321             {
    1322                 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 };
    1323                 codes = Pause;
    1324                 count = SIZEOF_ARRAY(Pause);
    1325             }
    1326             else
    1327             {
    1328                 /* Pause shall not produce a break code */
    1329                 return true;
    1330             }
    1331         }
    1332         else
    1333         {
    1334             if (fFlags & KeyPressed)
    1335             {
    1336                 /* Check if the guest has the same view on the modifier keys (NumLock,
    1337                  * CapsLock, ScrollLock) as the X server. If not, send KeyPress events
    1338                  * to synchronize the state. */
    1339                 fixModifierState(codes, &count);
    1340             }
    1341 
    1342             /* Check if it's C-A-D and GUI/PassCAD is not true */
    1343             if (!m_fPassCAD &&
    1344                 uScan == 0x53 /* Del */ &&
    1345                 ((m_pressedKeys[0x38] & IsKeyPressed) /* Alt */ ||
    1346                  (m_pressedKeys[0x38] & IsExtKeyPressed)) &&
    1347                 ((m_pressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ ||
    1348                  (m_pressedKeys[0x1d] & IsExtKeyPressed)))
    1349             {
    1350                 /* Use the C-A-D combination as a last resort to get the
    1351                  * keyboard and mouse back to the host when the user forgets
    1352                  * the Host Key. Note that it's always possible to send C-A-D
    1353                  * to the guest using the Host+Del combination. BTW, it would
    1354                  * be preferrable to completely ignore C-A-D in guests, but
    1355                  * that's not possible because we cannot predict what other
    1356                  * keys will be pressed next when one of C, A, D is held. */
    1357                 if (uisession()->isRunning() && m_bIsKeyboardCaptured)
    1358                 {
    1359                     captureKbd(false);
    1360                     if (!(uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated()))
    1361                         captureMouse(false);
    1362                 }
    1363 
    1364                 return true;
    1365             }
    1366 
    1367             /* Process the scancode and update the table of pressed keys: */
    1368             whatPressed = IsKeyPressed;
    1369 
    1370             if (fFlags & KeyExtended)
    1371             {
    1372                 codes[count++] = 0xE0;
    1373                 whatPressed = IsExtKeyPressed;
    1374             }
    1375 
    1376             if (fFlags & KeyPressed)
    1377             {
    1378                 codes[count++] = uScan;
    1379                 m_pressedKeys[uScan] |= whatPressed;
    1380             }
    1381             else
    1382             {
    1383                 /* If we haven't got this key's press message, we ignore its release: */
    1384                 if (!(m_pressedKeys[uScan] & whatPressed))
    1385                     return true;
    1386                 codes[count++] = uScan | 0x80;
    1387                 m_pressedKeys[uScan] &= ~whatPressed;
    1388             }
    1389 
    1390             if (m_bIsKeyboardCaptured)
    1391                 m_pressedKeys[uScan] |= IsKbdCaptured;
    1392             else
    1393                 m_pressedKeys[uScan] &= ~IsKbdCaptured;
    1394         }
    1395     }
    1396     else
    1397     {
    1398         /* Currently this is used in winLowKeyboardEvent() only: */
    1399         m_bIsHostkeyInCapture = m_bIsKeyboardCaptured;
    1400     }
    1401 
    1402     bool emitSignal = false;
    1403     int hotkey = 0;
    1404 
    1405     /* Process the host key: */
    1406     if (fFlags & KeyPressed)
    1407     {
    1408         if (isHostKey)
    1409         {
    1410             if (!m_bIsHostkeyPressed)
    1411             {
    1412                 m_bIsHostkeyPressed = m_bIsHostkeyAlone = true;
    1413                 if (uisession()->isRunning())
    1414                     saveKeyStates();
    1415                 emitSignal = true;
    1416             }
    1417         }
    1418         else
    1419         {
    1420             if (m_bIsHostkeyPressed)
    1421             {
    1422                 if (m_bIsHostkeyAlone)
    1423                 {
    1424                     hotkey = iKey;
    1425                     m_bIsHostkeyAlone = false;
    1426                 }
    1427             }
    1428         }
    1429     }
    1430     else
    1431     {
    1432         if (isHostKey)
    1433         {
    1434             if (m_bIsHostkeyPressed)
    1435             {
    1436                 m_bIsHostkeyPressed = false;
    1437 
    1438                 if (m_bIsHostkeyAlone)
    1439                 {
    1440                     if (uisession()->isPaused())
    1441                     {
    1442                         vboxProblem().remindAboutPausedVMInput();
    1443                     }
    1444                     else if (uisession()->isRunning())
    1445                     {
    1446                         bool captured = m_bIsKeyboardCaptured;
    1447                         bool ok = true;
    1448                         if (!captured)
    1449                         {
    1450                             /* temporarily disable auto capture that will take
    1451                              * place after this dialog is dismissed because
    1452                              * the capture state is to be defined by the
    1453                              * dialog result itself */
    1454                             m_bIsAutoCaptureDisabled = true;
    1455                             bool autoConfirmed = false;
    1456                             ok = vboxProblem().confirmInputCapture (&autoConfirmed);
    1457                             if (autoConfirmed)
    1458                                 m_bIsAutoCaptureDisabled = false;
    1459                             /* otherwise, the disable flag will be reset in
    1460                              * the next console view's foucs in event (since
    1461                              * may happen asynchronously on some platforms,
    1462                              * after we return from this code) */
    1463                         }
    1464 
    1465                         if (ok)
    1466                         {
    1467                             captureKbd (!captured, false);
    1468                             if (!(uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated()))
    1469                             {
    1470 #ifdef Q_WS_X11
    1471                                 /* make sure that pending FocusOut events from the
    1472                                  * previous message box are handled, otherwise the
    1473                                  * mouse is immediately ungrabbed. */
    1474                                 qApp->processEvents();
    1475 #endif
    1476                                 captureMouse(m_bIsKeyboardCaptured);
    1477                             }
    1478                         }
    1479                     }
    1480                 }
    1481 
    1482                 if (uisession()->isRunning())
    1483                     sendChangedKeyStates();
    1484 
    1485                 emitSignal = true;
    1486             }
    1487         }
    1488         else
    1489         {
    1490             if (m_bIsHostkeyPressed)
    1491                 m_bIsHostkeyAlone = false;
    1492         }
    1493     }
    1494 
    1495     /* emit the keyboard state change signal */
    1496     if (emitSignal)
    1497         emitKeyboardStateChanged();
    1498 
    1499     /* Process Host+<key> shortcuts. currently, <key> is limited to
    1500      * alphanumeric chars. Other Host+<key> combinations are handled in
    1501      * event(). */
    1502     if (hotkey)
    1503     {
    1504         bool processed = false;
    1505 #if defined (Q_WS_WIN32)
    1506         NOREF(pUniKey);
    1507         int n = GetKeyboardLayoutList(0, NULL);
    1508         Assert (n);
    1509         HKL *list = new HKL[n];
    1510         GetKeyboardLayoutList(n, list);
    1511         for (int i = 0; i < n && !processed; i++)
    1512         {
    1513             wchar_t ch;
    1514             static BYTE keys[256] = {0};
    1515             if (!ToUnicodeEx(hotkey, 0, keys, &ch, 1, 0, list[i]) == 1)
    1516                 ch = 0;
    1517             if (ch)
    1518                 processed = machineWindowWrapper()->machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(ch).toUpper().unicode())));
    1519         }
    1520         delete[] list;
    1521 #elif defined (Q_WS_X11)
    1522         NOREF(pUniKey);
    1523         Display *display = QX11Info::display();
    1524         int keysyms_per_keycode = getKeysymsPerKeycode();
    1525         KeyCode kc = XKeysymToKeycode (display, iKey);
    1526         for (int i = 0; i < keysyms_per_keycode && !processed; i += 2)
    1527         {
    1528             KeySym ks = XKeycodeToKeysym(display, kc, i);
    1529             char ch = 0;
    1530             if (!XkbTranslateKeySym(display, &ks, 0, &ch, 1, NULL) == 1)
    1531                 ch = 0;
    1532             if (ch)
    1533                 QChar c = QString::fromLocal8Bit(&ch, 1)[0];
    1534         }
    1535 #elif defined (Q_WS_MAC)
    1536         if (pUniKey && pUniKey[0] && !pUniKey[1])
    1537             processed = machineWindowWrapper()->machineLogic()->actionsPool()->processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(pUniKey[0]).toUpper().unicode()));
    1538 
    1539         /* Don't consider the hot key as pressed since the guest never saw
    1540          * it. (probably a generic thing) */
    1541         m_pressedKeys[uScan] &= ~whatPressed;
    1542 #endif
    1543 
    1544         /* Grab the key from Qt if processed, or pass it to Qt otherwise
    1545          * in order to process non-alphanumeric keys in event(), after they are
    1546          * converted to Qt virtual keys. */
    1547         return processed;
    1548     }
    1549 
    1550     /* No more to do, if the host key is in action or the VM is paused: */
    1551     if (m_bIsHostkeyPressed || isHostKey || uisession()->isPaused())
    1552     {
    1553         /* Grab the key from Qt and from VM if it's a host key,
    1554          * otherwise just pass it to Qt */
    1555         return isHostKey;
    1556     }
    1557 
    1558     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    1559     Assert(!keyboard.isNull());
    1560 
    1561 #if defined (Q_WS_WIN32)
    1562     /* send pending WM_PAINT events */
    1563     ::UpdateWindow(viewport()->winId());
    1564 #endif
    1565 
    1566     std::vector <LONG> scancodes(codes, &codes[count]);
    1567     keyboard.PutScancodes(QVector<LONG>::fromStdVector(scancodes));
    1568 
    1569     /* Grab the key from Qt: */
    1570     return true;
    1571 }
    1572 
    1573 bool UIMachineView::mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    1574                                Qt::MouseButtons aButtons, Qt::KeyboardModifiers /* aModifiers */,
    1575                                int aWheelDelta, Qt::Orientation aWheelDir)
    1576 {
    1577     int state = 0;
    1578     if (aButtons & Qt::LeftButton)
    1579         state |= KMouseButtonState_LeftButton;
    1580     if (aButtons & Qt::RightButton)
    1581         state |= KMouseButtonState_RightButton;
    1582     if (aButtons & Qt::MidButton)
    1583         state |= KMouseButtonState_MiddleButton;
    1584     if (aButtons & Qt::XButton1)
    1585         state |= KMouseButtonState_XButton1;
    1586     if (aButtons & Qt::XButton2)
    1587         state |= KMouseButtonState_XButton2;
    1588 
    1589 #ifdef Q_WS_MAC
    1590     /* Simulate the right click on Host+Left Mouse: */
    1591     if (m_bIsHostkeyPressed &&
    1592         m_bIsHostkeyAlone &&
    1593         state == KMouseButtonState_LeftButton)
    1594         state = KMouseButtonState_RightButton;
    1595 #endif /* Q_WS_MAC */
    1596 
    1597     int wheelVertical = 0;
    1598     int wheelHorizontal = 0;
    1599     if (aWheelDir == Qt::Vertical)
     527
     528    int iWheelVertical = 0;
     529    int iWheelHorizontal = 0;
     530    if (wheelDirection == Qt::Vertical)
    1600531    {
    1601532        /* The absolute value of wheel delta is 120 units per every wheel move;
    1602533         * positive deltas correspond to counterclockwize rotations (usually up),
    1603534         * negative deltas correspond to clockwize (usually down). */
    1604         wheelVertical = - (aWheelDelta / 120);
    1605     }
    1606     else if (aWheelDir == Qt::Horizontal)
    1607         wheelHorizontal = aWheelDelta / 120;
     535        iWheelVertical = - (wheelDelta / 120);
     536    }
     537    else if (wheelDirection == Qt::Horizontal)
     538        iWheelHorizontal = wheelDelta / 120;
    1608539
    1609540    if (uisession()->isMouseCaptured())
    1610541    {
    1611 #ifdef Q_WS_WIN32
     542#ifdef Q_WS_WIN
    1612543        /* Send pending WM_PAINT events: */
    1613         ::UpdateWindow(viewport()->winId());
     544        ::UpdateWindow(m_viewports[uScreenId]->winId());
    1614545#endif
    1615546
    1616547        CMouse mouse = session().GetConsole().GetMouse();
    1617         mouse.PutMouseEvent(aGlobalPos.x() - m_lastMousePos.x(),
    1618                             aGlobalPos.y() - m_lastMousePos.y(),
    1619                             wheelVertical, wheelHorizontal, state);
    1620 
    1621 #if defined (Q_WS_MAC)
    1622         /*
    1623          * Keep the mouse from leaving the widget.
    1624          *
     548        mouse.PutMouseEvent(globalPos.x() - m_lastMousePos.x(),
     549                            globalPos.y() - m_lastMousePos.y(),
     550                            iWheelVertical, iWheelHorizontal, iMouseButtonsState);
     551
     552#ifdef Q_WS_MAC
     553        /* Keep the mouse from leaving the widget.
    1625554         * This is a bit tricky to get right because if it escapes we won't necessarily
    1626555         * get mouse events any longer and can warp it back. So, we keep safety zone
    1627556         * of up to 300 pixels around the borders of the widget to prevent this from
    1628557         * happening. Also, the mouse is warped back to the center of the widget.
    1629          *
    1630          * (Note, aPos seems to be unreliable, it caused endless recursion here at one points...)
    1631          * (Note, synergy and other remote clients might not like this cursor warping.)
    1632          */
    1633         QRect rect = viewport()->visibleRegion().boundingRect();
    1634         QPoint pw = viewport()->mapToGlobal(viewport()->pos());
     558         * (Note, relativePos seems to be unreliable, it caused endless recursion here at one points...)
     559         * (Note, synergy and other remote clients might not like this cursor warping.) */
     560        QRect rect = m_viewports[uScreenId]->visibleRegion().boundingRect();
     561        QPoint pw = m_viewports[uScreenId]->mapToGlobal(m_viewports[uScreenId]->pos());
    1635562        rect.translate(pw.x(), pw.y());
    1636563
    1637         QRect dpRect = QApplication::desktop()->screenGeometry(viewport());
    1638         if (rect.intersects (dpRect))
     564        QRect dpRect = QApplication::desktop()->screenGeometry(m_viewports[uScreenId]);
     565        if (rect.intersects(dpRect))
    1639566            rect = rect.intersect(dpRect);
    1640567
    1641         int wsafe = rect.width() / 6;
    1642         rect.setWidth(rect.width() - wsafe * 2);
    1643         rect.setLeft(rect.left() + wsafe);
    1644 
    1645         int hsafe = rect.height() / 6;
    1646         rect.setWidth(rect.height() - hsafe * 2);
    1647         rect.setTop(rect.top() + hsafe);
    1648 
    1649         if (rect.contains(aGlobalPos, true))
    1650             m_lastMousePos = aGlobalPos;
     568        int iWsafe = rect.width() / 6;
     569        rect.setWidth(rect.width() - iWsafe * 2);
     570        rect.setLeft(rect.left() + iWsafe);
     571
     572        int iHsafe = rect.height() / 6;
     573        rect.setWidth(rect.height() - iHsafe * 2);
     574        rect.setTop(rect.top() + iHsafe);
     575
     576        if (rect.contains(globalPos, true))
     577            m_lastMousePos = globalPos;
    1651578        else
    1652579        {
     
    1654581            QCursor::setPos(m_lastMousePos);
    1655582        }
    1656 #else /* !Q_WS_MAC */
    1657 
    1658         /* "jerk" the mouse by bringing it to the opposite side
    1659          * to simulate the endless moving */
    1660 
    1661 # ifdef Q_WS_WIN32
    1662         int we = viewport()->width() - 1;
    1663         int he = viewport()->height() - 1;
    1664         QPoint p = aPos;
    1665         if (aPos.x() == 0)
    1666             p.setX(we - 1);
    1667         else if (aPos.x() == we)
     583#else /* Q_WS_MAC */
     584
     585        /* Bringing mouse to the opposite side to simulate the endless moving: */
     586
     587# ifdef Q_WS_WIN
     588        int iWe = m_viewports[uScreenId]->width() - 1;
     589        int iHe = m_viewports[uScreenId]->height() - 1;
     590        QPoint p = relativePos;
     591        if (relativePos.x() == 0)
     592            p.setX(iWe - 1);
     593        else if (relativePos.x() == iWe)
    1668594            p.setX(1);
    1669         if (aPos.y() == 0 )
    1670             p.setY(he - 1);
    1671         else if (aPos.y() == he)
     595        if (relativePos.y() == 0 )
     596            p.setY(iHe - 1);
     597        else if (relativePos.y() == iHe)
    1672598            p.setY(1);
    1673599
    1674         if (p != aPos)
    1675         {
    1676             m_lastMousePos = viewport()->mapToGlobal (p);
     600        if (p != relativePos)
     601        {
     602            m_lastMousePos = m_viewports[uScreenId]->mapToGlobal(p);
    1677603            QCursor::setPos(m_lastMousePos);
    1678604        }
    1679605        else
    1680606        {
    1681             m_lastMousePos = aGlobalPos;
    1682         }
    1683 # else
    1684         int we = QApplication::desktop()->width() - 1;
    1685         int he = QApplication::desktop()->height() - 1;
    1686         QPoint p = aGlobalPos;
    1687         if (aGlobalPos.x() == 0)
    1688             p.setX (we - 1);
    1689         else if (aGlobalPos.x() == we)
     607            m_lastMousePos = globalPos;
     608        }
     609# else /* Q_WS_WIN */
     610        int iWe = QApplication::desktop()->width() - 1;
     611        int iHe = QApplication::desktop()->height() - 1;
     612        QPoint p = globalPos;
     613        if (globalPos.x() == 0)
     614            p.setX(iWe - 1);
     615        else if (globalPos.x() == iWe)
    1690616            p.setX( 1 );
    1691         if (aGlobalPos.y() == 0)
    1692             p.setY (he - 1);
    1693         else if (aGlobalPos.y() == he)
    1694             p.setY (1);
    1695 
    1696         if (p != aGlobalPos)
     617        if (globalPos.y() == 0)
     618            p.setY(iHe - 1);
     619        else if (globalPos.y() == iHe)
     620            p.setY(1);
     621
     622        if (p != globalPos)
    1697623        {
    1698624            m_lastMousePos =  p;
     
    1701627        else
    1702628        {
    1703             m_lastMousePos = aGlobalPos;
    1704         }
    1705 # endif
     629            m_lastMousePos = globalPos;
     630        }
     631# endif /* !Q_WS_WIN */
    1706632#endif /* !Q_WS_MAC */
    1707633        return true; /* stop further event handling */
     
    1709635    else /* !uisession()->isMouseCaptured() */
    1710636    {
    1711 #if 0 // TODO: Move that to fullscreen event-hjadler:
    1712         if (mode() != VBoxDefs::SDLMode)
     637#if 0 // TODO: Move that to fullscreen event-handler:
     638        if (vboxGlobal().vmRenderMode() != VBoxDefs::SDLMode)
    1713639        {
    1714640            /* try to automatically scroll the guest canvas if the
     
    1716642            /// @todo (r=dmik) better use a timer for autoscroll
    1717643            QRect scrGeo = QApplication::desktop()->screenGeometry (this);
    1718             int dx = 0, dy = 0;
     644            int iDx = 0, iDy = 0;
    1719645            if (scrGeo.width() < contentsWidth())
    1720646            {
    1721                 if (scrGeo.left() == aGlobalPos.x()) dx = -1;
    1722                 if (scrGeo.right() == aGlobalPos.x()) dx = +1;
     647                if (scrGeo.left() == globalPos.x()) iDx = -1;
     648                if (scrGeo.right() == globalPos.x()) iDx = +1;
    1723649            }
    1724650            if (scrGeo.height() < contentsHeight())
    1725651            {
    1726                 if (scrGeo.top() == aGlobalPos.y()) dy = -1;
    1727                 if (scrGeo.bottom() == aGlobalPos.y()) dy = +1;
     652                if (scrGeo.top() == globalPos.y()) iDy = -1;
     653                if (scrGeo.bottom() == globalPos.y()) iDy = +1;
    1728654            }
    1729             if (dx || dy)
    1730                 scrollBy(dx, dy);
     655            if (iDx || iDy)
     656                scrollBy(iDx, iDy);
    1731657        }
    1732658#endif
     
    1734660        if (uisession()->isMouseSupportsAbsolute() && uisession()->isMouseIntegrated())
    1735661        {
    1736             int cw = contentsWidth(), ch = contentsHeight();
    1737             int vw = visibleWidth(), vh = visibleHeight();
    1738 
    1739             if (mode() != VBoxDefs::SDLMode)
     662            int iCw = m_views[uScreenId]->contentsWidth(), iCh = m_views[uScreenId]->contentsHeight();
     663            int iVw = m_views[uScreenId]->visibleWidth(), iVh = m_views[uScreenId]->visibleHeight();
     664
     665            if (vboxGlobal().vmRenderMode() != VBoxDefs::SDLMode)
    1740666            {
    1741667                /* Try to automatically scroll the guest canvas if the
    1742668                 * mouse goes outside its visible part: */
    1743                 int dx = 0;
    1744                 if (aPos.x() > vw) dx = aPos.x() - vw;
    1745                 else if (aPos.x() < 0) dx = aPos.x();
    1746                 int dy = 0;
    1747                 if (aPos.y() > vh) dy = aPos.y() - vh;
    1748                 else if (aPos.y() < 0) dy = aPos.y();
    1749                 if (dx != 0 || dy != 0) scrollBy (dx, dy);
     669                int iDx = 0;
     670                if (relativePos.x() > iVw) iDx = relativePos.x() - iVw;
     671                else if (relativePos.x() < 0) iDx = relativePos.x();
     672                int iDy = 0;
     673                if (relativePos.y() > iVh) iDy = relativePos.y() - iVh;
     674                else if (relativePos.y() < 0) iDy = relativePos.y();
     675                if (iDx != 0 || iDy != 0) m_views[uScreenId]->scrollBy(iDx, iDy);
    1750676            }
    1751677
    1752             QPoint cpnt = viewportToContents(aPos);
     678            QPoint cpnt = m_views[uScreenId]->viewportToContents(relativePos);
    1753679            if (cpnt.x() < 0) cpnt.setX(0);
    1754             else if (cpnt.x() > cw - 1) cpnt.setX(cw - 1);
     680            else if (cpnt.x() > iCw - 1) cpnt.setX(iCw - 1);
    1755681            if (cpnt.y() < 0) cpnt.setY(0);
    1756             else if (cpnt.y() > ch - 1) cpnt.setY(ch - 1);
    1757 
    1758             // TODO: Where to put that actually?
     682            else if (cpnt.y() > iCh - 1) cpnt.setY(iCh - 1);
     683
    1759684            /* Get & Setup absolute-event shift: */
    1760685            CFramebuffer framebuffer;
    1761686            LONG xShift = 0, yShift = 0;
    1762             session().GetConsole().GetDisplay().GetFramebuffer(screenId(), framebuffer, xShift, yShift);
     687            session().GetConsole().GetDisplay().GetFramebuffer(uScreenId, framebuffer, xShift, yShift);
    1763688            cpnt.setX(cpnt.x() + xShift);
    1764689            cpnt.setY(cpnt.y() + yShift);
    1765690
    1766691            CMouse mouse = session().GetConsole().GetMouse();
    1767             // AssertMsgFailed(("x=%d, y=%d", cpnt.x(), cpnt.y())); // this shows what absolute coordinates are correct!
    1768             mouse.PutMouseEventAbsolute(cpnt.x() + 1, cpnt.y() + 1, wheelVertical, wheelHorizontal, state);
     692            mouse.PutMouseEventAbsolute(cpnt.x() + 1, cpnt.y() + 1, iWheelVertical, iWheelHorizontal, iMouseButtonsState);
    1769693            return true;
    1770694        }
    1771695        else
    1772696        {
    1773             if (hasFocus() && (aType == QEvent::MouseButtonRelease && aButtons == Qt::NoButton))
     697            if (m_views[uScreenId]->hasFocus() && (iEventType == QEvent::MouseButtonRelease && mouseButtons == Qt::NoButton))
    1774698            {
    1775699                if (uisession()->isPaused())
     
    1781705                    /* Temporarily disable auto capture that will take place after this dialog is dismissed because
    1782706                     * the capture state is to be defined by the dialog result itself: */
    1783                     m_bIsAutoCaptureDisabled = true;
     707                    uisession()->setAutoCaptureDisabled(true);
    1784708                    bool autoConfirmed = false;
    1785709                    bool ok = vboxProblem().confirmInputCapture(&autoConfirmed);
    1786710                    if (autoConfirmed)
    1787                         m_bIsAutoCaptureDisabled = false;
     711                        uisession()->setAutoCaptureDisabled(false);
    1788712                    /* Otherwise, the disable flag will be reset in the next console view's foucs in event (since
    1789713                     * may happen asynchronously on some platforms, after we return from this code): */
     
    1795719                        qApp->processEvents();
    1796720#endif
    1797                         captureKbd(true);
    1798                         captureMouse(true);
     721                        /* Actually that will be a call to keyboard-handler, not no machine-view,
     722                         * but now keyboard-handler is not implemented yet. */
     723                        m_views[uScreenId]->captureKbd(true);
     724
     725                        captureMouse(uScreenId);
    1799726                    }
    1800727                }
     
    1806733}
    1807734
    1808 void UIMachineView::resizeEvent(QResizeEvent *pEvent)
    1809 {
    1810     updateSliders();
    1811     return QAbstractScrollArea::resizeEvent(pEvent);
    1812 }
    1813 
    1814 void UIMachineView::moveEvent(QMoveEvent *pEvent)
    1815 {
    1816     return QAbstractScrollArea::moveEvent(pEvent);
    1817 }
    1818 
    1819 void UIMachineView::paintEvent(QPaintEvent *pPaintEvent)
    1820 {
    1821     if (m_pauseShot.isNull())
    1822     {
    1823         /* Delegate the paint function to the VBoxFrameBuffer interface: */
    1824         if (m_pFrameBuffer)
    1825             m_pFrameBuffer->paintEvent(pPaintEvent);
    1826 #ifdef Q_WS_MAC
    1827         /* Update the dock icon if we are in the running state */
    1828         if (uisession()->isRunning())
    1829             updateDockIcon();
    1830 #endif /* Q_WS_MAC */
     735#ifdef Q_WS_WIN
     736/* This method is actually required only because under win-host
     737 * we do not really grab the mouse in case of capturing it: */
     738void UIMouseHandler::updateMouseCursorClipping()
     739{
     740    /* Check if such viewport is registered: */
     741    if (!m_viewports.contains(m_iMouseCaptureViewIndex))
    1831742        return;
    1832     }
    1833 
    1834 #ifdef VBOX_GUI_USE_QUARTZ2D
    1835     if (mode() == VBoxDefs::Quartz2DMode && m_pFrameBuffer)
    1836     {
    1837         m_pFrameBuffer->paintEvent(pPaintEvent);
    1838         updateDockIcon();
     743
     744    if (uisession()->isMouseCaptured())
     745    {
     746        QWidget *pMachineViewViewport = m_viewports[m_iMouseCaptureViewIndex];
     747        QRect r = pMachineViewViewport->rect();
     748        r.moveTopLeft(pMachineViewViewport->mapToGlobal(QPoint(0, 0)));
     749        RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
     750        ::ClipCursor(&rect);
    1839751    }
    1840752    else
    1841 #endif /* VBOX_GUI_USE_QUARTZ2D */
    1842     {
    1843         /* We have a snapshot for the paused state: */
    1844         QRect r = pPaintEvent->rect().intersect(viewport()->rect());
    1845         /* We have to disable paint on screen if we are using the regular painter: */
    1846         bool paintOnScreen = viewport()->testAttribute(Qt::WA_PaintOnScreen);
    1847         viewport()->setAttribute(Qt::WA_PaintOnScreen, false);
    1848         QPainter pnt(viewport());
    1849         pnt.drawPixmap(r.x(), r.y(), m_pauseShot, r.x() + contentsX(), r.y() + contentsY(), r.width(), r.height());
    1850         /* Restore the attribute to its previous state: */
    1851         viewport()->setAttribute(Qt::WA_PaintOnScreen, paintOnScreen);
    1852 #ifdef Q_WS_MAC
    1853         updateDockIcon();
    1854 #endif /* Q_WS_MAC */
    1855     }
    1856 }
    1857 
    1858 #if defined(Q_WS_WIN32)
    1859 
    1860 LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    1861 {
    1862     if (gView && nCode == HC_ACTION && gView->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT *)lParam))
    1863         return 1;
    1864 
    1865     return CallNextHookEx(NULL, nCode, wParam, lParam);
    1866 }
    1867 
    1868 bool UIMachineView::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event)
    1869 {
    1870     /* Sometimes it happens that Win inserts additional events on some key
    1871      * press/release. For example, it prepends ALT_GR in German layout with
    1872      * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
    1873      * to specially treat ALT_GR to enter additional chars to regular apps).
    1874      * These events are definitely unwanted in VM, so filter them out. */
    1875     /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
    1876      * code 0x23a. If this is not passed through then it is impossible to
    1877      * cancel CapsLock on a French keyboard.  I didn't find any other examples
    1878      * of these strange events.  Let's hope we are not missing anything else
    1879      * of importance! */
    1880     if (hasFocus() && (event.scanCode & ~0xFF))
    1881     {
    1882         if (event.vkCode == VK_CAPITAL)
    1883             return false;
    1884         else
    1885             return true;
    1886     }
    1887 
    1888     if (!m_bIsKeyboardCaptured)
    1889         return false;
    1890 
    1891     /* it's possible that a key has been pressed while the keyboard was not
    1892      * captured, but is being released under the capture. Detect this situation
    1893      * and return false to let Windows process the message normally and update
    1894      * its key state table (to avoid the stuck key effect). */
    1895     uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed;
    1896     if ((event.flags & 0x80) /* released */ &&
    1897         ((event.vkCode == m_globalSettings.hostKey() && !m_bIsHostkeyInCapture) ||
    1898          (m_pressedKeys[event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed))
    1899         return false;
    1900 
    1901     MSG message;
    1902     message.hwnd = winId();
    1903     message.message = msg;
    1904     message.wParam = event.vkCode;
    1905     message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24;
    1906 
    1907     /* Windows sets here the extended bit when the Right Shift key is pressed,
    1908      * which is totally wrong. Undo it. */
    1909     if (event.vkCode == VK_RSHIFT)
    1910         message.lParam &= ~0x1000000;
    1911 
    1912     /* we suppose here that this hook is always called on the main GUI thread */
    1913     long dummyResult;
    1914     return winEvent(&message, &dummyResult);
    1915 }
    1916 
    1917 bool UIMachineView::winEvent(MSG *aMsg, long* /* aResult */)
    1918 {
    1919     if (!(aMsg->message == WM_KEYDOWN || aMsg->message == WM_SYSKEYDOWN ||
    1920           aMsg->message == WM_KEYUP || aMsg->message == WM_SYSKEYUP))
    1921         return false;
    1922 
    1923     /* Check for the special flag possibly set at the end of this function */
    1924     if (aMsg->lParam & (0x1 << 25))
    1925     {
    1926         aMsg->lParam &= ~(0x1 << 25);
    1927         return false;
    1928     }
    1929 
    1930     int scan = (aMsg->lParam >> 16) & 0x7F;
    1931     /* scancodes 0x80 and 0x00 are ignored */
    1932     if (!scan)
    1933         return true;
    1934 
    1935     int vkey = aMsg->wParam;
    1936 
    1937     /* When one of the SHIFT keys is held and one of the cursor movement
    1938      * keys is pressed, Windows duplicates SHIFT press/release messages,
    1939      * but with the virtual key code set to 0xFF. These virtual keys are also
    1940      * sent in some other situations (Pause, PrtScn, etc.). Ignore such
    1941      * messages. */
    1942     if (vkey == 0xFF)
    1943         return true;
    1944 
    1945     int flags = 0;
    1946     if (aMsg->lParam & 0x1000000)
    1947         flags |= KeyExtended;
    1948     if (!(aMsg->lParam & 0x80000000))
    1949         flags |= KeyPressed;
    1950 
    1951     switch (vkey)
    1952     {
    1953         case VK_SHIFT:
    1954         case VK_CONTROL:
    1955         case VK_MENU:
    1956         {
    1957             /* overcome stupid Win32 modifier key generalization */
    1958             int keyscan = scan;
    1959             if (flags & KeyExtended)
    1960                 keyscan |= 0xE000;
    1961             switch (keyscan)
    1962             {
    1963                 case 0x002A: vkey = VK_LSHIFT; break;
    1964                 case 0x0036: vkey = VK_RSHIFT; break;
    1965                 case 0x001D: vkey = VK_LCONTROL; break;
    1966                 case 0xE01D: vkey = VK_RCONTROL; break;
    1967                 case 0x0038: vkey = VK_LMENU; break;
    1968                 case 0xE038: vkey = VK_RMENU; break;
    1969             }
    1970             break;
    1971         }
    1972         case VK_NUMLOCK:
    1973             /* Win32 sets the extended bit for the NumLock key. Reset it. */
    1974             flags &= ~KeyExtended;
    1975             break;
    1976         case VK_SNAPSHOT:
    1977             flags |= KeyPrint;
    1978             break;
    1979         case VK_PAUSE:
    1980             flags |= KeyPause;
    1981             break;
    1982     }
    1983 
    1984     bool result = keyEvent(vkey, scan, flags);
    1985     if (!result && m_bIsKeyboardCaptured)
    1986     {
    1987         /* keyEvent() returned that it didn't process the message, but since the
    1988          * keyboard is captured, we don't want to pass it to Windows. We just want
    1989          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    1990          * shortcuts for example). So send it direcltly to the window with the
    1991          * special flag in the reserved area of lParam (to avoid recursion). */
    1992         ::SendMessage(aMsg->hwnd, aMsg->message,
    1993                       aMsg->wParam, aMsg->lParam | (0x1 << 25));
    1994         return true;
    1995     }
    1996 
    1997     /* These special keys have to be handled by Windows as well to update the
    1998      * internal modifier state and to enable/disable the keyboard LED */
    1999     if (vkey == VK_NUMLOCK || vkey == VK_CAPITAL || vkey == VK_LSHIFT || vkey == VK_RSHIFT)
    2000         return false;
    2001 
    2002     return result;
    2003 }
    2004 
    2005 #elif defined(Q_WS_PM)
    2006 
    2007 bool UIMachineView::pmEvent(QMSG *aMsg)
    2008 {
    2009     if (aMsg->msg == UM_PREACCEL_CHAR)
    2010     {
    2011         /* We are inside the input hook
    2012          * let the message go through the normal system pipeline. */
    2013         if (!m_bIsKeyboardCaptured)
    2014             return false;
    2015     }
    2016 
    2017     if (aMsg->msg != WM_CHAR && aMsg->msg != UM_PREACCEL_CHAR)
    2018         return false;
    2019 
    2020     /* check for the special flag possibly set at the end of this function */
    2021     if (SHORT2FROMMP(aMsg->mp2) & 0x8000)
    2022     {
    2023         aMsg->mp2 = MPFROM2SHORT(SHORT1FROMMP(aMsg->mp2), SHORT2FROMMP(aMsg->mp2) & ~0x8000);
    2024         return false;
    2025     }
    2026 
    2027     USHORT ch = SHORT1FROMMP(aMsg->mp2);
    2028     USHORT f = SHORT1FROMMP(aMsg->mp1);
    2029 
    2030     int scan = (unsigned int)CHAR4FROMMP(aMsg->mp1);
    2031     if (!scan || scan > 0x7F)
    2032         return true;
    2033 
    2034     int vkey = QIHotKeyEdit::virtualKey(aMsg);
    2035 
    2036     int flags = 0;
    2037 
    2038     if ((ch & 0xFF) == 0xE0)
    2039     {
    2040         flags |= KeyExtended;
    2041         scan = ch >> 8;
    2042     }
    2043     else if (scan == 0x5C && (ch & 0xFF) == '/')
    2044     {
    2045         /* this is the '/' key on the keypad */
    2046         scan = 0x35;
    2047         flags |= KeyExtended;
    2048     }
    2049     else
    2050     {
    2051         /* For some keys, the scan code passed in QMSG is a pseudo scan
    2052          * code. We replace it with a real hardware scan code, according to
    2053          * http://www.computer-engineering.org/ps2keyboard/scancodes1.html.
    2054          * Also detect Pause and PrtScn and set flags. */
    2055         switch (vkey)
    2056         {
    2057             case VK_ENTER:     scan = 0x1C; flags |= KeyExtended; break;
    2058             case VK_CTRL:      scan = 0x1D; flags |= KeyExtended; break;
    2059             case VK_ALTGRAF:   scan = 0x38; flags |= KeyExtended; break;
    2060             case VK_LWIN:      scan = 0x5B; flags |= KeyExtended; break;
    2061             case VK_RWIN:      scan = 0x5C; flags |= KeyExtended; break;
    2062             case VK_WINMENU:   scan = 0x5D; flags |= KeyExtended; break;
    2063             case VK_FORWARD:   scan = 0x69; flags |= KeyExtended; break;
    2064             case VK_BACKWARD:  scan = 0x6A; flags |= KeyExtended; break;
    2065 #if 0
    2066             /// @todo this would send 0xE0 0x46 0xE0 0xC6. It's not fully
    2067             // clear what is more correct
    2068             case VK_BREAK:     scan = 0x46; flags |= KeyExtended; break;
    2069 #else
    2070             case VK_BREAK:     scan = 0;    flags |= KeyPause; break;
    2071 #endif
    2072             case VK_PAUSE:     scan = 0;    flags |= KeyPause;    break;
    2073             case VK_PRINTSCRN: scan = 0;    flags |= KeyPrint;    break;
    2074             default:;
    2075         }
    2076     }
    2077 
    2078     if (!(f & KC_KEYUP))
    2079         flags |= KeyPressed;
    2080 
    2081     bool result = keyEvent (vkey, scan, flags);
    2082     if (!result && m_bIsKeyboardCaptured)
    2083     {
    2084         /* keyEvent() returned that it didn't process the message, but since the
    2085          * keyboard is captured, we don't want to pass it to PM. We just want
    2086          * to let Qt process the message (to handle non-alphanumeric <HOST>+key
    2087          * shortcuts for example). So send it direcltly to the window with the
    2088          * special flag in the reserved area of lParam (to avoid recursion). */
    2089         ::WinSendMsg (aMsg->hwnd, WM_CHAR, aMsg->mp1,
    2090                       MPFROM2SHORT (SHORT1FROMMP (aMsg->mp2), SHORT2FROMMP (aMsg->mp2) | 0x8000));
    2091         return true;
    2092     }
    2093     return result;
    2094 }
    2095 
    2096 #elif defined(Q_WS_X11)
    2097 
    2098 static Bool VBoxConsoleViewCompEvent(Display *, XEvent *pEvent, XPointer pvArg)
    2099 {
    2100     XEvent *pKeyEvent = (XEvent*)pvArg;
    2101     if ((pEvent->type == XKeyPress) && (pEvent->xkey.keycode == pKeyEvent->xkey.keycode))
    2102         return True;
    2103     else
    2104         return False;
    2105 }
    2106 
    2107 bool UIMachineView::x11Event(XEvent *pEvent)
    2108 {
    2109     switch (pEvent->type)
    2110     {
    2111         /* We have to handle XFocusOut right here as this event is not passed
    2112          * to UIMachineView::event(). Handling this event is important for
    2113          * releasing the keyboard before the screen saver gets active.
    2114          *
    2115          * See public ticket #3894: Apparently this makes problems with newer
    2116          * versions of Qt and this hack is probably not necessary anymore.
    2117          * So disable it for Qt >= 4.5.0. */
    2118         case XFocusOut:
    2119         case XFocusIn:
    2120             if (uisession()->isRunning())
    2121             {
    2122                 if (VBoxGlobal::qtRTVersion() < ((4 << 16) | (5 << 8) | 0))
    2123                     focusEvent (pEvent->type == XFocusIn);
    2124             }
    2125             return false;
    2126         case XKeyPress:
    2127         case XKeyRelease:
    2128             break;
    2129         default:
    2130             return false; /* pass the event to Qt */
    2131     }
    2132 
    2133     /* Translate the keycode to a PC scan code. */
    2134     unsigned scan = handleXKeyEvent(pEvent);
    2135 
    2136     /* scancodes 0x00 (no valid translation) and 0x80 are ignored */
    2137     if (!scan & 0x7F)
    2138         return true;
    2139 
    2140     /* Fix for http://www.virtualbox.org/ticket/1296:
    2141      * when X11 sends events for repeated keys, it always inserts an
    2142      * XKeyRelease before the XKeyPress. */
    2143     XEvent returnEvent;
    2144     if ((pEvent->type == XKeyRelease) && (XCheckIfEvent(pEvent->xkey.display, &returnEvent,
    2145         VBoxConsoleViewCompEvent, (XPointer)pEvent) == True))
    2146     {
    2147         XPutBackEvent(pEvent->xkey.display, &returnEvent);
    2148         /* Discard it, don't pass it to Qt. */
    2149         return true;
    2150     }
    2151 
    2152     KeySym ks = ::XKeycodeToKeysym(pEvent->xkey.display, pEvent->xkey.keycode, 0);
    2153 
    2154     int flags = 0;
    2155     if (scan >> 8)
    2156         flags |= KeyExtended;
    2157     if (pEvent->type == XKeyPress)
    2158         flags |= KeyPressed;
    2159 
    2160     /* Remove the extended flag */
    2161     scan &= 0x7F;
    2162 
    2163     switch (ks)
    2164     {
    2165         case XK_Print:
    2166             flags |= KeyPrint;
    2167             break;
    2168         case XK_Pause:
    2169             flags |= KeyPause;
    2170             break;
    2171     }
    2172 
    2173     return keyEvent(ks, scan, flags);
    2174 }
    2175 
    2176 #elif defined(Q_WS_MAC)
    2177 
    2178 bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
    2179 {
    2180     bool ret = false;
    2181     UInt32 EventKind = ::GetEventKind(inEvent);
    2182     if (EventKind != kEventRawKeyModifiersChanged)
    2183     {
    2184         /* convert keycode to set 1 scan code. */
    2185         UInt32 keyCode = ~0U;
    2186         ::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
    2187         unsigned scanCode = ::DarwinKeycodeToSet1Scancode(keyCode);
    2188         if (scanCode)
    2189         {
    2190             /* calc flags. */
    2191             int flags = 0;
    2192             if (EventKind != kEventRawKeyUp)
    2193                 flags |= KeyPressed;
    2194             if (scanCode & VBOXKEY_EXTENDED)
    2195                 flags |= KeyExtended;
    2196             /** @todo KeyPause, KeyPrint. */
    2197             scanCode &= VBOXKEY_SCANCODE_MASK;
    2198 
    2199             /* get the unicode string (if present). */
    2200             AssertCompileSize(wchar_t, 2);
    2201             AssertCompileSize(UniChar, 2);
    2202             ByteCount cbWritten = 0;
    2203             wchar_t ucs[8];
    2204             if (::GetEventParameter(inEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL,
    2205                                     sizeof(ucs), &cbWritten, &ucs[0]) != 0)
    2206                 cbWritten = 0;
    2207             ucs[cbWritten / sizeof(wchar_t)] = 0; /* The api doesn't terminate it. */
    2208 
    2209             ret = keyEvent(keyCode, scanCode, flags, ucs[0] ? ucs : NULL);
    2210         }
    2211     }
    2212     else
    2213     {
    2214         /* May contain multiple modifier changes, kind of annoying. */
    2215         UInt32 newMask = 0;
    2216         ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
    2217                             sizeof(newMask), NULL, &newMask);
    2218         newMask = ::DarwinAdjustModifierMask(newMask, pvCocoaEvent);
    2219         UInt32 changed = newMask ^ m_darwinKeyModifiers;
    2220         if (changed)
    2221         {
    2222             for (UInt32 bit = 0; bit < 32; bit++)
    2223             {
    2224                 if (!(changed & (1 << bit)))
    2225                     continue;
    2226                 unsigned scanCode = ::DarwinModifierMaskToSet1Scancode(1 << bit);
    2227                 if (!scanCode)
    2228                     continue;
    2229                 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(1 << bit);
    2230                 Assert(keyCode);
    2231 
    2232                 if (!(scanCode & VBOXKEY_LOCK))
    2233                 {
    2234                     unsigned flags = (newMask & (1 << bit)) ? KeyPressed : 0;
    2235                     if (scanCode & VBOXKEY_EXTENDED)
    2236                         flags |= KeyExtended;
    2237                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2238                     ret |= keyEvent(keyCode, scanCode & 0xff, flags);
    2239                 }
    2240                 else
    2241                 {
    2242                     unsigned flags = 0;
    2243                     if (scanCode & VBOXKEY_EXTENDED)
    2244                         flags |= KeyExtended;
    2245                     scanCode &= VBOXKEY_SCANCODE_MASK;
    2246                     keyEvent(keyCode, scanCode, flags | KeyPressed);
    2247                     keyEvent(keyCode, scanCode, flags);
    2248                 }
    2249             }
    2250         }
    2251 
    2252         m_darwinKeyModifiers = newMask;
    2253 
    2254         /* Always return true here because we'll otherwise getting a Qt event
    2255            we don't want and that will only cause the Pause warning to pop up. */
    2256         ret = true;
    2257     }
    2258 
    2259     return ret;
    2260 }
    2261 
    2262 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab)
    2263 {
    2264     m_fKeyboardGrabbed = fGrab;
    2265     if (fGrab)
    2266     {
    2267         /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
    2268         ::CGSetLocalEventsSuppressionInterval(0.0);
    2269         setMouseCoalescingEnabled(false);
    2270 
    2271         /* Register the event callback/hook and grab the keyboard. */
    2272         UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
    2273                                                                 UIMachineView::darwinEventHandlerProc, this);
    2274 
    2275         ::DarwinGrabKeyboard (false);
    2276     }
    2277     else
    2278     {
    2279         ::DarwinReleaseKeyboard();
    2280         UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
    2281                                                                   UIMachineView::darwinEventHandlerProc, this);
    2282     }
    2283 }
    2284 
    2285 bool UIMachineView::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
    2286 {
    2287     UIMachineView *view = (UIMachineView*)pvUser;
    2288     EventRef inEvent = (EventRef)pvCarbonEvent;
    2289     UInt32 eventClass = ::GetEventClass(inEvent);
    2290 
    2291     /* Check if this is an application key combo. In that case we will not pass
    2292      * the event to the guest, but let the host process it. */
    2293     if (::darwinIsApplicationCommand(pvCocoaEvent))
    2294         return false;
    2295 
    2296     /* All keyboard class events needs to be handled. */
    2297     if (eventClass == kEventClassKeyboard)
    2298     {
    2299         if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
    2300             return true;
    2301     }
    2302     /* Pass the event along. */
    2303     return false;
    2304 }
    2305 
    2306 #endif
    2307 
    2308 void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount)
    2309 {
    2310     /* Synchronize the views of the host and the guest to the modifier keys.
    2311      * This function will add up to 6 additional keycodes to codes. */
    2312 
    2313 #if defined(Q_WS_X11)
    2314 
    2315     Window   wDummy1, wDummy2;
    2316     int      iDummy3, iDummy4, iDummy5, iDummy6;
    2317     unsigned uMask;
    2318     unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0;
    2319 
    2320     uKeyMaskCaps          = LockMask;
    2321     XModifierKeymap* map  = XGetModifierMapping(QX11Info::display());
    2322     KeyCode keyCodeNum    = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock);
    2323     KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock);
    2324 
    2325     for (int i = 0; i < 8; ++ i)
    2326     {
    2327         if (keyCodeNum != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeNum)
    2328             uKeyMaskNum = 1 << i;
    2329         else if (keyCodeScroll != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeScroll)
    2330             uKeyMaskScroll = 1 << i;
    2331     }
    2332     XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2,
    2333                   &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask);
    2334     XFreeModifiermap(map);
    2335 
    2336     if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(uMask & uKeyMaskNum)))
    2337     {
    2338         uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
    2339         piCodes[(*puCount)++] = 0x45;
    2340         piCodes[(*puCount)++] = 0x45 | 0x80;
    2341     }
    2342     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(uMask & uKeyMaskCaps)))
    2343     {
    2344         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    2345         piCodes[(*puCount)++] = 0x3a;
    2346         piCodes[(*puCount)++] = 0x3a | 0x80;
    2347         /* Some keyboard layouts require shift to be pressed to break
    2348          * capslock.  For simplicity, only do this if shift is not
    2349          * already held down. */
    2350         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    2351         {
    2352             piCodes[(*puCount)++] = 0x2a;
    2353             piCodes[(*puCount)++] = 0x2a | 0x80;
    2354         }
    2355     }
    2356 
    2357 #elif defined(Q_WS_WIN32)
    2358 
    2359     if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(GetKeyState(VK_NUMLOCK))))
    2360     {
    2361         uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
    2362         piCodes[(*puCount)++] = 0x45;
    2363         piCodes[(*puCount)++] = 0x45 | 0x80;
    2364     }
    2365     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(GetKeyState(VK_CAPITAL))))
    2366     {
    2367         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    2368         piCodes[(*puCount)++] = 0x3a;
    2369         piCodes[(*puCount)++] = 0x3a | 0x80;
    2370         /* Some keyboard layouts require shift to be pressed to break
    2371          * capslock.  For simplicity, only do this if shift is not
    2372          * already held down. */
    2373         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    2374         {
    2375             piCodes[(*puCount)++] = 0x2a;
    2376             piCodes[(*puCount)++] = 0x2a | 0x80;
    2377         }
    2378     }
    2379 
    2380 #elif defined(Q_WS_MAC)
    2381 
    2382     /* if (uisession()->numLockAdaptionCnt()) ... - NumLock isn't implemented by Mac OS X so ignore it. */
    2383     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
    2384     {
    2385         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    2386         piCodes[(*puCount)++] = 0x3a;
    2387         piCodes[(*puCount)++] = 0x3a | 0x80;
    2388         /* Some keyboard layouts require shift to be pressed to break
    2389          * capslock.  For simplicity, only do this if shift is not
    2390          * already held down. */
    2391         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    2392         {
    2393             piCodes[(*puCount)++] = 0x2a;
    2394             piCodes[(*puCount)++] = 0x2a | 0x80;
    2395         }
    2396     }
    2397 
    2398 #else
    2399 
    2400 //#warning Adapt UIMachineView::fixModifierState
    2401 
    2402 #endif
    2403 }
    2404 
    2405 QPoint UIMachineView::viewportToContents(const QPoint &vp) const
    2406 {
    2407     return QPoint(vp.x() + contentsX(), vp.y() + contentsY());
    2408 }
    2409 
    2410 void UIMachineView::scrollBy(int dx, int dy)
    2411 {
    2412     horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
    2413     verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
    2414 }
    2415 
    2416 #ifdef VBOX_WITH_VIDEOHWACCEL
    2417 void UIMachineView::scrollContentsBy(int dx, int dy)
    2418 {
    2419     if (m_pFrameBuffer)
    2420     {
    2421         m_pFrameBuffer->viewportScrolled(dx, dy);
    2422     }
    2423     QAbstractScrollArea::scrollContentsBy(dx, dy);
    2424 }
    2425 #endif
    2426 
    2427 void UIMachineView::emitKeyboardStateChanged()
    2428 {
    2429     emit keyboardStateChanged(keyboardState());
    2430 }
    2431 
    2432 void UIMachineView::emitMouseStateChanged()
    2433 {
    2434     emit mouseStateChanged(mouseState());
    2435 }
    2436 
    2437 void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */)
    2438 {
    2439     if (m_bIsKeyboardCaptured == fCapture)
    2440         return;
    2441 
    2442 #if defined(Q_WS_WIN32)
    2443     /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. */
    2444 #elif defined(Q_WS_X11)
    2445     /* On X11, we are using passive XGrabKey for normal (windowed) mode
    2446      * instead of XGrabKeyboard (called by QWidget::grabKeyboard())
    2447      * because XGrabKeyboard causes a problem under metacity - a window cannot be moved
    2448      * using the mouse if it is currently actively grabing the keyboard;
    2449      * For static modes we are using usual (active) keyboard grabbing. */
    2450     switch (machineLogic()->visualStateType())
    2451     {
    2452         /* If window is moveable we are making passive keyboard grab: */
    2453         case UIVisualStateType_Normal:
    2454         {
    2455             if (fCapture)
    2456                 XGrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync);
    2457             else
    2458                 XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId());
    2459             break;
    2460         }
    2461         /* If window is NOT moveable we are making active keyboard grab: */
    2462         case UIVisualStateType_Fullscreen:
    2463         case UIVisualStateType_Seamless:
    2464         {
    2465             if (fCapture)
    2466             {
    2467                 /* Keyboard grabbing can fail because of some keyboard shortcut is still grabbed by window manager.
    2468                  * We can't be sure this shortcut will be released at all, so we will retry to grab keyboard for 50 times,
    2469                  * and after we will just ignore that issue: */
    2470                 int cTriesLeft = 50;
    2471                 while (cTriesLeft && XGrabKeyboard(QX11Info::display(), machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync, CurrentTime)) { --cTriesLeft; }
    2472             }
    2473             else
    2474                 XUngrabKeyboard(QX11Info::display(), CurrentTime);
    2475             break;
    2476         }
    2477         /* Should we try to grab keyboard in default case? I think - NO. */
    2478         default:
    2479             break;
    2480     }
    2481 #elif defined(Q_WS_MAC)
    2482     /* On Mac OS X, we use the Qt methods + disabling global hot keys + watching modifiers
    2483      * (for right/left separation). */
    2484     if (fCapture)
    2485     {
    2486         ::DarwinDisableGlobalHotKeys(true);
    2487         grabKeyboard();
    2488     }
    2489     else
    2490     {
    2491         ::DarwinDisableGlobalHotKeys(false);
    2492         releaseKeyboard();
    2493     }
    2494 #else
    2495     if (fCapture)
    2496         grabKeyboard();
    2497     else
    2498         releaseKeyboard();
    2499 #endif
    2500 
    2501     m_bIsKeyboardCaptured = fCapture;
    2502 
    2503     if (fEmitSignal)
    2504         emitKeyboardStateChanged();
    2505 }
    2506 
    2507 void UIMachineView::captureMouse(bool fCapture, bool fEmitSignal /* = true */)
    2508 {
    2509     /* Do not change anything if its already so: */
    2510     if (uisession()->isMouseCaptured() == fCapture)
    2511         return;
    2512 
    2513     /* Store new mouse 'captured' state value: */
    2514     uisession()->setMouseCaptured(fCapture);
    2515 
    2516     if (fCapture)
    2517     {
    2518         /* Memorize the host position where the cursor was captured: */
    2519         m_capturedMousePos = QCursor::pos();
    2520 #ifdef Q_WS_WIN32
    2521         /* Remember what this window captured mouse: */
    2522         m_fItsMeWhoCapturedMouse = true;
    2523         /* Move the mouse to the center of the visible area: */
    2524         m_lastMousePos = mapToGlobal(visibleRegion().boundingRect().center());
    2525         QCursor::setPos(m_lastMousePos);
    2526         /* Update mouse clipping: */
    2527         updateMouseCursorClipping();
    2528 #elif defined (Q_WS_MAC)
    2529         /* Move the mouse to the center of the visible area: */
    2530         m_lastMousePos = mapToGlobal(visibleRegion().boundingRect().center());
    2531         QCursor::setPos(m_lastMousePos);
    2532         /* Grab all mouse events: */
    2533         viewport()->grabMouse();
    2534 #else
    2535         /* Grab all mouse events: */
    2536         viewport()->grabMouse();
    2537         m_lastMousePos = QCursor::pos();
    2538 #endif
    2539     }
    2540     else
    2541     {
    2542         /* Return the cursor to where it was when we captured it: */
    2543         QCursor::setPos(m_capturedMousePos);
    2544     }
    2545 
    2546     /* Updating guest mouse: */
    2547     CMouse mouse = session().GetConsole().GetMouse();
    2548     mouse.PutMouseEvent(0, 0, 0, 0, 0);
    2549 
    2550     /* Emit signal if required: */
    2551     if (fEmitSignal)
    2552         emitMouseStateChanged();
    2553 }
    2554 
    2555 void UIMachineView::saveKeyStates()
    2556 {
    2557     ::memcpy(m_pressedKeysCopy, m_pressedKeys, sizeof(m_pressedKeys));
    2558 }
    2559 
    2560 void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */)
    2561 {
    2562     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    2563     bool fSentRESEND = false;
    2564 
    2565     /* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing
    2566      * a single key click (for ex., Alt) and performing an unwanted action
    2567      * (for ex., activating the menu) when we release all pressed keys below.
    2568      * Note, that it's just a guess that sending RESEND will give the desired
    2569      * effect :), but at least it works with NT and W2k guests. */
    2570     for (uint i = 0; i < SIZEOF_ARRAY (m_pressedKeys); i++)
    2571     {
    2572         if (m_pressedKeys[i] & IsKeyPressed)
    2573         {
    2574             if (!fSentRESEND)
    2575             {
    2576                 keyboard.PutScancode (0xFE);
    2577                 fSentRESEND = true;
    2578             }
    2579             keyboard.PutScancode(i | 0x80);
    2580         }
    2581         else if (m_pressedKeys[i] & IsExtKeyPressed)
    2582         {
    2583             if (!fSentRESEND)
    2584             {
    2585                 keyboard.PutScancode(0xFE);
    2586                 fSentRESEND = true;
    2587             }
    2588             QVector <LONG> codes(2);
    2589             codes[0] = 0xE0;
    2590             codes[1] = i | 0x80;
    2591             keyboard.PutScancodes(codes);
    2592         }
    2593         m_pressedKeys[i] = 0;
    2594     }
    2595 
    2596     if (aReleaseHostKey)
    2597         m_bIsHostkeyPressed = false;
    2598 
    2599 #ifdef Q_WS_MAC
    2600     /* Clear most of the modifiers: */
    2601     m_darwinKeyModifiers &=
    2602         alphaLock | kEventKeyModifierNumLockMask |
    2603         (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey()));
    2604 #endif
    2605 
    2606     emitKeyboardStateChanged();
    2607 }
    2608 
    2609 void UIMachineView::sendChangedKeyStates()
    2610 {
    2611     QVector <LONG> codes(2);
    2612     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    2613     for (uint i = 0; i < SIZEOF_ARRAY(m_pressedKeys); ++ i)
    2614     {
    2615         uint8_t os = m_pressedKeysCopy[i];
    2616         uint8_t ns = m_pressedKeys[i];
    2617         if ((os & IsKeyPressed) != (ns & IsKeyPressed))
    2618         {
    2619             codes[0] = i;
    2620             if (!(ns & IsKeyPressed))
    2621                 codes[0] |= 0x80;
    2622             keyboard.PutScancode(codes[0]);
    2623         }
    2624         else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed))
    2625         {
    2626             codes[0] = 0xE0;
    2627             codes[1] = i;
    2628             if (!(ns & IsExtKeyPressed))
    2629                 codes[1] |= 0x80;
    2630             keyboard.PutScancodes(codes);
    2631         }
    2632     }
    2633 }
    2634 
    2635 void UIMachineView::dimImage(QImage &img)
    2636 {
    2637     for (int y = 0; y < img.height(); ++ y)
    2638     {
    2639         if (y % 2)
    2640         {
    2641             if (img.depth() == 32)
    2642             {
    2643                 for (int x = 0; x < img.width(); ++ x)
    2644                 {
    2645                     int gray = qGray(img.pixel (x, y)) / 2;
    2646                     img.setPixel(x, y, qRgb (gray, gray, gray));
    2647                 }
    2648             }
    2649             else
    2650             {
    2651                 ::memset(img.scanLine (y), 0, img.bytesPerLine());
    2652             }
    2653         }
    2654         else
    2655         {
    2656             if (img.depth() == 32)
    2657             {
    2658                 for (int x = 0; x < img.width(); ++ x)
    2659                 {
    2660                     int gray = (2 * qGray (img.pixel (x, y))) / 3;
    2661                     img.setPixel(x, y, qRgb (gray, gray, gray));
    2662                 }
    2663             }
    2664         }
    2665     }
    2666 }
    2667 
    2668 #ifdef Q_WS_MAC
    2669 CGImageRef UIMachineView::vmContentImage()
    2670 {
    2671     if (!m_pauseShot.isNull())
    2672     {
    2673         CGImageRef pauseImg = ::darwinToCGImageRef(&m_pauseShot);
    2674         /* Use the pause image as background */
    2675         return pauseImg;
    2676     }
    2677     else
    2678     {
    2679 # ifdef VBOX_GUI_USE_QUARTZ2D
    2680         if (mode() == VBoxDefs::Quartz2DMode)
    2681         {
    2682             /* If the render mode is Quartz2D we could use the CGImageRef
    2683              * of the framebuffer for the dock icon creation. This saves
    2684              * some conversion time. */
    2685             CGImageRef image = static_cast<UIFrameBufferQuartz2D*>(m_pFrameBuffer)->imageRef();
    2686             CGImageRetain(image); /* Retain it, cause the consumer will release it. */
    2687             return image;
    2688         }
    2689         else
    2690 # endif /* VBOX_GUI_USE_QUARTZ2D */
    2691             /* In image mode we have to create the image ref out of the
    2692              * framebuffer */
    2693             return frameBuffertoCGImageRef(m_pFrameBuffer);
    2694     }
    2695     return 0;
    2696 }
    2697 
    2698 CGImageRef UIMachineView::frameBuffertoCGImageRef(UIFrameBuffer *pFrameBuffer)
    2699 {
    2700     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    2701     Assert(cs);
    2702     /* Create the image copy of the framebuffer */
    2703     CGDataProviderRef dp = CGDataProviderCreateWithData(pFrameBuffer, pFrameBuffer->address(), pFrameBuffer->bitsPerPixel() / 8 * pFrameBuffer->width() * pFrameBuffer->height(), NULL);
    2704     Assert(dp);
    2705     CGImageRef ir = CGImageCreate(pFrameBuffer->width(), pFrameBuffer->height(), 8, 32, pFrameBuffer->bytesPerLine(), cs,
    2706                                   kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host, dp, 0, false,
    2707                                   kCGRenderingIntentDefault);
    2708     Assert(ir);
    2709     CGDataProviderRelease(dp);
    2710     CGColorSpaceRelease(cs);
    2711 
    2712     return ir;
    2713 }
    2714 
    2715 void UIMachineView::updateDockIcon()
    2716 {
    2717     machineLogic()->updateDockIcon();
    2718 }
    2719 
    2720 void UIMachineView::setMouseCoalescingEnabled(bool fOn)
    2721 {
    2722     /* Enable mouse event compression if we leave the VM view. This
    2723        is necessary for having smooth resizing of the VM/other
    2724        windows.
    2725        Disable mouse event compression if we enter the VM view. So
    2726        all mouse events are registered in the VM. Only do this if
    2727        the keyboard/mouse is grabbed (this is when we have a valid
    2728        event handler). */
    2729     if (fOn || m_fKeyboardGrabbed)
    2730         ::darwinSetMouseCoalescingEnabled(fOn);
    2731 }
    2732 #endif /* Q_WS_MAC */
    2733 
     753    {
     754        ::ClipCursor(NULL);
     755    }
     756}
     757#endif /* Q_WS_WIN */
     758
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h

    r30291 r30408  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * UIMachineView class declaration
     4 * UIMouseHandler class declaration
    55 */
    66
     
    1717 */
    1818
    19 #ifndef ___UIMachineView_h___
    20 #define ___UIMachineView_h___
     19#ifndef ___UIMouseHandler_h___
     20#define ___UIMouseHandler_h___
    2121
    2222/* Global includes */
    23 #include <QAbstractScrollArea>
    24 #include <QEventLoop>
     23#include <QObject>
     24#include <QPoint>
     25#include <QMap>
    2526
    2627/* Local includes */
    27 #include "COMDefs.h"
    2828#include "UIMachineDefs.h"
    2929
    30 #ifdef Q_WS_MAC
    31 # include <CoreFoundation/CFBase.h>
    32 #endif /* Q_WS_MAC */
     30/* Global forwards */
     31class QWidget;
    3332
    3433/* Local forwards */
     34class CSession;
    3535class UISession;
    36 class UIFrameBuffer;
    37 class UIMachineWindow;
    3836class UIMachineLogic;
    39 class VBoxGlobalSettings;
     37class UIMachineView;
    4038
    41 class UIMachineView : public QAbstractScrollArea
     39/* Delegate to control VM mouse functionality: */
     40class UIMouseHandler : public QObject
    4241{
    4342    Q_OBJECT;
     
    4544public:
    4645
    47     /* Desktop geometry types: */
    48     enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
     46    /* Factory functions to create/destroy mouse-handler: */
     47    static UIMouseHandler* create(UIMachineLogic *pMachineLogic, UIVisualStateType visualStateType);
     48    static void destroy(UIMouseHandler *pMouseHandler);
    4949
    50     /* Factory function to create required view sub-child: */
    51     static UIMachineView* create(  UIMachineWindow *pMachineWindow
    52                                  , VBoxDefs::RenderMode renderMode
    53 #ifdef VBOX_WITH_VIDEOHWACCEL
    54                                  , bool bAccelerate2DVideo
    55 #endif
    56                                  , UIVisualStateType visualStateType
    57                                  , ulong uScreenId);
    58     static void destroy(UIMachineView *pWhichView);
     50    /* Registers/Remove new machine-view: */
     51    void addMachineView(ulong uViewIndex, UIMachineView *pMachineView);
     52    void delMachineView(ulong uViewIndex);
    5953
    60     /* Public getters: */
    61     int keyboardState() const;
     54    /* Commands to capture/release mouse: */
     55    void captureMouse(ulong uScreenId);
     56    void releaseMouse();
     57
     58    /* Setter for mouse-integration feature: */
     59    void setMouseIntegrationEnabled(bool fEnabled);
     60
     61    /* Current mouse state: */
    6262    int mouseState() const;
    63     virtual QRegion lastVisibleRegion() const { return QRegion(); }
    64 
    65     /* Public setters: */
    66     virtual void setGuestAutoresizeEnabled(bool /* fEnabled */) {}
    67     virtual void setMouseIntegrationEnabled(bool fEnabled);
    68 
    69     /* Public members: */
    70     virtual void normalizeGeometry(bool /* bAdjustPosition = false */) = 0;
    7163
    7264signals:
    7365
    74     /* Mouse/Keyboard state-change signals: */
    75     void keyboardStateChanged(int iState);
    76     void mouseStateChanged(int iState);
     66    /* Notifies listeners about mouse state-change: */
     67    void mouseStateChanged(int iNewState);
    7768
    78     /* Utility signals: */
    79     void resizeHintDone();
     69protected slots:
     70
     71    /* Machine state-change handler: */
     72    virtual void sltMachineStateChanged();
     73
     74    /* Mouse capability-change handler: */
     75    virtual void sltMouseCapabilityChanged();
     76
     77    /* Mouse pointer-shape-change handler: */
     78    virtual void sltMousePointerShapeChanged();
    8079
    8180protected:
    8281
    83     /* Machine view constructor/destructor: */
    84     UIMachineView(  UIMachineWindow *pMachineWindow
    85                   , VBoxDefs::RenderMode renderMode
    86 #ifdef VBOX_WITH_VIDEOHWACCEL
    87                   , bool bAccelerate2DVideo
    88 #endif
    89                   , ulong uScreenId);
    90     virtual ~UIMachineView();
     82    /* Mouse-handler constructor/destructor: */
     83    UIMouseHandler(UIMachineLogic *pMachineLogic);
     84    virtual ~UIMouseHandler();
    9185
    92     /* Protected getters: */
     86    /* Getters: */
     87    UIMachineLogic* machineLogic() const;
    9388    UISession* uisession() const;
    94     CSession& session();
    95     QSize sizeHint() const;
    96     int contentsX() const;
    97     int contentsY() const;
    98     int contentsWidth() const;
    99     int contentsHeight() const;
    100     int visibleWidth() const;
    101     int visibleHeight() const;
    102     VBoxDefs::RenderMode mode() const { return m_mode; }
    103     ulong screenId() const { return m_uScreenId; }
    104     UIFrameBuffer* frameBuffer() const { return m_pFrameBuffer; }
    105     UIMachineWindow* machineWindowWrapper() const { return m_pMachineWindow; }
    106     UIMachineLogic* machineLogic() const;
    107     bool isHostKeyPressed() const { return m_bIsHostkeyPressed; }
    108     bool isMachineWindowResizeIgnored() const { return m_bIsMachineWindowResizeIgnored; }
    109     const QPixmap& pauseShot() const { return m_pauseShot; }
    110     QSize storedConsoleSize() const { return m_storedConsoleSize; }
    111     DesktopGeo desktopGeometryType() const { return m_desktopGeometryType; }
    112     QSize desktopGeometry() const;
    113     QSize guestSizeHint();
     89    CSession& session() const;
    11490
    115     /* Protected setters: */
    116     void setDesktopGeometry(DesktopGeo geometry, int iWidth, int iHeight);
    117     void storeConsoleSize(int iWidth, int iHeight);
    118     void setMachineWindowResizeIgnored(bool fIgnore = true) { m_bIsMachineWindowResizeIgnored = fIgnore; }
    119     void storeGuestSizeHint(const QSize &sizeHint);
    120 
    121     /* Protected helpers: */
    122     void updateMouseCursorShape();
    123 #ifdef Q_WS_WIN32
    124     void updateMouseCursorClipping();
    125 #endif
    126     virtual QRect workingArea() = 0;
    127     virtual void calculateDesktopGeometry() = 0;
    128     virtual void maybeRestrictMinimumSize() = 0;
    129     virtual void updateSliders();
    130 
    131 #ifdef Q_WS_MAC
    132     void updateDockIcon();
    133     void setMouseCoalescingEnabled(bool fOn);
    134     CGImageRef vmContentImage();
    135     CGImageRef frameBuffertoCGImageRef(UIFrameBuffer *pFrameBuffer);
    136 #endif /* Q_WS_MAC */
    137 
    138     /* Prepare routines: */
    139     virtual void prepareFrameBuffer();
    140     virtual void prepareCommon();
    141     virtual void prepareFilters();
    142     virtual void prepareConsoleConnections();
    143     virtual void loadMachineViewSettings();
    144 
    145     /* Cleanup routines: */
    146     //virtual void saveMachineViewSettings() {}
    147     //virtual void cleanupConsoleConnections() {}
    148     //virtual void cleanupFilters() {}
    149     virtual void cleanupCommon();
    150     virtual void cleanupFrameBuffer();
    151 
    152     /* Cross-platforms event processors: */
    153     bool event(QEvent *pEvent);
     91    /* Event handler for registered machine-view(s): */
    15492    bool eventFilter(QObject *pWatched, QEvent *pEvent);
    15593
    156     /* Protected variables: */
    157     QSize m_desktopGeometry;
     94    /* Separate function to handle most of existing mouse-events: */
     95    bool mouseEvent(int iEventType, ulong uScreenId,
     96                    const QPoint &relativePos, const QPoint &globalPos,
     97                    Qt::MouseButtons mouseButtons,
     98                    int wheelDelta, Qt::Orientation wheelDirection);
    15899
    159 protected slots:
     100#ifdef Q_WS_WIN
     101    /* This method is actually required only because under win-host
     102     * we do not really grab the mouse in case of capturing it: */
     103    void updateMouseCursorClipping();
     104#endif /* Q_WS_WIN */
    160105
    161     /* Console callback handlers: */
    162     virtual void sltMachineStateChanged();
    163     virtual void sltMousePointerShapeChanged();
    164     virtual void sltMouseCapabilityChanged();
    165     virtual void sltPerformGuestResize(const QSize & /* toSize */) {};
     106    /* Machine logic parent: */
     107    UIMachineLogic *m_pMachineLogic;
    166108
    167     /* Session callback handlers: */
    168     virtual void sltMouseCapturedStatusChanged();
     109    /* Registered machine-view(s): */
     110    QMap<ulong, UIMachineView*> m_views;
     111    /* Registered machine-view-viewport(s): */
     112    QMap<ulong, QWidget*> m_viewports;
    169113
    170     /* Various helper slots: */
    171     virtual void sltNormalizeGeometry() { normalizeGeometry(true); }
    172 
    173 private:
    174 
    175     /* Cross-platforms event processors: */
    176     void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
    177     bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
    178     bool mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    179                     Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
    180                     int aWheelDelta, Qt::Orientation aWheelDir);
    181     void resizeEvent(QResizeEvent *pEvent);
    182     void moveEvent(QMoveEvent *pEvent);
    183     void paintEvent(QPaintEvent *pEvent);
    184 
    185     /* Platform specific event processors: */
    186 #if defined(Q_WS_WIN32)
    187     static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    188     bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event);
    189     bool winEvent(MSG *aMsg, long *aResult);
    190 #elif defined(Q_WS_PM)
    191     bool pmEvent(QMSG *aMsg);
    192 #elif defined(Q_WS_X11)
    193     bool x11Event(XEvent *event);
    194 #elif defined(Q_WS_MAC)
    195     bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent);
    196     void darwinGrabKeyboardEvents(bool fGrab);
    197     static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser);
    198 #endif
    199 
    200     /* Private helpers: */
    201     void fixModifierState(LONG *piCodes, uint *puCount);
    202     QPoint viewportToContents(const QPoint &vp) const;
    203     void scrollBy(int dx, int dy);
    204 #ifdef VBOX_WITH_VIDEOHWACCEL
    205     void scrollContentsBy(int dx, int dy);
    206 #endif
    207     void emitKeyboardStateChanged();
    208     void emitMouseStateChanged();
    209     void captureKbd(bool fCapture, bool fEmitSignal = true);
    210     void captureMouse(bool fCapture, bool fEmitSignal = true);
    211     void saveKeyStates();
    212     void releaseAllPressedKeys(bool aReleaseHostKey = true);
    213     void sendChangedKeyStates();
    214 
    215     static void dimImage(QImage &img);
    216 
    217     /* Private members: */
    218     UIMachineWindow *m_pMachineWindow;
    219     VBoxDefs::RenderMode m_mode;
    220     ulong m_uScreenId;
    221     const VBoxGlobalSettings &m_globalSettings;
    222     UIFrameBuffer *m_pFrameBuffer;
    223     KMachineState m_previousState;
    224 
    225     DesktopGeo m_desktopGeometryType;
    226     QSize m_storedConsoleSize;
    227 
     114    /* Other mouse variables: */
    228115    QPoint m_lastMousePos;
    229116    QPoint m_capturedMousePos;
    230117    int m_iLastMouseWheelDelta;
    231 
    232     uint8_t m_pressedKeys[128];
    233     uint8_t m_pressedKeysCopy[128];
    234 
    235     bool m_bIsAutoCaptureDisabled : 1;
    236     bool m_bIsKeyboardCaptured : 1;
    237     bool m_bIsHostkeyPressed : 1;
    238     bool m_bIsHostkeyAlone : 1;
    239     bool m_bIsHostkeyInCapture : 1;
    240     bool m_bIsMachineWindowResizeIgnored : 1;
    241     bool m_fPassCAD : 1;
    242 #ifdef VBOX_WITH_VIDEOHWACCEL
    243     bool m_fAccelerate2DVideo;
    244 #endif
    245 
    246 #ifdef Q_WS_WIN
    247     bool m_fItsMeWhoCapturedMouse;
    248 #endif /* Q_WS_WIN */
    249 #ifdef Q_WS_MAC
    250     /** The current modifier key mask. Used to figure out which modifier
    251      *  key was pressed when we get a kEventRawKeyModifiersChanged event. */
    252     UInt32 m_darwinKeyModifiers;
    253     bool m_fKeyboardGrabbed;
    254 #endif /* Q_WS_MAC */
    255 
    256     QPixmap m_pauseShot;
    257 
    258     /* Friend classes: */
    259     friend class UIMachineLogic;
    260     friend class UIFrameBuffer;
    261     friend class UIFrameBufferQImage;
    262     friend class UIFrameBufferQuartz2D;
    263     friend class UIFrameBufferQGL;
    264     template<class, class, class> friend class VBoxOverlayFrameBuffer;
     118    int m_iMouseCaptureViewIndex;
    265119};
    266120
    267 /* This maintenance class is a part of future roll-back mechanism.
    268  * It allows to block main GUI thread until specific event received.
    269  * Later it will become more abstract but now its just used to help
    270  * fullscreen & seamless modes to restore normal guest size hint. */
    271 class UIMachineViewBlocker : public QEventLoop
    272 {
    273     Q_OBJECT;
     121#endif // !___UIMouseHandler_h___
    274122
    275 public:
    276 
    277     UIMachineViewBlocker()
    278         : QEventLoop(0)
    279         , m_iTimerId(0)
    280     {
    281         /* Also start timer to unlock pool in case of
    282          * required condition doesn't happens by some reason: */
    283         m_iTimerId = startTimer(3000);
    284     }
    285 
    286     virtual ~UIMachineViewBlocker()
    287     {
    288         /* Kill the timer: */
    289         killTimer(m_iTimerId);
    290     }
    291 
    292 protected:
    293 
    294     void timerEvent(QTimerEvent *pEvent)
    295     {
    296         /* If that timer event occurs => it seems
    297          * guest resize event doesn't comes in time,
    298          * shame on it, but we just unlocking 'this': */
    299         QEventLoop::timerEvent(pEvent);
    300         exit();
    301     }
    302 
    303     int m_iTimerId;
    304 };
    305 
    306 #endif // !___UIMachineView_h___
    307 
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h

    r30348 r30408  
    138138
    139139    /* Mouse setters: */
    140     void setMouseCaptured(bool fIsMouseCaptured) { m_fIsMouseCaptured = fIsMouseCaptured; emit sigMouseCapturedStatusChanged(); }
     140    void setMouseCaptured(bool fIsMouseCaptured) { m_fIsMouseCaptured = fIsMouseCaptured; }
    141141    void setMouseIntegrated(bool fIsMouseIntegrated) { m_fIsMouseIntegrated = fIsMouseIntegrated; }
    142142
     
    176176    /* Session signals: */
    177177    void sigMachineStarted();
    178     void sigMouseCapturedStatusChanged();
    179178
    180179public slots:
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp

    r30407 r30408  
    2727
    2828#include "UIActionsPool.h"
     29#include "UIMouseHandler.h"
    2930#include "UIMachineLogicFullscreen.h"
    3031#include "UIMachineWindow.h"
     
    194195    m_pScreenLayout->update();
    195196
     197    /* Create mouse-handler: */
     198    UIMouseHandler *pMouseHandler = UIMouseHandler::create(this, visualStateType());
     199    setMouseHandler(pMouseHandler);
     200
    196201    /* Create machine window(s): */
    197202    for (int cScreenId = 0; cScreenId < m_pScreenLayout->guestScreenCount(); ++cScreenId)
     
    225230    foreach (UIMachineWindow *pMachineWindow, machineWindows())
    226231        UIMachineWindow::destroy(pMachineWindow);
     232
     233    /* Cleanup mouse-handler: */
     234    UIMouseHandler::destroy(mouseHandler());
    227235
    228236#ifdef Q_WS_MAC
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineViewFullscreen.cpp

    r30347 r30408  
    7474    /* Initialization: */
    7575    sltMachineStateChanged();
    76     sltMousePointerShapeChanged();
    77     sltMouseCapabilityChanged();
    7876}
    7977
     
    188186#endif /* Q_WS_MAC */
    189187
    190             /* Update mouse cursor shape: */
    191             updateMouseCursorShape();
    192 
    193188            /* May be we have to restrict minimum size? */
    194189            maybeRestrictMinimumSize();
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp

    r30407 r30408  
    2727
    2828#include "UIActionsPool.h"
     29#include "UIMouseHandler.h"
    2930#include "UIDownloaderAdditions.h"
    3031#include "UIMachineLogicNormal.h"
     
    142143#endif /* Q_WS_MAC */
    143144
     145    /* Create mouse-handler: */
     146    UIMouseHandler *pMouseHandler = UIMouseHandler::create(this, visualStateType());
     147    setMouseHandler(pMouseHandler);
     148
    144149    /* Get monitors count: */
    145150    ulong uMonitorCount = session().GetMachine().GetMonitorCount();
     
    164169    foreach (UIMachineWindow *pMachineWindow, machineWindows())
    165170        UIMachineWindow::destroy(pMachineWindow);
     171
     172    /* Cleanup mouse-handler: */
     173    UIMouseHandler::destroy(mouseHandler());
    166174}
    167175
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp

    r30347 r30408  
    6969    sltMachineStateChanged();
    7070    sltAdditionsStateChanged();
    71     sltMousePointerShapeChanged();
    72     sltMouseCapabilityChanged();
    7371}
    7472
     
    176174            machineLogic()->updateDockIconSize(screenId(), pResizeEvent->width(), pResizeEvent->height());
    177175#endif /* Q_WS_MAC */
    178 
    179             /* Update mouse cursor shape: */
    180             updateMouseCursorShape();
    181176
    182177            /* May be we have to restrict minimum size? */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp

    r30347 r30408  
    3030
    3131#include "UIActionsPool.h"
     32#include "UIMouseHandler.h"
    3233#include "UIDownloaderAdditions.h"
    3334#include "UIDownloaderUserManual.h"
     
    489490
    490491        /* Mouse state-change updater: */
    491         connect(machineView(), SIGNAL(mouseStateChanged(int)), indicatorsPool()->indicator(UIIndicatorIndex_Mouse), SLOT(setState(int)));
     492        connect(machineLogic()->mouseHandler(), SIGNAL(mouseStateChanged(int)), indicatorsPool()->indicator(UIIndicatorIndex_Mouse), SLOT(setState(int)));
    492493
    493494        /* Early initialize required connections: */
    494495        indicatorsPool()->indicator(UIIndicatorIndex_Hostkey)->setState(machineView()->keyboardState());
    495         indicatorsPool()->indicator(UIIndicatorIndex_Mouse)->setState(machineView()->mouseState());
     496        indicatorsPool()->indicator(UIIndicatorIndex_Mouse)->setState(machineLogic()->mouseHandler()->mouseState());
    496497    }
    497498}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp

    r30407 r30408  
    2727
    2828#include "UIActionsPool.h"
     29#include "UIMouseHandler.h"
    2930#include "UIMachineLogicSeamless.h"
    3031#include "UIMachineWindow.h"
     
    184185    m_pScreenLayout->update();
    185186
     187    /* Create machine mouse-handler: */
     188    UIMouseHandler *pMouseHandler = UIMouseHandler::create(this, visualStateType());
     189    setMouseHandler(pMouseHandler);
     190
    186191    /* Create machine window(s): */
    187192    for (int cScreenId = 0; cScreenId < m_pScreenLayout->guestScreenCount(); ++cScreenId)
     
    206211    foreach (UIMachineWindow *pMachineWindow, machineWindows())
    207212        UIMachineWindow::destroy(pMachineWindow);
     213
     214    /* Cleanup mouse-handler: */
     215    UIMouseHandler::destroy(mouseHandler());
    208216}
    209217
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineViewSeamless.cpp

    r30347 r30408  
    7676    sltMachineStateChanged();
    7777    sltAdditionsStateChanged();
    78     sltMousePointerShapeChanged();
    79     sltMouseCapabilityChanged();
    8078}
    8179
     
    199197#endif /* Q_WS_MAC */
    200198
    201             /* Update mouse cursor shape: */
    202             updateMouseCursorShape();
    203 
    204199            /* Update machine-view sliders: */
    205200            updateSliders();
Note: See TracChangeset for help on using the changeset viewer.

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