VirtualBox

Changeset 26878 in vbox for trunk/src


Ignore:
Timestamp:
Feb 26, 2010 11:56:51 PM (15 years ago)
Author:
vboxsync
Message:

FE/Qt4: New running VM core: guest auto-resize feature fixed.

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

Legend:

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

    r26823 r26878  
    184184        return E_POINTER;
    185185    *pbSupported = TRUE;
    186     QRect screen = m_pMachineView->desktopGeometry();
     186    QSize screen = m_pMachineView->desktopGeometry();
    187187    if ((screen.width() != 0) && (uWidth > (ULONG)screen.width()))
    188188        *pbSupported = FALSE;
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r26862 r26878  
    148148}
    149149
     150void UIMachineView::destroy(UIMachineView *pWhichView)
     151{
     152    delete pWhichView;
     153}
     154
    150155int UIMachineView::keyboardState() const
    151156{
     
    197202    , m_bIsHostkeyAlone (false)
    198203    , m_bIsHostkeyInCapture(false)
    199     , m_bIsMachineWindowResizeIgnored(true)
     204    , m_bIsMachineWindowResizeIgnored(false)
    200205    , m_bIsFrameBufferResizeIgnored(false)
    201206    , m_fPassCAD(false)
    202207#ifdef VBOX_WITH_VIDEOHWACCEL
    203208    , m_fAccelerate2DVideo(bAccelerate2DVideo)
    204 #endif
    205 #if 0 // TODO: Do we need this?
    206     , mDoResize(false)
    207209#endif
    208210#if defined(Q_WS_MAC)
     
    214216    , mDockIconEnabled(true)
    215217#endif
    216     , m_desktopGeometryType(DesktopGeo_Invalid)
    217       /* Don't show a hardware pointer until we have one to show */
    218218{
    219219}
     
    277277}
    278278
    279 QRect UIMachineView::desktopGeometry() const
    280 {
    281     QRect geometry;
    282     switch (m_desktopGeometryType)
    283     {
    284         case DesktopGeo_Fixed:
    285         case DesktopGeo_Automatic:
    286             geometry = QRect(0, 0,
    287                              qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
    288                              qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
    289             break;
    290         case DesktopGeo_Any:
    291             geometry = QRect(0, 0, 0, 0);
    292             break;
    293         default:
    294             AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
    295     }
    296     return geometry;
    297 }
    298 
    299 void UIMachineView::calculateDesktopGeometry()
    300 {
    301     /* This method should not get called until we have initially set up the m_desktopGeometryType: */
    302     Assert((m_desktopGeometryType != DesktopGeo_Invalid));
    303     /* If we are not doing automatic geometry calculation then there is nothing to do: */
    304     if (DesktopGeo_Automatic == m_desktopGeometryType)
    305     {
    306         /* Available geometry of the desktop.  If the desktop is a single
    307          * screen, this will exclude space taken up by desktop taskbars
    308          * and things, but this is unfortunately not true for the more
    309          * complex case of a desktop spanning multiple screens: */
    310         QRect desktop = availableGeometry();
    311         /* The area taken up by the machine window on the desktop,
    312          * including window frame, title and menu bar and whatnot: */
    313         QRect frame = machineWindowWrapper()->machineWindow()->frameGeometry();
    314         /* The area taken up by the machine view, so excluding all decorations: */
    315         QRect window = geometry();
    316         /* To work out how big we can make the console window while still
    317          * fitting on the desktop, we calculate desktop - frame + window.
    318          * This works because the difference between frame and window
    319          * (or at least its width and height) is a constant. */
    320         m_desktopGeometry = QRect(0, 0, desktop.width() - frame.width() + window.width(),
    321                                         desktop.height() - frame.height() + window.height());
    322     }
    323 }
    324 
    325 void UIMachineView::setDesktopGeometry(DesktopGeo geometry, int aWidth, int aHeight)
    326 {
    327     switch (geometry)
    328     {
    329         case DesktopGeo_Fixed:
    330             m_desktopGeometryType = DesktopGeo_Fixed;
    331             if (aWidth != 0 && aHeight != 0)
    332                 m_desktopGeometry = QRect(0, 0, aWidth, aHeight);
    333             else
    334                 m_desktopGeometry = QRect(0, 0, 0, 0);
    335             storeConsoleSize(0, 0);
    336             break;
    337         case DesktopGeo_Automatic:
    338             m_desktopGeometryType = DesktopGeo_Automatic;
    339             m_desktopGeometry = QRect(0, 0, 0, 0);
    340             storeConsoleSize(0, 0);
    341             break;
    342         case DesktopGeo_Any:
    343             m_desktopGeometryType = DesktopGeo_Any;
    344             m_desktopGeometry = QRect(0, 0, 0, 0);
    345             break;
    346         default:
    347             AssertMsgFailed(("Invalid desktop geometry type %d\n", geometry));
    348             m_desktopGeometryType = DesktopGeo_Invalid;
    349     }
    350 }
    351 
    352 void UIMachineView::storeConsoleSize(int aWidth, int aHeight)
    353 {
    354     LogFlowThisFunc(("aWidth=%d, aHeight=%d\n", aWidth, aHeight));
    355     m_storedConsoleSize = QRect(0, 0, aWidth, aHeight);
    356 }
    357 
    358 QRect UIMachineView::availableGeometry()
    359 {
    360     return machineWindowWrapper()->machineWindow()->isFullScreen() ?
    361            QApplication::desktop()->screenGeometry(this) :
    362            QApplication::desktop()->availableGeometry(this);
     279void UIMachineView::updateMouseClipping()
     280{
     281    if (uisession()->isMouseCaptured())
     282    {
     283        viewport()->setCursor(QCursor(Qt::BlankCursor));
     284#ifdef Q_WS_WIN32
     285        QRect r = viewport()->rect();
     286        r.moveTopLeft(viewport()->mapToGlobal(QPoint (0, 0)));
     287        RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
     288        ::ClipCursor(&rect);
     289#endif
     290    }
     291    else
     292    {
     293#ifdef Q_WS_WIN32
     294        ::ClipCursor(NULL);
     295#endif
     296        /* return the cursor to where it was when we captured it and show it */
     297        QCursor::setPos(m_capturedMousePos);
     298        viewport()->unsetCursor();
     299    }
     300}
     301
     302void UIMachineView::updateSliders()
     303{
     304    QSize p = viewport()->size();
     305    QSize m = maximumViewportSize();
     306
     307    QSize v = QSize(m_pFrameBuffer->width(), m_pFrameBuffer->height());
     308    /* no scroll bars needed */
     309    if (m.expandedTo(v) == m)
     310        p = m;
     311
     312    horizontalScrollBar()->setRange(0, v.width() - p.width());
     313    verticalScrollBar()->setRange(0, v.height() - p.height());
     314    horizontalScrollBar()->setPageStep(p.width());
     315    verticalScrollBar()->setPageStep(p.height());
    363316}
    364317
     
    543496void UIMachineView::prepareConsoleConnections()
    544497{
    545     /* UISession notifier: */
    546     UISession *sender = machineWindowWrapper()->machineLogic()->uisession();
    547 
    548498    /* Machine state-change updater: */
    549     connect(sender, SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged()));
    550 
    551     /* Guest additions state-change updater: */
    552     connect(sender, SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged()));
     499    connect(uisession(), SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged()));
    553500
    554501    /* Mouse pointer shape state-change updater: */
    555     connect(sender, SIGNAL(sigMousePointerShapeChange()), this, SLOT(sltMousePointerShapeChanged()));
     502    connect(uisession(), SIGNAL(sigMousePointerShapeChange()), this, SLOT(sltMousePointerShapeChanged()));
    556503
    557504    /* Mouse capability state-change updater: */
    558     connect(sender, SIGNAL(sigMouseCapabilityChange()), this, SLOT(sltMouseCapabilityChanged()));
     505    connect(uisession(), SIGNAL(sigMouseCapabilityChange()), this, SLOT(sltMouseCapabilityChanged()));
    559506}
    560507
     
    563510    /* Global settings: */
    564511    {
    565         /* Remember the desktop geometry and register for geometry
    566          * change events for telling the guest about video modes we like: */
    567         QString desktopGeometry = vboxGlobal().settings().publicProperty("GUI/MaxGuestResolution");
    568         if ((desktopGeometry == QString::null) || (desktopGeometry == "auto"))
    569             setDesktopGeometry(DesktopGeo_Automatic, 0, 0);
    570         else if (desktopGeometry == "any")
    571             setDesktopGeometry(DesktopGeo_Any, 0, 0);
    572         else
    573         {
    574             int width = desktopGeometry.section(',', 0, 0).toInt();
    575             int height = desktopGeometry.section(',', 1, 1).toInt();
    576             setDesktopGeometry(DesktopGeo_Fixed, width, height);
    577         }
    578         connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(sltDesktopResized()));
    579 
    580512#ifdef Q_WS_X11
    581513        /* Initialize the X keyboard subsystem: */
     
    644576}
    645577
    646 void UIMachineView::sltMachineStateChanged()
    647 {
    648     /* Get machine state: */
    649     KMachineState state = uisession()->machineState();
    650     switch (state)
    651     {
    652         case KMachineState_Paused:
    653         case KMachineState_TeleportingPausedVM:
    654         {
    655             if (mode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
    656                 (state != KMachineState_TeleportingPausedVM || m_previousState != KMachineState_Teleporting))
    657             {
    658                 /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
    659                 QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
    660                 CDisplay dsp = session().GetConsole().GetDisplay();
    661                 dsp.TakeScreenShot(shot.bits(), shot.width(), shot.height());
    662                 /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
    663                  * after the machine execution was resumed. It's not fatal: */
    664                 if (dsp.isOk())
    665                 {
    666                     dimImage(shot);
    667                     m_pauseShot = QPixmap::fromImage(shot);
    668                     /* Fully repaint to pick up m_pauseShot: */
    669                     repaint();
    670                 }
    671             }
    672         }
    673         case KMachineState_Stuck:
    674         {
    675             /* Reuse the focus event handler to uncapture everything: */
    676             if (hasFocus())
    677                 focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
    678             break;
    679         }
    680         case KMachineState_Running:
    681         {
    682             if (m_previousState == KMachineState_Paused || m_previousState == KMachineState_TeleportingPausedVM)
    683             {
    684                 if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer)
    685                 {
    686                     /* Reset the pixmap to free memory: */
    687                     m_pauseShot = QPixmap();
    688                     /* Ask for full guest display update (it will also update
    689                      * the viewport through IFramebuffer::NotifyUpdate): */
    690                     CDisplay dsp = session().GetConsole().GetDisplay();
    691                     dsp.InvalidateAndUpdate();
    692                 }
    693             }
    694             /* Reuse the focus event handler to capture input: */
    695             if (hasFocus())
    696                 focusEvent(true /* aHasFocus */);
    697             break;
    698         }
    699         default:
    700             break;
    701     }
    702 
    703 #ifdef Q_WS_MAC
    704     /* Update Dock Overlay: */
    705     updateDockOverlay();
    706 #endif /* Q_WS_MAC */
    707 
    708     m_previousState = state;
    709 }
    710 
    711 void UIMachineView::sltAdditionsStateChanged()
    712 {
    713     /* Check if we should restrict minimum size: */
    714     maybeRestrictMinimumSize();
    715 
    716 #if 0 // TODO: Do we need this?
    717     if (!mDoResize && !isGuestSupportsGraphics() && fIsGuestSupportsGraphics &&
    718         (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen()))
    719         mDoResize = true;
    720     /* This will only be acted upon if mDoResize is true: */
    721     sltPerformGuestResize();
    722 #endif
    723 }
    724 
    725 void UIMachineView::sltMousePointerShapeChanged()
    726 {
    727     if (uisession()->isMouseSupportsAbsolute())
    728     {
    729         /* Should we hide/show pointer? */
    730         if (uisession()->isHidingHostPointer())
    731             viewport()->setCursor(Qt::BlankCursor);
    732         else
    733             viewport()->setCursor(uisession()->cursor());
    734     }
    735 }
    736 
    737 void UIMachineView::sltMouseCapabilityChanged()
    738 {
    739     /* Correct the mouse capture state and reset the cursor to the default shape if necessary: */
    740     if (uisession()->isMouseSupportsAbsolute())
    741     {
    742         CMouse mouse = session().GetConsole().GetMouse();
    743         mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
    744         captureMouse(false, false);
    745     }
    746     else
    747         viewport()->unsetCursor();
    748 
    749     /* Notify user about mouse integration state: */
    750     vboxProblem().remindAboutMouseIntegration(uisession()->isMouseSupportsAbsolute());
    751 
    752     /* Notify all listeners: */
    753     emitMouseStateChanged();
    754 }
    755 
    756 /* If the desktop geometry is set automatically, this will update it: */
    757 void UIMachineView::sltDesktopResized()
    758 {
    759     calculateDesktopGeometry();
    760 }
    761 
    762 #ifdef Q_WS_MAC
    763 void UIMachineView::sltChangeDockIconUpdate(const VBoxChangeDockIconUpdateEvent &event)
    764 {
    765     setDockIconEnabled(event.mChanged);
    766     updateDockOverlay();
    767 }
    768 
    769 # ifdef QT_MAC_USE_COCOA
    770 void UIMachineView::sltChangePresentationMode(const VBoxChangePresentationModeEvent &event)
    771 {
    772     // TODO_NEW_CORE
    773     // this is full screen related
    774 #if 0
    775     if (mIsFullscreen)
    776     {
    777         /* First check if we are on the primary screen, only than the presentation mode have to be changed. */
    778         QDesktopWidget* pDesktop = QApplication::desktop();
    779         if (pDesktop->screenNumber(this) == pDesktop->primaryScreen())
    780         {
    781             QString testStr = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_PresentationModeEnabled).toLower();
    782             /* Default to false if it is an empty value */
    783             if (testStr.isEmpty() || testStr == "false")
    784                 SetSystemUIMode(kUIModeAllHidden, 0);
    785             else
    786                 SetSystemUIMode(kUIModeAllSuppressed, 0);
    787         }
    788     }
    789     else
    790         SetSystemUIMode(kUIModeNormal, 0);
    791 #endif
    792 }
    793 # endif /* QT_MAC_USE_COCOA */
    794 #endif
    795 
    796578bool UIMachineView::event(QEvent *pEvent)
    797579{
     
    818600        }
    819601
    820         case VBoxDefs::ResizeEventType:
    821         {
    822             /* Some situations require initial VGA Resize Request
    823              * to be ignored at all, leaving previous framebuffer,
    824              * machine view and machine window sizes preserved: */
    825             if (uisession()->isGuestResizeIgnored())
    826                 return true;
    827 
    828             bool oldIgnoreMainwndResize = m_bIsMachineWindowResizeIgnored;
    829             m_bIsMachineWindowResizeIgnored = true;
    830 
    831             UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);
    832 
    833             /* Store the new size to prevent unwanted resize hints being sent back. */
    834             storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());
    835 
    836             /* Unfortunately restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen widgets are present.
    837              * This is the case on linux with SDL. As workaround we save/restore the arrow cursor manually.
    838              * See http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry for details.
    839              * Moreover the current cursor, which could be set by the guest, should be restored after resize: */
    840             QCursor cursor;
    841             if (uisession()->isHidingHostPointer())
    842                 cursor = QCursor(Qt::BlankCursor);
    843             else
    844                 cursor = viewport()->cursor();
    845             m_pFrameBuffer->resizeEvent(pResizeEvent);
    846             viewport()->setCursor(cursor);
    847 
    848 #ifdef Q_WS_MAC
    849             // TODO_NEW_CORE
    850 //            mDockIconPreview->setOriginalSize(pResizeEvent->width(), pResizeEvent->height());
    851 #endif /* Q_WS_MAC */
    852 
    853             /* This event appears in case of guest video was changed for somehow even without video resolution change.
    854              * In this last case the host VM window will not be resized according this event and the host mouse cursor
    855              * which was unset to default here will not be hidden in capture state. So it is necessary to perform
    856              * updateMouseClipping() for the guest resize event if the mouse cursor was captured: */
    857             if (uisession()->isMouseCaptured())
    858                 updateMouseClipping();
    859 
    860             /* Apply maximum size restriction: */
    861             setMaximumSize(sizeHint());
    862 
    863             /* May be we have to restrict minimum size? */
    864             maybeRestrictMinimumSize();
    865 
    866             /* Resize the guest canvas: */
    867             if (!m_bIsFrameBufferResizeIgnored)
    868                 resize(pResizeEvent->width(), pResizeEvent->height());
    869             updateSliders();
    870 
    871             /* Let our toplevel widget calculate its sizeHint properly. */
    872 #ifdef Q_WS_X11
    873             /* We use processEvents rather than sendPostedEvents & set the time out value to max cause on X11 otherwise
    874              * the layout isn't calculated correctly. Dosn't find the bug in Qt, but this could be triggered through
    875              * the async nature of the X11 window event system. */
    876             QCoreApplication::processEvents(QEventLoop::AllEvents, INT_MAX);
    877 #else /* Q_WS_X11 */
    878             QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
    879 #endif /* Q_WS_X11 */
    880 
    881             if (!m_bIsFrameBufferResizeIgnored)
    882                 normalizeGeometry(true /* adjustPosition */);
    883 
    884             /* Report to the VM thread that we finished resizing */
    885             session().GetConsole().GetDisplay().ResizeCompleted(0);
    886 
    887             m_bIsMachineWindowResizeIgnored = oldIgnoreMainwndResize;
    888 
    889             /* Make sure that all posted signals are processed: */
    890             qApp->processEvents();
    891 
    892             /* Emit a signal about guest was resized: */
    893             emit resizeHintDone();
    894 
    895             /* We also recalculate the desktop geometry if this is determined
    896              * automatically.  In fact, we only need this on the first resize,
    897              * but it is done every time to keep the code simpler. */
    898             calculateDesktopGeometry();
    899 
    900             /* Enable frame-buffer resize watching: */
    901             if (m_bIsFrameBufferResizeIgnored)
    902                 m_bIsFrameBufferResizeIgnored = false;
    903 
    904             return true;
    905         }
    906 
    907         /* See VBox[QImage|SDL]FrameBuffer::NotifyUpdate(): */
    908602        case VBoxDefs::RepaintEventType:
    909603        {
     
    1021715            if (m_bIsHostkeyPressed && pEvent->type() == QEvent::KeyPress)
    1022716            {
     717                /* Passing F1-F12 keys to the guest: */
    1023718                if (pKeyEvent->key() >= Qt::Key_F1 && pKeyEvent->key() <= Qt::Key_F12)
    1024719                {
     
    1048743                if (pKeyEvent->key() == Qt::Key_Home)
    1049744                {
    1050 #if 0 // TODO: Divide tha code to specific parts and move it there:
     745#if 0 // TODO: Divide tha code to specific parts of fullscreen & seamless and move it there:
    1051746                    /* Activate the main menu */
    1052747                    if (machineWindowWrapper()->isTrueSeamless() || machineWindowWrapper()->isTrueFullscreen())
    1053748                        machineWindowWrapper()->popupMainMenu (uisession()->isMouseCaptured());
    1054                     else
    1055                     {
    1056                         /* In Qt4 it is not enough to just set the focus to menu-bar.
    1057                          * So to get the menu-bar we have to send Qt::Key_Alt press/release events directly: */
    1058                         QKeyEvent e1(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier);
    1059                         QKeyEvent e2(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier);
    1060                         QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e1);
    1061                         QApplication::sendEvent(machineWindowWrapper()->menuBar(), &e2);
    1062                     }
    1063749#endif
    1064750                }
     
    1190876        switch (pEvent->type())
    1191877        {
    1192 #if 0 // TODO Move to normal specific event handler:
    1193             case QEvent::Resize:
    1194             {
    1195                 /* Set the "guest needs to resize" hint. This hint is acted upon when (and only when)
    1196                  * the autoresize property is "true": */
    1197                 mDoResize = isGuestSupportsGraphics() || machineWindowWrapper()->isTrueFullscreen();
    1198                 if (!m_bIsMachineWindowResizeIgnored && isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
    1199                     QTimer::singleShot(300, this, SLOT(sltPerformGuestResize()));
    1200                 break;
    1201             }
    1202 #endif
    1203878            case QEvent::WindowStateChange:
    1204879            {
    1205                 /* During minimizing and state restoring machineWindowWrapper() gets the focus
    1206                  * which belongs to console view window, so returning it properly. */
     880                /* During minimizing and state restoring machineWindowWrapper() gets
     881                 * the focus which belongs to console view window, so returning it properly. */
    1207882                QWindowStateChangeEvent *pWindowEvent = static_cast<QWindowStateChangeEvent*>(pEvent);
    1208883                if (pWindowEvent->oldState() & Qt::WindowMinimized)
     
    1218893            }
    1219894#if defined (Q_WS_WIN32)
    1220 #if defined (VBOX_GUI_USE_DDRAW)
    1221             case QEvent::Move:
    1222             {
    1223                 /* Notification from our parent that it has moved. We need this in order
    1224                  * to possibly adjust the direct screen blitting: */
    1225                 if (m_pFrameBuffer)
    1226                     m_pFrameBuffer->moveEvent(static_cast<QMoveEvent*>(pEvent));
    1227                 break;
    1228             }
    1229 #endif
    1230895            /* Install/uninstall low-level kbd hook on every activation/deactivation to:
    1231896             * a) avoid excess hook calls when we're not active and
     
    1260925        }
    1261926    }
    1262 #if 0 // TODO Move to normal specific event handler:
    1263     else if (pWatched == machineWindowWrapper()->menuBar())
    1264     {
    1265         /* Sometimes when we press ESC in the menu it brings the focus away (Qt bug?)
    1266          * causing no widget to have a focus, or holds the focus itself, instead of
    1267          * returning the focus to the console window. Here we fix this: */
    1268         switch (pEvent->type())
    1269         {
    1270             case QEvent::FocusOut:
    1271             {
    1272                 if (qApp->focusWidget() == 0)
    1273                     setFocus();
    1274                 break;
    1275             }
    1276             case QEvent::KeyPress:
    1277             {
    1278                 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
    1279                 if (pKeyEvent->key() == Qt::Key_Escape && (pKeyEvent->modifiers() == Qt::NoModifier))
    1280                     if (machineWindowWrapper()->menuBar()->hasFocus())
    1281                         setFocus();
    1282                 break;
    1283             }
    1284             default:
    1285                 break;
    1286         }
    1287     }
    1288 #endif
    1289927
    1290928    return QAbstractScrollArea::eventFilter (pWatched, pEvent);
    1291929}
     930
     931void UIMachineView::sltMachineStateChanged()
     932{
     933    /* Get machine state: */
     934    KMachineState state = uisession()->machineState();
     935    switch (state)
     936    {
     937        case KMachineState_Paused:
     938        case KMachineState_TeleportingPausedVM:
     939        {
     940            if (mode() != VBoxDefs::TimerMode &&  m_pFrameBuffer &&
     941                (state != KMachineState_TeleportingPausedVM || m_previousState != KMachineState_Teleporting))
     942            {
     943                /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
     944                QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
     945                CDisplay dsp = session().GetConsole().GetDisplay();
     946                dsp.TakeScreenShot(shot.bits(), shot.width(), shot.height());
     947                /* TakeScreenShot() may fail if, e.g. the Paused notification was delivered
     948                 * after the machine execution was resumed. It's not fatal: */
     949                if (dsp.isOk())
     950                {
     951                    dimImage(shot);
     952                    m_pauseShot = QPixmap::fromImage(shot);
     953                    /* Fully repaint to pick up m_pauseShot: */
     954                    repaint();
     955                }
     956            }
     957        }
     958        case KMachineState_Stuck:
     959        {
     960            /* Reuse the focus event handler to uncapture everything: */
     961            if (hasFocus())
     962                focusEvent(false /* aHasFocus*/, false /* aReleaseHostKey */);
     963            break;
     964        }
     965        case KMachineState_Running:
     966        {
     967            if (m_previousState == KMachineState_Paused || m_previousState == KMachineState_TeleportingPausedVM)
     968            {
     969                if (mode() != VBoxDefs::TimerMode && m_pFrameBuffer)
     970                {
     971                    /* Reset the pixmap to free memory: */
     972                    m_pauseShot = QPixmap();
     973                    /* Ask for full guest display update (it will also update
     974                     * the viewport through IFramebuffer::NotifyUpdate): */
     975                    CDisplay dsp = session().GetConsole().GetDisplay();
     976                    dsp.InvalidateAndUpdate();
     977                }
     978            }
     979            /* Reuse the focus event handler to capture input: */
     980            if (hasFocus())
     981                focusEvent(true /* aHasFocus */);
     982            break;
     983        }
     984        default:
     985            break;
     986    }
     987
     988#ifdef Q_WS_MAC
     989    /* Update Dock Overlay: */
     990    updateDockOverlay();
     991#endif /* Q_WS_MAC */
     992
     993    m_previousState = state;
     994}
     995
     996void UIMachineView::sltMousePointerShapeChanged()
     997{
     998    if (uisession()->isMouseSupportsAbsolute())
     999    {
     1000        /* Should we hide/show pointer? */
     1001        if (uisession()->isHidingHostPointer())
     1002            viewport()->setCursor(Qt::BlankCursor);
     1003        else
     1004            viewport()->setCursor(uisession()->cursor());
     1005    }
     1006}
     1007
     1008void UIMachineView::sltMouseCapabilityChanged()
     1009{
     1010    /* Correct the mouse capture state and reset the cursor to the default shape if necessary: */
     1011    if (uisession()->isMouseSupportsAbsolute())
     1012    {
     1013        CMouse mouse = session().GetConsole().GetMouse();
     1014        mouse.PutMouseEventAbsolute(-1, -1, 0, 0, 0);
     1015        captureMouse(false, false);
     1016    }
     1017    else
     1018        viewport()->unsetCursor();
     1019
     1020    /* Notify user about mouse integration state: */
     1021    vboxProblem().remindAboutMouseIntegration(uisession()->isMouseSupportsAbsolute());
     1022
     1023    /* Notify all listeners: */
     1024    emitMouseStateChanged();
     1025}
     1026
     1027#ifdef Q_WS_MAC
     1028void UIMachineView::sltChangeDockIconUpdate(const VBoxChangeDockIconUpdateEvent &event)
     1029{
     1030    setDockIconEnabled(event.mChanged);
     1031    updateDockOverlay();
     1032}
     1033
     1034# ifdef QT_MAC_USE_COCOA
     1035void UIMachineView::sltChangePresentationMode(const VBoxChangePresentationModeEvent &event)
     1036{
     1037    // TODO_NEW_CORE
     1038    // this is full screen related
     1039#if 0
     1040    if (mIsFullscreen)
     1041    {
     1042        /* First check if we are on the primary screen, only than the presentation mode have to be changed. */
     1043        QDesktopWidget* pDesktop = QApplication::desktop();
     1044        if (pDesktop->screenNumber(this) == pDesktop->primaryScreen())
     1045        {
     1046            QString testStr = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_PresentationModeEnabled).toLower();
     1047            /* Default to false if it is an empty value */
     1048            if (testStr.isEmpty() || testStr == "false")
     1049                SetSystemUIMode(kUIModeAllHidden, 0);
     1050            else
     1051                SetSystemUIMode(kUIModeAllSuppressed, 0);
     1052        }
     1053    }
     1054    else
     1055        SetSystemUIMode(kUIModeNormal, 0);
     1056#endif
     1057}
     1058# endif /* QT_MAC_USE_COCOA */
     1059#endif
    12921060
    12931061void UIMachineView::focusEvent(bool fHasFocus, bool fReleaseHostKey /* = true */)
     
    15991367
    16001368bool UIMachineView::mouseEvent(int aType, const QPoint &aPos, const QPoint &aGlobalPos,
    1601                                Qt::MouseButtons aButtons, Qt::KeyboardModifiers aModifiers,
     1369                               Qt::MouseButtons aButtons, Qt::KeyboardModifiers /* aModifiers */,
    16021370                               int aWheelDelta, Qt::Orientation aWheelDir)
    16031371{
    1604 #if 0
    1605     LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n",
    1606              __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(),
    1607                (aButtons & Qt::LeftButton ? 1 : 0)
    1608              | (aButtons & Qt::RightButton ? 2 : 0)
    1609              | (aButtons & Qt::MidButton ? 4 : 0)
    1610              | (aButtons & Qt::XButton1 ? 8 : 0)
    1611              | (aButtons & Qt::XButton2 ? 16 : 0),
    1612              aWheelDelta,
    1613                aWheelDir == Qt::Horizontal ? "Horizontal"
    1614              : aWheelDir == Qt::Vertical ? "Vertical" : "Unknown"));
    1615     Q_UNUSED (aModifiers);
    1616 #else
    1617     Q_UNUSED (aModifiers);
    1618 #endif
    1619 
    16201372    int state = 0;
    16211373    if (aButtons & Qt::LeftButton)
     
    16311383
    16321384#ifdef Q_WS_MAC
    1633     /* Simulate the right click on
    1634      * Host+Left Mouse */
     1385    /* Simulate the right click on Host+Left Mouse: */
    16351386    if (m_bIsHostkeyPressed &&
    16361387        m_bIsHostkeyAlone &&
     
    16551406#ifdef Q_WS_WIN32
    16561407        /* send pending WM_PAINT events */
    1657         ::UpdateWindow (viewport()->winId());
     1408        ::UpdateWindow(viewport()->winId());
    16581409#endif
    16591410
     
    25192270}
    25202271
    2521 void UIMachineView::updateSliders()
    2522 {
    2523     QSize p = viewport()->size();
    2524     QSize m = maximumViewportSize();
    2525 
    2526     QSize v = QSize(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    2527     /* no scroll bars needed */
    2528     if (m.expandedTo(v) == m)
    2529         p = m;
    2530 
    2531     horizontalScrollBar()->setRange(0, v.width() - p.width());
    2532     verticalScrollBar()->setRange(0, v.height() - p.height());
    2533     horizontalScrollBar()->setPageStep(p.width());
    2534     verticalScrollBar()->setPageStep(p.height());
    2535 }
    2536 
    25372272void UIMachineView::scrollBy(int dx, int dy)
    25382273{
     
    25772312#elif defined(Q_WS_X11)
    25782313        if (fCapture)
    2579                 XGrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId(), False, GrabModeAsync, GrabModeAsync);
     2314            XGrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId(), False, GrabModeAsync, GrabModeAsync);
    25802315        else
    2581                 XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId());
     2316            XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, window()->winId());
    25822317#elif defined(Q_WS_MAC)
    25832318    if (fCapture)
     
    26362371        /* Release mouse buttons: */
    26372372        CMouse mouse = session().GetConsole().GetMouse();
    2638         mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0);
     2373        mouse.PutMouseEvent(0, 0, 0, 0 /* Horizontal wheel */, 0);
    26392374    }
    26402375
     
    27242459            keyboard.PutScancodes(codes);
    27252460        }
    2726     }
    2727 }
    2728 
    2729 void UIMachineView::updateMouseClipping()
    2730 {
    2731     if (uisession()->isMouseCaptured())
    2732     {
    2733         viewport()->setCursor(QCursor(Qt::BlankCursor));
    2734 #ifdef Q_WS_WIN32
    2735         QRect r = viewport()->rect();
    2736         r.moveTopLeft(viewport()->mapToGlobal(QPoint (0, 0)));
    2737         RECT rect = { r.left(), r.top(), r.right() + 1, r.bottom() + 1 };
    2738         ::ClipCursor(&rect);
    2739 #endif
    2740     }
    2741     else
    2742     {
    2743 #ifdef Q_WS_WIN32
    2744         ::ClipCursor(NULL);
    2745 #endif
    2746         /* return the cursor to where it was when we captured it and show it */
    2747         QCursor::setPos(m_capturedMousePos);
    2748         viewport()->unsetCursor();
    27492461    }
    27502462}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r26816 r26878  
    5959#endif
    6060                                 , UIVisualStateType visualStateType);
     61    static void destroy(UIMachineView *pWhichView);
    6162
    6263    /* Public getters: */
     
    6768    virtual void setGuestAutoresizeEnabled(bool bEnabled) = 0;
    6869    virtual void setMouseIntegrationEnabled(bool bEnabled);
    69     //void setMachineViewFinalized(bool fTrue = true) { m_bIsMachineWindowResizeIgnored = !fTrue; }
    7070
    7171    /* Public members: */
     
    8585    void mouseStateChanged(int iState);
    8686
    87     /* Utility signals: */
    88     void resizeHintDone();
    89 
    9087protected:
    9188
     
    9996    virtual ~UIMachineView();
    10097
    101     /* Desktop geometry types: */
    102     enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
    103 
    10498    /* Protected getters: */
    10599    UISession* uisession() const;
    106100    CSession& session();
    107     UIMachineWindow* machineWindowWrapper() const { return m_pMachineWindow; }
    108     VBoxDefs::RenderMode mode() const { return m_mode; }
    109101    QSize sizeHint() const;
    110102    int contentsX() const;
     
    114106    int visibleWidth() const;
    115107    int visibleHeight() const;
    116     QRect desktopGeometry() const;
     108    VBoxDefs::RenderMode mode() const { return m_mode; }
     109    UIFrameBuffer* frameBuffer() const { return m_pFrameBuffer; }
     110    UIMachineWindow* machineWindowWrapper() const { return m_pMachineWindow; }
     111    bool isHostKeyPressed() const { return m_bIsHostkeyPressed; }
     112    bool isMachineWindowResizeIgnored() const { return m_bIsMachineWindowResizeIgnored; }
     113    bool isFrameBufferResizeIgnored() const { return m_bIsFrameBufferResizeIgnored; }
    117114    const QPixmap& pauseShot() const { return m_pauseShot; }
    118 
    119     /* Protected members: */
    120     void calculateDesktopGeometry();
    121     void setDesktopGeometry(DesktopGeo geometry, int iWidth, int iHeight);
    122     void storeConsoleSize(int iWidth, int iHeight);
    123     QRect availableGeometry();
    124     virtual void maybeRestrictMinimumSize() = 0;
     115    virtual QSize desktopGeometry() const = 0;
     116
     117    /* Protected setters: */
     118    void setMachineWindowResizeIgnored(bool fIgnore = true) { m_bIsMachineWindowResizeIgnored = fIgnore; }
     119    void setFrameBufferResizeIgnored(bool fIgnore = true) { m_bIsFrameBufferResizeIgnored = fIgnore; }
     120
     121    /* Protected helpers: */
     122    void updateMouseClipping();
     123    void updateSliders();
    125124
    126125    /* Prepare routines: */
     
    138137    virtual void cleanupFrameBuffer();
    139138
     139    /* Cross-platforms event processors: */
     140    bool event(QEvent *pEvent);
     141    bool eventFilter(QObject *pWatched, QEvent *pEvent);
     142
    140143protected slots:
    141144
    142145    /* Console callback handlers: */
    143146    virtual void sltMachineStateChanged();
    144     virtual void sltAdditionsStateChanged();
    145147    virtual void sltMousePointerShapeChanged();
    146148    virtual void sltMouseCapabilityChanged();
    147149
    148     /* Initiate resize request to guest: */
    149     virtual void sltPerformGuestResize(const QSize &aSize = QSize()) = 0;
    150 
    151150private slots:
    152 
    153     /* Watch dog for desktop resizes: */
    154     void sltDesktopResized();
    155151
    156152#ifdef Q_WS_MAC
     
    166162
    167163    /* Cross-platforms event processors: */
    168     bool event(QEvent *pEvent);
    169     bool eventFilter(QObject *pWatched, QEvent *pEvent);
    170164    void focusEvent(bool aHasFocus, bool aReleaseHostKey = true);
    171165    bool keyEvent(int aKey, uint8_t aScan, int aFlags, wchar_t *aUniKey = NULL);
     
    199193    void fixModifierState(int *piCodes, uint *puCount);
    200194    QPoint viewportToContents(const QPoint &vp) const;
    201     void updateSliders();
    202195    void scrollBy(int dx, int dy);
    203196#ifdef VBOX_WITH_VIDEOHWACCEL
     
    211204    void releaseAllPressedKeys(bool aReleaseHostKey = true);
    212205    void sendChangedKeyStates();
    213     void updateMouseClipping();
    214206
    215207    static void dimImage(QImage &img);
     
    239231#ifdef VBOX_WITH_VIDEOHWACCEL
    240232    bool m_fAccelerate2DVideo;
    241 #endif
    242 #if 0 // TODO: Do we need this flag?
    243     bool mDoResize : 1;
    244233#endif
    245234
     
    263252    bool mDockIconEnabled;
    264253#endif
    265     DesktopGeo m_desktopGeometryType;
    266     QRect m_desktopGeometry;
    267     QRect m_storedConsoleSize;
    268254
    269255    /* Friend classes: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp

    r26868 r26878  
    9191    : m_pMachineLogic(pMachineLogic)
    9292    , m_pMachineWindow(0)
     93    , m_pMachineViewContainer(0)
     94    , m_pTopSpacer(0)
     95    , m_pBottomSpacer(0)
     96    , m_pLeftSpacer(0)
     97    , m_pRightSpacer(0)
    9398    , m_pMachineView(0)
    9499{
     
    490495}
    491496
     497void UIMachineWindow::prepareMachineViewContainer()
     498{
     499    /* Create view container.
     500     * After it will be passed to parent widget of some mode,
     501     * there will be no need to delete it, so no need to cleanup: */
     502    m_pMachineViewContainer = new QGridLayout();
     503    m_pMachineViewContainer->setMargin(0);
     504    m_pMachineViewContainer->setSpacing(0);
     505
     506    /* Create and add shifting spacers.
     507     * After they will be inserted into layout, it will get the parentness
     508     * of those spacers, so there will be no need to cleanup them. */
     509    m_pTopSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
     510    m_pBottomSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
     511    m_pLeftSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
     512    m_pRightSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
     513    m_pMachineViewContainer->addItem(m_pTopSpacer, 0, 1);
     514    m_pMachineViewContainer->addItem(m_pBottomSpacer, 2, 1);
     515    m_pMachineViewContainer->addItem(m_pLeftSpacer, 1, 0);
     516    m_pMachineViewContainer->addItem(m_pRightSpacer, 1, 2);
     517}
     518
    492519void UIMachineWindow::updateAppearanceOf(int iElement)
    493520{
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h

    r26820 r26878  
    2929/* Global forwards */
    3030class QWidget;
     31class QGridLayout;
     32class QSpacerItem;
    3133class QCloseEvent;
    3234
     
    8183#endif
    8284    virtual void prepareMenuHelp();
     85    virtual void prepareMachineViewContainer();
    8386    //virtual void loadWindowSettings() {}
    8487
    8588    /* Cleanup helpers: */
    8689    //virtual void saveWindowSettings() {}
     90    //virtual void cleanupMachineViewContainer() {}
     91    //virtual void cleanupMenuHelp() {}
    8792#ifdef VBOX_WITH_DEBUGGER_GUI
    8893    //virtual void prepareMenuDebug() {}
     
    102107    UIMachineLogic *m_pMachineLogic;
    103108    QWidget *m_pMachineWindow;
     109
     110    QGridLayout *m_pMachineViewContainer;
     111    QSpacerItem *m_pTopSpacer;
     112    QSpacerItem *m_pBottomSpacer;
     113    QSpacerItem *m_pLeftSpacer;
     114    QSpacerItem *m_pRightSpacer;
     115
    104116    UIMachineView *m_pMachineView;
    105117    QString m_strWindowTitlePrefix;
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.cpp

    r26815 r26878  
    2525#include <QApplication>
    2626#include <QDesktopWidget>
    27 #include <QMainWindow>
    2827#include <QMenuBar>
     28#include <QTimer>
    2929
    3030/* Local includes */
     
    3434#include "UIMachineLogic.h"
    3535#include "UIMachineWindow.h"
     36#include "UIFrameBuffer.h"
    3637#include "UIMachineViewNormal.h"
     38#include "QIMainDialog.h"
    3739
    3840UIMachineViewNormal::UIMachineViewNormal(  UIMachineWindow *pMachineWindow
     
    4850#endif
    4951                   )
     52    , m_desktopGeometryType(DesktopGeo_Invalid)
     53    , m_bIsGuestAutoresizeEnabled(pMachineWindow->machineLogic()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked())
     54    , m_fShouldWeDoResize(false)
    5055{
    5156    /* Prepare frame buffer: */
     
    8085}
    8186
    82 void UIMachineViewNormal::sltPerformGuestResize(const QSize & /* toSize */)
    83 {
    84 #if 0 // TODO: fix that logic!
    85     if (isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
    86     {
     87void UIMachineViewNormal::sltAdditionsStateChanged()
     88{
     89    /* Check if we should restrict minimum size: */
     90    maybeRestrictMinimumSize();
     91}
     92
     93void UIMachineViewNormal::sltPerformGuestResize(const QSize &toSize)
     94{
     95    if (m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics())
     96    {
     97        /* Taking Main Dialog: */
     98        QIMainDialog *pMainDialog = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
     99                                    qobject_cast<QIMainDialog*>(machineWindowWrapper()->machineWindow()) : 0;
     100
    87101        /* If this slot is invoked directly then use the passed size
    88102         * otherwise get the available size for the guest display.
    89103         * We assume here that the centralWidget() contains this view only
    90104         * and gives it all available space. */
    91         QSize sz(toSize.isValid() ? toSize : machineWindow()->centralWidget()->size());
     105        QSize newSize(toSize.isValid() ? toSize : pMainDialog ? pMainDialog->centralWidget()->size() : QSize());
     106        AssertMsg(newSize.isValid(), ("This size should be valid!\n"));
     107
     108        /* Subtracting frame in case we basing on machine view size: */
    92109        if (!toSize.isValid())
    93             sz -= QSize(frameWidth() * 2, frameWidth() * 2);
    94         /* Do not send out useless hints. */
    95         if ((sz.width() == mStoredConsoleSize.width()) && (sz.height() == mStoredConsoleSize.height()))
     110            newSize -= QSize(frameWidth() * 2, frameWidth() * 2);
     111
     112        /* Do not send the same hints as we already have: */
     113        if ((newSize.width() == m_storedConsoleSize.width()) && (newSize.height() == m_storedConsoleSize.height()))
    96114            return;
     115
    97116        /* We only actually send the hint if
    98117         * 1) the autoresize property is set to true and
     
    102121         *    needed (e.g. the autoresize was just enabled and the console
    103122         *    was resized while it was disabled). */
    104         if (m_bIsGuestAutoresizeEnabled && (toSize.isValid() || mDoResize))
     123        if (toSize.isValid() || m_fShouldWeDoResize)
    105124        {
    106125            /* Remember the new size. */
    107             storeConsoleSize(sz.width(), sz.height());
    108 
    109             mConsole.GetDisplay().SetVideoModeHint(sz.width(), sz.height(), 0, 0);
     126            m_storedConsoleSize = newSize;
     127
     128            /* Send new size-hint to the guest: */
     129            session().GetConsole().GetDisplay().SetVideoModeHint(newSize.width(), newSize.height(), 0, 0);
    110130        }
    111         /* We have resized now... */
    112         mDoResize = false;
    113     }
    114 #endif
    115 }
    116 
    117 void UIMachineViewNormal::sltAdditionsStateChanged()
    118 {
    119     /* Base-class additions state-change-handler: */
    120     UIMachineView::sltAdditionsStateChanged();
    121 
    122     /* Enable/Disable guest auto-resizing depending on advanced graphics availablability: */
    123     setGuestAutoresizeEnabled(m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics());
     131        /* We had requested resize now, rejecting accident requests: */
     132        m_fShouldWeDoResize = false;
     133    }
     134}
     135
     136/* If the desktop geometry is set automatically, this will update it: */
     137void UIMachineViewNormal::sltDesktopResized()
     138{
     139    calculateDesktopGeometry();
    124140}
    125141
    126142void UIMachineViewNormal::prepareFilters()
    127143{
    128     /* Prepare base-class filters: */
     144    /* Base class filters: */
    129145    UIMachineView::prepareFilters();
    130146
    131     /* Normal window filters: */
    132     qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);
     147    /* Menu bar filters: */
     148    qobject_cast<QIMainDialog*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);
     149}
     150
     151void UIMachineViewNormal::prepareConsoleConnections()
     152{
     153    /* Base class connections: */
     154    UIMachineView::prepareConsoleConnections();
     155
     156    /* Guest additions state-change updater: */
     157    connect(uisession(), SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged()));
     158}
     159
     160void UIMachineViewNormal::loadMachineViewSettings()
     161{
     162    /* Base class settings: */
     163    UIMachineView::loadMachineViewSettings();
     164
     165    /* Global settings: */
     166    {
     167        /* Remember the desktop geometry and register for geometry
     168         * change events for telling the guest about video modes we like: */
     169        QString desktopGeometry = vboxGlobal().settings().publicProperty("GUI/MaxGuestResolution");
     170        if ((desktopGeometry == QString::null) || (desktopGeometry == "auto"))
     171            setDesktopGeometry(DesktopGeo_Automatic, 0, 0);
     172        else if (desktopGeometry == "any")
     173            setDesktopGeometry(DesktopGeo_Any, 0, 0);
     174        else
     175        {
     176            int width = desktopGeometry.section(',', 0, 0).toInt();
     177            int height = desktopGeometry.section(',', 1, 1).toInt();
     178            setDesktopGeometry(DesktopGeo_Fixed, width, height);
     179        }
     180        connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(sltDesktopResized()));
     181    }
    133182}
    134183
     
    141190        maybeRestrictMinimumSize();
    142191
    143         if (uisession()->isGuestSupportsGraphics() && m_bIsGuestAutoresizeEnabled)
     192        if (m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics())
    144193            sltPerformGuestResize();
    145194    }
    146195}
    147196
    148 void UIMachineViewNormal::normalizeGeometry(bool bAdjustPosition /* = false */)
     197QSize UIMachineViewNormal::desktopGeometry() const
     198{
     199    QSize geometry;
     200    switch (m_desktopGeometryType)
     201    {
     202        case DesktopGeo_Fixed:
     203        case DesktopGeo_Automatic:
     204            geometry = QSize(qMax(m_desktopGeometry.width(), m_storedConsoleSize.width()),
     205                             qMax(m_desktopGeometry.height(), m_storedConsoleSize.height()));
     206            break;
     207        case DesktopGeo_Any:
     208            geometry = QSize(0, 0);
     209            break;
     210        default:
     211            AssertMsgFailed(("Bad geometry type %d!\n", m_desktopGeometryType));
     212    }
     213    return geometry;
     214}
     215
     216void UIMachineViewNormal::normalizeGeometry(bool bAdjustPosition)
    149217{
    150218    QWidget *pTopLevelWidget = window();
     
    182250            availableGeo = dwt->availableGeometry(pTopLevelWidget->pos());
    183251
    184         frameGeo = VBoxGlobal::normalizeGeometry(frameGeo, availableGeo, mode() != VBoxDefs::SDLMode /* canResize */);
     252        frameGeo = VBoxGlobal::normalizeGeometry(frameGeo, availableGeo, mode() != VBoxDefs::SDLMode /* can resize? */);
    185253    }
    186254
     
    192260    /* Finally, set the frame geometry */
    193261    pTopLevelWidget->setGeometry(frameGeo.left() + dl, frameGeo.top() + dt, frameGeo.width() - dl - dr, frameGeo.height() - dt - db);
     262}
     263
     264void UIMachineViewNormal::calculateDesktopGeometry()
     265{
     266    /* This method should not get called until we have initially set up the m_desktopGeometryType: */
     267    Assert((m_desktopGeometryType != DesktopGeo_Invalid));
     268    /* If we are not doing automatic geometry calculation then there is nothing to do: */
     269    if (DesktopGeo_Automatic == m_desktopGeometryType)
     270    {
     271        /* Available geometry of the desktop.  If the desktop is a single
     272         * screen, this will exclude space taken up by desktop taskbars
     273         * and things, but this is unfortunately not true for the more
     274         * complex case of a desktop spanning multiple screens: */
     275        QRect desktop = availableGeometry();
     276        /* The area taken up by the machine window on the desktop,
     277         * including window frame, title and menu bar and whatnot: */
     278        QRect frame = machineWindowWrapper()->machineWindow()->frameGeometry();
     279        /* The area taken up by the machine view, so excluding all decorations: */
     280        QRect window = geometry();
     281        /* To work out how big we can make the console window while still
     282         * fitting on the desktop, we calculate desktop - frame + window.
     283         * This works because the difference between frame and window
     284         * (or at least its width and height) is a constant. */
     285        m_desktopGeometry = QSize(desktop.width() - frame.width() + window.width(),
     286                                  desktop.height() - frame.height() + window.height());
     287    }
     288}
     289
     290QRect UIMachineViewNormal::availableGeometry()
     291{
     292    return machineWindowWrapper()->machineWindow()->isFullScreen() ?
     293           QApplication::desktop()->screenGeometry(this) :
     294           QApplication::desktop()->availableGeometry(this);
     295}
     296
     297void UIMachineViewNormal::setDesktopGeometry(DesktopGeo geometry, int aWidth, int aHeight)
     298{
     299    switch (geometry)
     300    {
     301        case DesktopGeo_Fixed:
     302            m_desktopGeometryType = DesktopGeo_Fixed;
     303            if (aWidth != 0 && aHeight != 0)
     304                m_desktopGeometry = QSize(aWidth, aHeight);
     305            else
     306                m_desktopGeometry = QSize(0, 0);
     307            storeConsoleSize(0, 0);
     308            break;
     309        case DesktopGeo_Automatic:
     310            m_desktopGeometryType = DesktopGeo_Automatic;
     311            m_desktopGeometry = QSize(0, 0);
     312            storeConsoleSize(0, 0);
     313            break;
     314        case DesktopGeo_Any:
     315            m_desktopGeometryType = DesktopGeo_Any;
     316            m_desktopGeometry = QSize(0, 0);
     317            break;
     318        default:
     319            AssertMsgFailed(("Invalid desktop geometry type %d\n", geometry));
     320            m_desktopGeometryType = DesktopGeo_Invalid;
     321    }
     322}
     323
     324void UIMachineViewNormal::storeConsoleSize(int iWidth, int iHeight)
     325{
     326    m_storedConsoleSize = QSize(iWidth, iHeight);
    194327}
    195328
     
    209342}
    210343
     344bool UIMachineViewNormal::event(QEvent *pEvent)
     345{
     346    switch (pEvent->type())
     347    {
     348        case VBoxDefs::ResizeEventType:
     349        {
     350            /* Some situations require initial VGA Resize Request
     351             * to be ignored at all, leaving previous framebuffer,
     352             * machine view and machine window sizes preserved: */
     353            if (uisession()->isGuestResizeIgnored())
     354                return true;
     355
     356            bool oldIgnoreMainwndResize = isMachineWindowResizeIgnored();
     357            setMachineWindowResizeIgnored(true);
     358
     359            UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);
     360
     361            /* Store the new size to prevent unwanted resize hints being sent back. */
     362            storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());
     363
     364            /* Unfortunately restoreOverrideCursor() is broken in Qt 4.4.0 if WA_PaintOnScreen widgets are present.
     365             * This is the case on linux with SDL. As workaround we save/restore the arrow cursor manually.
     366             * See http://trolltech.com/developer/task-tracker/index_html?id=206165&method=entry for details.
     367             * Moreover the current cursor, which could be set by the guest, should be restored after resize: */
     368            QCursor cursor;
     369            if (uisession()->isHidingHostPointer())
     370                cursor = QCursor(Qt::BlankCursor);
     371            else
     372                cursor = viewport()->cursor();
     373            frameBuffer()->resizeEvent(pResizeEvent);
     374            viewport()->setCursor(cursor);
     375
     376#ifdef Q_WS_MAC
     377            // TODO_NEW_CORE
     378//            mDockIconPreview->setOriginalSize(pResizeEvent->width(), pResizeEvent->height());
     379#endif /* Q_WS_MAC */
     380
     381            /* This event appears in case of guest video was changed for somehow even without video resolution change.
     382             * In this last case the host VM window will not be resized according this event and the host mouse cursor
     383             * which was unset to default here will not be hidden in capture state. So it is necessary to perform
     384             * updateMouseClipping() for the guest resize event if the mouse cursor was captured: */
     385            if (uisession()->isMouseCaptured())
     386                updateMouseClipping();
     387
     388            /* Apply maximum size restriction: */
     389            setMaximumSize(sizeHint());
     390
     391            /* May be we have to restrict minimum size? */
     392            maybeRestrictMinimumSize();
     393
     394            /* Resize the guest canvas: */
     395            if (!isFrameBufferResizeIgnored())
     396                resize(pResizeEvent->width(), pResizeEvent->height());
     397            updateSliders();
     398
     399            /* Let our toplevel widget calculate its sizeHint properly. */
     400#ifdef Q_WS_X11
     401            /* We use processEvents rather than sendPostedEvents & set the time out value to max cause on X11 otherwise
     402             * the layout isn't calculated correctly. Dosn't find the bug in Qt, but this could be triggered through
     403             * the async nature of the X11 window event system. */
     404            QCoreApplication::processEvents(QEventLoop::AllEvents, INT_MAX);
     405#else /* Q_WS_X11 */
     406            QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
     407#endif /* Q_WS_X11 */
     408
     409            if (!isFrameBufferResizeIgnored())
     410                normalizeGeometry(true /* adjustPosition */);
     411
     412            /* Report to the VM thread that we finished resizing */
     413            session().GetConsole().GetDisplay().ResizeCompleted(0);
     414
     415            setMachineWindowResizeIgnored(oldIgnoreMainwndResize);
     416
     417            /* Make sure that all posted signals are processed: */
     418            qApp->processEvents();
     419
     420            /* Emit a signal about guest was resized: */
     421            emit resizeHintDone();
     422
     423            /* We also recalculate the desktop geometry if this is determined
     424             * automatically.  In fact, we only need this on the first resize,
     425             * but it is done every time to keep the code simpler. */
     426            calculateDesktopGeometry();
     427
     428            /* Enable frame-buffer resize watching: */
     429            if (isFrameBufferResizeIgnored())
     430                setFrameBufferResizeIgnored(false);
     431
     432            return true;
     433        }
     434
     435        case QEvent::KeyPress:
     436        case QEvent::KeyRelease:
     437        {
     438            QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
     439
     440            if (isHostKeyPressed() && pEvent->type() == QEvent::KeyPress)
     441            {
     442                if (pKeyEvent->key() == Qt::Key_Home)
     443                {
     444                    /* In Qt4 it is not enough to just set the focus to menu-bar.
     445                     * So to get the menu-bar we have to send Qt::Key_Alt press/release events directly: */
     446                    QKeyEvent e1(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier);
     447                    QKeyEvent e2(QEvent::KeyRelease, Qt::Key_Alt, Qt::NoModifier);
     448                    QMenuBar *pMenuBar = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
     449                                         qobject_cast<QIMainDialog*>(machineWindowWrapper()->machineWindow())->menuBar() : 0;
     450                    QApplication::sendEvent(pMenuBar, &e1);
     451                    QApplication::sendEvent(pMenuBar, &e2);
     452                }
     453                else
     454                    pEvent->ignore();
     455            }
     456        }
     457        default:
     458            break;
     459    }
     460    return UIMachineView::event(pEvent);
     461}
     462
     463bool UIMachineViewNormal::eventFilter(QObject *pWatched, QEvent *pEvent)
     464{
     465    /* Who are we watchin? */
     466    QIMainDialog *pMainDialog = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
     467        qobject_cast<QIMainDialog*>(machineWindowWrapper()->machineWindow()) : 0;
     468    QMenuBar *pMenuBar = pMainDialog ? qobject_cast<QIMainDialog*>(pMainDialog)->menuBar() : 0;
     469
     470    if (pWatched != 0 && pWatched == pMainDialog)
     471    {
     472        switch (pEvent->type())
     473        {
     474            case QEvent::Resize:
     475            {
     476                /* Set the "guest needs to resize" hint.
     477                 * This hint is acted upon when (and only when) the autoresize property is "true": */
     478                m_fShouldWeDoResize = uisession()->isGuestSupportsGraphics();
     479                if (!isMachineWindowResizeIgnored() && m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics())
     480                    QTimer::singleShot(300, this, SLOT(sltPerformGuestResize()));
     481                break;
     482            }
     483#if defined (Q_WS_WIN32)
     484# if defined (VBOX_GUI_USE_DDRAW)
     485            case QEvent::Move:
     486            {
     487                /* Notification from our parent that it has moved. We need this in order
     488                 * to possibly adjust the direct screen blitting: */
     489                if (frameBuffer())
     490                    frameBuffer()->moveEvent(static_cast<QMoveEvent*>(pEvent));
     491                break;
     492            }
     493# endif
     494#endif /* defined (Q_WS_WIN32) */
     495            default:
     496                break;
     497        }
     498    }
     499    else if (pWatched != 0 && pWatched == pMenuBar)
     500    {
     501        /* Sometimes when we press ESC in the menu it brings the focus away (Qt bug?)
     502         * causing no widget to have a focus, or holds the focus itself, instead of
     503         * returning the focus to the console window. Here we fix this: */
     504        switch (pEvent->type())
     505        {
     506            case QEvent::FocusOut:
     507            {
     508                if (qApp->focusWidget() == 0)
     509                    setFocus();
     510                break;
     511            }
     512            case QEvent::KeyPress:
     513            {
     514                QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
     515                if (pKeyEvent->key() == Qt::Key_Escape && (pKeyEvent->modifiers() == Qt::NoModifier))
     516                    if (pMenuBar->hasFocus())
     517                        setFocus();
     518                break;
     519            }
     520            default:
     521                break;
     522        }
     523    }
     524    return UIMachineView::eventFilter(pWatched, pEvent);
     525}
     526
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineViewNormal.h

    r26773 r26878  
    3131    Q_OBJECT;
    3232
     33signals:
     34
     35    /* Utility signals: */
     36    void resizeHintDone();
     37
    3338protected:
     39
     40    /* Desktop geometry types: */
     41    enum DesktopGeo { DesktopGeo_Invalid = 0, DesktopGeo_Fixed, DesktopGeo_Automatic, DesktopGeo_Any };
    3442
    3543    /* Normal machine view constructor/destructor: */
     
    4856
    4957    /* Slot to perform guest resize: */
    50     void sltPerformGuestResize(const QSize &aSize = QSize());
     58    void sltPerformGuestResize(const QSize &size = QSize());
     59
     60    /* Watch dog for desktop resizes: */
     61    void sltDesktopResized();
    5162
    5263private:
    5364
    54     /* Prepare routines: */
     65    /* Prepare helpers: */
    5566    void prepareFilters();
     67    void prepareConsoleConnections();
     68    void loadMachineViewSettings();
    5669
    57     /* Private setters: */
     70    /* Cleanup helpers: */
     71    //void saveMachineViewSettings() {}
     72    //void cleanupConsoleConnections() {}
     73    //cleanupFilters() {}
     74
     75    /* Hidden setters: */
    5876    void setGuestAutoresizeEnabled(bool bEnabled);
    5977
     78    /* Hidden getters: */
     79    QSize desktopGeometry() const;
     80
    6081    /* Private helpers: */
    61     void normalizeGeometry(bool bAdjustPosition = false);
     82    void normalizeGeometry(bool fAdjustPosition);
     83    void calculateDesktopGeometry();
     84    QRect availableGeometry();
     85    void setDesktopGeometry(DesktopGeo geometry, int iWidth, int iHeight);
     86    void storeConsoleSize(int iWidth, int iHeight);
    6287    void maybeRestrictMinimumSize();
    6388
     89    /* Event handlers: */
     90    bool event(QEvent *pEvent);
     91    bool eventFilter(QObject *pWatched, QEvent *pEvent);
     92
    6493    /* Private members: */
     94    DesktopGeo m_desktopGeometryType;
     95    QSize m_desktopGeometry;
     96    QSize m_storedConsoleSize;
    6597    bool m_bIsGuestAutoresizeEnabled : 1;
     98    bool m_fShouldWeDoResize : 1;
    6699
    67100    /* Friend classes: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp

    r26820 r26878  
    6969    retranslateUi();
    7070
     71    /* Prepare normal machine view container: */
     72    prepareMachineViewContainer();
     73
    7174    /* Prepare normal machine view: */
    7275    prepareMachineView();
     
    8689    /* Save normal window settings: */
    8790    saveWindowSettings();
     91
     92    /* Cleanup normal machine view: */
     93    cleanupMachineView();
    8894
    8995    /* Cleanup status-bar: */
     
    454460#endif
    455461
     462    /* Set central widget: */
     463    setCentralWidget(new QWidget);
     464
     465    /* Set central widget layout: */
     466    centralWidget()->setLayout(m_pMachineViewContainer);
     467
    456468    m_pMachineView = UIMachineView::create(  this
    457469                                           , vboxGlobal().vmRenderMode()
     
    461473                                           , machineLogic()->visualStateType());
    462474
    463     setCentralWidget(m_pMachineView);
     475    /* Add machine view into layout: */
     476    m_pMachineViewContainer->addWidget(m_pMachineView, 1, 1);
    464477
    465478    /* Setup machine view connections: */
     
    568581}
    569582
     583void UIMachineWindowNormal::cleanupMachineView()
     584{
     585    /* Do not cleanup machine view if it is not present: */
     586    if (!machineView())
     587        return;
     588
     589    UIMachineView::destroy(m_pMachineView);
     590    m_pMachineView = 0;
     591}
     592
    570593void UIMachineWindowNormal::cleanupStatusBar()
    571594{
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.h

    r26815 r26878  
    9292    void prepareStatusBar();
    9393    void prepareConnections();
     94    void prepareMachineView();
    9495    void loadWindowSettings();
    95     void prepareMachineView();
    9696
    9797    /* Cleanup helpers: */
    98     //void cleanupMachineView() {}
    9998    void saveWindowSettings();
     99    void cleanupMachineView();
    100100    //void cleanupConnections() {}
    101101    void cleanupStatusBar();
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