Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp	(revision 51707)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp	(revision 51708)
@@ -131,9 +131,9 @@
 void UIGMachinePreview::sltRecreatePreview()
 {
-    /* Only do this if we are visible: */
+    /* Skip invisible preview: */
     if (!isVisible())
         return;
 
-    /* Cleanup preview first: */
+    /* Cleanup previous image: */
     if (m_pPreviewImg)
     {
@@ -142,6 +142,6 @@
     }
 
-    /* Fetch the latest machine-state: */
-    KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState();
+    /* Fetch actual machine-state: */
+    const KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState();
 
     /* We are creating preview only for assigned and accessible VMs: */
@@ -149,79 +149,92 @@
         m_vRect.width() > 0 && m_vRect.height() > 0)
     {
-        QImage image(size().toSize(), QImage::Format_ARGB32);
-        image.fill(Qt::transparent);
-        QPainter painter(&image);
-        bool fDone = false;
-
-        /* Preview enabled? */
+        /* Prepare image: */
+        QImage image;
+
+        /* Preview update enabled? */
         if (m_pUpdateTimer->interval() > 0)
         {
-            /* Use the image which may be included in the save state. */
-            if (machineState == KMachineState_Saved || machineState == KMachineState_Restoring)
+            /* Depending on machine state: */
+            switch (machineState)
             {
-                ULONG width = 0, height = 0;
-                QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, width, height);
-                if (screenData.size() != 0)
+                /* If machine is in SAVED/RESTORING state: */
+                case KMachineState_Saved:
+                case KMachineState_Restoring:
                 {
-                    QImage shot = QImage::fromData(screenData.data(), screenData.size(), "PNG")
-                                  .scaled(m_vRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-                    dimImage(shot);
-                    painter.drawImage(m_vRect.x(), m_vRect.y(), shot);
-                    fDone = true;
+                    /* Use the screenshot from saved-state if possible: */
+                    ULONG uWidth = 0, uHeight = 0;
+                    QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, uWidth, uHeight);
+                    if (m_machine.isOk() && !screenData.isEmpty())
+                    {
+                        /* Create image based on shallow copy or screenshot data,
+                         * scale image down if necessary to the size possible to reflect: */
+                        image = QImage::fromData(screenData.data(), screenData.size(), "PNG")
+                                .scaled(imageAspectRatioSize(m_vRect.size(), QSize(uWidth, uHeight)),
+                                        Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+                        /* Dim image to give it required look: */
+                        dimImage(image);
+                    }
+                    break;
                 }
-            }
-            /* Use the current VM output. */
-            else if (machineState == KMachineState_Running || machineState == KMachineState_Paused)
-            {
-                if (m_session.GetState() == KSessionState_Locked)
+                /* If machine is in RUNNING/PAUSED state: */
+                case KMachineState_Running:
+                case KMachineState_Paused:
                 {
-                    CVirtualBox vbox = vboxGlobal().virtualBox();
-                    if (vbox.isOk())
+                    /* Make sure session state is Locked: */
+                    if (m_session.GetState() != KSessionState_Locked)
+                        break;
+
+                    /* Make sure console is OK: */
+                    CConsole console = m_session.GetConsole();
+                    if (!m_session.isOk() || console.isNull())
+                        break;
+                    /* Make sure display is OK: */
+                    CDisplay display = console.GetDisplay();
+                    if (!console.isOk() || display.isNull())
+                        break;
+
+                    /* Calculate aspect-ratio size: */
+                    ULONG uGuestWidth, uGuestHeight, uBpp;
+                    LONG iOriginX, iOriginY;
+                    display.GetScreenResolution(0, uGuestWidth, uGuestHeight, uBpp, iOriginX, iOriginY);
+                    const QSize size = imageAspectRatioSize(m_vRect.size(), QSize(uGuestWidth, uGuestHeight));
+
+                    /* Use direct VM content: */
+                    QVector<BYTE> screenData = display.TakeScreenShotToArray(0, size.width(), size.height());
+                    if (display.isOk() && !screenData.isEmpty())
                     {
-                        const CConsole& console = m_session.GetConsole();
-                        if (!console.isNull())
+                        /* Unfortunately we have to reorder the pixel data,
+                         * cause the VBox API returns RGBA data,
+                         * which is not a format QImage understand. */
+                        uint32_t *pData = (uint32_t*)screenData.data();
+                        for (int i = 0; i < screenData.size() / 4; ++i)
                         {
-                            CDisplay display = console.GetDisplay();
-                            /* Todo: correct aspect radio */
-//                            ULONG w, h, bpp;
-//                            LONG xOrigin, yOrigin;
-//                            display.GetScreenResolution(0, w, h, bpp, xOrigin, yOrigin);
-//                            QImage shot = QImage(w, h, QImage::Format_RGB32);
-//                            shot.fill(Qt::black);
-//                            display.TakeScreenShot(0, shot.bits(), shot.width(), shot.height());
-                            QVector<BYTE> screenData = display.TakeScreenShotToArray(0, m_vRect.width(), m_vRect.height());
-                            if (display.isOk() && screenData.size() != 0)
-                            {
-                                /* Unfortunately we have to reorder the pixel
-                                 * data, cause the VBox API returns RGBA data,
-                                 * which is not a format QImage understand.
-                                 * Todo: check for 32bit alignment, for both
-                                 * the data and the scanlines. Maybe we need to
-                                 * copy the data in any case. */
-                                uint32_t *d = (uint32_t*)screenData.data();
-                                for (int i = 0; i < screenData.size() / 4; ++i)
-                                {
-                                    uint32_t e = d[i];
-                                    d[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e));
-                                }
-
-                                QImage shot = QImage((uchar*)d, m_vRect.width(), m_vRect.height(), QImage::Format_RGB32);
-
-                                if (machineState == KMachineState_Paused)
-                                    dimImage(shot);
-                                painter.drawImage(m_vRect.x(), m_vRect.y(), shot);
-                                fDone = true;
-                            }
+                            uint32_t e = pData[i];
+                            pData[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e));
                         }
+                        /* Create image based on shallow copy or reordered data: */
+                        image = QImage((uchar*)pData, size.width(), size.height(), QImage::Format_RGB32);
+                        /* Dim image to give it required look for PAUSED state: */
+                        if (machineState == KMachineState_Paused)
+                            dimImage(image);
                     }
+                    break;
                 }
+                default:
+                    break;
             }
         }
 
-        if (fDone)
+        /* If image initialized: */
+        if (!image.isNull())
+        {
+            /* Shallow copy that image: */
             m_pPreviewImg = new QImage(image);
-    }
-
-    /* Redraw preview in any case! */
+            /* And detach that copy: */
+            m_pPreviewImg->bits();
+        }
+    }
+
+    /* Redraw preview in any case: */
     update();
 }
@@ -285,13 +298,19 @@
     if (m_pPreviewImg)
     {
-        /* Draw empty background: */
+        /* Draw black background: */
+        pPainter->fillRect(m_vRect, Qt::black);
+
+        /* Draw empty monitor frame: */
         pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_pbgEmptyImage);
 
-        /* Draw that image: */
-        pPainter->drawImage(0, 0, *m_pPreviewImg);
+        /* Move image to viewport center: */
+        QRect imageRect(QPoint(0, 0), m_pPreviewImg->size());
+        imageRect.moveCenter(m_vRect.center());
+        /* Draw preview image: */
+        pPainter->drawImage(imageRect.topLeft(), *m_pPreviewImg);
     }
     else
     {
-        /* Draw full background: */
+        /* Draw full monitor frame: */
         pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_pbgFullImage);
 
@@ -386,2 +405,33 @@
 }
 
+/* static */
+QSize UIGMachinePreview::imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize)
+{
+    /* Calculate host/guest aspect-ratio: */
+    const double dHostAspectRatio = (double)hostSize.width() / hostSize.height();
+    const double dGuestAspectRatio = (double)guestSize.width() / guestSize.height();
+    int iWidth = 0, iHeight = 0;
+    /* Guest-screen more thin by vertical than host-screen: */
+    if (dGuestAspectRatio >= dHostAspectRatio)
+    {
+        /* Get host width: */
+        iWidth = hostSize.width();
+        /* And calculate height based on guest aspect ratio: */
+        iHeight = (double)iWidth / dGuestAspectRatio;
+        /* But no more than host height: */
+        iHeight = qMin(iHeight, hostSize.height());
+    }
+    /* Host-screen more thin by vertical than guest-screen: */
+    else
+    {
+        /* Get host height: */
+        iHeight = hostSize.height();
+        /* And calculate width based on guest aspect ratio: */
+        iWidth = (double)iHeight * dGuestAspectRatio;
+        /* But no more than host width: */
+        iWidth = qMin(iWidth, hostSize.width());
+    }
+    /* Return actual size: */
+    return QSize(iWidth, iHeight);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.h	(revision 51707)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.h	(revision 51708)
@@ -90,4 +90,7 @@
     void stop();
 
+    /** Calculates image size suitable to passed @a hostSize and @a guestSize. */
+    static QSize imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize);
+
     /* Variables: */
     CSession m_session;
