VirtualBox

Changeset 30549 in vbox


Ignore:
Timestamp:
Jul 1, 2010 1:01:39 AM (15 years ago)
Author:
vboxsync
Message:

FE/Qt: New running VM core: UIMachineView full methods rearrangement.

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

Legend:

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

    r30544 r30549  
    4949#ifdef Q_WS_PM
    5050# include "QIHotKeyEdit.h"
    51 #endif /* defined (Q_WS_PM) */
     51#endif /* Q_WS_PM */
    5252
    5353#ifdef Q_WS_WIN
     
    5959static UIMachineView *gView = 0;
    6060static HHOOK gKbdHook = 0;
    61 #endif /* defined (Q_WS_WIN) */
     61#endif /* Q_WS_WIN */
    6262
    6363#ifdef Q_WS_X11
     
    7878# endif
    7979# include "XKeyboard.h"
    80 #endif /* defined (Q_WS_X11) */
     80#endif /* Q_WS_X11 */
    8181
    8282#ifdef Q_WS_MAC
     
    115115#ifdef VBOX_WITH_VIDEOHWACCEL
    116116                                     , bool bAccelerate2DVideo
    117 #endif
     117#endif /* VBOX_WITH_VIDEOHWACCEL */
    118118                                     )
    119119{
     
    126126#ifdef VBOX_WITH_VIDEOHWACCEL
    127127                                           , bAccelerate2DVideo
    128 #endif
     128#endif /* VBOX_WITH_VIDEOHWACCEL */
    129129                                           );
    130130            break;
     
    134134#ifdef VBOX_WITH_VIDEOHWACCEL
    135135                                               , bAccelerate2DVideo
    136 #endif
     136#endif /* VBOX_WITH_VIDEOHWACCEL */
    137137                                               );
    138138            break;
     
    142142#ifdef VBOX_WITH_VIDEOHWACCEL
    143143                                             , bAccelerate2DVideo
    144 #endif
     144#endif /* VBOX_WITH_VIDEOHWACCEL */
    145145                                             );
    146146            break;
     
    160160    return (m_bIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) |
    161161           (m_bIsHostkeyPressed ? UIViewStateType_HostKeyPressed : 0);
     162}
     163
     164void UIMachineView::sltMachineStateChanged()
     165{
     166    /* Get machine state: */
     167    KMachineState state = uisession()->machineState();
     168    switch (state)
     169    {
     170        case KMachineState_Paused:
     171        case KMachineState_TeleportingPausedVM:
     172        {
     173            if (vboxGlobal().vmRenderMode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
     174                (state != KMachineState_TeleportingPausedVM || m_previousState != KMachineState_Teleporting))
     175            {
     176                /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
     177                QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
     178                /* If TakeScreenShot fails or returns no image, just show a black image. */
     179                shot.fill(0);
     180                CDisplay dsp = session().GetConsole().GetDisplay();
     181                dsp.TakeScreenShot(screenId(), shot.bits(), shot.width(), shot.height());
     182                /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
     183                 * after the machine execution was resumed. It's not fatal: */
     184                if (dsp.isOk())
     185                {
     186                    dimImage(shot);
     187                }
     188                m_pauseShot = QPixmap::fromImage(shot);
     189                /* Fully repaint to pick up m_pauseShot: */
     190                viewport()->repaint();
     191            }
     192            /* Reuse the focus event handler to uncapture keyboard: */
     193            if (hasFocus())
     194                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     195            break;
     196        }
     197        case KMachineState_Stuck:
     198        {
     199            /* Reuse the focus event handler to uncapture keyboard: */
     200            if (hasFocus())
     201                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     202            break;
     203        }
     204        case KMachineState_Running:
     205        {
     206            if (   m_previousState == KMachineState_Paused
     207                || m_previousState == KMachineState_TeleportingPausedVM
     208                || m_previousState == KMachineState_Restoring)
     209            {
     210                if (vboxGlobal().vmRenderMode() != VBoxDefs::TimerMode && m_pFrameBuffer)
     211                {
     212                    /* Reset the pixmap to free memory: */
     213                    m_pauseShot = QPixmap();
     214                    /* Ask for full guest display update (it will also update
     215                     * the viewport through IFramebuffer::NotifyUpdate): */
     216                    CDisplay dsp = session().GetConsole().GetDisplay();
     217                    dsp.InvalidateAndUpdate();
     218                }
     219            }
     220            /* Reuse the focus event handler to capture keyboard: */
     221            if (hasFocus())
     222                focusEvent(true /* aHasFocus */);
     223            break;
     224        }
     225        default:
     226            break;
     227    }
     228
     229    m_previousState = state;
    162230}
    163231
     
    166234#ifdef VBOX_WITH_VIDEOHWACCEL
    167235                             , bool bAccelerate2DVideo
    168 #endif
     236#endif /* VBOX_WITH_VIDEOHWACCEL */
    169237                             )
    170238    : QAbstractScrollArea(pMachineWindow->machineWindow())
     
    195263}
    196264
    197 UISession* UIMachineView::uisession() const
    198 {
    199     return machineLogic()->uisession();
    200 }
    201 
    202 CSession& UIMachineView::session()
    203 {
    204     return uisession()->session();
    205 }
    206 
    207 QSize UIMachineView::sizeHint() const
    208 {
    209 #ifdef VBOX_WITH_DEBUGGER
    210     // TODO: Fix all DEBUGGER stuff!
    211     /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done by DevVGA if provoked before power on. */
    212     QSize fb(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    213     if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled()))
    214         fb = QSize(640, 480);
    215     return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2);
    216 #else
    217     return QSize(m_pFrameBuffer->width() + frameWidth() * 2, m_pFrameBuffer->height() + frameWidth() * 2);
    218 #endif
    219 }
    220 
    221 int UIMachineView::contentsX() const
    222 {
    223     return horizontalScrollBar()->value();
    224 }
    225 
    226 int UIMachineView::contentsY() const
    227 {
    228     return verticalScrollBar()->value();
    229 }
    230 
    231 int UIMachineView::contentsWidth() const
    232 {
    233     return m_pFrameBuffer->width();
    234 }
    235 
    236 int UIMachineView::contentsHeight() const
    237 {
    238     return m_pFrameBuffer->height();
    239 }
    240 
    241 int UIMachineView::visibleWidth() const
    242 {
    243     return horizontalScrollBar()->pageStep();
    244 }
    245 
    246 int UIMachineView::visibleHeight() const
    247 {
    248     return verticalScrollBar()->pageStep();
    249 }
    250 
    251 UIMachineLogic* UIMachineView::machineLogic() const
    252 {
    253     return machineWindowWrapper()->machineLogic();
    254 }
    255 
    256 QSize UIMachineView::desktopGeometry() const
    257 {
    258     QSize geometry;
    259     switch (m_desktopGeometryType)
    260     {
    261         case DesktopGeo_Fixed:
    262         case DesktopGeo_Automatic:
    263             geometry = QSize(qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
    264                              qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
    265             break;
    266         case DesktopGeo_Any:
    267             geometry = QSize(0, 0);
    268             break;
    269         default:
    270             AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
    271     }
    272     return geometry;
    273 }
    274 
    275 QSize UIMachineView::guestSizeHint()
    276 {
    277     /* Result: */
    278     QSize sizeHint;
    279 
    280     /* Get current machine: */
    281     CMachine machine = session().GetMachine();
    282 
    283     /* Load machine view hint: */
    284     QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
    285                      QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
    286     QString strValue = machine.GetExtraData(strKey);
    287 
    288     bool ok = true;
    289     int width = 0, height = 0;
    290     if (ok)
    291         width = strValue.section(',', 0, 0).toInt(&ok);
    292     if (ok)
    293         height = strValue.section(',', 1, 1).toInt(&ok);
    294 
    295     if (ok /* If previous parameters were read correctly! */)
    296     {
    297         /* Compose guest size hint from loaded values: */
    298         sizeHint = QSize(width, height);
    299     }
    300     else
    301     {
    302         /* Compose guest size hint from default attributes: */
    303         sizeHint = QSize(800, 600);
    304     }
    305 
    306     /* Return result: */
    307     return sizeHint;
    308 }
    309 
    310 void UIMachineView::setDesktopGeometry(DesktopGeo geometry, int aWidth, int aHeight)
    311 {
    312     switch (geometry)
    313     {
    314         case DesktopGeo_Fixed:
    315             m_desktopGeometryType = DesktopGeo_Fixed;
    316             if (aWidth != 0 && aHeight != 0)
    317                 m_desktopGeometry = QSize(aWidth, aHeight);
    318             else
    319                 m_desktopGeometry = QSize(0, 0);
    320             storeConsoleSize(0, 0);
    321             break;
    322         case DesktopGeo_Automatic:
    323             m_desktopGeometryType = DesktopGeo_Automatic;
    324             m_desktopGeometry = QSize(0, 0);
    325             storeConsoleSize(0, 0);
    326             break;
    327         case DesktopGeo_Any:
    328             m_desktopGeometryType = DesktopGeo_Any;
    329             m_desktopGeometry = QSize(0, 0);
    330             break;
    331         default:
    332             AssertMsgFailed(("Invalid desktop geometry type %d\n", geometry));
    333             m_desktopGeometryType = DesktopGeo_Invalid;
    334     }
    335 }
    336 
    337 void UIMachineView::storeConsoleSize(int iWidth, int iHeight)
    338 {
    339     m_storedConsoleSize = QSize(iWidth, iHeight);
    340 }
    341 
    342 void UIMachineView::storeGuestSizeHint(const QSize &sizeHint)
    343 {
    344     /* Get current machine: */
    345     CMachine machine = session().GetMachine();
    346 
    347     /* Save machine view hint: */
    348     QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
    349                      QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
    350     QString strValue = QString("%1,%2").arg(sizeHint.width()).arg(sizeHint.height());
    351     machine.SetExtraData(strKey, strValue);
    352 }
    353 
    354 void UIMachineView::updateSliders()
    355 {
    356     QSize p = viewport()->size();
    357     QSize m = maximumViewportSize();
    358 
    359     QSize v = QSize(frameBuffer()->width(), frameBuffer()->height());
    360     /* No scroll bars needed: */
    361     if (m.expandedTo(v) == m)
    362         p = m;
    363 
    364     horizontalScrollBar()->setRange(0, v.width() - p.width());
    365     verticalScrollBar()->setRange(0, v.height() - p.height());
    366     horizontalScrollBar()->setPageStep(p.width());
    367     verticalScrollBar()->setPageStep(p.height());
    368 }
    369 
    370265void UIMachineView::prepareFrameBuffer()
    371266{
     
    381276            pViewport = new VBoxViewport(this);
    382277    }
    383 #else
     278#else /* VBOX_GUI_USE_QGLFB */
    384279    VBoxViewport *pViewport = new VBoxViewport(this);
    385 #endif
     280#endif /* !VBOX_GUI_USE_QGLFB */
    386281    setViewport(pViewport);
    387282
     
    411306            else
    412307                m_pFrameBuffer = new UIFrameBufferQImage(this);
    413 # else
     308# else /* VBOX_WITH_VIDEOHWACCEL */
    414309            m_pFrameBuffer = new UIFrameBufferQImage(this);
    415 # endif
     310# endif /* !VBOX_WITH_VIDEOHWACCEL */
    416311            break;
    417312#endif /* VBOX_GUI_USE_QIMAGE */
     
    432327            /* This is somehow necessary to prevent strange X11 warnings on i386 and segfaults on x86_64: */
    433328            XFlush(QX11Info::display());
    434 # endif
     329# endif /* Q_WS_X11 */
    435330# if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
    436331            if (m_fAccelerate2DVideo)
     
    493388            else
    494389                m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
    495 # else
     390# else /* VBOX_WITH_VIDEOHWACCEL */
    496391            m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
    497 # endif
     392# endif /* !VBOX_WITH_VIDEOHWACCEL */
    498393            break;
    499394#endif /* VBOX_GUI_USE_QUARTZ2D */
     
    517412        }
    518413        if (fb.raw() != m_pFrameBuffer) /* <-this will evaluate to true iff m_fAccelerate2DVideo is disabled or iff no framebuffer is yet assigned */
    519 #endif
     414#endif /* VBOX_WITH_VIDEOHWACCEL */
    520415        {
    521416            m_pFrameBuffer->AddRef();
     
    558453    Assert(ok);
    559454    NOREF(ok);
    560 #endif
     455#endif /* Q_WS_PM */
    561456}
    562457
     
    587482        /* Initialize the X keyboard subsystem: */
    588483        initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
    589 #endif
     484#endif /* Q_WS_X11 */
    590485
    591486        /* Remember the desktop geometry and register for geometry
     
    651546        }
    652547        else
    653 #endif
     548#endif /* VBOX_WITH_VIDEOHWACCEL */
    654549        {
    655550            /* Warn framebuffer about its no more necessary: */
     
    666561}
    667562
     563UIMachineLogic* UIMachineView::machineLogic() const
     564{
     565    return machineWindowWrapper()->machineLogic();
     566}
     567
     568UISession* UIMachineView::uisession() const
     569{
     570    return machineLogic()->uisession();
     571}
     572
     573CSession& UIMachineView::session()
     574{
     575    return uisession()->session();
     576}
     577
     578QSize UIMachineView::sizeHint() const
     579{
     580#ifdef VBOX_WITH_DEBUGGER
     581    // TODO: Fix all DEBUGGER stuff!
     582    /* HACK ALERT! Really ugly workaround for the resizing to 9x1 done by DevVGA if provoked before power on. */
     583    QSize fb(m_pFrameBuffer->width(), m_pFrameBuffer->height());
     584    if ((fb.width() < 16 || fb.height() < 16) && (vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled()))
     585        fb = QSize(640, 480);
     586    return QSize(fb.width() + frameWidth() * 2, fb.height() + frameWidth() * 2);
     587#else /* VBOX_WITH_DEBUGGER */
     588    return QSize(m_pFrameBuffer->width() + frameWidth() * 2, m_pFrameBuffer->height() + frameWidth() * 2);
     589#endif /* !VBOX_WITH_DEBUGGER */
     590}
     591
     592int UIMachineView::contentsX() const
     593{
     594    return horizontalScrollBar()->value();
     595}
     596
     597int UIMachineView::contentsY() const
     598{
     599    return verticalScrollBar()->value();
     600}
     601
     602int UIMachineView::contentsWidth() const
     603{
     604    return m_pFrameBuffer->width();
     605}
     606
     607int UIMachineView::contentsHeight() const
     608{
     609    return m_pFrameBuffer->height();
     610}
     611
     612int UIMachineView::visibleWidth() const
     613{
     614    return horizontalScrollBar()->pageStep();
     615}
     616
     617int UIMachineView::visibleHeight() const
     618{
     619    return verticalScrollBar()->pageStep();
     620}
     621
     622QSize UIMachineView::desktopGeometry() const
     623{
     624    QSize geometry;
     625    switch (m_desktopGeometryType)
     626    {
     627        case DesktopGeo_Fixed:
     628        case DesktopGeo_Automatic:
     629            geometry = QSize(qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
     630                             qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
     631            break;
     632        case DesktopGeo_Any:
     633            geometry = QSize(0, 0);
     634            break;
     635        default:
     636            AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
     637    }
     638    return geometry;
     639}
     640
     641QSize UIMachineView::guestSizeHint()
     642{
     643    /* Result: */
     644    QSize sizeHint;
     645
     646    /* Get current machine: */
     647    CMachine machine = session().GetMachine();
     648
     649    /* Load machine view hint: */
     650    QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
     651                     QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
     652    QString strValue = machine.GetExtraData(strKey);
     653
     654    bool ok = true;
     655    int width = 0, height = 0;
     656    if (ok)
     657        width = strValue.section(',', 0, 0).toInt(&ok);
     658    if (ok)
     659        height = strValue.section(',', 1, 1).toInt(&ok);
     660
     661    if (ok /* If previous parameters were read correctly! */)
     662    {
     663        /* Compose guest size hint from loaded values: */
     664        sizeHint = QSize(width, height);
     665    }
     666    else
     667    {
     668        /* Compose guest size hint from default attributes: */
     669        sizeHint = QSize(800, 600);
     670    }
     671
     672    /* Return result: */
     673    return sizeHint;
     674}
     675
     676void UIMachineView::setDesktopGeometry(DesktopGeo geometry, int aWidth, int aHeight)
     677{
     678    switch (geometry)
     679    {
     680        case DesktopGeo_Fixed:
     681            m_desktopGeometryType = DesktopGeo_Fixed;
     682            if (aWidth != 0 && aHeight != 0)
     683                m_desktopGeometry = QSize(aWidth, aHeight);
     684            else
     685                m_desktopGeometry = QSize(0, 0);
     686            storeConsoleSize(0, 0);
     687            break;
     688        case DesktopGeo_Automatic:
     689            m_desktopGeometryType = DesktopGeo_Automatic;
     690            m_desktopGeometry = QSize(0, 0);
     691            storeConsoleSize(0, 0);
     692            break;
     693        case DesktopGeo_Any:
     694            m_desktopGeometryType = DesktopGeo_Any;
     695            m_desktopGeometry = QSize(0, 0);
     696            break;
     697        default:
     698            AssertMsgFailed(("Invalid desktop geometry type %d\n", geometry));
     699            m_desktopGeometryType = DesktopGeo_Invalid;
     700    }
     701}
     702
     703void UIMachineView::storeConsoleSize(int iWidth, int iHeight)
     704{
     705    m_storedConsoleSize = QSize(iWidth, iHeight);
     706}
     707
     708void UIMachineView::storeGuestSizeHint(const QSize &sizeHint)
     709{
     710    /* Get current machine: */
     711    CMachine machine = session().GetMachine();
     712
     713    /* Save machine view hint: */
     714    QString strKey = m_uScreenId == 0 ? QString("%1").arg(VBoxDefs::GUI_LastGuestSizeHint) :
     715                     QString("%1%2").arg(VBoxDefs::GUI_LastGuestSizeHint).arg(m_uScreenId);
     716    QString strValue = QString("%1,%2").arg(sizeHint.width()).arg(sizeHint.height());
     717    machine.SetExtraData(strKey, strValue);
     718}
     719
     720void UIMachineView::updateSliders()
     721{
     722    QSize p = viewport()->size();
     723    QSize m = maximumViewportSize();
     724
     725    QSize v = QSize(frameBuffer()->width(), frameBuffer()->height());
     726    /* No scroll bars needed: */
     727    if (m.expandedTo(v) == m)
     728        p = m;
     729
     730    horizontalScrollBar()->setRange(0, v.width() - p.width());
     731    verticalScrollBar()->setRange(0, v.height() - p.height());
     732    horizontalScrollBar()->setPageStep(p.width());
     733    verticalScrollBar()->setPageStep(p.height());
     734}
     735
     736void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount)
     737{
     738    /* Synchronize the views of the host and the guest to the modifier keys.
     739     * This function will add up to 6 additional keycodes to codes. */
     740
     741#if defined(Q_WS_X11)
     742
     743    Window   wDummy1, wDummy2;
     744    int      iDummy3, iDummy4, iDummy5, iDummy6;
     745    unsigned uMask;
     746    unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0;
     747
     748    uKeyMaskCaps          = LockMask;
     749    XModifierKeymap* map  = XGetModifierMapping(QX11Info::display());
     750    KeyCode keyCodeNum    = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock);
     751    KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock);
     752
     753    for (int i = 0; i < 8; ++ i)
     754    {
     755        if (keyCodeNum != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeNum)
     756            uKeyMaskNum = 1 << i;
     757        else if (keyCodeScroll != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeScroll)
     758            uKeyMaskScroll = 1 << i;
     759    }
     760    XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2,
     761                  &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask);
     762    XFreeModifiermap(map);
     763
     764    if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(uMask & uKeyMaskNum)))
     765    {
     766        uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
     767        piCodes[(*puCount)++] = 0x45;
     768        piCodes[(*puCount)++] = 0x45 | 0x80;
     769    }
     770    if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(uMask & uKeyMaskCaps)))
     771    {
     772        uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
     773        piCodes[(*puCount)++] = 0x3a;
     774        piCodes[(*puCount)++] = 0x3a | 0x80;
     775        /* Some keyboard layouts require shift to be pressed to break
     776         * capslock.  For simplicity, only do this if shift is not
     777         * already held down. */
     778        if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
     779        {
     780            piCodes[(*puCount)++] = 0x2a;
     781            piCodes[(*puCount)++] = 0x2a | 0x80;
     782        }
     783    }
     784
     785#elif defined(Q_WS_WIN)
     786
     787    if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(GetKeyState(VK_NUMLOCK))))
     788    {
     789        uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
     790        piCodes[(*puCount)++] = 0x45;
     791        piCodes[(*puCount)++] = 0x45 | 0x80;
     792    }
     793    if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(GetKeyState(VK_CAPITAL))))
     794    {
     795        uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
     796        piCodes[(*puCount)++] = 0x3a;
     797        piCodes[(*puCount)++] = 0x3a | 0x80;
     798        /* Some keyboard layouts require shift to be pressed to break
     799         * capslock.  For simplicity, only do this if shift is not
     800         * already held down. */
     801        if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
     802        {
     803            piCodes[(*puCount)++] = 0x2a;
     804            piCodes[(*puCount)++] = 0x2a | 0x80;
     805        }
     806    }
     807
     808#elif defined(Q_WS_MAC)
     809
     810    /* if (uisession()->numLockAdaptionCnt()) ... - NumLock isn't implemented by Mac OS X so ignore it. */
     811    if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
     812    {
     813        uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
     814        piCodes[(*puCount)++] = 0x3a;
     815        piCodes[(*puCount)++] = 0x3a | 0x80;
     816        /* Some keyboard layouts require shift to be pressed to break
     817         * capslock.  For simplicity, only do this if shift is not
     818         * already held down. */
     819        if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
     820        {
     821            piCodes[(*puCount)++] = 0x2a;
     822            piCodes[(*puCount)++] = 0x2a | 0x80;
     823        }
     824    }
     825
     826#else
     827
     828//#warning Adapt UIMachineView::fixModifierState
     829
     830#endif
     831}
     832
     833QPoint UIMachineView::viewportToContents(const QPoint &vp) const
     834{
     835    return QPoint(vp.x() + contentsX(), vp.y() + contentsY());
     836}
     837
     838void UIMachineView::scrollBy(int dx, int dy)
     839{
     840    horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
     841    verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
     842}
     843
     844void UIMachineView::emitKeyboardStateChanged()
     845{
     846    emit keyboardStateChanged(keyboardState());
     847}
     848
     849void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */)
     850{
     851    if (m_bIsKeyboardCaptured == fCapture)
     852        return;
     853
     854#if defined(Q_WS_WIN)
     855    /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. */
     856#elif defined(Q_WS_X11)
     857    /* On X11, we are using passive XGrabKey for normal (windowed) mode
     858     * instead of XGrabKeyboard (called by QWidget::grabKeyboard())
     859     * because XGrabKeyboard causes a problem under metacity - a window cannot be moved
     860     * using the mouse if it is currently actively grabing the keyboard;
     861     * For static modes we are using usual (active) keyboard grabbing. */
     862    switch (machineLogic()->visualStateType())
     863    {
     864        /* If window is moveable we are making passive keyboard grab: */
     865        case UIVisualStateType_Normal:
     866        {
     867            if (fCapture)
     868                XGrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync);
     869            else
     870                XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId());
     871            break;
     872        }
     873        /* If window is NOT moveable we are making active keyboard grab: */
     874        case UIVisualStateType_Fullscreen:
     875        case UIVisualStateType_Seamless:
     876        {
     877            if (fCapture)
     878            {
     879                /* Keyboard grabbing can fail because of some keyboard shortcut is still grabbed by window manager.
     880                 * We can't be sure this shortcut will be released at all, so we will retry to grab keyboard for 50 times,
     881                 * and after we will just ignore that issue: */
     882                int cTriesLeft = 50;
     883                while (cTriesLeft && XGrabKeyboard(QX11Info::display(), machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync, CurrentTime)) { --cTriesLeft; }
     884            }
     885            else
     886                XUngrabKeyboard(QX11Info::display(), CurrentTime);
     887            break;
     888        }
     889        /* Should we try to grab keyboard in default case? I think - NO. */
     890        default:
     891            break;
     892    }
     893#elif defined(Q_WS_MAC)
     894    /* On Mac OS X, we use the Qt methods + disabling global hot keys + watching modifiers
     895     * (for right/left separation). */
     896    if (fCapture)
     897    {
     898        ::DarwinDisableGlobalHotKeys(true);
     899        grabKeyboard();
     900    }
     901    else
     902    {
     903        ::DarwinDisableGlobalHotKeys(false);
     904        releaseKeyboard();
     905    }
     906#else
     907    if (fCapture)
     908        grabKeyboard();
     909    else
     910        releaseKeyboard();
     911#endif
     912
     913    m_bIsKeyboardCaptured = fCapture;
     914
     915    if (fEmitSignal)
     916        emitKeyboardStateChanged();
     917}
     918
     919void UIMachineView::saveKeyStates()
     920{
     921    ::memcpy(m_pressedKeysCopy, m_pressedKeys, sizeof(m_pressedKeys));
     922}
     923
     924void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */)
     925{
     926    CKeyboard keyboard = session().GetConsole().GetKeyboard();
     927    bool fSentRESEND = false;
     928
     929    /* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing
     930     * a single key click (for ex., Alt) and performing an unwanted action
     931     * (for ex., activating the menu) when we release all pressed keys below.
     932     * Note, that it's just a guess that sending RESEND will give the desired
     933     * effect :), but at least it works with NT and W2k guests. */
     934    for (uint i = 0; i < SIZEOF_ARRAY (m_pressedKeys); i++)
     935    {
     936        if (m_pressedKeys[i] & IsKeyPressed)
     937        {
     938            if (!fSentRESEND)
     939            {
     940                keyboard.PutScancode (0xFE);
     941                fSentRESEND = true;
     942            }
     943            keyboard.PutScancode(i | 0x80);
     944        }
     945        else if (m_pressedKeys[i] & IsExtKeyPressed)
     946        {
     947            if (!fSentRESEND)
     948            {
     949                keyboard.PutScancode(0xFE);
     950                fSentRESEND = true;
     951            }
     952            QVector <LONG> codes(2);
     953            codes[0] = 0xE0;
     954            codes[1] = i | 0x80;
     955            keyboard.PutScancodes(codes);
     956        }
     957        m_pressedKeys[i] = 0;
     958    }
     959
     960    if (aReleaseHostKey)
     961        m_bIsHostkeyPressed = false;
     962
     963#ifdef Q_WS_MAC
     964    /* Clear most of the modifiers: */
     965    m_darwinKeyModifiers &=
     966        alphaLock | kEventKeyModifierNumLockMask |
     967        (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey()));
     968#endif /* Q_WS_MAC */
     969
     970    emitKeyboardStateChanged();
     971}
     972
     973void UIMachineView::sendChangedKeyStates()
     974{
     975    QVector <LONG> codes(2);
     976    CKeyboard keyboard = session().GetConsole().GetKeyboard();
     977    for (uint i = 0; i < SIZEOF_ARRAY(m_pressedKeys); ++ i)
     978    {
     979        uint8_t os = m_pressedKeysCopy[i];
     980        uint8_t ns = m_pressedKeys[i];
     981        if ((os & IsKeyPressed) != (ns & IsKeyPressed))
     982        {
     983            codes[0] = i;
     984            if (!(ns & IsKeyPressed))
     985                codes[0] |= 0x80;
     986            keyboard.PutScancode(codes[0]);
     987        }
     988        else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed))
     989        {
     990            codes[0] = 0xE0;
     991            codes[1] = i;
     992            if (!(ns & IsExtKeyPressed))
     993                codes[1] |= 0x80;
     994            keyboard.PutScancodes(codes);
     995        }
     996    }
     997}
     998
     999void UIMachineView::dimImage(QImage &img)
     1000{
     1001    for (int y = 0; y < img.height(); ++ y)
     1002    {
     1003        if (y % 2)
     1004        {
     1005            if (img.depth() == 32)
     1006            {
     1007                for (int x = 0; x < img.width(); ++ x)
     1008                {
     1009                    int gray = qGray(img.pixel (x, y)) / 2;
     1010                    img.setPixel(x, y, qRgb (gray, gray, gray));
     1011                }
     1012            }
     1013            else
     1014            {
     1015                ::memset(img.scanLine (y), 0, img.bytesPerLine());
     1016            }
     1017        }
     1018        else
     1019        {
     1020            if (img.depth() == 32)
     1021            {
     1022                for (int x = 0; x < img.width(); ++ x)
     1023                {
     1024                    int gray = (2 * qGray (img.pixel (x, y))) / 3;
     1025                    img.setPixel(x, y, qRgb (gray, gray, gray));
     1026                }
     1027            }
     1028        }
     1029    }
     1030}
     1031
     1032#ifdef VBOX_WITH_VIDEOHWACCEL
     1033void UIMachineView::scrollContentsBy(int dx, int dy)
     1034{
     1035    if (m_pFrameBuffer)
     1036    {
     1037        m_pFrameBuffer->viewportScrolled(dx, dy);
     1038    }
     1039    QAbstractScrollArea::scrollContentsBy(dx, dy);
     1040}
     1041#endif /* VBOX_WITH_VIDEOHWACCEL */
     1042
     1043#ifdef Q_WS_MAC
     1044void UIMachineView::updateDockIcon()
     1045{
     1046    machineLogic()->updateDockIcon();
     1047}
     1048
     1049CGImageRef UIMachineView::vmContentImage()
     1050{
     1051    if (!m_pauseShot.isNull())
     1052    {
     1053        CGImageRef pauseImg = ::darwinToCGImageRef(&m_pauseShot);
     1054        /* Use the pause image as background */
     1055        return pauseImg;
     1056    }
     1057    else
     1058    {
     1059# ifdef VBOX_GUI_USE_QUARTZ2D
     1060        if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode)
     1061        {
     1062            /* If the render mode is Quartz2D we could use the CGImageRef
     1063             * of the framebuffer for the dock icon creation. This saves
     1064             * some conversion time. */
     1065            CGImageRef image = static_cast<UIFrameBufferQuartz2D*>(m_pFrameBuffer)->imageRef();
     1066            CGImageRetain(image); /* Retain it, cause the consumer will release it. */
     1067            return image;
     1068        }
     1069        else
     1070# endif /* VBOX_GUI_USE_QUARTZ2D */
     1071            /* In image mode we have to create the image ref out of the
     1072             * framebuffer */
     1073            return frameBuffertoCGImageRef(m_pFrameBuffer);
     1074    }
     1075    return 0;
     1076}
     1077
     1078CGImageRef UIMachineView::frameBuffertoCGImageRef(UIFrameBuffer *pFrameBuffer)
     1079{
     1080    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
     1081    Assert(cs);
     1082    /* Create the image copy of the framebuffer */
     1083    CGDataProviderRef dp = CGDataProviderCreateWithData(pFrameBuffer, pFrameBuffer->address(), pFrameBuffer->bitsPerPixel() / 8 * pFrameBuffer->width() * pFrameBuffer->height(), NULL);
     1084    Assert(dp);
     1085    CGImageRef ir = CGImageCreate(pFrameBuffer->width(), pFrameBuffer->height(), 8, 32, pFrameBuffer->bytesPerLine(), cs,
     1086                                  kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host, dp, 0, false,
     1087                                  kCGRenderingIntentDefault);
     1088    Assert(ir);
     1089    CGDataProviderRelease(dp);
     1090    CGColorSpaceRelease(cs);
     1091
     1092    return ir;
     1093}
     1094#endif /* Q_WS_MAC */
     1095
    6681096bool UIMachineView::event(QEvent *pEvent)
    6691097{
     
    7061134            return true;
    7071135        }
    708 #endif
     1136#endif /* VBOX_WITH_VIDEOHWACCEL */
    7091137
    7101138        case QEvent::KeyPress:
     
    8491277            return true;
    8501278        }
    851 #endif
     1279#endif /* Q_WS_MAC */
    8521280
    8531281        default:
     
    9361364}
    9371365
    938 void UIMachineView::sltMachineStateChanged()
    939 {
    940     /* Get machine state: */
    941     KMachineState state = uisession()->machineState();
    942     switch (state)
    943     {
    944         case KMachineState_Paused:
    945         case KMachineState_TeleportingPausedVM:
    946         {
    947             if (vboxGlobal().vmRenderMode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
    948                 (state != KMachineState_TeleportingPausedVM || m_previousState != KMachineState_Teleporting))
    949             {
    950                 /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
    951                 QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
    952                 /* If TakeScreenShot fails or returns no image, just show a black image. */
    953                 shot.fill(0);
    954                 CDisplay dsp = session().GetConsole().GetDisplay();
    955                 dsp.TakeScreenShot(screenId(), shot.bits(), shot.width(), shot.height());
    956                 /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
    957                  * after the machine execution was resumed. It's not fatal: */
    958                 if (dsp.isOk())
    959                 {
    960                     dimImage(shot);
    961                 }
    962                 m_pauseShot = QPixmap::fromImage(shot);
    963                 /* Fully repaint to pick up m_pauseShot: */
    964                 viewport()->repaint();
    965             }
    966             /* Reuse the focus event handler to uncapture keyboard: */
    967             if (hasFocus())
    968                 focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
    969             break;
    970         }
    971         case KMachineState_Stuck:
    972         {
    973             /* Reuse the focus event handler to uncapture keyboard: */
    974             if (hasFocus())
    975                 focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
    976             break;
    977         }
    978         case KMachineState_Running:
    979         {
    980             if (   m_previousState == KMachineState_Paused
    981                 || m_previousState == KMachineState_TeleportingPausedVM
    982                 || m_previousState == KMachineState_Restoring)
    983             {
    984                 if (vboxGlobal().vmRenderMode() != VBoxDefs::TimerMode && m_pFrameBuffer)
    985                 {
    986                     /* Reset the pixmap to free memory: */
    987                     m_pauseShot = QPixmap();
    988                     /* Ask for full guest display update (it will also update
    989                      * the viewport through IFramebuffer::NotifyUpdate): */
    990                     CDisplay dsp = session().GetConsole().GetDisplay();
    991                     dsp.InvalidateAndUpdate();
    992                 }
    993             }
    994             /* Reuse the focus event handler to capture keyboard: */
    995             if (hasFocus())
    996                 focusEvent(true /* aHasFocus */);
    997             break;
    998         }
    999         default:
    1000             break;
    1001     }
    1002 
    1003     m_previousState = state;
    1004 }
    1005 
    10061366void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */)
    10071367{
    10081368    if (fHasFocus)
    10091369    {
    1010 #ifdef Q_WS_WIN32
     1370#ifdef Q_WS_WIN
    10111371        if (!uisession()->isAutoCaptureDisabled() && m_globalSettings.autoCapture() && GetAncestor(winId(), GA_ROOT) == GetForegroundWindow())
    1012 #else
     1372#else /* Q_WS_WIN */
    10131373        if (!uisession()->isAutoCaptureDisabled() && m_globalSettings.autoCapture())
    1014 #endif
     1374#endif /* !Q_WS_WIN */
    10151375        {
    10161376            captureKbd(true);
     
    12111571                                 * mouse is immediately ungrabbed. */
    12121572                                qApp->processEvents();
    1213 #endif
     1573#endif /* Q_WS_X11 */
    12141574                                if (m_bIsKeyboardCaptured)
    12151575                                    machineLogic()->mouseHandler()->captureMouse(screenId());
     
    12441604    {
    12451605        bool processed = false;
    1246 #if defined (Q_WS_WIN32)
     1606#if defined (Q_WS_WIN)
    12471607        NOREF(pUniKey);
    12481608        int n = GetKeyboardLayoutList(0, NULL);
     
    13001660    Assert(!keyboard.isNull());
    13011661
    1302 #if defined (Q_WS_WIN32)
     1662#ifdef Q_WS_WIN
    13031663    /* send pending WM_PAINT events */
    13041664    ::UpdateWindow(viewport()->winId());
    1305 #endif
     1665#endif /* Q_WS_WIN */
    13061666
    13071667    std::vector <LONG> scancodes(codes, &codes[count]);
     
    13621722}
    13631723
    1364 #if defined(Q_WS_WIN32)
     1724#if defined(Q_WS_WIN)
    13651725
    13661726LRESULT CALLBACK UIMachineView::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
     
    16862046#elif defined(Q_WS_MAC)
    16872047
     2048void UIMachineView::darwinGrabKeyboardEvents(bool fGrab)
     2049{
     2050    m_fKeyboardGrabbed = fGrab;
     2051    if (fGrab)
     2052    {
     2053        /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
     2054        ::CGSetLocalEventsSuppressionInterval(0.0);
     2055        machineLogic()->mouseHandler()->setMouseCoalescingEnabled(false);
     2056
     2057        /* Register the event callback/hook and grab the keyboard. */
     2058        UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
     2059                                                                UIMachineView::darwinEventHandlerProc, this);
     2060
     2061        ::DarwinGrabKeyboard (false);
     2062    }
     2063    else
     2064    {
     2065        ::DarwinReleaseKeyboard();
     2066        UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
     2067                                                                  UIMachineView::darwinEventHandlerProc, this);
     2068    }
     2069}
     2070
     2071bool UIMachineView::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
     2072{
     2073    UIMachineView *view = (UIMachineView*)pvUser;
     2074    EventRef inEvent = (EventRef)pvCarbonEvent;
     2075    UInt32 eventClass = ::GetEventClass(inEvent);
     2076
     2077    /* Check if this is an application key combo. In that case we will not pass
     2078     * the event to the guest, but let the host process it. */
     2079    if (::darwinIsApplicationCommand(pvCocoaEvent))
     2080        return false;
     2081
     2082    /* All keyboard class events needs to be handled. */
     2083    if (eventClass == kEventClassKeyboard)
     2084    {
     2085        if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
     2086            return true;
     2087    }
     2088    /* Pass the event along. */
     2089    return false;
     2090}
     2091
    16882092bool UIMachineView::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
    16892093{
     
    17702174}
    17712175
    1772 void UIMachineView::darwinGrabKeyboardEvents(bool fGrab)
    1773 {
    1774     m_fKeyboardGrabbed = fGrab;
    1775     if (fGrab)
    1776     {
    1777         /* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
    1778         ::CGSetLocalEventsSuppressionInterval(0.0);
    1779         machineLogic()->mouseHandler()->setMouseCoalescingEnabled(false);
    1780 
    1781         /* Register the event callback/hook and grab the keyboard. */
    1782         UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
    1783                                                                 UIMachineView::darwinEventHandlerProc, this);
    1784 
    1785         ::DarwinGrabKeyboard (false);
    1786     }
    1787     else
    1788     {
    1789         ::DarwinReleaseKeyboard();
    1790         UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */,
    1791                                                                   UIMachineView::darwinEventHandlerProc, this);
    1792     }
    1793 }
    1794 
    1795 bool UIMachineView::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
    1796 {
    1797     UIMachineView *view = (UIMachineView*)pvUser;
    1798     EventRef inEvent = (EventRef)pvCarbonEvent;
    1799     UInt32 eventClass = ::GetEventClass(inEvent);
    1800 
    1801     /* Check if this is an application key combo. In that case we will not pass
    1802      * the event to the guest, but let the host process it. */
    1803     if (::darwinIsApplicationCommand(pvCocoaEvent))
    1804         return false;
    1805 
    1806     /* All keyboard class events needs to be handled. */
    1807     if (eventClass == kEventClassKeyboard)
    1808     {
    1809         if (view->darwinKeyboardEvent (pvCocoaEvent, inEvent))
    1810             return true;
    1811     }
    1812     /* Pass the event along. */
    1813     return false;
    1814 }
    1815 
    18162176#endif
    18172177
    1818 void UIMachineView::fixModifierState(LONG *piCodes, uint *puCount)
    1819 {
    1820     /* Synchronize the views of the host and the guest to the modifier keys.
    1821      * This function will add up to 6 additional keycodes to codes. */
    1822 
    1823 #if defined(Q_WS_X11)
    1824 
    1825     Window   wDummy1, wDummy2;
    1826     int      iDummy3, iDummy4, iDummy5, iDummy6;
    1827     unsigned uMask;
    1828     unsigned uKeyMaskNum = 0, uKeyMaskCaps = 0, uKeyMaskScroll = 0;
    1829 
    1830     uKeyMaskCaps          = LockMask;
    1831     XModifierKeymap* map  = XGetModifierMapping(QX11Info::display());
    1832     KeyCode keyCodeNum    = XKeysymToKeycode(QX11Info::display(), XK_Num_Lock);
    1833     KeyCode keyCodeScroll = XKeysymToKeycode(QX11Info::display(), XK_Scroll_Lock);
    1834 
    1835     for (int i = 0; i < 8; ++ i)
    1836     {
    1837         if (keyCodeNum != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeNum)
    1838             uKeyMaskNum = 1 << i;
    1839         else if (keyCodeScroll != NoSymbol && map->modifiermap[map->max_keypermod * i] == keyCodeScroll)
    1840             uKeyMaskScroll = 1 << i;
    1841     }
    1842     XQueryPointer(QX11Info::display(), DefaultRootWindow(QX11Info::display()), &wDummy1, &wDummy2,
    1843                   &iDummy3, &iDummy4, &iDummy5, &iDummy6, &uMask);
    1844     XFreeModifiermap(map);
    1845 
    1846     if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(uMask & uKeyMaskNum)))
    1847     {
    1848         uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
    1849         piCodes[(*puCount)++] = 0x45;
    1850         piCodes[(*puCount)++] = 0x45 | 0x80;
    1851     }
    1852     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(uMask & uKeyMaskCaps)))
    1853     {
    1854         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    1855         piCodes[(*puCount)++] = 0x3a;
    1856         piCodes[(*puCount)++] = 0x3a | 0x80;
    1857         /* Some keyboard layouts require shift to be pressed to break
    1858          * capslock.  For simplicity, only do this if shift is not
    1859          * already held down. */
    1860         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    1861         {
    1862             piCodes[(*puCount)++] = 0x2a;
    1863             piCodes[(*puCount)++] = 0x2a | 0x80;
    1864         }
    1865     }
    1866 
    1867 #elif defined(Q_WS_WIN32)
    1868 
    1869     if (uisession()->numLockAdaptionCnt() && (uisession()->isNumLock() ^ !!(GetKeyState(VK_NUMLOCK))))
    1870     {
    1871         uisession()->setNumLockAdaptionCnt(uisession()->numLockAdaptionCnt() - 1);
    1872         piCodes[(*puCount)++] = 0x45;
    1873         piCodes[(*puCount)++] = 0x45 | 0x80;
    1874     }
    1875     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(GetKeyState(VK_CAPITAL))))
    1876     {
    1877         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    1878         piCodes[(*puCount)++] = 0x3a;
    1879         piCodes[(*puCount)++] = 0x3a | 0x80;
    1880         /* Some keyboard layouts require shift to be pressed to break
    1881          * capslock.  For simplicity, only do this if shift is not
    1882          * already held down. */
    1883         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    1884         {
    1885             piCodes[(*puCount)++] = 0x2a;
    1886             piCodes[(*puCount)++] = 0x2a | 0x80;
    1887         }
    1888     }
    1889 
    1890 #elif defined(Q_WS_MAC)
    1891 
    1892     /* if (uisession()->numLockAdaptionCnt()) ... - NumLock isn't implemented by Mac OS X so ignore it. */
    1893     if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
    1894     {
    1895         uisession()->setCapsLockAdaptionCnt(uisession()->capsLockAdaptionCnt() - 1);
    1896         piCodes[(*puCount)++] = 0x3a;
    1897         piCodes[(*puCount)++] = 0x3a | 0x80;
    1898         /* Some keyboard layouts require shift to be pressed to break
    1899          * capslock.  For simplicity, only do this if shift is not
    1900          * already held down. */
    1901         if (uisession()->isCapsLock() && !(m_pressedKeys[0x2a] & IsKeyPressed))
    1902         {
    1903             piCodes[(*puCount)++] = 0x2a;
    1904             piCodes[(*puCount)++] = 0x2a | 0x80;
    1905         }
    1906     }
    1907 
    1908 #else
    1909 
    1910 //#warning Adapt UIMachineView::fixModifierState
    1911 
    1912 #endif
    1913 }
    1914 
    1915 QPoint UIMachineView::viewportToContents(const QPoint &vp) const
    1916 {
    1917     return QPoint(vp.x() + contentsX(), vp.y() + contentsY());
    1918 }
    1919 
    1920 void UIMachineView::scrollBy(int dx, int dy)
    1921 {
    1922     horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
    1923     verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
    1924 }
    1925 
    1926 #ifdef VBOX_WITH_VIDEOHWACCEL
    1927 void UIMachineView::scrollContentsBy(int dx, int dy)
    1928 {
    1929     if (m_pFrameBuffer)
    1930     {
    1931         m_pFrameBuffer->viewportScrolled(dx, dy);
    1932     }
    1933     QAbstractScrollArea::scrollContentsBy(dx, dy);
    1934 }
    1935 #endif
    1936 
    1937 void UIMachineView::emitKeyboardStateChanged()
    1938 {
    1939     emit keyboardStateChanged(keyboardState());
    1940 }
    1941 
    1942 void UIMachineView::captureKbd(bool fCapture, bool fEmitSignal /* = true */)
    1943 {
    1944     if (m_bIsKeyboardCaptured == fCapture)
    1945         return;
    1946 
    1947 #if defined(Q_WS_WIN32)
    1948     /* On Win32, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. */
    1949 #elif defined(Q_WS_X11)
    1950     /* On X11, we are using passive XGrabKey for normal (windowed) mode
    1951      * instead of XGrabKeyboard (called by QWidget::grabKeyboard())
    1952      * because XGrabKeyboard causes a problem under metacity - a window cannot be moved
    1953      * using the mouse if it is currently actively grabing the keyboard;
    1954      * For static modes we are using usual (active) keyboard grabbing. */
    1955     switch (machineLogic()->visualStateType())
    1956     {
    1957         /* If window is moveable we are making passive keyboard grab: */
    1958         case UIVisualStateType_Normal:
    1959         {
    1960             if (fCapture)
    1961                 XGrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync);
    1962             else
    1963                 XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, machineWindowWrapper()->machineWindow()->winId());
    1964             break;
    1965         }
    1966         /* If window is NOT moveable we are making active keyboard grab: */
    1967         case UIVisualStateType_Fullscreen:
    1968         case UIVisualStateType_Seamless:
    1969         {
    1970             if (fCapture)
    1971             {
    1972                 /* Keyboard grabbing can fail because of some keyboard shortcut is still grabbed by window manager.
    1973                  * We can't be sure this shortcut will be released at all, so we will retry to grab keyboard for 50 times,
    1974                  * and after we will just ignore that issue: */
    1975                 int cTriesLeft = 50;
    1976                 while (cTriesLeft && XGrabKeyboard(QX11Info::display(), machineWindowWrapper()->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync, CurrentTime)) { --cTriesLeft; }
    1977             }
    1978             else
    1979                 XUngrabKeyboard(QX11Info::display(), CurrentTime);
    1980             break;
    1981         }
    1982         /* Should we try to grab keyboard in default case? I think - NO. */
    1983         default:
    1984             break;
    1985     }
    1986 #elif defined(Q_WS_MAC)
    1987     /* On Mac OS X, we use the Qt methods + disabling global hot keys + watching modifiers
    1988      * (for right/left separation). */
    1989     if (fCapture)
    1990     {
    1991         ::DarwinDisableGlobalHotKeys(true);
    1992         grabKeyboard();
    1993     }
    1994     else
    1995     {
    1996         ::DarwinDisableGlobalHotKeys(false);
    1997         releaseKeyboard();
    1998     }
    1999 #else
    2000     if (fCapture)
    2001         grabKeyboard();
    2002     else
    2003         releaseKeyboard();
    2004 #endif
    2005 
    2006     m_bIsKeyboardCaptured = fCapture;
    2007 
    2008     if (fEmitSignal)
    2009         emitKeyboardStateChanged();
    2010 }
    2011 
    2012 void UIMachineView::saveKeyStates()
    2013 {
    2014     ::memcpy(m_pressedKeysCopy, m_pressedKeys, sizeof(m_pressedKeys));
    2015 }
    2016 
    2017 void UIMachineView::releaseAllPressedKeys(bool aReleaseHostKey /* = true */)
    2018 {
    2019     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    2020     bool fSentRESEND = false;
    2021 
    2022     /* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing
    2023      * a single key click (for ex., Alt) and performing an unwanted action
    2024      * (for ex., activating the menu) when we release all pressed keys below.
    2025      * Note, that it's just a guess that sending RESEND will give the desired
    2026      * effect :), but at least it works with NT and W2k guests. */
    2027     for (uint i = 0; i < SIZEOF_ARRAY (m_pressedKeys); i++)
    2028     {
    2029         if (m_pressedKeys[i] & IsKeyPressed)
    2030         {
    2031             if (!fSentRESEND)
    2032             {
    2033                 keyboard.PutScancode (0xFE);
    2034                 fSentRESEND = true;
    2035             }
    2036             keyboard.PutScancode(i | 0x80);
    2037         }
    2038         else if (m_pressedKeys[i] & IsExtKeyPressed)
    2039         {
    2040             if (!fSentRESEND)
    2041             {
    2042                 keyboard.PutScancode(0xFE);
    2043                 fSentRESEND = true;
    2044             }
    2045             QVector <LONG> codes(2);
    2046             codes[0] = 0xE0;
    2047             codes[1] = i | 0x80;
    2048             keyboard.PutScancodes(codes);
    2049         }
    2050         m_pressedKeys[i] = 0;
    2051     }
    2052 
    2053     if (aReleaseHostKey)
    2054         m_bIsHostkeyPressed = false;
    2055 
    2056 #ifdef Q_WS_MAC
    2057     /* Clear most of the modifiers: */
    2058     m_darwinKeyModifiers &=
    2059         alphaLock | kEventKeyModifierNumLockMask |
    2060         (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask (m_globalSettings.hostKey()));
    2061 #endif
    2062 
    2063     emitKeyboardStateChanged();
    2064 }
    2065 
    2066 void UIMachineView::sendChangedKeyStates()
    2067 {
    2068     QVector <LONG> codes(2);
    2069     CKeyboard keyboard = session().GetConsole().GetKeyboard();
    2070     for (uint i = 0; i < SIZEOF_ARRAY(m_pressedKeys); ++ i)
    2071     {
    2072         uint8_t os = m_pressedKeysCopy[i];
    2073         uint8_t ns = m_pressedKeys[i];
    2074         if ((os & IsKeyPressed) != (ns & IsKeyPressed))
    2075         {
    2076             codes[0] = i;
    2077             if (!(ns & IsKeyPressed))
    2078                 codes[0] |= 0x80;
    2079             keyboard.PutScancode(codes[0]);
    2080         }
    2081         else if ((os & IsExtKeyPressed) != (ns & IsExtKeyPressed))
    2082         {
    2083             codes[0] = 0xE0;
    2084             codes[1] = i;
    2085             if (!(ns & IsExtKeyPressed))
    2086                 codes[1] |= 0x80;
    2087             keyboard.PutScancodes(codes);
    2088         }
    2089     }
    2090 }
    2091 
    2092 void UIMachineView::dimImage(QImage &img)
    2093 {
    2094     for (int y = 0; y < img.height(); ++ y)
    2095     {
    2096         if (y % 2)
    2097         {
    2098             if (img.depth() == 32)
    2099             {
    2100                 for (int x = 0; x < img.width(); ++ x)
    2101                 {
    2102                     int gray = qGray(img.pixel (x, y)) / 2;
    2103                     img.setPixel(x, y, qRgb (gray, gray, gray));
    2104                 }
    2105             }
    2106             else
    2107             {
    2108                 ::memset(img.scanLine (y), 0, img.bytesPerLine());
    2109             }
    2110         }
    2111         else
    2112         {
    2113             if (img.depth() == 32)
    2114             {
    2115                 for (int x = 0; x < img.width(); ++ x)
    2116                 {
    2117                     int gray = (2 * qGray (img.pixel (x, y))) / 3;
    2118                     img.setPixel(x, y, qRgb (gray, gray, gray));
    2119                 }
    2120             }
    2121         }
    2122     }
    2123 }
    2124 
    2125 #ifdef Q_WS_MAC
    2126 CGImageRef UIMachineView::vmContentImage()
    2127 {
    2128     if (!m_pauseShot.isNull())
    2129     {
    2130         CGImageRef pauseImg = ::darwinToCGImageRef(&m_pauseShot);
    2131         /* Use the pause image as background */
    2132         return pauseImg;
    2133     }
    2134     else
    2135     {
    2136 # ifdef VBOX_GUI_USE_QUARTZ2D
    2137         if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode)
    2138         {
    2139             /* If the render mode is Quartz2D we could use the CGImageRef
    2140              * of the framebuffer for the dock icon creation. This saves
    2141              * some conversion time. */
    2142             CGImageRef image = static_cast<UIFrameBufferQuartz2D*>(m_pFrameBuffer)->imageRef();
    2143             CGImageRetain(image); /* Retain it, cause the consumer will release it. */
    2144             return image;
    2145         }
    2146         else
    2147 # endif /* VBOX_GUI_USE_QUARTZ2D */
    2148             /* In image mode we have to create the image ref out of the
    2149              * framebuffer */
    2150             return frameBuffertoCGImageRef(m_pFrameBuffer);
    2151     }
    2152     return 0;
    2153 }
    2154 
    2155 CGImageRef UIMachineView::frameBuffertoCGImageRef(UIFrameBuffer *pFrameBuffer)
    2156 {
    2157     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    2158     Assert(cs);
    2159     /* Create the image copy of the framebuffer */
    2160     CGDataProviderRef dp = CGDataProviderCreateWithData(pFrameBuffer, pFrameBuffer->address(), pFrameBuffer->bitsPerPixel() / 8 * pFrameBuffer->width() * pFrameBuffer->height(), NULL);
    2161     Assert(dp);
    2162     CGImageRef ir = CGImageCreate(pFrameBuffer->width(), pFrameBuffer->height(), 8, 32, pFrameBuffer->bytesPerLine(), cs,
    2163                                   kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host, dp, 0, false,
    2164                                   kCGRenderingIntentDefault);
    2165     Assert(ir);
    2166     CGDataProviderRelease(dp);
    2167     CGColorSpaceRelease(cs);
    2168 
    2169     return ir;
    2170 }
    2171 
    2172 void UIMachineView::updateDockIcon()
    2173 {
    2174     machineLogic()->updateDockIcon();
    2175 }
    2176 #endif /* Q_WS_MAC */
    2177 
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r30548 r30549  
    5454#ifdef VBOX_WITH_VIDEOHWACCEL
    5555                                 , bool bAccelerate2DVideo
    56 #endif
     56#endif /* VBOX_WITH_VIDEOHWACCEL */
    5757    );
    5858    /* Factory function to destroy required machine-view: */
     
    6868    virtual void normalizeGeometry(bool /* bAdjustPosition = false */) = 0;
    6969
     70protected slots:
     71
     72    /* Console callback handlers: */
     73    virtual void sltMachineStateChanged();
     74
    7075signals:
    7176
     
    8388#ifdef VBOX_WITH_VIDEOHWACCEL
    8489                  , bool bAccelerate2DVideo
    85 #endif
     90#endif /* VBOX_WITH_VIDEOHWACCEL */
    8691    );
    8792    /* Machine-view destructor: */
    8893    virtual ~UIMachineView();
    8994
     95    /* Prepare routines: */
     96    virtual void prepareFrameBuffer();
     97    virtual void prepareCommon();
     98    virtual void prepareFilters();
     99    virtual void prepareConsoleConnections();
     100    virtual void loadMachineViewSettings();
     101
     102    /* Cleanup routines: */
     103    //virtual void saveMachineViewSettings() {}
     104    //virtual void cleanupConsoleConnections() {}
     105    //virtual void cleanupFilters() {}
     106    virtual void cleanupCommon();
     107    virtual void cleanupFrameBuffer();
     108
    90109    /* Protected getters: */
     110    UIMachineWindow* machineWindowWrapper() const { return m_pMachineWindow; }
     111    UIMachineLogic* machineLogic() const;
    91112    UISession* uisession() const;
    92113    CSession& session();
     
    100121    ulong screenId() const { return m_uScreenId; }
    101122    UIFrameBuffer* frameBuffer() const { return m_pFrameBuffer; }
    102     UIMachineWindow* machineWindowWrapper() const { return m_pMachineWindow; }
    103     UIMachineLogic* machineLogic() const;
    104123    bool isHostKeyPressed() const { return m_bIsHostkeyPressed; }
    105124    bool isMachineWindowResizeIgnored() const { return m_bIsMachineWindowResizeIgnored; }
     
    126145    virtual void maybeRestrictMinimumSize() = 0;
    127146    virtual void updateSliders();
    128 
     147    void fixModifierState(LONG *piCodes, uint *puCount);
     148    QPoint viewportToContents(const QPoint &vp) const;
     149    void scrollBy(int dx, int dy);
     150    void emitKeyboardStateChanged();
     151    void captureKbd(bool fCapture, bool fEmitSignal = true);
     152    void saveKeyStates();
     153    void releaseAllPressedKeys(bool aReleaseHostKey = true);
     154    void sendChangedKeyStates();
     155    static void dimImage(QImage &img);
     156#ifdef VBOX_WITH_VIDEOHWACCEL
     157    void scrollContentsBy(int dx, int dy);
     158#endif /* VBOX_WITH_VIDEOHWACCEL */
    129159#ifdef Q_WS_MAC
    130160    void updateDockIcon();
     
    133163#endif /* Q_WS_MAC */
    134164
    135     /* Prepare routines: */
    136     virtual void prepareFrameBuffer();
    137     virtual void prepareCommon();
    138     virtual void prepareFilters();
    139     virtual void prepareConsoleConnections();
    140     virtual void loadMachineViewSettings();
    141 
    142     /* Cleanup routines: */
    143     //virtual void saveMachineViewSettings() {}
    144     //virtual void cleanupConsoleConnections() {}
    145     //virtual void cleanupFilters() {}
    146     virtual void cleanupCommon();
    147     virtual void cleanupFrameBuffer();
    148 
    149165    /* Cross-platforms event processors: */
    150166    bool event(QEvent *pEvent);
    151167    bool eventFilter(QObject *pWatched, QEvent *pEvent);
    152 
    153     /* Protected variables: */
    154     QSize m_desktopGeometry;
    155 
    156 protected slots:
    157 
    158     /* Console callback handlers: */
    159     virtual void sltMachineStateChanged();
    160 
    161 private:
    162 
    163     /* Cross-platforms event processors: */
    164168    void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
    165169    bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
     
    169173
    170174    /* Platform specific event processors: */
    171 #if defined(Q_WS_WIN32)
     175#if defined(Q_WS_WIN)
    172176    static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    173177    bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event);
     
    178182    bool x11Event(XEvent *event);
    179183#elif defined(Q_WS_MAC)
    180     bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent);
    181184    void darwinGrabKeyboardEvents(bool fGrab);
    182185    static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser);
     186    bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent);
    183187#endif
    184 
    185     /* Private helpers: */
    186     void fixModifierState(LONG *piCodes, uint *puCount);
    187     QPoint viewportToContents(const QPoint &vp) const;
    188     void scrollBy(int dx, int dy);
    189 #ifdef VBOX_WITH_VIDEOHWACCEL
    190     void scrollContentsBy(int dx, int dy);
    191 #endif
    192     void emitKeyboardStateChanged();
    193     void captureKbd(bool fCapture, bool fEmitSignal = true);
    194     void saveKeyStates();
    195     void releaseAllPressedKeys(bool aReleaseHostKey = true);
    196     void sendChangedKeyStates();
    197 
    198     static void dimImage(QImage &img);
    199188
    200189    /* Private members: */
     
    206195
    207196    DesktopGeo m_desktopGeometryType;
     197    QSize m_desktopGeometry;
    208198    QSize m_storedConsoleSize;
    209199
     
    218208    bool m_fPassCAD : 1;
    219209#ifdef VBOX_WITH_VIDEOHWACCEL
    220     bool m_fAccelerate2DVideo;
    221 #endif
     210    bool m_fAccelerate2DVideo : 1;
     211#endif /* VBOX_WITH_VIDEOHWACCEL */
    222212
    223213#ifdef Q_WS_MAC
Note: See TracChangeset for help on using the changeset viewer.

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